Merge remote-tracking branch 'origin/dev' into ofBotsAndMobs

This commit is contained in:
Kelenius
2015-04-26 15:47:38 +03:00
328 changed files with 8860 additions and 7586 deletions

View File

@@ -383,7 +383,6 @@
user << "You are too far away to read the gauge."
if(welded)
user << "It seems welded shut."
..()
/obj/machinery/atmospherics/unary/vent_pump/power_change()
var/old_stat = stat

View File

@@ -277,7 +277,6 @@
user << "A small gauge in the corner reads [round(last_flow_rate, 0.1)] L/s; [round(last_power_draw)] W"
else
user << "You are too far away to read the gauge."
..()
/obj/machinery/atmospherics/unary/vent_scrubber/Del()
if(initial_loc)

View File

@@ -0,0 +1,93 @@
/*
/tg/station13 /atom/movable Pool:
---------------------------------
By RemieRichards
Creation/Deletion is laggy, so let's reduce reuse and recycle!
Locked to /atom/movable and it's subtypes due to Loc being a const var on /atom
but being read&write on /movable due to how they... move.
*/
var/global/list/GlobalPool = list()
//You'll be using this proc 90% of the time.
//It grabs a type from the pool if it can
//And if it can't, it creates one
//The pool is flexible and will expand to fit
//The new created atom when it eventually
//Goes into the pool
//Second argument can be a new location
//Or a list of arguments
//Either way it gets passed to new
/proc/PoolOrNew(var/get_type,var/second_arg)
if(!get_type)
return
var/atom/movable/AM
AM = GetFromPool(get_type,second_arg)
if(!AM)
if(ispath(get_type))
if(islist(second_arg))
return new get_type (arglist(second_arg))
else
return new get_type (second_arg)
return AM
/proc/GetFromPool(var/get_type,var/second_arg)
if(!get_type)
return 0
if(isnull(GlobalPool[get_type]))
return 0
if(length(GlobalPool[get_type]) == 0)
return 0
var/atom/movable/AM = pick_n_take(GlobalPool[get_type])
if(AM)
AM.ResetVars()
if(islist(second_arg))
AM.loc = second_arg[1]
AM.New(arglist(second_arg))
else
AM.loc = second_arg
AM.New(second_arg)
return AM
return 0
/proc/PlaceInPool(var/atom/movable/AM)
if(!istype(AM))
return
if(AM in GlobalPool[AM.type])
return
if(!GlobalPool[AM.type])
GlobalPool[AM.type] = list()
GlobalPool[AM.type] |= AM
AM.Destroy()
AM.ResetVars()
/atom/movable/proc/ResetVars(var/list/exlude = list())
var/list/excluded = list("animate_movement", "loc", "locs", "parent_type", "vars", "verbs", "type") + exlude
for(var/V in vars)
if(V in excluded)
continue
vars[V] = initial(vars[V])
vars["loc"] = null

View File

@@ -27,6 +27,11 @@
if(A.name == N)
return A
return 0
/proc/get_area_master(const/O)
var/area/A = get_area(O)
if (isarea(A))
return A.master
/proc/in_range(source, user)
if(get_dist(source, user) <= 1)

View File

@@ -49,6 +49,17 @@ var/global/list/undershirt_t = list("White Tank top" = "u1", "Black Tank top" =
//Backpacks
var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Alt")
var/global/list/exclude_jobs = list(/datum/job/ai,/datum/job/cyborg)
// Visual nets
var/list/datum/visualnet/visual_nets = list()
var/datum/visualnet/camera/cameranet = new()
var/datum/visualnet/cult/cultnet = new()
// Runes
var/global/list/rune_list = new()
var/global/list/escape_list = list()
var/global/list/endgame_exits = list()
var/global/list/endgame_safespawns = list()
//////////////////////////
/////Initial Building/////
//////////////////////////

View File

@@ -30,6 +30,13 @@
return "[output][and_text][input[index]]"
/proc/ConvertReqString2List(var/list/source_list)
var/list/temp_list = params2list(source_list)
for(var/O in temp_list)
temp_list[O] = text2num(temp_list[O])
return temp_list
//Returns list element or null. Should prevent "index out of bounds" error.
proc/listgetindex(var/list/list,index)
if(istype(list) && list.len)

View File

@@ -183,7 +183,7 @@
/proc/replace_characters(var/t,var/list/repl_chars)
for(var/char in repl_chars)
replacetext(t, char, repl_chars[char])
t = replacetext(t, char, repl_chars[char])
return t
//Adds 'u' number of zeros ahead of the text 't'

View File

@@ -48,6 +48,11 @@
#define ui_monkey_mask "5:14,1:5" //monkey
#define ui_monkey_back "6:14,1:5" //monkey
#define ui_construct_health "15:00,7:15" //same height as humans, hugging the right border
#define ui_construct_purge "15:00,6:15"
#define ui_construct_fire "14:16,8:13" //above health, slightly to the left
#define ui_construct_pull "14:28,2:10" //above the zone_sel icon
//Lower right, persistant menu
#define ui_dropbutton "11:22,1:5"
#define ui_drop_throw "14:28,2:7"
@@ -119,3 +124,6 @@
#define ui_iarrowleft "SOUTH-1,11"
#define ui_iarrowright "SOUTH-1,13"
#define ui_spell_master "14:16,14:16"
#define ui_genetic_master "14:16,12:16"

View File

@@ -33,7 +33,7 @@ var/list/global_huds = list(
screen.screen_loc = "1,1"
screen.icon = 'icons/obj/hud_full.dmi'
screen.icon_state = icon_state
screen.layer = 17
screen.layer = SCREEN_LAYER
screen.mouse_opacity = 0
return screen
@@ -249,7 +249,11 @@ datum/hud/New(mob/owner)
robot_hud()
else if(isobserver(mymob))
ghost_hud()
else
mymob.instantiate_hud(src)
/mob/proc/instantiate_hud(var/datum/hud/HUD)
return
//Triggered when F12 is pressed (Unless someone changed something in the DMF)
/mob/verb/button_pressed_F12(var/full = 0 as null)

View File

@@ -101,3 +101,59 @@
mymob.client.screen += src.adding
return
/mob/living/simple_animal/construct/instantiate_hud(var/datum/hud/HUD)
HUD.construct_hud()
/datum/hud/proc/construct_hud()
var/constructtype
if(istype(mymob,/mob/living/simple_animal/construct/armoured) || istype(mymob,/mob/living/simple_animal/construct/behemoth))
constructtype = "juggernaut"
else if(istype(mymob,/mob/living/simple_animal/construct/builder))
constructtype = "artificer"
else if(istype(mymob,/mob/living/simple_animal/construct/wraith))
constructtype = "wraith"
else if(istype(mymob,/mob/living/simple_animal/construct/harvester))
constructtype = "harvester"
mymob.flash = new /obj/screen()
mymob.flash.icon = 'icons/mob/screen1.dmi'
mymob.flash.icon_state = "blank"
mymob.flash.name = "flash"
mymob.flash.screen_loc = "1,1 to 15,15"
mymob.flash.layer = 17
if(constructtype)
mymob.fire = new /obj/screen()
mymob.fire.icon = 'icons/mob/screen1_construct.dmi'
mymob.fire.icon_state = "fire0"
mymob.fire.name = "fire"
mymob.fire.screen_loc = ui_construct_fire
mymob.healths = new /obj/screen()
mymob.healths.icon = 'icons/mob/screen1_construct.dmi'
mymob.healths.icon_state = "[constructtype]_health0"
mymob.healths.name = "health"
mymob.healths.screen_loc = ui_construct_health
mymob.pullin = new /obj/screen()
mymob.pullin.icon = 'icons/mob/screen1_construct.dmi'
mymob.pullin.icon_state = "pull0"
mymob.pullin.name = "pull"
mymob.pullin.screen_loc = ui_construct_pull
mymob.zone_sel = new /obj/screen/zone_sel()
mymob.zone_sel.icon = 'icons/mob/screen1_construct.dmi'
mymob.zone_sel.overlays.len = 0
mymob.zone_sel.overlays += image('icons/mob/zone_sel.dmi', "[mymob.zone_sel.selecting]")
mymob.purged = new /obj/screen()
mymob.purged.icon = 'icons/mob/screen1_construct.dmi'
mymob.purged.icon_state = "purge0"
mymob.purged.name = "purged"
mymob.purged.screen_loc = ui_construct_purge
mymob.client.screen = null
mymob.client.screen += list(mymob.fire, mymob.healths, mymob.pullin, mymob.zone_sel, mymob.purged, mymob.flash)

View File

@@ -0,0 +1,175 @@
/obj/screen/movable/spell_master
name = "Spells"
icon = 'icons/mob/screen_spells.dmi'
icon_state = "wiz_spell_ready"
var/list/obj/screen/spell/spell_objects = list()
var/showing = 0
var/open_state = "master_open"
var/closed_state = "master_closed"
screen_loc = ui_spell_master
var/mob/spell_holder
/obj/screen/movable/spell_master/MouseDrop()
if(showing)
return
return ..()
/obj/screen/movable/spell_master/Click()
if(!spell_objects.len)
qdel(src)
return
toggle_open()
/obj/screen/movable/spell_master/proc/toggle_open(var/forced_state = 0)
if(showing && (forced_state != 2))
for(var/obj/screen/spell/O in spell_objects)
if(spell_holder && spell_holder.client)
spell_holder.client.screen -= O
O.handle_icon_updates = 0
showing = 0
overlays.len = 0
overlays.Add(closed_state)
else if(forced_state != 1)
var/temp_loc = screen_loc
var/x_position = text2num(copytext(temp_loc, 1, findtext(temp_loc, ":")))
var/x_pix = text2num(copytext(temp_loc, findtext(temp_loc, ":") + 1, findtext(temp_loc, ",")))
temp_loc = copytext(temp_loc, findtext(temp_loc, ",") + 1)
var/y_position = text2num(copytext(temp_loc, 1, findtext(temp_loc, ":")))
var/y_pix = text2num(copytext(temp_loc, findtext(temp_loc, ":")+1))
for(var/i = 1; i <= spell_objects.len; i++)
var/obj/screen/spell/S = spell_objects[i]
S.screen_loc = "[x_position + (x_position < 8 ? 1 : -1)*(i%7)]:[x_pix],[y_position + (y_position < 8 ? round(i/7) : -round(i/7))]:[y_pix]"
if(spell_holder && spell_holder.client)
spell_holder.client.screen += S
S.handle_icon_updates = 1
update_spells(1)
showing = 1
overlays.len = 0
overlays.Add(open_state)
/obj/screen/movable/spell_master/proc/add_spell(var/spell/spell)
if(!spell) return
for(var/obj/screen/spell/spellscreen in spell_objects)
if(spellscreen.spell == spell)
return
if(spell.spell_flags & NO_BUTTON) //no button to add if we don't get one
return
var/obj/screen/spell/newscreen = new
newscreen.spell = spell
if(!spell.override_base) //if it's not set, we do basic checks
if(spell.spell_flags & CONSTRUCT_CHECK)
newscreen.spell_base = "const" //construct spells
else
newscreen.spell_base = "wiz" //wizard spells
else
newscreen.spell_base = spell.override_base
newscreen.name = spell.name
newscreen.update_charge(1)
spell_objects.Add(newscreen)
toggle_open(2) //forces the icons to refresh on screen
/obj/screen/movable/spell_master/proc/remove_spell(var/spell/spell)
for(var/obj/screen/spell/s_object in spell_objects)
if(s_object.spell == spell)
spell_objects.Remove(s_object)
qdel(s_object)
break
if(spell_objects.len)
toggle_open(showing + 1)
else
spell_holder.spell_masters.Remove(src)
qdel(src)
/obj/screen/movable/spell_master/proc/silence_spells(var/amount)
for(var/obj/screen/spell/spell in spell_objects)
spell.spell.silenced = amount
spell.update_charge(1)
/obj/screen/movable/spell_master/proc/update_spells(forced = 0, mob/user)
if(user && user.client)
if(!(src in user.client.screen))
user.client.screen += src
for(var/obj/screen/spell/spell in spell_objects)
spell.update_charge(forced)
/obj/screen/movable/spell_master/genetic
name = "Mutant Powers"
icon_state = "genetic_spell_ready"
open_state = "genetics_open"
closed_state = "genetics_closed"
screen_loc = ui_genetic_master
//////////////ACTUAL SPELLS//////////////
//This is what you click to cast things//
/////////////////////////////////////////
/obj/screen/spell
icon = 'icons/mob/screen_spells.dmi'
icon_state = "wiz_spell_base"
var/spell_base = "wiz"
var/last_charge = 0 //not a time, but the last remembered charge value
var/spell/spell = null
var/handle_icon_updates = 0
var/icon/last_charged_icon
/obj/screen/spell/proc/update_charge(var/forced_update = 0)
if(!spell)
qdel(src)
return
if((last_charge == spell.charge_counter || !handle_icon_updates) && !forced_update)
return //nothing to see here
overlays -= spell.hud_state
if(spell.charge_type == Sp_RECHARGE || spell.charge_type == Sp_CHARGES)
if(spell.charge_counter < spell.charge_max)
icon_state = "[spell_base]_spell_base"
if(spell.charge_counter > 0)
var/icon/partial_charge = icon(src.icon, "[spell_base]_spell_ready")
partial_charge.Crop(1, 1, partial_charge.Width(), round(partial_charge.Height() * spell.charge_counter / spell.charge_max))
overlays += partial_charge
if(last_charged_icon)
overlays -= last_charged_icon
last_charged_icon = partial_charge
else if(last_charged_icon)
overlays -= last_charged_icon
last_charged_icon = null
else
icon_state = "[spell_base]_spell_ready"
if(last_charged_icon)
overlays -= last_charged_icon
else
icon_state = "[spell_base]_spell_ready"
overlays += spell.hud_state
last_charge = spell.charge_counter
overlays -= "silence"
if(spell.silenced)
overlays += "silence"
/obj/screen/spell/Click()
if(!usr || !spell)
qdel(src)
return
spell.perform(usr)
update_charge(1)

View File

@@ -0,0 +1,160 @@
var/datum/controller/process/garbage_collector/garbage_collector
// #define GC_DEBUG 1
/datum/controller/process/garbage_collector
var/collection_timeout = 300 //deciseconds to wait to let running procs finish before we just say fuck it and force del() the object
var/max_checks_multiplier = 5 //multiplier (per-decisecond) for calculating max number of tests per SS tick. These tests check if our GC'd objects are actually GC'd
var/max_forcedel_multiplier = 1 //multiplier (per-decisecond) for calculating max number of force del() calls per SS tick.
var/dels = 0 // number of del()'s we've done this tick
var/list/destroyed = list() // list of refID's of things that should be garbage collected
// refID's are associated with the time at which they time out and need to be manually del()
// we do this so we aren't constantly locating them and preventing them from being gc'd
var/list/logging = list() // list of all types that have failed to GC associated with the number of times that's happened.
// the types are stored as strings
/datum/controller/process/garbage_collector/setup()
name = "garbage"
schedule_interval = 60 // every 6 seconds
if(!garbage_collector)
garbage_collector = src
/datum/controller/process/garbage_collector/doWork()
dels = 0
var/time_to_kill = world.time - collection_timeout // Anything qdel() but not GC'd BEFORE this time needs to be manually del()
var/checkRemain = max_checks_multiplier * schedule_interval
var/maxDels = max_forcedel_multiplier * schedule_interval
while(destroyed.len && --checkRemain >= 0)
if(dels >= maxDels)
#ifdef GC_DEBUG
testing("GC: Reached max force dels per tick [dels] vs [GC_FORCE_DEL_PER_TICK]")
#endif
break // Server's already pretty pounded, everything else can wait 2 seconds
var/refID = destroyed[1]
var/GCd_at_time = destroyed[refID]
if(GCd_at_time > time_to_kill)
#ifdef GC_DEBUG
testing("GC: [refID] not old enough, breaking at [world.time] for [GCd_at_time - time_to_kill] deciseconds until [GCd_at_time + GC_COLLECTION_TIMEOUT]")
#endif
break // Everything else is newer, skip them
var/atom/A = locate(refID)
#ifdef GC_DEBUG
testing("GC: [refID] old enough to test: GCd_at_time: [GCd_at_time] time_to_kill: [time_to_kill] current: [world.time]")
#endif
if(A && A.gc_destroyed == GCd_at_time) // So if something else coincidently gets the same ref, it's not deleted by mistake
// Something's still referring to the qdel'd object. Kill it.
testing("GC: -- \ref[A] | [A.type] was unable to be GC'd and was deleted --")
logging["[A.type]"]++
del(A)
++dels
#ifdef GC_DEBUG
else
testing("GC: [refID] properly GC'd at [world.time] with timeout [GCd_at_time]")
#endif
destroyed.Cut(1, 2)
scheck()
/datum/controller/process/garbage_collector/proc/AddTrash(datum/A)
if(!istype(A) || !isnull(A.gc_destroyed))
return
#ifdef GC_DEBUG
testing("GC: AddTrash([A.type])")
#endif
A.gc_destroyed = world.time
destroyed -= "\ref[A]" // Removing any previous references that were GC'd so that the current object will be at the end of the list.
destroyed["\ref[A]"] = world.time
// Should be treated as a replacement for the 'del' keyword.
// Datums passed to this will be given a chance to clean up references to allow the GC to collect them.
/proc/qdel(var/datum/A)
if(!A)
return
if(!istype(A))
//warning("qdel() passed object of type [A.type]. qdel() can only handle /datum types.")
del(A)
garbage_collector.dels++
else if(isnull(A.gc_destroyed))
// Let our friend know they're about to get fucked up.
. = !A.Destroy()
if(. && A)
A.finalize_qdel()
/datum/proc/finalize_qdel()
del(src)
/turf/finalize_qdel()
garbage_collector.AddTrash(src)
// Default implementation of clean-up code.
// This should be overridden to remove all references pointing to the object being destroyed.
// Return true if the the GC controller should allow the object to continue existing. (Useful if pooling objects.)
/datum/proc/Destroy()
return
/datum/var/gc_destroyed //Time when this object was destroyed.
#ifdef TESTING
/client/var/running_find_references
/atom/verb/find_references()
set category = "Debug"
set name = "Find References"
set background = 1
set src in world
if(!usr || !usr.client)
return
if(usr.client.running_find_references)
testing("CANCELLED search for references to a [usr.client.running_find_references].")
usr.client.running_find_references = null
return
if(alert("Running this will create a lot of lag until it finishes. You can cancel it by running it again. Would you like to begin the search?", "Find References", "Yes", "No") == "No")
return
// Remove this object from the list of things to be auto-deleted.
if(garbage)
garbage.destroyed -= "\ref[src]"
usr.client.running_find_references = type
testing("Beginning search for references to a [type].")
var/list/things = list()
for(var/client/thing)
things += thing
for(var/datum/thing)
things += thing
for(var/atom/thing)
things += thing
testing("Collected list of things in search for references to a [type]. ([things.len] Thing\s)")
for(var/datum/thing in things)
if(!usr.client.running_find_references) return
for(var/varname in thing.vars)
var/variable = thing.vars[varname]
if(variable == src)
testing("Found [src.type] \ref[src] in [thing.type]'s [varname] var.")
else if(islist(variable))
if(src in variable)
testing("Found [src.type] \ref[src] in [thing.type]'s [varname] list var.")
testing("Completed search for references to a [type].")
usr.client.running_find_references = null
/client/verb/purge_all_destroyed_objects()
set category = "Debug"
if(garbage)
while(garbage.destroyed.len)
var/datum/o = locate(garbage.destroyed[1])
if(istype(o) && o.gc_destroyed)
del(o)
garbage.dels++
garbage.destroyed.Cut(1, 2)
#endif
#ifdef GC_DEBUG
#undef GC_DEBUG
#endif

View File

@@ -3,7 +3,7 @@
/datum/controller/process/nanoui/setup()
name = "nanoui"
schedule_interval = 20 // every 2 seconds
schedule_interval = 10 // every 1 second
updateQueueInstance = new
/datum/controller/process/nanoui/doWork()

View File

@@ -0,0 +1,9 @@
var/global/list/processing_turfs = list()
/datum/controller/process/turf/setup()
name = "turf"
schedule_interval = 20 // every 2 seconds
/datum/controller/process/turf/doWork()
for(var/turf/unsimulated/wall/supermatter/SM in processing_turfs)
SM.process()

View File

@@ -323,6 +323,7 @@ turf/proc/shift_to_subarea()
A.SetLightLevel(level, color_light)
A.contents += src // move the turf into the area
universe.OnTurfTick(src)
// Dedicated lighting sublevel for space turfs
// helps us depower things in space, remove space fire alarms,

View File

@@ -114,6 +114,8 @@ var/global/datum/emergency_shuttle_controller/emergency_shuttle
priority_announcement.Announce("The scheduled crew transfer has been cancelled.")
/datum/emergency_shuttle_controller/proc/can_call()
if (!universe.OnShuttleCall(null))
return 0
if (deny_shuttle)
return 0
if (shuttle.moving_status != SHUTTLE_IDLE || !shuttle.location) //must be idle at centcom

View File

@@ -99,6 +99,16 @@
add_inherent_law("Interfere with no being that is not a fellow drone.")
..()
/datum/ai_laws/construction_drone
name = "Construction Protocols"
law_header = "Construction Protocols"
selectable = 1
/datum/ai_laws/construction_drone/New()
add_inherent_law("Repair, refit and upgrade your assigned vessel.")
add_inherent_law("Prevent unplanned damage to your assigned vessel wherever possible.")
..()
/******************** T.Y.R.A.N.T. ********************/
/datum/ai_laws/tyrant
name = "T.Y.R.A.N.T."

View File

@@ -1,988 +0,0 @@
// reference: /client/proc/modify_variables(var/atom/O, var/param_var_name = null, var/autodetect_class = 0)
client
proc/debug_variables(datum/D in world)
set category = "Debug"
set name = "View Variables"
//set src in world
if(!usr.client || !usr.client.holder)
usr << "\red You need to be an administrator to access this."
return
var/title = ""
var/body = ""
if(!D) return
if(istype(D, /atom))
var/atom/A = D
title = "[A.name] (\ref[A]) = [A.type]"
#ifdef VARSICON
if (A.icon)
body += debug_variable("icon", new/icon(A.icon, A.icon_state, A.dir), 0)
#endif
var/icon/sprite
if(istype(D,/atom))
var/atom/AT = D
if(AT.icon && AT.icon_state)
sprite = new /icon(AT.icon, AT.icon_state)
usr << browse_rsc(sprite, "view_vars_sprite.png")
title = "[D] (\ref[D]) = [D.type]"
body += {"<script type="text/javascript">
function updateSearch(){
var filter_text = document.getElementById('filter');
var filter = filter_text.value.toLowerCase();
if(event.keyCode == 13){ //Enter / return
var vars_ol = document.getElementById('vars');
var lis = vars_ol.getElementsByTagName("li");
for ( var i = 0; i < lis.length; ++i )
{
try{
var li = lis\[i\];
if ( li.style.backgroundColor == "#ffee88" )
{
alist = lis\[i\].getElementsByTagName("a")
if(alist.length > 0){
location.href=alist\[0\].href;
}
}
}catch(err) { }
}
return
}
if(event.keyCode == 38){ //Up arrow
var vars_ol = document.getElementById('vars');
var lis = vars_ol.getElementsByTagName("li");
for ( var i = 0; i < lis.length; ++i )
{
try{
var li = lis\[i\];
if ( li.style.backgroundColor == "#ffee88" )
{
if( (i-1) >= 0){
var li_new = lis\[i-1\];
li.style.backgroundColor = "white";
li_new.style.backgroundColor = "#ffee88";
return
}
}
}catch(err) { }
}
return
}
if(event.keyCode == 40){ //Down arrow
var vars_ol = document.getElementById('vars');
var lis = vars_ol.getElementsByTagName("li");
for ( var i = 0; i < lis.length; ++i )
{
try{
var li = lis\[i\];
if ( li.style.backgroundColor == "#ffee88" )
{
if( (i+1) < lis.length){
var li_new = lis\[i+1\];
li.style.backgroundColor = "white";
li_new.style.backgroundColor = "#ffee88";
return
}
}
}catch(err) { }
}
return
}
//This part here resets everything to how it was at the start so the filter is applied to the complete list. Screw efficiency, it's client-side anyway and it only looks through 200 or so variables at maximum anyway (mobs).
if(complete_list != null && complete_list != ""){
var vars_ol1 = document.getElementById("vars");
vars_ol1.innerHTML = complete_list
}
if(filter.value == ""){
return;
}else{
var vars_ol = document.getElementById('vars');
var lis = vars_ol.getElementsByTagName("li");
for ( var i = 0; i < lis.length; ++i )
{
try{
var li = lis\[i\];
if ( li.innerText.toLowerCase().indexOf(filter) == -1 )
{
vars_ol.removeChild(li);
i--;
}
}catch(err) { }
}
}
var lis_new = vars_ol.getElementsByTagName("li");
for ( var j = 0; j < lis_new.length; ++j )
{
var li1 = lis\[j\];
if (j == 0){
li1.style.backgroundColor = "#ffee88";
}else{
li1.style.backgroundColor = "white";
}
}
}
function selectTextField(){
var filter_text = document.getElementById('filter');
filter_text.focus();
filter_text.select();
}
function loadPage(list) {
if(list.options\[list.selectedIndex\].value == ""){
return;
}
location.href=list.options\[list.selectedIndex\].value;
}
</script> "}
body += "<body onload='selectTextField(); updateSearch()' onkeyup='updateSearch()'>"
body += "<div align='center'><table width='100%'><tr><td width='50%'>"
if(sprite)
body += "<table align='center' width='100%'><tr><td><img src='view_vars_sprite.png'></td><td>"
else
body += "<table align='center' width='100%'><tr><td>"
body += "<div align='center'>"
if(istype(D,/atom))
var/atom/A = D
if(isliving(A))
body += "<a href='?_src_=vars;rename=\ref[D]'><b>[D]</b></a>"
if(A.dir)
body += "<br><font size='1'><a href='?_src_=vars;rotatedatum=\ref[D];rotatedir=left'><<</a> <a href='?_src_=vars;datumedit=\ref[D];varnameedit=dir'>[dir2text(A.dir)]</a> <a href='?_src_=vars;rotatedatum=\ref[D];rotatedir=right'>>></a></font>"
var/mob/living/M = A
body += "<br><font size='1'><a href='?_src_=vars;datumedit=\ref[D];varnameedit=ckey'>[M.ckey ? M.ckey : "No ckey"]</a> / <a href='?_src_=vars;datumedit=\ref[D];varnameedit=real_name'>[M.real_name ? M.real_name : "No real name"]</a></font>"
body += {"
<br><font size='1'>
BRUTE:<font size='1'><a href='?_src_=vars;mobToDamage=\ref[D];adjustDamage=brute'>[M.getBruteLoss()]</a>
FIRE:<font size='1'><a href='?_src_=vars;mobToDamage=\ref[D];adjustDamage=fire'>[M.getFireLoss()]</a>
TOXIN:<font size='1'><a href='?_src_=vars;mobToDamage=\ref[D];adjustDamage=toxin'>[M.getToxLoss()]</a>
OXY:<font size='1'><a href='?_src_=vars;mobToDamage=\ref[D];adjustDamage=oxygen'>[M.getOxyLoss()]</a>
CLONE:<font size='1'><a href='?_src_=vars;mobToDamage=\ref[D];adjustDamage=clone'>[M.getCloneLoss()]</a>
BRAIN:<font size='1'><a href='?_src_=vars;mobToDamage=\ref[D];adjustDamage=brain'>[M.getBrainLoss()]</a>
</font>
"}
else
body += "<a href='?_src_=vars;datumedit=\ref[D];varnameedit=name'><b>[D]</b></a>"
if(A.dir)
body += "<br><font size='1'><a href='?_src_=vars;rotatedatum=\ref[D];rotatedir=left'><<</a> <a href='?_src_=vars;datumedit=\ref[D];varnameedit=dir'>[dir2text(A.dir)]</a> <a href='?_src_=vars;rotatedatum=\ref[D];rotatedir=right'>>></a></font>"
else
body += "<b>[D]</b>"
body += "</div>"
body += "</tr></td></table>"
var/formatted_type = text("[D.type]")
if(length(formatted_type) > 25)
var/middle_point = length(formatted_type) / 2
var/splitpoint = findtext(formatted_type,"/",middle_point)
if(splitpoint)
formatted_type = "[copytext(formatted_type,1,splitpoint)]<br>[copytext(formatted_type,splitpoint)]"
else
formatted_type = "Type too long" //No suitable splitpoint (/) found.
body += "<div align='center'><b><font size='1'>[formatted_type]</font></b>"
if(src.holder && src.holder.marked_datum && src.holder.marked_datum == D)
body += "<br><font size='1' color='red'><b>Marked Object</b></font>"
body += "</div>"
body += "</div></td>"
body += "<td width='50%'><div align='center'><a href='?_src_=vars;datumrefresh=\ref[D]'>Refresh</a>"
//if(ismob(D))
// body += "<br><a href='?_src_=vars;mob_player_panel=\ref[D]'>Show player panel</a></div></td></tr></table></div><hr>"
body += {" <form>
<select name="file" size="1"
onchange="loadPage(this.form.elements\[0\])"
target="_parent._top"
onmouseclick="this.focus()"
style="background-color:#ffffff">
"}
body += {" <option value>Select option</option>
<option value> </option>
"}
body += "<option value='?_src_=vars;mark_object=\ref[D]'>Mark Object</option>"
if(ismob(D))
body += "<option value='?_src_=vars;mob_player_panel=\ref[D]'>Show player panel</option>"
body += "<option value>---</option>"
if(ismob(D))
body += "<option value='?_src_=vars;give_spell=\ref[D]'>Give Spell</option>"
body += "<option value='?_src_=vars;give_disease2=\ref[D]'>Give Disease</option>"
body += "<option value='?_src_=vars;give_disease=\ref[D]'>Give TG-style Disease</option>"
body += "<option value='?_src_=vars;godmode=\ref[D]'>Toggle Godmode</option>"
body += "<option value='?_src_=vars;build_mode=\ref[D]'>Toggle Build Mode</option>"
body += "<option value='?_src_=vars;ninja=\ref[D]'>Make Space Ninja</option>"
body += "<option value='?_src_=vars;make_skeleton=\ref[D]'>Make 2spooky</option>"
body += "<option value='?_src_=vars;direct_control=\ref[D]'>Assume Direct Control</option>"
body += "<option value='?_src_=vars;drop_everything=\ref[D]'>Drop Everything</option>"
body += "<option value='?_src_=vars;regenerateicons=\ref[D]'>Regenerate Icons</option>"
body += "<option value='?_src_=vars;addlanguage=\ref[D]'>Add Language</option>"
body += "<option value='?_src_=vars;remlanguage=\ref[D]'>Remove Language</option>"
body += "<option value='?_src_=vars;addorgan=\ref[D]'>Add Organ</option>"
body += "<option value='?_src_=vars;remorgan=\ref[D]'>Remove Organ</option>"
body += "<option value='?_src_=vars;fix_nano=\ref[D]'>Fix NanoUI</option>"
body += "<option value='?_src_=vars;addverb=\ref[D]'>Add Verb</option>"
body += "<option value='?_src_=vars;remverb=\ref[D]'>Remove Verb</option>"
if(ishuman(D))
body += "<option value>---</option>"
body += "<option value='?_src_=vars;setspecies=\ref[D]'>Set Species</option>"
body += "<option value='?_src_=vars;makeai=\ref[D]'>Make AI</option>"
body += "<option value='?_src_=vars;makerobot=\ref[D]'>Make cyborg</option>"
body += "<option value='?_src_=vars;makemonkey=\ref[D]'>Make monkey</option>"
body += "<option value='?_src_=vars;makealien=\ref[D]'>Make alien</option>"
body += "<option value='?_src_=vars;makeslime=\ref[D]'>Make slime</option>"
body += "<option value>---</option>"
body += "<option value='?_src_=vars;gib=\ref[D]'>Gib</option>"
if(isobj(D))
body += "<option value='?_src_=vars;delall=\ref[D]'>Delete all of type</option>"
if(isobj(D) || ismob(D) || isturf(D))
body += "<option value='?_src_=vars;explode=\ref[D]'>Trigger explosion</option>"
body += "<option value='?_src_=vars;emp=\ref[D]'>Trigger EM pulse</option>"
body += "</select></form>"
body += "</div></td></tr></table></div><hr>"
body += "<font size='1'><b>E</b> - Edit, tries to determine the variable type by itself.<br>"
body += "<b>C</b> - Change, asks you for the var type first.<br>"
body += "<b>M</b> - Mass modify: changes this variable for all objects of this type.</font><br>"
body += "<hr><table width='100%'><tr><td width='20%'><div align='center'><b>Search:</b></div></td><td width='80%'><input type='text' id='filter' name='filter_text' value='' style='width:100%;'></td></tr></table><hr>"
body += "<ol id='vars'>"
var/list/names = list()
for (var/V in D.vars)
names += V
names = sortList(names)
for (var/V in names)
body += debug_variable(V, D.vars[V], 0, D)
body += "</ol>"
var/html = "<html><head>"
if (title)
html += "<title>[title]</title>"
html += {"<style>
body
{
font-family: Verdana, sans-serif;
font-size: 9pt;
}
.value
{
font-family: "Courier New", monospace;
font-size: 8pt;
}
</style>"}
html += "</head><body>"
html += body
html += {"
<script type='text/javascript'>
var vars_ol = document.getElementById("vars");
var complete_list = vars_ol.innerHTML;
</script>
"}
html += "</body></html>"
usr << browse(html, "window=variables\ref[D];size=475x650")
return
proc/debug_variable(name, value, level, var/datum/DA = null)
var/html = ""
if(DA)
html += "<li style='backgroundColor:white'>(<a href='?_src_=vars;datumedit=\ref[DA];varnameedit=[name]'>E</a>) (<a href='?_src_=vars;datumchange=\ref[DA];varnamechange=[name]'>C</a>) (<a href='?_src_=vars;datummass=\ref[DA];varnamemass=[name]'>M</a>) "
else
html += "<li>"
if (isnull(value))
html += "[name] = <span class='value'>null</span>"
else if (istext(value))
html += "[name] = <span class='value'>\"[value]\"</span>"
else if (isicon(value))
#ifdef VARSICON
var/icon/I = new/icon(value)
var/rnd = rand(1,10000)
var/rname = "tmp\ref[I][rnd].png"
usr << browse_rsc(I, rname)
html += "[name] = (<span class='value'>[value]</span>) <img class=icon src=\"[rname]\">"
#else
html += "[name] = /icon (<span class='value'>[value]</span>)"
#endif
/* else if (istype(value, /image))
#ifdef VARSICON
var/rnd = rand(1, 10000)
var/image/I = value
src << browse_rsc(I.icon, "tmp\ref[value][rnd].png")
html += "[name] = <img src=\"tmp\ref[value][rnd].png\">"
#else
html += "[name] = /image (<span class='value'>[value]</span>)"
#endif
*/
else if (isfile(value))
html += "[name] = <span class='value'>'[value]'</span>"
else if (istype(value, /datum))
var/datum/D = value
html += "<a href='?_src_=vars;Vars=\ref[value]'>[name] \ref[value]</a> = [D.type]"
else if (istype(value, /client))
var/client/C = value
html += "<a href='?_src_=vars;Vars=\ref[value]'>[name] \ref[value]</a> = [C] [C.type]"
//
else if (istype(value, /list))
var/list/L = value
html += "[name] = /list ([L.len])"
if (L.len > 0 && !(name == "underlays" || name == "overlays" || name == "vars" || L.len > 500))
// not sure if this is completely right...
if(0) //(L.vars.len > 0)
html += "<ol>"
html += "</ol>"
else
html += "<ul>"
var/index = 1
for (var/entry in L)
if(istext(entry))
html += debug_variable(entry, L[entry], level + 1)
//html += debug_variable("[index]", L[index], level + 1)
else
html += debug_variable(index, L[index], level + 1)
index++
html += "</ul>"
else
html += "[name] = <span class='value'>[value]</span>"
html += "</li>"
return html
/client/proc/view_var_Topic(href, href_list, hsrc)
//This should all be moved over to datum/admins/Topic() or something ~Carn
if( (usr.client != src) || !src.holder )
return
if(href_list["Vars"])
debug_variables(locate(href_list["Vars"]))
//~CARN: for renaming mobs (updates their name, real_name, mind.name, their ID/PDA and datacore records).
else if(href_list["rename"])
if(!check_rights(R_VAREDIT)) return
var/mob/M = locate(href_list["rename"])
if(!istype(M))
usr << "This can only be used on instances of type /mob"
return
var/new_name = sanitize(input(usr,"What would you like to name this mob?","Input a name",M.real_name) as text|null, MAX_NAME_LEN)
if( !new_name || !M ) return
message_admins("Admin [key_name_admin(usr)] renamed [key_name_admin(M)] to [new_name].")
M.fully_replace_character_name(M.real_name,new_name)
href_list["datumrefresh"] = href_list["rename"]
else if(href_list["varnameedit"] && href_list["datumedit"])
if(!check_rights(R_VAREDIT)) return
var/D = locate(href_list["datumedit"])
if(!istype(D,/datum) && !istype(D,/client))
usr << "This can only be used on instances of types /client or /datum"
return
modify_variables(D, href_list["varnameedit"], 1)
else if(href_list["varnamechange"] && href_list["datumchange"])
if(!check_rights(R_VAREDIT)) return
var/D = locate(href_list["datumchange"])
if(!istype(D,/datum) && !istype(D,/client))
usr << "This can only be used on instances of types /client or /datum"
return
modify_variables(D, href_list["varnamechange"], 0)
else if(href_list["varnamemass"] && href_list["datummass"])
if(!check_rights(R_VAREDIT)) return
var/atom/A = locate(href_list["datummass"])
if(!istype(A))
usr << "This can only be used on instances of type /atom"
return
cmd_mass_modify_object_variables(A, href_list["varnamemass"])
else if(href_list["mob_player_panel"])
if(!check_rights(0)) return
var/mob/M = locate(href_list["mob_player_panel"])
if(!istype(M))
usr << "This can only be used on instances of type /mob"
return
src.holder.show_player_panel(M)
href_list["datumrefresh"] = href_list["mob_player_panel"]
else if(href_list["give_spell"])
if(!check_rights(R_ADMIN|R_FUN)) return
var/mob/M = locate(href_list["give_spell"])
if(!istype(M))
usr << "This can only be used on instances of type /mob"
return
src.give_spell(M)
href_list["datumrefresh"] = href_list["give_spell"]
else if(href_list["give_disease"])
if(!check_rights(R_ADMIN|R_FUN)) return
var/mob/M = locate(href_list["give_disease"])
if(!istype(M))
usr << "This can only be used on instances of type /mob"
return
src.give_disease(M)
href_list["datumrefresh"] = href_list["give_spell"]
else if(href_list["give_disease2"])
if(!check_rights(R_ADMIN|R_FUN)) return
var/mob/M = locate(href_list["give_disease2"])
if(!istype(M))
usr << "This can only be used on instances of type /mob"
return
src.give_disease2(M)
href_list["datumrefresh"] = href_list["give_spell"]
else if(href_list["godmode"])
if(!check_rights(R_REJUVINATE)) return
var/mob/M = locate(href_list["godmode"])
if(!istype(M))
usr << "This can only be used on instances of type /mob"
return
src.cmd_admin_godmode(M)
href_list["datumrefresh"] = href_list["godmode"]
else if(href_list["gib"])
if(!check_rights(0)) return
var/mob/M = locate(href_list["gib"])
if(!istype(M))
usr << "This can only be used on instances of type /mob"
return
src.cmd_admin_gib(M)
else if(href_list["build_mode"])
if(!check_rights(R_BUILDMODE)) return
var/mob/M = locate(href_list["build_mode"])
if(!istype(M))
usr << "This can only be used on instances of type /mob"
return
togglebuildmode(M)
href_list["datumrefresh"] = href_list["build_mode"]
else if(href_list["drop_everything"])
if(!check_rights(R_DEBUG|R_ADMIN)) return
var/mob/M = locate(href_list["drop_everything"])
if(!istype(M))
usr << "This can only be used on instances of type /mob"
return
if(usr.client)
usr.client.cmd_admin_drop_everything(M)
else if(href_list["direct_control"])
if(!check_rights(0)) return
var/mob/M = locate(href_list["direct_control"])
if(!istype(M))
usr << "This can only be used on instances of type /mob"
return
if(usr.client)
usr.client.cmd_assume_direct_control(M)
else if(href_list["make_skeleton"])
if(!check_rights(R_FUN)) return
var/mob/living/carbon/human/H = locate(href_list["make_skeleton"])
if(!istype(H))
usr << "This can only be used on instances of type /mob/living/carbon/human"
return
H.ChangeToSkeleton()
href_list["datumrefresh"] = href_list["make_skeleton"]
else if(href_list["delall"])
if(!check_rights(R_DEBUG|R_SERVER)) return
var/obj/O = locate(href_list["delall"])
if(!isobj(O))
usr << "This can only be used on instances of type /obj"
return
var/action_type = alert("Strict type ([O.type]) or type and all subtypes?",,"Strict type","Type and subtypes","Cancel")
if(action_type == "Cancel" || !action_type)
return
if(alert("Are you really sure you want to delete all objects of type [O.type]?",,"Yes","No") != "Yes")
return
if(alert("Second confirmation required. Delete?",,"Yes","No") != "Yes")
return
var/O_type = O.type
switch(action_type)
if("Strict type")
var/i = 0
for(var/obj/Obj in world)
if(Obj.type == O_type)
i++
del(Obj)
if(!i)
usr << "No objects of this type exist"
return
log_admin("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted) ")
message_admins("\blue [key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted) ")
if("Type and subtypes")
var/i = 0
for(var/obj/Obj in world)
if(istype(Obj,O_type))
i++
del(Obj)
if(!i)
usr << "No objects of this type exist"
return
log_admin("[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted) ")
message_admins("\blue [key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted) ")
else if(href_list["explode"])
if(!check_rights(R_DEBUG|R_FUN)) return
var/atom/A = locate(href_list["explode"])
if(!isobj(A) && !ismob(A) && !isturf(A))
usr << "This can only be done to instances of type /obj, /mob and /turf"
return
src.cmd_admin_explosion(A)
href_list["datumrefresh"] = href_list["explode"]
else if(href_list["emp"])
if(!check_rights(R_DEBUG|R_FUN)) return
var/atom/A = locate(href_list["emp"])
if(!isobj(A) && !ismob(A) && !isturf(A))
usr << "This can only be done to instances of type /obj, /mob and /turf"
return
src.cmd_admin_emp(A)
href_list["datumrefresh"] = href_list["emp"]
else if(href_list["mark_object"])
if(!check_rights(0)) return
var/datum/D = locate(href_list["mark_object"])
if(!istype(D))
usr << "This can only be done to instances of type /datum"
return
src.holder.marked_datum = D
href_list["datumrefresh"] = href_list["mark_object"]
else if(href_list["rotatedatum"])
if(!check_rights(0)) return
var/atom/A = locate(href_list["rotatedatum"])
if(!istype(A))
usr << "This can only be done to instances of type /atom"
return
switch(href_list["rotatedir"])
if("right") A.set_dir(turn(A.dir, -45))
if("left") A.set_dir(turn(A.dir, 45))
href_list["datumrefresh"] = href_list["rotatedatum"]
else if(href_list["makemonkey"])
if(!check_rights(R_SPAWN)) return
var/mob/living/carbon/human/H = locate(href_list["makemonkey"])
if(!istype(H))
usr << "This can only be done to instances of type /mob/living/carbon/human"
return
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return
if(!H)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("monkeyone"=href_list["makemonkey"]))
else if(href_list["makerobot"])
if(!check_rights(R_SPAWN)) return
var/mob/living/carbon/human/H = locate(href_list["makerobot"])
if(!istype(H))
usr << "This can only be done to instances of type /mob/living/carbon/human"
return
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return
if(!H)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("makerobot"=href_list["makerobot"]))
else if(href_list["makealien"])
if(!check_rights(R_SPAWN)) return
var/mob/living/carbon/human/H = locate(href_list["makealien"])
if(!istype(H))
usr << "This can only be done to instances of type /mob/living/carbon/human"
return
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return
if(!H)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("makealien"=href_list["makealien"]))
else if(href_list["makeslime"])
if(!check_rights(R_SPAWN)) return
var/mob/living/carbon/human/H = locate(href_list["makeslime"])
if(!istype(H))
usr << "This can only be done to instances of type /mob/living/carbon/human"
return
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return
if(!H)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("makeslime"=href_list["makeslime"]))
else if(href_list["makeai"])
if(!check_rights(R_SPAWN)) return
var/mob/living/carbon/human/H = locate(href_list["makeai"])
if(!istype(H))
usr << "This can only be done to instances of type /mob/living/carbon/human"
return
if(alert("Confirm mob type change?",,"Transform","Cancel") != "Transform") return
if(!H)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("makeai"=href_list["makeai"]))
else if(href_list["setspecies"])
if(!check_rights(R_SPAWN)) return
var/mob/living/carbon/human/H = locate(href_list["setspecies"])
if(!istype(H))
usr << "This can only be done to instances of type /mob/living/carbon/human"
return
var/new_species = input("Please choose a new species.","Species",null) as null|anything in all_species
if(!H)
usr << "Mob doesn't exist anymore"
return
if(H.set_species(new_species))
usr << "Set species of [H] to [H.species]."
else
usr << "Failed! Something went wrong."
else if(href_list["addlanguage"])
if(!check_rights(R_SPAWN)) return
var/mob/H = locate(href_list["addlanguage"])
if(!istype(H))
usr << "This can only be done to instances of type /mob"
return
var/new_language = input("Please choose a language to add.","Language",null) as null|anything in all_languages
if(!new_language)
return
if(!H)
usr << "Mob doesn't exist anymore"
return
if(H.add_language(new_language))
usr << "Added [new_language] to [H]."
else
usr << "Mob already knows that language."
else if(href_list["remlanguage"])
if(!check_rights(R_SPAWN)) return
var/mob/H = locate(href_list["remlanguage"])
if(!istype(H))
usr << "This can only be done to instances of type /mob"
return
if(!H.languages.len)
usr << "This mob knows no languages."
return
var/datum/language/rem_language = input("Please choose a language to remove.","Language",null) as null|anything in H.languages
if(!rem_language)
return
if(!H)
usr << "Mob doesn't exist anymore"
return
if(H.remove_language(rem_language.name))
usr << "Removed [rem_language] from [H]."
else
usr << "Mob doesn't know that language."
else if(href_list["addverb"])
if(!check_rights(R_DEBUG)) return
var/mob/living/H = locate(href_list["addverb"])
if(!istype(H))
usr << "This can only be done to instances of type /mob/living"
return
var/list/possibleverbs = list()
possibleverbs += "Cancel" // One for the top...
possibleverbs += typesof(/mob/proc,/mob/verb,/mob/living/proc,/mob/living/verb)
switch(H.type)
if(/mob/living/carbon/human)
possibleverbs += typesof(/mob/living/carbon/proc,/mob/living/carbon/verb,/mob/living/carbon/human/verb,/mob/living/carbon/human/proc)
if(/mob/living/silicon/robot)
possibleverbs += typesof(/mob/living/silicon/proc,/mob/living/silicon/robot/proc,/mob/living/silicon/robot/verb)
if(/mob/living/silicon/ai)
possibleverbs += typesof(/mob/living/silicon/proc,/mob/living/silicon/ai/proc,/mob/living/silicon/ai/verb)
possibleverbs -= H.verbs
possibleverbs += "Cancel" // ...And one for the bottom
var/verb = input("Select a verb!", "Verbs",null) as anything in possibleverbs
if(!H)
usr << "Mob doesn't exist anymore"
return
if(!verb || verb == "Cancel")
return
else
H.verbs += verb
else if(href_list["remverb"])
if(!check_rights(R_DEBUG)) return
var/mob/H = locate(href_list["remverb"])
if(!istype(H))
usr << "This can only be done to instances of type /mob"
return
var/verb = input("Please choose a verb to remove.","Verbs",null) as null|anything in H.verbs
if(!H)
usr << "Mob doesn't exist anymore"
return
if(!verb)
return
else
H.verbs -= verb
else if(href_list["addorgan"])
if(!check_rights(R_SPAWN)) return
var/mob/living/carbon/M = locate(href_list["addorgan"])
if(!istype(M))
usr << "This can only be done to instances of type /mob/living/carbon"
return
var/new_organ = input("Please choose an organ to add.","Organ",null) as null|anything in typesof(/obj/item/organ)-/obj/item/organ
if(!new_organ) return
if(!M)
usr << "Mob doesn't exist anymore"
return
if(locate(new_organ) in M.internal_organs)
usr << "Mob already has that organ."
return
<<<<<<< HEAD
new new_organ(M)
=======
if(istype(M,/mob/living/carbon/human))
var/mob/living/carbon/human/H = M
var/datum/organ/internal/I = new new_organ(H)
var/organ_slot = input(usr, "Which slot do you want the organ to go in ('default' for default)?") as text|null
if(!organ_slot)
return
if(organ_slot != "default")
organ_slot = sanitize(organ_slot)
else
if(I.removed_type)
var/obj/item/organ/O = new I.removed_type()
organ_slot = O.organ_tag
del(O)
else
organ_slot = "unknown organ"
if(H.internal_organs_by_name[organ_slot])
usr << "[H] already has an organ in that slot."
del(I)
return
H.internal_organs |= I
H.internal_organs_by_name[organ_slot] = I
usr << "Added new [new_organ] to [H] as slot [organ_slot]."
else
new new_organ(M)
usr << "Added new [new_organ] to [M]."
>>>>>>> 2aa4646fa0425bed412e2ef0e7852591ecb4bc40
else if(href_list["remorgan"])
if(!check_rights(R_SPAWN)) return
var/mob/living/carbon/M = locate(href_list["remorgan"])
if(!istype(M))
usr << "This can only be done to instances of type /mob/living/carbon"
return
var/obj/item/organ/rem_organ = input("Please choose an organ to remove.","Organ",null) as null|anything in M.internal_organs
if(!M)
usr << "Mob doesn't exist anymore"
return
if(!(locate(rem_organ) in M.internal_organs))
usr << "Mob does not have that organ."
return
usr << "Removed [rem_organ] from [M]."
rem_organ.removed()
del(rem_organ)
else if(href_list["fix_nano"])
if(!check_rights(R_DEBUG)) return
var/mob/H = locate(href_list["fix_nano"])
if(!istype(H) || !H.client)
usr << "This can only be done on mobs with clients"
return
nanomanager.send_resources(H.client)
usr << "Resource files sent"
H << "Your NanoUI Resource files have been refreshed"
log_admin("[key_name(usr)] resent the NanoUI resource files to [key_name(H)] ")
else if(href_list["regenerateicons"])
if(!check_rights(0)) return
var/mob/M = locate(href_list["regenerateicons"])
if(!ismob(M))
usr << "This can only be done to instances of type /mob"
return
M.regenerate_icons()
else if(href_list["adjustDamage"] && href_list["mobToDamage"])
if(!check_rights(R_DEBUG|R_ADMIN|R_FUN)) return
var/mob/living/L = locate(href_list["mobToDamage"])
if(!istype(L)) return
var/Text = href_list["adjustDamage"]
var/amount = input("Deal how much damage to mob? (Negative values here heal)","Adjust [Text]loss",0) as num
if(!L)
usr << "Mob doesn't exist anymore"
return
switch(Text)
if("brute") L.adjustBruteLoss(amount)
if("fire") L.adjustFireLoss(amount)
if("toxin") L.adjustToxLoss(amount)
if("oxygen")L.adjustOxyLoss(amount)
if("brain") L.adjustBrainLoss(amount)
if("clone") L.adjustCloneLoss(amount)
else
usr << "You caused an error. DEBUG: Text:[Text] Mob:[L]"
return
if(amount != 0)
log_admin("[key_name(usr)] dealt [amount] amount of [Text] damage to [L] ")
message_admins("\blue [key_name(usr)] dealt [amount] amount of [Text] damage to [L] ")
href_list["datumrefresh"] = href_list["mobToDamage"]
if(href_list["datumrefresh"])
var/datum/DAT = locate(href_list["datumrefresh"])
if(!istype(DAT, /datum))
return
src.debug_variables(DAT)
return

View File

@@ -43,10 +43,10 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/datum/supply_packs/food
name = "Kitchen supply crate"
contains = list(/obj/item/weapon/reagent_containers/food/snacks/flour,
/obj/item/weapon/reagent_containers/food/snacks/flour,
/obj/item/weapon/reagent_containers/food/snacks/flour,
/obj/item/weapon/reagent_containers/food/snacks/flour,
contains = list(/obj/item/weapon/reagent_containers/food/condiment/flour,
/obj/item/weapon/reagent_containers/food/condiment/flour,
/obj/item/weapon/reagent_containers/food/condiment/flour,
/obj/item/weapon/reagent_containers/food/condiment/flour,
/obj/item/weapon/reagent_containers/food/drinks/milk,
/obj/item/weapon/reagent_containers/food/drinks/milk,
/obj/item/weapon/storage/fancy/egg_box,
@@ -1506,5 +1506,20 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/obj/item/device/floor_painter,
/obj/item/device/floor_painter)
/datum/supply_packs/bluespacerelay
name = "Emergency Bluespace Relay Assembly Kit"
cost = 75
containername = "emergency bluespace relay assembly kit"
containertype = /obj/structure/closet/crate
group = "Engineering"
contains = list(/obj/item/weapon/circuitboard/bluespacerelay,
/obj/item/weapon/stock_parts/manipulator,
/obj/item/weapon/stock_parts/manipulator,
/obj/item/weapon/stock_parts/subspace/filter,
/obj/item/weapon/stock_parts/subspace/crystal,
/obj/item/weapon/storage/toolbox/electrical)

View File

@@ -91,9 +91,11 @@
/obj/item/weapon/cane/concealed/New()
..()
concealed_blade = new/obj/item/weapon/butterfly/switchblade(src)
var/obj/item/weapon/butterfly/switchblade/temp_blade = new(src)
concealed_blade = temp_blade
temp_blade.attack_self()
/obj/item/weapon/cane/concealed/attack_self(mob/user)
/obj/item/weapon/cane/concealed/attack_self(var/mob/user)
if(concealed_blade)
user.visible_message("<span class='warning'>[user] has unsheathed \a [concealed_blade] from \his [src]!</span>", "You unsheathe \the [concealed_blade] from \the [src].")
// Calling drop/put in hands to properly call item drop/pickup procs
@@ -101,8 +103,9 @@
user.drop_from_inventory(src)
user.put_in_hands(concealed_blade)
user.put_in_hands(src)
user.update_inv_l_hand(0)
user.update_inv_r_hand()
concealed_blade = null
update_icon()
else
..()

View File

@@ -1,13 +1,31 @@
proc/log_and_message_admins(var/message as text)
log_admin(usr ? "[key_name(usr)] [message]" : "EVENT [message]")
message_admins(usr ? "[key_name(usr)] [message]" : "EVENT [message]")
proc/log_and_message_admins(var/message as text, var/mob/user = usr)
log_admin(user ? "[key_name(user)] [message]" : "EVENT [message]")
message_admins(user ? "[key_name(user)] [message]" : "EVENT [message]")
proc/log_and_message_admins_many(var/list/mob/users, var/message)
if(!users || !users.len)
return
var/list/user_keys = list()
for(var/mob/user in users)
user_keys += key_name(user)
log_admin("[english_list(user_keys)] [message]")
message_admins("[english_list(user_keys)] [message]")
proc/admin_log_and_message_admins(var/message as text)
log_admin(usr ? "[key_name_admin(usr)] [message]" : "EVENT [message]")
message_admins(usr ? "[key_name_admin(usr)] [message]" : "EVENT [message]", 1)
proc/admin_attack_log(var/mob/attacker, var/mob/victim, var/attacker_message, var/victim_message, var/admin_message)
victim.attack_log += text("\[[time_stamp()]\] <font color='orange'>[victim_message] [key_name(attacker)]</font>")
attacker.attack_log += text("\[[time_stamp()]\] <font color='red'>[attacker_message] [key_name(victim)]</font>")
victim.attack_log += text("\[[time_stamp()]\] <font color='orange'>[key_name(attacker)] - [victim_message]</font>")
attacker.attack_log += text("\[[time_stamp()]\] <font color='red'>[key_name(victim)] - [attacker_message]</font>")
msg_admin_attack("[key_name(attacker)] [admin_message] [key_name(victim)] (INTENT: [uppertext(attacker.a_intent)]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[attacker.x];Y=[attacker.y];Z=[attacker.z]'>JMP</a>)")
proc/admin_attacker_log_many_victims(var/mob/attacker, var/list/mob/victims, var/attacker_message, var/victim_message, var/admin_message)
if(!victims || !victims.len)
return
for(var/mob/victim in victims)
admin_attack_log(attacker, victim, attacker_message, victim_message, admin_message)

View File

@@ -30,13 +30,14 @@
title = "Security Announcement"
announcement_type = "Security Announcement"
/datum/announcement/proc/Announce(var/message as text, var/new_title = "", var/new_sound = null, var/do_newscast = newscast)
/datum/announcement/proc/Announce(var/message as text, var/new_title = "", var/new_sound = null, var/do_newscast = newscast, var/msg_sanitized = 0)
if(!message)
return
var/message_title = new_title ? new_title : title
var/message_sound = new_sound ? new_sound : sound
message = sanitize(message, extra = 0)
if(!msg_sanitized)
message = sanitize(message, extra = 0)
message_title = sanitizeSafe(message_title)
Message(message, message_title)

View File

@@ -34,7 +34,7 @@
return 1
if(flags & ANTAG_SET_APPEARANCE)
player.change_appearance(APPEARANCE_ALL, player, player, valid_species)
player.change_appearance(APPEARANCE_ALL, player.loc, player, valid_species, state = z_state)
/datum/antagonist/proc/unequip(var/mob/living/carbon/human/player)
if(!istype(player))

View File

@@ -30,8 +30,8 @@ var/datum/antagonist/raider/raiders
var/list/raider_glasses = list(
/obj/item/clothing/glasses/thermal,
/obj/item/clothing/glasses/thermal/eyepatch,
/obj/item/clothing/glasses/thermal/monocle
/obj/item/clothing/glasses/thermal/plain/eyepatch,
/obj/item/clothing/glasses/thermal/plain/monocle
)
var/list/raider_helmets = list(

View File

@@ -95,21 +95,31 @@ var/datum/antagonist/wizard/wizards
//To batch-remove wizard spells. Linked to mind.dm.
/mob/proc/spellremove(var/mob/M as mob)
for(var/obj/effect/proc_holder/spell/spell_to_remove in src.spell_list)
del(spell_to_remove)
for(var/spell/spell_to_remove in src.spell_list)
remove_spell(spell_to_remove)
/*Checks if the wizard can cast spells.
obj/item/clothing
var/wizard_garb = 0
// Does this clothing slot count as wizard garb? (Combines a few checks)
/proc/is_wiz_garb(var/obj/item/clothing/C)
return C && C.wizard_garb
/*Checks if the wizard is wearing the proper attire.
Made a proc so this is not repeated 14 (or more) times.*/
/mob/proc/casting()
//Removed the stat check because not all spells require clothing now.
if(!istype(usr:wear_suit, /obj/item/clothing/suit/wizrobe))
usr << "I don't feel strong enough without my robe."
/mob/proc/wearing_wiz_garb()
src << "Silly creature, you're not a human. Only humans can cast this spell."
return 0
// Humans can wear clothes.
/mob/living/carbon/human/wearing_wiz_garb()
if(!is_wiz_garb(src.wear_suit))
src << "<span class='warning'>I don't feel strong enough without my robe.</span>"
return 0
if(!istype(usr:shoes, /obj/item/clothing/shoes/sandal))
usr << "I don't feel strong enough without my sandals."
if(!is_wiz_garb(src.shoes))
src << "<span class='warning'>I don't feel strong enough without my sandals.</span>"
return 0
if(!istype(usr:head, /obj/item/clothing/head/wizard))
usr << "I don't feel strong enough without my hat."
if(!is_wiz_garb(src.head))
src << "<span class='warning'>I don't feel strong enough without my hat.</span>"
return 0
else
return 1
return 1

View File

@@ -24,11 +24,13 @@ var/datum/antagonist/cultist/cult
flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE
max_antags = 200 // No upper limit.
max_antags_round = 200
var/allow_narsie = 1
var/datum/mind/sacrifice_target
var/list/startwords = list("blood","join","self","hell")
var/list/allwords = list("travel","self","see","hell","blood","join","tech","destroy", "other", "hide")
var/list/sacrificed = list()
var/list/harvested = list()
/datum/antagonist/cultist/New()
..()

View File

@@ -873,27 +873,27 @@ area/space/atmosalert()
music = null
/area/crew_quarters/captain
name = "\improper Captain's Office"
name = "\improper Command - Captain's Office"
icon_state = "captain"
/area/crew_quarters/heads/hop
name = "\improper Head of Personnel's Office"
name = "\improper Command - HoP's Office"
icon_state = "head_quarters"
/area/crew_quarters/heads/hor
name = "\improper Research Director's Office"
name = "\improper Research - RD's Office"
icon_state = "head_quarters"
/area/crew_quarters/heads/chief
name = "\improper Chief Engineer's Office"
name = "\improper Engineering - CE's Office"
icon_state = "head_quarters"
/area/crew_quarters/heads/hos
name = "\improper Head of Security's Office"
name = "\improper Security - HoS' Office"
icon_state = "head_quarters"
/area/crew_quarters/heads/cmo
name = "\improper Chief Medical Officer's Office"
name = "\improper Medbay - CMO's Office"
icon_state = "head_quarters"
/area/crew_quarters/courtroom
@@ -1085,7 +1085,7 @@ area/space/atmosalert()
icon_state = "atmos_storage"
/area/engineering/drone_fabrication
name = "\improper Drone Fabrication"
name = "\improper Engineering Drone Fabrication"
icon_state = "drone_fab"
/area/engineering/engine_smes
@@ -1171,23 +1171,23 @@ area/space/atmosalert()
icon_state = "panelsP"
/area/maintenance/auxsolarport
name = "Fore Port Solar Maintenance"
name = "Solar Maintenance - Fore Port"
icon_state = "SolarcontrolP"
/area/maintenance/starboardsolar
name = "Aft Starboard Solar Maintenance"
name = "Solar Maintenance - Aft Starboard"
icon_state = "SolarcontrolS"
/area/maintenance/portsolar
name = "Aft Port Solar Maintenance"
name = "Solar Maintenance - Aft Port"
icon_state = "SolarcontrolP"
/area/maintenance/auxsolarstarboard
name = "Fore Starboard Solar Maintenance"
name = "Solar Maintenance - Fore Starboard"
icon_state = "SolarcontrolS"
/area/maintenance/foresolar
name = "Fore Solar Maintenance"
name = "Solar Maintenance - Fore"
icon_state = "SolarcontrolA"
/area/assembly/chargebay
@@ -1362,35 +1362,35 @@ area/space/atmosalert()
icon_state = "security"
/area/security/lobby
name = "\improper Security lobby"
name = "\improper Security Lobby"
icon_state = "security"
/area/security/brig
name = "\improper Brig"
name = "\improper Security - Brig"
icon_state = "brig"
/area/security/prison
name = "\improper Prison Wing"
name = "\improper Security - Prison Wing"
icon_state = "sec_prison"
/area/security/warden
name = "\improper Warden"
name = "\improper Security - Warden's Office"
icon_state = "Warden"
/area/security/armoury
name = "\improper Armory"
name = "\improper Security - Armory"
icon_state = "Warden"
/area/security/detectives_office
name = "\improper Detective's Office"
name = "\improper Security - Forensic Office"
icon_state = "detective"
/area/security/range
name = "\improper Firing Range"
name = "\improper Security - Firing Range"
icon_state = "firingrange"
/area/security/tactical
name = "\improper Tactical Equipment"
name = "\improper Security - Tactical Equipment"
icon_state = "Tactical"
@@ -1420,7 +1420,7 @@ area/space/atmosalert()
icon_state = "checkpoint1"
/area/security/checkpoint2
name = "\improper Security Checkpoint"
name = "\improper Security - Arrival Checkpoint"
icon_state = "security"
/area/security/checkpoint/supply
@@ -1451,14 +1451,6 @@ area/space/atmosalert()
name = "\improper Quartermasters"
icon_state = "quart"
///////////WORK IN PROGRESS//////////
/area/quartermaster/sorting
name = "\improper Delivery Office"
icon_state = "quartstorage"
////////////WORK IN PROGRESS//////////
/area/quartermaster/office
name = "\improper Cargo Office"
icon_state = "quartoffice"
@@ -1468,21 +1460,13 @@ area/space/atmosalert()
icon_state = "quartstorage"
/area/quartermaster/qm
name = "\improper Quartermaster's Office"
name = "\improper Cargo - Quartermaster's Office"
icon_state = "quart"
/area/quartermaster/miningdock
name = "\improper Mining Dock"
name = "\improper Cargo Mining Dock"
icon_state = "mining"
/area/quartermaster/miningstorage
name = "\improper Mining Storage"
icon_state = "green"
/area/quartermaster/mechbay
name = "\improper Mech Bay"
icon_state = "yellow"
/area/janitor/
name = "\improper Custodial Closet"
icon_state = "janitor"
@@ -1770,7 +1754,7 @@ area/space/atmosalert()
//Construction
/area/construction
name = "\improper Construction Area"
name = "\improper Engineering Construction Area"
icon_state = "yellow"
/area/construction/supplyshuttle
@@ -2041,6 +2025,7 @@ area/space/atmosalert()
luminosity = 1
lighting_use_dynamic = 0
requires_power = 0
ambience = list()
var/sound/mysound = null
New()

View File

@@ -229,6 +229,9 @@ its easier to just keep the beam vertical.
/atom/proc/fire_act()
return
/atom/proc/melt()
return
/atom/proc/hitby(atom/movable/AM as mob|obj)
if (density)

View File

@@ -166,6 +166,7 @@
H.f_style = facial_hair_styles_list[beard]
H.force_update_limbs()
H.update_eyes()
H.update_hair()
return 1

View File

@@ -235,9 +235,9 @@
H.r_eyes = hex2num(getblock(structure,8,3))
H.g_eyes = hex2num(getblock(structure,9,3))
H.b_eyes = hex2num(getblock(structure,10,3))
if(H.internal_organs_by_name["eyes"])
var/obj/item/organ/eyes/eyes = H.internal_organs_by_name["eyes"]
eyes.eye_colour = list(H.r_eyes,H.g_eyes,H.b_eyes)
H.update_eyes()
if (isblockon(getblock(structure, 11,3),11 , 1))
H.gender = FEMALE

File diff suppressed because it is too large Load Diff

View File

@@ -463,7 +463,6 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
// sending display messages
C << "<span class='notice'>We have regenerated.</span>"
C.visible_message("<span class='warning'>[src] appears to wake from the dead, having healed all wounds.</span>")
feedback_add_details("changeling_powers","FD")

View File

@@ -8,4 +8,4 @@
required_enemies = 3
uplink_welcome = "Nar-Sie Uplink Console:"
end_on_antag_death = 1
antag_tag = MODE_CULTIST
antag_tag = MODE_CULTIST

View File

@@ -8,6 +8,8 @@
throwforce = 10
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
/obj/item/weapon/melee/cultblade/cultify()
return
/obj/item/weapon/melee/cultblade/attack(mob/living/target as mob, mob/living/carbon/human/user as mob)
if(iscultist(user))
@@ -40,15 +42,22 @@
min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE
siemens_coefficient = 0
/obj/item/clothing/head/culthood/cultify()
return
/obj/item/clothing/head/culthood/magus
name = "magus helm"
icon_state = "magus"
item_state = "magus"
desc = "A helm worn by the followers of Nar-Sie."
flags_inv = HIDEFACE
flags = HEADCOVERSEYES | HEADCOVERSMOUTH | BLOCKHAIR
body_parts_covered = HEAD|FACE|EYES
/obj/item/clothing/head/culthood/alt
icon_state = "cult_hoodalt"
item_state = "cult_hoodalt"
/obj/item/clothing/suit/cultrobes/alt
icon_state = "cultrobesalt"
item_state = "cultrobesalt"
/obj/item/clothing/suit/cultrobes
name = "cult robes"
desc = "A set of armored robes worn by the followers of Nar-Sie"
@@ -60,27 +69,20 @@
flags_inv = HIDEJUMPSUIT
siemens_coefficient = 0
/obj/item/clothing/head/magus
name = "magus helm"
icon_state = "magus"
item_state = "magus"
desc = "A helm worn by the followers of Nar-Sie."
flags_inv = HIDEFACE
flags = HEADCOVERSEYES | HEADCOVERSMOUTH | BLOCKHAIR
body_parts_covered = HEAD|FACE|EYES
armor = list(melee = 30, bullet = 30, laser = 30,energy = 20, bomb = 0, bio = 0, rad = 0)
siemens_coefficient = 0
/obj/item/clothing/suit/cultrobes/cultify()
return
/obj/item/clothing/suit/magusred
/obj/item/clothing/suit/cultrobes/alt
icon_state = "cultrobesalt"
item_state = "cultrobesalt"
/obj/item/clothing/suit/cultrobes/magusred
name = "magus robes"
desc = "A set of armored robes worn by the followers of Nar-Sie"
icon_state = "magusred"
item_state = "magusred"
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
allowed = list(/obj/item/weapon/book/tome,/obj/item/weapon/melee/cultblade)
armor = list(melee = 50, bullet = 30, laser = 50,energy = 20, bomb = 25, bio = 10, rad = 0)
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
siemens_coefficient = 0
/obj/item/clothing/head/helmet/space/cult
name = "cult helmet"
@@ -90,6 +92,8 @@
armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30)
siemens_coefficient = 0
/obj/item/clothing/head/helmet/space/cult/cultify()
return
/obj/item/clothing/suit/space/cult
name = "cult armour"
@@ -101,4 +105,7 @@
slowdown = 1
armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30)
siemens_coefficient = 0
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS
/obj/item/clothing/suit/space/cult/cultify()
return

View File

@@ -3,6 +3,9 @@
anchored = 1
icon = 'icons/obj/cult.dmi'
/obj/structure/cult/cultify()
return
/obj/structure/cult/talisman
name = "Altar"
desc = "A bloodstained altar dedicated to Nar-Sie"
@@ -18,8 +21,52 @@
name = "Pylon"
desc = "A floating crystal that hums with an unearthly energy"
icon_state = "pylon"
var/isbroken = 0
luminosity = 5
l_color = "#3e0000"
var/obj/item/wepon = null
/obj/structure/cult/pylon/attack_hand(mob/M as mob)
attackpylon(M, 5)
/obj/structure/cult/pylon/attack_generic(var/mob/user, var/damage)
attackpylon(user, damage)
/obj/structure/cult/pylon/attackby(obj/item/W as obj, mob/user as mob)
attackpylon(user, W.force)
/obj/structure/cult/pylon/proc/attackpylon(mob/user as mob, var/damage)
if(!isbroken)
if(prob(1+ damage * 5))
user << "You hit the pylon, and its crystal breaks apart!"
for(var/mob/M in viewers(src))
if(M == user)
continue
M.show_message("[user.name] smashed the pylon!", 3, "You hear a tinkle of crystal shards", 2)
playsound(get_turf(src), 'sound/effects/Glassbr3.ogg', 75, 1)
isbroken = 1
density = 0
icon_state = "pylon-broken"
SetLuminosity(0)
else
user << "You hit the pylon!"
playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1)
else
if(prob(damage * 2))
user << "You pulverize what was left of the pylon!"
qdel(src)
else
user << "You hit the pylon!"
playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1)
/obj/structure/cult/pylon/proc/repair(mob/user as mob)
if(isbroken)
user << "You repair the pylon."
isbroken = 0
density = 1
icon_state = "pylon"
SetLuminosity(5)
/obj/structure/cult/tome
name = "Desk"
@@ -45,6 +92,7 @@
density = 1
unacidable = 1
anchored = 1.0
var/spawnable = null
/obj/effect/gateway/Bumped(mob/M as mob|obj)
spawn(0)
@@ -54,4 +102,74 @@
/obj/effect/gateway/Crossed(AM as mob|obj)
spawn(0)
return
return
return
/obj/effect/gateway/active
luminosity=5
l_color="#ff0000"
spawnable=list(
/mob/living/simple_animal/hostile/scarybat,
/mob/living/simple_animal/hostile/creature,
/mob/living/simple_animal/hostile/faithless
)
/obj/effect/gateway/active/cult
luminosity=5
l_color="#ff0000"
spawnable=list(
/mob/living/simple_animal/hostile/scarybat/cult,
/mob/living/simple_animal/hostile/creature/cult,
/mob/living/simple_animal/hostile/faithless/cult
)
/obj/effect/gateway/active/cult/cultify()
return
/obj/effect/gateway/active/New()
spawn(rand(30,60) SECONDS)
var/t = pick(spawnable)
new t(src.loc)
qdel(src)
/obj/effect/gateway/active/Crossed(var/atom/A)
if(!istype(A, /mob/living))
return
var/mob/living/M = A
if(M.stat != DEAD)
if(M.monkeyizing)
return
if(M.has_brain_worms())
return //Borer stuff - RR
if(iscultist(M)) return
if(!ishuman(M) && !isrobot(M)) return
M.monkeyizing = 1
M.canmove = 0
M.icon = null
M.overlays.len = 0
M.invisibility = 101
if(istype(M, /mob/living/silicon/robot))
var/mob/living/silicon/robot/Robot = M
if(Robot.mmi)
del(Robot.mmi)
else
for(var/obj/item/W in M)
if(istype(W, /obj/item/weapon/implant))
qdel(W)
continue
W.layer = initial(W.layer)
W.loc = M.loc
W.dropped(M)
var/mob/living/new_mob = new /mob/living/simple_animal/corgi(A.loc)
new_mob.a_intent = I_HURT
if(M.mind)
M.mind.transfer_to(new_mob)
else
new_mob.key = M.key
new_mob << "<B>Your form morphs into that of a corgi.</B>" //Because we don't have cluwnes

View File

@@ -0,0 +1,63 @@
/mob
//thou shall always be able to see the Geometer of Blood
var/image/narsimage = null
var/image/narglow = null
/mob/proc/cultify()
return
/mob/dead/cultify()
if(icon_state != "ghost-narsie")
icon = 'icons/mob/mob.dmi'
icon_state = "ghost-narsie"
overlays = 0
invisibility = 0
src << "<span class='sinister'>Even as a non-corporal being, you can feel Nar-Sie's presence altering you. You are now visible to everyone.</span>"
/mob/living/cultify()
if(iscultist(src) && client)
var/mob/living/simple_animal/construct/harvester/C = new(get_turf(src))
mind.transfer_to(C)
C << "<span class='sinister'>The Geometer of Blood is overjoyed to be reunited with its followers, and accepts your body in sacrifice. As reward, you have been gifted with the shell of an Harvester.<br>Your tendrils can use and draw runes without need for a tome, your eyes can see beings through walls, and your mind can open any door. Use these assets to serve Nar-Sie and bring him any remaining living human in the world.<br>You can teleport yourself back to Nar-Sie along with any being under yourself at any time using your \"Harvest\" spell.</span>"
dust()
else if(client)
var/mob/dead/G = (ghostize())
G.icon = 'icons/mob/mob.dmi'
G.icon_state = "ghost-narsie"
G.overlays = 0
G.invisibility = 0
G << "<span class='sinister'>You feel relieved as what's left of your soul finally escapes its prison of flesh.</span>"
cult.harvested += G.mind
else
dust()
/mob/proc/see_narsie(var/obj/machinery/singularity/narsie/large/N, var/dir)
if(N.chained)
if(narsimage)
del(narsimage)
del(narglow)
return
if((N.z == src.z)&&(get_dist(N,src) <= (N.consume_range+10)) && !(N in view(src)))
if(!narsimage) //Create narsimage
narsimage = image('icons/obj/narsie.dmi',src.loc,"narsie",9,1)
narsimage.mouse_opacity = 0
if(!narglow) //Create narglow
narglow = image('icons/obj/narsie.dmi',narsimage.loc,"glow-narsie",LIGHTING_LAYER+2,1)
narglow.mouse_opacity = 0
//Else if no dir is given, simply send them the image of narsie
var/new_x = 32 * (N.x - src.x) + N.pixel_x
var/new_y = 32 * (N.y - src.y) + N.pixel_y
narsimage.pixel_x = new_x
narsimage.pixel_y = new_y
narglow.pixel_x = new_x
narglow.pixel_y = new_y
narsimage.loc = src.loc
narglow.loc = src.loc
//Display the new narsimage to the player
src << narsimage
src << narglow
else
if(narsimage)
del(narsimage)
del(narglow)

View File

@@ -0,0 +1,153 @@
/obj/proc/cultify()
qdel(src)
/obj/effect/decal/cleanable/blood/cultify()
return
/obj/effect/decal/remains/cultify()
return
/obj/effect/overlay/cultify()
return
/obj/item/device/flashlight/lamp/cultify()
new /obj/structure/cult/pylon(loc)
..()
/obj/item/stack/sheet/wood/cultify()
return
/obj/item/weapon/book/cultify()
new /obj/item/weapon/book/tome(loc)
..()
/obj/item/weapon/claymore/cultify()
new /obj/item/weapon/melee/cultblade(loc)
..()
/obj/item/weapon/storage/backpack/cultify()
new /obj/item/weapon/storage/backpack/cultpack(loc)
..()
/obj/item/weapon/storage/backpack/cultpack/cultify()
return
/obj/item/weapon/table_parts/cultify()
new /obj/item/weapon/table_parts/wood(loc)
..()
/obj/item/weapon/table_parts/wood/cultify()
return
/obj/machinery/cultify()
// We keep the number of cultified machines down by only converting those that are dense
// The alternative is to keep a separate file of exceptions.
if(density)
var/list/random_structure = list(
/obj/structure/cult/talisman,
/obj/structure/cult/forge,
/obj/structure/cult/tome
)
var/I = pick(random_structure)
new I(loc)
..()
/obj/machinery/atmospherics/cultify()
if(src.invisibility != INVISIBILITY_MAXIMUM)
src.invisibility = INVISIBILITY_MAXIMUM
density = 0
/obj/machinery/cooking/cultify()
new /obj/structure/cult/talisman(loc)
qdel(src)
/obj/machinery/computer/cultify()
new /obj/structure/cult/tome(loc)
qdel(src)
/obj/machinery/door/cultify()
new /obj/structure/mineral_door/wood(loc)
icon_state = "null"
density = 0
c_animation = new /atom/movable/overlay(src.loc)
c_animation.name = "cultification"
c_animation.density = 0
c_animation.anchored = 1
c_animation.icon = 'icons/effects/effects.dmi'
c_animation.layer = 5
c_animation.master = src.loc
c_animation.icon_state = "breakdoor"
flick("cultification",c_animation)
spawn(10)
del(c_animation)
qdel(src)
/obj/machinery/door/firedoor/cultify()
qdel(src)
/obj/machinery/light/cultify()
new /obj/structure/cult/pylon(loc)
qdel(src)
/obj/machinery/mech_sensor/cultify()
qdel(src)
/obj/machinery/power/apc/cultify()
if(src.invisibility != INVISIBILITY_MAXIMUM)
src.invisibility = INVISIBILITY_MAXIMUM
/obj/machinery/vending/cultify()
new /obj/structure/cult/forge(loc)
qdel(src)
/obj/structure/bed/chair/cultify()
var/obj/structure/bed/chair/wood/wings/I = new(loc)
I.dir = dir
..()
/obj/structure/bed/chair/wood/cultify()
return
/obj/structure/bookcase/cultify()
return
/obj/structure/grille/cultify()
new /obj/structure/grille/cult(get_turf(src))
..()
/obj/structure/grille/cult/cultify()
return
/obj/structure/mineral_door/cultify()
new /obj/structure/mineral_door/wood(loc)
..()
/obj/structure/mineral_door/wood/cultify()
return
/obj/machinery/singularity/cultify()
var/dist = max((current_size - 2), 1)
explosion(get_turf(src), dist, dist * 2, dist * 4)
qdel(src)
/obj/structure/shuttle/engine/heater/cultify()
new /obj/structure/cult/pylon(loc)
..()
/obj/structure/shuttle/engine/propulsion/cultify()
var/turf/T = get_turf(src)
if(T)
T.ChangeTurf(/turf/simulated/wall/cult)
..()
/obj/structure/stool/cultify()
var/obj/structure/bed/chair/wood/wings/I = new(loc)
I.dir = dir
..()
/obj/structure/table/cultify()
new /obj/structure/table/woodentable(loc)
..()
/obj/structure/table/woodentable/cultify()
return

View File

@@ -0,0 +1,43 @@
/turf/proc/cultify()
ChangeTurf(/turf/space)
return
/turf/simulated/floor/cultify()
cultify_floor()
/turf/simulated/floor/carpet/cultify()
return
/turf/simulated/shuttle/floor/cultify()
cultify_floor()
/turf/simulated/shuttle/floor4/cultify()
cultify_floor()
/turf/simulated/shuttle/wall/cultify()
cultify_wall()
/turf/simulated/wall/cultify()
cultify_wall()
/turf/simulated/wall/cult/cultify()
return
/turf/unsimulated/beach/cultify()
return
/turf/unsimulated/floor/cultify()
cultify_floor()
/turf/unsimulated/wall/cultify()
cultify_wall()
/turf/proc/cultify_floor()
if((icon_state != "cult")&&(icon_state != "cult-narsie"))
name = "engraved floor"
icon_state = "cult"
turf_animation('icons/effects/effects.dmi',"cultfloor",0,0,MOB_LAYER-1)
/turf/proc/cultify_wall()
ChangeTurf(/turf/unsimulated/wall/cult)
turf_animation('icons/effects/effects.dmi',"cultwall",0,0,MOB_LAYER-1)

View File

@@ -0,0 +1,101 @@
/*
In short:
* Random area alarms
* All areas jammed
* Random gateways spawning hellmonsters (and turn people into cluwnes if ran into)
* Broken APCs/Fire Alarms
* Scary music
* Random tiles changing to culty tiles.
*/
/datum/universal_state/hell
name = "Hell Rising"
desc = "OH FUCK OH FUCK OH FUCK"
decay_rate = 5 // 5% chance of a turf decaying on lighting update/airflow (there's no actual tick for turfs)
/datum/universal_state/hell/OnShuttleCall(var/mob/user)
return 1
/*
if(user)
user << "<span class='sinister'>All you hear on the frequency is static and panicked screaming. There will be no shuttle call today.</span>"
return 0
*/
/datum/universal_state/hell/DecayTurf(var/turf/T)
if(!T.holy)
T.cultify()
for(var/obj/machinery/light/L in T.contents)
new /obj/structure/cult/pylon(L.loc)
qdel(L)
return
/datum/universal_state/hell/OnTurfChange(var/turf/T)
var/turf/space/spess = T
if(istype(spess))
spess.overlays += "hell01"
// Apply changes when entering state
/datum/universal_state/hell/OnEnter()
set background = 1
escape_list = get_area_turfs(locate(/area/hallway/secondary/exit))
//Separated into separate procs for profiling
AreaSet()
OverlaySet()
MiscSet()
APCSet()
KillMobs()
AmbientSet()
runedec += 9000 //basically removing the rune cap
/datum/universal_state/hell/proc/AreaSet()
for(var/area/ca in world)
var/area/A = ca.master
if(!istype(A,/area) || A.name=="Space")
continue
// Reset all alarms.
A.fire = null
A.atmos = 1
A.atmosalm = 0
A.poweralm = 1
A.party = null
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/proc/AmbientSet()
for(var/turf/T in world)
if(istype(T, /turf/space)) continue
T.update_lumcount(1, 255, 0, 0, 0)
/datum/universal_state/hell/proc/MiscSet()
for(var/turf/simulated/floor/T in world)
if(!T.holy && prob(1))
new /obj/effect/gateway/active/cult(T)
for (var/obj/machinery/firealarm/alm in machines)
if (!(alm.stat & BROKEN))
alm.ex_act(2)
/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))
APC.chargemode = 0
if(APC.cell)
APC.cell.charge = 0
APC.emagged = 1
APC.queue_icon_update()
/datum/universal_state/hell/proc/KillMobs()
for(var/mob/living/simple_animal/M in mob_list)
if(M && !M.client)
M.stat = DEAD

View File

@@ -2,7 +2,8 @@
var/cultwords = list()
var/runedec = 0
var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology", "self", "see", "other", "hide")
var/global/list/engwords = list("travel", "blood", "join", "hell", "destroy", "technology", "self", "see", "other", "hide")
var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","mgar","balaq", "karazet", "geeri")
/client/proc/check_words() // -- Urist
set category = "Special Verbs"
@@ -14,7 +15,7 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology",
usr << "[cultwords[word]] is [word]"
/proc/runerandom() //randomizes word meaning
var/list/runewords=list("ire","ego","nahlizet","certum","veri","jatkaa","mgar","balaq", "karazet", "geeri") ///"orkan" and "allaq" removed.
var/list/runewords=rnwords
for (var/word in engwords)
cultwords[word] = pick(runewords)
runewords-=cultwords[word]
@@ -32,8 +33,9 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology",
var/word1
var/word2
var/word3
var/image/blood_image
var/list/converting = list()
// Places these combos are mentioned: this file - twice in the rune code, once in imbued tome, once in tome's HTML runes.dm - in the imbue rune code. If you change a combination - dont forget to change it everywhere.
// travel self [word] - Teleport to random [rune with word destination matching]
@@ -65,10 +67,21 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology",
// join hide technology - stun rune. Rune color: bright pink.
New()
..()
var/image/blood = image(loc = src)
blood.override = 1
blood_image = image(loc = src)
blood_image.override = 1
for(var/mob/living/silicon/ai/AI in player_list)
AI.client.images += blood
if(AI.client)
AI.client.images += blood_image
rune_list.Add(src)
Del()
for(var/mob/living/silicon/ai/AI in player_list)
if(AI.client)
AI.client.images -= blood_image
qdel(blood_image)
blood_image = null
rune_list.Remove(src)
..()
examine(mob/user)
..()
@@ -457,6 +470,8 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology",
user << "\red You slice open one of your fingers and begin drawing a rune on the floor whilst chanting the ritual that binds your life essence with the dark arcane energies flowing through the surrounding world."
user.take_overall_damage((rand(9)+1)/10) // 0.1 to 1.0 damage
if(do_after(user, 50))
var/area/A = get_area(user)
log_and_message_admins("created \an [chosen_rune] rune at \the [A.name] - [user.loc.x]-[user.loc.y]-[user.loc.z].")
if(usr.get_active_hand() != src)
return
var/mob/living/carbon/human/H = user
@@ -495,6 +510,9 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology",
else
user << "The scriptures of Nar-Sie, The One Who Sees, The Geometer of Blood. Contains the details of every ritual his followers could think of. Most of these are useless, though."
/obj/item/weapon/book/tome/cultify()
return
/obj/item/weapon/book/tome/imbued //admin tome, spawns working runes without waiting
w_class = 2.0
var/cultistsonly = 1
@@ -514,6 +532,8 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology",
var/mob/living/carbon/human/H = user
R.blood_DNA = list()
R.blood_DNA[H.dna.unique_enzymes] = H.dna.b_type
var/area/A = get_area(user)
log_and_message_admins("created \an [r] rune at \the [A.name] - [user.loc.x]-[user.loc.y]-[user.loc.z].")
switch(r)
if("teleport")
var/list/words = list("ire", "ego", "nahlizet", "certum", "veri", "jatkaa", "balaq", "mgar", "karazet", "geeri")

View File

@@ -1,5 +1,8 @@
var/list/sacrificed = list()
/obj/effect/rune/cultify()
return
/obj/effect/rune
/////////////////////////////////////////FIRST RUNE
@@ -99,6 +102,7 @@ var/list/sacrificed = list()
/////////////////////////////////////////THIRD RUNE
convert()
var/mob/attacker = usr
var/mob/living/carbon/target = null
for(var/mob/living/carbon/M in src.loc)
if(!iscultist(M) && M.stat < DEAD && !(M in converting))
@@ -123,10 +127,10 @@ var/list/sacrificed = list()
if(target.getFireLoss() < 100)
target.hallucination = min(target.hallucination, 500)
return 0
target.take_overall_damage(0, rand(5, 20)) // You dirty resister cannot handle the damage to your mind. Easily. - even cultists who accept right away should experience some effects
// Resist messages go!
if(initial_message) //don't do this stuff right away, only if they resist or hesitate.
admin_attack_log(attacker, target, "Used a convert rune", "Was subjected to a convert rune", "used a convert rune on")
switch(target.getFireLoss())
if(0 to 25)
target << "<span class='danger'>Your blood boils as you force yourself to resist the corruption invading every corner of your mind.</span>"
@@ -176,12 +180,16 @@ var/list/sacrificed = list()
/////////////////////////////////////////FOURTH RUNE
tearreality()
var/cultist_count = 0
if(!cult.allow_narsie)
return fizzle()
var/list/cultists = new()
for(var/mob/M in range(1,src))
if(iscultist(M) && !M.stat)
M.say("Tok-lyr rqa'nap g[pick("'","`")]lt-ulotf!")
cultist_count += 1
if(cultist_count >= 9)
cultists += 1
if(cultists.len >= 9)
log_and_message_admins_many(cultists, "summoned Nar-sie.")
new /obj/machinery/singularity/narsie/large(src.loc)
return
else
@@ -190,6 +198,7 @@ var/list/sacrificed = list()
/////////////////////////////////////////FIFTH RUNE
emp(var/U,var/range_red) //range_red - var which determines by which number to reduce the default emp range, U is the source loc, needed because of talisman emps which are held in hand at the moment of using and that apparently messes things up -- Urist
log_and_message_admins("activated an EMP rune.")
if(istype(src,/obj/effect/rune))
usr.say("Ta'gh fara[pick("'","`")]qha fel d'amar det!")
else
@@ -211,6 +220,7 @@ var/list/sacrificed = list()
if(R.word1==cultwords["travel"] && R.word2==cultwords["blood"] && R.word3==cultwords["self"])
for(var/mob/living/carbon/D in R.loc)
if(D.stat!=2)
admin_attack_log(usr, D, "Used a blood drain rune.", "Was victim of a blood drain rune.", "used a blood drain rune on")
var/bdrain = rand(1,25)
D << "\red You feel weakened."
D.take_overall_damage(bdrain, 0)
@@ -443,6 +453,7 @@ var/list/sacrificed = list()
D.real_name += " "
D.real_name += pick("Apparition", "Aptrgangr", "Dis", "Draugr", "Dybbuk", "Eidolon", "Fetch", "Fylgja", "Ghast", "Ghost", "Gjenganger", "Haint", "Phantom", "Phantasm", "Poltergeist", "Revenant", "Shade", "Shadow", "Soul", "Spectre", "Spirit", "Spook", "Visitant", "Wraith")
log_and_message_admins("used a manifest rune.")
var/mob/living/user = usr
while(this_rune && user && user.stat==CONSCIOUS && user.client && user.loc==this_rune.loc)
user.take_organ_damage(1, 0)
@@ -657,6 +668,7 @@ var/list/sacrificed = list()
usr << "\red The victim is still alive, you will need more cultists chanting for the sacrifice to succeed."
else
if(prob(40))
usr << "\red The Geometer of blood accepts this sacrifice."
cult.grant_runeword(usr)
else
@@ -853,7 +865,7 @@ var/list/sacrificed = list()
deafen()
if(istype(src,/obj/effect/rune))
var/affected = 0
var/list/affected = new()
for(var/mob/living/carbon/C in range(7,src))
if (iscultist(C))
continue
@@ -862,17 +874,18 @@ var/list/sacrificed = list()
continue
C.ear_deaf += 50
C.show_message("\red The world around you suddenly becomes quiet.", 3)
affected++
affected += C
if(prob(1))
C.sdisabilities |= DEAF
if(affected)
if(affected.len)
usr.say("Sti[pick("'","`")] kaliedir!")
usr << "\red The world becomes quiet as the deafening rune dissipates into fine dust."
admin_attacker_log_many_victims(usr, affected, "Used a deafen rune.", "Was victim of a deafen rune.", "used a deafen rune on")
del(src)
else
return fizzle()
else
var/affected = 0
var/list/affected = new()
for(var/mob/living/carbon/C in range(7,usr))
if (iscultist(C))
continue
@@ -882,10 +895,11 @@ var/list/sacrificed = list()
C.ear_deaf += 30
//talismans is weaker.
C.show_message("\red The world around you suddenly becomes quiet.", 3)
affected++
if(affected)
affected += C
if(affected.len)
usr.whisper("Sti[pick("'","`")] kaliedir!")
usr << "\red Your talisman turns into gray dust, deafening everyone around."
admin_attacker_log_many_victims(usr, affected, "Used a deafen rune.", "Was victim of a deafen rune.", "used a deafen rune on")
for (var/mob/V in orange(1,src))
if(!(iscultist(V)))
V.show_message("\red Dust flows from [usr]'s hands for a moment, and the world suddenly becomes quiet..", 3)
@@ -893,7 +907,7 @@ var/list/sacrificed = list()
blind()
if(istype(src,/obj/effect/rune))
var/affected = 0
var/list/affected = new()
for(var/mob/living/carbon/C in viewers(src))
if (iscultist(C))
continue
@@ -907,15 +921,16 @@ var/list/sacrificed = list()
if(prob(10))
C.sdisabilities |= BLIND
C.show_message("\red Suddenly you see red flash that blinds you.", 3)
affected++
if(affected)
affected += C
if(affected.len)
usr.say("Sti[pick("'","`")] kaliesin!")
usr << "\red The rune flashes, blinding those who not follow the Nar-Sie, and dissipates into fine dust."
admin_attacker_log_many_victims(usr, affected, "Used a blindness rune.", "Was victim of a blindness rune.", "used a blindness rune on")
del(src)
else
return fizzle()
else
var/affected = 0
var/list/affected = new()
for(var/mob/living/carbon/C in view(2,usr))
if (iscultist(C))
continue
@@ -925,11 +940,12 @@ var/list/sacrificed = list()
C.eye_blurry += 30
C.eye_blind += 10
//talismans is weaker.
affected++
affected += C
C.show_message("\red You feel a sharp pain in your eyes, and the world disappears into darkness..", 3)
if(affected)
if(affected.len)
usr.whisper("Sti[pick("'","`")] kaliesin!")
usr << "\red Your talisman turns into gray dust, blinding those who not follow the Nar-Sie."
admin_attacker_log_many_victims(usr, affected, "Used a blindness rune.", "Was victim of a blindness rune.", "used a blindness rune on")
return
@@ -940,12 +956,13 @@ var/list/sacrificed = list()
if (istype(H.current,/mob/living/carbon))
cultists+=H.current
*/
var/culcount = 0 //also, wording for it is old wording for obscure rune, which is now hide-see-blood.
var/list/cultists = new //also, wording for it is old wording for obscure rune, which is now hide-see-blood.
var/list/victims = new
// var/list/cultboil = list(cultists-usr) //and for this words are destroy-see-blood.
for(var/mob/living/carbon/C in orange(1,src))
if(iscultist(C) && !C.stat)
culcount++
if(culcount>=3)
cultists+=C
if(cultists.len>=3)
for(var/mob/living/carbon/M in viewers(usr))
if(iscultist(M))
continue
@@ -954,6 +971,7 @@ var/list/sacrificed = list()
continue
M.take_overall_damage(51,51)
M << "\red Your blood boils!"
victims += M
if(prob(5))
spawn(5)
M.gib()
@@ -964,6 +982,8 @@ var/list/sacrificed = list()
if(iscultist(C) && !C.stat)
C.say("Dedo ol[pick("'","`")]btoh!")
C.take_overall_damage(15, 0)
admin_attacker_log_many_victims(usr, victims, "Used a blood boil rune.", "Was the victim of a blood boil rune.", "used a blood boil rune on")
log_and_message_admins_many(cultists - usr, "assisted activating a blood boil rune.")
del(src)
else
return fizzle()
@@ -1003,7 +1023,6 @@ var/list/sacrificed = list()
if(istype(src,/obj/effect/rune)) ///When invoked as rune, flash and stun everyone around.
usr.say("Fuu ma[pick("'","`")]jin!")
for(var/mob/living/L in viewers(src))
if(iscarbon(L))
var/mob/living/carbon/C = L
flick("e_flash", C.flash)
@@ -1012,11 +1031,13 @@ var/list/sacrificed = list()
C.Weaken(1)
C.Stun(1)
C.show_message("\red The rune explodes in a bright flash.", 3)
admin_attack_log(usr, C, "Used a stun rune.", "Was victim of a stun rune.", "used a stun rune on")
else if(issilicon(L))
var/mob/living/silicon/S = L
S.Weaken(5)
S.show_message("\red BZZZT... The rune has exploded in a bright flash.", 3)
admin_attack_log(usr, S, "Used a stun rune.", "Was victim of a stun rune.", "used a stun rune on")
del(src)
else ///When invoked as talisman, stun and mute the target mob.
usr.say("Dream sign ''Evil sealing talisman'[pick("'","`")]!")
@@ -1030,7 +1051,7 @@ var/list/sacrificed = list()
if(issilicon(T))
T.Weaken(15)
admin_attack_log(usr, T, "Used a stun rune.", "Was victim of a stun rune.", "used a stun rune on")
else if(iscarbon(T))
var/mob/living/carbon/C = T
flick("e_flash", C.flash)
@@ -1038,6 +1059,7 @@ var/list/sacrificed = list()
C.silent += 15
C.Weaken(25)
C.Stun(25)
admin_attack_log(usr, C, "Used a stun rune.", "Was victim of a stun rune.", "used a stun rune on")
return
/////////////////////////////////////////TWENTY-FIFTH RUNE

View File

@@ -106,7 +106,7 @@
if("soulstone")
new /obj/item/device/soulstone(get_turf(usr))
if("construct")
new /obj/structure/constructshell(get_turf(usr))
new /obj/structure/constructshell/cult(get_turf(usr))
src.uses--
supply()
return

View File

@@ -0,0 +1,68 @@
/**********************
* ENDGAME STUFF
**********************/
// Universal State
// Handles stuff like space icon_state, constants, etc.
// Essentially a policy manager. Once shit hits the fan, this changes its policies.
// Called by master controller.
// Default shit.
/datum/universal_state
// Just for reference, for now.
// Might eventually add an observatory job.
var/name = "Normal"
var/desc = "Nothing seems awry."
// Sets world.turf, replaces all turfs of type /turf/space.
var/space_type = /turf/space
// Replaces all turfs of type /turf/space/transit
var/transit_space_type = /turf/space/transit
// Chance of a floor or wall getting damaged [0-100]
// Simulates stuff getting broken due to molecular bonds decaying.
var/decay_rate = 0
// Actually decay the turf.
/datum/universal_state/proc/DecayTurf(var/turf/T)
if(istype(T,/turf/simulated/wall))
var/turf/simulated/wall/W=T
W.melt()
return
if(istype(T,/turf/simulated/floor))
var/turf/simulated/floor/F=T
// Burnt?
if(!F.burnt)
F.burn_tile()
else
F.ReplaceWithLattice()
return
// Return 0 to cause shuttle call to fail.
/datum/universal_state/proc/OnShuttleCall(var/mob/user)
return 1
// Processed per tick
/datum/universal_state/proc/OnTurfTick(var/turf/T)
if(decay_rate && prob(decay_rate))
DecayTurf(T)
// Apply changes when exiting state
/datum/universal_state/proc/OnExit()
// Does nothing by default
// Apply changes when entering state
/datum/universal_state/proc/OnEnter()
// Does nothing by default
// Apply changes to a new turf.
/datum/universal_state/proc/OnTurfChange(var/turf/NT)
return
/proc/SetUniversalState(var/newstate,var/on_exit=1, var/on_enter=1)
if(on_exit)
universe.OnExit()
universe = new newstate
if(on_enter)
universe.OnEnter()

View File

@@ -0,0 +1,117 @@
// QUALITY COPYPASTA
/turf/unsimulated/wall/supermatter
name = "Bluespace"
desc = "THE END IS right now actually."
icon = 'icons/turf/space.dmi'
icon_state = "bluespace"
//luminosity = 5
//l_color="#0066FF"
layer = LIGHTING_LAYER+1
var/spawned=0 // DIR mask
var/next_check=0
var/list/avail_dirs = list(NORTH,SOUTH,EAST,WEST)
/turf/unsimulated/wall/supermatter/New()
..()
processing_turfs.Add(src)
next_check = world.time+5 SECONDS
/turf/unsimulated/wall/supermatter/Destroy()
processing_turfs.Remove(src)
..()
/turf/unsimulated/wall/supermatter/proc/process()
// Only check infrequently.
if(next_check>world.time) return
// No more available directions? Shut down process().
if(avail_dirs.len==0)
processing_objects.Remove(src)
return 1
// We're checking, reset the timer.
next_check = world.time+5 SECONDS
// Choose a direction.
var/pdir = pick(avail_dirs)
avail_dirs -= pdir
var/turf/T=get_step(src,pdir)
// EXPAND
if(!istype(T,type))
// Do pretty fadeout animation for 1s.
new /obj/effect/overlay/bluespacify(T)
spawn(10)
// Nom.
for(var/atom/movable/A in T)
if(A)
if(istype(A,/mob/living))
del(A)
else if(istype(A,/mob)) // Observers, AI cameras.
continue
qdel(A)
T.ChangeTurf(type)
if((spawned & (NORTH|SOUTH|EAST|WEST)) == (NORTH|SOUTH|EAST|WEST))
processing_turfs -= src
return
/turf/unsimulated/wall/supermatter/attack_generic(mob/user as mob)
return attack_hand(user)
/turf/unsimulated/wall/supermatter/attack_robot(mob/user as mob)
if(Adjacent(user))
return attack_hand(user)
else
user << "<span class = \"warning\">What the fuck are you doing?</span>"
return
// /vg/: Don't let ghosts fuck with this.
/turf/unsimulated/wall/supermatter/attack_ghost(mob/user as mob)
user.examinate(src)
/turf/unsimulated/wall/supermatter/attack_ai(mob/user as mob)
return user.examinate(src)
/turf/unsimulated/wall/supermatter/attack_hand(mob/user as mob)
user.visible_message("<span class=\"warning\">\The [user] reaches out and touches \the [src]... And then blinks out of existance.</span>",\
"<span class=\"danger\">You reach out and touch \the [src]. Everything immediately goes quiet. Your last thought is \"That was not a wise decision.\"</span>",\
"<span class=\"warning\">You hear an unearthly noise.</span>")
playsound(src, 'sound/effects/supermatter.ogg', 50, 1)
Consume(user)
/turf/unsimulated/wall/supermatter/attackby(obj/item/weapon/W as obj, mob/living/user as mob)
user.visible_message("<span class=\"warning\">\The [user] touches \a [W] to \the [src] as a silence fills the room...</span>",\
"<span class=\"danger\">You touch \the [W] to \the [src] when everything suddenly goes silent.\"</span>\n<span class=\"notice\">\The [W] flashes into dust as you flinch away from \the [src].</span>",\
"<span class=\"warning\">Everything suddenly goes silent.</span>")
playsound(src, 'sound/effects/supermatter.ogg', 50, 1)
user.drop_from_inventory(W)
Consume(W)
/turf/unsimulated/wall/supermatter/Bumped(atom/AM as mob|obj)
if(istype(AM, /mob/living))
AM.visible_message("<span class=\"warning\">\The [AM] slams into \the [src] inducing a resonance... \his body starts to glow and catch flame before flashing into ash.</span>",\
"<span class=\"danger\">You slam into \the [src] as your ears are filled with unearthly ringing. Your last thought is \"Oh, fuck.\"</span>",\
"<span class=\"warning\">You hear an unearthly noise as a wave of heat washes over you.</span>")
else
AM.visible_message("<span class=\"warning\">\The [AM] smacks into \the [src] and rapidly flashes to ash.</span>",\
"<span class=\"warning\">You hear a loud crack as you are washed with a wave of heat.</span>")
playsound(src, 'sound/effects/supermatter.ogg', 50, 1)
Consume(AM)
/turf/unsimulated/wall/supermatter/proc/Consume(var/mob/living/user)
if(istype(user,/mob/dead/observer))
return
del(user)

View File

@@ -0,0 +1,81 @@
/*** EXIT PORTAL ***/
/obj/machinery/singularity/narsie/large/exit
name = "Bluespace Rift"
desc = "NO TIME TO EXPLAIN, JUMP IN"
icon = 'icons/obj/rift.dmi'
icon_state = "rift"
move_self = 0
announce=0
narnar=0
layer=LIGHTING_LAYER+2 // ITS SO BRIGHT
consume_range = 6
/obj/machinery/singularity/narsie/large/exit/New()
..()
processing_objects.Add(src)
/obj/machinery/singularity/narsie/large/exit/update_icon()
overlays = 0
/obj/machinery/singularity/narsie/large/exit/process()
for(var/mob/M in player_list)
if(M.client)
M.see_rift(src)
eat()
/obj/machinery/singularity/narsie/large/exit/acquire(var/mob/food)
return
/obj/machinery/singularity/narsie/large/exit/consume(const/atom/A)
if(!(A.singuloCanEat()))
return 0
if (istype(A, /mob/living/))
do_teleport(A, pick(endgame_safespawns)) //dead-on precision
else if (isturf(A))
var/turf/T = A
var/dist = get_dist(T, src)
if (dist <= consume_range && T.density)
T.density = 0
for (var/atom/movable/AM in T.contents)
if (AM == src) // This is the snowflake.
continue
if (dist <= consume_range)
consume(AM)
continue
if (dist > consume_range)
if (101 == AM.invisibility)
continue
spawn (0)
AM.singularity_pull(src, src.current_size)
/mob
//thou shall always be able to see the rift
var/image/riftimage = null
/mob/proc/see_rift(var/obj/machinery/singularity/narsie/large/exit/R)
if((R.z == src.z) && (get_dist(R,src) <= (R.consume_range+10)) && !(R in view(src)))
if(!riftimage)
riftimage = image('icons/obj/rift.dmi',src.loc,"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
riftimage.pixel_x = new_x
riftimage.pixel_y = new_y
riftimage.loc = src.loc
src << riftimage
else
if(riftimage)
del(riftimage)

View File

@@ -0,0 +1,140 @@
/datum/universal_state/supermatter_cascade
name = "Supermatter Cascade"
desc = "Unknown harmonance affecting universal substructure, converting nearby matter to supermatter."
decay_rate = 5 // 5% chance of a turf decaying on lighting update/airflow (there's no actual tick for turfs)
/datum/universal_state/supermatter_cascade/OnShuttleCall(var/mob/user)
if(user)
user << "<span class='sinister'>All you hear on the frequency is static and panicked screaming. There will be no shuttle call today.</span>"
return 0
/datum/universal_state/supermatter_cascade/OnTurfChange(var/turf/T)
var/turf/space/spess = T
if(istype(spess))
spess.overlays += "end01"
/datum/universal_state/supermatter_cascade/DecayTurf(var/turf/T)
if(istype(T,/turf/simulated/wall))
var/turf/simulated/wall/W=T
W.melt()
return
if(istype(T,/turf/simulated/floor))
var/turf/simulated/floor/F=T
// Burnt?
if(!F.burnt)
F.burn_tile()
else
if(!istype(F,/turf/simulated/floor/plating))
F.break_tile_to_plating()
return
// Apply changes when entering state
/datum/universal_state/supermatter_cascade/OnEnter()
set background = 1
world << "<span class='sinister' style='font-size:22pt'>You are blinded by a brilliant flash of energy.</span>"
world << sound('sound/effects/cascade.ogg')
for(var/mob/M in player_list)
flick("e_flash", M.flash)
if(emergency_shuttle.can_recall())
priority_announcement.Announce("The emergency shuttle has returned due to bluespace distortion.")
emergency_shuttle.recall()
AreaSet()
OverlaySet()
MiscSet()
APCSet()
AmbientSet()
// Disable Nar-Sie.
cult.allow_narsie = 0
PlayerSet()
new /obj/machinery/singularity/narsie/large/exit(pick(endgame_exits))
spawn(rand(30,60) SECONDS)
var/txt = {"
There's been a galaxy-wide electromagnetic pulse. All of our systems are heavily damaged and many personnel are dead or dying. We are seeing increasing indications of the universe itself beginning to unravel.
[station_name()], you are the only facility nearby a bluespace rift, which is near your research outpost. You are hereby directed to enter the rift using all means necessary, quite possibly as the last of your species alive.
You have five minutes before the universe collapses. Good l\[\[###!!!-
AUTOMATED ALERT: Link to [command_name()] lost."}
priority_announcement.Announce(txt,"SUPERMATTER CASCADE DETECTED")
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()
return
/datum/universal_state/supermatter_cascade/proc/AreaSet()
for(var/area/ca in world)
var/area/A=ca.master
if(A.z in config.admin_levels)
continue
if(!istype(A,/area) || 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/proc/AmbientSet()
for(var/turf/T in world)
if(istype(T, /turf/space)) continue
if(!(T.z in config.admin_levels))
T.update_lumcount(1, 160, 255, 0, 0)
/datum/universal_state/supermatter_cascade/proc/MiscSet()
for (var/obj/machinery/firealarm/alm in world)
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))
APC.chargemode = 0
if(APC.cell)
APC.cell.charge = 0
APC.emagged = 1
APC.queue_icon_update()
/datum/universal_state/supermatter_cascade/proc/PlayerSet()
for(var/datum/mind/M in player_list)
if(!istype(M.current,/mob/living))
continue
if(M.current.stat!=2)
M.current.Weaken(10)
flick("e_flash", M.current.flash)
clear_antag_roles(M)

View File

@@ -105,6 +105,16 @@
else
icon_state = "table2-idle"
/obj/machinery/optable/MouseDrop_T(mob/target, mob/user)
var/mob/living/M = user
if(user.stat || user.restrained() || !check_table(user) || !iscarbon(target))
return
if(istype(M))
take_victim(target,user)
else
return ..()
/obj/machinery/optable/verb/climb_on()
set name = "Climb On Table"
set category = "Object"

View File

@@ -469,14 +469,14 @@
ui_interact(user)
wires.Interact(user)
/obj/machinery/alarm/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/custom_state = null)
/obj/machinery/alarm/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state)
var/data[0]
var/remote_connection = 0
var/remote_access = 0
if(custom_state)
var/list/state = custom_state.href_list(user)
remote_connection = state["remote_connection"] // Remote connection means we're non-adjacent/connecting from another computer
remote_access = state["remote_access"] // Remote access means we also have the privilege to alter the air alarm.
if(state)
var/list/href = state.href_list(user)
remote_connection = href["remote_connection"] // Remote connection means we're non-adjacent/connecting from another computer
remote_access = href["remote_access"] // Remote access means we also have the privilege to alter the air alarm.
data["locked"] = locked && !user.isSilicon()
data["remote_connection"] = remote_connection
@@ -491,7 +491,7 @@
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
ui = new(user, src, ui_key, "air_alarm.tmpl", src.name, 325, 625, master_ui = master_ui, custom_state = custom_state)
ui = new(user, src, ui_key, "air_alarm.tmpl", src.name, 325, 625, master_ui = master_ui, state = state)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
@@ -616,7 +616,7 @@
data["thresholds"] = thresholds
/obj/machinery/alarm/CanUseTopic(var/mob/user, href_list, var/datum/topic_state/custom_state)
/obj/machinery/alarm/CanUseTopic(var/mob/user, var/datum/topic_state/state, var/href_list = list())
if(buildstage != 2)
return STATUS_CLOSE
@@ -627,17 +627,15 @@
. = shorted ? STATUS_DISABLED : STATUS_INTERACTIVE
if(. == STATUS_INTERACTIVE)
var/extra_href = custom_state.href_list(usr)
// Prevent remote users from altering RCON settings unless they already have access (I realize the risks)
var/extra_href = state.href_list(usr)
// Prevent remote users from altering RCON settings unless they already have access
if(href_list["rcon"] && extra_href["remote_connection"] && !extra_href["remote_access"])
. = STATUS_UPDATE
//TODO: Move the rest of if(!locked || extra_href["remote_access"] || usr.isAI()) and hrefs here
return min(..(), .)
/obj/machinery/alarm/Topic(href, href_list, var/nowindow = 0, var/datum/topic_state/custom_state)
if(..(href, href_list, nowindow, custom_state))
/obj/machinery/alarm/Topic(href, href_list, var/nowindow = 0, var/datum/topic_state/state)
if(..(href, href_list, nowindow, state))
return 1
// hrefs that can always be called -walter0o
@@ -666,7 +664,7 @@
return 1
// hrefs that need the AA unlocked -walter0o
var/extra_href = custom_state.href_list(usr)
var/extra_href = state.href_list(usr)
if(!(locked && !extra_href["remote_connection"]) || extra_href["remote_access"] || usr.isSilicon())
if(href_list["command"])
var/device_id = href_list["id_tag"]

View File

@@ -182,7 +182,7 @@
else
output += "<FONT color='red'>ERROR: Can not find input port</FONT> <A href='?src=\ref[src];in_refresh_status=1'>Search</A><BR>"
output += "Flow Rate Limit: <A href='?src=\ref[src];adj_input_flow_rate=-100'>-</A> <A href='?src=\ref[src];adj_input_flow_rate=-10'>-</A> <A href='?src=\ref[src];adj_input_flow_rate=-1'>-</A> <A href='?src=\ref[src];adj_input_flow_rate=-0.1'>-</A> [round(input_flow_setting, 0.1)] L/s <A href='?src=\ref[src];adj_input_flow_rate=0.1'>+</A> <A href='?src=\ref[src];adj_input_flow_rate=1'>+</A> <A href='?src=\ref[src];adj_input_flow_rate=10'>+</A> <A href='?src=\ref[src];adj_input_flow_rate=100'>+</A><BR>"
output += "<BR>"
@@ -230,7 +230,7 @@ Max Output Pressure: [output_pressure] kPa<BR>"}
spawn(1)
src.updateUsrDialog()
return 1
if(!radio_connection)
return 0
var/datum/signal/signal = new
@@ -239,32 +239,32 @@ Max Output Pressure: [output_pressure] kPa<BR>"}
if(href_list["in_refresh_status"])
input_info = null
signal.data = list ("tag" = input_tag, "status" = 1)
return 1
. = 1
if(href_list["in_toggle_injector"])
input_info = null
signal.data = list ("tag" = input_tag, "power_toggle" = 1)
return 1
. = 1
if(href_list["in_set_flowrate"])
input_info = null
signal.data = list ("tag" = input_tag, "set_volume_rate" = "[input_flow_setting]")
return 1
. = 1
if(href_list["out_refresh_status"])
output_info = null
signal.data = list ("tag" = output_tag, "status" = 1)
return 1
. = 1
if(href_list["out_toggle_power"])
output_info = null
signal.data = list ("tag" = output_tag, "power_toggle" = 1)
return 1
. = 1
if(href_list["out_set_pressure"])
output_info = null
signal.data = list ("tag" = output_tag, "set_internal_pressure" = "[pressure_setting]")
return 1
. = 1
signal.data["sigtype"]="command"
radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
@@ -302,7 +302,7 @@ Max Output Pressure: [output_pressure] kPa<BR>"}
else
output += "<FONT color='red'>ERROR: Can not find input port</FONT> <A href='?src=\ref[src];in_refresh_status=1'>Search</A><BR>"
output += "Flow Rate Limit: <A href='?src=\ref[src];adj_input_flow_rate=-100'>-</A> <A href='?src=\ref[src];adj_input_flow_rate=-10'>-</A> <A href='?src=\ref[src];adj_input_flow_rate=-1'>-</A> <A href='?src=\ref[src];adj_input_flow_rate=-0.1'>-</A> [round(input_flow_setting, 0.1)] L/s <A href='?src=\ref[src];adj_input_flow_rate=0.1'>+</A> <A href='?src=\ref[src];adj_input_flow_rate=1'>+</A> <A href='?src=\ref[src];adj_input_flow_rate=10'>+</A> <A href='?src=\ref[src];adj_input_flow_rate=100'>+</A><BR>"
output += "<BR>"
@@ -350,7 +350,7 @@ Min Core Pressure: [pressure_limit] kPa<BR>"}
spawn(1)
src.updateUsrDialog()
return 1
if(!radio_connection)
return 0
var/datum/signal/signal = new
@@ -359,32 +359,32 @@ Min Core Pressure: [pressure_limit] kPa<BR>"}
if(href_list["in_refresh_status"])
input_info = null
signal.data = list ("tag" = input_tag, "status" = 1)
return 1
. = 1
if(href_list["in_toggle_injector"])
input_info = null
signal.data = list ("tag" = input_tag, "power_toggle" = 1)
return 1
. = 1
if(href_list["in_set_flowrate"])
input_info = null
signal.data = list ("tag" = input_tag, "set_volume_rate" = "[input_flow_setting]")
return 1
. = 1
if(href_list["out_refresh_status"])
output_info = null
signal.data = list ("tag" = output_tag, "status" = 1)
return 1
. = 1
if(href_list["out_toggle_power"])
output_info = null
signal.data = list ("tag" = output_tag, "power_toggle" = 1)
return 1
. = 1
if(href_list["out_set_pressure"])
output_info = null
signal.data = list ("tag" = output_tag, "set_external_pressure" = "[pressure_setting]", "checks" = 1)
return 1
. = 1
signal.data["sigtype"]="command"
radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)

View File

@@ -0,0 +1,34 @@
/obj/machinery/bluespacerelay
name = "Emergency Bluespace Relay"
desc = "This sends messages through bluespace! Wow!"
icon = 'icons/obj/stationobjs.dmi'
icon_state = "bspacerelay"
anchored = 1
density = 1
use_power = 1
var/on = 1
idle_power_usage = 15000
active_power_usage = 15000
/obj/machinery/bluespacerelay/process()
update_power()
update_icon()
/obj/machinery/bluespacerelay/update_icon()
if(on)
icon_state = initial(icon_state)
else
icon_state = "[initial(icon_state)]_off"
/obj/machinery/bluespacerelay/proc/update_power()
if(stat & (BROKEN|NOPOWER|EMPED))
on = 0
else
on = 1

View File

@@ -8,7 +8,7 @@
active_power_usage = 10
layer = 5
var/list/network = list("SS13")
var/list/network = list("Exodus")
var/c_tag = null
var/c_tag_order = 999
var/status = 1

View File

@@ -78,7 +78,7 @@
if(isscrewdriver(W))
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
var/input = sanitize(input(usr, "Which networks would you like to connect this camera to? Separate networks with a comma. No Spaces!\nFor example: SS13,Security,Secret ", "Set Network", "SS13"))
var/input = sanitize(input(usr, "Which networks would you like to connect this camera to? Separate networks with a comma. No Spaces!\nFor example: Exodus,Security,Secret ", "Set Network", "Exodus"))
if(!input)
usr << "No input found please hang up and try your call again."
return
@@ -90,7 +90,7 @@
var/area/camera_area = get_area(src)
var/temptag = "[sanitize(camera_area.name)] ([rand(1, 999)])"
input = sanitizeSafe(input(usr, "How would you like to name the camera?", "Set Camera Name", temptag))
input = sanitizeSafe(input(usr, "How would you like to name the camera?", "Set Camera Name", temptag), MAX_NAME_LEN)
state = 4
var/obj/machinery/camera/C = new(src.loc)

View File

@@ -1,4 +1,94 @@
// PRESETS
#define NETWORK_CRESCENT "Crescent"
#define NETWORK_CIVILIAN_EAST "Civilian East"
#define NETWORK_CIVILIAN_WEST "Civilian West"
#define NETWORK_COMMAND "Command"
#define NETWORK_ENGINE "Engine"
#define NETWORK_ENGINEERING "Engineering"
#define NETWORK_ENGINEERING_OUTPOST "Engineering Outpost"
#define NETWORK_ERT "ERT"
#define NETWORK_EXODUS "Exodus"
#define NETWORK_MEDBAY "Medbay"
#define NETWORK_MINE "MINE"
#define NETWORK_RESEARCH "Research"
#define NETWORK_RESEARCH_OUTPOST "Research Outpost"
#define NETWORK_PRISON "Prison"
#define NETWORK_SECURITY "Security"
#define NETWORK_TELECOM "Tcomsat"
#define NETWORK_THUNDER "thunder"
var/global/list/station_networks = list(
NETWORK_CIVILIAN_EAST,
NETWORK_CIVILIAN_WEST,
NETWORK_COMMAND,
NETWORK_ENGINE,
NETWORK_ENGINEERING,
NETWORK_ENGINEERING_OUTPOST,
NETWORK_EXODUS,
NETWORK_MEDBAY,
NETWORK_MINE,
NETWORK_RESEARCH,
NETWORK_RESEARCH_OUTPOST,
NETWORK_PRISON,
NETWORK_SECURITY
)
var/global/list/engineering_networks = list(
NETWORK_ENGINE,
NETWORK_ENGINEERING,
NETWORK_ENGINEERING_OUTPOST,
"Atmosphere Alarms",
"Fire Alarms",
"Power Alarms")
/obj/machinery/camera/network/crescent
network = list(NETWORK_CRESCENT)
/obj/machinery/camera/network/civilian_east
network = list(NETWORK_CIVILIAN_EAST)
/obj/machinery/camera/network/civilian_west
network = list(NETWORK_CIVILIAN_WEST)
/obj/machinery/camera/network/command
network = list(NETWORK_COMMAND)
/obj/machinery/camera/network/engine
network = list(NETWORK_ENGINE)
/obj/machinery/camera/network/engineering
network = list(NETWORK_ENGINEERING)
/obj/machinery/camera/network/engineering_outpost
network = list(NETWORK_ENGINEERING_OUTPOST)
/obj/machinery/camera/network/ert
network = list(NETWORK_ERT)
/obj/machinery/camera/network/exodus
network = list(NETWORK_EXODUS)
/obj/machinery/camera/network/mining
network = list(NETWORK_MINE)
/obj/machinery/camera/network/prison
network = list(NETWORK_PRISON)
/obj/machinery/camera/network/medbay
network = list(NETWORK_MEDBAY)
/obj/machinery/camera/network/research
network = list(NETWORK_RESEARCH)
/obj/machinery/camera/network/research_outpost
network = list(NETWORK_RESEARCH_OUTPOST)
/obj/machinery/camera/network/security
network = list(NETWORK_SECURITY)
/obj/machinery/camera/network/telecom
network = list(NETWORK_TELECOM)
/obj/machinery/camera/network/thunder
network = list(NETWORK_THUNDER)
// EMP
@@ -11,6 +101,15 @@
/obj/machinery/camera/xray
icon_state = "xraycam" // Thanks to Krutchen for the icons.
/obj/machinery/camera/xray/security
network = list(NETWORK_SECURITY)
/obj/machinery/camera/xray/medbay
network = list(NETWORK_MEDBAY)
/obj/machinery/camera/xray/research
network = list(NETWORK_RESEARCH)
/obj/machinery/camera/xray/New()
..()
upgradeXRay()
@@ -23,6 +122,10 @@
// ALL UPGRADES
/obj/machinery/camera/all/command
network = list(NETWORK_COMMAND)
/obj/machinery/camera/all/New()
..()
upgradeEmpProof()
@@ -30,16 +133,6 @@
upgradeMotion()
// AUTONAME
/obj/machinery/camera/autoname/engineering_outpost
network = list("SS13", "Engineering Outpost")
/obj/machinery/camera/autoname/mining_outpost
network = list("SS13", "MINE")
/obj/machinery/camera/autoname/research_outpost
network = list("SS13", "Research Outpost")
/obj/machinery/camera/autoname
var/number = 0 //camera number in area
@@ -57,6 +150,7 @@
if(C.number)
number = max(number, C.number+1)
c_tag = "[A.name] #[number]"
invalidateCameraCache()
// CHECKS
@@ -97,3 +191,21 @@
if (isMotion())
mult++
active_power_usage = mult*initial(active_power_usage)
#undef NETWORK_CENTRAL_CRESCENT
#undef NETWORK_CIVILIAN_EAST
#undef NETWORK_CIVILIAN_WEST
#undef NETWORK_COMMAND
#undef NETWORK_ENGINE
#undef NETWORK_ENGINEERING
#undef NETWORK_ENGINEERING_OUTPOST
#undef NETWORK_ERT
#undef NETWORK_EXODUS
#undef NETWORK_MEDBAY
#undef NETWORK_MINE
#undef NETWORK_RESEARCH
#undef NETWORK_RESEARCH_OUTPOST
#undef NETWORK_PRISON
#undef NETWORK_SECURITY
#undef NETWORK_TELECOM
#undef NETWORK_THUNDER

View File

@@ -15,7 +15,6 @@
cameranet.process_sort()
var/list/T = list()
T["Cancel"] = "Cancel"
for (var/obj/machinery/camera/C in cameranet.cameras)
var/list/tempnetwork = C.network&src.network
if (tempnetwork.len)
@@ -30,11 +29,10 @@
set category = "AI Commands"
set name = "Show Camera List"
if(src.stat == 2)
src << "You can't list the cameras because you are dead!"
if(check_unable())
return
if (!camera || camera == "Cancel")
if (!camera)
return 0
var/obj/machinery/camera/C = track.cameras[camera]

View File

@@ -0,0 +1,34 @@
/obj/machinery/bluespacerelay
name = "Emergency Bluespace Relay"
desc = "This sends messages through bluespace! Wow!"
icon = 'icons/obj/stationobjs.dmi'
icon_state = "bspacerelay"
anchored = 1
density = 1
use_power = 1
var/on = 1
idle_power_usage = 15000
active_power_usage = 15000
/obj/machinery/bluespacerelay/process()
update_power()
update_icon()
/obj/machinery/bluespacerelay/update_icon()
if(on)
icon_state = initial(icon_state)
else
icon_state = "[initial(icon_state)]_off"
/obj/machinery/bluespacerelay/proc/update_power()
if(stat & (BROKEN|NOPOWER|EMPED))
on = 0
else
on = 1

View File

@@ -13,7 +13,7 @@ var/global/list/minor_air_alarms = list()
/obj/machinery/computer/atmos_alert/New()
..()
atmosphere_alarm.register(src, /obj/machinery/computer/station_alert/update_icon)
/obj/machinery/computer/atmos_alert/Del()
atmosphere_alarm.unregister(src)
..()
@@ -68,16 +68,13 @@ var/global/list/minor_air_alarms = list()
var/obj/machinery/alarm/air_alarm = alarm_source.source
if(istype(air_alarm))
var/list/new_ref = list("atmos_reset" = 1)
air_alarm.Topic(href, new_ref, custom_state = atmos_alert_topic)
air_alarm.Topic(href, new_ref, state = air_alarm_topic)
return 1
var/datum/topic_state/atmos_alert/atmos_alert_topic = new()
var/datum/topic_state/air_alarm_topic/air_alarm_topic = new()
/datum/topic_state/atmos_alert
flags = NANO_IGNORE_DISTANCE
/datum/topic_state/air_alarm/href_list(var/mob/user)
/datum/topic_state/air_alarm_topic/href_list(var/mob/user)
var/list/extra_href = list()
extra_href["remote_connection"] = 1
extra_href["remote_access"] = 1

View File

@@ -76,7 +76,7 @@
var/obj/machinery/alarm/alarm = locate(href_list["alarm"]) in (monitored_alarms ? monitored_alarms : machines)
if(alarm)
var/datum/topic_state/TS = generate_state(alarm)
alarm.ui_interact(usr, master_ui = ui_ref, custom_state = TS)
alarm.ui_interact(usr, master_ui = ui_ref, state = TS)
return 1
/obj/machinery/computer/atmoscontrol/proc/generate_state(var/alarm)
@@ -86,7 +86,6 @@
return state
/datum/topic_state/air_alarm
flags = NANO_IGNORE_DISTANCE
var/obj/machinery/computer/atmoscontrol/atmos_control = null
var/obj/machinery/alarm/air_alarm = null

View File

@@ -12,11 +12,16 @@
icon_state = "cameras"
var/obj/machinery/camera/current = null
var/last_pic = 1.0
var/list/network = list("SS13")
var/list/network
var/mapping = 0//For the overview file, interesting bit of code.
circuit = /obj/item/weapon/circuitboard/security
var/camera_cache = null
New()
if(!network)
network = station_networks
..()
attack_ai(var/mob/user as mob)
return attack_hand(user)
@@ -235,9 +240,13 @@
name = "engineering camera monitor"
desc = "Used to monitor fires and breaches."
icon_state = "engineeringcameras"
network = list("Engineering","Power Alarms","Atmosphere Alarms","Fire Alarms")
circuit = /obj/item/weapon/circuitboard/security/engineering
/obj/machinery/computer/security/engineering/New()
if(!network)
network = engineering_networks
..()
/obj/machinery/computer/security/nuclear
name = "head mounted camera monitor"
desc = "Used to access the built-in cameras in helmets."

View File

@@ -48,9 +48,7 @@
/obj/machinery/computer/communications/Topic(href, href_list)
if(..())
return 1
if (src.z > 1)
usr << "\red <b>Unable to establish a connection</b>: \black You're too far away from the station!"
return
usr.set_machine(src)
if(!href_list["operation"])
@@ -68,8 +66,8 @@
if (I && istype(I))
if(src.check_access(I))
authenticated = 1
if(access_captain in I.access)
authenticated = 2
//if(access_captain in I.access)
//authenticated = 2
crew_announcement.announcer = GetNameAndAssignmentFromId(I)
if("logout")
authenticated = 0
@@ -82,7 +80,7 @@
var/obj/item/device/pda/pda = I
I = pda.id
if (I && istype(I))
if(access_captain in I.access || access_heads in I.access) //Let heads change the alert level.
if(access_heads in I.access) //Let heads change the alert level.
var/old_level = security_level
if(!tmp_alertlevel) tmp_alertlevel = SEC_LEVEL_GREEN
if(tmp_alertlevel < SEC_LEVEL_GREEN) tmp_alertlevel = SEC_LEVEL_GREEN
@@ -106,7 +104,7 @@
usr << "You need to swipe your ID."
if("announce")
if(src.authenticated==2)
if(src.authenticated==1)
if(message_cooldown)
usr << "Please allow at least one minute to pass between announcements"
return
@@ -183,32 +181,35 @@
// OMG CENTCOMM LETTERHEAD
if("MessageCentcomm")
if(src.authenticated==2)
if(src.authenticated==1)
if(centcomm_message_cooldown)
usr << "\red Arrays recycling. Please stand by."
usr << "<span class='warning'>Arrays recycling. Please stand by.</span>"
return
if(!is_relay_online())//Contact Centcom has a check, Syndie doesn't to allow for Traitor funs.
usr <<"<span class='warning'>No Emergency Bluespace Relay detected. Unable to transmit message.</span>"
return
var/input = sanitize(input("Please choose a message to transmit to Centcomm via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response. There is a 30 second delay before you may send another message, be clear, full and concise.", "To abort, send an empty message.", ""))
if(!input || !(usr in view(1,src)))
return
Centcomm_announce(input, usr)
usr << "\blue Message transmitted."
usr << "<span class='notice'>Message transmitted.</span>"
log_say("[key_name(usr)] has made an IA Centcomm announcement: [input]")
centcomm_message_cooldown = 1
spawn(300)//10 minute cooldown
spawn(300)//30 second cooldown
centcomm_message_cooldown = 0
// OMG SYNDICATE ...LETTERHEAD
if("MessageSyndicate")
if((src.authenticated==2) && (src.emagged))
if((src.authenticated==1) && (src.emagged))
if(centcomm_message_cooldown)
usr << "\red Arrays recycling. Please stand by."
usr << "<span class='warning'>Arrays recycling. Please stand by.</span>"
return
var/input = sanitize(input(usr, "Please choose a message to transmit to \[ABNORMAL ROUTING CORDINATES\] via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response. There is a 30 second delay before you may send another message, be clear, full and concise.", "To abort, send an empty message.", ""))
if(!input || !(usr in view(1,src)))
return
Syndicate_announce(input, usr)
usr << "\blue Message transmitted."
usr << "<span class='notice'>Message transmitted.</span>"
log_say("[key_name(usr)] has made an illegal announcement: [input]")
centcomm_message_cooldown = 1
spawn(300)//10 minute cooldown
@@ -279,9 +280,6 @@
/obj/machinery/computer/communications/attack_hand(var/mob/user as mob)
if(..())
return
if (src.z > 6)
user << "\red <b>Unable to establish a connection</b>: \black You're too far away from the station!"
return
user.set_machine(src)
var/dat = "<head><title>Communications Console</title></head><body>"
@@ -301,7 +299,7 @@
if(STATE_DEFAULT)
if (src.authenticated)
dat += "<BR>\[ <A HREF='?src=\ref[src];operation=logout'>Log Out</A> \]"
if (src.authenticated==2)
if (src.authenticated==1)
dat += "<BR>\[ <A HREF='?src=\ref[src];operation=announce'>Make An Announcement</A> \]"
if(src.emagged == 0)
dat += "<BR>\[ <A HREF='?src=\ref[src];operation=MessageCentcomm'>Send an emergency message to Centcomm</A> \]"
@@ -430,6 +428,10 @@
if ((!( ticker ) || !emergency_shuttle.location()))
return
if(!universe.OnShuttleCall(usr))
user << "<span class='notice'>Cannot establish a bluespace connection.</span>"
return
if(deathsquad.deployed)
user << "Centcom will not allow the shuttle to be called. Consider all contracts terminated."
return
@@ -439,7 +441,7 @@
return
if(world.time < 6000) // Ten minute grace period to let the game get going without lolmetagaming. -- TLE
user << "The emergency shuttle is refueling. Please wait another [round((6000-world.time)/60)] minutes before trying again."
user << "The emergency shuttle is refueling. Please wait another [round((6000-world.time)/600)] minute\s before trying again."
return
if(emergency_shuttle.going_to_centcom())
@@ -519,6 +521,13 @@
message_admins("[key_name_admin(user)] has recalled the shuttle.", 1)
return
/proc/is_relay_online()
for(var/obj/machinery/bluespacerelay/M in world)
if(M.stat == 0)
return 1
return 0
/obj/machinery/computer/communications/proc/post_status(var/command, var/data1, var/data2)
var/datum/radio_frequency/frequency = radio_controller.return_frequency(1435)

View File

@@ -4,13 +4,17 @@
desc = "Used to access the station's automated alert system."
icon_state = "alert:0"
circuit = "/obj/item/weapon/circuitboard/stationalert"
var/alarms = list("Fire"=list(), "Atmosphere"=list(), "Power"=list())
var/obj/nano_module/alarm_monitor/engineering/alarm_monitor
var/obj/nano_module/alarm_monitor/alarm_monitor
var/monitor_type = /obj/nano_module/alarm_monitor/engineering
/obj/machinery/computer/station_alert/security
name = "Security Alert Console"
monitor_type = /obj/nano_module/alarm_monitor/security
/obj/machinery/computer/station_alert/New()
alarm_monitor = new(src)
alarm_monitor.register(src, /obj/machinery/computer/station_alert/update_icon)
..()
alarm_monitor = new monitor_type(src)
alarm_monitor.register(src, /obj/machinery/computer/station_alert/update_icon)
/obj/machinery/computer/station_alert/Del()
alarm_monitor.unregister(src)

View File

@@ -36,10 +36,10 @@
if(damage >= 10)
if(src.density)
visible_message("<span class='danger'>\The [user] forces \the [src] open!</span>")
open()
open(1)
else
visible_message("<span class='danger'>\The [user] forces \the [src] closed!</span>")
close()
close(1)
else
visible_message("<span class='notice'>\The [user] strains fruitlessly to force \the [src] [density ? "open" : "closed"].</span>")
return
@@ -610,7 +610,7 @@ About the new airlock wires panel:
..(user)
return
/obj/machinery/door/airlock/CanUseTopic(var/mob/user, href_list)
/obj/machinery/door/airlock/CanUseTopic(var/mob/user)
if(!user.isSilicon())
return STATUS_CLOSE
@@ -627,7 +627,7 @@ About the new airlock wires panel:
user << "<span class='warning'>Unable to interface: Connection refused.</span>"
return STATUS_CLOSE
return STATUS_INTERACTIVE
return ..()
/obj/machinery/door/airlock/Topic(href, href_list, var/nowindow = 0)
if(..())
@@ -776,7 +776,7 @@ About the new airlock wires panel:
user << "\blue The airlock's motors resist your efforts to force it."
else if(locked)
user << "\blue The airlock's bolts prevent it from being forced."
else if( !welded && !operating )
else
if(density)
spawn(0) open(1)
else
@@ -825,11 +825,8 @@ About the new airlock wires panel:
return
/obj/machinery/door/airlock/open(var/forced=0)
if(!can_open())
if(!can_open(forced))
return 0
if(!forced)
if( !arePowerSystemsOn() || isWireCut(AIRLOCK_WIRE_OPEN_DOOR) )
return 0
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', 100, 1)
@@ -839,7 +836,11 @@ About the new airlock wires panel:
src.closeOther.close()
return ..()
/obj/machinery/door/airlock/can_open()
/obj/machinery/door/airlock/can_open(var/forced=0)
if(!forced)
if(!arePowerSystemsOn() || isWireCut(AIRLOCK_WIRE_OPEN_DOOR))
return 0
if(locked || welded)
return 0
return ..()

View File

@@ -1,7 +1,4 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
#define DOOR_OPEN_LAYER 2.7 //Under all objects if opened. 2.7 due to tables being at 2.6
#define DOOR_CLOSED_LAYER 3.1 //Above most items if closed
#define DOOR_REPAIR_AMOUNT 50 //amount of health regained per stack amount used
/obj/machinery/door
@@ -37,6 +34,9 @@
dir = EAST
var/width = 1
// turf animation
var/atom/movable/overlay/c_animation = null
/obj/machinery/door/attack_generic(var/mob/user, var/damage)
if(damage >= 10)
visible_message("<span class='danger'>\The [user] smashes into the [src]!</span>")
@@ -307,6 +307,17 @@
update_icon()
return
/obj/machinery/door/examine(mob/user)
..()
if(src.health < src.maxhealth / 4)
user << "\The [src] looks like it's about to break!"
else if(src.health < src.maxhealth / 2)
user << "\The [src] looks seriously damaged!"
else if(src.health < src.maxhealth * 3/4)
user << "\The [src] shows signs of damage!"
/obj/machinery/door/proc/set_broken()
stat |= BROKEN
for (var/mob/O in viewers(src, null))
@@ -377,9 +388,8 @@
return
/obj/machinery/door/proc/open()
if(!can_open()) return
if(!operating) operating = 1
/obj/machinery/door/proc/open(var/forced = 0)
if(!can_open(forced)) return
do_animate("opening")
icon_state = "door0"
@@ -403,8 +413,8 @@
/obj/machinery/door/proc/next_close_time()
return world.time + (normalspeed ? 150 : 5)
/obj/machinery/door/proc/close()
if(!can_close())
/obj/machinery/door/proc/close(var/forced = 0)
if(!can_close(forced))
return
operating = 1

View File

@@ -135,11 +135,12 @@
return 1
else
user << "\red You have no idea what you can cook with this [O]."
return 1
..()
src.updateUsrDialog()
/obj/machinery/microwave/attack_ai(mob/user as mob)
return 0
if(istype(user, /mob/living/silicon/robot) && Adjacent(user))
attack_hand(user)
/obj/machinery/microwave/attack_hand(mob/user as mob)
user.set_machine(src)

View File

@@ -140,6 +140,7 @@
S.dry = 1
item_quants[S.name]--
S.name = "dried [S.name]"
S.color = "#AAAAAA"
S.loc = loc
else
var/D = S.dried_type
@@ -244,7 +245,7 @@
..()
/obj/machinery/smartfridge/attack_ai(mob/user as mob)
return 0
attack_hand(user)
/obj/machinery/smartfridge/attack_hand(mob/user as mob)
if(stat & (NOPOWER|BROKEN))

View File

@@ -185,7 +185,7 @@ Class Procs:
/obj/machinery/proc/inoperable(var/additional_flags = 0)
return (stat & (NOPOWER|BROKEN|additional_flags))
/obj/machinery/CanUseTopic(var/mob/user, var/be_close)
/obj/machinery/CanUseTopic(var/mob/user)
if(!interact_offline && (stat & (NOPOWER|BROKEN)))
return STATUS_CLOSE

View File

@@ -496,7 +496,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon)))
usr.set_machine(src)
if(href_list["set_channel_name"])
src.channel_name = sanitizeSafe(input(usr, "Provide a Feed Channel Name", "Network Channel Handler", ""))
src.channel_name = sanitizeSafe(input(usr, "Provide a Feed Channel Name", "Network Channel Handler", ""), MAX_LNAME_LEN)
src.updateUsrDialog()
//src.update_icon()
@@ -596,7 +596,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
src.updateUsrDialog()
else if(href_list["set_wanted_name"])
src.channel_name = sanitizeSafe(input(usr, "Provide the name of the Wanted person", "Network Security Handler", ""))
src.channel_name = sanitizeSafe(input(usr, "Provide the name of the Wanted person", "Network Security Handler", ""), MAX_LNAME_LEN)
src.updateUsrDialog()
else if(href_list["set_wanted_desc"])

View File

@@ -214,7 +214,7 @@
usr << "<span class='notice'>\The [src] has to be secured first!</span>"
return STATUS_CLOSE
return STATUS_INTERACTIVE
return ..()
/obj/machinery/porta_turret/Topic(href, href_list, var/nowindow = 0)
@@ -858,8 +858,7 @@
return
if(istype(I, /obj/item/weapon/pen)) //you can rename turrets like bots!
var/t = input(user, "Enter new turret name", name, finish_name) as text
t = sanitize(t)
var/t = sanitizeSafe(input(user, "Enter new turret name", name, finish_name) as text, MAX_NAME_LEN)
if(!t)
return
if(!in_range(src, usr) && loc != usr)

View File

@@ -250,7 +250,7 @@ var/list/obj/machinery/requests_console/allConsoles = list()
if(href_list["sendAnnouncement"])
if(!announcementConsole) return
announcement.Announce(message)
announcement.Announce(message, msg_sanitized = 1)
reset_announce()
screen = 0

View File

@@ -79,7 +79,7 @@
if(isLocked(user))
return STATUS_CLOSE
return STATUS_INTERACTIVE
return ..()
/obj/machinery/turretid/attackby(obj/item/weapon/W, mob/user)
if(stat & BROKEN)

View File

@@ -179,12 +179,15 @@
return
/obj/machinery/vending/attackby(obj/item/weapon/W as obj, mob/user as mob)
var/obj/item/weapon/card/id/I = W.GetID()
if (currently_vending && vendor_account && !vendor_account.suspended)
var/paid = 0
var/handled = 0
if(istype(W, /obj/item/weapon/card/id))
var/obj/item/weapon/card/id/C = W
paid = pay_with_card(C)
if (I) //for IDs and PDAs and wallets with IDs
paid = pay_with_card(I,W)
handled = 1
else if (istype(W, /obj/item/weapon/spacecash/ewallet))
var/obj/item/weapon/spacecash/ewallet/C = W
@@ -202,9 +205,12 @@
nanomanager.update_uis(src)
return // don't smack that machine with your 2 thalers
if (istype(W, /obj/item/weapon/card/emag))
if (I || istype(W, /obj/item/weapon/spacecash))
attack_hand(user)
return
else if (istype(W, /obj/item/weapon/card/emag))
src.emagged = 1
user << "You short out the product lock on [src]"
user << "You short out the product lock on \the [src]"
return
else if(istype(W, /obj/item/weapon/screwdriver))
src.panel_open = !src.panel_open
@@ -224,7 +230,7 @@
W.loc = src
coin = W
categories |= CAT_COIN
user << "\blue You insert the [W] into the [src]"
user << "\blue You insert \the [W] into \the [src]"
nanomanager.update_uis(src)
return
else if(istype(W, /obj/item/weapon/wrench))
@@ -234,9 +240,9 @@
switch (anchored)
if (0)
anchored = 1
user.visible_message("[user] tightens the bolts securing \the [src] to the floor.", "You tighten the bolts securing \the [src] to the floor.")
user.visible_message("\The [user] tightens the bolts securing \the [src] to the floor.", "You tighten the bolts securing \the [src] to the floor.")
if (1)
user.visible_message("[user] unfastens the bolts securing \the [src] to the floor.", "You unfasten the bolts securing \the [src] to the floor.")
user.visible_message("\The [user] unfastens the bolts securing \the [src] to the floor.", "You unfasten the bolts securing \the [src] to the floor.")
anchored = 0
return
@@ -266,7 +272,7 @@
if(istype(cashmoney, /obj/item/weapon/spacecash/bundle))
// Bundles can just have money subtracted, and will work
visible_message("<span class='info'>[usr] inserts some cash into [src].</span>")
visible_message("<span class='info'>\The [usr] inserts some cash into \the [src].</span>")
var/obj/item/weapon/spacecash/bundle/cashmoney_bundle = cashmoney
cashmoney_bundle.worth -= currently_vending.price
@@ -281,7 +287,7 @@
// This is really dirty, but there's no superclass for all bills, so we
// just assume that all spacecash that's not something else is a bill
visible_message("<span class='info'>[usr] inserts a bill into [src].</span>")
visible_message("<span class='info'>\The [usr] inserts a bill into \the [src].</span>")
var/left = cashmoney.worth - currently_vending.price
usr.drop_from_inventory(cashmoney)
del(cashmoney)
@@ -300,7 +306,7 @@
* successful, 0 if failed.
*/
/obj/machinery/vending/proc/pay_with_ewallet(var/obj/item/weapon/spacecash/ewallet/wallet)
visible_message("<span class='info'>[usr] swipes a card through [src].</span>")
visible_message("<span class='info'>\The [usr] swipes \the [wallet] through \the [src].</span>")
if(currently_vending.price > wallet.worth)
src.status_message = "Insufficient funds on chargecard."
src.status_error = 1
@@ -316,8 +322,11 @@
* Takes payment for whatever is the currently_vending item. Returns 1 if
* successful, 0 if failed
*/
/obj/machinery/vending/proc/pay_with_card(var/obj/item/weapon/card/id/I)
visible_message("<span class='info'>[usr] swipes a card through [src].</span>")
/obj/machinery/vending/proc/pay_with_card(var/obj/item/weapon/card/id/I, var/obj/item/ID_container)
if(I==ID_container || ID_container == null)
visible_message("<span class='info'>\The [usr] swipes \the [I] through \the [src].</span>")
else
visible_message("<span class='info'>\The [usr] swipes \the [ID_container] through \the [src].</span>")
var/datum/money_account/customer_account = get_account(I.associated_account_number)
if (!customer_account)
src.status_message = "Error: Unable to access account. Please contact technical support if problem persists."
@@ -470,17 +479,6 @@
if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))))
if ((href_list["vend"]) && (src.vend_ready) && (!currently_vending))
if(istype(usr,/mob/living/silicon))
if(istype(usr,/mob/living/silicon/robot))
var/mob/living/silicon/robot/R = usr
if(!(R.module && istype(R.module,/obj/item/weapon/robot_module/butler) ))
usr << "\red The vending machine refuses to interface with you, as you are not in its target demographic!"
return
else
usr << "\red The vending machine refuses to interface with you, as you are not in its target demographic!"
return
if((!allowed(usr)) && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH
usr << "<span class='warning'>Access denied.</span>" //Unless emagged of course
flick(icon_deny,src)
@@ -495,6 +493,9 @@
if(R.price <= 0)
src.vend(R, usr)
else if(istype(usr,/mob/living/silicon)) //If the item is not free, provide feedback if a synth is trying to buy something.
usr << "<span class='danger'>Artificial unit recognized. Artificial units cannot complete this transaction. Purchase canceled.</span>"
return
else
src.currently_vending = R
if(!vendor_account || vendor_account.suspended)
@@ -529,7 +530,7 @@
return
if(coin.string_attached)
if(prob(50))
user << "\blue You successfully pull the coin out before the [src] could swallow it."
user << "\blue You successfully pull the coin out before \the [src] could swallow it."
else
user << "\blue You weren't able to pull the coin out fast enough, the machine ate it, string and all."
del(coin)
@@ -558,7 +559,7 @@
/obj/machinery/vending/proc/stock(var/datum/data/vending_product/R, var/mob/user)
if(src.panel_open)
user << "\blue You stock the [src] with \a [R.product_name]"
user << "\blue You stock \the [src] with \a [R.product_name]"
R.amount++
nanomanager.update_uis(src)
@@ -592,7 +593,7 @@
return
for(var/mob/O in hearers(src, null))
O.show_message("<span class='game say'><span class='name'>[src]</span> beeps, \"[message]\"",2)
O.show_message("<span class='game say'><span class='name'>\The [src]</span> beeps, \"[message]\"",2)
return
/obj/machinery/vending/power_change()
@@ -938,7 +939,7 @@
desc = "Spare tool vending. What? Did you expect some witty description?"
icon_state = "engivend"
icon_deny = "engivend-deny"
req_access = list(access_engine_equip) //Engineering Equipment access
req_access = list(access_engine_equip)
products = list(/obj/item/clothing/glasses/meson = 2,/obj/item/device/multitool = 4,/obj/item/weapon/airlock_electronics = 10,/obj/item/weapon/module/power_control = 10,/obj/item/weapon/airalarm_electronics = 10,/obj/item/weapon/cell/high = 10)
contraband = list(/obj/item/weapon/cell/potato = 3)
premium = list(/obj/item/weapon/storage/belt/utility = 3)

View File

@@ -79,6 +79,14 @@
xeno_spawn += loc
del(src)
if("endgame_exit")
endgame_safespawns += loc
del(src)
if("bluespacerift")
endgame_exits += loc
del(src)
landmarks_list += src
return 1

View File

@@ -3,6 +3,10 @@
unacidable = 1
var/i_attached//Added for possible image attachments to objects. For hallucinations and the like.
/obj/effect/overlay/Destroy()
PlaceInPool(src)
return 1 //cancels the GCing
/obj/effect/overlay/beam//Not actually a projectile, just an effect.
name="beam"
icon='icons/effects/beam.dmi'
@@ -31,4 +35,10 @@
/obj/effect/overlay/coconut
name = "Coconuts"
icon = 'icons/misc/beach.dmi'
icon_state = "coconuts"
icon_state = "coconuts"
/obj/effect/overlay/bluespacify
name = "Bluespace"
icon = 'icons/turf/space.dmi'
icon_state = "bluespacify"
layer = LIGHTING_LAYER

View File

@@ -49,7 +49,7 @@
return
if (!in_range(src, user) && src.loc != user)
return
t = sanitize(t)
t = sanitizeSafe(t, MAX_NAME_LEN)
if (t)
src.name = "body bag - "
src.name += t

5
code/game/objects/items/devices/PDA/PDA.dm Executable file → Normal file
View File

@@ -542,7 +542,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
if (!ui)
// the ui does not exist, so we'll create a new() one
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
ui = new(user, src, ui_key, "pda.tmpl", title, 520, 400)
ui = new(user, src, ui_key, "pda.tmpl", title, 520, 400, state = inventory_state)
// when the ui is first opened this is the data it will use
ui.load_cached_data(ManifestJSON)
@@ -825,7 +825,8 @@ var/global/list/obj/item/device/pda/PDAs = list()
difficulty += P.cartridge.access_engine
difficulty += P.cartridge.access_clown
difficulty += P.cartridge.access_janitor
difficulty += 3 * P.hidden_uplink
if(P.hidden_uplink)
difficulty += 3
if(prob(difficulty))
U.show_message("\red An error flashes on your [src].", 1)

View File

@@ -53,6 +53,9 @@ datum/nano_item_lists
var/uplink_owner = null//text-only
var/used_TC = 0
/obj/item/device/uplink/nano_host()
return loc
/obj/item/device/uplink/New()
..()
welcome = ticker.mode.uplink_welcome
@@ -219,7 +222,7 @@ datum/nano_item_lists
if (!ui)
// the ui does not exist, so we'll create a new() one
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
ui = new(user, src, ui_key, "uplink.tmpl", title, 450, 600)
ui = new(user, src, ui_key, "uplink.tmpl", title, 450, 600, state = inventory_state)
// when the ui is first opened this is the data it will use
ui.set_initial_data(data)
// open the new ui window

View File

@@ -291,21 +291,14 @@
..()
if(istype(W, /obj/item/device/flash))
if(istype(user,/mob/living/silicon/robot))
user << "\red How do you propose to do that?"
return
else if(src.flash1 && src.flash2)
user << "\blue You have already inserted the eyes!"
return
else if(src.flash1)
user.drop_item()
W.loc = src
src.flash2 = W
user << "\blue You insert the flash into the eye socket!"
var/current_module = user.get_active_hand()
if(current_module == W)
user << "<span class='warning'>How do you propose to do that?</span>"
return
else
add_flashes(W,user)
else
user.drop_item()
W.loc = src
src.flash1 = W
user << "\blue You insert the flash into the eye socket!"
add_flashes(W,user)
else if(istype(W, /obj/item/weapon/stock_parts/manipulator))
user << "\blue You install some manipulators and modify the head, creating a functional spider-bot!"
new /mob/living/simple_animal/spiderbot(get_turf(loc))
@@ -315,6 +308,22 @@
return
return
/obj/item/robot_parts/head/proc/add_flashes(obj/item/W as obj, mob/user as mob) //Made into a seperate proc to avoid copypasta
if(src.flash1 && src.flash2)
user << "<span class='notice'>You have already inserted the eyes!</span>"
return
else if(src.flash1)
user.drop_item()
W.loc = src
src.flash2 = W
user << "<span class='notice'>You insert the flash into the eye socket!</span>"
else
user.drop_item()
W.loc = src
src.flash1 = W
user << "<span class='notice'>You insert the flash into the eye socket!</span>"
/obj/item/robot_parts/attackby(obj/item/W as obj, mob/user as mob)
if(istype(W,/obj/item/weapon/card/emag))
if(sabotaged)

View File

@@ -28,6 +28,9 @@
/datum/matter_synth/medicine
name = "Medicine Synthesizer"
/datum/matter_synth/nanite
name = "Nanite Synthesizer"
/datum/matter_synth/metal
name = "Metal Synthesizer"

View File

@@ -161,6 +161,7 @@
singular_name = "reinforced glass sheet"
icon_state = "sheet-rglass"
charge_costs = list(500, 1000)
stacktype = /obj/item/stack/sheet/glass/reinforced
/*
* Phoron Glass sheets

View File

@@ -146,7 +146,7 @@ var/global/list/datum/stack_recipe/wood_recipes = list ( \
new/datum/stack_recipe("wooden sandals", /obj/item/clothing/shoes/sandal, 1), \
new/datum/stack_recipe("wood floor tile", /obj/item/stack/tile/wood, 1, 4, 20), \
new/datum/stack_recipe("table parts", /obj/item/weapon/table_parts/wood, 2), \
new/datum/stack_recipe("wooden chair", /obj/structure/bed/chair/wood/normal, 3, time = 10, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("wooden chair", /obj/structure/bed/chair/wood, 3, time = 10, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("wooden barricade", /obj/structure/barricade/wooden, 5, time = 50, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("crossbow frame", /obj/item/weapon/crossbowframe, 5, time = 25, one_per_turf = 0, on_floor = 0), \
new/datum/stack_recipe("wooden door", /obj/structure/mineral_door/wood, 10, time = 20, one_per_turf = 1, on_floor = 1), \

View File

@@ -54,14 +54,9 @@ RSF
user << "Changed dispensing mode to 'Dice Pack'"
return
if (mode == 5)
mode = 6
mode = 1
user << "Changed dispensing mode to 'Cigarette'"
return
if (mode == 6)
mode = 1
user << "Changed dispensing mode to 'Dosh'"
return
// Change mode
/obj/item/weapon/rsf/afterattack(atom/A, mob/user as mob, proximity)
@@ -84,8 +79,8 @@ RSF
switch(mode)
if(1)
product = new /obj/item/weapon/spacecash/c10()
used_energy = 200
product = new /obj/item/clothing/mask/smokable/cigarette()
used_energy = 10
if(2)
product = new /obj/item/weapon/reagent_containers/food/drinks/drinkingglass()
used_energy = 50
@@ -98,9 +93,6 @@ RSF
if(5)
product = new /obj/item/weapon/storage/pill_bottle/dice()
used_energy = 200
if(6)
product = new /obj/item/clothing/mask/smokable/cigarette()
used_energy = 10
user << "Dispensing [product ? product : "product"]..."
product.loc = get_turf(A)

View File

@@ -224,13 +224,13 @@
/obj/item/weapon/card/id/syndicate/attack_self(mob/user as mob)
if(!src.registered_name)
//Stop giving the players unsanitized unputs! You are giving ways for players to intentionally crash clients! -Nodrak
var t = sanitizeName(input(user, "What name would you like to put on this card?", "Agent card name", ishuman(user) ? user.real_name : user.name))
var t = sanitizeName(input(user, "What name would you like to put on this card?", "Agent card name", ishuman(user) ? user.real_name : user.name), MAX_NAME_LEN)
if(!t) //Same as mob/new_player/prefrences.dm
alert("Invalid name.")
return
src.registered_name = t
var u = sanitize(input(user, "What occupation would you like to put on this card?\nNote: This will not grant any access levels other than Maintenance.", "Agent card job assignment", "Agent"))
var u = sanitize(input(user, "What occupation would you like to put on this card?\nNote: This will not grant any access levels other than Maintenance.", "Agent card job assignment", "Agent"), MAX_LNAME_LEN)
if(!u)
alert("Invalid assignment.")
src.registered_name = ""

View File

@@ -5,16 +5,23 @@
/obj/item/weapon/circuitboard/security
name = T_BOARD("security camera monitor")
build_path = /obj/machinery/computer/security
var/network = list("SS13")
req_access = list(access_security)
var/list/network
var/locked = 1
var/emagged = 0
/obj/item/weapon/circuitboard/security/New()
..()
network = station_networks
/obj/item/weapon/circuitboard/security/engineering
name = T_BOARD("engineering camera monitor")
build_path = /obj/machinery/computer/security/engineering
network = list("Engineering","Power Alarms","Atmosphere Alarms","Fire Alarms")
req_access = list()
/obj/item/weapon/circuitboard/security/engineering/New()
..()
network = engineering_networks
/obj/item/weapon/circuitboard/security/mining
name = T_BOARD("mining camera monitor")

View File

@@ -0,0 +1,16 @@
#ifndef T_BOARD
#error T_BOARD macro is not defined but we need it!
#endif
/obj/item/weapon/circuitboard/bluespacerelay
name = T_BOARD("bluespacerelay")
build_path = "/obj/machinery/bluespacerelay"
board_type = "machine"
origin_tech = "bluespace=4,programming=4"
frame_desc = "Requires 30 Cable Coil, 1 Hyperwave Filter and 1 Ansible Crystal, and 2 Micro-Manipulators"
req_components = list(
"/obj/item/stack/cable_coil" = 30,
"/obj/item/weapon/stock_parts/manipulator" = 2,
"/obj/item/weapon/stock_parts/subspace/filter" = 1,
"/obj/item/weapon/stock_parts/subspace/crystal" = 1,
)

View File

@@ -26,7 +26,7 @@
return
if((!in_range(src, usr) && src.loc != user))
return
t = sanitize(t)
t = sanitizeSafe(t, MAX_NAME_LEN)
if(t)
src.name = text("Glass Case - '[]'", t)
else

View File

@@ -98,7 +98,7 @@
<br>
<h2>OPERATING PRINCIPLES</h2>
<br>
<li>The supermatter crystal serves as the fundamental power source of the engine. Upon being charged, it begins to emit large amounts of heat and radiation, as well and oxygen and plasma. As oxygen accelerates the reaction, and plasma carries the risk of fire, these must be filtered out. NOTE: Supermatter radiation will not charge radiation collectors.</li>
<li>The supermatter crystal serves as the fundamental power source of the engine. Upon being charged, it begins to emit large amounts of heat and radiation, as well and oxygen and phoron gas. As oxygen accelerates the reaction, and phoron carries the risk of fire, these must be filtered out. NOTE: Supermatter radiation will not charge radiation collectors.</li>
<br>
<li>Air in the reactor chamber housing the supermatter is circulated through the reactor loop, which passes through the filters and thermoelectric generators. The thermoelectric generators transfer heat from the reactor loop to the colder radiator loop, thereby generating power. Additional power is generated from internal turbines in the circulators.</li>
<br>
@@ -106,7 +106,7 @@
<br>
<li>The MK 1 Prototype Thermoelectric Supermatter Engine is designed to operate at reactor temperatures of 3000K to 4000K and generate up to 1MW of power. Beyond 1MW, the thermoelectric generators will begin to lose power through electrical discharge, reducing efficiency, but additional power generation remains feasible.</li>
<br>
<li>The crystal structure of the supermatter will begin to liquefy if its temperature exceeds 5000K. This eventually results in a massive release of light, heat and radiation, disintegration of both the supermatter crystal and most of the surrounding area, and as as-of-yet poorly documented psychological effects on all animals within a 2km. Appropriate action should be taken to stabilize or eject the supermatter before such occurs.</li>
<li>The crystal structure of the supermatter will begin to liquefy if its temperature exceeds 5000K. This eventually results in a massive release of light, heat and radiation, disintegration of both the supermatter crystal and most of the surrounding area, and as as-of-yet poorly documented psychological effects on all animals within a 2km radius. Appropriate action should be taken to stabilize or eject the supermatter before such occurs.</li>
<br>
<h2>SUPERMATTER HANDLING</h2>
<li>Do not expose supermatter to oxygen.</li>
@@ -125,7 +125,7 @@
<ol>
<li>Ensure that radiation protection and meson goggles are worn at all times while working in the engine room.</li>
<li>Ensure that reactor and radiator loops are undamaged and unobstructed.</li>
<li>Ensure that plasma and oxygen gas exhaust from filters is properly contained or disposed. Do not allow exhaust pressure to exceed 4500 kPa.</li>
<li>Ensure that phoron and oxygen gas exhaust from filters is properly contained or disposed. Do not allow exhaust pressure to exceed 4500 kPa.</li>
<li>Ensure that engine room Area Power Controller (APC) and engine Superconducting Magnetic Energy Storage unit (SMES) are properly charged.</li>
<li>Ensure that reactor temperature does not exceed 5000K. In event of reactor temperature exceeding 5000K, see EMERGENCY COOLING PROCEDURE.</li>
<li>In event of imminent and/or unavoidable delamination, see EJECTION PROCEDURE.</li>

View File

@@ -9,6 +9,9 @@
var/tape_type = /obj/item/tape
var/icon_base
var/list/image/hazard_overlays
var/list/tape_roll_applications = list()
/obj/item/tape
name = "tape"
icon = 'icons/policetape.dmi'
@@ -17,6 +20,15 @@
var/crumpled = 0
var/icon_base
/obj/item/tape/New()
..()
if(!hazard_overlays)
hazard_overlays = list()
hazard_overlays["[NORTH]"] = new/image('icons/effects/warning_stripes.dmi', icon_state = "N")
hazard_overlays["[EAST]"] = new/image('icons/effects/warning_stripes.dmi', icon_state = "E")
hazard_overlays["[SOUTH]"] = new/image('icons/effects/warning_stripes.dmi', icon_state = "S")
hazard_overlays["[WEST]"] = new/image('icons/effects/warning_stripes.dmi', icon_state = "W")
/obj/item/taperoll/police
name = "police tape"
desc = "A roll of police tape used to block off crime scenes from the public."
@@ -98,7 +110,10 @@
usr << "\blue You finish placing the [src]." //Git Test
/obj/item/taperoll/afterattack(var/atom/A, mob/user as mob, proximity)
if (proximity && istype(A, /obj/machinery/door/airlock))
if(!proximity)
return
if (istype(A, /obj/machinery/door/airlock))
var/turf/T = get_turf(A)
var/obj/item/tape/P = new tape_type(T.x,T.y,T.z)
P.loc = locate(T.x,T.y,T.z)
@@ -106,6 +121,23 @@
P.layer = 3.2
user << "\blue You finish placing the [src]."
if (istype(A, /turf/simulated/floor) ||istype(A, /turf/unsimulated/floor))
var/turf/F = A
var/direction = user.loc == F ? user.dir : turn(user.dir, 180)
var/icon/hazard_overlay = hazard_overlays["[direction]"]
if(tape_roll_applications[F] == null)
tape_roll_applications[F] = 0
if(tape_roll_applications[F] & direction) // hazard_overlay in F.overlays wouldn't work.
user.visible_message("[user] uses the adhesive of \the [src] to remove area markings from \the [F].", "You use the adhesive of \the [src] to remove area markings from \the [F].")
F.overlays -= hazard_overlay
tape_roll_applications[F] &= ~direction
else
user.visible_message("[user] applied \the [src] on \the [F] to create area markings.", "You apply \the [src] on \the [F] to create area markings.")
F.overlays |= hazard_overlay
tape_roll_applications[F] |= direction
return
/obj/item/tape/proc/crumple()
if(!crumpled)
crumpled = 1

View File

@@ -16,15 +16,14 @@
var/damtype = "brute"
var/force = 0
/obj/Topic(href, href_list, var/nowindow = 0, var/datum/topic_state/custom_state = default_state)
/obj/Topic(href, href_list, var/nowindow = 0, var/datum/topic_state/state = default_state)
// Calling Topic without a corresponding window open causes runtime errors
if(!nowindow && ..())
return 1
// In the far future no checks are made in an overriding Topic() beyond if(..()) return
// Instead any such checks are made in CanUseTopic()
var/obj/host = nano_host()
if(host.CanUseTopic(usr, href_list, custom_state) == STATUS_INTERACTIVE)
if(CanUseTopic(usr, state, href_list) == STATUS_INTERACTIVE)
CouldUseTopic(usr)
return 0

View File

@@ -2,6 +2,7 @@
icon = 'icons/obj/barsigns.dmi'
icon_state = "empty"
anchored = 1
var/cult = 0
New()
ChangeSign(pick("pinkflamingo", "magmasea", "limbo", "rustyaxe", "armokbar", "brokendrum", "meadbay", "thedamnwall", "thecavern", "cindikate", "theorchard", "thesaucyclown", "theclownshead", "whiskeyimplant", "carpecarp", "robustroadhouse", "greytide", "theredshirt"))
return
@@ -12,6 +13,9 @@
return
/obj/structure/sign/double/barsign/attackby(obj/item/I, mob/user)
if(cult)
return
if(istype(I, /obj/item/weapon/card/id))
var/obj/item/weapon/card/id/card = I
if(access_bar in card.GetAccess())

View File

@@ -249,6 +249,10 @@
src.add_fingerprint(user)
return
/obj/structure/closet/attack_ai(mob/user)
if(istype(user, /mob/living/silicon/robot) && Adjacent(user)) // Robots can open/close it, but not the AI.
attack_hand(user)
/obj/structure/closet/relaymove(mob/user as mob)
if(user.stat || !isturf(src.loc))
return

View File

@@ -19,7 +19,7 @@
New()
..()
for(var/i = 0, i < 6, i++)
new /obj/item/weapon/reagent_containers/food/snacks/flour(src)
new /obj/item/weapon/reagent_containers/food/condiment/flour(src)
new /obj/item/weapon/reagent_containers/food/condiment/sugar(src)
for(var/i = 0, i < 3, i++)
new /obj/item/weapon/reagent_containers/food/snacks/meat/monkey(src)

View File

@@ -24,5 +24,6 @@
new /obj/item/weapon/minihoe(src)
new /obj/item/weapon/hatchet(src)
new /obj/item/weapon/wirecutters/clippers(src)
new /obj/item/weapon/reagent_containers/spray/plantbgone(src)
// new /obj/item/weapon/bee_net(src) //No more bees, March 2014
return

View File

@@ -0,0 +1,133 @@
/obj/structure/closet/statue
name = "statue"
desc = "An incredibly lifelike marble carving"
icon = 'icons/obj/statue.dmi'
icon_state = "human_male"
density = 1
anchored = 1
health = 0 //destroying the statue kills the mob within
var/intialTox = 0 //these are here to keep the mob from taking damage from things that logically wouldn't affect a rock
var/intialFire = 0 //it's a little sloppy I know but it was this or the GODMODE flag. Lesser of two evils.
var/intialBrute = 0
var/intialOxy = 0
var/timer = 240 //eventually the person will be freed
/obj/structure/closet/statue/New(loc, var/mob/living/L)
if(L && (ishuman(L) || L.isMonkey() || iscorgi(L)))
if(L.buckled)
L.buckled = 0
L.anchored = 0
if(L.client)
L.client.perspective = EYE_PERSPECTIVE
L.client.eye = src
L.loc = src
L.sdisabilities |= MUTE
health = L.health + 100 //stoning damaged mobs will result in easier to shatter statues
intialTox = L.getToxLoss()
intialFire = L.getFireLoss()
intialBrute = L.getBruteLoss()
intialOxy = L.getOxyLoss()
if(ishuman(L))
name = "statue of [L.name]"
if(L.gender == "female")
icon_state = "human_female"
else if(L.isMonkey())
name = "statue of a monkey"
icon_state = "monkey"
else if(iscorgi(L))
name = "statue of a corgi"
icon_state = "corgi"
desc = "If it takes forever, I will wait for you..."
if(health == 0) //meaning if the statue didn't find a valid target
del(src)
return
processing_objects.Add(src)
..()
/obj/structure/closet/statue/process()
timer--
for(var/mob/living/M in src) //Go-go gadget stasis field
M.setToxLoss(intialTox)
M.adjustFireLoss(intialFire - M.getFireLoss())
M.adjustBruteLoss(intialBrute - M.getBruteLoss())
M.setOxyLoss(intialOxy)
if (timer <= 0)
dump_contents()
processing_objects.Remove(src)
del(src)
/obj/structure/closet/statue/dump_contents()
for(var/obj/O in src)
O.loc = src.loc
for(var/mob/living/M in src)
M.loc = src.loc
M.sdisabilities &= ~MUTE
M.take_overall_damage((M.health - health - 100),0) //any new damage the statue incurred is transfered to the mob
if(M.client)
M.client.eye = M.client.mob
M.client.perspective = MOB_PERSPECTIVE
/obj/structure/closet/statue/open()
return
/obj/structure/closet/statue/close()
return
/obj/structure/closet/statue/toggle()
return
/obj/structure/closet/statue/bullet_act(var/obj/item/projectile/Proj)
health -= Proj.damage
if(health <= 0)
for(var/mob/M in src)
shatter(M)
return
/obj/structure/closet/statue/attack_generic(var/mob/user, damage, attacktext, environment_smash)
if(damage && environment_smash)
for(var/mob/M in src)
shatter(M)
/obj/structure/closet/statue/blob_act()
for(var/mob/M in src)
shatter(M)
/obj/structure/closet/statue/meteorhit(obj/O as obj)
if(O.icon_state == "flaming")
for(var/mob/M in src)
M.meteorhit(O)
shatter(M)
/obj/structure/closet/statue/attackby(obj/item/I as obj, mob/user as mob)
health -= I.force
visible_message("<span class='danger'>[user] strikes [src] with [I].</span>")
if(health <= 0)
for(var/mob/M in src)
shatter(M)
/obj/structure/closet/statue/MouseDrop_T()
return
/obj/structure/closet/statue/relaymove()
return
/obj/structure/closet/statue/attack_hand()
return
/obj/structure/closet/statue/verb_toggleopen()
return
/obj/structure/closet/statue/update_icon()
return
/obj/structure/closet/statue/proc/shatter(mob/user as mob)
if (user)
user.dust()
dump_contents()
visible_message("<span class='warning'>[src] shatters!.</span>")
del(src)

View File

@@ -113,7 +113,7 @@
del(src)
return
if(/obj/item/stack/sheet/plasteel)
if(/obj/item/stack/sheet/plasteel, /obj/item/stack/sheet/plasteel/cyborg)
if(!anchored)
if(S.use(2))
user << "\blue You create a false wall! Push on it to open or close the passage."

View File

@@ -22,6 +22,11 @@
/obj/structure/grille/meteorhit(var/obj/M)
del(src)
/obj/structure/grille/update_icon()
if(destroyed)
icon_state = "[initial(icon_state)]-b"
else
icon_state = initial(icon_state)
/obj/structure/grille/Bumped(atom/user)
if(ismob(user)) shock(user, 70)
@@ -165,9 +170,9 @@
/obj/structure/grille/proc/healthcheck()
if(health <= 0)
if(!destroyed)
icon_state = "brokengrille"
density = 0
destroyed = 1
update_icon()
new /obj/item/stack/rods(loc)
else
@@ -215,3 +220,14 @@
health -= damage
spawn(1) healthcheck()
return 1
/obj/structure/grille/cult
name = "cult grille"
desc = "A matrice built out of an unknown material, with some sort of force field blocking air around it"
icon_state = "grillecult"
health = 40 //Make it strong enough to avoid people breaking in too easily
/obj/structure/grille/cult/CanPass(atom/movable/mover, turf/target, height = 1.5, air_group = 0)
if(air_group)
return 0 //Make sure air doesn't drain
..()

View File

@@ -80,11 +80,11 @@
var/mob/living/carbon/human/vox/vox = new(get_turf(src),"Vox")
vox.gender = user.gender
raiders.equip(vox)
new /obj/item/organ/stack/vox(vox)
if(user.mind)
user.mind.transfer_to(vox)
spawn(1)
var/newname = input(vox,"Enter a name, or leave blank for the default name.", "Name change","") as text
newname = sanitize(newname)
var/newname = sanitizeSafe(input(vox,"Enter a name, or leave blank for the default name.", "Name change","") as text, MAX_NAME_LEN)
if(!newname || newname == "")
var/datum/language/L = all_languages[vox.species.default_language]
newname = L.get_random_name()

View File

@@ -92,7 +92,7 @@
return
if ((!in_range(src, usr) && src.loc != user))
return
t = sanitize(t)
t = sanitizeSafe(t, MAX_NAME_LEN)
if (t)
src.name = text("Morgue- '[]'", t)
else
@@ -258,7 +258,7 @@
return
if ((!in_range(src, usr) > 1 && src.loc != user))
return
t = sanitize(t)
t = sanitizeSafe(t, MAX_NAME_LEN)
if (t)
src.name = text("Crematorium- '[]'", t)
else

View File

@@ -67,15 +67,13 @@
return
// Chair types
/obj/structure/bed/chair/wood/normal
/obj/structure/bed/chair/wood
icon_state = "wooden_chair"
name = "wooden chair"
desc = "Old is never too old to not be in fashion."
/obj/structure/bed/chair/wood/wings
icon_state = "wooden_chair_wings"
name = "wooden chair"
desc = "Old is never too old to not be in fashion."
/obj/structure/bed/chair/wood/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W, /obj/item/weapon/wrench))

View File

@@ -12,6 +12,8 @@
/turf/simulated/New()
..()
if(istype(loc, /area/chapel))
holy = 1
levelupdate()
/turf/simulated/proc/AddTracks(var/typepath,var/bloodDNA,var/comingdir,var/goingdir,var/bloodcolor="#A10808")

View File

@@ -74,6 +74,8 @@
name = "engraved floor"
icon_state = "cult"
/turf/simulated/floor/engine/cult/cultify()
return
/turf/simulated/floor/engine/n20
New()

View File

@@ -106,6 +106,20 @@
//Damage
/turf/simulated/wall/melt()
if(mineral == "diamond")
return
src.ChangeTurf(/turf/simulated/floor/plating)
var/turf/simulated/floor/F = src
if(!F)
return
F.burn_tile()
F.icon_state = "wall_thermite"
visible_message("<span class='danger'>\The [src] spontaneously combusts!.</span>") //!!OH SHIT!!
return
/turf/simulated/wall/proc/take_damage(dam)
if(dam)
damage = max(0, damage + dam)

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