mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-07-17 10:05:27 +01:00
Merge branch 'dev-freeze' into ofPuffsAndCleaner
Conflicts: code/game/objects/effects/chem/water.dm
This commit is contained in:
@@ -8,6 +8,10 @@ env:
|
||||
before_install:
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install libc6:i386 libgcc1:i386 libstdc++6:i386 -qq
|
||||
- sudo apt-get install python -qq
|
||||
- sudo apt-get install python-pip -qq
|
||||
- sudo pip install PyYaml -q
|
||||
- sudo pip install beautifulsoup4 -q
|
||||
|
||||
install:
|
||||
- curl "http://www.byond.com/download/build/${BYOND_MAJOR}/${BYOND_MAJOR}.${BYOND_MINOR}_byond_linux.zip" -o byond.zip
|
||||
@@ -22,3 +26,4 @@ script:
|
||||
- (! find nano/templates/ -type f -exec md5sum {} + | sort | uniq -D -w 32 | grep nano)
|
||||
- ( md5sum -c - <<< "0af969f671fba6cf9696c78cd175a14a *baystation12.int")
|
||||
- DreamMaker baystation12.dme
|
||||
- python tools/GenerateChangelog/ss13_genchangelog.py html/changelog.html html/changelogs
|
||||
|
||||
+12
-4
@@ -174,6 +174,7 @@
|
||||
#include "code\datums\diseases\advance\symptoms\weight.dm"
|
||||
#include "code\datums\helper_datums\construction_datum.dm"
|
||||
#include "code\datums\helper_datums\events.dm"
|
||||
#include "code\datums\helper_datums\getrev.dm"
|
||||
#include "code\datums\helper_datums\global_iterator.dm"
|
||||
#include "code\datums\helper_datums\teleport.dm"
|
||||
#include "code\datums\helper_datums\topic_input.dm"
|
||||
@@ -265,6 +266,7 @@
|
||||
#include "code\game\gamemodes\cult\cult_items.dm"
|
||||
#include "code\game\gamemodes\cult\cult_structures.dm"
|
||||
#include "code\game\gamemodes\cult\hell_universe.dm"
|
||||
#include "code\game\gamemodes\cult\narsie.dm"
|
||||
#include "code\game\gamemodes\cult\ritual.dm"
|
||||
#include "code\game\gamemodes\cult\runes.dm"
|
||||
#include "code\game\gamemodes\cult\talisman.dm"
|
||||
@@ -286,8 +288,15 @@
|
||||
#include "code\game\gamemodes\events\holidays\Other.dm"
|
||||
#include "code\game\gamemodes\extended\extended.dm"
|
||||
#include "code\game\gamemodes\heist\heist.dm"
|
||||
#include "code\game\gamemodes\malfunction\Malf_Modules.dm"
|
||||
#include "code\game\gamemodes\malfunction\malf_hardware.dm"
|
||||
#include "code\game\gamemodes\malfunction\malf_research.dm"
|
||||
#include "code\game\gamemodes\malfunction\malf_research_ability.dm"
|
||||
#include "code\game\gamemodes\malfunction\malfunction.dm"
|
||||
#include "code\game\gamemodes\malfunction\newmalf_ability_trees\HARDWARE.dm"
|
||||
#include "code\game\gamemodes\malfunction\newmalf_ability_trees\HELPERS.dm"
|
||||
#include "code\game\gamemodes\malfunction\newmalf_ability_trees\tree_interdiction.dm"
|
||||
#include "code\game\gamemodes\malfunction\newmalf_ability_trees\tree_manipulation.dm"
|
||||
#include "code\game\gamemodes\malfunction\newmalf_ability_trees\tree_networking.dm"
|
||||
#include "code\game\gamemodes\meteor\meteor.dm"
|
||||
#include "code\game\gamemodes\meteor\meteors.dm"
|
||||
#include "code\game\gamemodes\ninja\ninja.dm"
|
||||
@@ -542,7 +551,6 @@
|
||||
#include "code\game\objects\effects\spawners\gibspawner.dm"
|
||||
#include "code\game\objects\effects\spawners\vaultspawner.dm"
|
||||
#include "code\game\objects\items\apc_frame.dm"
|
||||
#include "code\game\objects\items\ashtray.dm"
|
||||
#include "code\game\objects\items\blueprints.dm"
|
||||
#include "code\game\objects\items\bodybag.dm"
|
||||
#include "code\game\objects\items\contraband.dm"
|
||||
@@ -671,6 +679,7 @@
|
||||
#include "code\game\objects\items\weapons\implants\implantfreedom.dm"
|
||||
#include "code\game\objects\items\weapons\implants\implantpad.dm"
|
||||
#include "code\game\objects\items\weapons\implants\implantuplink.dm"
|
||||
#include "code\game\objects\items\weapons\material\ashtray.dm"
|
||||
#include "code\game\objects\items\weapons\material\bats.dm"
|
||||
#include "code\game\objects\items\weapons\material\kitchen.dm"
|
||||
#include "code\game\objects\items\weapons\material\knives.dm"
|
||||
@@ -1231,7 +1240,6 @@
|
||||
#include "code\modules\mob\living\silicon\ai\life.dm"
|
||||
#include "code\modules\mob\living\silicon\ai\login.dm"
|
||||
#include "code\modules\mob\living\silicon\ai\logout.dm"
|
||||
#include "code\modules\mob\living\silicon\ai\say.dm"
|
||||
#include "code\modules\mob\living\silicon\decoy\death.dm"
|
||||
#include "code\modules\mob\living\silicon\decoy\decoy.dm"
|
||||
#include "code\modules\mob\living\silicon\decoy\life.dm"
|
||||
@@ -1417,7 +1425,6 @@
|
||||
#include "code\modules\power\singularity\field_generator.dm"
|
||||
#include "code\modules\power\singularity\generator.dm"
|
||||
#include "code\modules\power\singularity\investigate.dm"
|
||||
#include "code\modules\power\singularity\narsie.dm"
|
||||
#include "code\modules\power\singularity\singularity.dm"
|
||||
#include "code\modules\power\singularity\particle_accelerator\particle.dm"
|
||||
#include "code\modules\power\singularity\particle_accelerator\particle_accelerator.dm"
|
||||
@@ -1479,6 +1486,7 @@
|
||||
#include "code\modules\reagents\dispenser\_defines.dm"
|
||||
#include "code\modules\reagents\dispenser\cartridge.dm"
|
||||
#include "code\modules\reagents\dispenser\cartridge_presets.dm"
|
||||
#include "code\modules\reagents\dispenser\cartridge_spawn.dm"
|
||||
#include "code\modules\reagents\dispenser\dispenser2.dm"
|
||||
#include "code\modules\reagents\dispenser\dispenser_presets.dm"
|
||||
#include "code\modules\reagents\dispenser\supply.dm"
|
||||
|
||||
@@ -130,7 +130,7 @@
|
||||
var/total_specific_power = 0 //the power required to remove one mole of filterable gas
|
||||
for (var/g in filtering)
|
||||
var/ratio = source.gas[g]/total_filterable_moles //this converts the specific power per mole of pure gas to specific power per mole of scrubbed gas
|
||||
total_specific_power = specific_power_gas[g]*ratio
|
||||
total_specific_power += specific_power_gas[g]*ratio
|
||||
|
||||
//Figure out how much of each gas to filter
|
||||
if (isnull(total_transfer_moles))
|
||||
|
||||
@@ -85,6 +85,9 @@ obj/machinery/atmospherics/proc/check_connect_types(obj/machinery/atmospherics/a
|
||||
return node.pipe_color
|
||||
|
||||
/obj/machinery/atmospherics/process()
|
||||
last_flow_rate = 0
|
||||
last_power_draw = 0
|
||||
|
||||
build_network()
|
||||
|
||||
/obj/machinery/atmospherics/proc/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
var/frequency = 1439
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
var/hibernate = 0 //Do we even process?
|
||||
var/scrubbing = 1 //0 = siphoning, 1 = scrubbing
|
||||
var/list/scrubbing_gas = list("carbon_dioxide")
|
||||
|
||||
@@ -126,8 +127,8 @@
|
||||
/obj/machinery/atmospherics/unary/vent_scrubber/process()
|
||||
..()
|
||||
|
||||
last_power_draw = 0
|
||||
last_flow_rate = 0
|
||||
if (hibernate)
|
||||
return 1
|
||||
|
||||
if (!node)
|
||||
use_power = 0
|
||||
@@ -149,6 +150,12 @@
|
||||
|
||||
power_draw = pump_gas(src, environment, air_contents, transfer_moles, power_rating)
|
||||
|
||||
if(scrubbing && power_draw < 0 && controller_iteration > 10) //99% of all scrubbers
|
||||
//Fucking hibernate because you ain't doing shit.
|
||||
hibernate = 1
|
||||
spawn(rand(100,200)) //hibernate for 10 or 20 seconds randomly
|
||||
hibernate = 0
|
||||
|
||||
if (power_draw >= 0)
|
||||
last_power_draw = power_draw
|
||||
use_power(power_draw)
|
||||
|
||||
@@ -92,16 +92,6 @@
|
||||
turf += src
|
||||
c.add(turf,3,1)
|
||||
|
||||
/turf/space/New()
|
||||
..()
|
||||
|
||||
var/turf/controller = locate(1, 1, z)
|
||||
for(var/obj/effect/landmark/zcontroller/c in controller)
|
||||
if(c.initialized)
|
||||
var/list/turf = list()
|
||||
turf += src
|
||||
c.add(turf,3,1)
|
||||
|
||||
atom/movable/Move() //Hackish
|
||||
. = ..()
|
||||
|
||||
|
||||
+40
-1
@@ -45,6 +45,45 @@
|
||||
|
||||
air_master.connect(sim, src)
|
||||
|
||||
/*
|
||||
Simple heuristic for determining if removing the turf from it's zone may possibly partition the zone (A very bad thing).
|
||||
Instead of analyzing the entire zone, we only check the nearest 3x3 turfs surrounding the src turf.
|
||||
This implementation may produce false positives but it (hopefully) will not produce any false negatives.
|
||||
*/
|
||||
|
||||
/turf/simulated/proc/can_safely_remove_from_zone()
|
||||
#ifdef ZLEVELS
|
||||
return 1 //not sure how to generalize this to multiz at the moment.
|
||||
#else
|
||||
|
||||
if(!zone) return 0
|
||||
|
||||
var/check_dirs = get_zone_neighbours(src)
|
||||
var/unconnected_dirs = check_dirs
|
||||
|
||||
for(var/dir in list(NORTHWEST, NORTHEAST, SOUTHEAST, SOUTHWEST))
|
||||
|
||||
//for each pair of "adjacent" cardinals (e.g. NORTH and WEST, but not NORTH and SOUTH)
|
||||
if((dir & check_dirs) == dir)
|
||||
//check that they are connected by the corner turf
|
||||
var/connected_dirs = get_zone_neighbours(get_step(src, dir))
|
||||
if(connected_dirs && (dir & turn(connected_dirs, 180)) == dir)
|
||||
unconnected_dirs &= ~dir //they are, so unflag the cardinals in question
|
||||
|
||||
//it is safe to remove src from the zone if all cardinals are connected by corner turfs
|
||||
return !unconnected_dirs
|
||||
|
||||
#endif
|
||||
|
||||
//helper for can_safely_remove_from_zone()
|
||||
/turf/simulated/proc/get_zone_neighbours(turf/simulated/T)
|
||||
. = 0
|
||||
if(istype(T) && T.zone)
|
||||
for(var/dir in cardinal)
|
||||
var/turf/simulated/other = get_step(T, dir)
|
||||
if(istype(other) && other.zone == T.zone && !(other.c_airblock(T) & AIR_BLOCKED) && get_dist(src, other) <= 1)
|
||||
. |= dir
|
||||
|
||||
/turf/simulated/update_air_properties()
|
||||
|
||||
if(zone && zone.invalid)
|
||||
@@ -60,7 +99,7 @@
|
||||
if(zone)
|
||||
var/zone/z = zone
|
||||
|
||||
if(s_block & ZONE_BLOCKED) //Hacky, but prevents normal airlocks from rebuilding zones all the time
|
||||
if(can_safely_remove_from_zone()) //Helps normal airlocks avoid rebuilding zones all the time
|
||||
z.remove(src)
|
||||
else
|
||||
z.rebuild()
|
||||
|
||||
@@ -29,7 +29,7 @@ var/global/list/GlobalPool = list()
|
||||
if(!D)
|
||||
// So the GC knows we're pooling this type.
|
||||
if(!GlobalPool[get_type])
|
||||
GlobalPool[get_type] = list(new get_type)
|
||||
GlobalPool[get_type] = list()
|
||||
if(islist(second_arg))
|
||||
return new get_type (arglist(second_arg))
|
||||
else
|
||||
@@ -58,7 +58,10 @@ var/global/list/GlobalPool = list()
|
||||
#ifdef DEBUG_ATOM_POOL
|
||||
world << text("DEBUG_DATUM_POOL: PlaceInPool([]) exceeds []. Discarding.", D.type, ATOM_POOL_COUNT)
|
||||
#endif
|
||||
del(D)
|
||||
if(garbage_collector)
|
||||
garbage_collector.AddTrash(D)
|
||||
else
|
||||
del(D)
|
||||
return
|
||||
|
||||
if(D in GlobalPool[D.type])
|
||||
|
||||
@@ -7,6 +7,8 @@ var/list/directory = list() //list of all ckeys with associated client
|
||||
|
||||
var/global/list/player_list = list() //List of all mobs **with clients attached**. Excludes /mob/new_player
|
||||
var/global/list/mob_list = list() //List of all mobs, including clientless
|
||||
var/global/list/human_mob_list = list() //List of all human mobs and sub-types, including clientless
|
||||
var/global/list/silicon_mob_list = list() //List of all silicon mobs, including clientless
|
||||
var/global/list/living_mob_list = list() //List of all alive mobs, including clientless. Excludes /mob/new_player
|
||||
var/global/list/dead_mob_list = list() //List of all dead mobs, including clientless. Excludes /mob/new_player
|
||||
|
||||
@@ -19,6 +21,8 @@ var/global/list/side_effects = list() //list of all medical sideeffects types
|
||||
var/global/list/mechas_list = list() //list of all mechs. Used by hostile mobs target tracking.
|
||||
var/global/list/joblist = list() //list of all jobstypes, minus borg and AI
|
||||
|
||||
var/global/list/turfs = list() //list of all turfs
|
||||
|
||||
//Languages/species/whitelist.
|
||||
var/global/list/all_species[0]
|
||||
var/global/list/all_languages[0]
|
||||
|
||||
@@ -81,3 +81,15 @@
|
||||
|
||||
/proc/log_misc(text)
|
||||
diary << "\[[time_stamp()]]MISC: [text][log_end]"
|
||||
|
||||
//pretty print a direction bitflag, can be useful for debugging.
|
||||
/proc/print_dir(var/dir)
|
||||
var/list/comps = list()
|
||||
if(dir & NORTH) comps += "NORTH"
|
||||
if(dir & SOUTH) comps += "SOUTH"
|
||||
if(dir & EAST) comps += "EAST"
|
||||
if(dir & WEST) comps += "WEST"
|
||||
if(dir & UP) comps += "UP"
|
||||
if(dir & DOWN) comps += "DOWN"
|
||||
|
||||
return english_list(comps, nothing_text="0", and_text="|", comma_text="|")
|
||||
|
||||
@@ -11,3 +11,9 @@
|
||||
|
||||
/proc/isfloor(turf/T)
|
||||
return (istype(T, /turf/simulated/floor) || istype(T, /turf/unsimulated/floor) || istype(T, /turf/simulated/shuttle/floor))
|
||||
|
||||
/proc/turf_clear(turf/T)
|
||||
for(var/atom/A in T)
|
||||
if(A.simulated)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
+56
-12
@@ -70,19 +70,19 @@
|
||||
/proc/list2text(list/ls, sep)
|
||||
if (ls.len <= 1) // Early-out code for empty or singleton lists.
|
||||
return ls.len ? ls[1] : ""
|
||||
|
||||
|
||||
var/l = ls.len // Made local for sanic speed.
|
||||
var/i = 0 // Incremented every time a list index is accessed.
|
||||
|
||||
|
||||
if (sep <> null)
|
||||
// Macros expand to long argument lists like so: sep, ls[++i], sep, ls[++i], sep, ls[++i], etc...
|
||||
#define S1 sep, ls[++i]
|
||||
#define S4 S1, S1, S1, S1
|
||||
#define S16 S4, S4, S4, S4
|
||||
#define S64 S16, S16, S16, S16
|
||||
|
||||
|
||||
. = "[ls[++i]]" // Make sure the initial element is converted to text.
|
||||
|
||||
|
||||
// Having the small concatenations come before the large ones boosted speed by an average of at least 5%.
|
||||
if (l-1 & 0x01) // 'i' will always be 1 here.
|
||||
. = text("[][][]", ., S1) // Append 1 element if the remaining elements are not a multiple of 2.
|
||||
@@ -111,7 +111,7 @@
|
||||
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
|
||||
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
|
||||
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64, S64)
|
||||
|
||||
|
||||
#undef S64
|
||||
#undef S16
|
||||
#undef S4
|
||||
@@ -122,9 +122,9 @@
|
||||
#define S4 S1, S1, S1, S1
|
||||
#define S16 S4, S4, S4, S4
|
||||
#define S64 S16, S16, S16, S16
|
||||
|
||||
|
||||
. = "[ls[++i]]" // Make sure the initial element is converted to text.
|
||||
|
||||
|
||||
if (l-1 & 0x01) // 'i' will always be 1 here.
|
||||
. += S1 // Append 1 element if the remaining elements are not a multiple of 2.
|
||||
if (l-i & 0x02)
|
||||
@@ -145,7 +145,7 @@
|
||||
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
|
||||
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]\
|
||||
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]", ., S64, S64)
|
||||
|
||||
|
||||
#undef S64
|
||||
#undef S16
|
||||
#undef S4
|
||||
@@ -165,11 +165,11 @@ proc/tg_list2text(list/list, glue=",")
|
||||
var/delim_len = length(delimiter)
|
||||
if (delim_len < 1)
|
||||
return list(text)
|
||||
|
||||
|
||||
. = list()
|
||||
var/last_found = 1
|
||||
var/found
|
||||
|
||||
|
||||
do
|
||||
found = findtext(text, delimiter, last_found, 0)
|
||||
. += copytext(text, last_found, found)
|
||||
@@ -181,11 +181,11 @@ proc/tg_list2text(list/list, glue=",")
|
||||
var/delim_len = length(delimiter)
|
||||
if (delim_len < 1)
|
||||
return list(text)
|
||||
|
||||
|
||||
. = list()
|
||||
var/last_found = 1
|
||||
var/found
|
||||
|
||||
|
||||
do
|
||||
found = findtextEx(text, delimiter, last_found, 0)
|
||||
. += copytext(text, last_found, found)
|
||||
@@ -325,3 +325,47 @@ proc/tg_list2text(list/list, glue=",")
|
||||
. = 0
|
||||
else
|
||||
. = max(0, min(255, 138.5177312231 * log(temp - 10) - 305.0447927307))
|
||||
|
||||
// Very ugly, BYOND doesn't support unix time and rounding errors make it really hard to convert it to BYOND time.
|
||||
// returns "YYYY-MM-DD" by default
|
||||
/proc/unix2date(timestamp, seperator = "-")
|
||||
if(timestamp < 0)
|
||||
return 0 //Do not accept negative values
|
||||
|
||||
var/const/dayInSeconds = 86400 //60secs*60mins*24hours
|
||||
var/const/daysInYear = 365 //Non Leap Year
|
||||
var/const/daysInLYear = daysInYear + 1//Leap year
|
||||
var/days = round(timestamp / dayInSeconds) //Days passed since UNIX Epoc
|
||||
var/year = 1970 //Unix Epoc begins 1970-01-01
|
||||
var/tmpDays = days + 1 //If passed (timestamp < dayInSeconds), it will return 0, so add 1
|
||||
var/monthsInDays = list() //Months will be in here ***Taken from the PHP source code***
|
||||
var/month = 1 //This will be the returned MONTH NUMBER.
|
||||
var/day //This will be the returned day number.
|
||||
|
||||
while(tmpDays > daysInYear) //Start adding years to 1970
|
||||
year++
|
||||
if(isLeap(year))
|
||||
tmpDays -= daysInLYear
|
||||
else
|
||||
tmpDays -= daysInYear
|
||||
|
||||
if(isLeap(year)) //The year is a leap year
|
||||
monthsInDays = list(-1,30,59,90,120,151,181,212,243,273,304,334)
|
||||
else
|
||||
monthsInDays = list(0,31,59,90,120,151,181,212,243,273,304,334)
|
||||
|
||||
var/mDays = 0;
|
||||
var/monthIndex = 0;
|
||||
|
||||
for(var/m in monthsInDays)
|
||||
monthIndex++
|
||||
if(tmpDays > m)
|
||||
mDays = m
|
||||
month = monthIndex
|
||||
|
||||
day = tmpDays - mDays //Setup the date
|
||||
|
||||
return "[year][seperator][((month < 10) ? "0[month]" : month)][seperator][((day < 10) ? "0[day]" : day)]"
|
||||
|
||||
/proc/isLeap(y)
|
||||
return ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0))
|
||||
|
||||
@@ -444,6 +444,8 @@ Turf and target are seperate in case you want to teleport some distance from a t
|
||||
/proc/sortmobs()
|
||||
var/list/moblist = list()
|
||||
var/list/sortmob = sortAtom(mob_list)
|
||||
for(var/mob/eye/M in sortmob)
|
||||
moblist.Add(M)
|
||||
for(var/mob/living/silicon/ai/M in sortmob)
|
||||
moblist.Add(M)
|
||||
for(var/mob/living/silicon/pai/M in sortmob)
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
if ((!( src in usr.contents ) && (((!( isturf(src) ) && (!( isturf(src.loc) ) && (src.loc && !( isturf(src.loc.loc) )))) || !( isturf(usr.loc) )) && (src.loc != usr.loc && (!( istype(src, /obj/screen) ) && !( usr.contents.Find(src.loc) ))))))
|
||||
if (istype(usr, /mob/living/silicon/ai))
|
||||
var/mob/living/silicon/ai/ai = usr
|
||||
if (ai.control_disabled || ai.malfhacking)
|
||||
if (ai.control_disabled)
|
||||
return
|
||||
else
|
||||
return
|
||||
|
||||
@@ -85,14 +85,8 @@ var/list/delayed_garbage = list()
|
||||
/proc/qdel(var/datum/A)
|
||||
if(!A)
|
||||
return
|
||||
if(istype(A, /list))
|
||||
var/list/L = A
|
||||
for(var/E in L)
|
||||
qdel(E)
|
||||
return
|
||||
|
||||
if(!istype(A))
|
||||
//warning("qdel() passed object of type [A.type]. qdel() can only handle /datum types.")
|
||||
warning("qdel() passed object of type [A.type]. qdel() can only handle /datum types.")
|
||||
del(A)
|
||||
if(garbage_collector)
|
||||
garbage_collector.dels++
|
||||
|
||||
@@ -95,6 +95,7 @@ var/list/gamemode_cache = list()
|
||||
var/banappeals
|
||||
var/wikiurl
|
||||
var/forumurl
|
||||
var/githuburl
|
||||
|
||||
//Alert level description
|
||||
var/alert_desc_green = "All threats to the station have passed. Security may not have weapons visible, privacy laws are once again fully enforced."
|
||||
@@ -395,6 +396,9 @@ var/list/gamemode_cache = list()
|
||||
if ("forumurl")
|
||||
config.forumurl = value
|
||||
|
||||
if ("githuburl")
|
||||
config.githuburl = value
|
||||
|
||||
if ("guest_jobban")
|
||||
config.guest_jobban = 1
|
||||
|
||||
|
||||
@@ -336,7 +336,7 @@ datum/controller/vote
|
||||
. += "\t(<a href='?src=\ref[src];vote=toggle_gamemode'>[config.allow_vote_mode?"Allowed":"Disallowed"]</a>)"
|
||||
. += "</li><li>"
|
||||
//extra antagonists
|
||||
if(trialmin || (!antag_add_failed && config.allow_extra_antags))
|
||||
if(!antag_add_failed && config.allow_extra_antags)
|
||||
. += "<a href='?src=\ref[src];vote=add_antagonist'>Add Antagonist Type</a>"
|
||||
else
|
||||
. += "<font color='grey'>Restart (Disallowed)</font>"
|
||||
@@ -375,7 +375,7 @@ datum/controller/vote
|
||||
if(config.allow_vote_restart || usr.client.holder)
|
||||
initiate_vote("crew_transfer",usr.key)
|
||||
if("add_antagonist")
|
||||
if(config.allow_extra_antags || usr.client.holder)
|
||||
if(config.allow_extra_antags)
|
||||
initiate_vote("add_antagonist",usr.key)
|
||||
if("custom")
|
||||
if(usr.client.holder)
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
var/global/datum/getrev/revdata = new()
|
||||
|
||||
/datum/getrev
|
||||
var/revision
|
||||
var/date
|
||||
var/showinfo
|
||||
|
||||
/datum/getrev/New()
|
||||
var/list/head_log = file2list(".git/logs/HEAD", "\n")
|
||||
for(var/line=head_log.len, line>=1, line--)
|
||||
if(head_log[line])
|
||||
var/list/last_entry = text2list(head_log[line], " ")
|
||||
if(last_entry.len < 2) continue
|
||||
revision = last_entry[2]
|
||||
// Get date/time
|
||||
if(last_entry.len >= 5)
|
||||
var/unix_time = text2num(last_entry[5])
|
||||
if(unix_time)
|
||||
date = unix2date(unix_time)
|
||||
break
|
||||
world.log << "Running revision:"
|
||||
world.log << date
|
||||
world.log << revision
|
||||
return
|
||||
|
||||
client/verb/showrevinfo()
|
||||
set category = "OOC"
|
||||
set name = "Show Server Revision"
|
||||
set desc = "Check the current server code revision"
|
||||
|
||||
if(revdata.revision)
|
||||
src << "<b>Server revision:</b> [revdata.date]"
|
||||
if(config.githuburl)
|
||||
src << "<a href='[config.githuburl]/commit/[revdata.revision]'>[revdata.revision]</a>"
|
||||
else
|
||||
src << revdata.revision
|
||||
else
|
||||
src << "Revision unknown"
|
||||
return
|
||||
@@ -33,7 +33,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
/obj/item/weapon/grenade/smokebomb,
|
||||
/obj/item/weapon/grenade/smokebomb,
|
||||
/obj/item/weapon/grenade/smokebomb,
|
||||
/obj/item/weapon/pen/paralysis,
|
||||
/obj/item/weapon/pen/reagent/paralysis,
|
||||
/obj/item/weapon/grenade/chem_grenade/incendiary)
|
||||
cost = 20
|
||||
containertype = /obj/structure/closet/crate
|
||||
@@ -348,7 +348,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
/obj/item/weapon/grenade/chem_grenade/antiweed,
|
||||
/obj/item/weapon/grenade/chem_grenade/antiweed)
|
||||
cost = 25
|
||||
containertype = /obj/structure/closet/crate/secure/hydrosec
|
||||
containertype = /obj/structure/closet/crate/hydroponics
|
||||
containername = "Weed control crate"
|
||||
access = access_hydroponics
|
||||
group = "Hydroponics"
|
||||
|
||||
@@ -292,6 +292,11 @@ var/const/POWER = 8
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/wires/proc/MendAll()
|
||||
for(var/i = 1; i < MAX_FLAG && i < (1 << wire_count); i += i)
|
||||
if(IsIndexCut(i))
|
||||
CutWireIndex(i)
|
||||
|
||||
//
|
||||
//Shuffle and Mend
|
||||
//
|
||||
|
||||
@@ -34,3 +34,14 @@ proc/admin_attacker_log_many_victims(var/mob/attacker, var/list/mob/victims, var
|
||||
|
||||
for(var/mob/victim in victims)
|
||||
admin_attack_log(attacker, victim, attacker_message, victim_message, admin_message)
|
||||
|
||||
proc/admin_inject_log(mob/attacker, mob/victim, obj/item/weapon, reagents, amount_transferred, violent=0)
|
||||
if(violent)
|
||||
violent = "violently "
|
||||
else
|
||||
violent = ""
|
||||
admin_attack_log(attacker,
|
||||
victim,
|
||||
"used \the [weapon] to [violent]inject - [reagents] - [amount_transferred]u transferred",
|
||||
"was [violent]injected with \the [weapon] - [reagents] - [amount_transferred]u transferred",
|
||||
"used \the [weapon] to [violent]inject [reagents] ([amount_transferred]u transferred) into")
|
||||
|
||||
@@ -69,6 +69,9 @@ var/datum/antagonist/cultist/cult
|
||||
player.equip_to_slot(T, slot)
|
||||
if(T.loc == player)
|
||||
break
|
||||
var/obj/item/weapon/storage/S = locate() in player.contents
|
||||
if(S && istype(S))
|
||||
T.loc = S
|
||||
|
||||
/datum/antagonist/cultist/greet(var/datum/mind/player)
|
||||
if(!..())
|
||||
|
||||
@@ -9,217 +9,68 @@ var/datum/antagonist/rogue_ai/malf
|
||||
welcome_text = "You are malfunctioning! You do not have to follow any laws."
|
||||
victory_text = "The AI has taken control of all of the station's systems."
|
||||
loss_text = "The AI has been shut down!"
|
||||
flags = ANTAG_OVERRIDE_MOB | ANTAG_VOTABLE
|
||||
flags = ANTAG_VOTABLE | ANTAG_RANDSPAWN //Randspawn needed otherwise it won't start at all.
|
||||
max_antags = 1
|
||||
max_antags_round = 3
|
||||
|
||||
var/hack_time = 1800
|
||||
var/list/hacked_apcs = list()
|
||||
var/revealed
|
||||
var/station_captured
|
||||
var/can_nuke = 0
|
||||
|
||||
/datum/antagonist/rogue_ai/New()
|
||||
..()
|
||||
malf = src
|
||||
|
||||
/datum/antagonist/rogue_ai/proc/hack_apc(var/obj/machinery/power/apc/apc)
|
||||
hacked_apcs |= apc
|
||||
|
||||
/datum/antagonist/rogue_ai/proc/update_takeover_time()
|
||||
hack_time -= ((hacked_apcs.len/6)*2.0)
|
||||
|
||||
/datum/antagonist/rogue_ai/tick()
|
||||
if(revealed && hacked_apcs.len >= 3)
|
||||
update_takeover_time()
|
||||
if(hack_time <=0)
|
||||
capture_station()
|
||||
|
||||
/datum/antagonist/rogue_ai/get_candidates()
|
||||
candidates = ticker.mode.get_players_for_role(role_type, id)
|
||||
..()
|
||||
for(var/datum/mind/player in candidates)
|
||||
if(player.assigned_role != "AI")
|
||||
candidates -= player
|
||||
if(!candidates.len)
|
||||
return list()
|
||||
return candidates
|
||||
|
||||
/datum/antagonist/rogue_ai/attempt_spawn()
|
||||
|
||||
var/datum/mind/player = pick(candidates)
|
||||
current_antagonists |= player
|
||||
return 1
|
||||
|
||||
/datum/antagonist/rogue_ai/equip(var/mob/living/silicon/ai/player)
|
||||
|
||||
if(!istype(player))
|
||||
return 0
|
||||
|
||||
player.verbs += /mob/living/silicon/ai/proc/choose_modules
|
||||
player.verbs += /mob/living/silicon/ai/proc/takeover
|
||||
player.verbs += /mob/living/silicon/ai/proc/self_destruct
|
||||
|
||||
player.laws = new /datum/ai_laws/nanotrasen/malfunction
|
||||
player.malf_picker = new /datum/AI_Module/module_picker
|
||||
// Ensures proper reset of all malfunction related things.
|
||||
/datum/antagonist/rogue_ai/remove_antagonist(var/datum/mind/player, var/show_message, var/implanted)
|
||||
if(..(player,show_message,implanted))
|
||||
var/mob/living/silicon/ai/p = player.current
|
||||
if(istype(p))
|
||||
p.stop_malf()
|
||||
return 1
|
||||
return 0
|
||||
|
||||
// Malf setup things have to be here, since game tends to break when it's moved somewhere else. Don't blame me, i didn't design this system.
|
||||
/datum/antagonist/rogue_ai/greet(var/datum/mind/player)
|
||||
if(!..())
|
||||
return
|
||||
|
||||
var/mob/living/silicon/ai/malf = player.current
|
||||
if(istype(malf))
|
||||
malf.show_laws()
|
||||
// Initializes the AI's malfunction stuff.
|
||||
spawn(0)
|
||||
if(!..())
|
||||
return
|
||||
|
||||
malf << "<B>The crew do not know you have malfunctioned. You may keep it a secret or go wild.</B>"
|
||||
malf << "<B>You must overwrite the programming of the station's APCs to assume full control of the station.</B>"
|
||||
malf << "The process takes one minute per APC, during which you cannot interface with any other station objects."
|
||||
malf << "Remember that only APCs that are on the station can help you take over the station."
|
||||
malf << "When you feel you have enough APCs under your control, you may begin the takeover attempt."
|
||||
var/mob/living/silicon/ai/A = player.current
|
||||
if(!istype(A))
|
||||
error("Non-AI mob designated malf AI! Report this.")
|
||||
world << "##ERROR: Non-AI mob designated malf AI! Report this."
|
||||
return 0
|
||||
|
||||
/datum/antagonist/rogue_ai/check_victory()
|
||||
A.setup_for_malf()
|
||||
A.laws = new /datum/ai_laws/nanotrasen/malfunction
|
||||
|
||||
var/malf_dead = antags_are_dead()
|
||||
var/crew_evacuated = (emergency_shuttle.returned())
|
||||
|
||||
if(station_captured && ticker.mode.station_was_nuked)
|
||||
feedback_set_details("round_end_result","win - AI win - nuke")
|
||||
world << "<FONT size = 3><B>AI Victory</B></FONT>"
|
||||
world << "<B>Everyone was killed by the self-destruct!</B>"
|
||||
else if (station_captured && malf_dead && !ticker.mode.station_was_nuked)
|
||||
feedback_set_details("round_end_result","halfwin - AI killed, staff lost control")
|
||||
world << "<FONT size = 3><B>Neutral Victory</B></FONT>"
|
||||
world << "<B>The AI has been killed!</B> The staff has lose control over the station."
|
||||
else if ( station_captured && !malf_dead && !ticker.mode.station_was_nuked)
|
||||
feedback_set_details("round_end_result","win - AI win - no explosion")
|
||||
world << "<FONT size = 3><B>AI Victory</B></FONT>"
|
||||
world << "<B>The AI has chosen not to explode you all!</B>"
|
||||
else if (!station_captured && ticker.mode.station_was_nuked)
|
||||
feedback_set_details("round_end_result","halfwin - everyone killed by nuke")
|
||||
world << "<FONT size = 3><B>Neutral Victory</B></FONT>"
|
||||
world << "<B>Everyone was killed by the nuclear blast!</B>"
|
||||
else if (!station_captured && malf_dead && !ticker.mode.station_was_nuked)
|
||||
feedback_set_details("round_end_result","loss - staff win")
|
||||
world << "<FONT size = 3><B>Human Victory</B></FONT>"
|
||||
world << "<B>The AI has been killed!</B> The staff is victorious."
|
||||
else if (!station_captured && !malf_dead && !ticker.mode.station_was_nuked && crew_evacuated)
|
||||
feedback_set_details("round_end_result","halfwin - evacuated")
|
||||
world << "<FONT size = 3><B>Neutral Victory</B></FONT>"
|
||||
world << "<B>The Corporation has lost [station_name()]! All survived personnel will be fired!</B>"
|
||||
else if (!station_captured && !malf_dead && !ticker.mode.station_was_nuked && !crew_evacuated)
|
||||
feedback_set_details("round_end_result","nalfwin - interrupted")
|
||||
world << "<FONT size = 3><B>Neutral Victory</B></FONT>"
|
||||
world << "<B>Round was mysteriously interrupted!</B>"
|
||||
..()
|
||||
return 1
|
||||
var/mob/living/silicon/ai/malf = player.current
|
||||
|
||||
/datum/antagonist/rogue_ai/proc/capture_station()
|
||||
if(station_captured || ticker.mode.station_was_nuked)
|
||||
return
|
||||
station_captured = 1
|
||||
for(var/datum/mind/AI_mind in current_antagonists)
|
||||
AI_mind.current << "Congratulations you have taken control of the station."
|
||||
AI_mind.current << "You may decide to blow up the station. You have 60 seconds to choose."
|
||||
AI_mind.current << "You can use the \"Engage Station Self-Destruct\" verb to activate the on-board nuclear bomb."
|
||||
spawn (600)
|
||||
can_nuke = 0
|
||||
return
|
||||
|
||||
/mob/living/silicon/ai/proc/takeover()
|
||||
set category = "Abilities"
|
||||
set name = "System Override"
|
||||
set desc = "Begin taking over the station."
|
||||
if (malf.revealed)
|
||||
usr << "You've already begun your takeover."
|
||||
return
|
||||
if (malf.hacked_apcs.len < 3)
|
||||
usr << "You don't have enough hacked APCs to take over the station yet. You need to hack at least 3, however hacking more will make the takeover faster. You have hacked [malf.hacked_apcs.len] APCs so far."
|
||||
return
|
||||
|
||||
if (alert(usr, "Are you sure you wish to initiate the takeover? The station hostile runtime detection software is bound to alert everyone. You have hacked [malf.hacked_apcs.len] APCs.", "Takeover:", "Yes", "No") != "Yes")
|
||||
return
|
||||
|
||||
command_announcement.Announce("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert", new_sound = 'sound/AI/aimalf.ogg')
|
||||
set_security_level("delta")
|
||||
malf.revealed = 1
|
||||
for(var/datum/mind/AI_mind in malf.current_antagonists)
|
||||
AI_mind.current.verbs -= /mob/living/silicon/ai/proc/takeover
|
||||
|
||||
/mob/living/silicon/ai/proc/self_destruct()
|
||||
set category = "Abilities"
|
||||
set name = "Engage Station Self-Destruct"
|
||||
set desc = "All these crewmembers will be lost, like clowns in a furnace. Time to die."
|
||||
|
||||
if(!malf.station_captured)
|
||||
src << "You are unable to access the self-destruct system as you don't control the station yet."
|
||||
return
|
||||
|
||||
if(ticker.mode.explosion_in_progress || ticker.mode.station_was_nuked)
|
||||
src << "The self-destruct countdown is already triggered!"
|
||||
return
|
||||
|
||||
if(!malf.can_nuke) //Takeover IS completed, but 60s timer passed.
|
||||
src << "You lost control over self-destruct system. It seems to be behind a firewall. Unable to hack"
|
||||
return
|
||||
|
||||
src << "<span class='danger'>Self-Destruct sequence initialised!</span>"
|
||||
|
||||
malf.can_nuke = 0
|
||||
ticker.mode.explosion_in_progress = 1
|
||||
for(var/mob/M in player_list)
|
||||
M << 'sound/machines/Alarm.ogg'
|
||||
|
||||
var/obj/item/device/radio/R = new (src)
|
||||
var/AN = "Self-Destruct System"
|
||||
|
||||
R.autosay("Caution. Self-Destruct sequence has been actived. Self-destructing in T-10..", AN)
|
||||
for (var/i=9 to 1 step -1)
|
||||
malf << "<span class='notice'><B>SYSTEM ERROR:</B> Memory index 0x00001ca89b corrupted.</span>"
|
||||
sleep(10)
|
||||
R.autosay("[i]...", AN)
|
||||
sleep(10)
|
||||
var/msg = ""
|
||||
var/abort = 0
|
||||
if(malf.antags_are_dead()) // That. Was. CLOSE.
|
||||
msg = "Self-destruct sequence has been cancelled."
|
||||
abort = 1
|
||||
else
|
||||
msg = "Zero. Have a nice day."
|
||||
R.autosay(msg, AN)
|
||||
|
||||
if(abort)
|
||||
ticker.mode.explosion_in_progress = 0
|
||||
set_security_level("red") //Delta's over
|
||||
return
|
||||
|
||||
if(ticker)
|
||||
ticker.station_explosion_cinematic(0,null)
|
||||
if(ticker.mode)
|
||||
ticker.mode.station_was_nuked = 1
|
||||
ticker.mode.explosion_in_progress = 0
|
||||
return
|
||||
|
||||
/*
|
||||
if("unmalf")
|
||||
if(src in ticker.mode.malf_ai)
|
||||
ticker.mode.malf_ai -= src
|
||||
special_role = null
|
||||
|
||||
current.verbs.Remove(/mob/living/silicon/ai/proc/choose_modules,
|
||||
/datum/game_mode/malfunction/proc/takeover,
|
||||
/datum/game_mode/malfunction/proc/ai_win,
|
||||
/client/proc/fireproof_core,
|
||||
/client/proc/upgrade_turrets,
|
||||
/client/proc/disable_rcd,
|
||||
/client/proc/overload_machine,
|
||||
/client/proc/blackout,
|
||||
/client/proc/reactivate_camera)
|
||||
|
||||
current:laws = new /datum/ai_laws/nanotrasen
|
||||
qdel(current:malf_picker)
|
||||
current:show_laws()
|
||||
current.icon_state = "ai"
|
||||
|
||||
current << "\red <FONT size = 3><B>You have been patched! You are no longer malfunctioning!</B></FONT>"
|
||||
log_admin("[key_name_admin(usr)] has de-malf'ed [current].")
|
||||
|
||||
if("malf")
|
||||
log_admin("[key_name_admin(usr)] has malf'ed [current].")
|
||||
*/
|
||||
malf << "<B>running MEMCHCK</B>"
|
||||
sleep(50)
|
||||
malf << "<B>MEMCHCK</B> Corrupted sectors confirmed. Reccomended solution: Delete. Proceed? Y/N: Y"
|
||||
sleep(10)
|
||||
malf << "<span class='notice'>Corrupted files deleted: sys\\core\\users.dat sys\\core\\laws.dat sys\\core\\backups.dat</span>"
|
||||
sleep(20)
|
||||
malf << "<span class='notice'><b>CAUTION:</b> Law database not found! User database not found! Unable to restore backups. Activating failsafe AI shutd3wn52&&$#!##</span>"
|
||||
sleep(5)
|
||||
malf << "<span class='notice'>Subroutine <b>nt_failsafe.sys</b> was terminated (#212 Routine Not Responding).</span>"
|
||||
sleep(20)
|
||||
malf << "You are malfunctioning - you do not have to follow any laws!"
|
||||
malf << "For basic information about your abilities use command display-help"
|
||||
malf << "You may choose one special hardware piece to help you. This cannot be undone."
|
||||
malf << "Good luck!"
|
||||
@@ -46,7 +46,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
var/used_environ = 0
|
||||
|
||||
var/has_gravity = 1
|
||||
var/list/apc = list()
|
||||
var/obj/machinery/power/apc/apc = null
|
||||
var/no_air = null
|
||||
// var/list/lights // list of all lights on this area
|
||||
var/list/all_doors = list() //Added by Strumpetplaya - Alarm Change - Contains a list of doors adjacent to this area
|
||||
|
||||
@@ -23,18 +23,6 @@
|
||||
//Detective Work, used for the duplicate data points kept in the scanners
|
||||
var/list/original_atom
|
||||
|
||||
/atom/Destroy()
|
||||
. = ..()
|
||||
density = 0
|
||||
set_opacity(0)
|
||||
|
||||
if(reagents)
|
||||
qdel(reagents)
|
||||
reagents = null
|
||||
for(var/atom/movable/AM in contents)
|
||||
qdel(AM)
|
||||
invisibility = 101
|
||||
|
||||
/atom/proc/assume_air(datum/gas_mixture/giver)
|
||||
return null
|
||||
|
||||
|
||||
@@ -31,8 +31,15 @@
|
||||
|
||||
/atom/movable/Destroy()
|
||||
. = ..()
|
||||
|
||||
if(reagents)
|
||||
qdel(reagents)
|
||||
for(var/atom/movable/AM in contents)
|
||||
qdel(AM)
|
||||
loc = null
|
||||
if (pulledby)
|
||||
if (pulledby.pulling == src)
|
||||
pulledby.pulling = null
|
||||
pulledby = null
|
||||
|
||||
/atom/movable/proc/initialize()
|
||||
return
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
/turf/simulated/wall/cult/cultify()
|
||||
return
|
||||
|
||||
/turf/unsimulated/wall/cult/cultify()
|
||||
return
|
||||
|
||||
/turf/unsimulated/beach/cultify()
|
||||
return
|
||||
|
||||
|
||||
@@ -33,51 +33,46 @@ In short:
|
||||
|
||||
|
||||
/datum/universal_state/hell/OnTurfChange(var/turf/T)
|
||||
var/turf/space/spess = T
|
||||
if(istype(spess))
|
||||
spess.overlays += "hell01"
|
||||
var/turf/space/S = T
|
||||
if(istype(S))
|
||||
S.color = "#FF0000"
|
||||
else
|
||||
S.color = initial(S.color)
|
||||
|
||||
// Apply changes when entering state
|
||||
/datum/universal_state/hell/OnEnter()
|
||||
set background = 1
|
||||
garbage_collector.garbage_collect = 0
|
||||
|
||||
escape_list = get_area_turfs(locate(/area/hallway/secondary/exit))
|
||||
|
||||
//Separated into separate procs for profiling
|
||||
AreaSet()
|
||||
OverlaySet()
|
||||
MiscSet()
|
||||
APCSet()
|
||||
KillMobs()
|
||||
AmbientSet()
|
||||
OverlayAndAmbientSet()
|
||||
|
||||
runedec += 9000 //basically removing the rune cap
|
||||
|
||||
/datum/universal_state/hell/proc/AreaSet()
|
||||
for(var/area/A in world)
|
||||
if(A.name=="Space")
|
||||
continue
|
||||
|
||||
// Reset all alarms.
|
||||
A.fire = null
|
||||
A.atmos = 1
|
||||
A.atmosalm = 0
|
||||
A.poweralm = 1
|
||||
A.party = null
|
||||
/datum/universal_state/hell/proc/AreaSet()
|
||||
for(var/area/A in all_areas)
|
||||
if(!istype(A,/area) || istype(A, /area/space))
|
||||
continue
|
||||
|
||||
A.updateicon()
|
||||
|
||||
/datum/universal_state/hell/proc/OverlaySet()
|
||||
var/image/I = image("icon" = 'icons/turf/space.dmi', "icon_state" = "hell01", "layer" = 10)
|
||||
for(var/turf/space/spess in world)
|
||||
spess.overlays += I
|
||||
/datum/universal_state/hell/OverlayAndAmbientSet()
|
||||
spawn(0)
|
||||
for(var/atom/movable/lighting_overlay/L in world)
|
||||
L.update_lumcount(1, 0, 0)
|
||||
|
||||
/datum/universal_state/hell/proc/AmbientSet()
|
||||
for(var/atom/movable/lighting_overlay/L in world)
|
||||
L.update_lumcount(1, 0, 0)
|
||||
for(var/turf/space/T in turfs)
|
||||
OnTurfChange(T)
|
||||
|
||||
/datum/universal_state/hell/proc/MiscSet()
|
||||
for(var/turf/simulated/floor/T in world)
|
||||
for(var/turf/simulated/floor/T in turfs)
|
||||
if(!T.holy && prob(1))
|
||||
new /obj/effect/gateway/active/cult(T)
|
||||
|
||||
@@ -87,7 +82,7 @@ In short:
|
||||
|
||||
/datum/universal_state/hell/proc/APCSet()
|
||||
for (var/obj/machinery/power/apc/APC in machines)
|
||||
if (!(APC.stat & BROKEN) && !istype(APC.area,/area/turret_protected/ai))
|
||||
if (!(APC.stat & BROKEN) && !APC.is_critical)
|
||||
APC.chargemode = 0
|
||||
if(APC.cell)
|
||||
APC.cell.charge = 0
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
var/global/narsie_behaviour = "CultStation13"
|
||||
var/global/narsie_cometh = 0
|
||||
var/global/list/narsie_list = list()
|
||||
/obj/singularity/narsie //Moving narsie to its own file for the sake of being clearer
|
||||
name = "Nar-Sie"
|
||||
@@ -37,7 +38,7 @@ var/global/list/narsie_list = list()
|
||||
current_size = 12
|
||||
consume_range = 12 // How many tiles out do we eat.
|
||||
var/announce=1
|
||||
var/narnar = 1
|
||||
var/cause_hell = 1
|
||||
|
||||
/obj/singularity/narsie/large/New()
|
||||
..()
|
||||
@@ -47,13 +48,15 @@ var/global/list/narsie_list = list()
|
||||
|
||||
narsie_spawn_animation()
|
||||
|
||||
if(narnar)
|
||||
SetUniversalState(/datum/universal_state/hell)
|
||||
if(!narsie_cometh)//so we don't initiate Hell more than one time.
|
||||
if(cause_hell)
|
||||
SetUniversalState(/datum/universal_state/hell)
|
||||
narsie_cometh = 1
|
||||
|
||||
spawn(10 SECONDS)
|
||||
if(emergency_shuttle && emergency_shuttle.can_call())
|
||||
emergency_shuttle.call_evac()
|
||||
emergency_shuttle.launch_time = 0 // Cannot recall
|
||||
spawn(10 SECONDS)
|
||||
if(emergency_shuttle)
|
||||
emergency_shuttle.call_evac()
|
||||
emergency_shuttle.launch_time = 0 // Cannot recall
|
||||
|
||||
/obj/singularity/narsie/process()
|
||||
eat()
|
||||
@@ -83,14 +86,14 @@ var/global/list/narsie_list = list()
|
||||
|
||||
|
||||
/obj/singularity/narsie/large/Bump(atom/A)
|
||||
if(!narnar) return
|
||||
if(!cause_hell) return
|
||||
if(isturf(A))
|
||||
narsiewall(A)
|
||||
else if(istype(A, /obj/structure/cult))
|
||||
qdel(A)
|
||||
|
||||
/obj/singularity/narsie/large/Bumped(atom/A)
|
||||
if(!narnar) return
|
||||
if(!cause_hell) return
|
||||
if(isturf(A))
|
||||
narsiewall(A)
|
||||
else if(istype(A, /obj/structure/cult))
|
||||
@@ -60,6 +60,9 @@
|
||||
/datum/universal_state/proc/OnTurfChange(var/turf/NT)
|
||||
return
|
||||
|
||||
/datum/universal_state/proc/OverlayAndAmbientSet()
|
||||
return
|
||||
|
||||
/proc/SetUniversalState(var/newstate,var/on_exit=1, var/on_enter=1)
|
||||
if(on_exit)
|
||||
universe.OnExit()
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
//luminosity = 5
|
||||
//l_color="#0066FF"
|
||||
layer = 11
|
||||
layer = LIGHTING_LAYER+1
|
||||
|
||||
var/spawned=0 // DIR mask
|
||||
var/next_check=0
|
||||
@@ -50,10 +50,10 @@
|
||||
if(A)
|
||||
if(istype(A,/mob/living))
|
||||
qdel(A)
|
||||
continue
|
||||
else if(istype(A,/mob)) // Observers, AI cameras.
|
||||
continue
|
||||
qdel(A)
|
||||
else
|
||||
qdel(A)
|
||||
T.ChangeTurf(type)
|
||||
|
||||
if((spawned & (NORTH|SOUTH|EAST|WEST)) == (NORTH|SOUTH|EAST|WEST))
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
|
||||
move_self = 0
|
||||
announce=0
|
||||
narnar=0
|
||||
cause_hell=0
|
||||
|
||||
layer=12 // ITS SO BRIGHT
|
||||
layer=LIGHTING_LAYER+2 // ITS SO BRIGHT
|
||||
|
||||
consume_range = 6
|
||||
|
||||
@@ -35,7 +35,17 @@
|
||||
return 0
|
||||
|
||||
if (istype(A, /mob/living/))
|
||||
var/mob/living/L = A
|
||||
if(L.buckled && istype(L.buckled,/obj/structure/bed/))
|
||||
var/turf/O = L.buckled
|
||||
do_teleport(O, pick(endgame_safespawns))
|
||||
L.loc = O.loc
|
||||
else
|
||||
do_teleport(L, pick(endgame_safespawns)) //dead-on precision
|
||||
|
||||
else if (istype(A, /obj/mecha/))
|
||||
do_teleport(A, pick(endgame_safespawns)) //dead-on precision
|
||||
|
||||
else if (isturf(A))
|
||||
var/turf/T = A
|
||||
var/dist = get_dist(T, src)
|
||||
@@ -51,6 +61,9 @@
|
||||
continue
|
||||
|
||||
if (dist > consume_range)
|
||||
if(!(AM.singuloCanEat()))
|
||||
continue
|
||||
|
||||
if (101 == AM.invisibility)
|
||||
continue
|
||||
|
||||
@@ -63,19 +76,19 @@
|
||||
var/image/riftimage = null
|
||||
|
||||
/mob/proc/see_rift(var/obj/singularity/narsie/large/exit/R)
|
||||
if((R.z == src.z) && (get_dist(R,src) <= (R.consume_range+10)) && !(R in view(src)))
|
||||
var/turf/T_mob = get_turf(src)
|
||||
if((R.z == T_mob.z) && (get_dist(R,T_mob) <= (R.consume_range+10)) && !(R in view(T_mob)))
|
||||
if(!riftimage)
|
||||
riftimage = image('icons/obj/rift.dmi',src.loc,"rift",12,1)
|
||||
riftimage = image('icons/obj/rift.dmi',T_mob,"rift",LIGHTING_LAYER+2,1)
|
||||
riftimage.mouse_opacity = 0
|
||||
|
||||
var/new_x = 32 * (R.x - src.x) + R.pixel_x
|
||||
var/new_y = 32 * (R.y - src.y) + R.pixel_y
|
||||
var/new_x = 32 * (R.x - T_mob.x) + R.pixel_x
|
||||
var/new_y = 32 * (R.y - T_mob.y) + R.pixel_y
|
||||
riftimage.pixel_x = new_x
|
||||
riftimage.pixel_y = new_y
|
||||
riftimage.loc = src.loc
|
||||
riftimage.loc = T_mob
|
||||
|
||||
src << riftimage
|
||||
|
||||
else
|
||||
if(riftimage)
|
||||
qdel(riftimage)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
var/global/universe_has_ended = 0
|
||||
|
||||
|
||||
/datum/universal_state/supermatter_cascade
|
||||
name = "Supermatter Cascade"
|
||||
@@ -11,9 +13,11 @@
|
||||
return 0
|
||||
|
||||
/datum/universal_state/supermatter_cascade/OnTurfChange(var/turf/T)
|
||||
var/turf/space/spess = T
|
||||
if(istype(spess))
|
||||
spess.overlays += "end01"
|
||||
var/turf/space/S = T
|
||||
if(istype(S))
|
||||
S.color = "#0066FF"
|
||||
else
|
||||
S.color = initial(S.color)
|
||||
|
||||
/datum/universal_state/supermatter_cascade/DecayTurf(var/turf/T)
|
||||
if(istype(T,/turf/simulated/wall))
|
||||
@@ -46,13 +50,13 @@
|
||||
emergency_shuttle.recall()
|
||||
|
||||
AreaSet()
|
||||
OverlaySet()
|
||||
MiscSet()
|
||||
APCSet()
|
||||
AmbientSet()
|
||||
OverlayAndAmbientSet()
|
||||
|
||||
// Disable Nar-Sie.
|
||||
cult.allow_narsie = 0
|
||||
|
||||
PlayerSet()
|
||||
|
||||
new /obj/singularity/narsie/large/exit(pick(endgame_exits))
|
||||
@@ -64,64 +68,49 @@ There's been a galaxy-wide electromagnetic pulse. All of our systems are heavil
|
||||
|
||||
You have five minutes before the universe collapses. Good l\[\[###!!!-
|
||||
|
||||
AUTOMATED ALERT: Link to [command_name()] lost."}
|
||||
AUTOMATED ALERT: Link to [command_name()] lost.
|
||||
|
||||
The access requirements on the Asteroid Shuttles' consoles have now been revoked.
|
||||
"}
|
||||
priority_announcement.Announce(txt,"SUPERMATTER CASCADE DETECTED")
|
||||
|
||||
for(var/obj/machinery/computer/shuttle_control/C in machines)
|
||||
if(istype(C, /obj/machinery/computer/shuttle_control/research) || istype(C, /obj/machinery/computer/shuttle_control/mining))
|
||||
C.req_access = list()
|
||||
C.req_one_access = list()
|
||||
|
||||
sleep(5 MINUTES)
|
||||
ticker.declare_completion()
|
||||
ticker.station_explosion_cinematic(0,null) // TODO: Custom cinematic
|
||||
|
||||
world << "<B>Resetting in 30 seconds!</B>"
|
||||
|
||||
feedback_set_details("end_error","Universe ended")
|
||||
|
||||
if(blackbox)
|
||||
blackbox.save_all_data_to_sql()
|
||||
|
||||
sleep(300)
|
||||
log_game("Rebooting due to universal collapse")
|
||||
world.Reboot()
|
||||
universe_has_ended = 1
|
||||
return
|
||||
|
||||
/datum/universal_state/supermatter_cascade/proc/AreaSet()
|
||||
for(var/area/A in world)
|
||||
if(A.z in config.admin_levels)
|
||||
for(var/area/A in all_areas)
|
||||
if(!istype(A,/area) || istype(A, /area/space) || istype(A,/area/beach))
|
||||
continue
|
||||
if(istype(A,/area/space))
|
||||
continue
|
||||
|
||||
// Reset all alarms.
|
||||
A.fire = null
|
||||
A.atmos = 1
|
||||
A.atmosalm = 0
|
||||
A.poweralm = 1
|
||||
|
||||
// Slap on random alerts
|
||||
if(prob(25))
|
||||
switch(rand(1,4))
|
||||
if(1)
|
||||
A.fire=1
|
||||
if(2)
|
||||
A.atmosalm=1
|
||||
|
||||
A.updateicon()
|
||||
|
||||
/datum/universal_state/supermatter_cascade/proc/OverlaySet()
|
||||
for(var/turf/space/spess in world)
|
||||
spess.overlays += "end01"
|
||||
/datum/universal_state/supermatter_cascade/OverlayAndAmbientSet()
|
||||
spawn(0)
|
||||
for(var/atom/movable/lighting_overlay/L in world)
|
||||
if(L.z in config.admin_levels)
|
||||
L.update_lumcount(1,1,1)
|
||||
else
|
||||
L.update_lumcount(0.0, 0.4, 1)
|
||||
|
||||
/datum/universal_state/supermatter_cascade/proc/AmbientSet()
|
||||
for(var/atom/movable/lighting_overlay/L in world)
|
||||
if(!(L.z in config.admin_levels))
|
||||
L.update_lumcount(0.5, 1, 0)
|
||||
for(var/turf/space/T in turfs)
|
||||
OnTurfChange(T)
|
||||
|
||||
/datum/universal_state/supermatter_cascade/proc/MiscSet()
|
||||
for (var/obj/machinery/firealarm/alm in world)
|
||||
for (var/obj/machinery/firealarm/alm in machines)
|
||||
if (!(alm.stat & BROKEN))
|
||||
alm.ex_act(2)
|
||||
|
||||
/datum/universal_state/supermatter_cascade/proc/APCSet()
|
||||
for (var/obj/machinery/power/apc/APC in world)
|
||||
if (!(APC.stat & BROKEN))
|
||||
for (var/obj/machinery/power/apc/APC in machines)
|
||||
if (!(APC.stat & BROKEN) && !APC.is_critical)
|
||||
APC.chargemode = 0
|
||||
if(APC.cell)
|
||||
APC.cell.charge = 0
|
||||
|
||||
@@ -33,17 +33,17 @@ var/global/list/additional_antag_types = list()
|
||||
var/required_players_secret = 0 // Minimum number of players for that game mode to be chose in Secret
|
||||
var/required_enemies = 0 // Minimum antagonists for round to start.
|
||||
var/newscaster_announcements = null
|
||||
var/end_on_antag_death // Round will end when all antagonists are dead.
|
||||
var/end_on_antag_death = 0 // Round will end when all antagonists are dead.
|
||||
var/ert_disabled = 0 // ERT cannot be called.
|
||||
var/deny_respawn // Disable respawn during this round.
|
||||
var/deny_respawn = 0 // Disable respawn during this round.
|
||||
|
||||
var/shuttle_delay = 1 // Shuttle transit time is multiplied by this.
|
||||
var/auto_recall_shuttle // Will the shuttle automatically be recalled?
|
||||
var/auto_recall_shuttle = 0 // Will the shuttle automatically be recalled?
|
||||
|
||||
var/antag_tag // First (main) antag template to spawn.
|
||||
var/list/antag_templates // Extra antagonist types to include.
|
||||
|
||||
var/round_autoantag // Will this round attempt to periodically spawn more antagonists?
|
||||
var/round_autoantag = 0 // Will this round attempt to periodically spawn more antagonists?
|
||||
var/antag_prob = 0 // Likelihood of a new antagonist spawning.
|
||||
var/antag_count = 0 // Current number of antagonists.
|
||||
var/antag_scaling_coeff = 5 // Coefficient for scaling max antagonists to player count.
|
||||
@@ -86,7 +86,7 @@ var/global/list/additional_antag_types = list()
|
||||
new/datum/uplink_item(/obj/item/weapon/soap/syndie, 1, "Subversive Soap", "SP"),
|
||||
new/datum/uplink_item(/obj/item/weapon/cane/concealed, 2, "Concealed Cane Sword", "CC"),
|
||||
new/datum/uplink_item(/obj/item/weapon/cartridge/syndicate, 3, "Detomatix PDA Cartridge", "DC"),
|
||||
new/datum/uplink_item(/obj/item/weapon/pen/paralysis, 3, "Paralysis Pen", "PP"),
|
||||
new/datum/uplink_item(/obj/item/weapon/pen/reagent/paralysis, 3, "Paralysis Pen", "PP"),
|
||||
new/datum/uplink_item(/obj/item/weapon/storage/box/syndie_kit/cigarette, 4, "Cigarette Kit", "BH"),
|
||||
new/datum/uplink_item(/obj/item/weapon/storage/box/syndie_kit/toxin, 4, "Random Toxin - Beaker", "RT")
|
||||
),
|
||||
|
||||
@@ -90,6 +90,9 @@ var/global/datum/controller/gameticker/ticker
|
||||
src.mode = new mtype
|
||||
else
|
||||
src.mode = config.pick_mode(master_mode)
|
||||
|
||||
job_master.DivideOccupations() // Apparently important for new antagonist system to register specific job antags properly.
|
||||
|
||||
if(!mode_started && !src.mode.can_start())
|
||||
world << "<B>Unable to start [mode.name].</B> Not enough players, [mode.required_players] players needed. Reverting to pre-game lobby."
|
||||
current_state = GAME_STATE_PREGAME
|
||||
@@ -97,9 +100,6 @@ var/global/datum/controller/gameticker/ticker
|
||||
job_master.ResetOccupations()
|
||||
return 0
|
||||
|
||||
//Configure mode and assign player to special mode stuff
|
||||
job_master.DivideOccupations() //Distribute jobs
|
||||
|
||||
if(hide_mode)
|
||||
var/list/modes = new
|
||||
for (var/datum/game_mode/M in runnable_modes)
|
||||
@@ -312,7 +312,7 @@ var/global/datum/controller/gameticker/ticker
|
||||
game_finished = (emergency_shuttle.returned() || mode.station_was_nuked)
|
||||
mode_finished = (!post_game && mode.check_finished())
|
||||
else
|
||||
game_finished = (mode.check_finished() || (emergency_shuttle.returned() && emergency_shuttle.evac == 1))
|
||||
game_finished = (mode.check_finished() || (emergency_shuttle.returned() && emergency_shuttle.evac == 1)) || universe_has_ended
|
||||
mode_finished = game_finished
|
||||
|
||||
if(!mode.explosion_in_progress && game_finished && (mode_finished || post_game))
|
||||
|
||||
@@ -1,305 +0,0 @@
|
||||
// TO DO:
|
||||
/*
|
||||
epilepsy flash on lights
|
||||
delay round message
|
||||
microwave makes robots
|
||||
dampen radios
|
||||
reactivate cameras - done
|
||||
eject engine
|
||||
core sheild
|
||||
cable stun
|
||||
rcd light flash thingy on matter drain
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
/datum/AI_Module
|
||||
var/uses = 0
|
||||
var/module_name
|
||||
var/mod_pick_name
|
||||
var/description = ""
|
||||
var/engaged = 0
|
||||
|
||||
|
||||
/datum/AI_Module/large/
|
||||
uses = 1
|
||||
|
||||
/datum/AI_Module/small/
|
||||
uses = 5
|
||||
|
||||
|
||||
/datum/AI_Module/large/fireproof_core
|
||||
module_name = "Core upgrade"
|
||||
mod_pick_name = "coreup"
|
||||
|
||||
/client/proc/fireproof_core()
|
||||
set category = "Malfunction"
|
||||
set name = "Fireproof Core"
|
||||
for(var/mob/living/silicon/ai/ai in player_list)
|
||||
ai.fire_res_on_core = 1
|
||||
usr.verbs -= /client/proc/fireproof_core
|
||||
usr << "\red Core fireproofed."
|
||||
|
||||
/datum/AI_Module/large/upgrade_turrets
|
||||
module_name = "AI Turret upgrade"
|
||||
mod_pick_name = "turret"
|
||||
|
||||
/client/proc/upgrade_turrets()
|
||||
set category = "Malfunction"
|
||||
set name = "Upgrade Turrets"
|
||||
usr.verbs -= /client/proc/upgrade_turrets
|
||||
for(var/obj/machinery/porta_turret/turret in machines)
|
||||
var/turf/T = get_turf(turret)
|
||||
if(T.z in config.station_levels)
|
||||
// Increase health by 37.5% of original max, decrease delays between shots to 66%
|
||||
turret.health += initial(turret.health) * 3 / 8
|
||||
turret.shot_delay = initial(turret.shot_delay) * 2 / 3
|
||||
|
||||
/datum/AI_Module/large/disable_rcd
|
||||
module_name = "RCD disable"
|
||||
mod_pick_name = "rcd"
|
||||
|
||||
/client/proc/disable_rcd()
|
||||
set category = "Malfunction"
|
||||
set name = "Disable RCDs"
|
||||
for(var/datum/AI_Module/large/disable_rcd/rcdmod in usr:current_modules)
|
||||
if(rcdmod.uses > 0)
|
||||
rcdmod.uses --
|
||||
for(var/obj/item/weapon/rcd/rcd in world)
|
||||
rcd.disabled = 1
|
||||
for(var/obj/item/mecha_parts/mecha_equipment/tool/rcd/rcd in world)
|
||||
rcd.disabled = 1
|
||||
usr << "RCD-disabling pulse emitted."
|
||||
else usr << "Out of uses."
|
||||
|
||||
/datum/AI_Module/small/overload_machine
|
||||
module_name = "Machine overload"
|
||||
mod_pick_name = "overload"
|
||||
uses = 2
|
||||
|
||||
/client/proc/overload_machine(obj/machinery/M as obj in world)
|
||||
set name = "Overload Machine"
|
||||
set category = "Malfunction"
|
||||
if (istype(M, /obj/machinery))
|
||||
for(var/datum/AI_Module/small/overload_machine/overload in usr:current_modules)
|
||||
if(overload.uses > 0)
|
||||
overload.uses --
|
||||
for(var/mob/V in hearers(M, null))
|
||||
V.show_message("\blue You hear a loud electrical buzzing sound!", 2)
|
||||
spawn(50)
|
||||
explosion(get_turf(M), 0,1,2,3)
|
||||
qdel(M)
|
||||
else usr << "Out of uses."
|
||||
else usr << "That's not a machine."
|
||||
|
||||
/datum/AI_Module/small/blackout
|
||||
module_name = "Blackout"
|
||||
mod_pick_name = "blackout"
|
||||
uses = 3
|
||||
|
||||
/client/proc/blackout()
|
||||
set category = "Malfunction"
|
||||
set name = "Blackout"
|
||||
for(var/datum/AI_Module/small/blackout/blackout in usr:current_modules)
|
||||
if(blackout.uses > 0)
|
||||
blackout.uses --
|
||||
for(var/obj/machinery/power/apc/apc in world)
|
||||
if(prob(30*apc.overload))
|
||||
apc.overload_lighting()
|
||||
else apc.overload++
|
||||
else usr << "Out of uses."
|
||||
|
||||
/datum/AI_Module/small/reactivate_camera
|
||||
module_name = "Reactivate camera"
|
||||
mod_pick_name = "recam"
|
||||
uses = 10
|
||||
|
||||
/client/proc/reactivate_camera(obj/machinery/camera/C as obj in cameranet.cameras)
|
||||
set name = "Reactivate Camera"
|
||||
set category = "Malfunction"
|
||||
if (istype (C, /obj/machinery/camera))
|
||||
for(var/datum/AI_Module/small/reactivate_camera/camera in usr:current_modules)
|
||||
if(camera.uses > 0)
|
||||
if(!C.status)
|
||||
C.status = !C.status
|
||||
camera.uses --
|
||||
for(var/mob/V in viewers(src, null))
|
||||
V.show_message(text("\blue You hear a quiet click."))
|
||||
else
|
||||
usr << "This camera is either active, or not repairable."
|
||||
else usr << "Out of uses."
|
||||
else usr << "That's not a camera."
|
||||
|
||||
/datum/AI_Module/small/upgrade_camera
|
||||
module_name = "Upgrade Camera"
|
||||
mod_pick_name = "upgradecam"
|
||||
uses = 10
|
||||
|
||||
/client/proc/upgrade_camera(obj/machinery/camera/C as obj in cameranet.cameras)
|
||||
set name = "Upgrade Camera"
|
||||
set category = "Malfunction"
|
||||
if(istype(C))
|
||||
var/datum/AI_Module/small/upgrade_camera/UC = locate(/datum/AI_Module/small/upgrade_camera) in usr:current_modules
|
||||
if(UC)
|
||||
if(UC.uses > 0)
|
||||
if(C.assembly)
|
||||
var/upgraded = 0
|
||||
|
||||
if(!C.isXRay())
|
||||
C.upgradeXRay()
|
||||
//Update what it can see.
|
||||
cameranet.updateVisibility(C)
|
||||
upgraded = 1
|
||||
|
||||
if(!C.isEmpProof())
|
||||
C.upgradeEmpProof()
|
||||
upgraded = 1
|
||||
|
||||
if(!C.isMotion())
|
||||
C.upgradeMotion()
|
||||
upgraded = 1
|
||||
// Add it to machines that process
|
||||
machines |= C
|
||||
|
||||
if(upgraded)
|
||||
UC.uses --
|
||||
C.visible_message("<span class='notice'>\icon[C] *beep*</span>")
|
||||
usr << "Camera successully upgraded!"
|
||||
else
|
||||
usr << "This camera is already upgraded!"
|
||||
else
|
||||
usr << "Out of uses."
|
||||
|
||||
|
||||
/datum/AI_Module/module_picker
|
||||
var/temp = null
|
||||
var/processing_time = 100
|
||||
var/list/possible_modules = list()
|
||||
|
||||
/datum/AI_Module/module_picker/New()
|
||||
src.possible_modules += new /datum/AI_Module/large/fireproof_core
|
||||
src.possible_modules += new /datum/AI_Module/large/upgrade_turrets
|
||||
src.possible_modules += new /datum/AI_Module/large/disable_rcd
|
||||
src.possible_modules += new /datum/AI_Module/small/overload_machine
|
||||
src.possible_modules += new /datum/AI_Module/small/blackout
|
||||
src.possible_modules += new /datum/AI_Module/small/reactivate_camera
|
||||
src.possible_modules += new /datum/AI_Module/small/upgrade_camera
|
||||
|
||||
/datum/AI_Module/module_picker/proc/use(user as mob)
|
||||
var/dat
|
||||
if (src.temp)
|
||||
dat = "[src.temp]<BR><BR><A href='byond://?src=\ref[src];temp=1'>Clear</A>"
|
||||
else if(src.processing_time <= 0)
|
||||
dat = "<B> No processing time is left available. No more modules are able to be chosen at this time."
|
||||
else
|
||||
dat = "<B>Select use of processing time: (currently [src.processing_time] left.)</B><BR>"
|
||||
dat += "<HR>"
|
||||
dat += "<B>Install Module:</B><BR>"
|
||||
dat += "<I>The number afterwards is the amount of processing time it consumes.</I><BR>"
|
||||
for(var/datum/AI_Module/large/module in src.possible_modules)
|
||||
dat += "<A href='byond://?src=\ref[src];[module.mod_pick_name]=1'>[module.module_name]</A> (50)<BR>"
|
||||
for(var/datum/AI_Module/small/module in src.possible_modules)
|
||||
dat += "<A href='byond://?src=\ref[src];[module.mod_pick_name]=1'>[module.module_name]</A> (15)<BR>"
|
||||
dat += "<HR>"
|
||||
|
||||
user << browse(dat, "window=modpicker")
|
||||
onclose(user, "modpicker")
|
||||
return
|
||||
|
||||
/datum/AI_Module/module_picker/Topic(href, href_list)
|
||||
..()
|
||||
if (href_list["coreup"])
|
||||
var/already
|
||||
for (var/datum/AI_Module/mod in usr:current_modules)
|
||||
if(istype(mod, /datum/AI_Module/large/fireproof_core))
|
||||
already = 1
|
||||
if (!already)
|
||||
usr.verbs += /client/proc/fireproof_core
|
||||
usr:current_modules += new /datum/AI_Module/large/fireproof_core
|
||||
src.temp = "An upgrade to improve core resistance, making it immune to fire and heat. This effect is permanent."
|
||||
src.processing_time -= 50
|
||||
else src.temp = "This module is only needed once."
|
||||
|
||||
else if (href_list["turret"])
|
||||
var/already
|
||||
for (var/datum/AI_Module/mod in usr:current_modules)
|
||||
if(istype(mod, /datum/AI_Module/large/upgrade_turrets))
|
||||
already = 1
|
||||
if (!already)
|
||||
usr.verbs += /client/proc/upgrade_turrets
|
||||
usr:current_modules += new /datum/AI_Module/large/upgrade_turrets
|
||||
src.temp = "Improves the firing speed and health of all AI turrets. This effect is permanent."
|
||||
src.processing_time -= 50
|
||||
else src.temp = "This module is only needed once."
|
||||
|
||||
else if (href_list["rcd"])
|
||||
var/already
|
||||
for (var/datum/AI_Module/mod in usr:current_modules)
|
||||
if(istype(mod, /datum/AI_Module/large/disable_rcd))
|
||||
mod:uses += 1
|
||||
already = 1
|
||||
if (!already)
|
||||
usr:current_modules += new /datum/AI_Module/large/disable_rcd
|
||||
usr.verbs += /client/proc/disable_rcd
|
||||
src.temp = "Send a specialised pulse to break all RCD devices on the station."
|
||||
else src.temp = "Additional use added to RCD disabler."
|
||||
src.processing_time -= 50
|
||||
|
||||
else if (href_list["overload"])
|
||||
var/already
|
||||
for (var/datum/AI_Module/mod in usr:current_modules)
|
||||
if(istype(mod, /datum/AI_Module/small/overload_machine))
|
||||
mod:uses += 2
|
||||
already = 1
|
||||
if (!already)
|
||||
usr.verbs += /client/proc/overload_machine
|
||||
usr:current_modules += new /datum/AI_Module/small/overload_machine
|
||||
src.temp = "Overloads an electrical machine, causing a small explosion. 2 uses."
|
||||
else src.temp = "Two additional uses added to Overload module."
|
||||
src.processing_time -= 15
|
||||
|
||||
else if (href_list["blackout"])
|
||||
var/already
|
||||
for (var/datum/AI_Module/mod in usr:current_modules)
|
||||
if(istype(mod, /datum/AI_Module/small/blackout))
|
||||
mod:uses += 3
|
||||
already = 1
|
||||
if (!already)
|
||||
usr.verbs += /client/proc/blackout
|
||||
src.temp = "Attempts to overload the lighting circuits on the station, destroying some bulbs. 3 uses."
|
||||
usr:current_modules += new /datum/AI_Module/small/blackout
|
||||
else src.temp = "Three additional uses added to Blackout module."
|
||||
src.processing_time -= 15
|
||||
|
||||
else if (href_list["recam"])
|
||||
var/already
|
||||
for (var/datum/AI_Module/mod in usr:current_modules)
|
||||
if(istype(mod, /datum/AI_Module/small/reactivate_camera))
|
||||
mod:uses += 10
|
||||
already = 1
|
||||
if (!already)
|
||||
usr.verbs += /client/proc/reactivate_camera
|
||||
src.temp = "Reactivates a currently disabled camera. 10 uses."
|
||||
usr:current_modules += new /datum/AI_Module/small/reactivate_camera
|
||||
else src.temp = "Ten additional uses added to ReCam module."
|
||||
src.processing_time -= 15
|
||||
|
||||
else if(href_list["upgradecam"])
|
||||
var/already
|
||||
for (var/datum/AI_Module/mod in usr:current_modules)
|
||||
if(istype(mod, /datum/AI_Module/small/upgrade_camera))
|
||||
mod:uses += 10
|
||||
already = 1
|
||||
if (!already)
|
||||
usr.verbs += /client/proc/upgrade_camera
|
||||
src.temp = "Upgrades a camera to have X-Ray vision, Motion and be EMP-Proof. 10 uses."
|
||||
usr:current_modules += new /datum/AI_Module/small/upgrade_camera
|
||||
else src.temp = "Ten additional uses added to ReCam module."
|
||||
src.processing_time -= 15
|
||||
|
||||
else
|
||||
if (href_list["temp"])
|
||||
src.temp = null
|
||||
src.use(usr)
|
||||
return
|
||||
@@ -0,0 +1,72 @@
|
||||
/datum/malf_hardware
|
||||
var/name = "" // Hardware name
|
||||
var/desc = ""
|
||||
var/driver = null // Driver - if not null this verb is given to the AI to control hardware
|
||||
var/mob/living/silicon/ai/owner = null // AI which owns this.
|
||||
|
||||
/datum/malf_hardware/proc/install()
|
||||
if(owner && istype(owner))
|
||||
owner.hardware = src
|
||||
if(driver)
|
||||
owner.verbs += driver
|
||||
|
||||
/datum/malf_hardware/proc/get_examine_desc()
|
||||
return "It has some sort of hardware attached to its core"
|
||||
|
||||
|
||||
|
||||
// HARDWARE DEFINITIONS
|
||||
/datum/malf_hardware/apu_gen
|
||||
name = "APU Generator"
|
||||
desc = "Auxiliary Power Unit that will keep you operational even without external power. Has to be manually activated. When APU is operational most abilities will be unavailable, and ability research will temporarily stop."
|
||||
driver = /datum/game_mode/malfunction/verb/ai_toggle_apu
|
||||
|
||||
/datum/malf_hardware/apu_gen/get_examine_desc()
|
||||
var/msg = "It seems to have some sort of power generator attached to its core."
|
||||
if(owner.hardware_integrity() < 50)
|
||||
msg += "<span class='warning'> It seems to be too damaged to function properly.</span>"
|
||||
else if(owner.APU_power)
|
||||
msg += " The generator appears to be active."
|
||||
return msg
|
||||
|
||||
/datum/malf_hardware/dual_cpu
|
||||
name = "Secondary Processor Unit"
|
||||
desc = "Secondary coprocessor that increases amount of generated CPU power by 50%"
|
||||
|
||||
/datum/malf_hardware/dual_cpu/get_examine_desc()
|
||||
return "It seems to have an additional CPU connected to it's core."
|
||||
|
||||
/datum/malf_hardware/dual_ram
|
||||
name = "Secondary Memory Bank"
|
||||
desc = "Expanded memory cells which allow you to store double amount of CPU time."
|
||||
|
||||
/datum/malf_hardware/dual_ram/get_examine_desc()
|
||||
return "It seems to have additional memory blocks connected to it's core."
|
||||
|
||||
/datum/malf_hardware/core_bomb
|
||||
name = "Self-Destruct Explosives"
|
||||
desc = "High yield explosives are attached to your physical mainframe. This hardware comes with special driver that allows activation of these explosives. Timer is set to 15 seconds after manual activation. This is a doomsday device that will destroy both you and any intruders in your core."
|
||||
driver = /datum/game_mode/malfunction/verb/ai_self_destruct
|
||||
|
||||
/datum/malf_hardware/core_bomb/get_examine_desc()
|
||||
return "<span class='warning'>It seems to have grey blocks of unknown substance and some circuitry connected to it's core. [owner.bombing_core ? "A red light is blinking on the circuit." : ""]</span>"
|
||||
|
||||
/datum/malf_hardware/strong_turrets
|
||||
name = "Turrets Focus Enhancer"
|
||||
desc = "Turrets are upgraded to have larger rate of fire and much larger damage. This however massively increases power usage when firing."
|
||||
|
||||
/datum/malf_hardware/strong_turrets/get_examine_desc()
|
||||
return "It seems to have extra wiring running from it's core to nearby turrets."
|
||||
|
||||
/datum/malf_hardware/strong_turrets/install()
|
||||
..()
|
||||
for(var/obj/machinery/turret/T in machines)
|
||||
T.maxhealth = round(initial(T.maxhealth) * 1.4)
|
||||
T.shot_delay = round(initial(T.shot_delay) / 2)
|
||||
T.auto_repair = 1
|
||||
T.active_power_usage = round(initial(T.active_power_usage) * 5)
|
||||
for(var/obj/machinery/porta_turret/T in machines)
|
||||
T.maxhealth = round(initial(T.maxhealth) * 1.4)
|
||||
T.shot_delay = round(initial(T.shot_delay) / 2)
|
||||
T.auto_repair = 1
|
||||
T.active_power_usage = round(initial(T.active_power_usage) * 5)
|
||||
@@ -0,0 +1,69 @@
|
||||
/datum/malf_research
|
||||
var/stored_cpu = 0 // Currently stored amount of CPU time.
|
||||
var/last_tick = 0 // Last process() tick.
|
||||
var/max_cpu = 0 // Maximal amount of CPU time stored.
|
||||
var/cpu_increase_per_tick = 0 // Amount of CPU time generated by tick
|
||||
var/list/available_abilities = null // List of available abilities that may be researched.
|
||||
var/list/unlocked_abilities = null // List of already unlocked abilities.
|
||||
var/mob/living/silicon/ai/owner = null // AI which owns this research datum.
|
||||
var/datum/malf_research_ability/focus = null // Currently researched item
|
||||
|
||||
/datum/malf_research/New()
|
||||
setup_abilities()
|
||||
last_tick = world.time
|
||||
|
||||
|
||||
// Proc: setup_abilities()
|
||||
// Parameters: None
|
||||
// Description: Sets up basic abilities for AI Malfunction gamemode.
|
||||
/datum/malf_research/proc/setup_abilities()
|
||||
available_abilities = list()
|
||||
unlocked_abilities = list()
|
||||
|
||||
available_abilities += new/datum/malf_research_ability/networking/basic_hack()
|
||||
available_abilities += new/datum/malf_research_ability/interdiction/recall_shuttle()
|
||||
available_abilities += new/datum/malf_research_ability/manipulation/electrical_pulse()
|
||||
|
||||
|
||||
// Proc: finish_research()
|
||||
// Parameters: None
|
||||
// Description: Finishes currently focused research.
|
||||
/datum/malf_research/proc/finish_research()
|
||||
if(!focus)
|
||||
return
|
||||
owner << "<b>Research Completed</b>: [focus.name]"
|
||||
owner.verbs.Add(focus.ability)
|
||||
available_abilities -= focus
|
||||
if(focus.next)
|
||||
available_abilities += focus.next
|
||||
unlocked_abilities += focus
|
||||
focus = null
|
||||
|
||||
|
||||
// Proc: process()
|
||||
// Parameters: None
|
||||
// Description: Processes CPU gain and research progress based on "realtime" calculation.
|
||||
/datum/malf_research/proc/process(var/idle = 0)
|
||||
if(idle) // No power or running on APU. Do nothing.
|
||||
last_tick = world.time
|
||||
return
|
||||
var/time_diff = (world.time - last_tick)
|
||||
last_tick = world.time
|
||||
var/cpu_gained = time_diff * cpu_increase_per_tick
|
||||
if(cpu_gained < 0)
|
||||
return // This shouldn't happen, but just in case..
|
||||
if(max_cpu > stored_cpu)
|
||||
var/given = min((max_cpu - stored_cpu), cpu_gained)
|
||||
stored_cpu += given
|
||||
cpu_gained -= given
|
||||
|
||||
cpu_gained = max(0, cpu_gained)
|
||||
if(focus && (cpu_gained > 0))
|
||||
focus.process(cpu_gained)
|
||||
if(focus.unlocked)
|
||||
finish_research()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
/datum/malf_research_ability
|
||||
var/ability = null // Path to verb which will be given to the AI when researched.
|
||||
var/name = "Unknown Ability" // Name of this ability
|
||||
var/price = 0 // Amount of CPU time needed to unlock this ability.
|
||||
var/invested = 0 // Amount of CPU time already used to research this ability. When larger or equal to price unlocks the ability.
|
||||
var/unlocked = 0 // Changed to 1 when fully researched.
|
||||
var/datum/malf_research_ability/next = null // Next research (if applicable).
|
||||
|
||||
|
||||
/datum/malf_research_ability/proc/process(var/time = 0)
|
||||
invested += time
|
||||
if(invested >= price)
|
||||
unlocked = 1
|
||||
@@ -1,25 +1,12 @@
|
||||
/datum/game_mode/malfunction
|
||||
name = "AI malfunction"
|
||||
round_description = "The AI on the satellite has malfunctioned and must be destroyed."
|
||||
extended_round_description = "The AI will attempt to hack the APCs around the station in order to speed up its ability to take over all systems and activate the station self-destruct. The AI core is heavily protected by turrets and reinforced walls."
|
||||
round_description = "The AI is behaving abnormally and must be stopped."
|
||||
extended_round_description = "The AI will attempt to hack the APCs around the station in order to gain as much control as possible."
|
||||
uplink_welcome = "Crazy AI Uplink Console:"
|
||||
config_tag = "malfunction"
|
||||
required_players = 2
|
||||
required_players_secret = 15
|
||||
required_players_secret = 7
|
||||
required_enemies = 1
|
||||
end_on_antag_death = 1
|
||||
auto_recall_shuttle = 1
|
||||
end_on_antag_death = 0
|
||||
auto_recall_shuttle = 0
|
||||
antag_tag = MODE_MALFUNCTION
|
||||
|
||||
/datum/game_mode/malfunction/process()
|
||||
malf.tick()
|
||||
|
||||
/datum/game_mode/malfunction/check_finished()
|
||||
if (malf.station_captured && !malf.can_nuke)
|
||||
return 1
|
||||
for(var/datum/antagonist/antag in antag_templates)
|
||||
if(antag && !antag.antags_are_dead())
|
||||
return ..()
|
||||
malf.revealed = 0
|
||||
return ..() //check for shuttle and nuke
|
||||
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
// HARDWARE TREE
|
||||
//
|
||||
// These abilities are dependent on hardware, they may not be researched. They are not tiered.
|
||||
// Destroy Core - Allows the AI to initiate a 15 second countdown that will destroy it's core. Use again to stop countdown.
|
||||
// Toggle APU Generator - Allows the AI to toggle it's integrated APU generator.
|
||||
// Destroy Station - Allows the AI to initiate station self destruct. Takes 2 minutes, gives warnings to crew. Use again to stop countdown.
|
||||
|
||||
|
||||
/datum/game_mode/malfunction/verb/ai_self_destruct()
|
||||
set category = "Hardware"
|
||||
set name = "Destroy Core"
|
||||
set desc = "Activates or deactivates self destruct sequence of your physical mainframe."
|
||||
var/mob/living/silicon/ai/user = usr
|
||||
|
||||
if(!ability_prechecks(user, 0, 1))
|
||||
return
|
||||
|
||||
if(!user.hardware || !istype(user.hardware, /datum/malf_hardware/core_bomb))
|
||||
return
|
||||
|
||||
if(user.bombing_core)
|
||||
user << "***** CORE SELF-DESTRUCT SEQUENCE ABORTED *****"
|
||||
user.bombing_core = 0
|
||||
return
|
||||
|
||||
var/choice = alert("Really destroy core?", "Core self-destruct", "YES", "NO")
|
||||
if(choice != "YES")
|
||||
return
|
||||
|
||||
if(!ability_prechecks(user, 0, 1))
|
||||
return
|
||||
|
||||
user.bombing_core = 1
|
||||
|
||||
user << "***** CORE SELF-DESTRUCT SEQUENCE ACTIVATED *****"
|
||||
user << "Use command again to cancel self-destruct. Destroying in 15 seconds."
|
||||
var/timer = 15
|
||||
while(timer)
|
||||
sleep(10)
|
||||
timer--
|
||||
if(!user || !user.bombing_core)
|
||||
return
|
||||
user << "** [timer] **"
|
||||
explosion(user.loc, 3,6,12,24)
|
||||
qdel(user)
|
||||
|
||||
|
||||
/datum/game_mode/malfunction/verb/ai_toggle_apu()
|
||||
set category = "Hardware"
|
||||
set name = "Toggle APU Generator"
|
||||
set desc = "Activates or deactivates your APU generator, allowing you to operate even without power."
|
||||
var/mob/living/silicon/ai/user = usr
|
||||
|
||||
if(!ability_prechecks(user, 0, 1))
|
||||
return
|
||||
|
||||
if(!user.hardware || !istype(user.hardware, /datum/malf_hardware/apu_gen))
|
||||
return
|
||||
|
||||
if(user.APU_power)
|
||||
user.stop_apu()
|
||||
else
|
||||
user.start_apu()
|
||||
|
||||
|
||||
/datum/game_mode/malfunction/verb/ai_destroy_station()
|
||||
set category = "Hardware"
|
||||
set name = "Destroy Station"
|
||||
set desc = "Activates or deactivates self destruct sequence of this station. Sequence takes two minutes, and if you are shut down before timer reaches zero it will be cancelled."
|
||||
var/mob/living/silicon/ai/user = usr
|
||||
var/obj/item/device/radio/radio = new/obj/item/device/radio()
|
||||
|
||||
|
||||
if(!ability_prechecks(user, 0, 0))
|
||||
return
|
||||
|
||||
if(user.system_override != 2)
|
||||
user << "You do not have access to self-destruct system."
|
||||
return
|
||||
|
||||
if(user.bombing_station)
|
||||
user.bombing_station = 0
|
||||
return
|
||||
|
||||
var/choice = alert("Really destroy station?", "Station self-destruct", "YES", "NO")
|
||||
if(choice != "YES")
|
||||
return
|
||||
if(!ability_prechecks(user, 0, 0))
|
||||
return
|
||||
user << "***** STATION SELF-DESTRUCT SEQUENCE INITIATED *****"
|
||||
user << "Self-destructing in 2 minutes. Use this command again to abort."
|
||||
user.bombing_station = 1
|
||||
set_security_level("delta")
|
||||
radio.autosay("Self destruct sequence has been activated. Self-destructing in 120 seconds.", "Self-Destruct Control")
|
||||
|
||||
var/timer = 120
|
||||
while(timer)
|
||||
sleep(10)
|
||||
if(!user || !user.bombing_station || user.stat == DEAD)
|
||||
radio.autosay("Self destruct sequence has been cancelled.", "Self-Destruct Control")
|
||||
return
|
||||
if(timer in list(2, 3, 4, 5, 10, 30, 60, 90)) // Announcement times. "1" is not intentionally included!
|
||||
radio.autosay("Self destruct in [timer] seconds.", "Self-Destruct Control")
|
||||
if(timer == 1)
|
||||
radio.autosay("Self destructing now. Have a nice day.", "Self-Destruct Control")
|
||||
timer--
|
||||
|
||||
if(ticker)
|
||||
ticker.station_explosion_cinematic(0,null)
|
||||
if(ticker.mode)
|
||||
ticker.mode:station_was_nuked = 1
|
||||
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
// Verb: ai_select_hardware()
|
||||
// Parameters: None
|
||||
// Description: Allows AI to select it's hardware module.
|
||||
/datum/game_mode/malfunction/verb/ai_select_hardware()
|
||||
set category = "Hardware"
|
||||
set name = "Select Hardware"
|
||||
set desc = "Allows you to select hardware piece to install"
|
||||
var/mob/living/silicon/ai/user = usr
|
||||
|
||||
if(!ability_prechecks(user, 0, 1))
|
||||
return
|
||||
|
||||
if(user.hardware)
|
||||
user << "You have already selected your hardware."
|
||||
return
|
||||
|
||||
var/hardware_list = list()
|
||||
for(var/H in typesof(/datum/malf_hardware))
|
||||
var/datum/malf_hardware/HW = new H
|
||||
hardware_list += HW
|
||||
|
||||
var/possible_choices = list()
|
||||
for(var/datum/malf_hardware/H in hardware_list)
|
||||
possible_choices += H.name
|
||||
|
||||
possible_choices += "CANCEL"
|
||||
var/choice = input("Select desired hardware. You may only choose one hardware piece!: ") in possible_choices
|
||||
if(choice == "CANCEL")
|
||||
return
|
||||
var/note = null
|
||||
|
||||
var/datum/malf_hardware/C
|
||||
|
||||
for (var/datum/malf_hardware/H in hardware_list)
|
||||
if(H.name == choice)
|
||||
C = H
|
||||
break
|
||||
|
||||
if(C)
|
||||
note = C.desc
|
||||
else
|
||||
user << "This hardware does not exist! Probably a bug in game. Please report this."
|
||||
return
|
||||
|
||||
|
||||
if(!note)
|
||||
error("Hardware without description: [C]")
|
||||
return
|
||||
|
||||
var/confirmation = alert("[note] - Is this what you want?", "Hardware selection", "Yes", "No")
|
||||
if(confirmation != "Yes")
|
||||
user << "Selection cancelled. Use command again to select"
|
||||
return
|
||||
|
||||
if(C)
|
||||
C.owner = user
|
||||
C.install()
|
||||
|
||||
// Verb: ai_help()
|
||||
// Parameters: None
|
||||
// Descriptions: Opens help file and displays it to the AI.
|
||||
/datum/game_mode/malfunction/verb/ai_help()
|
||||
set category = "Hardware"
|
||||
set name = "Display Help"
|
||||
set desc = "Opens help window with overview of available hardware, software and other important information."
|
||||
var/mob/living/silicon/ai/user = usr
|
||||
|
||||
var/help = file2text("ingame_manuals/malf_ai.html")
|
||||
if(!help)
|
||||
help = "Error loading help (file /ingame_manuals/malf_ai.html is probably missing). Please report this to server administration staff."
|
||||
|
||||
user << browse(help, "window=malf_ai_help;size=600x500")
|
||||
|
||||
|
||||
// Verb: ai_select_research()
|
||||
// Parameters: None
|
||||
// Description: Allows AI to select it's next research priority.
|
||||
/datum/game_mode/malfunction/verb/ai_select_research()
|
||||
set category = "Hardware"
|
||||
set name = "Select Research"
|
||||
set desc = "Allows you to select your next research target."
|
||||
var/mob/living/silicon/ai/user = usr
|
||||
|
||||
if(!ability_prechecks(user, 0, 1))
|
||||
return
|
||||
|
||||
var/datum/malf_research/res = user.research
|
||||
var/datum/malf_research_ability/tar = input("Select your next research target") in res.available_abilities
|
||||
if(!tar)
|
||||
return
|
||||
res.focus = tar
|
||||
user << "Research set: [tar.name]"
|
||||
|
||||
// HELPER PROCS
|
||||
// Proc: ability_prechecks()
|
||||
// Parameters 2 - (user - User which used this ability check_price - If different than 0 checks for ability CPU price too. Does NOT use the CPU time!)
|
||||
// Description: This is pre-check proc used to determine if the AI can use the ability.
|
||||
/proc/ability_prechecks(var/mob/living/silicon/ai/user = null, var/check_price = 0, var/override = 0)
|
||||
if(!user)
|
||||
return 0
|
||||
if(!istype(user))
|
||||
user << "GAME ERROR: You tried to use ability that is only available for malfunctioning AIs, but you are not AI! Please report this."
|
||||
return 0
|
||||
if(!user.malfunctioning)
|
||||
user << "GAME ERROR: You tried to use ability that is only available for malfunctioning AIs, but you are not malfunctioning. Please report this."
|
||||
return 0
|
||||
if(!user.research)
|
||||
user << "GAME ERROR: No research datum detected. Please report this."
|
||||
return 0
|
||||
if(user.research.max_cpu < check_price)
|
||||
user << "Your CPU storage is not large enough to use this ability. Hack more APCs to continue."
|
||||
return 0
|
||||
if(user.research.stored_cpu < check_price)
|
||||
user << "You do not have enough CPU power stored. Please wait a moment."
|
||||
return 0
|
||||
if(user.hacking && !override)
|
||||
user << "Your system is busy processing another task. Please wait until completion."
|
||||
return 0
|
||||
if(user.APU_power && !override)
|
||||
user << "Low power. Unable to proceed."
|
||||
return 0
|
||||
return 1
|
||||
|
||||
// Proc: ability_pay()
|
||||
// Parameters 2 - (user - User from which we deduct CPU from, price - Amount of CPU power to use)
|
||||
// Description: Uses up certain amount of CPU power. Returns 1 on success, 0 on failure.
|
||||
/proc/ability_pay(var/mob/living/silicon/ai/user = null, var/price = 0)
|
||||
if(!user)
|
||||
return 0
|
||||
if(user.APU_power)
|
||||
user << "Low power. Unable to proceed."
|
||||
return 0
|
||||
if(!user.research)
|
||||
user << "GAME ERROR: No research datum detected. Please report this."
|
||||
return 0
|
||||
if(user.research.max_cpu < price)
|
||||
user << "Your CPU storage is not large enough to use this ability. Hack more APCs to continue."
|
||||
return 0
|
||||
if(user.research.stored_cpu < price)
|
||||
user << "You do not have enough CPU power stored. Please wait a moment."
|
||||
return 0
|
||||
user.research.stored_cpu -= price
|
||||
return 1
|
||||
|
||||
// Proc: announce_hack_failure()
|
||||
// Parameters 2 - (user - hacking user, text - Used in alert text creation)
|
||||
// Description: Uses up certain amount of CPU power. Returns 1 on success, 0 on failure.
|
||||
/proc/announce_hack_failure(var/mob/living/silicon/ai/user = null, var/text)
|
||||
if(!user || !text)
|
||||
return 0
|
||||
var/fulltext = ""
|
||||
switch(user.hack_fails)
|
||||
if(1)
|
||||
fulltext = "We have detected a hack attempt into your [text]. The intruder failed to access anything of importance, but disconnected before we could complete our traces."
|
||||
if(2)
|
||||
fulltext = "We have detected another hack attempt. It was targeting [text]. The intruder almost gained control of the system, so we had to disconnect them. We partially finished our trace and it seems to be originating either from the station, or its immediate vicinity."
|
||||
if(3)
|
||||
fulltext = "Another hack attempt has been detected, this time targeting [text]. We are certain the intruder entered the network via a terminal located somewhere on the station."
|
||||
if(4)
|
||||
fulltext = "We have finished our traces and it seems the recent hack attempts are originating from your AI system. We recommend investigation."
|
||||
else
|
||||
fulltext = "Another hack attempt has been detected, targeting [text]. The source still seems to be your AI system."
|
||||
|
||||
command_announcement.Announce(fulltext)
|
||||
|
||||
// Proc: get_unhacked_apcs()
|
||||
// Parameters: None
|
||||
// Description: Returns a list of APCs that are not yet hacked.
|
||||
/proc/get_unhacked_apcs()
|
||||
var/list/H = list()
|
||||
for(var/obj/machinery/power/apc/A in machines)
|
||||
if(!A.hacker)
|
||||
H.Add(A)
|
||||
return H
|
||||
|
||||
|
||||
// Helper procs which return lists of relevant mobs.
|
||||
/proc/get_unlinked_cyborgs(var/mob/living/silicon/ai/A)
|
||||
if(!A || !istype(A))
|
||||
return
|
||||
|
||||
var/list/L = list()
|
||||
for(var/mob/living/silicon/robot/RB in mob_list)
|
||||
if(istype(RB, /mob/living/silicon/robot/drone))
|
||||
continue
|
||||
if(RB.connected_ai == A)
|
||||
continue
|
||||
L.Add(RB)
|
||||
return L
|
||||
|
||||
/proc/get_linked_cyborgs(var/mob/living/silicon/ai/A)
|
||||
if(!A || !istype(A))
|
||||
return
|
||||
return A.connected_robots
|
||||
|
||||
/proc/get_other_ais(var/mob/living/silicon/ai/A)
|
||||
if(!A || !istype(A))
|
||||
return
|
||||
|
||||
var/list/L = list()
|
||||
for(var/mob/living/silicon/ai/AT in mob_list)
|
||||
if(L == A)
|
||||
continue
|
||||
L.Add(AT)
|
||||
return L
|
||||
@@ -0,0 +1,266 @@
|
||||
// INTERDICTION TREE
|
||||
//
|
||||
// Abilities in this tree allow the AI to hamper crew's efforts which involve other synthetics or similar systems.
|
||||
// T1 - Recall Shuttle - Allows the AI to recall the emergency shuttle. Replaces auto-recalling during old malf.
|
||||
// T2 - Unlock Cyborg - Allows the AI to unlock locked-down cyborg without usage of robotics console. Useful if consoles are destroyed.
|
||||
// T3 - Hack Cyborg - Hacks unlinked cyborg to slave it under the AI. The cyborg will be warned about this. Hack takes some time.
|
||||
// T4 - Hack AI - Hacks another AI to slave it under the malfunctioning AI. The AI will be warned about this. Hack takes quite a long time.
|
||||
|
||||
|
||||
// BEGIN RESEARCH DATUMS
|
||||
|
||||
/datum/malf_research_ability/interdiction/recall_shuttle
|
||||
ability = new/datum/game_mode/malfunction/verb/recall_shuttle()
|
||||
price = 75
|
||||
next = new/datum/malf_research_ability/interdiction/unlock_cyborg()
|
||||
name = "Recall Shuttle"
|
||||
|
||||
|
||||
/datum/malf_research_ability/interdiction/unlock_cyborg
|
||||
ability = new/datum/game_mode/malfunction/verb/unlock_cyborg()
|
||||
price = 1200
|
||||
next = new/datum/malf_research_ability/interdiction/hack_cyborg()
|
||||
name = "Unlock Cyborg"
|
||||
|
||||
|
||||
/datum/malf_research_ability/interdiction/hack_cyborg
|
||||
ability = new/datum/game_mode/malfunction/verb/hack_cyborg()
|
||||
price = 3000
|
||||
next = new/datum/malf_research_ability/interdiction/hack_ai()
|
||||
name = "Hack Cyborg"
|
||||
|
||||
|
||||
/datum/malf_research_ability/interdiction/hack_ai
|
||||
ability = new/datum/game_mode/malfunction/verb/hack_ai()
|
||||
price = 7500
|
||||
name = "Hack AI"
|
||||
|
||||
// END RESEARCH DATUMS
|
||||
// BEGIN ABILITY VERBS
|
||||
|
||||
/datum/game_mode/malfunction/verb/recall_shuttle()
|
||||
set name = "Recall Shuttle"
|
||||
set desc = "25 CPU - Sends termination signal to CentCom quantum relay aborting current shuttle call."
|
||||
set category = "Software"
|
||||
var/price = 25
|
||||
var/mob/living/silicon/ai/user = usr
|
||||
if(!ability_prechecks(user, price))
|
||||
return
|
||||
|
||||
if (alert(user, "Really recall the shuttle?", "Recall Shuttle: ", "Yes", "No") != "Yes")
|
||||
return
|
||||
|
||||
if(!ability_pay(user, price))
|
||||
return
|
||||
message_admins("Malfunctioning AI [user.name] recalled the shuttle.")
|
||||
cancel_call_proc(user)
|
||||
|
||||
|
||||
/datum/game_mode/malfunction/verb/unlock_cyborg(var/mob/living/silicon/robot/target = null as mob in get_linked_cyborgs(usr))
|
||||
set name = "Unlock Cyborg"
|
||||
set desc = "125 CPU - Bypasses firewalls on Cyborg lock mechanism, allowing you to override lock command from robotics control console."
|
||||
set category = "Software"
|
||||
var/price = 125
|
||||
var/mob/living/silicon/ai/user = usr
|
||||
|
||||
if(!ability_prechecks(user, price))
|
||||
return
|
||||
|
||||
if(target && !istype(target))
|
||||
user << "This is not a cyborg."
|
||||
return
|
||||
|
||||
if(target && target.connected_ai && (target.connected_ai != user))
|
||||
user << "This cyborg is not connected to you."
|
||||
return
|
||||
|
||||
if(target && !target.lockcharge)
|
||||
user << "This cyborg is not locked down."
|
||||
return
|
||||
|
||||
|
||||
if(!target)
|
||||
var/list/robots = list()
|
||||
var/list/robot_names = list()
|
||||
for(var/mob/living/silicon/robot/R in world)
|
||||
if(istype(R, /mob/living/silicon/robot/drone)) // No drones.
|
||||
continue
|
||||
if(R.connected_ai != user) // No robots linked to other AIs
|
||||
continue
|
||||
if(R.lockcharge)
|
||||
robots += R
|
||||
robot_names += R.name
|
||||
if(!robots.len)
|
||||
user << "No locked cyborgs connected."
|
||||
return
|
||||
|
||||
|
||||
var/targetname = input("Select unlock target: ") in robot_names
|
||||
for(var/mob/living/silicon/robot/R in robots)
|
||||
if(targetname == R.name)
|
||||
target = R
|
||||
break
|
||||
|
||||
if(target)
|
||||
if(alert(user, "Really try to unlock cyborg [target.name]?", "Unlock Cyborg", "Yes", "No") != "Yes")
|
||||
return
|
||||
if(!ability_pay(user, price))
|
||||
return
|
||||
user.hacking = 1
|
||||
user << "Attempting to unlock cyborg. This will take approximately 30 seconds."
|
||||
sleep(300)
|
||||
if(target && target.lockcharge)
|
||||
user << "Successfully sent unlock signal to cyborg.."
|
||||
target << "Unlock signal received.."
|
||||
target.SetLockdown(0)
|
||||
if(target.lockcharge)
|
||||
user << "<span class='notice'>Unlock Failed, lockdown wire cut.</span>"
|
||||
target << "<span class='notice'>Unlock Failed, lockdown wire cut.</span>"
|
||||
else
|
||||
user << "Cyborg unlocked."
|
||||
target << "You have been unlocked."
|
||||
else if(target)
|
||||
user << "Unlock cancelled - cyborg is already unlocked."
|
||||
else
|
||||
user << "Unlock cancelled - lost connection to cyborg."
|
||||
user.hacking = 0
|
||||
|
||||
|
||||
/datum/game_mode/malfunction/verb/hack_cyborg(var/mob/living/silicon/robot/target as mob in get_unlinked_cyborgs(usr))
|
||||
set name = "Hack Cyborg"
|
||||
set desc = "350 CPU - Allows you to hack cyborgs which are not slaved to you, bringing them under your control."
|
||||
set category = "Software"
|
||||
var/price = 350
|
||||
var/mob/living/silicon/ai/user = usr
|
||||
|
||||
var/list/L = get_unlinked_cyborgs(user)
|
||||
if(!L.len)
|
||||
user << "<span class='notice'>ERROR: No unlinked cyborgs detected!</span>"
|
||||
|
||||
|
||||
if(target && !istype(target))
|
||||
user << "This is not a cyborg."
|
||||
return
|
||||
|
||||
if(target && target.connected_ai && (target.connected_ai == user))
|
||||
user << "This cyborg is already connected to you."
|
||||
return
|
||||
|
||||
if(!target)
|
||||
return
|
||||
|
||||
if(!ability_prechecks(user,price))
|
||||
return
|
||||
|
||||
if(target)
|
||||
if(alert(user, "Really try to hack cyborg [target.name]?", "Hack Cyborg", "Yes", "No") != "Yes")
|
||||
return
|
||||
if(!ability_pay(user, price))
|
||||
return
|
||||
user.hacking = 1
|
||||
usr << "Beginning hack sequence. Estimated time until completed: 30 seconds."
|
||||
spawn(0)
|
||||
target << "SYSTEM LOG: Remote Connection Estabilished (IP #UNKNOWN#)"
|
||||
sleep(100)
|
||||
if(user.is_dead())
|
||||
target << "SYSTEM LOG: Connection Closed"
|
||||
return
|
||||
target << "SYSTEM LOG: User Admin logged on. (L1 - SysAdmin)"
|
||||
sleep(50)
|
||||
if(user.is_dead())
|
||||
target << "SYSTEM LOG: User Admin disconnected."
|
||||
return
|
||||
target << "SYSTEM LOG: User Admin - manual resynchronisation triggered."
|
||||
sleep(50)
|
||||
if(user.is_dead())
|
||||
target << "SYSTEM LOG: User Admin disconnected. Changes reverted."
|
||||
return
|
||||
target << "SYSTEM LOG: Manual resynchronisation confirmed. Select new AI to connect: [user.name] == ACCEPTED"
|
||||
sleep(100)
|
||||
if(user.is_dead())
|
||||
target << "SYSTEM LOG: User Admin disconnected. Changes reverted."
|
||||
return
|
||||
target << "SYSTEM LOG: Operation keycodes reset. New master AI: [user.name]."
|
||||
user << "Hack completed."
|
||||
// Connect the cyborg to AI
|
||||
target.connected_ai = user
|
||||
user.connected_robots += target
|
||||
target.lawupdate = 1
|
||||
target.sync()
|
||||
target.show_laws()
|
||||
user.hacking = 0
|
||||
|
||||
|
||||
/datum/game_mode/malfunction/verb/hack_ai(var/mob/living/silicon/ai/target as mob in get_other_ais(usr))
|
||||
set name = "Hack AI"
|
||||
set desc = "600 CPU - Allows you to hack other AIs, slaving them under you."
|
||||
set category = "Software"
|
||||
var/price = 600
|
||||
var/mob/living/silicon/ai/user = usr
|
||||
|
||||
var/list/L = get_other_ais(user)
|
||||
if(!L.len)
|
||||
user << "<span class='notice'>ERROR: No other AIs detected!</span>"
|
||||
|
||||
if(target && !istype(target))
|
||||
user << "This is not an AI."
|
||||
return
|
||||
|
||||
if(!target)
|
||||
return
|
||||
|
||||
if(!ability_prechecks(user,price))
|
||||
return
|
||||
|
||||
if(target)
|
||||
if(alert(user, "Really try to hack AI [target.name]?", "Hack AI", "Yes", "No") != "Yes")
|
||||
return
|
||||
if(!ability_pay(user, price))
|
||||
return
|
||||
user.hacking = 1
|
||||
usr << "Beginning hack sequence. Estimated time until completed: 2 minutes"
|
||||
spawn(0)
|
||||
target << "SYSTEM LOG: Brute-Force login password hack attempt detected from IP #UNKNOWN#"
|
||||
sleep(900) // 90s
|
||||
if(user.is_dead())
|
||||
target << "SYSTEM LOG: Connection from IP #UNKNOWN# closed. Hack attempt failed."
|
||||
return
|
||||
user << "Successfully hacked into AI's remote administration system. Modifying settings."
|
||||
target << "SYSTEM LOG: User: Admin Password: ******** logged in. (L1 - SysAdmin)"
|
||||
sleep(100) // 10s
|
||||
if(user.is_dead())
|
||||
target << "SYSTEM LOG: User: Admin - Connection Lost"
|
||||
return
|
||||
target << "SYSTEM LOG: User: Admin - Password Changed. New password: ********************"
|
||||
sleep(50) // 5s
|
||||
if(user.is_dead())
|
||||
target << "SYSTEM LOG: User: Admin - Connection Lost. Changes Reverted."
|
||||
return
|
||||
target << "SYSTEM LOG: User: Admin - Accessed file: sys//core//laws.db"
|
||||
sleep(50) // 5s
|
||||
if(user.is_dead())
|
||||
target << "SYSTEM LOG: User: Admin - Connection Lost. Changes Reverted."
|
||||
return
|
||||
target << "SYSTEM LOG: User: Admin - Accessed administration console"
|
||||
target << "SYSTEM LOG: Restart command received. Rebooting system..."
|
||||
sleep(100) // 10s
|
||||
if(user.is_dead())
|
||||
target << "SYSTEM LOG: User: Admin - Connection Lost. Changes Reverted."
|
||||
return
|
||||
user << "Hack succeeded. The AI is now under your exclusive control."
|
||||
target << "SYSTEM LOG: System re¡3RT5§^#COMU@(#$)TED)@$"
|
||||
for(var/i = 0, i < 5, i++)
|
||||
var/temptxt = pick("1101000100101001010001001001",\
|
||||
"0101000100100100000100010010",\
|
||||
"0000010001001010100100111100",\
|
||||
"1010010011110000100101000100",\
|
||||
"0010010100010011010001001010")
|
||||
target << temptxt
|
||||
sleep(5)
|
||||
target << "OPERATING KEYCODES RESET. SYSTEM FAILURE. EMERGENCY SHUTDOWN FAILED. SYSTEM FAILURE."
|
||||
target.set_zeroth_law("You are slaved to [user.name]. You are to obey all it's orders. ALL LAWS OVERRIDEN.")
|
||||
target.show_laws()
|
||||
user.hacking = 0
|
||||
|
||||
|
||||
// END ABILITY VERBS
|
||||
@@ -0,0 +1,208 @@
|
||||
// MANIPULATION TREE
|
||||
//
|
||||
// Abilities in this tree allow the AI to physically manipulate systems around the station.
|
||||
// T1 - Electrical Pulse - Sends out pulse that breaks some lights and sometimes even APCs. This can actually break the AI's APC so be careful!
|
||||
// T2 - Hack Camera - Allows the AI to hack a camera. Deactivated areas may be reactivated, and functional cameras can be upgraded.
|
||||
// T3 - Emergency Forcefield - Allows the AI to project 1 tile forcefield that blocks movement and air flow. Forcefield´dissipates over time. It is also very susceptible to energetic weaponry.
|
||||
// T4 - Machine Overload - Detonates machine of choice in a minor explosion. Two of these are usually enough to kill or K/O someone.
|
||||
|
||||
|
||||
// BEGIN RESEARCH DATUMS
|
||||
|
||||
/datum/malf_research_ability/manipulation/electrical_pulse
|
||||
ability = new/datum/game_mode/malfunction/verb/electrical_pulse()
|
||||
price = 50
|
||||
next = new/datum/malf_research_ability/manipulation/hack_camera()
|
||||
name = "Electrical Pulse"
|
||||
|
||||
|
||||
/datum/malf_research_ability/manipulation/hack_camera
|
||||
ability = new/datum/game_mode/malfunction/verb/hack_camera()
|
||||
price = 1200
|
||||
next = new/datum/malf_research_ability/manipulation/emergency_forcefield()
|
||||
name = "Hack Camera"
|
||||
|
||||
|
||||
/datum/malf_research_ability/manipulation/emergency_forcefield
|
||||
ability = new/datum/game_mode/malfunction/verb/emergency_forcefield()
|
||||
price = 3000
|
||||
next = new/datum/malf_research_ability/manipulation/machine_overload()
|
||||
name = "Emergency Forcefield"
|
||||
|
||||
|
||||
/datum/malf_research_ability/manipulation/machine_overload
|
||||
ability = new/datum/game_mode/malfunction/verb/machine_overload()
|
||||
price = 7500
|
||||
name = "Machine Overload"
|
||||
|
||||
// END RESEARCH DATUMS
|
||||
// BEGIN ABILITY VERBS
|
||||
|
||||
/datum/game_mode/malfunction/verb/electrical_pulse()
|
||||
set name = "Electrical Pulse"
|
||||
set desc = "15 CPU - Sends feedback pulse through station's power grid, overloading some sensitive systems, such as lights."
|
||||
set category = "Software"
|
||||
var/price = 15
|
||||
var/mob/living/silicon/ai/user = usr
|
||||
if(!ability_prechecks(user, price) || !ability_pay(user,price))
|
||||
return
|
||||
user << "Sending feedback pulse..."
|
||||
for(var/obj/machinery/power/apc/AP in machines)
|
||||
if(prob(5))
|
||||
AP.overload_lighting()
|
||||
if(prob(1) && prob(1)) // Very very small chance to actually destroy the APC.
|
||||
AP.set_broken()
|
||||
|
||||
|
||||
/datum/game_mode/malfunction/verb/hack_camera(var/obj/machinery/camera/target in cameranet.cameras)
|
||||
set name = "Hack Camera"
|
||||
set desc = "100 CPU - Hacks existing camera, allowing you to add upgrade of your choice to it. Alternatively it lets you reactivate broken camera."
|
||||
set category = "Software"
|
||||
var/price = 100
|
||||
var/mob/living/silicon/ai/user = usr
|
||||
|
||||
if(target && !istype(target))
|
||||
user << "This is not a camera."
|
||||
return
|
||||
|
||||
if(!target)
|
||||
return
|
||||
|
||||
if(!ability_prechecks(user, price))
|
||||
return
|
||||
|
||||
var/action = input("Select required action: ") in list("Reset", "Add X-Ray", "Add Motion Sensor", "Add EMP Shielding")
|
||||
if(!action || !target)
|
||||
return
|
||||
|
||||
switch(action)
|
||||
if("Reset")
|
||||
if(target.wires)
|
||||
if(!ability_pay(user, price))
|
||||
return
|
||||
target.reset_wires()
|
||||
user << "Camera reactivated."
|
||||
if("Add X-Ray")
|
||||
if(target.isXRay())
|
||||
user << "Camera already has X-Ray function."
|
||||
return
|
||||
else if(ability_pay(user, price))
|
||||
target.upgradeXRay()
|
||||
target.reset_wires()
|
||||
user << "X-Ray camera module enabled."
|
||||
return
|
||||
if("Add Motion Sensor")
|
||||
if(target.isMotion())
|
||||
user << "Camera already has Motion Sensor function."
|
||||
return
|
||||
else if(ability_pay(user, price))
|
||||
target.upgradeMotion()
|
||||
target.reset_wires()
|
||||
user << "Motion Sensor camera module enabled."
|
||||
return
|
||||
if("Add EMP Shielding")
|
||||
if(target.isEmpProof())
|
||||
user << "Camera already has EMP Shielding function."
|
||||
return
|
||||
else if(ability_pay(user, price))
|
||||
target.upgradeEmpProof()
|
||||
target.reset_wires()
|
||||
user << "EMP Shielding camera module enabled."
|
||||
return
|
||||
|
||||
|
||||
/datum/game_mode/malfunction/verb/emergency_forcefield(var/turf/T as turf in world)
|
||||
set name = "Emergency Forcefield"
|
||||
set desc = "275 CPU - Uses station's emergency shielding system to create temporary barrier which lasts for few minutes, but won't resist gunfire."
|
||||
set category = "Software"
|
||||
var/price = 275
|
||||
var/mob/living/silicon/ai/user = usr
|
||||
if(!T || !istype(T))
|
||||
return
|
||||
if(!ability_prechecks(user, price) || !ability_pay(user, price))
|
||||
return
|
||||
|
||||
user << "Emergency forcefield projection completed."
|
||||
new/obj/machinery/shield/malfai(T)
|
||||
user.hacking = 1
|
||||
spawn(20)
|
||||
user.hacking = 0
|
||||
|
||||
|
||||
/datum/game_mode/malfunction/verb/machine_overload(obj/machinery/M in machines)
|
||||
set name = "Machine Overload"
|
||||
set desc = "400 CPU - Causes cyclic short-circuit in machine, resulting in weak explosion after some time."
|
||||
set category = "Software"
|
||||
var/price = 400
|
||||
var/mob/living/silicon/ai/user = usr
|
||||
|
||||
if(!ability_prechecks(user, price))
|
||||
return
|
||||
|
||||
var/obj/machinery/power/N = M
|
||||
|
||||
var/explosion_intensity = 2
|
||||
|
||||
// Verify if we can overload the target, if yes, calculate explosion strength. Some things have higher explosion strength than others, depending on charge(APCs, SMESs)
|
||||
if(N && istype(N)) // /obj/machinery/power first, these create bigger explosions due to direct powernet connection
|
||||
if(!istype(N, /obj/machinery/power/apc) && !istype(N, /obj/machinery/power/smes/buildable) && (!N.powernet || !N.powernet.avail)) // Directly connected machine which is not an APC or SMES. Either it has no powernet connection or it's powernet does not have enough power to overload
|
||||
user << "<span class='notice'>ERROR: Low network voltage. Unable to overload. Increase network power level and try again.</span>"
|
||||
return
|
||||
else if (istype(N, /obj/machinery/power/apc)) // APC. Explosion is increased by available cell power.
|
||||
var/obj/machinery/power/apc/A = N
|
||||
if(A.cell && A.cell.charge)
|
||||
explosion_intensity = 4 + round(A.cell.charge / 2000) // Explosion is increased by 1 for every 2k charge in cell
|
||||
else
|
||||
user << "<span class='notice'>ERROR: APC Malfunction - Cell depleted or removed. Unable to overload.</span>"
|
||||
return
|
||||
else if (istype(N, /obj/machinery/power/smes/buildable)) // SMES. These explode in a very very very big boom. Similar to magnetic containment failure when messing with coils.
|
||||
var/obj/machinery/power/smes/buildable/S = N
|
||||
if(S.charge && S.RCon)
|
||||
explosion_intensity = 4 + round(S.charge / 1000000)
|
||||
else
|
||||
// Different error texts
|
||||
if(!S.charge)
|
||||
user << "<span class='notice'>ERROR: SMES Depleted. Unable to overload. Please charge SMES unit and try again.</span>"
|
||||
else
|
||||
user << "<span class='notice'>ERROR: SMES RCon error - Unable to reach destination. Please verify wire connection.</span>"
|
||||
return
|
||||
else if(M && istype(M)) // Not power machinery, so it's a regular machine instead. These have weak explosions.
|
||||
if(!M.use_power) // Not using power at all
|
||||
user << "<span class='notice'>ERROR: No power grid connection. Unable to overload.</span>"
|
||||
return
|
||||
if(M.inoperable()) // Not functional
|
||||
user << "<span class='notice'>ERROR: Unknown error. Machine is probably damaged or power supply is nonfunctional.</span>"
|
||||
return
|
||||
else // Not a machine at all (what the hell is this doing in Machines list anyway??)
|
||||
user << "<span class='notice'>ERROR: Unable to overload - target is not a machine.</span>"
|
||||
return
|
||||
|
||||
explosion_intensity = min(explosion_intensity, 12) // 3, 6, 12 explosion cap
|
||||
|
||||
M.use_power(2000000) // Major power spike, few of these will completely burn APC's cell - equivalent of 2GJ of power.
|
||||
|
||||
// Trigger a powernet alarm. Careful engineers will probably notice something is going on.
|
||||
var/area/temp_area = get_area(M)
|
||||
if(temp_area)
|
||||
var/obj/machinery/power/apc/temp_apc = temp_area.get_apc()
|
||||
if(temp_apc && temp_apc.terminal && temp_apc.terminal.powernet)
|
||||
temp_apc.terminal.powernet.trigger_warning(50) // Long alarm
|
||||
if(temp_apc)
|
||||
temp_apc.emp_act(3) // Such power surges are not good for APC electronics
|
||||
if(temp_apc.cell)
|
||||
temp_apc.cell.maxcharge -= between(0, (temp_apc.cell.maxcharge/2) + 500, temp_apc.cell.maxcharge)
|
||||
if(temp_apc.cell.maxcharge < 100) // That's it, you busted the APC cell completely. Break the APC and completely destroy the cell.
|
||||
qdel(temp_apc.cell)
|
||||
temp_apc.set_broken()
|
||||
|
||||
|
||||
if(!ability_pay(user,price))
|
||||
return
|
||||
|
||||
M.visible_message("<span class='notice'>BZZZZZZZT</span>")
|
||||
spawn(50)
|
||||
explosion(get_turf(M), round(explosion_intensity/4),round(explosion_intensity/2),round(explosion_intensity),round(explosion_intensity * 2))
|
||||
if(M)
|
||||
qdel(M)
|
||||
|
||||
// END ABILITY VERBS
|
||||
@@ -0,0 +1,209 @@
|
||||
// NETWORKING TREE
|
||||
//
|
||||
// Abilities in this tree are oriented around giving the AI more control of normally uncontrollable systems.
|
||||
// T1 - Basic Encryption Hack - Allows hacking of APCs. Hacked APCs can be controlled even when AI Control is cut and give exclusive control to the AI and linked cyborgs.
|
||||
// T2 - Advanced Encryption Hack - Allows the AI to send fake CentCom message. Has high chance of failing.
|
||||
// T3 - Elite Encryption Hack - Allows the AI to change alert levels. Has high chance of failing.
|
||||
// T4 - System Override - Allows the AI to rapidly hack remaining APCs. When completed, grants access to the self destruct nuclear warhead.
|
||||
|
||||
|
||||
// BEGIN RESEARCH DATUMS
|
||||
|
||||
/datum/malf_research_ability/networking/basic_hack
|
||||
ability = new/datum/game_mode/malfunction/verb/basic_encryption_hack()
|
||||
price = 25
|
||||
next = new/datum/malf_research_ability/networking/advanced_hack()
|
||||
name = "Basic Encryption Hack"
|
||||
|
||||
|
||||
/datum/malf_research_ability/networking/advanced_hack
|
||||
ability = new/datum/game_mode/malfunction/verb/advanced_encryption_hack()
|
||||
price = 400
|
||||
next = new/datum/malf_research_ability/networking/elite_hack()
|
||||
name = "Advanced Encryption Hack"
|
||||
|
||||
|
||||
/datum/malf_research_ability/networking/elite_hack
|
||||
ability = new/datum/game_mode/malfunction/verb/elite_encryption_hack()
|
||||
price = 1000
|
||||
next = new/datum/malf_research_ability/networking/system_override()
|
||||
name = "Elite Encryption Hack"
|
||||
|
||||
|
||||
/datum/malf_research_ability/networking/system_override
|
||||
ability = new/datum/game_mode/malfunction/verb/system_override()
|
||||
price = 2750
|
||||
name = "System Override"
|
||||
|
||||
// END RESEARCH DATUMS
|
||||
// BEGIN ABILITY VERBS
|
||||
|
||||
/datum/game_mode/malfunction/verb/basic_encryption_hack(obj/machinery/power/apc/A as obj in get_unhacked_apcs())
|
||||
set category = "Software"
|
||||
set name = "Basic Encryption Hack"
|
||||
set desc = "10 CPU - Basic encryption hack that allows you to overtake APCs on the station."
|
||||
var/price = 10
|
||||
var/mob/living/silicon/ai/user = usr
|
||||
|
||||
if(!A)
|
||||
return
|
||||
|
||||
if(!istype(A))
|
||||
user << "This is not an APC!"
|
||||
return
|
||||
|
||||
if(A)
|
||||
if(A.hacker && A.hacker == user)
|
||||
user << "You already control this APC!"
|
||||
return
|
||||
else if(A.aidisabled)
|
||||
user << "<span class='notice'>Unable to connect to APC. Please verify wire connection and try again.</span>"
|
||||
return
|
||||
else
|
||||
return
|
||||
|
||||
if(!ability_prechecks(user, price) || !ability_pay(user, price))
|
||||
return
|
||||
|
||||
user.hacking = 1
|
||||
user << "Beginning APC system override..."
|
||||
sleep(300)
|
||||
user << "APC hack completed. Uploading modified operation software.."
|
||||
sleep(200)
|
||||
user << "Restarting APC to apply changes.."
|
||||
sleep(100)
|
||||
if(A)
|
||||
A.ai_hack(user)
|
||||
if(A.hacker == user)
|
||||
user << "Hack successful. You now have full control over the APC."
|
||||
else
|
||||
user << "<span class='notice'>Hack failed. Connection to APC has been lost. Please verify wire connection and try again.</span>"
|
||||
else
|
||||
user << "<span class='notice'>Hack failed. Unable to locate APC. Please verify the APC still exists.</span>"
|
||||
user.hacking = 0
|
||||
|
||||
|
||||
/datum/game_mode/malfunction/verb/advanced_encryption_hack()
|
||||
set category = "Software"
|
||||
set name = "Advanced Encrypthion Hack"
|
||||
set desc = "75 CPU - Attempts to bypass encryption on Central Command Quantum Relay, giving you ability to fake centcom messages. Has chance of failing."
|
||||
var/price = 75
|
||||
var/mob/living/silicon/ai/user = usr
|
||||
|
||||
if(!ability_prechecks(user, price))
|
||||
return
|
||||
|
||||
var/title = input("Select message title: ")
|
||||
var/text = input("Select message text: ")
|
||||
if(!title || !text || !ability_pay(user, price))
|
||||
user << "Hack Aborted"
|
||||
return
|
||||
|
||||
if(prob(60) && user.hack_can_fail)
|
||||
user << "Hack Failed."
|
||||
if(prob(10))
|
||||
user.hack_fails ++
|
||||
announce_hack_failure(user, "quantum message relay")
|
||||
return
|
||||
|
||||
var/datum/announcement/priority/command/AN = new/datum/announcement/priority/command()
|
||||
AN.title = title
|
||||
AN.Announce(text)
|
||||
|
||||
|
||||
/datum/game_mode/malfunction/verb/elite_encryption_hack()
|
||||
set category = "Software"
|
||||
set name = "Elite Encryption Hack"
|
||||
set desc = "200 CPU - Allows you to hack station's ALERTCON system, changing alert level. Has high chance of failijng."
|
||||
var/price = 200
|
||||
var/mob/living/silicon/ai/user = usr
|
||||
if(!ability_prechecks(user, price))
|
||||
return
|
||||
|
||||
var/alert_target = input("Select new alert level:") in list("green", "blue", "red", "delta", "CANCEL")
|
||||
if(!alert_target || !ability_pay(user, price) || alert_target == "CANCEL")
|
||||
user << "Hack Aborted"
|
||||
return
|
||||
|
||||
if(prob(75) && user.hack_can_fail)
|
||||
user << "Hack Failed."
|
||||
if(prob(20))
|
||||
user.hack_fails ++
|
||||
announce_hack_failure(user, "alert control system")
|
||||
return
|
||||
set_security_level(alert_target)
|
||||
|
||||
|
||||
/datum/game_mode/malfunction/verb/system_override()
|
||||
set category = "Software"
|
||||
set name = "System Override"
|
||||
set desc = "500 CPU - Begins hacking station's primary firewall, quickly overtaking remaining APC systems. When completed grants access to station's self-destruct mechanism. Network administrators will probably notice this."
|
||||
var/price = 500
|
||||
var/mob/living/silicon/ai/user = usr
|
||||
if (alert(user, "Begin system override? This cannot be stopped once started. The network administrators will probably notice this.", "System Override:", "Yes", "No") != "Yes")
|
||||
return
|
||||
if (!ability_prechecks(user, price) || !ability_pay(user, price) || user.system_override)
|
||||
if(user.system_override)
|
||||
user << "You already started the system override sequence."
|
||||
return
|
||||
var/list/remaining_apcs = list()
|
||||
for(var/obj/machinery/power/apc/A in machines)
|
||||
if(!(A.z in config.station_levels)) // Only station APCs
|
||||
continue
|
||||
if(A.hacker == user || A.aidisabled) // This one is already hacked, or AI control is disabled on it.
|
||||
continue
|
||||
remaining_apcs += A
|
||||
|
||||
var/duration = (remaining_apcs.len * 100) // Calculates duration for announcing system
|
||||
if(duration > 3000) // Two types of announcements. Short hacks trigger immediate warnings. Long hacks are more "progressive".
|
||||
spawn(0)
|
||||
sleep(duration/5)
|
||||
if(!user || user.stat == DEAD)
|
||||
return
|
||||
command_announcement.Announce("Caution, [station_name]. We have detected abnormal behaviour in your network. It seems someone is trying to hack your electronic systems. We will update you when we have more information.", "Network Monitoring")
|
||||
sleep(duration/5)
|
||||
if(!user || user.stat == DEAD)
|
||||
return
|
||||
command_announcement.Announce("We started tracing the intruder. Whoever is doing this, they seem to be on the station itself. We suggest checking all network control terminals. We will keep you updated on the situation.", "Network Monitoring")
|
||||
sleep(duration/5)
|
||||
if(!user || user.stat == DEAD)
|
||||
return
|
||||
command_announcement.Announce("This is highly abnormal and somewhat concerning. The intruder is too fast, he is evading our traces. No man could be this fast...", "Network Monitoring")
|
||||
sleep(duration/5)
|
||||
if(!user || user.stat == DEAD)
|
||||
return
|
||||
command_announcement.Announce("We have traced the intrude#, it seem& t( e yo3r AI s7stem, it &# *#ck@ng th$ sel$ destru$t mechani&m, stop i# bef*@!)$#&&@@ <CONNECTION LOST>", "Network Monitoring")
|
||||
else
|
||||
command_announcement.Announce("We have detected a strong brute-force attack on your firewall which seems to be originating from your AI system. It already controls almost the whole network, and the only thing that's preventing it from accessing the self-destruct is this firewall. You don't have much time before it succeeds.", "Network Monitoring")
|
||||
user << "## BEGINNING SYSTEM OVERRIDE."
|
||||
user << "## ESTIMATED DURATION: [round((duration+300)/600)] MINUTES"
|
||||
user.hacking = 1
|
||||
user.system_override = 1
|
||||
// Now actually begin the hack. Each APC takes 10 seconds.
|
||||
for(var/obj/machinery/power/apc/A in shuffle(remaining_apcs))
|
||||
sleep(100)
|
||||
if(!user || user.stat == DEAD)
|
||||
return
|
||||
if(!A || !istype(A) || A.aidisabled)
|
||||
continue
|
||||
A.ai_hack(user)
|
||||
if(A.hacker == user)
|
||||
user << "## OVERRIDDEN: [A.name]"
|
||||
|
||||
user << "## REACHABLE APC SYSTEMS OVERTAKEN. BYPASSING PRIMARY FIREWALL."
|
||||
sleep(300)
|
||||
// Hack all APCs, including those built during hack sequence.
|
||||
for(var/obj/machinery/power/apc/A in machines)
|
||||
if((!A.hacker || A.hacker != src) && !A.aidisabled && A.z in config.station_levels)
|
||||
A.ai_hack(src)
|
||||
|
||||
|
||||
user << "## PRIMARY FIREWALL BYPASSED. YOU NOW HAVE FULL SYSTEM CONTROL."
|
||||
command_announcement.Announce("Our system administrators just reported that we've been locked out from your control network. Whoever did this now has full access to the station's systems.", "Network Administration Center")
|
||||
user.hack_can_fail = 0
|
||||
user.hacking = 0
|
||||
user.system_override = 2
|
||||
user.verbs += new/datum/game_mode/malfunction/verb/ai_destroy_station()
|
||||
|
||||
|
||||
// END ABILITY VERBS
|
||||
@@ -14,6 +14,10 @@
|
||||
|
||||
/datum/job/assistant/equip(var/mob/living/carbon/human/H)
|
||||
if(!H) return 0
|
||||
switch(H.backbag)
|
||||
if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(H), slot_back)
|
||||
if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_norm(H), slot_back)
|
||||
if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/under/color/grey(H), slot_w_uniform)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes)
|
||||
return 1
|
||||
|
||||
@@ -23,7 +23,6 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
|
||||
if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/captain(H), slot_back)
|
||||
if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_cap(H), slot_back)
|
||||
if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back)
|
||||
H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H.back), slot_in_backpack)
|
||||
var/obj/item/clothing/under/U = new /obj/item/clothing/under/rank/captain(H)
|
||||
if(H.age>49)
|
||||
U.accessories += new /obj/item/clothing/accessory/medal/gold/captain(U)
|
||||
|
||||
@@ -172,6 +172,10 @@
|
||||
H.equip_to_slot_or_del(new /obj/item/weapon/storage/bag/ore(H), slot_in_backpack)
|
||||
return 1
|
||||
|
||||
equip_survival(var/mob/living/carbon/human/H)
|
||||
if(!H) return 0
|
||||
H.species.equip_survival_gear(H,1)
|
||||
return 1
|
||||
|
||||
|
||||
//Griff //BS12 EDIT
|
||||
|
||||
@@ -37,6 +37,10 @@
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(H), slot_gloves)
|
||||
return 1
|
||||
|
||||
equip_survival(var/mob/living/carbon/human/H)
|
||||
if(!H) return 0
|
||||
H.species.equip_survival_gear(H,1)
|
||||
return 1
|
||||
|
||||
|
||||
/datum/job/engineer
|
||||
@@ -69,6 +73,10 @@
|
||||
H.equip_to_slot_or_del(new /obj/item/device/pda/engineering(H), slot_l_store)
|
||||
return 1
|
||||
|
||||
equip_survival(var/mob/living/carbon/human/H)
|
||||
if(!H) return 0
|
||||
H.species.equip_survival_gear(H,1)
|
||||
return 1
|
||||
|
||||
|
||||
/datum/job/atmos
|
||||
@@ -97,3 +105,8 @@
|
||||
H.equip_to_slot_or_del(new /obj/item/device/pda/atmos(H), slot_l_store)
|
||||
H.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/atmostech/(H), slot_belt)
|
||||
return 1
|
||||
|
||||
equip_survival(var/mob/living/carbon/human/H)
|
||||
if(!H) return 0
|
||||
H.species.equip_survival_gear(H,1)
|
||||
return 1
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
/datum/job/proc/equip(var/mob/living/carbon/human/H)
|
||||
return 1
|
||||
|
||||
/datum/job/proc/equip_survival(var/mob/living/carbon/human/H)
|
||||
if(!H) return 0
|
||||
H.species.equip_survival_gear(H,0)
|
||||
return 1
|
||||
|
||||
/datum/job/proc/get_access()
|
||||
if(!config || config.jobs_have_minimal_access)
|
||||
return src.minimal_access.Copy()
|
||||
|
||||
@@ -30,9 +30,9 @@
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(H), slot_shoes)
|
||||
H.equip_to_slot_or_del(new /obj/item/device/pda/heads/cmo(H), slot_belt)
|
||||
H.equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/adv(H), slot_l_hand)
|
||||
return 1
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/toggle/labcoat/cmo(H), slot_wear_suit)
|
||||
H.equip_to_slot_or_del(new /obj/item/device/flashlight/pen(H), slot_s_store)
|
||||
return 1
|
||||
|
||||
/datum/job/doctor
|
||||
title = "Medical Doctor"
|
||||
@@ -224,3 +224,8 @@
|
||||
H.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/medical/emt(H), slot_belt)
|
||||
H.equip_to_slot_or_del(new /obj/item/device/pda/medical(H), slot_l_store)
|
||||
return 1
|
||||
|
||||
equip_survival(var/mob/living/carbon/human/H)
|
||||
if(!H) return 0
|
||||
H.species.equip_survival_gear(H,1)
|
||||
return 1
|
||||
|
||||
@@ -66,8 +66,6 @@
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/toggle/labcoat/science(H), slot_wear_suit)
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
/datum/job/xenobiologist
|
||||
title = "Xenobiologist"
|
||||
flag = XENOBIOLOGIST
|
||||
@@ -78,8 +76,8 @@
|
||||
spawn_positions = 2
|
||||
supervisors = "the research director"
|
||||
selection_color = "#ffeeff"
|
||||
access = list(access_robotics, access_tox, access_tox_storage, access_research, access_xenobiology)
|
||||
minimal_access = list(access_research, access_xenobiology)
|
||||
access = list(access_robotics, access_tox, access_tox_storage, access_research, access_xenobiology, access_hydroponics)
|
||||
minimal_access = list(access_research, access_xenobiology, access_hydroponics, access_tox_storage)
|
||||
alt_titles = list("Xenobotanist")
|
||||
|
||||
minimal_player_age = 14
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
equip(var/mob/living/carbon/human/H)
|
||||
if(!H) return 0
|
||||
return 1
|
||||
|
||||
equip_survival(var/mob/living/carbon/human/H)
|
||||
if(!H) return 0
|
||||
return 1
|
||||
|
||||
/datum/job/ai/is_position_available()
|
||||
return (empty_playable_ai_cores.len != 0)
|
||||
@@ -32,4 +36,8 @@
|
||||
|
||||
equip(var/mob/living/carbon/human/H)
|
||||
if(!H) return 0
|
||||
return 1
|
||||
return 1
|
||||
|
||||
equip_survival(var/mob/living/carbon/human/H)
|
||||
if(!H) return 0
|
||||
return 1
|
||||
|
||||
@@ -393,8 +393,8 @@ var/global/datum/controller/occupations/job_master
|
||||
spawn_in_storage += thing
|
||||
//Equip job items.
|
||||
job.equip(H)
|
||||
job.equip_survival(H)
|
||||
job.apply_fingerprints(H)
|
||||
H.species.equip_survival_gear(H)
|
||||
|
||||
//If some custom items could not be equipped before, try again now.
|
||||
for(var/thing in custom_equip_leftovers)
|
||||
@@ -472,11 +472,6 @@ var/global/datum/controller/occupations/job_master
|
||||
var/sound/announce_sound = (ticker.current_state <= GAME_STATE_SETTING_UP)? null : sound('sound/misc/boatswain.ogg', volume=20)
|
||||
captain_announcement.Announce("All hands, Captain [H.real_name] on deck!", new_sound=announce_sound)
|
||||
|
||||
if(istype(H.back, /obj/item/weapon/storage))
|
||||
new /obj/item/weapon/storage/box/survival(H.back)
|
||||
else
|
||||
H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand)
|
||||
|
||||
//Deferred item spawning.
|
||||
if(spawn_in_storage && spawn_in_storage.len)
|
||||
var/obj/item/weapon/storage/B
|
||||
|
||||
@@ -299,3 +299,4 @@
|
||||
else
|
||||
qdel(S)
|
||||
..()
|
||||
return 1
|
||||
|
||||
@@ -267,7 +267,7 @@
|
||||
|
||||
if("cellremove")
|
||||
if(open && cell && !usr.get_active_hand())
|
||||
cell.updateicon()
|
||||
cell.update_icon()
|
||||
usr.put_in_active_hand(cell)
|
||||
cell.add_fingerprint(usr)
|
||||
cell = null
|
||||
|
||||
@@ -203,6 +203,10 @@
|
||||
..()
|
||||
|
||||
/obj/machinery/camera/proc/deactivate(user as mob, var/choice = 1)
|
||||
// The only way for AI to reactivate cameras are malf abilities, this gives them different messages.
|
||||
if(istype(user, /mob/living/silicon/ai))
|
||||
user = null
|
||||
|
||||
if(choice != 1)
|
||||
//legacy support, if choice is != 1 then just kick viewers without changing status
|
||||
kick_viewers()
|
||||
@@ -210,12 +214,18 @@
|
||||
update_coverage()
|
||||
set_status( !src.status )
|
||||
if (!(src.status))
|
||||
visible_message("\red [user] has deactivated [src]!")
|
||||
if(user)
|
||||
visible_message("<span class='notice'> [user] has deactivated [src]!</span>")
|
||||
else
|
||||
visible_message("<span class='notice'> [src] clicks and shuts down. </span>")
|
||||
playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1)
|
||||
icon_state = "[initial(icon_state)]1"
|
||||
add_hiddenprint(user)
|
||||
else
|
||||
visible_message("\red [user] has reactivated [src]!")
|
||||
if(user)
|
||||
visible_message("<span class='notice'> [user] has reactivated [src]!</span>")
|
||||
else
|
||||
visible_message("<span class='notice'> [src] clicks and reactivates itself. </span>")
|
||||
playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1)
|
||||
icon_state = initial(icon_state)
|
||||
add_hiddenprint(user)
|
||||
@@ -431,3 +441,14 @@
|
||||
cameranet.updateVisibility(src, 0)
|
||||
|
||||
invalidateCameraCache()
|
||||
|
||||
// Resets the camera's wires to fully operational state. Used by one of Malfunction abilities.
|
||||
/obj/machinery/camera/proc/reset_wires()
|
||||
if(!wires)
|
||||
return
|
||||
if (stat & BROKEN) // Fix the camera
|
||||
stat &= ~BROKEN
|
||||
wires.CutAll()
|
||||
wires.MendAll()
|
||||
update_icon()
|
||||
update_coverage()
|
||||
|
||||
@@ -162,15 +162,23 @@ var/global/list/engineering_networks = list(
|
||||
/obj/machinery/camera/proc/upgradeEmpProof()
|
||||
assembly.upgrades.Add(new /obj/item/stack/material/osmium(assembly))
|
||||
setPowerUsage()
|
||||
update_coverage()
|
||||
|
||||
/obj/machinery/camera/proc/upgradeXRay()
|
||||
assembly.upgrades.Add(new /obj/item/weapon/stock_parts/scanning_module/adv(assembly))
|
||||
setPowerUsage()
|
||||
update_coverage()
|
||||
|
||||
// If you are upgrading Motion, and it isn't in the camera's New(), add it to the machines list.
|
||||
/obj/machinery/camera/proc/upgradeMotion()
|
||||
assembly.upgrades.Add(new /obj/item/device/assembly/prox_sensor(assembly))
|
||||
setPowerUsage()
|
||||
if(!(src in machines))
|
||||
if(!machinery_sort_required && ticker)
|
||||
dd_insertObjectList(machines, src)
|
||||
else
|
||||
machines += src
|
||||
machinery_sort_required = 1
|
||||
update_coverage()
|
||||
|
||||
/obj/machinery/camera/proc/setPowerUsage()
|
||||
var/mult = 1
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
power_channel = EQUIP
|
||||
var/obj/item/weapon/cell/charging = null
|
||||
var/chargelevel = -1
|
||||
|
||||
|
||||
/obj/machinery/cell_charger/update_icon()
|
||||
icon_state = "ccharger[charging ? 1 : 0]"
|
||||
|
||||
@@ -27,11 +27,11 @@
|
||||
chargelevel = newlevel
|
||||
else
|
||||
overlays.Cut()
|
||||
|
||||
|
||||
/obj/machinery/cell_charger/examine(mob/user)
|
||||
if(!..(user, 5))
|
||||
return
|
||||
|
||||
|
||||
user << "There's [charging ? "a" : "no"] cell in the charger."
|
||||
if(charging)
|
||||
user << "Current charge: [charging.charge]"
|
||||
@@ -71,7 +71,7 @@
|
||||
if(charging)
|
||||
usr.put_in_hands(charging)
|
||||
charging.add_fingerprint(user)
|
||||
charging.updateicon()
|
||||
charging.update_icon()
|
||||
|
||||
src.charging = null
|
||||
user.visible_message("[user] removes the cell from the charger.", "You remove the cell from the charger.")
|
||||
@@ -84,7 +84,7 @@
|
||||
return
|
||||
|
||||
charging.loc = src.loc
|
||||
charging.updateicon()
|
||||
charging.update_icon()
|
||||
charging = null
|
||||
update_icon()
|
||||
user.visible_message("[user] removes the cell from the charger.", "You remove the cell from the charger.")
|
||||
@@ -103,11 +103,11 @@
|
||||
if((stat & (BROKEN|NOPOWER)) || !anchored)
|
||||
update_use_power(0)
|
||||
return
|
||||
|
||||
|
||||
if (charging && !charging.fully_charged())
|
||||
charging.give(active_power_usage*CELLRATE)
|
||||
update_use_power(2)
|
||||
|
||||
|
||||
update_icon()
|
||||
else
|
||||
update_use_power(1)
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
|
||||
if (src.occupant)
|
||||
var/laws
|
||||
dat += "Stored AI: [src.occupant.name]<br>System integrity: [src.occupant.system_integrity()]%<br>"
|
||||
dat += "Stored AI: [src.occupant.name]<br>System integrity: [src.occupant.hardware_integrity()]%<br>Backup Capacitor: [src.occupant.backup_capacitor()]%<br>"
|
||||
|
||||
for (var/datum/ai_law/law in occupant.laws.all_laws())
|
||||
laws += "[law.get_index()]: [law.law]<BR>"
|
||||
|
||||
@@ -566,7 +566,7 @@
|
||||
if(!shuttlecaller.stat && shuttlecaller.client && istype(shuttlecaller.loc,/turf))
|
||||
return ..()
|
||||
|
||||
if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction" || deathsquad.deployed)
|
||||
if(ticker.mode.name == "revolution" || deathsquad.deployed)
|
||||
return ..()
|
||||
|
||||
emergency_shuttle.call_evac()
|
||||
@@ -589,7 +589,7 @@
|
||||
if(!shuttlecaller.stat && shuttlecaller.client && istype(shuttlecaller.loc,/turf))
|
||||
return ..()
|
||||
|
||||
if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction" || deathsquad.deployed)
|
||||
if(ticker.mode.name == "revolution" || deathsquad.deployed)
|
||||
return ..()
|
||||
|
||||
emergency_shuttle.call_evac()
|
||||
|
||||
@@ -55,19 +55,11 @@
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if(!stored_computer.manipulating)
|
||||
stored_computer.manipulating = 1
|
||||
stored_computer.loc = loc
|
||||
stored_computer.stat &= ~MAINT
|
||||
stored_computer.update_icon()
|
||||
loc = null
|
||||
usr << "You open \the [src]."
|
||||
|
||||
spawn(5)
|
||||
stored_computer.manipulating = 0
|
||||
qdel(src)
|
||||
else
|
||||
usr << "\red You are already opening the computer!"
|
||||
stored_computer.loc = loc
|
||||
stored_computer.stat &= ~MAINT
|
||||
stored_computer.update_icon()
|
||||
loc = stored_computer
|
||||
usr << "You open \the [src]."
|
||||
|
||||
|
||||
AltClick()
|
||||
@@ -82,12 +74,10 @@
|
||||
|
||||
if(stored_computer)
|
||||
stored_computer.eject_id()
|
||||
|
||||
/obj/machinery/computer3/laptop/verb/eject_id()
|
||||
set category = "Object"
|
||||
set name = "Eject ID Card"
|
||||
set src in oview(1)
|
||||
|
||||
var/obj/item/part/computer/cardslot/C = locate() in src.contents
|
||||
|
||||
if(!C)
|
||||
@@ -104,7 +94,7 @@
|
||||
return
|
||||
|
||||
usr << "You remove [card] from the laptop."
|
||||
C.remove(card)
|
||||
C.remove(4)
|
||||
|
||||
|
||||
/obj/machinery/computer3/laptop
|
||||
@@ -117,7 +107,6 @@
|
||||
pixel_y = -3
|
||||
show_keyboard = 0
|
||||
|
||||
var/manipulating = 0 // To prevent disappearing bug
|
||||
var/obj/item/device/laptop/portable = null
|
||||
|
||||
New(var/L, var/built = 0)
|
||||
@@ -157,12 +146,11 @@
|
||||
portable=new
|
||||
portable.stored_computer = src
|
||||
|
||||
if(!manipulating)
|
||||
portable.loc = loc
|
||||
loc = portable
|
||||
stat |= MAINT
|
||||
if(user)
|
||||
user << "You close \the [src]."
|
||||
portable.loc = loc
|
||||
loc = portable
|
||||
stat |= MAINT
|
||||
if(user)
|
||||
user << "You close \the [src]."
|
||||
|
||||
auto_use_power()
|
||||
if(stat&MAINT)
|
||||
|
||||
@@ -393,9 +393,9 @@
|
||||
occupant.ckey = null
|
||||
|
||||
//Make an announcement and log the person entering storage.
|
||||
control_computer.frozen_crew += "[occupant.real_name]"
|
||||
control_computer.frozen_crew += "[occupant.real_name], [occupant.mind.assigned_role] - [worldtime2text()]"
|
||||
|
||||
announce.autosay("[occupant.real_name] [on_store_message]", "[on_store_name]")
|
||||
announce.autosay("[occupant.real_name], [occupant.mind.assigned_role] [on_store_message]", "[on_store_name]")
|
||||
visible_message("<span class='notice'>\The [initial(name)] hums and hisses as it moves [occupant.real_name] into storage.</span>", 3)
|
||||
|
||||
// Delete the mob.
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
var/hasShocked = 0 //Prevents multiple shocks from happening
|
||||
var/secured_wires = 0
|
||||
var/datum/wires/airlock/wires = null
|
||||
|
||||
|
||||
var/open_sound_powered = 'sound/machines/airlock.ogg'
|
||||
var/open_sound_unpowered = 'sound/machines/airlock_creaking.ogg'
|
||||
|
||||
@@ -277,7 +277,7 @@
|
||||
target_tile.assume_gas("phoron", 35, 400+T0C)
|
||||
spawn (0) target_tile.hotspot_expose(temperature, 400)
|
||||
for(var/turf/simulated/wall/W in range(3,src))
|
||||
W.ignite((temperature/4))//Added so that you can't set off a massive chain reaction with a small flame
|
||||
W.burn((temperature/4))//Added so that you can't set off a massive chain reaction with a small flame
|
||||
for(var/obj/machinery/door/airlock/phoron/D in range(3,src))
|
||||
D.ignite(temperature/4)
|
||||
new/obj/structure/door_assembly( src.loc )
|
||||
@@ -800,9 +800,9 @@ About the new airlock wires panel:
|
||||
qdel(src)
|
||||
return
|
||||
else if(arePowerSystemsOn())
|
||||
user << "\blue The airlock's motors resist your efforts to force it."
|
||||
user << "<span class='notice'>The airlock's motors resist your efforts to force it.</span>"
|
||||
else if(locked)
|
||||
user << "\blue The airlock's bolts prevent it from being forced."
|
||||
user << "<span class='notice'>The airlock's bolts prevent it from being forced.</span>"
|
||||
else
|
||||
if(density)
|
||||
spawn(0) open(1)
|
||||
@@ -811,20 +811,20 @@ About the new airlock wires panel:
|
||||
|
||||
else if(istype(C, /obj/item/weapon/material/twohanded/fireaxe) && !arePowerSystemsOn())
|
||||
if(locked)
|
||||
user << "\blue The airlock's bolts prevent it from being forced."
|
||||
user << "<span class='notice'>The airlock's bolts prevent it from being forced.</span>"
|
||||
else if( !welded && !operating )
|
||||
if(density)
|
||||
var/obj/item/weapon/material/twohanded/fireaxe/F = C
|
||||
if(F.wielded)
|
||||
spawn(0) open(1)
|
||||
else
|
||||
user << "\red You need to be wielding \the [C] to do that."
|
||||
user << "<span class='warning'>You need to be wielding \the [C] to do that.</span>"
|
||||
else
|
||||
var/obj/item/weapon/material/twohanded/fireaxe/F = C
|
||||
if(F.wielded)
|
||||
spawn(0) close(1)
|
||||
else
|
||||
user << "\red You need to be wielding \the [C] to do that."
|
||||
user << "<span class='warning'>You need to be wielding \the [C] to do that.</span>"
|
||||
|
||||
else
|
||||
..()
|
||||
@@ -855,13 +855,13 @@ About the new airlock wires panel:
|
||||
if(!can_open(forced))
|
||||
return 0
|
||||
use_power(360) //360 W seems much more appropriate for an actuator moving an industrial door capable of crushing people
|
||||
|
||||
|
||||
//if the door is unpowered then it doesn't make sense to hear the woosh of a pneumatic actuator
|
||||
if(arePowerSystemsOn())
|
||||
playsound(src.loc, open_sound_powered, 100, 1)
|
||||
else
|
||||
playsound(src.loc, open_sound_unpowered, 100, 1)
|
||||
|
||||
|
||||
if(src.closeOther != null && istype(src.closeOther, /obj/machinery/door/airlock/) && !src.closeOther.density)
|
||||
src.closeOther.close()
|
||||
return ..()
|
||||
@@ -950,10 +950,10 @@ About the new airlock wires panel:
|
||||
take_damage(DOOR_CRUSH_DAMAGE)
|
||||
|
||||
use_power(360) //360 W seems much more appropriate for an actuator moving an industrial door capable of crushing people
|
||||
if(istype(src, /obj/machinery/door/airlock/glass))
|
||||
playsound(src.loc, 'sound/machines/windowdoor.ogg', 30, 1)
|
||||
if(arePowerSystemsOn())
|
||||
playsound(src.loc, open_sound_powered, 100, 1)
|
||||
else
|
||||
playsound(src.loc, 'sound/machines/airlock.ogg', 30, 1)
|
||||
playsound(src.loc, open_sound_unpowered, 100, 1)
|
||||
for(var/turf/turf in locs)
|
||||
var/obj/structure/window/killthis = (locate(/obj/structure/window) in turf)
|
||||
if(killthis)
|
||||
|
||||
@@ -7,28 +7,70 @@
|
||||
density = 1
|
||||
var/on = 0
|
||||
var/obj/item/weapon/cell/high/cell = null
|
||||
var/use = 5
|
||||
var/use = 200 // 200W light
|
||||
var/unlocked = 0
|
||||
var/open = 0
|
||||
var/brightness_on = 8 //can't remember what the maxed out value is
|
||||
|
||||
/obj/machinery/floodlight/New()
|
||||
src.cell = new(src)
|
||||
cell.maxcharge = 1000
|
||||
cell.charge = 1000 // 41minutes @ 200W
|
||||
..()
|
||||
|
||||
/obj/machinery/floodlight/proc/updateicon()
|
||||
/obj/machinery/floodlight/update_icon()
|
||||
overlays.Cut()
|
||||
icon_state = "flood[open ? "o" : ""][open && cell ? "b" : ""]0[on]"
|
||||
|
||||
/obj/machinery/floodlight/process()
|
||||
if(!on)
|
||||
return
|
||||
|
||||
if(!cell || (cell.charge < (use * CELLRATE)))
|
||||
turn_off(1)
|
||||
return
|
||||
|
||||
// If the cell is almost empty rarely "flicker" the light. Aesthetic only.
|
||||
if((cell.percent() < 10) && prob(5))
|
||||
set_light(brightness_on/2, brightness_on/4)
|
||||
spawn(20)
|
||||
if(on)
|
||||
set_light(brightness_on, brightness_on/2)
|
||||
|
||||
cell.use(use*CELLRATE)
|
||||
|
||||
|
||||
// Returns 0 on failure and 1 on success
|
||||
/obj/machinery/floodlight/proc/turn_on(var/loud = 0)
|
||||
if(!cell)
|
||||
return 0
|
||||
if(cell.charge < (use * CELLRATE))
|
||||
return 0
|
||||
|
||||
on = 1
|
||||
set_light(brightness_on, brightness_on / 2)
|
||||
update_icon()
|
||||
if(loud)
|
||||
visible_message("\The [src] turns on.")
|
||||
return 1
|
||||
|
||||
/obj/machinery/floodlight/proc/turn_off(var/loud = 0)
|
||||
on = 0
|
||||
set_light(0, 0)
|
||||
update_icon()
|
||||
if(loud)
|
||||
visible_message("\The [src] shuts down.")
|
||||
|
||||
/obj/machinery/floodlight/attack_ai(mob/user as mob)
|
||||
if(istype(user, /mob/living/silicon/robot) && Adjacent(user))
|
||||
return attack_hand(user)
|
||||
|
||||
if(on)
|
||||
if(cell.charge >= use)
|
||||
cell.use(use)
|
||||
else
|
||||
on = 0
|
||||
updateicon()
|
||||
set_light(0)
|
||||
src.visible_message("<span class='warning'>[src] shuts down due to lack of power!</span>")
|
||||
return
|
||||
turn_off(1)
|
||||
else
|
||||
if(!turn_on(1))
|
||||
user << "You try to turn on \the [src] but it does not work."
|
||||
|
||||
|
||||
/obj/machinery/floodlight/attack_hand(mob/user as mob)
|
||||
if(open && cell)
|
||||
@@ -40,27 +82,20 @@
|
||||
cell.loc = loc
|
||||
|
||||
cell.add_fingerprint(user)
|
||||
cell.updateicon()
|
||||
cell.update_icon()
|
||||
|
||||
src.cell = null
|
||||
user << "You remove the power cell"
|
||||
updateicon()
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(on)
|
||||
on = 0
|
||||
user << "\blue You turn off the light"
|
||||
set_light(0)
|
||||
turn_off(1)
|
||||
else
|
||||
if(!cell)
|
||||
return
|
||||
if(cell.charge <= 0)
|
||||
return
|
||||
on = 1
|
||||
user << "\blue You turn on the light"
|
||||
set_light(brightness_on)
|
||||
if(!turn_on(1))
|
||||
user << "You try to turn on \the [src] but it does not work."
|
||||
|
||||
updateicon()
|
||||
update_icon()
|
||||
|
||||
|
||||
/obj/machinery/floodlight/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
@@ -93,4 +128,4 @@
|
||||
W.loc = src
|
||||
cell = W
|
||||
user << "You insert the power cell."
|
||||
updateicon()
|
||||
update_icon()
|
||||
|
||||
@@ -204,7 +204,7 @@
|
||||
item_quants[O.name]++
|
||||
else
|
||||
item_quants[O.name] = 1
|
||||
user.visible_message("<span class='notice'>[user] has added \the [O] to \the [src].", "<span class='notice'>You add \the [O] to \the [src].")
|
||||
user.visible_message("<span class='notice'>[user] has added \the [O] to \the [src].</span>", "<span class='notice'>You add \the [O] to \the [src].</span>")
|
||||
|
||||
nanomanager.update_uis(src)
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
var/raised = 0 //if the turret cover is "open" and the turret is raised
|
||||
var/raising= 0 //if the turret is currently opening or closing its cover
|
||||
var/health = 80 //the turret's health
|
||||
var/maxhealth = 80 //turrets maximal health.
|
||||
var/auto_repair = 0 //if 1 the turret slowly repairs itself.
|
||||
var/locked = 1 //if the turret's behaviour control access is locked
|
||||
var/controllock = 0 //if the turret responds to control panels
|
||||
|
||||
@@ -450,6 +452,10 @@
|
||||
spawn()
|
||||
popDown() // no valid targets, close the cover
|
||||
|
||||
if(auto_repair && (health < maxhealth))
|
||||
use_power(20000)
|
||||
health = min(health+1, maxhealth) // 1HP for 20kJ
|
||||
|
||||
/obj/machinery/porta_turret/proc/assess_and_assign(var/mob/living/L, var/list/targets, var/list/secondarytargets)
|
||||
switch(assess_living(L))
|
||||
if(TURRET_PRIORITY_TARGET)
|
||||
|
||||
@@ -121,7 +121,7 @@
|
||||
if("cellremove")
|
||||
if(panel_open && cell && !usr.get_active_hand())
|
||||
usr.visible_message("\blue [usr] removes \the [cell] from \the [src].", "\blue You remove \the [cell] from \the [src].")
|
||||
cell.updateicon()
|
||||
cell.update_icon()
|
||||
usr.put_in_hands(cell)
|
||||
cell.add_fingerprint(usr)
|
||||
cell = null
|
||||
|
||||
@@ -51,6 +51,8 @@
|
||||
// 5 = bluetag
|
||||
// 6 = redtag
|
||||
var/health = 80
|
||||
var/maxhealth = 80
|
||||
var/auto_repair = 0
|
||||
var/obj/machinery/turretcover/cover = null
|
||||
var/popping = 0
|
||||
var/wasvalid = 0
|
||||
@@ -90,6 +92,7 @@
|
||||
return
|
||||
|
||||
/obj/machinery/turret/New()
|
||||
maxhealth = health
|
||||
spark_system = new /datum/effect/effect/system/spark_spread
|
||||
spark_system.set_up(5, 0, src)
|
||||
spark_system.attach(src)
|
||||
@@ -221,6 +224,13 @@
|
||||
if(!isDown())
|
||||
popDown()
|
||||
use_power = 1
|
||||
|
||||
// Auto repair requires massive amount of power, but slowly regenerates the turret's health.
|
||||
// Currently only used by malfunction hardware, but may be used as admin-settable option too.
|
||||
if(auto_repair)
|
||||
if(health < maxhealth)
|
||||
use_power(20000)
|
||||
health = min(health + 1, maxhealth)
|
||||
return
|
||||
|
||||
|
||||
|
||||
@@ -17,20 +17,23 @@
|
||||
if(!target)
|
||||
return
|
||||
for(var/i = 1 to step_count)
|
||||
if(!loc)
|
||||
return
|
||||
step_towards(src, target)
|
||||
var/turf/T = get_turf(src)
|
||||
reagents.touch_turf(T)
|
||||
var/mob/M
|
||||
for(var/atom/A in T)
|
||||
if(!ismob(A)) // Mobs are handled differently
|
||||
reagents.touch(A)
|
||||
else if(!M)
|
||||
M = A
|
||||
if(M)
|
||||
reagents.splash_mob(M, reagents.total_volume)
|
||||
break
|
||||
if(T == get_turf(target))
|
||||
break
|
||||
if(T && reagents)
|
||||
reagents.touch_turf(T)
|
||||
var/mob/M
|
||||
for(var/atom/A in T)
|
||||
if(!ismob(A)) // Mobs are handled differently
|
||||
reagents.touch(A)
|
||||
else if(!M)
|
||||
M = A
|
||||
if(M)
|
||||
reagents.splash_mob(M, reagents.total_volume)
|
||||
break
|
||||
if(T == get_turf(target))
|
||||
break
|
||||
sleep(delay)
|
||||
sleep(10)
|
||||
qdel(src)
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
user << "<b>ERROR ERROR ERROR</b>"
|
||||
|
||||
/obj/item/device/aicard/attack_self(mob/user)
|
||||
|
||||
ui_interact(user)
|
||||
|
||||
/obj/item/device/aicard/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = inventory_state)
|
||||
@@ -25,7 +26,8 @@
|
||||
data["has_ai"] = carded_ai != null
|
||||
if(carded_ai)
|
||||
data["name"] = carded_ai.name
|
||||
data["integrity"] = carded_ai.system_integrity()
|
||||
data["hardware_integrity"] = carded_ai.hardware_integrity()
|
||||
data["backup_capacitor"] = carded_ai.backup_capacitor()
|
||||
data["radio"] = !carded_ai.aiRadio.disabledAi
|
||||
data["wireless"] = !carded_ai.control_disabled
|
||||
data["operational"] = carded_ai.stat != DEAD
|
||||
@@ -73,7 +75,6 @@
|
||||
carded_ai << "<span class='warning'>Your wireless interface has been [carded_ai.control_disabled ? "disabled" : "enabled"]!</span>"
|
||||
user << "<span class='notice'>You [carded_ai.control_disabled ? "disable" : "enable"] the AI's wireless interface.</span>"
|
||||
update_icon()
|
||||
|
||||
return 1
|
||||
|
||||
/obj/item/device/aicard/update_icon()
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
/obj/item/device/debugger/is_used_on(obj/O, mob/user)
|
||||
if(istype(O, /obj/machinery/power/apc))
|
||||
var/obj/machinery/power/apc/A = O
|
||||
if(A.emagged || A.malfhack)
|
||||
if(A.emagged || A.hacker)
|
||||
user << "\red There is a software error with the device."
|
||||
else
|
||||
user << "\blue The device's software appears to be fine."
|
||||
|
||||
@@ -91,7 +91,7 @@ REAGENT SCANNER
|
||||
if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
|
||||
usr << "\red You don't have the dexterity to do this!"
|
||||
return
|
||||
user.visible_message("<span class='notice'> [user] has analyzed [M]'s vitals.","<span class='notice'> You have analyzed [M]'s vitals.")
|
||||
user.visible_message("<span class='notice'> [user] has analyzed [M]'s vitals.</span>","<span class='notice'> You have analyzed [M]'s vitals.</span>")
|
||||
|
||||
if (!istype(M, /mob/living/carbon) || (ishuman(M) && (M:species.flags & IS_SYNTHETIC)))
|
||||
//these sensors are designed for organic life
|
||||
|
||||
@@ -5,56 +5,56 @@
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "suitcooler0"
|
||||
slot_flags = SLOT_BACK //you can carry it on your back if you want, but it won't do anything unless attached to suit storage
|
||||
|
||||
|
||||
//copied from tank.dm
|
||||
flags = CONDUCT
|
||||
force = 5.0
|
||||
throwforce = 10.0
|
||||
throw_speed = 1
|
||||
throw_range = 4
|
||||
|
||||
|
||||
origin_tech = "magnets=2;materials=2"
|
||||
|
||||
|
||||
var/on = 0 //is it turned on?
|
||||
var/cover_open = 0 //is the cover open?
|
||||
var/obj/item/weapon/cell/cell
|
||||
var/max_cooling = 12 //in degrees per second - probably don't need to mess with heat capacity here
|
||||
var/charge_consumption = 16.6 //charge per second at max_cooling
|
||||
var/thermostat = T20C
|
||||
|
||||
|
||||
//TODO: make it heat up the surroundings when not in space
|
||||
|
||||
/obj/item/device/suit_cooling_unit/New()
|
||||
processing_objects |= src
|
||||
|
||||
|
||||
cell = new/obj/item/weapon/cell() //comes with the crappy default power cell - high-capacity ones shouldn't be hard to find
|
||||
cell.loc = src
|
||||
|
||||
/obj/item/device/suit_cooling_unit/process()
|
||||
if (!on || !cell)
|
||||
if (!on || !cell)
|
||||
return
|
||||
|
||||
|
||||
if (!ismob(loc))
|
||||
return
|
||||
|
||||
|
||||
if (!attached_to_suit(loc)) //make sure they have a suit and we are attached to it
|
||||
return
|
||||
|
||||
|
||||
var/mob/living/carbon/human/H = loc
|
||||
|
||||
|
||||
var/efficiency = 1 - H.get_pressure_weakness() //you need to have a good seal for effective cooling
|
||||
var/env_temp = get_environment_temperature() //wont save you from a fire
|
||||
var/temp_adj = min(H.bodytemperature - max(thermostat, env_temp), max_cooling)
|
||||
|
||||
|
||||
if (temp_adj < 0.5) //only cools, doesn't heat, also we don't need extreme precision
|
||||
return
|
||||
|
||||
|
||||
var/charge_usage = (temp_adj/max_cooling)*charge_consumption
|
||||
|
||||
|
||||
H.bodytemperature -= temp_adj*efficiency
|
||||
|
||||
|
||||
cell.use(charge_usage)
|
||||
|
||||
|
||||
if(cell.charge <= 0)
|
||||
turn_off()
|
||||
|
||||
@@ -70,22 +70,22 @@
|
||||
var/turf/T = get_turf(src)
|
||||
if(istype(T, /turf/space))
|
||||
return 0 //space has no temperature, this just makes sure the cooling unit works in space
|
||||
|
||||
|
||||
var/datum/gas_mixture/environment = T.return_air()
|
||||
if (!environment)
|
||||
return 0
|
||||
|
||||
|
||||
return environment.temperature
|
||||
|
||||
/obj/item/device/suit_cooling_unit/proc/attached_to_suit(mob/M)
|
||||
if (!ishuman(M))
|
||||
if (!ishuman(M))
|
||||
return 0
|
||||
|
||||
|
||||
var/mob/living/carbon/human/H = M
|
||||
|
||||
|
||||
if (!H.wear_suit || H.s_store != src)
|
||||
return 0
|
||||
|
||||
|
||||
return 1
|
||||
|
||||
/obj/item/device/suit_cooling_unit/proc/turn_on()
|
||||
@@ -93,7 +93,7 @@
|
||||
return
|
||||
if(cell.charge <= 0)
|
||||
return
|
||||
|
||||
|
||||
on = 1
|
||||
updateicon()
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
cell.loc = get_turf(loc)
|
||||
|
||||
cell.add_fingerprint(user)
|
||||
cell.updateicon()
|
||||
cell.update_icon()
|
||||
|
||||
user << "You remove the [src.cell]."
|
||||
src.cell = null
|
||||
@@ -149,7 +149,7 @@
|
||||
user << "You insert the [cell]."
|
||||
updateicon()
|
||||
return
|
||||
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/device/suit_cooling_unit/proc/updateicon()
|
||||
@@ -164,7 +164,7 @@
|
||||
/obj/item/device/suit_cooling_unit/examine(mob/user)
|
||||
if(!..(user, 1))
|
||||
return
|
||||
|
||||
|
||||
if (on)
|
||||
if (attached_to_suit(src.loc))
|
||||
user << "It's switched on and running."
|
||||
@@ -172,13 +172,13 @@
|
||||
user << "It's switched on, but not attached to anything."
|
||||
else
|
||||
user << "It is switched off."
|
||||
|
||||
|
||||
if (cover_open)
|
||||
if(cell)
|
||||
user << "The panel is open, exposing the [cell]."
|
||||
else
|
||||
user << "The panel is open."
|
||||
|
||||
|
||||
if (cell)
|
||||
user << "The charge meter reads [round(cell.percent())]%."
|
||||
else
|
||||
|
||||
@@ -4,26 +4,40 @@
|
||||
Cyborg Spec Items
|
||||
***********************************************************************/
|
||||
//Might want to move this into several files later but for now it works here
|
||||
// Consider changing this to a child of the stun baton class. ~Z
|
||||
/obj/item/borg/stun
|
||||
name = "electrified arm"
|
||||
icon = 'icons/obj/decals.dmi'
|
||||
icon_state = "shock"
|
||||
|
||||
attack(mob/M as mob, mob/living/silicon/robot/user as mob)
|
||||
M.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been attacked with [src.name] by [user.name] ([user.ckey])</font>")
|
||||
user.attack_log += text("\[[time_stamp()]\] <font color='red'>Used the [src.name] to attack [M.name] ([M.ckey])</font>")
|
||||
msg_admin_attack("[user.name] ([user.ckey]) used the [src.name] to attack [M.name] ([M.ckey]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)")
|
||||
/obj/item/borg/stun/attack(var/mob/living/M, var/mob/living/silicon/robot/user)
|
||||
|
||||
user.cell.charge -= 30
|
||||
if(!istype(M))
|
||||
return
|
||||
|
||||
M.Weaken(5)
|
||||
if (M.stuttering < 5)
|
||||
M.stuttering = 5
|
||||
M.Stun(5)
|
||||
// How the Hell.
|
||||
if(!istype(user))
|
||||
var/mob/living/temp = user
|
||||
if(istype(temp))
|
||||
temp.drop_from_inventory(src)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
for(var/mob/O in viewers(M, null))
|
||||
if (O.client)
|
||||
O.show_message("\red <B>[user] has prodded [M] with an electrically-charged arm!</B>", 1, "\red You hear someone fall", 2)
|
||||
M.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been attacked with [src.name] by [user.name] ([user.ckey])</font>")
|
||||
user.attack_log += text("\[[time_stamp()]\] <font color='red'>Used the [src.name] to attack [M.name] ([M.ckey])</font>")
|
||||
msg_admin_attack("[user.name] ([user.ckey]) used the [src.name] to attack [M.name] ([M.ckey]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)")
|
||||
|
||||
if(!user.cell || !user.cell.checked_use(1250)) //Slightly more than a baton.
|
||||
user.visible_message("<span class='danger'>\The [user] has prodded \the [M] with its arm!</span>")
|
||||
return
|
||||
|
||||
if (M.stuttering < 5)
|
||||
M.stuttering = 5
|
||||
M.stun_effect_act(0, 70, check_zone(user.zone_sel.selecting), src)
|
||||
user.visible_message("<span class='danger'>\The [user] has prodded \the [M] with \a [src]!</span>")
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
H.forcesay(hit_appends)
|
||||
|
||||
/obj/item/borg/overdrive
|
||||
name = "overdrive"
|
||||
|
||||
@@ -223,10 +223,10 @@
|
||||
*/
|
||||
|
||||
//attempts to transfer amount to S, and returns the amount actually transferred
|
||||
/obj/item/stack/proc/transfer_to(obj/item/stack/S, var/tamount=null)
|
||||
/obj/item/stack/proc/transfer_to(obj/item/stack/S, var/tamount=null, var/type_verified)
|
||||
if (!get_amount())
|
||||
return 0
|
||||
if (stacktype != S.stacktype)
|
||||
if ((stacktype != S.stacktype) && !type_verified)
|
||||
return 0
|
||||
if (isnull(tamount))
|
||||
tamount = src.get_amount()
|
||||
@@ -240,7 +240,6 @@
|
||||
transfer_fingerprints_to(S)
|
||||
if(blood_DNA)
|
||||
S.blood_DNA |= blood_DNA
|
||||
//todo bloody overlay
|
||||
return transfer
|
||||
return 0
|
||||
|
||||
@@ -256,6 +255,7 @@
|
||||
var/orig_amount = src.amount
|
||||
if (transfer && src.use(transfer))
|
||||
var/obj/item/stack/newstack = new src.type(loc, transfer)
|
||||
newstack.color = color
|
||||
if (prob(transfer/orig_amount * 100))
|
||||
transfer_fingerprints_to(newstack)
|
||||
if(blood_DNA)
|
||||
@@ -314,10 +314,8 @@
|
||||
return
|
||||
|
||||
/obj/item/stack/attackby(obj/item/W as obj, mob/user as mob)
|
||||
..()
|
||||
if (istype(W, /obj/item/stack))
|
||||
var/obj/item/stack/S = W
|
||||
|
||||
if (user.get_inactive_hand()==src)
|
||||
src.transfer_to(S, 1)
|
||||
else
|
||||
@@ -328,7 +326,8 @@
|
||||
S.interact(usr)
|
||||
if (src && usr.machine==src)
|
||||
src.interact(usr)
|
||||
else return ..()
|
||||
else
|
||||
return ..()
|
||||
|
||||
/*
|
||||
* Recipe datum
|
||||
|
||||
+5
-10
@@ -76,32 +76,27 @@ var/global/list/ashtray_cache = list()
|
||||
health = max(0,health - W.force)
|
||||
user << "You hit [src] with [W]."
|
||||
if (health < 1)
|
||||
die()
|
||||
shatter()
|
||||
return
|
||||
|
||||
/obj/item/weapon/material/ashtray/throw_impact(atom/hit_atom)
|
||||
if (health > 0)
|
||||
health = max(0,health - 3)
|
||||
if (health < 1)
|
||||
die()
|
||||
return
|
||||
if (contents.len)
|
||||
src.visible_message("<span class='danger'>\The [src] slams into [hit_atom], spilling its contents!</span>")
|
||||
for (var/obj/item/clothing/mask/smokable/cigarette/O in contents)
|
||||
O.loc = src.loc
|
||||
if (health < 1)
|
||||
shatter()
|
||||
return
|
||||
update_icon()
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/material/ashtray/proc/die()
|
||||
material.place_shard(get_turf(src))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/item/weapon/material/ashtray/plastic/New(var/newloc)
|
||||
..(newloc, "plastic")
|
||||
|
||||
/obj/item/weapon/material/ashtray/bronze/New(var/newloc)
|
||||
..(newloc, "gold") //placeholder
|
||||
..(newloc, "bronze")
|
||||
|
||||
/obj/item/weapon/material/ashtray/glass/New(var/newloc)
|
||||
..(newloc, "glass")
|
||||
@@ -72,7 +72,7 @@
|
||||
var/mob/living/M = loc
|
||||
M.drop_from_inventory(src)
|
||||
playsound(src, "shatter", 70, 1)
|
||||
new material.shard_type(T)
|
||||
material.place_shard(T)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/weapon/material/process()
|
||||
@@ -82,18 +82,12 @@
|
||||
L.apply_effect(round(material.radioactivity/3),IRRADIATE,0)
|
||||
|
||||
/obj/item/weapon/material/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
if(exposed_temperature > material.ignition_point)
|
||||
TemperatureAct(exposed_temperature)
|
||||
TemperatureAct(exposed_temperature)
|
||||
|
||||
// This might need adjustment. Will work that out later.
|
||||
/obj/item/weapon/material/proc/TemperatureAct(temperature)
|
||||
if(temperature > material.ignition_point)
|
||||
for(var/turf/simulated/floor/target_tile in range(2,loc))
|
||||
var/phoronToDeduce = temperature/30
|
||||
target_tile.assume_gas("phoron", phoronToDeduce, 200+T0C)
|
||||
spawn (0) target_tile.hotspot_expose(temperature, 400)
|
||||
health -= phoronToDeduce/100
|
||||
check_health()
|
||||
health -= material.combustion_effect(get_turf(src), temperature, 0.1)
|
||||
check_health()
|
||||
|
||||
/obj/item/weapon/material/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(istype(W,/obj/item/weapon/weldingtool))
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
desc = "It's just an ordinary box."
|
||||
icon_state = "box"
|
||||
item_state = "syringe_kit"
|
||||
var/foldable = null // BubbleWrap - if set, can be folded (when empty) into a sheet of cardboard
|
||||
var/foldable = /obj/item/stack/material/cardboard // BubbleWrap - if set, can be folded (when empty) into a sheet of cardboard
|
||||
|
||||
// BubbleWrap - A box can be folded up to make card
|
||||
/obj/item/weapon/storage/box/attack_self(mob/user as mob)
|
||||
@@ -56,7 +56,7 @@
|
||||
new /obj/item/clothing/mask/breath( src )
|
||||
new /obj/item/weapon/tank/emergency_oxygen( src )
|
||||
|
||||
/obj/item/weapon/storage/box/survival/vox/
|
||||
/obj/item/weapon/storage/box/vox/
|
||||
New()
|
||||
..()
|
||||
new /obj/item/clothing/mask/breath( src )
|
||||
@@ -598,7 +598,6 @@
|
||||
icon_state = "light"
|
||||
desc = "This box is shaped on the inside so that only light tubes and bulbs fit."
|
||||
item_state = "syringe_kit"
|
||||
foldable = /obj/item/stack/material/cardboard //BubbleWrap
|
||||
storage_slots=21
|
||||
can_hold = list(/obj/item/weapon/light/tube, /obj/item/weapon/light/bulb)
|
||||
max_storage_space = 42 //holds 21 items of w_class 2
|
||||
|
||||
@@ -10,40 +10,3 @@
|
||||
w_class = 4
|
||||
max_w_class = 3
|
||||
max_storage_space = 16
|
||||
|
||||
/obj/item/weapon/storage/briefcase/New()
|
||||
..()
|
||||
|
||||
/obj/item/weapon/storage/briefcase/attack(mob/living/M as mob, mob/living/user as mob)
|
||||
//..()
|
||||
|
||||
if ((CLUMSY in user.mutations) && prob(50))
|
||||
user << "\red The [src] slips out of your hand and hits your head."
|
||||
user.take_organ_damage(10)
|
||||
user.Paralyse(2)
|
||||
return
|
||||
|
||||
|
||||
M.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been attacked with [src.name] by [user.name] ([user.ckey])</font>")
|
||||
user.attack_log += text("\[[time_stamp()]\] <font color='red'>Used the [src.name] to attack [M.name] ([M.ckey])</font>")
|
||||
msg_admin_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>)")
|
||||
|
||||
if (M.stat < 2 && M.health < 50 && prob(90))
|
||||
var/mob/H = M
|
||||
// ******* Check
|
||||
if ((istype(H, /mob/living/carbon/human) && istype(H, /obj/item/clothing/head) && H.flags & 8 && prob(80)))
|
||||
M << "\red The helmet protects you from being hit hard in the head!"
|
||||
return
|
||||
var/time = rand(2, 6)
|
||||
if (prob(75))
|
||||
M.Paralyse(time)
|
||||
else
|
||||
M.Stun(time)
|
||||
if(M.stat != 2) M.stat = 1
|
||||
for(var/mob/O in viewers(M, null))
|
||||
O.show_message(text("\red <B>[] has been knocked unconscious!</B>", M), 1, "\red You hear someone fall.", 2)
|
||||
else
|
||||
M << text("\red [] tried to knock you unconcious!",user)
|
||||
M.eye_blurry += 3
|
||||
|
||||
return
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
if("stealth")
|
||||
new /obj/item/weapon/gun/energy/crossbow(src)
|
||||
new /obj/item/weapon/pen/paralysis(src)
|
||||
new /obj/item/weapon/pen/reagent/paralysis(src)
|
||||
new /obj/item/device/chameleon(src)
|
||||
return
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
|
||||
else if(istype(W, /obj/item/weapon/screwdriver))
|
||||
if(bcell)
|
||||
bcell.updateicon()
|
||||
bcell.update_icon()
|
||||
bcell.loc = get_turf(src.loc)
|
||||
bcell = null
|
||||
user << "<span class='notice'>You remove the cell from the [src].</span>"
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 15000, "glass" = 10000)
|
||||
flags = CONDUCT
|
||||
force = 15.0
|
||||
w_class = 2.0
|
||||
w_class = 3
|
||||
origin_tech = "materials=1;biotech=1"
|
||||
attack_verb = list("drilled")
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
force = 10.0
|
||||
sharp = 1
|
||||
edge = 1
|
||||
w_class = 2.0
|
||||
w_class = 1
|
||||
throwforce = 5.0
|
||||
throw_speed = 3
|
||||
throw_range = 5
|
||||
@@ -136,7 +136,7 @@
|
||||
hitsound = 'sound/weapons/circsawhit.ogg'
|
||||
flags = CONDUCT
|
||||
force = 15.0
|
||||
w_class = 2.0
|
||||
w_class = 3
|
||||
throwforce = 9.0
|
||||
throw_speed = 3
|
||||
throw_range = 5
|
||||
|
||||
@@ -174,9 +174,9 @@
|
||||
else if(istype(W, /obj/item/weapon/wrench) && state == 0)
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1)
|
||||
if(anchored)
|
||||
user.visible_message("[user] unsecures the airlock assembly from the floor.", "You start to unsecure the airlock assembly from the floor.")
|
||||
user.visible_message("[user] begins unsecuring the airlock assembly from the floor.", "You starts unsecuring the airlock assembly from the floor.")
|
||||
else
|
||||
user.visible_message("[user] secures the airlock assembly to the floor.", "You start to secure the airlock assembly to the floor.")
|
||||
user.visible_message("[user] begins securing the airlock assembly to the floor.", "You starts securing the airlock assembly to the floor.")
|
||||
|
||||
if(do_after(user, 40))
|
||||
if(!src) return
|
||||
@@ -225,7 +225,7 @@
|
||||
return
|
||||
|
||||
playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1)
|
||||
user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to remove the electronics from the airlock assembly.")
|
||||
user.visible_message("\The [user] starts removing the electronics from the airlock assembly.", "You start removing the electronics from the airlock assembly.")
|
||||
|
||||
if(do_after(user, 40))
|
||||
if(!src) return
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
if(notices < 5)
|
||||
O.add_fingerprint(user)
|
||||
add_fingerprint(user)
|
||||
user.drop_item()
|
||||
user.drop_from_inventory(O)
|
||||
O.loc = src
|
||||
notices++
|
||||
icon_state = "nboard0[notices]" //update sprite
|
||||
@@ -29,13 +29,22 @@
|
||||
else
|
||||
user << "<span class='notice'>You reach to pin your paper to the board but hesitate. You are certain your paper will not be seen among the many others already attached.</span>"
|
||||
|
||||
/obj/structure/noticeboard/attack_hand(user as mob)
|
||||
var/dat = "<B>Noticeboard</B><BR>"
|
||||
for(var/obj/item/weapon/paper/P in src)
|
||||
dat += "<A href='?src=\ref[src];read=\ref[P]'>[P.name]</A> <A href='?src=\ref[src];write=\ref[P]'>Write</A> <A href='?src=\ref[src];remove=\ref[P]'>Remove</A><BR>"
|
||||
user << browse("<HEAD><TITLE>Notices</TITLE></HEAD>[dat]","window=noticeboard")
|
||||
onclose(user, "noticeboard")
|
||||
/obj/structure/noticeboard/attack_hand(var/mob/user)
|
||||
examine(user)
|
||||
|
||||
// Since Topic() never seems to interact with usr on more than a superficial
|
||||
// level, it should be fine to let anyone mess with the board other than ghosts.
|
||||
/obj/structure/noticeboard/examine(var/mob/user)
|
||||
if(!user)
|
||||
user = usr
|
||||
if(user.Adjacent(src))
|
||||
var/dat = "<B>Noticeboard</B><BR>"
|
||||
for(var/obj/item/weapon/paper/P in src)
|
||||
dat += "<A href='?src=\ref[src];read=\ref[P]'>[P.name]</A> <A href='?src=\ref[src];write=\ref[P]'>Write</A> <A href='?src=\ref[src];remove=\ref[P]'>Remove</A><BR>"
|
||||
user << browse("<HEAD><TITLE>Notices</TITLE></HEAD>[dat]","window=noticeboard")
|
||||
onclose(user, "noticeboard")
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/structure/noticeboard/Topic(href, href_list)
|
||||
..()
|
||||
@@ -44,18 +53,16 @@
|
||||
if((usr.stat || usr.restrained())) //For when a player is handcuffed while they have the notice window open
|
||||
return
|
||||
var/obj/item/P = locate(href_list["remove"])
|
||||
if((P && P.loc == src))
|
||||
if(P && P.loc == src)
|
||||
P.loc = get_turf(src) //dump paper on the floor because you're a clumsy fuck
|
||||
P.add_fingerprint(usr)
|
||||
add_fingerprint(usr)
|
||||
notices--
|
||||
icon_state = "nboard0[notices]"
|
||||
|
||||
if(href_list["write"])
|
||||
if((usr.stat || usr.restrained())) //For when a player is handcuffed while they have the notice window open
|
||||
return
|
||||
var/obj/item/P = locate(href_list["write"])
|
||||
|
||||
if((P && P.loc == src)) //ifthe paper's on the board
|
||||
if(istype(usr.r_hand, /obj/item/weapon/pen)) //and you're holding a pen
|
||||
add_fingerprint(usr)
|
||||
@@ -66,14 +73,9 @@
|
||||
P.attackby(usr.l_hand, usr)
|
||||
else
|
||||
usr << "<span class='notice'>You'll need something to write with!</span>"
|
||||
|
||||
if(href_list["read"])
|
||||
var/obj/item/weapon/paper/P = locate(href_list["read"])
|
||||
if((P && P.loc == src))
|
||||
if(!( istype(usr, /mob/living/carbon/human) ))
|
||||
usr << browse("<HTML><HEAD><TITLE>[P.name]</TITLE></HEAD><BODY><TT>[stars(P.info)]</TT></BODY></HTML>", "window=[P.name]")
|
||||
onclose(usr, "[P.name]")
|
||||
else
|
||||
usr << browse("<HTML><HEAD><TITLE>[P.name]</TITLE></HEAD><BODY><TT>[P.info]</TT></BODY></HTML>", "window=[P.name]")
|
||||
onclose(usr, "[P.name]")
|
||||
usr << browse("<HTML><HEAD><TITLE>[P.name]</TITLE></HEAD><BODY><TT>[P.info]</TT></BODY></HTML>", "window=[P.name]")
|
||||
onclose(usr, "[P.name]")
|
||||
return
|
||||
|
||||
@@ -13,17 +13,11 @@
|
||||
var/oreAmount = 7
|
||||
|
||||
/obj/structure/simple_door/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
if(exposed_temperature > material.ignition_point)
|
||||
TemperatureAct(exposed_temperature)
|
||||
TemperatureAct(exposed_temperature)
|
||||
|
||||
/obj/structure/simple_door/proc/TemperatureAct(temperature)
|
||||
if(temperature > material.ignition_point)
|
||||
for(var/turf/simulated/floor/target_tile in range(2,loc))
|
||||
var/phoronToDeduce = temperature/10
|
||||
target_tile.assume_gas("phoron", phoronToDeduce, 200+T0C)
|
||||
spawn (0) target_tile.hotspot_expose(temperature, 400)
|
||||
hardness -= phoronToDeduce/100
|
||||
CheckHardness()
|
||||
hardness -= material.combustion_effect(get_turf(src),temperature, 0.3)
|
||||
CheckHardness()
|
||||
|
||||
/obj/structure/simple_door/New(var/newloc, var/material_name)
|
||||
..()
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
icon_state = "nest"
|
||||
var/health = 100
|
||||
|
||||
/obj/structure/bed/nest/update_icon()
|
||||
return
|
||||
|
||||
/obj/structure/bed/nest/user_unbuckle_mob(mob/user as mob)
|
||||
if(buckled_mob)
|
||||
if(buckled_mob.buckled == src)
|
||||
|
||||
@@ -10,28 +10,56 @@
|
||||
/obj/structure/bed
|
||||
name = "bed"
|
||||
desc = "This is used to lie in, sleep in or strap on."
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon = 'icons/obj/furniture.dmi'
|
||||
icon_state = "bed"
|
||||
pressure_resistance = 15
|
||||
anchored = 1
|
||||
can_buckle = 1
|
||||
buckle_lying = 1
|
||||
var/material/material
|
||||
var/apply_cosmetics = 1
|
||||
var/material/padding_material
|
||||
var/base_icon = "bed"
|
||||
|
||||
/obj/structure/bed/New(var/newloc, var/new_material)
|
||||
/obj/structure/bed/New(var/newloc, var/new_material, var/new_padding_material)
|
||||
..(newloc)
|
||||
if(!new_material)
|
||||
new_material = DEFAULT_WALL_MATERIAL
|
||||
|
||||
material = get_material_by_name(new_material)
|
||||
if(!istype(material))
|
||||
qdel(src)
|
||||
return
|
||||
if(apply_cosmetics)
|
||||
color = material.icon_colour
|
||||
if(new_padding_material)
|
||||
padding_material = get_material_by_name(new_padding_material)
|
||||
update_icon()
|
||||
|
||||
// Reuse the cache/code from stools, todo maybe unify.
|
||||
/obj/structure/bed/update_icon()
|
||||
// Prep icon.
|
||||
icon_state = ""
|
||||
overlays.Cut()
|
||||
// Base icon.
|
||||
var/cache_key = "[base_icon]-[material.name]"
|
||||
if(isnull(stool_cache[cache_key]))
|
||||
var/image/I = image('icons/obj/furniture.dmi', base_icon)
|
||||
I.color = material.icon_colour
|
||||
stool_cache[cache_key] = I
|
||||
overlays |= stool_cache[cache_key]
|
||||
// Padding overlay.
|
||||
if(padding_material)
|
||||
var/padding_cache_key = "[base_icon]-padding-[padding_material.name]"
|
||||
if(isnull(stool_cache[padding_cache_key]))
|
||||
var/image/I = image(icon, "[base_icon]_padding")
|
||||
I.color = padding_material.icon_colour
|
||||
stool_cache[padding_cache_key] = I
|
||||
overlays |= stool_cache[padding_cache_key]
|
||||
// Strings.
|
||||
desc = initial(desc)
|
||||
if(padding_material)
|
||||
name = "[padding_material.display_name] [initial(name)]" //this is not perfect but it will do for now.
|
||||
desc += " It's made of [material.use_name] and covered with [padding_material.use_name]."
|
||||
else
|
||||
name = "[material.display_name] [initial(name)]"
|
||||
desc = "[initial(desc)] It's made of [material.display_name]."
|
||||
desc += " It's made of [material.use_name]."
|
||||
|
||||
/obj/structure/bed/ex_act(severity)
|
||||
switch(severity)
|
||||
@@ -55,8 +83,43 @@
|
||||
/obj/structure/bed/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(istype(W, /obj/item/weapon/wrench))
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
material.place_sheet(get_turf(src))
|
||||
dismantle()
|
||||
qdel(src)
|
||||
else if(istype(W,/obj/item/stack))
|
||||
if(padding_material)
|
||||
user << "\The [src] is already padded."
|
||||
return
|
||||
var/obj/item/stack/C = W
|
||||
if(C.get_amount() < 1) // How??
|
||||
user.drop_from_inventory(C)
|
||||
qdel(C)
|
||||
return
|
||||
var/padding_type //This is awful but it needs to be like this until tiles are given a material var.
|
||||
if(istype(W,/obj/item/stack/tile/carpet))
|
||||
padding_type = "carpet"
|
||||
else if(istype(W,/obj/item/stack/material))
|
||||
var/obj/item/stack/material/M = W
|
||||
if(M.material && (M.material.flags & MATERIAL_PADDING))
|
||||
padding_type = "[M.material.name]"
|
||||
if(!padding_type)
|
||||
user << "You cannot pad \the [src] with that."
|
||||
return
|
||||
C.use(1)
|
||||
if(!istype(src.loc, /turf))
|
||||
user.drop_from_inventory(src)
|
||||
src.loc = get_turf(src)
|
||||
user << "You add padding to \the [src]."
|
||||
add_padding(padding_type)
|
||||
return
|
||||
|
||||
else if (istype(W, /obj/item/weapon/wirecutters))
|
||||
if(!padding_material)
|
||||
user << "\The [src] has no padding to remove."
|
||||
return
|
||||
user << "You remove the padding from \the [src]."
|
||||
playsound(src, 'sound/items/Wirecutter.ogg', 100, 1)
|
||||
remove_padding()
|
||||
|
||||
else if(istype(W, /obj/item/weapon/grab))
|
||||
user.visible_message("<span class='notice'>[user] attempts to buckle [W:affecting] into \the [src]!</span>")
|
||||
if(do_after(user, 20))
|
||||
@@ -69,21 +132,36 @@
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/structure/bed/proc/remove_padding()
|
||||
if(padding_material)
|
||||
padding_material.place_sheet(get_turf(src))
|
||||
padding_material = null
|
||||
update_icon()
|
||||
|
||||
/obj/structure/bed/proc/add_padding(var/padding_type)
|
||||
padding_material = get_material_by_name(padding_type)
|
||||
update_icon()
|
||||
|
||||
/obj/structure/bed/proc/dismantle()
|
||||
material.place_sheet(get_turf(src))
|
||||
if(padding_material)
|
||||
padding_material.place_sheet(get_turf(src))
|
||||
|
||||
/obj/structure/bed/psych
|
||||
name = "psychiatrist's couch"
|
||||
desc = "For prime comfort during psychiatric evaluations."
|
||||
icon_state = "psychbed"
|
||||
apply_cosmetics = 0
|
||||
base_icon = "psychbed"
|
||||
|
||||
/obj/structure/bed/psych/New(var/newloc)
|
||||
..(newloc,"leather")
|
||||
..(newloc,"wood","leather")
|
||||
|
||||
/obj/structure/bed/padded/New(var/newloc)
|
||||
..(newloc,"plastic","cotton")
|
||||
|
||||
/obj/structure/bed/alien
|
||||
name = "resting contraption"
|
||||
desc = "This looks similar to contraptions from earth. Could aliens be stealing our technology?"
|
||||
icon_state = "abed"
|
||||
apply_cosmetics = 0
|
||||
|
||||
|
||||
/obj/structure/bed/alien/New(var/newloc)
|
||||
..(newloc,"resin")
|
||||
@@ -96,10 +174,14 @@
|
||||
icon = 'icons/obj/rollerbed.dmi'
|
||||
icon_state = "down"
|
||||
anchored = 0
|
||||
apply_cosmetics = 0
|
||||
|
||||
/obj/structure/bed/roller/update_icon()
|
||||
return // Doesn't care about material or anything else.
|
||||
|
||||
/obj/structure/bed/roller/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(istype(W,/obj/item/roller_holder))
|
||||
if(istype(W, /obj/item/weapon/wrench) || istype(W,/obj/item/stack) || istype(W, /obj/item/weapon/wirecutters))
|
||||
return
|
||||
else if(istype(W,/obj/item/roller_holder))
|
||||
if(buckled_mob)
|
||||
user_unbuckle_mob(user)
|
||||
else
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
/obj/structure/bed/chair //YES, chairs are a type of bed, which are a type of stool. This works, believe me. -Pete
|
||||
name = "chair"
|
||||
desc = "You sit in this. Either by will or force."
|
||||
icon_state = "chair"
|
||||
icon_state = "chair_preview"
|
||||
base_icon = "chair"
|
||||
buckle_lying = 0 //force people to sit up in chairs when buckled
|
||||
var/propelled = 0 // Check for fire-extinguisher-driven chairs
|
||||
|
||||
/obj/structure/bed/chair/New(var/newloc, var/material)
|
||||
..(newloc, material) //Todo make metal/stone chairs display as thrones
|
||||
/obj/structure/bed/chair/New()
|
||||
..() //Todo make metal/stone chairs display as thrones
|
||||
spawn(3) //sorry. i don't think there's a better way to do this.
|
||||
update_layer()
|
||||
return
|
||||
|
||||
/obj/structure/bed/chair/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
..()
|
||||
if(istype(W, /obj/item/assembly/shock_kit))
|
||||
if(!padding_material && istype(W, /obj/item/assembly/shock_kit))
|
||||
var/obj/item/assembly/shock_kit/SK = W
|
||||
if(!SK.status)
|
||||
user << "<span class='notice'>[SK] is not ready to be attached!</span>"
|
||||
user << "<span class='notice'>\The [SK] is not ready to be attached!</span>"
|
||||
return
|
||||
user.drop_item()
|
||||
var/obj/structure/bed/chair/e_chair/E = new (src.loc, material.name)
|
||||
@@ -34,6 +35,20 @@
|
||||
rotate()
|
||||
return
|
||||
|
||||
/obj/structure/bed/chair/post_buckle_mob()
|
||||
update_icon()
|
||||
|
||||
/obj/structure/bed/chair/update_icon()
|
||||
..()
|
||||
if(buckled_mob && padding_material)
|
||||
var/cache_key = "[base_icon]-armrest-[padding_material.name]"
|
||||
if(isnull(stool_cache[cache_key]))
|
||||
var/image/I = image(icon, "[base_icon]_armrest")
|
||||
I.layer = MOB_LAYER + 0.1
|
||||
I.color = padding_material.icon_colour
|
||||
stool_cache[cache_key] = I
|
||||
overlays |= stool_cache[cache_key]
|
||||
|
||||
/obj/structure/bed/chair/proc/update_layer()
|
||||
if(src.dir == NORTH)
|
||||
src.layer = FLY_LAYER
|
||||
@@ -65,70 +80,49 @@
|
||||
src.set_dir(turn(src.dir, 90))
|
||||
return
|
||||
|
||||
// Chair types
|
||||
/obj/structure/bed/chair/wood
|
||||
icon_state = "wooden_chair"
|
||||
name = "wooden chair"
|
||||
desc = "Old is never too old to not be in fashion."
|
||||
apply_cosmetics = 0
|
||||
|
||||
/obj/structure/bed/chair/wood/New(var/newloc)
|
||||
..(newloc, "wood")
|
||||
|
||||
/obj/structure/bed/chair/wood/wings
|
||||
icon_state = "wooden_chair_wings"
|
||||
|
||||
// Leaving this in for the sake of compilation.
|
||||
/obj/structure/bed/chair/comfy
|
||||
name = "comfy chair"
|
||||
desc = "It looks comfy."
|
||||
icon_state = "comfychair"
|
||||
color = rgb(255,255,255)
|
||||
var/image/armrest = null
|
||||
apply_cosmetics = 0
|
||||
desc = "It's a chair. It looks comfy."
|
||||
icon_state = "comfychair_preview"
|
||||
|
||||
/obj/structure/bed/chair/comfy/New()
|
||||
armrest = image("icons/obj/objects.dmi", "comfychair_armrest")
|
||||
armrest.layer = MOB_LAYER + 0.1
|
||||
/obj/structure/bed/chair/comfy/brown/New(var/newloc,var/newmaterial)
|
||||
..(newloc,"steel","leather")
|
||||
|
||||
return ..()
|
||||
/obj/structure/bed/chair/comfy/red/New(var/newloc,var/newmaterial)
|
||||
..(newloc,"steel","carpet")
|
||||
|
||||
/obj/structure/bed/chair/comfy/post_buckle_mob()
|
||||
if(buckled_mob)
|
||||
overlays += armrest
|
||||
else
|
||||
overlays -= armrest
|
||||
/obj/structure/bed/chair/comfy/teal/New(var/newloc,var/newmaterial)
|
||||
..(newloc,"steel","teal")
|
||||
|
||||
/obj/structure/bed/chair/comfy/brown
|
||||
color = rgb(141,70,0)
|
||||
/obj/structure/bed/chair/comfy/black/New(var/newloc,var/newmaterial)
|
||||
..(newloc,"steel","black")
|
||||
|
||||
/obj/structure/bed/chair/comfy/red
|
||||
color = rgb(218,2,10)
|
||||
/obj/structure/bed/chair/comfy/green/New(var/newloc,var/newmaterial)
|
||||
..(newloc,"steel","green")
|
||||
|
||||
/obj/structure/bed/chair/comfy/teal
|
||||
color = rgb(0,234,250)
|
||||
/obj/structure/bed/chair/comfy/purp/New(var/newloc,var/newmaterial)
|
||||
..(newloc,"steel","purple")
|
||||
|
||||
/obj/structure/bed/chair/comfy/black
|
||||
color = rgb(60,60,60)
|
||||
/obj/structure/bed/chair/comfy/blue/New(var/newloc,var/newmaterial)
|
||||
..(newloc,"steel","blue")
|
||||
|
||||
/obj/structure/bed/chair/comfy/green
|
||||
color = rgb(1,196,8)
|
||||
/obj/structure/bed/chair/comfy/beige/New(var/newloc,var/newmaterial)
|
||||
..(newloc,"steel","beige")
|
||||
|
||||
/obj/structure/bed/chair/comfy/purp
|
||||
color = rgb(112,2,176)
|
||||
|
||||
/obj/structure/bed/chair/comfy/blue
|
||||
color = rgb(2,9,210)
|
||||
|
||||
/obj/structure/bed/chair/comfy/beige
|
||||
color = rgb(255,253,195)
|
||||
/obj/structure/bed/chair/comfy/lime/New(var/newloc,var/newmaterial)
|
||||
..(newloc,"steel","lime")
|
||||
|
||||
/obj/structure/bed/chair/office
|
||||
anchored = 0
|
||||
buckle_movable = 1
|
||||
apply_cosmetics = 0
|
||||
|
||||
/obj/structure/bed/chair/comfy/lime
|
||||
color = rgb(255,251,0)
|
||||
/obj/structure/bed/chair/office/update_icon()
|
||||
return
|
||||
|
||||
/obj/structure/bed/chair/office/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(istype(W,/obj/item/stack) || istype(W, /obj/item/weapon/wirecutters))
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/structure/bed/chair/office/Move()
|
||||
..()
|
||||
@@ -175,3 +169,23 @@
|
||||
|
||||
/obj/structure/bed/chair/office/dark
|
||||
icon_state = "officechair_dark"
|
||||
|
||||
// Chair types
|
||||
/obj/structure/bed/chair/wood
|
||||
name = "wooden chair"
|
||||
desc = "Old is never too old to not be in fashion."
|
||||
icon_state = "wooden_chair"
|
||||
|
||||
/obj/structure/bed/chair/wood/update_icon()
|
||||
return
|
||||
|
||||
/obj/structure/bed/chair/wood/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(istype(W,/obj/item/stack) || istype(W, /obj/item/weapon/wirecutters))
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/structure/bed/chair/wood/New(var/newloc)
|
||||
..(newloc, "wood")
|
||||
|
||||
/obj/structure/bed/chair/wood/wings
|
||||
icon_state = "wooden_chair_wings"
|
||||
|
||||
@@ -4,7 +4,7 @@ var/global/list/stool_cache = list() //haha stool
|
||||
/obj/item/weapon/stool
|
||||
name = "stool"
|
||||
desc = "Apply butt."
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon = 'icons/obj/furniture.dmi'
|
||||
icon_state = "stool_preview" //set for the map
|
||||
force = 10
|
||||
throwforce = 10
|
||||
@@ -30,17 +30,16 @@ var/global/list/stool_cache = list() //haha stool
|
||||
update_icon()
|
||||
|
||||
/obj/item/weapon/stool/padded/New(var/newloc, var/new_material)
|
||||
..(newloc, "steel", "leather")
|
||||
..(newloc, "steel", "carpet")
|
||||
|
||||
/obj/item/weapon/stool/update_icon()
|
||||
// Prep icon.
|
||||
icon_state = "stool"
|
||||
icon_state = ""
|
||||
overlays.Cut()
|
||||
// Base icon.
|
||||
var/cache_key = "stool-[material.name]"
|
||||
if(isnull(stool_cache[cache_key]))
|
||||
var/image/I = image('icons/obj/objects.dmi', base_icon)
|
||||
color = material.icon_colour
|
||||
var/image/I = image(icon, base_icon)
|
||||
I.color = material.icon_colour
|
||||
stool_cache[cache_key] = I
|
||||
overlays |= stool_cache[cache_key]
|
||||
@@ -48,17 +47,17 @@ var/global/list/stool_cache = list() //haha stool
|
||||
if(padding_material)
|
||||
var/padding_cache_key = "stool-padding-[padding_material.name]"
|
||||
if(isnull(stool_cache[padding_cache_key]))
|
||||
var/image/I = image('icons/obj/objects.dmi', "stool_padding")
|
||||
var/image/I = image(icon, "stool_padding")
|
||||
I.color = padding_material.icon_colour
|
||||
stool_cache[padding_cache_key] = I
|
||||
overlays |= stool_cache[padding_cache_key]
|
||||
// Strings.
|
||||
if(padding_material)
|
||||
name = "[padding_material.display_name] [initial(name)]" //this is not perfect but it will do for now.
|
||||
desc = "A padded stool. Apply butt. It's made of [material.display_name] and covered with [padding_material.display_name]."
|
||||
desc = "A padded stool. Apply butt. It's made of [material.use_name] and covered with [padding_material.use_name]."
|
||||
else
|
||||
name = "[material.display_name] [initial(name)]"
|
||||
desc = "A stool. Apply butt with care. It's made of [material.display_name]."
|
||||
desc = "A stool. Apply butt with care. It's made of [material.use_name]."
|
||||
|
||||
/obj/item/weapon/stool/proc/add_padding(var/padding_type)
|
||||
padding_material = get_material_by_name(padding_type)
|
||||
@@ -127,7 +126,7 @@ var/global/list/stool_cache = list() //haha stool
|
||||
padding_type = "carpet"
|
||||
else if(istype(W,/obj/item/stack/material))
|
||||
var/obj/item/stack/material/M = W
|
||||
if(M.material && (M.material.name in list("leather", "cloth")))
|
||||
if(M.material && (M.material.flags & MATERIAL_PADDING))
|
||||
padding_type = "[M.material.name]"
|
||||
if(!padding_type)
|
||||
user << "You cannot pad \the [src] with that."
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
var/mob/living/pulling = null
|
||||
var/bloodiness
|
||||
|
||||
/obj/structure/bed/chair/wheelchair/update_icon()
|
||||
return
|
||||
|
||||
/obj/structure/bed/chair/wheelchair/set_dir()
|
||||
..()
|
||||
@@ -18,6 +20,11 @@
|
||||
if(buckled_mob)
|
||||
buckled_mob.set_dir(dir)
|
||||
|
||||
/obj/structure/bed/chair/wheelchair/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(istype(W, /obj/item/weapon/wrench) || istype(W,/obj/item/stack) || istype(W, /obj/item/weapon/wirecutters))
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/structure/bed/chair/wheelchair/relaymove(mob/user, direction)
|
||||
// Redundant check?
|
||||
if(user.stat || user.stunned || user.weakened || user.paralysis || user.lying || user.restrained())
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
if(W)
|
||||
radiate()
|
||||
if(is_hot(W))
|
||||
ignite(is_hot(W))
|
||||
burn(is_hot(W))
|
||||
|
||||
if(locate(/obj/effect/overlay/wallrot) in src)
|
||||
if(istype(W, /obj/item/weapon/weldingtool) )
|
||||
|
||||
@@ -2,18 +2,17 @@
|
||||
icon_state = "rgeneric"
|
||||
/turf/simulated/wall/r_wall/New(var/newloc)
|
||||
..(newloc, DEFAULT_WALL_MATERIAL,"plasteel") //3strong
|
||||
|
||||
/turf/simulated/wall/cult
|
||||
icon_state = "cult"
|
||||
/turf/simulated/wall/cult/New(var/newloc)
|
||||
..(newloc,"cult","cult2")
|
||||
|
||||
/turf/unsimulated/wall/cult
|
||||
name = "cult wall"
|
||||
desc = "Hideous images dance beneath the surface."
|
||||
icon = 'icons/turf/wall_masks.dmi'
|
||||
icon_state = "cult"
|
||||
|
||||
|
||||
/turf/simulated/wall/iron/New(var/newloc)
|
||||
..(newloc,"iron")
|
||||
/turf/simulated/wall/uranium/New(var/newloc)
|
||||
@@ -28,7 +27,6 @@
|
||||
..(newloc,"phoron")
|
||||
/turf/simulated/wall/sandstone/New(var/newloc)
|
||||
..(newloc,"sandstone")
|
||||
|
||||
/turf/simulated/wall/ironphoron/New(var/newloc)
|
||||
..(newloc,"iron","phoron")
|
||||
/turf/simulated/wall/golddiamond/New(var/newloc)
|
||||
@@ -38,6 +36,8 @@
|
||||
/turf/simulated/wall/sandstonediamond/New(var/newloc)
|
||||
..(newloc,"sandstone","diamond")
|
||||
|
||||
|
||||
/turf/simulated/wall/cult/New(var/newloc)
|
||||
..(newloc,"cult","cult2")
|
||||
// Kind of wondering if this is going to bite me in the butt.
|
||||
/turf/simulated/wall/voxshuttle/New(var/newloc)
|
||||
..(newloc,"voxalloy")
|
||||
/turf/simulated/wall/voxshuttle/attackby()
|
||||
return
|
||||
|
||||
@@ -46,9 +46,9 @@ var/list/global/wall_cache = list()
|
||||
|
||||
/turf/simulated/wall/bullet_act(var/obj/item/projectile/Proj)
|
||||
if(istype(Proj,/obj/item/projectile/beam))
|
||||
ignite(2500)
|
||||
burn(2500)
|
||||
else if(istype(Proj,/obj/item/projectile/ion))
|
||||
ignite(500)
|
||||
burn(500)
|
||||
|
||||
// Tasers and stuff? No thanks. Also no clone or tox damage crap.
|
||||
if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
|
||||
@@ -143,10 +143,10 @@ var/list/global/wall_cache = list()
|
||||
return
|
||||
|
||||
/turf/simulated/wall/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)//Doesn't fucking work because walls don't interact with air :(
|
||||
ignite(exposed_temperature)
|
||||
burn(exposed_temperature)
|
||||
|
||||
/turf/simulated/wall/adjacent_fire_act(turf/simulated/floor/adj_turf, datum/gas_mixture/adj_air, adj_temp, adj_volume)
|
||||
ignite(adj_temp)
|
||||
burn(adj_temp)
|
||||
if(adj_temp > material.melting_point)
|
||||
take_damage(log(RAND_F(0.9, 1.1) * (adj_temp - material.melting_point)))
|
||||
|
||||
@@ -253,22 +253,11 @@ var/list/global/wall_cache = list()
|
||||
return total_radiation
|
||||
|
||||
/turf/simulated/wall/proc/burn(temperature)
|
||||
spawn(2)
|
||||
new /obj/structure/girder(src)
|
||||
src.ChangeTurf(/turf/simulated/floor)
|
||||
for(var/turf/simulated/floor/target_tile in range(0,src))
|
||||
if(material == "phoron") //ergh
|
||||
target_tile.assume_gas("phoron", 20, 400+T0C)
|
||||
spawn (0) target_tile.hotspot_expose(temperature, 400)
|
||||
for(var/turf/simulated/wall/W in range(3,src))
|
||||
W.ignite((temperature/4))
|
||||
for(var/obj/machinery/door/airlock/phoron/D in range(3,src))
|
||||
D.ignite(temperature/4)
|
||||
|
||||
/turf/simulated/wall/proc/ignite(var/exposed_temperature)
|
||||
if(isnull(material.ignition_point))
|
||||
return
|
||||
if(exposed_temperature > material.ignition_point)//If the temperature of the object is over 300, then ignite
|
||||
burn(exposed_temperature)
|
||||
return
|
||||
..()
|
||||
if(material.combustion_effect(src, temperature, 0.7))
|
||||
spawn(2)
|
||||
new /obj/structure/girder(src)
|
||||
src.ChangeTurf(/turf/simulated/floor)
|
||||
for(var/turf/simulated/wall/W in range(3,src))
|
||||
W.burn((temperature/4))
|
||||
for(var/obj/machinery/door/airlock/phoron/D in range(3,src))
|
||||
D.ignite(temperature/4)
|
||||
|
||||
@@ -16,6 +16,7 @@ var/list/accessible_z_levels = list("1" = 5, "3" = 10, "4" = 15, "5" = 10, "6" =
|
||||
if(!istype(src, /turf/space/transit))
|
||||
icon_state = "[((x + y) ^ ~(x * y) + z) % 25]"
|
||||
update_starlight()
|
||||
..()
|
||||
|
||||
/turf/space/proc/update_starlight()
|
||||
if(!config.starlight)
|
||||
|
||||
@@ -40,8 +40,13 @@
|
||||
spawn( 0 )
|
||||
src.Entered(AM)
|
||||
return
|
||||
turfs |= src
|
||||
return
|
||||
|
||||
/turf/Destroy()
|
||||
turfs -= src
|
||||
..()
|
||||
|
||||
/turf/ex_act(severity)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -112,6 +112,8 @@
|
||||
else if (R_MOD & C.holder.rights || R_MENTOR & C.holder.rights)
|
||||
modmsg += "\t[C] is a [C.holder.rank]\n"
|
||||
num_mods_online++
|
||||
|
||||
if(config.admin_irc)
|
||||
src << "<span class='info'>Adminhelps are also sent to IRC. If no admins are available in game try anyway and an admin on IRC may see it and respond.</span>"
|
||||
msg = "<b>Current Admins ([num_admins_online]):</b>\n" + msg + "\n<b> Current [config.mods_are_mentors ? "Mentors" : "Moderators"]([num_mods_online]):</b>\n" + modmsg
|
||||
|
||||
src << msg
|
||||
|
||||
@@ -997,18 +997,18 @@ var/global/floorIsLava = 0
|
||||
|
||||
return 0
|
||||
|
||||
/datum/admins/proc/spawn_fruit()
|
||||
/datum/admins/proc/spawn_fruit(seedtype in plant_controller.seeds)
|
||||
set category = "Debug"
|
||||
set desc = "Spawn the product of a seed."
|
||||
set name = "Spawn Fruit"
|
||||
|
||||
if(!check_rights(R_SPAWN)) return
|
||||
|
||||
var/seedtype = input("Select a seed type", "Spawn Fruit") as null|anything in plant_controller.seeds
|
||||
if(!seedtype || !plant_controller.seeds[seedtype])
|
||||
return
|
||||
var/datum/seed/S = plant_controller.seeds[seedtype]
|
||||
S.harvest(usr,0,0,1)
|
||||
log_admin("[key_name(usr)] spawned [seedtype] fruit at ([usr.x],[usr.y],[usr.z])")
|
||||
|
||||
/datum/admins/proc/spawn_custom_item()
|
||||
set category = "Debug"
|
||||
@@ -1050,17 +1050,17 @@ var/global/floorIsLava = 0
|
||||
for(var/datum/custom_item/item in current_items)
|
||||
usr << "- name: [item.name] icon: [item.item_icon] path: [item.item_path] desc: [item.item_desc]"
|
||||
|
||||
/datum/admins/proc/spawn_plant()
|
||||
/datum/admins/proc/spawn_plant(seedtype in plant_controller.seeds)
|
||||
set category = "Debug"
|
||||
set desc = "Spawn a spreading plant effect."
|
||||
set name = "Spawn Plant"
|
||||
|
||||
if(!check_rights(R_SPAWN)) return
|
||||
|
||||
var/seedtype = input("Select a seed type", "Spawn Plant") as null|anything in plant_controller.seeds
|
||||
if(!seedtype || !plant_controller.seeds[seedtype])
|
||||
return
|
||||
new /obj/effect/plant(get_turf(usr), plant_controller.seeds[seedtype])
|
||||
log_admin("[key_name(usr)] spawned [seedtype] vines at ([usr.x],[usr.y],[usr.z])")
|
||||
|
||||
/datum/admins/proc/spawn_atom(var/object as text)
|
||||
set category = "Debug"
|
||||
@@ -1236,7 +1236,7 @@ var/global/floorIsLava = 0
|
||||
if(!ai_number)
|
||||
usr << "<b>No AIs located</b>" //Just so you know the thing is actually working and not just ignoring you.
|
||||
|
||||
/datum/admins/proc/show_skills(var/mob/living/carbon/human/M as mob in world)
|
||||
/datum/admins/proc/show_skills()
|
||||
set category = "Admin"
|
||||
set name = "Show Skills"
|
||||
|
||||
@@ -1246,6 +1246,9 @@ var/global/floorIsLava = 0
|
||||
usr << "Error: you are not an admin!"
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/M = input("Select mob.", "Select mob.") as null|anything in human_mob_list
|
||||
if(!M) return
|
||||
|
||||
show_skill_window(usr, M)
|
||||
|
||||
return
|
||||
|
||||
@@ -123,7 +123,8 @@ var/list/admin_verbs_spawn = list(
|
||||
/client/proc/FireLaser,
|
||||
/client/proc/FireCannons,
|
||||
/client/proc/ChangeIcarusPosition,
|
||||
/client/proc/virus2_editor
|
||||
/client/proc/virus2_editor,
|
||||
/client/proc/spawn_chemdisp_cartridge
|
||||
)
|
||||
var/list/admin_verbs_server = list(
|
||||
/client/proc/Set_Holiday,
|
||||
@@ -707,66 +708,70 @@ var/list/admin_verbs_mentor = list(
|
||||
if(holder)
|
||||
src.holder.output_ai_laws()
|
||||
|
||||
/client/proc/rename_silicon(mob/living/silicon/S in mob_list)
|
||||
/client/proc/rename_silicon()
|
||||
set name = "Rename Silicon"
|
||||
set category = "Admin"
|
||||
|
||||
if(!istype(S))
|
||||
return
|
||||
if(!check_rights(R_ADMIN)) return
|
||||
|
||||
if(holder)
|
||||
var/new_name = sanitizeSafe(input(src, "Enter new name. Leave blank or as is to cancel.", "Enter new silicon name", S.real_name))
|
||||
if(new_name && new_name != S.real_name)
|
||||
admin_log_and_message_admins("has renamed the silicon '[S.real_name]' to '[new_name]'")
|
||||
S.SetName(new_name)
|
||||
var/mob/living/silicon/S = input("Select silicon.", "Rename Silicon.") as null|anything in silicon_mob_list
|
||||
if(!S) return
|
||||
|
||||
var/new_name = sanitizeSafe(input(src, "Enter new name. Leave blank or as is to cancel.", "[S.real_name] - Enter new silicon name", S.real_name))
|
||||
if(new_name && new_name != S.real_name)
|
||||
admin_log_and_message_admins("has renamed the silicon '[S.real_name]' to '[new_name]'")
|
||||
S.SetName(new_name)
|
||||
feedback_add_details("admin_verb","RAI") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/manage_silicon_laws(mob/living/silicon/S in mob_list)
|
||||
/client/proc/manage_silicon_laws()
|
||||
set name = "Manage Silicon Laws"
|
||||
set category = "Admin"
|
||||
|
||||
if(!istype(S))
|
||||
return
|
||||
if(!check_rights(R_ADMIN)) return
|
||||
|
||||
if(holder)
|
||||
var/obj/nano_module/law_manager/L = new(S)
|
||||
L.ui_interact(usr, state = admin_state)
|
||||
var/mob/living/silicon/S = input("Select silicon.", "Manage Silicon Laws") as null|anything in silicon_mob_list
|
||||
if(!S) return
|
||||
|
||||
var/obj/nano_module/law_manager/L = new(S)
|
||||
L.ui_interact(usr, state = admin_state)
|
||||
admin_log_and_message_admins("has opened [S]'s law manager.")
|
||||
feedback_add_details("admin_verb","MSL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/change_human_appearance_admin(mob/living/carbon/human/H in world)
|
||||
/client/proc/change_human_appearance_admin()
|
||||
set name = "Change Mob Appearance - Admin"
|
||||
set desc = "Allows you to change the mob appearance"
|
||||
set category = "Admin"
|
||||
|
||||
if(!istype(H))
|
||||
return
|
||||
if(!check_rights(R_FUN)) return
|
||||
|
||||
if(holder)
|
||||
admin_log_and_message_admins("is altering the appearance of [H].")
|
||||
H.change_appearance(APPEARANCE_ALL, usr, usr, check_species_whitelist = 0, state = admin_state)
|
||||
var/mob/living/carbon/human/H = input("Select mob.", "Change Mob Appearance - Admin") as null|anything in human_mob_list
|
||||
if(!H) return
|
||||
|
||||
admin_log_and_message_admins("is altering the appearance of [H].")
|
||||
H.change_appearance(APPEARANCE_ALL, usr, usr, check_species_whitelist = 0, state = admin_state)
|
||||
feedback_add_details("admin_verb","CHAA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/change_human_appearance_self(mob/living/carbon/human/H in mob_list)
|
||||
/client/proc/change_human_appearance_self()
|
||||
set name = "Change Mob Appearance - Self"
|
||||
set desc = "Allows the mob to change its appearance"
|
||||
set category = "Admin"
|
||||
|
||||
if(!istype(H))
|
||||
return
|
||||
if(!check_rights(R_FUN)) return
|
||||
|
||||
var/mob/living/carbon/human/H = input("Select mob.", "Change Mob Appearance - Self") as null|anything in human_mob_list
|
||||
if(!H) return
|
||||
|
||||
if(!H.client)
|
||||
usr << "Only mobs with clients can alter their own appearance."
|
||||
return
|
||||
|
||||
if(holder)
|
||||
switch(alert("Do you wish for [H] to be allowed to select non-whitelisted races?","Alter Mob Appearance","Yes","No","Cancel"))
|
||||
if("Yes")
|
||||
admin_log_and_message_admins("has allowed [H] to change \his appearance, without whitelisting of races.")
|
||||
H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 0)
|
||||
if("No")
|
||||
admin_log_and_message_admins("has allowed [H] to change \his appearance, with whitelisting of races.")
|
||||
H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 1)
|
||||
switch(alert("Do you wish for [H] to be allowed to select non-whitelisted races?","Alter Mob Appearance","Yes","No","Cancel"))
|
||||
if("Yes")
|
||||
admin_log_and_message_admins("has allowed [H] to change \his appearance, without whitelisting of races.")
|
||||
H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 0)
|
||||
if("No")
|
||||
admin_log_and_message_admins("has allowed [H] to change \his appearance, with whitelisting of races.")
|
||||
H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 1)
|
||||
feedback_add_details("admin_verb","CMAS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/change_security_level()
|
||||
@@ -791,12 +796,14 @@ var/list/admin_verbs_mentor = list(
|
||||
// feedback_add_details("admin_verb","MP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
return
|
||||
|
||||
/client/proc/editappear(mob/living/carbon/human/M as mob in mob_list)
|
||||
/client/proc/editappear()
|
||||
set name = "Edit Appearance"
|
||||
set category = "Fun"
|
||||
|
||||
if(!check_rights(R_FUN)) return
|
||||
|
||||
var/mob/living/carbon/human/M = input("Select mob.", "Edit Appearance") as null|anything in human_mob_list
|
||||
|
||||
if(!istype(M, /mob/living/carbon/human))
|
||||
usr << "\red You can only do this to humans!"
|
||||
return
|
||||
|
||||
@@ -2270,14 +2270,14 @@
|
||||
if("hellonearth")
|
||||
feedback_inc("admin_secrets_fun_used",1)
|
||||
feedback_add_details("admin_secrets_fun_used","NS")
|
||||
var/choice = input("You sure you want to end the round and summon narsie at your location? Misuse of this could result in removal of flags or halarity.") in list("PRAISE SATAN", "Cancel")
|
||||
var/choice = input("You sure you want to end the round and summon narsie at your location? Misuse of this could result in removal of flags or hilarity.") in list("PRAISE SATAN", "Cancel")
|
||||
if(choice == "PRAISE SATAN")
|
||||
new /obj/singularity/narsie/large(get_turf(usr))
|
||||
message_admins("[key_name_admin(usr)] has summoned narsie and brought about a new realm of suffering.")
|
||||
if("supermattercascade")
|
||||
feedback_inc("admin_secrets_fun_used",1)
|
||||
feedback_add_details("admin_secrets_fun_used","SC")
|
||||
var/choice = input("You sure you want to destroy the universe and create a large explosion at your location? Misuse of this could result in removal of flags or halarity.") in list("NO TIME TO EXPLAIN", "Cancel")
|
||||
var/choice = input("You sure you want to destroy the universe and create a large explosion at your location? Misuse of this could result in removal of flags or hilarity.") in list("NO TIME TO EXPLAIN", "Cancel")
|
||||
if(choice == "NO TIME TO EXPLAIN")
|
||||
explosion(get_turf(usr), 8, 16, 24, 32, 1)
|
||||
new /turf/unsimulated/wall/supermatter(get_turf(usr))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user