Merge branch 'master' into upstream-merge-30297

This commit is contained in:
LetterJay
2017-09-13 06:41:37 -05:00
committed by GitHub
40 changed files with 1557 additions and 2171 deletions
+2
View File
@@ -1,5 +1,7 @@
// simple is_type and similar inline helpers
#define isdatum(D) (istype(D, /datum))
#define islist(L) (istype(L, /list))
#define in_range(source, user) (get_dist(source, user) <= 1)
-6
View File
@@ -399,8 +399,6 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
#define NUKE_SYNDICATE_BASE 3
#define STATION_DESTROYED_NUKE 4
#define STATION_EVACUATED 5
#define GANG_LOSS 6
#define GANG_TAKEOVER 7
#define BLOB_WIN 8
#define BLOB_NUKE 9
#define BLOB_DESTROYED 10
@@ -437,10 +435,6 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
#define GIBTONITE_DETONATE 3
//for obj explosion block calculation
#define EXPLOSION_BLOCK_PROC -1
//Gangster starting influences
#define GANGSTER_SOLDIER_STARTING_INFLUENCE 5
#define GANGSTER_BOSS_STARTING_INFLUENCE 20
//for determining which type of heartbeat sound is playing
#define BEAT_FAST 1
+5
View File
@@ -10,6 +10,11 @@
//if TESTING is enabled, qdel will call this object's find_references() verb.
//defines for the gc_destroyed var
#define GC_QUEUE_PREQUEUE 1
#define GC_QUEUE_CHECK 2
#define GC_QUEUE_HARDDELETE 3
#define GC_QUEUE_COUNT 3 //increase this when adding more steps.
#define GC_QUEUED_FOR_QUEUING -1
#define GC_QUEUED_FOR_HARD_DEL -2
#define GC_CURRENTLY_BEING_QDELETED -3
-2
View File
@@ -18,7 +18,6 @@
#define ROLE_BLOB "blob"
#define ROLE_NINJA "space ninja"
#define ROLE_MONKEY "monkey"
#define ROLE_GANG "gangster"
#define ROLE_ABDUCTOR "abductor"
#define ROLE_REVENANT "revenant"
#define ROLE_DEVIL "devil"
@@ -41,7 +40,6 @@ GLOBAL_LIST_INIT(special_roles, list(
ROLE_BLOB = /datum/game_mode/blob,
ROLE_NINJA,
ROLE_MONKEY = /datum/game_mode/monkey,
ROLE_GANG = /datum/game_mode/gang,
ROLE_REVENANT,
ROLE_ABDUCTOR = /datum/game_mode/abduction,
ROLE_DEVIL = /datum/game_mode/devil,
+8
View File
@@ -13,3 +13,11 @@ When using time2text(), please use "DDD" to find the weekday. Refrain from using
#define FRIDAY "Fri"
#define SATURDAY "Sat"
#define SUNDAY "Sun"
#define SECONDS *10
#define MINUTES SECONDS*60
#define HOURS MINUTES*60
#define TICKS *world.tick_lag
+3
View File
@@ -96,6 +96,9 @@
if (config.log_pda)
WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]CHAT: [text]")
/proc/log_qdel(text)
WRITE_FILE(GLOB.world_qdel_log, "\[[time_stamp()]]QDEL: [text]")
/proc/log_sql(text)
WRITE_FILE(GLOB.sql_error_log, "\[[time_stamp()]]SQL: [text]")
+9
View File
@@ -49,3 +49,12 @@ GLOBAL_VAR_INIT(cmp_field, "name")
/proc/cmp_ruincost_priority(datum/map_template/ruin/A, datum/map_template/ruin/B)
return initial(A.cost) - initial(B.cost)
/proc/cmp_qdel_item_time(datum/qdel_item/A, datum/qdel_item/B)
. = B.hard_delete_time - A.hard_delete_time
if (!.)
. = B.destroy_time - A.destroy_time
if (!.)
. = B.failures - A.failures
if (!.)
. = B.qdels - A.qdels
+2
View File
@@ -4,6 +4,8 @@ GLOBAL_VAR(world_game_log)
GLOBAL_PROTECT(world_game_log)
GLOBAL_VAR(world_runtime_log)
GLOBAL_PROTECT(world_runtime_log)
GLOBAL_VAR(world_qdel_log)
GLOBAL_PROTECT(world_qdel_log)
GLOBAL_VAR(world_attack_log)
GLOBAL_PROTECT(world_attack_log)
GLOBAL_VAR(world_href_log)
+208 -142
View File
@@ -1,40 +1,44 @@
SUBSYSTEM_DEF(garbage)
name = "Garbage"
priority = 15
wait = 20
wait = 2 SECONDS
flags = SS_POST_FIRE_TIMING|SS_BACKGROUND|SS_NO_INIT
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
var/collection_timeout = 3000// deciseconds to wait to let running procs finish before we just say fuck it and force del() the object
var/delslasttick = 0 // number of del()'s we've done this tick
var/gcedlasttick = 0 // number of things that gc'ed last tick
var/list/collection_timeout = list(0, 2 MINUTES, 10 SECONDS) // deciseconds to wait before moving something up in the queue to the next level
//Stat tracking
var/delslasttick = 0 // number of del()'s we've done this tick
var/gcedlasttick = 0 // number of things that gc'ed last tick
var/totaldels = 0
var/totalgcs = 0
var/highest_del_time = 0
var/highest_del_tickusage = 0
var/list/queue = 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/pass_counts
var/list/fail_counts
var/list/tobequeued = list() //We store the references of things to be added to the queue separately so we can spread out GC overhead over a few ticks
var/list/items = list() // Holds our qdel_item statistics datums
var/list/didntgc = 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
var/list/sleptDestroy = list() //Same as above but these are paths that slept during their Destroy call
//Queue
var/list/queues
var/list/noqdelhint = list()// list of all types that do not return a QDEL_HINT
// all types that did not respect qdel(A, force=TRUE) and returned one
// of the immortality qdel hints
var/list/noforcerespect = list()
#ifdef TESTING
var/list/qdel_list = list() // list of all types that have been qdel()eted
#endif
/datum/controller/subsystem/garbage/PreInit()
queues = new(GC_QUEUE_COUNT)
pass_counts = new(GC_QUEUE_COUNT)
fail_counts = new(GC_QUEUE_COUNT)
for(var/i in 1 to GC_QUEUE_COUNT)
queues[i] = list()
pass_counts[i] = 0
fail_counts[i] = 0
/datum/controller/subsystem/garbage/stat_entry(msg)
msg += "Q:[queue.len]|D:[delslasttick]|G:[gcedlasttick]|"
var/list/counts = list()
for (var/list/L in queues)
counts += length(L)
msg += "Q:[counts.Join(",")]|D:[delslasttick]|G:[gcedlasttick]|"
msg += "GR:"
if (!(delslasttick+gcedlasttick))
msg += "n/a|"
@@ -46,116 +50,179 @@ SUBSYSTEM_DEF(garbage)
msg += "n/a|"
else
msg += "TGR:[round((totalgcs/(totaldels+totalgcs))*100, 0.01)]%"
msg += " P:[pass_counts.Join(",")]"
msg += "|F:[fail_counts.Join(",")]"
..(msg)
/datum/controller/subsystem/garbage/Shutdown()
//Adds the del() log to world.log in a format condensable by the runtime condenser found in tools
if(didntgc.len || sleptDestroy.len)
var/list/dellog = list()
for(var/path in didntgc)
dellog += "Path : [path] \n"
dellog += "Failures : [didntgc[path]] \n"
if(path in sleptDestroy)
dellog += "Sleeps : [sleptDestroy[path]] \n"
sleptDestroy -= path
for(var/path in sleptDestroy)
dellog += "Path : [path] \n"
dellog += "Sleeps : [sleptDestroy[path]] \n"
text2file(dellog.Join(), "[GLOB.log_directory]/qdel.log")
//Adds the del() log to the qdel log file
var/list/dellog = list()
//sort by how long it's wasted hard deleting
sortTim(items, cmp=/proc/cmp_qdel_item_time, associative = TRUE)
for(var/path in items)
var/datum/qdel_item/I = items[path]
dellog += "Path: [path]"
if (I.failures)
dellog += "\tFailures: [I.failures]"
dellog += "\tqdel() Count: [I.qdels]"
dellog += "\tDestroy() Cost: [I.destroy_time]ms"
if (I.hard_deletes)
dellog += "\tTotal Hard Deletes [I.hard_deletes]"
dellog += "\tTime Spent Hard Deleting: [I.hard_delete_time]ms"
if (I.slept_destroy)
dellog += "\tSleeps: [I.slept_destroy]"
if (I.no_respect_force)
dellog += "\tIgnored force: [I.no_respect_force] times"
if (I.no_hint)
dellog += "\tNo hint: [I.no_hint] times"
log_qdel(dellog.Join("\n"))
/datum/controller/subsystem/garbage/fire()
HandleToBeQueued()
if(state == SS_RUNNING)
HandleQueue()
//the fact that this resets its processing each fire (rather then resume where it left off) is intentional.
var/queue = GC_QUEUE_PREQUEUE
while (state == SS_RUNNING)
switch (queue)
if (GC_QUEUE_PREQUEUE)
HandlePreQueue()
queue = GC_QUEUE_PREQUEUE+1
if (GC_QUEUE_CHECK)
HandleQueue(GC_QUEUE_CHECK)
queue = GC_QUEUE_CHECK+1
if (GC_QUEUE_HARDDELETE)
HandleQueue(GC_QUEUE_HARDDELETE)
break
if (state == SS_PAUSED) //make us wait again before the next run.
state = SS_RUNNING
state = SS_RUNNING
//If you see this proc high on the profile, what you are really seeing is the garbage collection/soft delete overhead in byond.
//Don't attempt to optimize, not worth the effort.
/datum/controller/subsystem/garbage/proc/HandleToBeQueued()
var/list/tobequeued = src.tobequeued
var/starttime = world.time
var/starttimeofday = world.timeofday
while(tobequeued.len && starttime == world.time && starttimeofday == world.timeofday)
if (MC_TICK_CHECK)
break
var/ref = tobequeued[1]
Queue(ref)
tobequeued.Cut(1, 2)
/datum/controller/subsystem/garbage/proc/HandlePreQueue()
var/list/tobequeued = queues[GC_QUEUE_PREQUEUE]
var/static/count = 0
if (count)
var/c = count
count = 0 //so if we runtime on the Cut, we don't try again.
tobequeued.Cut(1,c+1)
/datum/controller/subsystem/garbage/proc/HandleQueue()
delslasttick = 0
gcedlasttick = 0
var/time_to_kill = world.time - collection_timeout // Anything qdel() but not GC'd BEFORE this time needs to be manually del()
var/list/queue = src.queue
var/starttime = world.time
var/starttimeofday = world.timeofday
while(queue.len && starttime == world.time && starttimeofday == world.timeofday)
for (var/ref in tobequeued)
count++
Queue(ref, GC_QUEUE_PREQUEUE+1)
if (MC_TICK_CHECK)
break
var/refID = queue[1]
if (count)
tobequeued.Cut(1,count+1)
count = 0
/datum/controller/subsystem/garbage/proc/HandleQueue(level = GC_QUEUE_CHECK)
if (level == GC_QUEUE_CHECK)
delslasttick = 0
gcedlasttick = 0
var/cut_off_time = world.time - collection_timeout[level] //ignore entries newer then this
var/list/queue = queues[level]
var/static/lastlevel
var/static/count = 0
if (count) //runtime last run before we could do this.
var/c = count
count = 0 //so if we runtime on the Cut, we don't try again.
var/list/lastqueue = queues[lastlevel]
lastqueue.Cut(1, c+1)
lastlevel = level
for (var/refID in queue)
if (!refID)
queue.Cut(1, 2)
count++
if (MC_TICK_CHECK)
break
continue
var/GCd_at_time = queue[refID]
if(GCd_at_time > time_to_kill)
if(GCd_at_time > cut_off_time)
break // Everything else is newer, skip them
queue.Cut(1, 2)
var/datum/A
A = locate(refID)
if (A && A.gc_destroyed == GCd_at_time) // So if something else coincidently gets the same ref, it's not deleted by mistake
#ifdef GC_FAILURE_HARD_LOOKUP
A.find_references()
#endif
count++
// Something's still referring to the qdel'd object. Kill it.
var/type = A.type
testing("GC: -- \ref[A] | [type] was unable to be GC'd and was deleted --")
didntgc["[type]"]++
HardDelete(A)
var/datum/D
D = locate(refID)
++delslasttick
++totaldels
else
if (!D || D.gc_destroyed != GCd_at_time) // So if something else coincidently gets the same ref, it's not deleted by mistake
++gcedlasttick
++totalgcs
pass_counts[level]++
if (MC_TICK_CHECK)
break
continue
/datum/controller/subsystem/garbage/proc/QueueForQueuing(datum/A)
if (istype(A) && A.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
tobequeued += A
A.gc_destroyed = GC_QUEUED_FOR_QUEUING
// Something's still referring to the qdel'd object.
fail_counts[level]++
switch (level)
if (GC_QUEUE_CHECK)
#ifdef GC_FAILURE_HARD_LOOKUP
D.find_references()
#endif
var/type = D.type
var/datum/qdel_item/I = items[type]
testing("GC: -- \ref[D] | [type] was unable to be GC'd --")
I.failures++
if (GC_QUEUE_HARDDELETE)
HardDelete(D)
if (MC_TICK_CHECK)
break
continue
/datum/controller/subsystem/garbage/proc/Queue(datum/A)
if (isnull(A) || (!isnull(A.gc_destroyed) && A.gc_destroyed >= 0))
Queue(D, level+1)
if (MC_TICK_CHECK)
break
if (count)
queue.Cut(1,count+1)
count = 0
/datum/controller/subsystem/garbage/proc/PreQueue(datum/D)
if (D.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
queues[GC_QUEUE_PREQUEUE] += D
D.gc_destroyed = GC_QUEUED_FOR_QUEUING
/datum/controller/subsystem/garbage/proc/Queue(datum/D, level = GC_QUEUE_CHECK)
if (isnull(D))
return
if (A.gc_destroyed == GC_QUEUED_FOR_HARD_DEL)
HardDelete(A)
if (D.gc_destroyed == GC_QUEUED_FOR_HARD_DEL)
level = GC_QUEUE_HARDDELETE
if (level > GC_QUEUE_COUNT)
HardDelete(D)
return
var/gctime = world.time
var/refid = "\ref[A]"
A.gc_destroyed = gctime
var/refid = "\ref[D]"
D.gc_destroyed = gctime
var/list/queue = queues[level]
if (queue[refid])
queue -= refid // Removing any previous references that were GC'd so that the current object will be at the end of the list.
queue[refid] = gctime
//this is purely to separate things profile wise.
/datum/controller/subsystem/garbage/proc/HardDelete(datum/A)
//this is mainly to separate things profile wise.
/datum/controller/subsystem/garbage/proc/HardDelete(datum/D)
var/time = world.timeofday
var/tick = TICK_USAGE
var/ticktime = world.time
var/type = A.type
var/refID = "\ref[A]"
del(A)
++delslasttick
++totaldels
var/type = D.type
var/refID = "\ref[D]"
del(D)
tick = (TICK_USAGE-tick+((world.time-ticktime)/world.tick_lag*100))
var/datum/qdel_item/I = items[type]
I.hard_deletes++
I.hard_delete_time += TICK_DELTA_TO_MS(tick)
if (tick > highest_del_tickusage)
highest_del_tickusage = tick
time = world.timeofday - time
@@ -166,18 +233,33 @@ SUBSYSTEM_DEF(garbage)
if (time > 10)
log_game("Error: [type]([refID]) took longer than 1 second to delete (took [time/10] seconds to delete)")
message_admins("Error: [type]([refID]) took longer than 1 second to delete (took [time/10] seconds to delete).")
postpone(time/5)
/datum/controller/subsystem/garbage/proc/HardQueue(datum/A)
if (istype(A) && A.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
tobequeued += A
A.gc_destroyed = GC_QUEUED_FOR_HARD_DEL
postpone(time)
/datum/controller/subsystem/garbage/proc/HardQueue(datum/D)
if (D.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
queues[GC_QUEUE_PREQUEUE] += D
D.gc_destroyed = GC_QUEUED_FOR_HARD_DEL
/datum/controller/subsystem/garbage/Recover()
if (istype(SSgarbage.queue))
queue |= SSgarbage.queue
if (istype(SSgarbage.tobequeued))
tobequeued |= SSgarbage.tobequeued
if (istype(SSgarbage.queues))
for (var/i in 1 to SSgarbage.queues.len)
queues[i] |= SSgarbage.queues[i]
/datum/qdel_item
var/name = ""
var/qdels = 0 //Total number of times it's passed thru qdel.
var/destroy_time = 0 //Total amount of milliseconds spent processing this type's Destroy()
var/failures = 0 //Times it was queued for soft deletion but failed to soft delete.
var/hard_deletes = 0 //Different from failures because it also includes QDEL_HINT_HARDDEL deletions
var/hard_delete_time = 0//Total amount of milliseconds spent hard deleting this type.
var/no_respect_force = 0//Number of times it's not respected force=TRUE
var/no_hint = 0 //Number of times it's not even bother to give a qdel hint
var/slept_destroy = 0 //Number of times it's slept in its destroy
/datum/qdel_item/New(mytype)
name = "[mytype]"
// 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.
@@ -185,21 +267,27 @@ SUBSYSTEM_DEF(garbage)
if(!istype(D))
del(D)
return
#ifdef TESTING
SSgarbage.qdel_list += "[D.type]"
#endif
var/datum/qdel_item/I = SSgarbage.items[D.type]
if (!I)
I = SSgarbage.items[D.type] = new /datum/qdel_item(D.type)
I.qdels++
if(isnull(D.gc_destroyed))
D.SendSignal(COMSIG_PARENT_QDELETED)
D.gc_destroyed = GC_CURRENTLY_BEING_QDELETED
var/start_time = world.time
var/start_tick = world.tick_usage
var/hint = D.Destroy(force) // Let our friend know they're about to get fucked up.
if(world.time != start_time)
SSgarbage.sleptDestroy["[D.type]"]++
I.slept_destroy++
else
I.destroy_time += TICK_USAGE_TO_MS(start_tick)
if(!D)
return
switch(hint)
if (QDEL_HINT_QUEUE) //qdel should queue the object for deletion.
SSgarbage.QueueForQueuing(D)
SSgarbage.PreQueue(D)
if (QDEL_HINT_IWILLGC)
D.gc_destroyed = world.time
return
@@ -209,28 +297,33 @@ SUBSYSTEM_DEF(garbage)
return
// Returning LETMELIVE after being told to force destroy
// indicates the objects Destroy() does not respect force
if(!SSgarbage.noforcerespect["[D.type]"])
SSgarbage.noforcerespect["[D.type]"] = "[D.type]"
#ifdef TESTING
if(!I.no_respect_force)
testing("WARNING: [D.type] has been force deleted, but is \
returning an immortal QDEL_HINT, indicating it does \
not respect the force flag for qdel(). It has been \
placed in the queue, further instances of this type \
will also be queued.")
SSgarbage.QueueForQueuing(D)
#endif
I.no_respect_force++
SSgarbage.PreQueue(D)
if (QDEL_HINT_HARDDEL) //qdel should assume this object won't gc, and queue a hard delete using a hard reference to save time from the locate()
SSgarbage.HardQueue(D)
if (QDEL_HINT_HARDDEL_NOW) //qdel should assume this object won't gc, and hard del it post haste.
SSgarbage.HardDelete(D)
if (QDEL_HINT_FINDREFERENCE)//qdel will, if TESTING is enabled, display all references to this object, then queue the object for deletion.
SSgarbage.QueueForQueuing(D)
SSgarbage.PreQueue(D)
#ifdef TESTING
D.find_references()
#endif
else
if(!SSgarbage.noqdelhint["[D.type]"])
SSgarbage.noqdelhint["[D.type]"] = "[D.type]"
#ifdef TESTING
if(!I.no_hint)
testing("WARNING: [D.type] is not returning a qdel hint. It is being placed in the queue. Further instances of this type will also be queued.")
SSgarbage.QueueForQueuing(D)
#endif
I.no_hint++
SSgarbage.PreQueue(D)
else if(D.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
CRASH("[D.type] destroy proc was called multiple times, likely due to a qdel loop in the Destroy logic")
@@ -281,15 +374,6 @@ SUBSYSTEM_DEF(garbage)
SSgarbage.can_fire = 1
SSgarbage.next_fire = world.time + world.tick_lag
/client/verb/purge_all_destroyed_objects()
set category = "Debug"
while(SSgarbage.queue.len)
var/datum/o = locate(SSgarbage.queue[1])
if(istype(o) && o.gc_destroyed)
del(o)
SSgarbage.totaldels++
SSgarbage.queue.Cut(1, 2)
/datum/verb/qdel_then_find_references()
set category = "Debug"
set name = "qdel() then Find References"
@@ -300,24 +384,6 @@ SUBSYSTEM_DEF(garbage)
if(!running_find_references)
find_references(TRUE)
/client/verb/show_qdeleted()
set category = "Debug"
set name = "Show qdel() Log"
set desc = "Render the qdel() log and display it"
var/dat = "<B>List of things that have been qdel()eted this round</B><BR><BR>"
var/tmplist = list()
for(var/elem in SSgarbage.qdel_list)
if(!(elem in tmplist))
tmplist[elem] = 0
tmplist[elem]++
for(var/path in tmplist)
dat += "[path] - [tmplist[path]] times<BR>"
usr << browse(dat, "window=qdeletedlog")
/datum/proc/DoSearchVar(X, Xname)
if(usr && usr.client && !usr.client.running_find_references) return
if(istype(X, /datum))
-9
View File
@@ -315,11 +315,6 @@ SUBSYSTEM_DEF(ticker)
flick("station_corrupted",cinematic)
SEND_SOUND(world, sound('sound/effects/ghost.ogg'))
actually_blew_up = FALSE
if("gang war") //Gang Domination (just show the override screen)
cinematic.icon_state = "intro_malf_still"
flick("intro_malf",cinematic)
actually_blew_up = FALSE
sleep(70)
if("fake") //The round isn't over, we're just freaking people out for fun
flick("intro_nuke",cinematic)
sleep(35)
@@ -739,10 +734,6 @@ SUBSYSTEM_DEF(ticker)
news_message = "We would like to reassure all employees that the reports of a Syndicate backed nuclear attack on [station_name()] are, in fact, a hoax. Have a secure day!"
if(STATION_EVACUATED)
news_message = "The crew of [station_name()] has been evacuated amid unconfirmed reports of enemy activity."
if(GANG_LOSS)
news_message = "Organized crime aboard [station_name()] has been stamped out by members of our ever vigilant security team. Remember to thank your assigned officers today!"
if(GANG_TAKEOVER)
news_message = "Contact with [station_name()] has been lost after a sophisticated hacking attack by organized criminal elements. Stay vigilant!"
if(BLOB_WIN)
news_message = "[station_name()] was overcome by an unknown biological outbreak, killing all crew on board. Don't let it happen to you! Remember, a clean work station is a safe work station."
if(BLOB_NUKE)
+1 -6
View File
@@ -75,12 +75,7 @@ GLOBAL_LIST_INIT(huds, list(
//MOB PROCS
/mob/proc/reload_huds()
var/gang_huds = list()
if(SSticker.mode)
for(var/datum/gang/G in SSticker.mode.gangs)
gang_huds += G.ganghud
for(var/datum/atom_hud/hud in (GLOB.huds|gang_huds|GLOB.active_alternate_appearances))
for(var/datum/atom_hud/hud in (GLOB.huds|GLOB.active_alternate_appearances))
if(hud && hud.hudusers[src])
hud.add_hud_to(src)
+2 -132
View File
@@ -56,7 +56,6 @@
var/list/antag_datums
var/antag_hud_icon_state = null //this mind's ANTAG_HUD should have this icon_state
var/datum/atom_hud/antag/antag_hud = null //this mind's antag HUD
var/datum/gang/gang_datum //Which gang this mind belongs to, if any
var/damnation_type = 0
var/datum/mind/soulOwner //who owns the soul. Under normal circumstances, this will point to src
var/hasSoul = TRUE // If false, renders the character unable to sell their soul.
@@ -228,11 +227,6 @@
remove_objectives()
remove_antag_equip()
/datum/mind/proc/remove_gang()
SSticker.mode.remove_gangster(src,0,1,1)
remove_objectives()
/datum/mind/proc/remove_antag_equip()
var/list/Mob_Contents = current.get_contents()
for(var/obj/item/I in Mob_Contents)
@@ -251,14 +245,11 @@
remove_wizard()
remove_cultist()
remove_rev()
remove_gang()
SSticker.mode.update_changeling_icons_removed(src)
SSticker.mode.update_traitor_icons_removed(src)
SSticker.mode.update_wiz_icons_removed(src)
SSticker.mode.update_cult_icons_removed(src)
SSticker.mode.update_rev_icons_removed(src)
if(gang_datum)
gang_datum.remove_gang_hud(src)
/datum/mind/proc/equip_traitor(var/employer = "The Syndicate", var/silent = FALSE)
if(!current)
@@ -328,9 +319,6 @@
if(iscultist(creator))
SSticker.mode.add_cultist(src)
else if(is_gangster(creator))
SSticker.mode.add_gangster(src, creator.mind.gang_datum, TRUE)
else if(is_revolutionary_in_general(creator))
SSticker.mode.add_revolutionary(src)
@@ -385,7 +373,6 @@
"nuclear",
"wizard",
"revolution",
"gang",
"cult",
"clockcult",
"abductor",
@@ -568,48 +555,8 @@
sections["revolution"] = text
/** GANG ***/
text = "gang"
if (SSticker.mode.config_tag=="gang")
text = uppertext(text)
text = "<i><b>[text]</b></i>: "
text += "[current.isloyal() ? "<B>MINDSHIELDED</B>" : "not mindshielded"] | "
if(src in SSticker.mode.get_all_gangsters())
text += "<a href='?src=\ref[src];gang=clear'>none</a>"
else
text += "<B>NONE</B>"
if(current && current.client && (ROLE_GANG in current.client.prefs.be_special))
text += " | Enabled in Prefs<BR>"
else
text += " | Disabled in Prefs<BR>"
for(var/datum/gang/G in SSticker.mode.gangs)
text += "<i>[G.name]</i>: "
if(src in (G.gangsters))
text += "<B>GANGSTER</B>"
else
text += "<a href='?src=\ref[src];gangster=\ref[G]'>gangster</a>"
text += " | "
if(src in (G.bosses))
text += "<B>GANG LEADER</B>"
text += " | Equipment: <a href='?src=\ref[src];gang=equip'>give</a>"
var/list/L = current.get_contents()
var/obj/item/device/gangtool/gangtool = locate() in L
if (gangtool)
text += " | <a href='?src=\ref[src];gang=takeequip'>take</a>"
else
text += "<a href='?src=\ref[src];gangboss=\ref[G]'>gang leader</a>"
text += "<BR>"
if(GLOB.gang_colors_pool.len)
text += "<a href='?src=\ref[src];gang=new'>Create New Gang</a>"
sections["gang"] = text
/** ABDUCTION **/
text = "abductor"
/** Abductors **/
text = "Abductor"
if(SSticker.mode.config_tag == "abductor")
text = uppertext(text)
text = "<i><b>[text]</b></i>: "
@@ -1031,73 +978,6 @@
//////////////////// GANG MODE
else if (href_list["gang"])
switch(href_list["gang"])
if("clear")
remove_gang()
message_admins("[key_name_admin(usr)] has de-gang'ed [current].")
log_admin("[key_name(usr)] has de-gang'ed [current].")
if("equip")
switch(SSticker.mode.equip_gang(current,gang_datum))
if(1)
to_chat(usr, "<span class='warning'>Unable to equip territory spraycan!</span>")
if(2)
to_chat(usr, "<span class='warning'>Unable to equip recruitment pen and spraycan!</span>")
if(3)
to_chat(usr, "<span class='warning'>Unable to equip gangtool, pen, and spraycan!</span>")
if("takeequip")
var/list/L = current.get_contents()
for(var/obj/item/pen/gang/pen in L)
qdel(pen)
for(var/obj/item/device/gangtool/gangtool in L)
qdel(gangtool)
for(var/obj/item/toy/crayon/spraycan/gang/SC in L)
qdel(SC)
if("new")
if(GLOB.gang_colors_pool.len)
var/list/names = list("Random") + GLOB.gang_name_pool
var/gangname = input("Pick a gang name.","Select Name") as null|anything in names
if(gangname && GLOB.gang_colors_pool.len) //Check again just in case another admin made max gangs at the same time
if(!(gangname in GLOB.gang_name_pool))
gangname = null
var/datum/gang/newgang = new(null,gangname)
SSticker.mode.gangs += newgang
message_admins("[key_name_admin(usr)] has created the [newgang.name] Gang.")
log_admin("[key_name(usr)] has created the [newgang.name] Gang.")
else if (href_list["gangboss"])
var/datum/gang/G = locate(href_list["gangboss"]) in SSticker.mode.gangs
if(!G || (src in G.bosses))
return
SSticker.mode.remove_gangster(src,0,2,1)
G.bosses[src] = GANGSTER_BOSS_STARTING_INFLUENCE
gang_datum = G
special_role = "[G.name] Gang Boss"
G.add_gang_hud(src)
to_chat(current, "<FONT size=3 color=red><B>You are a [G.name] Gang Boss!</B></FONT>")
message_admins("[key_name_admin(usr)] has added [current] to the [G.name] Gang leadership.")
log_admin("[key_name(usr)] has added [current] to the [G.name] Gang leadership.")
SSticker.mode.forge_gang_objectives(src)
SSticker.mode.greet_gang(src,0)
else if (href_list["gangster"])
var/datum/gang/G = locate(href_list["gangster"]) in SSticker.mode.gangs
if(!G || (src in G.gangsters))
return
SSticker.mode.remove_gangster(src,0,2,1)
SSticker.mode.add_gangster(src,G,0)
message_admins("[key_name_admin(usr)] has added [current] to the [G.name] Gang (A).")
log_admin("[key_name(usr)] has added [current] to the [G.name] Gang (A).")
/////////////////////////////////
else if (href_list["cult"])
switch(href_list["cult"])
if("clear")
@@ -1584,16 +1464,6 @@
var/fail = 0
fail |= !SSticker.mode.equip_revolutionary(current)
/datum/mind/proc/make_Gang(datum/gang/G)
special_role = "[G.name] Gang Boss"
G.bosses += src
gang_datum = G
G.add_gang_hud(src)
SSticker.mode.forge_gang_objectives(src)
SSticker.mode.greet_gang(src)
SSticker.mode.equip_gang(current,G)
/datum/mind/proc/make_Abductor()
var/role = alert("Abductor Role ?","Role","Agent","Scientist")
var/team = input("Abductor Team ?","Team ?") in list(1,2,3,4)
+1 -38
View File
@@ -48,41 +48,4 @@
newhud.join_hud(current)
/datum/mind/proc/leave_all_antag_huds()
for(var/datum/atom_hud/antag/hud in GLOB.huds)
if(hud.hudusers[current])
hud.leave_hud(current)
/datum/atom_hud/antag/gang
var/color = null
/datum/atom_hud/antag/gang/add_to_hud(atom/A)
if(!A)
return
var/image/holder = A.hud_list[ANTAG_HUD]
if(holder)
holder.color = color
..()
/datum/atom_hud/antag/gang/remove_from_hud(atom/A)
if(!A)
return
var/image/holder = A.hud_list[ANTAG_HUD]
if(holder)
holder.color = null
..()
/datum/atom_hud/antag/gang/join_hud(mob/M)
if(!istype(M))
CRASH("join_hud(): [M] ([M.type]) is not a mob!")
var/image/holder = M.hud_list[ANTAG_HUD]
if(holder)
holder.color = color
..()
/datum/atom_hud/antag/gang/leave_hud(mob/M)
if(!istype(M))
CRASH("leave_hud(): [M] ([M.type]) is not a mob!")
var/image/holder = M.hud_list[ANTAG_HUD]
if(holder)
holder.color = null
..()
for(var/datum/atom_hud/antag/hud in GLOB.huds)
-5
View File
@@ -30,11 +30,6 @@
altogether."
if("extended")
text += "The transmission mostly failed to mention your sector. It is possible that there is nothing in the Syndicate that could threaten your station during this shift."
if("gang")
text += "Cybersun Industries representatives claimed that they, in joint research with the Tiger Cooperative, have made a major breakthrough in brainwashing technology, and have \
made the nanobots that apply the \"conversion\" very small and capable of fitting into usually innocent objects - namely, pens. While they refused to outsource this technology for \
months to come due to its flaws, they reported some as missing but passed it off to carelessness. At Central Command, we don't like mysteries, and we have reason to believe that this \
technology was stolen for anti-Nanotrasen use. Be on the lookout for territory claims and unusually violent crew behavior, applying mindshield implants as necessary."
if("malf")
text += "A large ionospheric anomaly recently passed through your sector. Although physically undetectable, ionospherics tend to have an extreme effect on telecommunications equipment \
as well as artificial intelligence units. Closely observe the behavior of artificial intelligence, and treat any machine malfunctions as purposeful. If necessary, termination of the \
@@ -306,10 +306,6 @@
to_chat(S, "<span class='warning'>This device is attempting to corrupt our entire network; attempting to interact with it is too risky. Aborting.</span>")
return FALSE
/obj/effect/decal/cleanable/crayon/gang/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>Searching... sensor malfunction! Target lost. Aborting.</span>")
return FALSE
/obj/effect/rune/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>Searching... sensor malfunction! Target lost. Aborting.</span>")
return FALSE
-252
View File
@@ -198,258 +198,6 @@
H.equip_to_slot_or_del(new /obj/item/twohanded/spear(H), slot_back)
/////////////////////Multiverse Blade////////////////////
/obj/item/multisword
name = "multiverse sword"
desc = "A weapon capable of conquering the universe and beyond. Activate it to summon copies of yourself from others dimensions to fight by your side."
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "multiverse"
item_state = "multiverse"
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
hitsound = 'sound/weapons/bladeslice.ogg'
flags_1 = CONDUCT_1
slot_flags = SLOT_BELT
sharpness = IS_SHARP
force = 20
throwforce = 10
w_class = WEIGHT_CLASS_NORMAL
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
var/faction = list("unassigned")
var/cooldown = 0
var/assigned = "unassigned"
var/static/list/multiverse = list()
/obj/item/multisword/New()
..()
multiverse += src
/obj/item/multisword/Destroy()
multiverse.Remove(src)
return ..()
/obj/item/multisword/attack_self(mob/user)
if(user.mind.special_role == "apprentice")
to_chat(user, "<span class='warning'>You know better than to touch your teacher's stuff.</span>")
return
if(cooldown < world.time)
var/faction_check = 0
for(var/F in faction)
if(F in user.faction)
faction_check = 1
break
if(faction_check == 0)
faction = list("[user.real_name]")
assigned = "[user.real_name]"
user.faction = list("[user.real_name]")
to_chat(user, "You bind the sword to yourself. You can now use it to summon help.")
if(!is_gangster(user))
var/datum/gang/multiverse/G = new(src, "[user.real_name]")
SSticker.mode.gangs += G
G.bosses[user.mind] = 0
G.add_gang_hud(user.mind)
user.mind.gang_datum = G
to_chat(user, "<span class='warning'><B>With your new found power you could easily conquer the station!</B></span>")
var/datum/objective/hijackclone/hijack_objective = new /datum/objective/hijackclone
hijack_objective.owner = user.mind
user.mind.objectives += hijack_objective
hijack_objective.explanation_text = "Ensure only [user.real_name] and their copies are on the shuttle!"
to_chat(user, "<B>Objective #[1]</B>: [hijack_objective.explanation_text]")
SSticker.mode.traitors += user.mind
user.mind.special_role = "[user.real_name] Prime"
else
var/list/candidates = get_candidates(ROLE_WIZARD)
if(candidates.len)
var/client/C = pick(candidates)
spawn_copy(C, get_turf(user.loc), user)
to_chat(user, "<span class='warning'><B>The sword flashes, and you find yourself face to face with...you!</B></span>")
cooldown = world.time + 400
for(var/obj/item/multisword/M in multiverse)
if(M.assigned == assigned)
M.cooldown = cooldown
else
to_chat(user, "You fail to summon any copies of yourself. Perhaps you should try again in a bit.")
else
to_chat(user, "<span class='warning'><B>[src] is recharging! Keep in mind it shares a cooldown with the swords wielded by your copies.</span>")
/obj/item/multisword/proc/spawn_copy(var/client/C, var/turf/T, mob/user)
var/mob/living/carbon/human/M = new/mob/living/carbon/human(T)
C.prefs.copy_to(M, icon_updates=0)
M.key = C.key
M.mind.name = user.real_name
to_chat(M, "<B>You are an alternate version of [user.real_name] from another universe! Help them accomplish their goals at all costs.</B>")
SSticker.mode.add_gangster(M.mind, user.mind.gang_datum, FALSE)
M.real_name = user.real_name
M.name = user.real_name
M.faction = list("[user.real_name]")
if(prob(50))
var/list/all_species = list()
for(var/speciestype in subtypesof(/datum/species))
var/datum/species/S = speciestype
if(!initial(S.dangerous_existence))
all_species += speciestype
M.set_species(pick(all_species), icon_update=0)
M.update_body()
M.update_hair()
M.update_body_parts()
M.dna.update_dna_identity()
equip_copy(M)
/obj/item/multisword/proc/equip_copy(var/mob/living/carbon/human/M)
var/obj/item/multisword/sword = new /obj/item/multisword
sword.assigned = assigned
sword.faction = list("[assigned]")
var/randomize = pick("mobster","roman","wizard","cyborg","syndicate","assistant", "animu", "cultist", "highlander", "clown", "killer", "pirate", "soviet", "officer", "gladiator")
switch(randomize)
if("mobster")
M.equip_to_slot_or_del(new /obj/item/clothing/head/fedora(M), slot_head)
M.equip_to_slot_or_del(new /obj/item/clothing/shoes/laceup(M), slot_shoes)
M.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/black(M), slot_gloves)
M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_ears)
M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(M), slot_glasses)
M.equip_to_slot_or_del(new /obj/item/clothing/under/suit_jacket/really_black(M), slot_w_uniform)
M.put_in_hands_or_del(sword)
if("roman")
var/hat = pick(/obj/item/clothing/head/helmet/roman, /obj/item/clothing/head/helmet/roman/legionaire)
M.equip_to_slot_or_del(new hat(M), slot_head)
M.equip_to_slot_or_del(new /obj/item/clothing/under/roman(M), slot_w_uniform)
M.equip_to_slot_or_del(new /obj/item/clothing/shoes/roman(M), slot_shoes)
M.put_in_hands_or_del(new /obj/item/shield/riot/roman(M))
M.put_in_hands_or_del(sword)
if("wizard")
M.equip_to_slot_or_del(new /obj/item/clothing/under/color/lightpurple(M), slot_w_uniform)
M.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/red(M), slot_wear_suit)
M.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal/magic(M), slot_shoes)
M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_ears)
M.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/red(M), slot_head)
M.put_in_hands_or_del(sword)
if("cyborg")
for(var/X in M.bodyparts)
var/obj/item/bodypart/affecting = X
affecting.change_bodypart_status(BODYPART_ROBOTIC, FALSE, TRUE)
M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/eyepatch(M), slot_glasses)
M.put_in_hands_or_del(sword)
if("syndicate")
M.equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(M), slot_w_uniform)
M.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(M), slot_shoes)
M.equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(M), slot_gloves)
M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/swat(M), slot_head)
M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_ears)
M.equip_to_slot_or_del(new /obj/item/clothing/suit/armor/vest(M), slot_wear_suit)
M.equip_to_slot_or_del(new /obj/item/clothing/mask/gas(M),slot_wear_mask)
M.put_in_hands_or_del(sword)
if("assistant")
M.equip_to_slot_or_del(new /obj/item/clothing/under/color/grey(M), slot_w_uniform)
M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_ears)
M.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/black(M), slot_shoes)
M.put_in_hands_or_del(sword)
if("animu")
M.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(M), slot_shoes)
M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_ears)
M.equip_to_slot_or_del(new /obj/item/clothing/head/kitty(M), slot_head)
M.equip_to_slot_or_del(new /obj/item/clothing/under/schoolgirl/red(M), slot_w_uniform)
M.put_in_hands_or_del(sword)
if("cultist")
M.equip_to_slot_or_del(new /obj/item/clothing/head/culthood/alt(M), slot_head)
M.equip_to_slot_or_del(new /obj/item/clothing/suit/cultrobes/alt(M), slot_wear_suit)
M.equip_to_slot_or_del(new /obj/item/clothing/shoes/cult(M), slot_shoes)
M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_ears)
M.put_in_hands_or_del(sword)
if("highlander")
M.equip_to_slot_or_del(new /obj/item/clothing/under/kilt(M), slot_w_uniform)
M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_ears)
M.equip_to_slot_or_del(new /obj/item/clothing/head/beret(M), slot_head)
M.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(M), slot_shoes)
M.put_in_hands_or_del(sword)
if("clown")
M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/clown(M), slot_w_uniform)
M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_ears)
M.equip_to_slot_or_del(new /obj/item/clothing/shoes/clown_shoes(M), slot_shoes)
M.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clown_hat(M), slot_wear_mask)
M.equip_to_slot_or_del(new /obj/item/bikehorn(M), slot_l_store)
M.put_in_hands_or_del(sword)
if("killer")
M.equip_to_slot_or_del(new /obj/item/clothing/under/overalls(M), slot_w_uniform)
M.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/white(M), slot_shoes)
M.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/latex(M), slot_gloves)
M.equip_to_slot_or_del(new /obj/item/clothing/mask/surgical(M), slot_wear_mask)
M.equip_to_slot_or_del(new /obj/item/clothing/head/welding(M), slot_head)
M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_ears)
M.equip_to_slot_or_del(new /obj/item/clothing/suit/apron(M), slot_wear_suit)
M.equip_to_slot_or_del(new /obj/item/kitchen/knife(M), slot_l_store)
M.equip_to_slot_or_del(new /obj/item/scalpel(M), slot_r_store)
M.put_in_hands_or_del(sword)
for(var/obj/item/carried_item in M.get_equipped_items())
carried_item.add_mob_blood(M)
for(var/obj/item/I in M.held_items)
I.add_mob_blood(M)
if("pirate")
M.equip_to_slot_or_del(new /obj/item/clothing/under/pirate(M), slot_w_uniform)
M.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/brown(M), slot_shoes)
M.equip_to_slot_or_del(new /obj/item/clothing/head/bandana(M), slot_head)
M.equip_to_slot_or_del(new /obj/item/clothing/glasses/eyepatch(M), slot_glasses)
M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_ears)
M.put_in_hands_or_del(sword)
if("soviet")
M.equip_to_slot_or_del(new /obj/item/clothing/head/pirate/captain(M), slot_head)
M.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(M), slot_shoes)
M.equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(M), slot_gloves)
M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_ears)
M.equip_to_slot_or_del(new /obj/item/clothing/suit/pirate/captain(M), slot_wear_suit)
M.equip_to_slot_or_del(new /obj/item/clothing/under/soviet(M), slot_w_uniform)
M.put_in_hands_or_del(sword)
if("officer")
M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/beret(M), slot_head)
M.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(M), slot_shoes)
M.equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(M), slot_gloves)
M.equip_to_slot_or_del(new /obj/item/clothing/mask/cigarette/cigar/havana(M), slot_wear_mask)
M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_ears)
M.equip_to_slot_or_del(new /obj/item/clothing/suit/jacket/miljacket(M), slot_wear_suit)
M.equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(M), slot_w_uniform)
M.equip_to_slot_or_del(new /obj/item/clothing/glasses/eyepatch(M), slot_glasses)
M.put_in_hands_or_del(sword)
if("gladiator")
M.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/gladiator(M), slot_head)
M.equip_to_slot_or_del(new /obj/item/clothing/under/gladiator(M), slot_w_uniform)
M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_ears)
M.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(M), slot_shoes)
M.put_in_hands_or_del(sword)
else
return
M.update_body_parts()
var/obj/item/card/id/W = new /obj/item/card/id
W.icon_state = "centcom"
W.access += ACCESS_MAINT_TUNNELS
W.assignment = "Multiverse Traveller"
W.registered_name = M.real_name
W.update_label(M.real_name)
M.equip_to_slot_or_del(W, slot_wear_id)
/obj/item/voodoo
name = "wicker doll"
desc = "Something creepy about it."
-15
View File
@@ -97,21 +97,6 @@
var/completion = round(C.get_completion())
return completion
/obj/effect/countdown/dominator
name = "dominator countdown"
text_size = 1
color = "#ff00ff" // Overwritten when the dominator starts
/obj/effect/countdown/dominator/get_value()
var/obj/machinery/dominator/D = attached_to
if(!istype(D))
return
else if(D.gang && D.gang.is_dominating)
var/timer = D.gang.domination_time_remaining()
return timer
else
return "OFFLINE"
/obj/effect/countdown/clockworkgate
name = "gateway countdown"
text_size = 1
@@ -11,8 +11,6 @@
name = e_name
desc = "A [name] vandalizing the station."
if(type == "poseur tag")
type = pick(GLOB.gang_name_pool)
if(alt_icon)
icon = alt_icon
@@ -24,41 +22,3 @@
src.transform = M
add_atom_colour(main, FIXED_COLOUR_PRIORITY)
/obj/effect/decal/cleanable/crayon/gang
layer = HIGH_OBJ_LAYER //Harder to hide
do_icon_rotate = FALSE //These are designed to always face south, so no rotation please.
var/datum/gang/gang
var/datum/mind/user_mind
var/area/territory
/obj/effect/decal/cleanable/crayon/gang/Initialize(mapload, var/datum/gang/G, var/e_name = "gang tag", var/rotation = 0, var/mob/user)
if(!type || !G)
qdel(src)
user_mind = user.mind
territory = get_area(src)
gang = G
var/newcolor = G.color_hex
icon_state = G.name
G.territory_new |= list(territory.type = territory.name)
//If this isn't tagged by a specific gangster there's no bonus income.
set_mind_owner(user_mind)
..(mapload, newcolor, icon_state, e_name, rotation)
/obj/effect/decal/cleanable/crayon/gang/proc/set_mind_owner(datum/mind/mind)
if(istype(user_mind) && istype(gang) && islist(gang.tags_by_mind[user_mind])) //Clear us out of old ownership
gang.tags_by_mind[user_mind] -= src
if(istype(mind))
if(!islist(gang.tags_by_mind[mind]))
gang.tags_by_mind[mind] = list()
gang.tags_by_mind[mind] += src
user_mind = mind
/obj/effect/decal/cleanable/crayon/gang/Destroy()
if(gang)
gang.territory -= territory.type
set_mind_owner(null)
gang.territory_new -= territory.type
gang.territory_lost |= list(territory.type = territory.name)
return ..()
+14 -90
View File
@@ -54,7 +54,6 @@
var/self_contained = TRUE // If it deletes itself when it is empty
var/list/validSurfaces = list(/turf/open/floor)
var/gang = FALSE //For marking territory
var/edible = TRUE // That doesn't mean eating it is a good idea
@@ -278,15 +277,6 @@
else if(drawing in numerals)
temp = "number"
// If a gang member is using a gang spraycan, it'll behave differently
var/gang_mode = FALSE
if(gang && user.mind && user.mind.gang_datum)
gang_mode = TRUE
// discontinue if the area isn't valid for tagging because gang "honour"
if(gang_mode && (!can_claim_for_gang(user, target)))
return
var/graf_rot
if(drawing in oriented)
switch(user.dir)
@@ -307,8 +297,6 @@
playsound(user.loc, 'sound/effects/spray.ogg', 5, 1, 5)
var/takes_time = !instant
if(gang_mode)
takes_time = TRUE
var/wait_time = 50
if(PAINT_LARGE_HORIZONTAL)
@@ -325,28 +313,21 @@
var/list/turf/affected_turfs = list()
if(actually_paints)
if(gang_mode)
// Double check it wasn't tagged in the meanwhile
if(!can_claim_for_gang(user, target))
return
tag_for_gang(user, target)
affected_turfs += target
else
switch(paint_mode)
if(PAINT_NORMAL)
new /obj/effect/decal/cleanable/crayon(target, paint_color, drawing, temp, graf_rot)
switch(paint_mode)
if(PAINT_NORMAL)
new /obj/effect/decal/cleanable/crayon(target, paint_color, drawing, temp, graf_rot)
affected_turfs += target
if(PAINT_LARGE_HORIZONTAL)
var/turf/left = locate(target.x-1,target.y,target.z)
var/turf/right = locate(target.x+1,target.y,target.z)
if(is_type_in_list(left, validSurfaces) && is_type_in_list(right, validSurfaces))
new /obj/effect/decal/cleanable/crayon(left, paint_color, drawing, temp, graf_rot, PAINT_LARGE_HORIZONTAL_ICON)
affected_turfs += left
affected_turfs += right
affected_turfs += target
if(PAINT_LARGE_HORIZONTAL)
var/turf/left = locate(target.x-1,target.y,target.z)
var/turf/right = locate(target.x+1,target.y,target.z)
if(is_type_in_list(left, validSurfaces) && is_type_in_list(right, validSurfaces))
new /obj/effect/decal/cleanable/crayon(left, paint_color, drawing, temp, graf_rot, PAINT_LARGE_HORIZONTAL_ICON)
affected_turfs += left
affected_turfs += right
affected_turfs += target
else
to_chat(user, "<span class='warning'>There isn't enough space to paint!</span>")
return
else
to_chat(user, "<span class='warning'>There isn't enough space to paint!</span>")
return
if(!instant)
to_chat(user, "<span class='notice'>You finish drawing \the [temp].</span>")
@@ -385,47 +366,6 @@
else
..()
/obj/item/toy/crayon/proc/can_claim_for_gang(mob/user, atom/target)
// Check area validity.
// Reject space, player-created areas, and non-station z-levels.
var/area/A = get_area(target)
if(!A || (A.z != ZLEVEL_STATION) || !A.valid_territory)
to_chat(user, "<span class='warning'>[A] is unsuitable for tagging.</span>")
return FALSE
var/spraying_over = FALSE
for(var/obj/effect/decal/cleanable/crayon/gang/G in target)
spraying_over = TRUE
for(var/obj/machinery/power/apc in target)
to_chat(user, "<span class='warning'>You can't tag an APC.</span>")
return FALSE
var/occupying_gang = territory_claimed(A, user)
if(occupying_gang && !spraying_over)
to_chat(user, "<span class='danger'>[A] has already been tagged by the [occupying_gang] gang! You must get rid of or spray over the old tag first!</span>")
return FALSE
// If you pass the gaunlet of checks, you're good to proceed
return TRUE
/obj/item/toy/crayon/proc/territory_claimed(area/territory, mob/user)
for(var/datum/gang/G in SSticker.mode.gangs)
if(territory.type in (G.territory|G.territory_new))
. = G.name
break
/obj/item/toy/crayon/proc/tag_for_gang(mob/user, atom/target)
//Delete any old markings on this tile, including other gang tags
for(var/obj/effect/decal/cleanable/crayon/old_marking in target)
qdel(old_marking)
var/gangID = user.mind.gang_datum
var/area/territory = get_area(target)
new /obj/effect/decal/cleanable/crayon/gang(target,gangID,"graffiti",0,user)
to_chat(user, "<span class='notice'>You tagged [territory] for your gang!</span>")
/obj/item/toy/crayon/red
icon_state = "crayonred"
paint_color = "#DA0000"
@@ -676,25 +616,9 @@
spray_overlay.color = paint_color
add_overlay(spray_overlay)
/obj/item/toy/crayon/spraycan/gang
//desc = "A modified container containing suspicious paint."
charges = 20
gang = TRUE
pre_noise = FALSE
post_noise = TRUE
/obj/item/toy/crayon/spraycan/gang/New(loc, datum/gang/G)
..()
if(G)
paint_color = G.color_hex
update_icon()
/obj/item/toy/crayon/spraycan/gang/examine(mob/user)
. = ..()
if((user.mind && user.mind.gang_datum) || isobserver(user))
to_chat(user, "This spraycan has been specially modified for tagging territory.")
/obj/item/toy/crayon/spraycan/borg
name = "cyborg spraycan"
desc = "A metallic container containing shiny synthesised paint."
@@ -135,8 +135,6 @@
message_say = "FOR NAR-SIE!"
else if(role == "revolutionary" || role == "head revolutionary")
message_say = "VIVA LA REVOLUTION!"
else if(user.mind.gang_datum)
message_say = "[uppertext(user.mind.gang_datum.name)] RULES!"
user.say(message_say)
explosion(user,0,2,0) //Cheap explosion imitation because putting prime() here causes runtimes
user.gib(1, 1)
@@ -192,8 +190,6 @@
message_say = "FOR NAR-SIE!"
else if(role == "revolutionary" || role == "head revolutionary")
message_say = "VIVA LA REVOLUTION!"
else if(user.mind.gang_datum)
message_say = "[uppertext(user.mind.gang_datum.name)] RULES!"
user.say(message_say)
target = user
message_admins("[ADMIN_LOOKUPFLW(user)] suicided with [name] at [ADMIN_COORDJMP(src)]",0,1)
@@ -19,19 +19,12 @@
/obj/item/implant/mindshield/implant(mob/living/target, mob/user, silent = 0)
if(..())
if((target.mind in (SSticker.mode.head_revolutionaries | SSticker.mode.get_gang_bosses())))
if((target.mind in (SSticker.mode.head_revolutionaries)))
if(!silent)
target.visible_message("<span class='warning'>[target] seems to resist the implant!</span>", "<span class='warning'>You feel something interfering with your mental conditioning, but you resist it!</span>")
removed(target, 1)
qdel(src)
return 0
if(target.mind in SSticker.mode.get_gangsters())
SSticker.mode.remove_gangster(target.mind)
if(!silent)
target.visible_message("<span class='warning'>[src] was destroyed in the process!</span>", "<span class='notice'>You feel a sense of peace and security. You are now protected from brainwashing.</span>")
removed(target, 1)
qdel(src)
return 0
if(target.mind in SSticker.mode.revolutionaries)
SSticker.mode.remove_revolutionary(target.mind)
if(!silent)
+1
View File
@@ -86,6 +86,7 @@ GLOBAL_PROTECT(security_mode)
GLOB.world_game_log = file("[GLOB.log_directory]/game.log")
GLOB.world_attack_log = file("[GLOB.log_directory]/attack.log")
GLOB.world_runtime_log = file("[GLOB.log_directory]/runtime.log")
GLOB.world_qdel_log = file("[GLOB.log_directory]/qdel.log")
GLOB.world_href_log = file("[GLOB.log_directory]/hrefs.html")
GLOB.sql_error_log = file("[GLOB.log_directory]/sql.log")
WRITE_FILE(GLOB.world_game_log, "\n\nStarting up round ID [GLOB.round_id]. [time_stamp()]\n---------------------")
+1 -19
View File
@@ -440,25 +440,7 @@
dat += "<tr><td><a href='?_src_=vars;[HrefToken()];Vars=\ref[N]'>[N.name]([N.key])</a><i>Head body destroyed!</i></td>"
dat += "<td><A href='?priv_msg=[N.key]'>PM</A></td></tr>"
dat += "</table>"
for(var/datum/gang/G in SSticker.mode.gangs)
dat += "<br><table cellspacing=5><tr><td><B>[G.name] Gang: [round((G.territory.len/GLOB.start_state.num_territories)*100, 1)]% Control</B></td><td></td></tr>"
for(var/datum/mind/N in G.bosses)
var/mob/M = N.current
if(!M)
dat += "<tr><td><a href='?_src_=vars;Vars=\ref[N]'>[N.name]([N.key])</a><i>Gang Boss body destroyed!</i></td>"
dat += "<td><A href='?priv_msg=[N.key]'>PM</A></td></tr>"
else
dat += "<tr><td><a href='?_src_=holder;adminplayeropts=\ref[M]'>[M.real_name]</a> <b>(Boss)</b>[M.client ? "" : " <i>(No Client)</i>"][M.stat == DEAD ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
dat += "<td><A href='?priv_msg=[M.ckey]'>PM</A></td>"
dat += "<td><A href='?_src_=holder;adminplayerobservefollow=\ref[M]'>FLW</a></td></tr>"
for(var/datum/mind/N in G.gangsters)
var/mob/M = N.current
if(M)
dat += "<tr><td><a href='?_src_=holder;adminplayeropts=\ref[M]'>[M.real_name]</a>[M.client ? "" : " <i>(No Client)</i>"][M.stat == DEAD ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
dat += "<td><A href='?priv_msg=[M.ckey]'>PM</A></td></tr>"
dat += "</table>"
if(SSticker.mode.changelings.len > 0)
dat += "<br><table cellspacing=5><tr><td><B>Changelings</B></td><td></td><td></td></tr>"
for(var/datum/mind/changeling in SSticker.mode.changelings)
-15
View File
@@ -129,13 +129,6 @@
message_admins("[key_name(usr)] spawned a blob with base resource gain [strength].")
log_admin("[key_name(usr)] spawned a blob with base resource gain [strength].")
new/datum/round_event/ghost_role/blob(TRUE, strength)
if("gangs")
if(src.makeGangsters())
message_admins("[key_name(usr)] created gangs.")
log_admin("[key_name(usr)] created gangs.")
else
message_admins("[key_name(usr)] tried to create gangs. Unfortunately, there were not enough candidates available.")
log_admin("[key_name(usr)] failed create gangs.")
if("centcom")
message_admins("[key_name(usr)] is creating a CentCom response team...")
if(src.makeEmergencyresponseteam())
@@ -839,14 +832,6 @@
else
dat += "<td width='20%'><a href='?src=\ref[src];[HrefToken()];jobban3=revolutionary;jobban4=\ref[M]'>Revolutionary</a></td>"
//Gangster
if(jobban_isbanned(M, "gangster") || isbanned_dept)
dat += "<td width='20%'><a href='?src=\ref[src];jobban3=gangster;jobban4=\ref[M]'><font color=red>Gangster</font></a></td>"
else
dat += "<td width='20%'><a href='?src=\ref[src];jobban3=gangster;jobban4=\ref[M]'>Gangster</a></td>"
dat += "</tr><tr align='center'>" //Breaking it up so it fits nicer on the screen every 5 entries
//Cultist
if(jobban_isbanned(M, "cultist") || isbanned_dept)
dat += "<td width='20%'><a href='?src=\ref[src];[HrefToken()];jobban3=cultist;jobban4=\ref[M]'><font color=red>Cultist</font></a></td>"
+22 -12
View File
@@ -743,21 +743,31 @@ GLOBAL_PROTECT(AdminProcCallCount)
/client/proc/cmd_display_del_log()
set category = "Debug"
set name = "Display del() Log"
set desc = "Displays a list of things that have failed to GC this round"
set desc = "Display del's log of everything that's passed through it."
var/dat = "<B>List of things that failed to GC this round</B><BR><BR>"
for(var/path in SSgarbage.didntgc)
dat += "[path] - [SSgarbage.didntgc[path]] times<BR>"
var/list/dellog = list("<B>List of things that have gone through qdel this round</B><BR><BR><ol>")
sortTim(SSgarbage.items, cmp=/proc/cmp_qdel_item_time, associative = TRUE)
for(var/path in SSgarbage.items)
var/datum/qdel_item/I = SSgarbage.items[path]
dellog += "<li><u>[path]</u><ul>"
if (I.failures)
dellog += "<li>Failures: [I.failures]</li>"
dellog += "<li>qdel() Count: [I.qdels]</li>"
dellog += "<li>Destroy() Cost: [I.destroy_time]ms</li>"
if (I.hard_deletes)
dellog += "<li>Total Hard Deletes [I.hard_deletes]</li>"
dellog += "<li>Time Spent Hard Deleting: [I.hard_delete_time]ms</li>"
if (I.slept_destroy)
dellog += "<li>Sleeps: [I.slept_destroy]</li>"
if (I.no_respect_force)
dellog += "<li>Ignored force: [I.no_respect_force]</li>"
if (I.no_hint)
dellog += "<li>No hint: [I.no_hint]</li>"
dellog += "</ul></li>"
dat += "<B>List of paths that did not return a qdel hint in Destroy()</B><BR><BR>"
for(var/path in SSgarbage.noqdelhint)
dat += "[path]<BR>"
dellog += "</ol>"
dat += "<B>List of paths that slept in Destroy()</B><BR><BR>"
for(var/path in SSgarbage.sleptDestroy)
dat += "[path]<BR>"
usr << browse(dat, "window=dellog")
usr << browse(dellog.Join(), "window=dellog")
/client/proc/cmd_display_init_log()
set category = "Debug"
-45
View File
@@ -77,48 +77,3 @@ GLOBAL_VAR_INIT(highlander, FALSE)
to_chat(src, "<span class='boldannounce'>Your [H1.name] cries out for blood. Claim the lives of others, and your own will be restored!\n\
Activate it in your hand, and it will lead to the nearest target. Attack the nuclear authentication disk with it, and you will store it.</span>")
/proc/only_me()
if(!SSticker.HasRoundStarted())
alert("The game hasn't started yet!")
return
for(var/mob/living/carbon/human/H in GLOB.player_list)
if(H.stat == 2 || !(H.client)) continue
if(is_special_character(H)) continue
SSticker.mode.traitors += H.mind
H.mind.special_role = "[H.real_name] Prime"
var/datum/objective/hijackclone/hijack_objective = new /datum/objective/hijackclone
hijack_objective.owner = H.mind
H.mind.objectives += hijack_objective
to_chat(H, "<B>You are the multiverse summoner. Activate your blade to summon copies of yourself from another universe to fight by your side.</B>")
H.mind.announce_objectives()
var/datum/gang/multiverse/G = new(src, "[H.real_name]")
SSticker.mode.gangs += G
G.bosses[H.mind] = 0 //No they don't use influence but this prevents runtimes.
G.add_gang_hud(H.mind)
H.mind.gang_datum = G
var/obj/item/slot_item_ID = H.get_item_by_slot(slot_wear_id)
qdel(slot_item_ID)
var/obj/item/slot_item_hand = H.get_item_for_held_index(2)
H.dropItemToGround(slot_item_hand)
var /obj/item/multisword/multi = new(H)
H.put_in_hands_or_del(multi)
var/obj/item/card/id/W = new(H)
W.icon_state = "centcom"
W.access = get_all_accesses()
W.access += get_all_centcom_access()
W.assignment = "Multiverse Summoner"
W.registered_name = H.real_name
W.update_label(H.real_name)
H.equip_to_slot_or_del(W, slot_wear_id)
message_admins("<span class='adminnotice'>[key_name_admin(usr)] used THERE CAN BE ONLY ME!</span>")
log_admin("[key_name(usr)] used there can be only me.")
File diff suppressed because it is too large Load Diff
@@ -81,8 +81,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
be_special += ROLE_NINJA
if(2048)
be_special += ROLE_MONKEY
if(4096)
be_special += ROLE_GANG
if(16384)
be_special += ROLE_ABDUCTOR
-1
View File
@@ -22,7 +22,6 @@
var/cooldown = 0
var/obj/item/device/flashlight/F = null
var/can_flashlight = 0
var/gang //Is this a gang outfit?
var/scan_reagents = 0 //Can the wearer see reagents while it's equipped?
//Var modification - PLEASE be careful with this I know who you are and where you live
-3
View File
@@ -163,6 +163,3 @@
icon = 'icons/obj/clothing/neck.dmi'
icon_state = "bling"
item_color = "bling"
/obj/item/clothing/neck/necklace/dope/gang_contraband_value()
return 2
-14
View File
@@ -221,9 +221,6 @@ GLOBAL_PROTECT(exp_to_update)
to_chat(mob,"<span class='notice'>You got: [minutes] [role] EXP!</span>")
if(mob.mind.special_role && !mob.mind.var_edited)
var/trackedrole = mob.mind.special_role
var/gangrole = lookforgangrole(mob.mind.special_role)
if(gangrole)
trackedrole = gangrole
play_records[trackedrole] += minutes
if(announce_changes)
to_chat(src,"<span class='notice'>You got: [minutes] [trackedrole] EXP!</span>")
@@ -266,14 +263,3 @@ GLOBAL_PROTECT(exp_to_update)
else if(isnull(prefs.db_flags))
prefs.db_flags = 0 //This PROBABLY won't happen, but better safe than sorry.
return TRUE
//Since each gang is tracked as a different antag type, records need to be generalized or you get up to 57 different possible records
/proc/lookforgangrole(rolecheck)
if(findtext(rolecheck,"Gangster"))
return "Gangster"
else if(findtext(rolecheck,"Gang Boss"))
return "Gang Boss"
else if(findtext(rolecheck,"Gang Lieutenant"))
return "Gang Lieutenant"
else
return FALSE
+3 -4
View File
@@ -309,10 +309,9 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
..()
if(statpanel("Status"))
if(SSticker.HasRoundStarted())
if(istype(SSticker.mode, /datum/game_mode/blob))
var/datum/game_mode/blob/B = SSticker.mode
if(B.message_sent)
stat(null, "Blobs to Blob Win: [GLOB.blobs_legit.len]/[B.blobwincount]")
var/datum/game_mode/blob/B = SSticker.mode
if(B.message_sent)
stat(null, "Blobs to Blob Win: [GLOB.blobs_legit.len]/[B.blobwincount]")
/mob/dead/observer/verb/reenter_corpse()
set category = "Ghost"
-3
View File
@@ -746,9 +746,6 @@
if(statpanel("Status"))
if(SSticker && SSticker.mode)
for(var/datum/gang/G in SSticker.mode.gangs)
if(G.is_dominating)
stat(null, "[G.name] Gang Takeover: [max(G.domination_time_remaining(), 0)]")
if(istype(SSticker.mode, /datum/game_mode/blob))
var/datum/game_mode/blob/B = SSticker.mode
if(B.message_sent)
-1
View File
@@ -2,5 +2,4 @@
if(mind && SSticker.mode)
SSticker.mode.remove_cultist(mind, 0, 0)
SSticker.mode.remove_revolutionary(mind, 0)
SSticker.mode.remove_gangster(mind, remove_bosses=1)
..()
@@ -5,4 +5,3 @@
show_laws(0)
if(mind)
SSticker.mode.remove_revolutionary(mind)
SSticker.mode.remove_gangster(mind,1,remove_bosses=1)
-10
View File
@@ -301,16 +301,6 @@
var/datum/DBQuery/query_round_shuttle_name = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET shuttle_name = '[name]' WHERE id = [GLOB.round_id]")
query_round_shuttle_name.Execute()
// Gangs only have one attempt left if the shuttle has
// docked with the station to prevent suffering from
// endless dominator delays
for(var/datum/gang/G in SSticker.mode.gangs)
if(G.is_dominating)
G.dom_attempts = 0
else
G.dom_attempts = min(1,G.dom_attempts)
if(SHUTTLE_DOCKED)
if(time_left <= ENGINES_START_TIME)
mode = SHUTTLE_IGNITING
+12 -21
View File
@@ -218,10 +218,6 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
surplus = 40
include_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/dangerous/smg/unrestricted
item = /obj/item/gun/ballistic/automatic/c20r/unrestricted
include_modes = list(/datum/game_mode/gang)
/datum/uplink_item/dangerous/machinegun
name = "L6 Squad Automatic Weapon"
desc = "A fully-loaded Aussec Armoury belt-fed machine gun. \
@@ -265,7 +261,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
item = /obj/item/gun/energy/kinetic_accelerator/crossbow
cost = 12
surplus = 50
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/gang)
exclude_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/dangerous/flamethrower
name = "Flamethrower"
@@ -274,7 +270,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
item = /obj/item/flamethrower/full/tank
cost = 4
surplus = 40
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/gang)
include_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/dangerous/sword
name = "Energy Sword"
@@ -361,7 +357,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
item = /obj/item/reagent_containers/spray/chemsprayer/bioterror
cost = 20
surplus = 0
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/gang)
include_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/stealthy_weapons/virus_grenade
name = "Fungal Tuberculosis Grenade"
@@ -472,7 +468,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
These bullets pack a lot of punch that can knock most targets down, but do limited overall damage."
item = /obj/item/ammo_box/magazine/smgm45
cost = 3
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/gang)
include_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/ammo/smg/bag
name = ".45 Ammo Duffel Bag"
@@ -613,7 +609,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
item = /obj/item/sleeping_carp_scroll
cost = 17
surplus = 0
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/gang)
exclude_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/stealthy_weapons/cqc
name = "CQC Manual"
@@ -643,7 +639,6 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
item = /obj/item/gun/ballistic/automatic/toy/pistol/riot
cost = 3
surplus = 10
exclude_modes = list(/datum/game_mode/gang)
/datum/uplink_item/stealthy_weapons/sleepy_pen
name = "Sleepy Pen"
@@ -653,7 +648,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
falls asleep, they will be able to move and act."
item = /obj/item/pen/sleepy
cost = 4
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/gang)
exclude_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/stealthy_weapons/soap
name = "Syndicate Soap"
@@ -676,7 +671,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
item = /obj/item/storage/box/syndie_kit/romerol
cost = 25
cant_discount = TRUE
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/gang)
exclude_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/stealthy_weapons/dart_pistol
name = "Dart Pistol"
@@ -784,7 +779,6 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
move the projector from their hand. Disguised users move slowly, and projectiles pass over them."
item = /obj/item/device/chameleon
cost = 7
exclude_modes = list(/datum/game_mode/gang)
/datum/uplink_item/stealthy_tools/camera_bug
name = "Camera Bug"
@@ -818,7 +812,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
item = /obj/item/reagent_containers/syringe/mulligan
cost = 4
surplus = 30
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/gang)
exclude_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/stealthy_tools/emplight
name = "EMP Flashlight"
@@ -846,7 +840,6 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
//Space Suits and Hardsuits
/datum/uplink_item/suits
category = "Space Suits and Hardsuits"
exclude_modes = list(/datum/game_mode/gang)
surplus = 40
/datum/uplink_item/suits/space_suit
@@ -897,7 +890,6 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
in electronic devices, subverts intended functions, and easily breaks security mechanisms."
item = /obj/item/card/emag
cost = 6
exclude_modes = list(/datum/game_mode/gang)
/datum/uplink_item/device_tools/toolbox
name = "Full Syndicate Toolbox"
@@ -927,7 +919,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
and other supplies helpful for a field medic."
item = /obj/item/storage/firstaid/tactical
cost = 4
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/gang)
include_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/device_tools/syndietome
name = "Syndicate Tome"
@@ -1044,7 +1036,6 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
sends you a small beacon that will teleport the larger beacon to your location upon activation."
item = /obj/item/device/sbeacondrop
cost = 14
exclude_modes = list(/datum/game_mode/gang)
/datum/uplink_item/device_tools/syndicate_bomb
name = "Syndicate Bomb"
@@ -1090,7 +1081,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
item = /obj/item/shield/energy
cost = 16
surplus = 20
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/gang)
include_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/device_tools/medgun
name = "Medbeam Gun"
@@ -1378,7 +1369,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
you will receive."
item = /obj/item/storage/box/syndicate
cost = 20
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/gang)
exclude_modes = list(/datum/game_mode/nuclear)
cant_discount = TRUE
/datum/uplink_item/badass/surplus
@@ -1388,7 +1379,7 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once.
item = /obj/structure/closet/crate
cost = 20
player_minimum = 25
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/gang)
exclude_modes = list(/datum/game_mode/nuclear)
cant_discount = TRUE
/datum/uplink_item/badass/surplus/spawn_item(turf/loc, obj/item/device/uplink/U)