Merge remote-tracking branch 'refs/remotes/origin/master' into custom_roundstart_items

This commit is contained in:
kevinz000
2017-05-14 20:54:47 -07:00
270 changed files with 12488 additions and 5920 deletions
+4
View File
@@ -13,6 +13,10 @@
#define MC_AVERAGE_FAST(average, current) (0.7 * (average) + 0.3 * (current))
#define MC_AVERAGE(average, current) (0.8 * (average) + 0.2 * (current))
#define MC_AVERAGE_SLOW(average, current) (0.9 * (average) + 0.1 * (current))
#define MC_AVG_FAST_UP_SLOW_DOWN(average, current) (average > current ? MC_AVERAGE_SLOW(average, current) : MC_AVERAGE_FAST(average, current))
#define MC_AVG_SLOW_UP_FAST_DOWN(average, current) (average < current ? MC_AVERAGE_SLOW(average, current) : MC_AVERAGE_FAST(average, current))
#define NEW_SS_GLOBAL(varname) if(varname != src){if(istype(varname)){Recover();qdel(varname);}varname = src;}
#define START_PROCESSING(Processor, Datum) if (!Datum.isprocessing) {Datum.isprocessing = 1;Processor.processing += Datum}
+12 -5
View File
@@ -16,10 +16,10 @@
#define LIGHTING_BASE_MATRIX \
list \
( \
LIGHTING_SOFT_THRESHOLD, LIGHTING_SOFT_THRESHOLD, LIGHTING_SOFT_THRESHOLD, 0, \
LIGHTING_SOFT_THRESHOLD, LIGHTING_SOFT_THRESHOLD, LIGHTING_SOFT_THRESHOLD, 0, \
LIGHTING_SOFT_THRESHOLD, LIGHTING_SOFT_THRESHOLD, LIGHTING_SOFT_THRESHOLD, 0, \
LIGHTING_SOFT_THRESHOLD, LIGHTING_SOFT_THRESHOLD, LIGHTING_SOFT_THRESHOLD, 0, \
1, 1, 1, 0, \
1, 1, 1, 0, \
1, 1, 1, 0, \
1, 1, 1, 0, \
0, 0, 0, 1 \
) \
@@ -78,4 +78,11 @@
#define DYNAMIC_LIGHTING_ENABLED 1 //dynamic lighting enabled
#define DYNAMIC_LIGHTING_FORCED 2 //dynamic lighting enabled even if the area doesn't require power
#define DYNAMIC_LIGHTING_IFSTARLIGHT 3 //dynamic lighting enabled only if starlight is.
#define IS_DYNAMIC_LIGHTING(A) A.dynamic_lighting
#define IS_DYNAMIC_LIGHTING(A) A.dynamic_lighting
//code assumes higher numbers override lower numbers.
#define LIGHTING_NO_UPDATE 0
#define LIGHTING_VIS_UPDATE 1
#define LIGHTING_CHECK_UPDATE 2
#define LIGHTING_FORCE_UPDATE 3
+3
View File
@@ -0,0 +1,3 @@
#define CHECKBOX_NONE 0
#define CHECKBOX_GROUP 1
#define CHECKBOX_TOGGLE 2
+4
View File
@@ -33,4 +33,8 @@
#define STATUS_EFFECT_SIGILMARK /datum/status_effect/sigil_mark
#define STATUS_EFFECT_BELLIGERENT /datum/status_effect/belligerent //forces the affected to walk, doing damage if they try to run
#define STATUS_EFFECT_MANIAMOTOR /datum/status_effect/maniamotor //disrupts, damages, and confuses the affected as long as they're in range of the motor
#define MAX_MANIA_SEVERITY 100 //how high the mania severity can go
#define MANIA_DAMAGE_TO_CONVERT 90 //how much damage is required before it'll convert affected targets
#define STATUS_EFFECT_HISWRATH /datum/status_effect/his_wrath //His Wrath.
+10
View File
@@ -0,0 +1,10 @@
diff a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm (rejected hunks)
@@ -33,4 +33,8 @@
#define STATUS_EFFECT_SIGILMARK /datum/status_effect/sigil_mark
#define STATUS_EFFECT_BELLIGERENT /datum/status_effect/belligerent //forces the affected to walk, doing damage if they try to run
+#define STATUS_EFFECT_MANIAMOTOR /datum/status_effect/maniamotor //disrupts, damages, and confuses the affected as long as they're in range of the motor
+#define MAX_MANIA_SEVERITY 100 //how high the mania severity can go
+#define MANIA_DAMAGE_TO_CONVERT 90 //how much damage is required before it'll convert affected targets
+
#define STATUS_EFFECT_HISWRATH /datum/status_effect/his_wrath //His Wrath.
+1
View File
@@ -457,6 +457,7 @@
#define LAZYACCESS(L, I) (L ? (isnum(I) ? (I > 0 && I <= L.len ? L[I] : null) : L[I]) : null)
#define LAZYLEN(L) length(L)
#define LAZYCLEARLIST(L) if(L) L.Cut()
#define SANITIZE_LIST(L) ( islist(L) ? L : list() )
/* Definining a counter as a series of key -> numeric value entries
+17 -20
View File
@@ -20,13 +20,13 @@
/proc/log_admin(text)
GLOB.admin_log.Add(text)
if (config.log_admin)
GLOB.diary << "\[[time_stamp()]]ADMIN: [text]"
GLOB.world_game_log << "\[[time_stamp()]]ADMIN: [text]"
//Items using this proc are stripped from public logs - use with caution
/proc/log_admin_private(text)
GLOB.admin_log.Add(text)
if (config.log_admin)
GLOB.diary << "\[[time_stamp()]]ADMINPRIVATE: [text]"
GLOB.world_game_log << "\[[time_stamp()]]ADMINPRIVATE: [text]"
/proc/log_adminsay(text)
if (config.log_adminchat)
@@ -38,67 +38,64 @@
/proc/log_game(text)
if (config.log_game)
GLOB.diary << "\[[time_stamp()]]GAME: [text]"
GLOB.world_game_log << "\[[time_stamp()]]GAME: [text]"
/proc/log_vote(text)
if (config.log_vote)
GLOB.diary << "\[[time_stamp()]]VOTE: [text]"
GLOB.world_game_log << "\[[time_stamp()]]VOTE: [text]"
/proc/log_access(text)
if (config.log_access)
GLOB.diary << "\[[time_stamp()]]ACCESS: [text]"
GLOB.world_game_log << "\[[time_stamp()]]ACCESS: [text]"
/proc/log_say(text)
if (config.log_say)
GLOB.diary << "\[[time_stamp()]]SAY: [text]"
GLOB.world_game_log << "\[[time_stamp()]]SAY: [text]"
/proc/log_prayer(text)
if (config.log_prayer)
GLOB.diary << "\[[time_stamp()]]PRAY: [text]"
GLOB.world_game_log << "\[[time_stamp()]]PRAY: [text]"
/proc/log_law(text)
if (config.log_law)
GLOB.diary << "\[[time_stamp()]]LAW: [text]"
GLOB.world_game_log << "\[[time_stamp()]]LAW: [text]"
/proc/log_ooc(text)
if (config.log_ooc)
GLOB.diary << "\[[time_stamp()]]OOC: [text]"
GLOB.world_game_log << "\[[time_stamp()]]OOC: [text]"
/proc/log_whisper(text)
if (config.log_whisper)
GLOB.diary << "\[[time_stamp()]]WHISPER: [text]"
GLOB.world_game_log << "\[[time_stamp()]]WHISPER: [text]"
/proc/log_emote(text)
if (config.log_emote)
GLOB.diary << "\[[time_stamp()]]EMOTE: [text]"
GLOB.world_game_log << "\[[time_stamp()]]EMOTE: [text]"
/proc/log_attack(text)
if (config.log_attack)
GLOB.diaryofmeanpeople << "\[[time_stamp()]]ATTACK: [text]"
GLOB.world_attack_log << "\[[time_stamp()]]ATTACK: [text]"
/proc/log_pda(text)
if (config.log_pda)
GLOB.diary << "\[[time_stamp()]]PDA: [text]"
GLOB.world_game_log << "\[[time_stamp()]]PDA: [text]"
/proc/log_comment(text)
if (config.log_pda)
//reusing the PDA option because I really don't think news comments are worth a config option
GLOB.diary << "\[[time_stamp()]]COMMENT: [text]"
GLOB.world_game_log << "\[[time_stamp()]]COMMENT: [text]"
/proc/log_chat(text)
if (config.log_pda)
GLOB.diary << "\[[time_stamp()]]CHAT: [text]"
GLOB.world_game_log << "\[[time_stamp()]]CHAT: [text]"
/proc/log_sql(text)
if(config.sql_enabled)
GLOB.diary << "\[[time_stamp()]]SQL: [text]"
GLOB.world_game_log << "\[[time_stamp()]]SQL: [text]"
//This replaces world.log so it displays both in DD and the file
/proc/log_world(text)
if(config && config.log_runtimes)
world.log = GLOB.runtime_diary
world.log << text
world.log = null
GLOB.world_runtime_log << text
world.log << text
// Helper procs for building detailed log lines
-37
View File
@@ -1,37 +0,0 @@
#define YOUNG 4
/client/proc/join_date_check(y,m,d)
var/datum/DBQuery/query_datediff = SSdbcore.NewQuery("SELECT DATEDIFF(Now(),'[y]-[m]-[d]')")
if(!query_datediff.Execute())
return FALSE
if(query_datediff.NextRow())
var/diff = text2num(query_datediff.item[1])
if(config.use_account_age_for_jobs)
player_age = max(0,diff) //So job code soesn't freak out if they are time traveling.
if(diff < YOUNG)
var/msg = "(IP: [address], ID: [computer_id]) is a new BYOND account made on [y]-[m]-[d]."
if(diff < 0)
msg += " They are also apparently from the future."
message_admins("[key_name_admin(src)] [msg]")
return TRUE
#undef YOUNG
/client/proc/findJoinDate()
var/http[] = world.Export("http://byond.com/members/[src.ckey]?format=text")
if(!http)
log_world("Failed to connect to byond age check for [src.ckey]")
return FALSE
var/F = file2text(http["CONTENT"])
if(F)
var/regex/R = regex("joined = \"(\\d{4})-(\\d{2})-(\\d{2})\"")
if(!R.Find(F))
CRASH("Age check regex failed")
var/y = R.group[1]
var/m = R.group[2]
var/d = R.group[3]
return join_date_check(y,m,d)
+1 -1
View File
@@ -24,4 +24,4 @@ GLOBAL_LIST_EMPTY(whitelisted_species_list)
/proc/log_mentor(text)
GLOB.mentor_log.Add(text)
GLOB.diary << "\[[time_stamp()]]MENTOR: [text]"
GLOB.world_game_log << "\[[time_stamp()]]MENTOR: [text]"
@@ -104,5 +104,6 @@ GLOBAL_LIST_INIT(maintenance_loot, list(
/obj/item/weapon/storage/secure/briefcase = 3,
/obj/item/weapon/storage/toolbox/artistic = 2,
/obj/item/toy/eightball = 1,
/obj/item/weapon/storage/daki = 3,
"" = 3
))
+33 -27
View File
@@ -1,28 +1,34 @@
GLOBAL_VAR(diary)
GLOBAL_PROTECT(diary)
GLOBAL_VAR(runtime_diary)
GLOBAL_PROTECT(runtime_diary)
GLOBAL_VAR(diaryofmeanpeople)
GLOBAL_PROTECT(diaryofmeanpeople)
GLOBAL_VAR(href_logfile)
GLOBAL_PROTECT(href_logfile)
GLOBAL_LIST_EMPTY(bombers)
GLOBAL_PROTECT(bombers)
GLOBAL_LIST_EMPTY(admin_log)
GLOBAL_PROTECT(admin_log)
GLOBAL_LIST_EMPTY(lastsignalers) //keeps last 100 signals here in format: "[src] used \ref[src] @ location [src.loc]: [freq]/[code]"
GLOBAL_PROTECT(lastsignalers)
GLOBAL_LIST_EMPTY(lawchanges) //Stores who uploaded laws to which silicon-based lifeform, and what the law was
GLOBAL_PROTECT(lawchanges)
GLOBAL_LIST_EMPTY(combatlog)
GLOBAL_PROTECT(combatlog)
GLOBAL_LIST_EMPTY(IClog)
GLOBAL_PROTECT(IClog)
GLOBAL_LIST_EMPTY(OOClog)
GLOBAL_PROTECT(OOClog)
GLOBAL_LIST_EMPTY(adminlog)
GLOBAL_PROTECT(adminlog)
GLOBAL_VAR(log_directory)
GLOBAL_PROTECT(log_directory)
GLOBAL_VAR(world_game_log)
GLOBAL_PROTECT(world_game_log)
GLOBAL_VAR(world_runtime_log)
GLOBAL_PROTECT(world_runtime_log)
GLOBAL_VAR(world_attack_log)
GLOBAL_PROTECT(world_attack_log)
GLOBAL_VAR(world_href_log)
GLOBAL_PROTECT(world_href_log)
GLOBAL_VAR(round_id)
GLOBAL_PROTECT(round_id)
GLOBAL_VAR(config_error_log)
GLOBAL_PROTECT(config_error_log)
GLOBAL_LIST_EMPTY(bombers)
GLOBAL_PROTECT(bombers)
GLOBAL_LIST_EMPTY(admin_log)
GLOBAL_PROTECT(admin_log)
GLOBAL_LIST_EMPTY(lastsignalers) //keeps last 100 signals here in format: "[src] used \ref[src] @ location [src.loc]: [freq]/[code]"
GLOBAL_PROTECT(lastsignalers)
GLOBAL_LIST_EMPTY(lawchanges) //Stores who uploaded laws to which silicon-based lifeform, and what the law was
GLOBAL_PROTECT(lawchanges)
GLOBAL_LIST_EMPTY(combatlog)
GLOBAL_PROTECT(combatlog)
GLOBAL_LIST_EMPTY(IClog)
GLOBAL_PROTECT(IClog)
GLOBAL_LIST_EMPTY(OOClog)
GLOBAL_PROTECT(OOClog)
GLOBAL_LIST_EMPTY(adminlog)
GLOBAL_PROTECT(adminlog)
GLOBAL_LIST_EMPTY(active_turfs_startlist)
+80 -47
View File
@@ -107,64 +107,112 @@
var/obj/item/W = get_active_held_item()
if(W == A)
W.attack_self(src)
update_inv_hands()
return
// operate three levels deep here (item in backpack in src; item in box in backpack in src, not any deeper)
if(A.ClickAccessible(src, depth=INVENTORY_DEPTH))
// No adjacency needed
//These are always reachable.
//User itself, current loc, and user inventory
if(DirectAccess(A))
if(W)
melee_item_attack_chain(src, W, A, params)
melee_item_attack_chain(src,W,A,params)
else
if(ismob(A))
changeNext_move(CLICK_CD_MELEE)
UnarmedAttack(A)
return
if(!isturf(loc)) // This is going to stop you from telekinesing from inside a closet, but I don't shed many tears for that
//Can't reach anything else in lockers or other weirdness
if(!loc.AllowClick())
return
// Allows you to click on a box's contents, if that box is on the ground, but no deeper than that
if(isturf(A) || isturf(A.loc) || (A.loc && isturf(A.loc.loc)))
if(Adjacent(A) || (W && CheckReach(src, A, W.reach))) //Adjacent or reaching attacks
if(W)
melee_item_attack_chain(src, W, A, params)
else
if(ismob(A))
changeNext_move(CLICK_CD_MELEE)
UnarmedAttack(A, 1)
return
else // non-adjacent click
if(W)
W.afterattack(A,src,0,params) // 0: not Adjacent
else
RangedAttack(A, params)
//Standard reach turf to turf or reaching inside storage
if(CanReach(A,W))
if(W)
melee_item_attack_chain(src,W,A,params)
else
if(ismob(A))
changeNext_move(CLICK_CD_MELEE)
UnarmedAttack(A,1)
else
if(W)
W.afterattack(A,src,0,params)
else
RangedAttack(A,params)
/atom/movable/proc/CanReach(atom/target,obj/item/tool,view_only = FALSE)
if(isturf(target) || isturf(target.loc) || DirectAccess(target)) //Directly accessible atoms
if(Adjacent(target) || (tool && CheckToolReach(src, target, tool.reach))) //Adjacent or reaching attacks
return TRUE
else
//Things inside storage insde another storage
//Eg Contents of a box in a backpack
var/atom/outer_storage = get_atom_on_turf(target)
if(outer_storage == target) //whatever that is we don't want infinite loop.
return FALSE
if(outer_storage && CanReach(outer_storage,tool) && outer_storage.CanReachStorage(target,src,view_only ? STORAGE_VIEW_DEPTH : INVENTORY_DEPTH))
return TRUE
return FALSE
//Can [target] in this container be reached by [user], can't be more than [depth] levels deep
/atom/proc/CanReachStorage(atom/target,user,depth)
return FALSE
/obj/item/weapon/storage/CanReachStorage(atom/target,user,depth)
while(target && depth > 0)
target = target.loc
depth--
if(target == src)
return TRUE
return FALSE
/atom/movable/proc/DirectAccess(atom/target)
if(target == src)
return TRUE
if(target == loc)
return TRUE
/mob/DirectAccess(atom/target)
if(..())
return TRUE
if(target in contents) //This could probably use moving down and restricting to inventory only
return TRUE
return FALSE
/mob/living/DirectAccess(atom/target)
if(..()) //Lightweight checks first
return TRUE
if(target in GetAllContents())
return TRUE
/atom/proc/AllowClick()
return FALSE
/turf/AllowClick()
return TRUE
/proc/CheckReach(atom/movable/here, atom/movable/there, reach)
/proc/CheckToolReach(atom/movable/here, atom/movable/there, reach)
if(!here || !there)
return
switch(reach)
if(0)
return here.loc == there.loc
return FALSE
if(1)
return here.Adjacent(there)
return FALSE //here.Adjacent(there)
if(2 to INFINITY)
var/obj/dummy = new(get_turf(here)) //We'll try to move this every tick, failing if we can't
var/obj/dummy = new(get_turf(here))
dummy.pass_flags |= PASSTABLE
dummy.invisibility = INVISIBILITY_ABSTRACT
for(var/i in 1 to reach) //Limit it to that many tries
var/turf/T = get_step(dummy, get_dir(dummy, there))
if(dummy.loc == there.loc)
if(dummy.CanReach(there))
qdel(dummy)
return 1
if(there.density && dummy in range(1, there)) //For windows and suchlike
qdel(dummy)
return 1
return TRUE
if(!dummy.Move(T)) //we're blocked!
qdel(dummy)
return
qdel(dummy)
// Default behavior: ignore double clicks (the second click that makes the doubleclick call already calls for a normal click)
/mob/proc/DblClickOn(atom/A, params)
@@ -304,21 +352,6 @@
/atom/proc/CtrlShiftClick(mob/user)
return
/*
Helper to check can the mob click/access an item.
Used by mob inventory and storage items.
*/
/atom/proc/ClickAccessible(mob/user, depth=1)
if(src == user.loc || (src in user.contents))
return TRUE
if(loc && depth > 1)
return loc.ClickAccessible(user, depth-1)
/turf/ClickAccessible(mob/user, depth=1)
return
/*
Misc helpers
+1
View File
@@ -393,6 +393,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
textlist += "<br>"
else
textlist += "Seconds until Ratvar's arrival: <b>[G.get_arrival_text(TRUE)]</b><br>"
break
if(unconverted_ais_exist)
if(unconverted_ais_exist > 1)
textlist += "<b>[unconverted_ais_exist] unconverted AIs exist!</b><br>"
+18 -25
View File
@@ -43,10 +43,8 @@
var/log_attack = 0 // log attack messages
var/log_adminchat = 0 // log admin chat messages
var/log_pda = 0 // log pda messages
var/log_hrefs = 0 // log all links clicked in-game. Could be used for debugging and tracking down exploits
var/log_twitter = 0 // log certain expliotable parrots and other such fun things in a JSON file of twitter valid phrases.
var/log_world_topic = 0 // log all world.Topic() calls
var/log_runtimes = FALSE // log runtimes into a file
var/sql_enabled = 0 // for sql switching
var/allow_admin_ooccolor = 0 // Allows admins with relevant permissions to have their own ooc colour
var/allow_vote_restart = 0 // allow votes to restart
@@ -129,6 +127,7 @@
var/forbid_peaceborg = 0
var/panic_bunker = 0 // prevents new people it hasn't seen before from connecting
var/notify_new_player_age = 0 // how long do we notify admins of a new player
var/notify_new_player_account_age = 0 // how long do we notify admins of a new byond account
var/irc_first_connection_alert = 0 // do we notify the irc channel when somebody is connecting for the first time?
var/traitor_scaling_coeff = 6 //how much does the amount of players get divided by to determine traitors
@@ -269,7 +268,7 @@
if(M.config_tag)
if(!(M.config_tag in modes)) // ensure each mode is added only once
GLOB.diary << "Adding game mode [M.name] ([M.config_tag]) to configuration."
GLOB.config_error_log << "Adding game mode [M.name] ([M.config_tag]) to configuration."
modes += M.config_tag
mode_names[M.config_tag] = M.name
probabilities[M.config_tag] = M.probability
@@ -358,8 +357,6 @@
log_adminchat = 1
if("log_pda")
log_pda = 1
if("log_hrefs")
log_hrefs = 1
if("log_twitter")
log_twitter = 1
if("log_world_topic")
@@ -476,6 +473,8 @@
panic_bunker = 1
if("notify_new_player_age")
notify_new_player_age = text2num(value)
if("notify_new_player_account_age")
notify_new_player_account_age = text2num(value)
if("irc_first_connection_alert")
irc_first_connection_alert = 1
if("check_randomizer")
@@ -493,12 +492,6 @@
ipintel_save_bad = text2num(value)
if("aggressive_changelog")
aggressive_changelog = 1
if("log_runtimes")
log_runtimes = TRUE
var/newlog = file("data/logs/runtimes/runtime-[time2text(world.realtime, "YYYY-MM-DD")].log")
if(GLOB.runtime_diary != newlog)
world.log << "Now logging runtimes to data/logs/runtimes/runtime-[time2text(world.realtime, "YYYY-MM-DD")].log"
GLOB.runtime_diary = newlog
if("autoconvert_notes")
autoconvert_notes = 1
if("allow_webclient")
@@ -542,7 +535,7 @@
if("error_msg_delay")
error_msg_delay = text2num(value)
else
GLOB.diary << "Unknown setting in configuration: '[name]'"
GLOB.config_error_log << "Unknown setting in configuration: '[name]'"
else if(type == "game_options")
switch(name)
@@ -605,13 +598,13 @@
if(mode_name in modes)
continuous[mode_name] = 1
else
GLOB.diary << "Unknown continuous configuration definition: [mode_name]."
GLOB.config_error_log << "Unknown continuous configuration definition: [mode_name]."
if("midround_antag")
var/mode_name = lowertext(value)
if(mode_name in modes)
midround_antag[mode_name] = 1
else
GLOB.diary << "Unknown midround antagonist configuration definition: [mode_name]."
GLOB.config_error_log << "Unknown midround antagonist configuration definition: [mode_name]."
if("midround_antag_time_check")
midround_antag_time_check = text2num(value)
if("midround_antag_life_check")
@@ -627,9 +620,9 @@
if(mode_name in modes)
min_pop[mode_name] = text2num(mode_value)
else
GLOB.diary << "Unknown minimum population configuration definition: [mode_name]."
GLOB.config_error_log << "Unknown minimum population configuration definition: [mode_name]."
else
GLOB.diary << "Incorrect minimum population configuration definition: [mode_name] [mode_value]."
GLOB.config_error_log << "Incorrect minimum population configuration definition: [mode_name] [mode_value]."
if("max_pop")
var/pop_pos = findtext(value, " ")
var/mode_name = null
@@ -641,9 +634,9 @@
if(mode_name in modes)
max_pop[mode_name] = text2num(mode_value)
else
GLOB.diary << "Unknown maximum population configuration definition: [mode_name]."
GLOB.config_error_log << "Unknown maximum population configuration definition: [mode_name]."
else
GLOB.diary << "Incorrect maximum population configuration definition: [mode_name] [mode_value]."
GLOB.config_error_log << "Incorrect maximum population configuration definition: [mode_name] [mode_value]."
if("shuttle_refuel_delay")
shuttle_refuel_delay = text2num(value)
if("show_game_type_odds")
@@ -671,9 +664,9 @@
if(prob_name in modes)
probabilities[prob_name] = text2num(prob_value)
else
GLOB.diary << "Unknown game mode probability configuration definition: [prob_name]."
GLOB.config_error_log << "Unknown game mode probability configuration definition: [prob_name]."
else
GLOB.diary << "Incorrect probability configuration definition: [prob_name] [prob_value]."
GLOB.config_error_log << "Incorrect probability configuration definition: [prob_name] [prob_value]."
if("protect_roles_from_antagonist")
protect_roles_from_antagonist = 1
@@ -720,7 +713,7 @@
// Value is in the form "LAWID,NUMBER"
var/list/L = splittext(value, ",")
if(L.len != 2)
GLOB.diary << "Invalid LAW_WEIGHT: " + t
GLOB.config_error_log << "Invalid LAW_WEIGHT: " + t
continue
var/lawid = L[1]
var/weight = text2num(L[2])
@@ -776,8 +769,8 @@
mentors_mobname_only = 1
if ("mentor_legacy_system")
mentor_legacy_system = 1
else
GLOB.diary << "Unknown setting in configuration: '[name]'"
// else
// GLOB.config_error_log << "Adding game mode [M.name] ([M.config_tag]) to configuration."
fps = round(fps)
if(fps <= 0)
@@ -831,7 +824,7 @@
maplist[currentmap.map_name] = currentmap
currentmap = null
else
GLOB.diary << "Unknown command in map vote config: '[command]'"
GLOB.config_error_log << "Unknown command in map vote config: '[command]'"
/datum/configuration/proc/loadsql(filename)
@@ -875,7 +868,7 @@
if("feedback_tableprefix")
global.sqlfdbktableprefix = value
else
GLOB.diary << "Unknown setting in configuration: '[name]'"
GLOB.config_error_log << "Unknown setting in configuration: '[name]'"
/datum/configuration/proc/pick_mode(mode_name)
// I wish I didn't have to instance the game modes in order to look up
+6
View File
@@ -52,6 +52,12 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars)
/datum/controller/global_vars/Initialize()
gvars_datum_init_order = list()
gvars_datum_protected_varlist = list("gvars_datum_protected_varlist")
//See https://github.com/tgstation/tgstation/issues/26954
for(var/I in typesof(/datum/controller/global_vars/proc))
var/CLEANBOT_RETURNS = "[I]"
pass(CLEANBOT_RETURNS)
for(var/I in vars - gvars_datum_in_built_vars)
var/start_tick = world.time
call(src, "InitGlobal[I]")()
+13 -8
View File
@@ -280,7 +280,7 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING)
// because sleeps are processed in the order received, so longer sleeps are more likely to run first
if (world.tick_usage > TICK_LIMIT_MC)
sleep_delta += 2
GLOB.CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING - (TICK_LIMIT_RUNNING * 0.5)
GLOB.CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING * 0.5
sleep(world.tick_lag * (processing + sleep_delta))
continue
@@ -421,26 +421,31 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING)
else
tick_precentage = tick_remaining
GLOB.CURRENT_TICKLIMIT = world.tick_usage + tick_precentage
tick_precentage = max(tick_precentage*0.5, tick_precentage-queue_node.tick_overrun)
GLOB.CURRENT_TICKLIMIT = round(world.tick_usage + tick_precentage)
if (!(queue_node_flags & SS_TICKER))
ran_non_ticker = TRUE
ran = TRUE
tick_usage = world.tick_usage
queue_node_paused = (queue_node.state == SS_PAUSED || queue_node.state == SS_PAUSING)
last_type_processed = queue_node
queue_node.state = SS_RUNNING
tick_usage = world.tick_usage
var/state = queue_node.ignite(queue_node_paused)
tick_usage = world.tick_usage - tick_usage
if (state == SS_RUNNING)
state = SS_IDLE
current_tick_budget -= queue_node_priority
tick_usage = world.tick_usage - tick_usage
if (tick_usage < 0)
tick_usage = 0
queue_node.tick_overrun = max(0, MC_AVG_FAST_UP_SLOW_DOWN(queue_node.tick_overrun, tick_usage-tick_precentage))
queue_node.state = state
if (state == SS_PAUSED)
@@ -467,13 +472,13 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING)
queue_node.times_fired++
if (queue_node_flags & SS_TICKER)
queue_node.next_fire = world.time + (world.tick_lag * queue_node.wait)
queue_node.next_fire = world.time + (world.tick_lag * (queue_node.wait + (queue_node.tick_overrun/100)))
else if (queue_node_flags & SS_POST_FIRE_TIMING)
queue_node.next_fire = world.time + queue_node.wait
queue_node.next_fire = world.time + queue_node.wait + (world.tick_lag * (queue_node.tick_overrun/100))
else if (queue_node_flags & SS_KEEP_TIMING)
queue_node.next_fire += queue_node.wait
else
queue_node.next_fire = queue_node.queued_time + queue_node.wait
queue_node.next_fire = queue_node.queued_time + queue_node.wait + (world.tick_lag * (queue_node.tick_overrun/100))
queue_node.queued_time = 0
+2 -1
View File
@@ -17,6 +17,7 @@
var/next_fire = 0 //scheduled world.time for next fire()
var/cost = 0 //average time to execute
var/tick_usage = 0 //average tick usage
var/tick_overrun = 0 //average tick overrun
var/state = SS_IDLE //tracks the current state of the ss, running, paused, etc.
var/paused_ticks = 0 //ticks this ss is taking to run right now.
var/paused_tick_usage //total tick_usage of all of our runs while pausing this run
@@ -168,7 +169,7 @@
if(can_fire && !(SS_NO_FIRE in flags))
msg = "[round(cost,1)]ms|[round(tick_usage,1)]%|[round(ticks,0.1)]\t[msg]"
msg = "[round(cost,1)]ms|[round(tick_usage,1)]%([round(tick_overrun,1)]%)|[round(ticks,0.1)]\t[msg]"
else
msg = "OFFLINE\t[msg]"
+2 -13
View File
@@ -42,6 +42,7 @@ SUBSYSTEM_DEF(blackbox)
msg_cargo = SSblackbox.msg_cargo
msg_other = SSblackbox.msg_other
feedback = SSblackbox.feedback
//no touchie
@@ -84,25 +85,13 @@ SUBSYSTEM_DEF(blackbox)
if (!SSdbcore.Connect())
return
var/round_id
var/datum/DBQuery/query_feedback_max_id = SSdbcore.NewQuery("SELECT MAX(round_id) AS round_id FROM [format_table_name("feedback")]")
if(!query_feedback_max_id.Execute())
return
while (query_feedback_max_id.NextRow())
round_id = query_feedback_max_id.item[1]
if (!isnum(round_id))
round_id = text2num(round_id)
round_id++
var/sqlrowlist = ""
for (var/datum/feedback_variable/FV in feedback)
if (sqlrowlist != "")
sqlrowlist += ", " //a comma (,) at the start of the first row to insert will trigger a SQL error
sqlrowlist += "(null, Now(), [round_id], \"[sanitizeSQL(FV.get_variable())]\", [FV.get_value()], \"[sanitizeSQL(FV.get_details())]\")"
sqlrowlist += "(null, Now(), [GLOB.round_id], \"[sanitizeSQL(FV.get_variable())]\", [FV.get_value()], \"[sanitizeSQL(FV.get_details())]\")"
if (sqlrowlist == "")
return
+15 -5
View File
@@ -287,6 +287,8 @@ SUBSYSTEM_DEF(job)
if(PopcapReached())
RejectPlayer(player)
var/datum/job/validjob
// Loop through all jobs
for(var/datum/job/job in shuffledoccupations) // SHUFFLE ME BABY
if(!job)
@@ -308,16 +310,24 @@ SUBSYSTEM_DEF(job)
Debug("DO non-human failed, Player: [player], Job:[job.title]")
continue
// If the player wants that job on this level, then try give it to him.
if(player.client.prefs.GetJobDepartment(job, level) & job.flag)
// If the job isn't filled
if((job.current_positions < job.spawn_positions) || job.spawn_positions == -1)
Debug("DO pass, Player: [player], Level:[level], Job:[job.title]")
AssignRole(player, job.title)
unassigned -= player
break
validjob = job
//Is the Job empty? Stop Looking Then!
if (!job.current_positions)
break
//Assign us the last job we found
if (validjob)
Debug("DO pass, Player: [player], Level:[level], Job:[validjob.title]")
AssignRole(player, validjob.title)
unassigned -= player
break
// Hand out random jobs to the people who didn't get any in the last check
// Also makes sure that they got their preference correct
+2 -10
View File
@@ -36,18 +36,10 @@ SUBSYSTEM_DEF(lighting)
for (i in 1 to GLOB.lighting_update_lights.len)
var/datum/light_source/L = GLOB.lighting_update_lights[i]
if (L.check() || QDELETED(L) || L.force_update)
L.remove_lum()
if (!QDELETED(L))
L.apply_lum()
L.update_corners()
else if (L.vis_update) //We smartly update only tiles that became (in) visible to use.
L.smart_vis_update()
L.needs_update = LIGHTING_NO_UPDATE
L.vis_update = FALSE
L.force_update = FALSE
L.needs_update = FALSE
if(init_tick_checks)
CHECK_TICK
else if (MC_TICK_CHECK)
+1 -1
View File
@@ -150,7 +150,7 @@ SUBSYSTEM_DEF(pai)
if(!(ROLE_PAI in G.client.prefs.be_special))
continue
//G << 'sound/misc/server-ready.ogg' //Alerting them to their consideration
to_chat(G, "<span class='ghostalert'>Someone is requesting a pAI personality! Use the pAI button to submit yourself as one.</span>")
to_chat(G, "<span class='ghostalert'>[user] is requesting a pAI personality! Use the pAI button to submit yourself as one.</span>")
addtimer(CALLBACK(src, .proc/spam_again), spam_delay)
var/list/available = list()
for(var/datum/paiCandidate/c in SSpai.candidates)
+11 -8
View File
@@ -9,7 +9,6 @@ SUBSYSTEM_DEF(persistence)
var/list/obj/structure/chisel_message/chisel_messages = list()
var/list/saved_messages = list()
var/savefile/chisel_messages_sav
var/savefile/trophy_sav
var/list/saved_trophies = list()
@@ -75,14 +74,14 @@ SUBSYSTEM_DEF(persistence)
break //Who's been duping the bird?!
/datum/controller/subsystem/persistence/proc/LoadChiselMessages()
chisel_messages_sav = new /savefile("data/npc_saves/ChiselMessages.sav")
var/savefile/chisel_messages_sav = new /savefile("data/npc_saves/ChiselMessages.sav")
var/saved_json
chisel_messages_sav[SSmapping.config.map_name] >> saved_json
if(!saved_json)
return
var/saved_messages = json_decode(saved_json)
var/list/saved_messages = json_decode(saved_json)
for(var/item in saved_messages)
if(!islist(item))
@@ -104,10 +103,10 @@ SUBSYSTEM_DEF(persistence)
var/obj/structure/chisel_message/M = new(T)
M.unpack(item)
if(!M.loc)
M.persists = FALSE
qdel(M)
if(!QDELETED(M))
M.unpack(item)
log_world("Loaded [saved_messages.len] engraved messages on map [SSmapping.config.map_name]")
/datum/controller/subsystem/persistence/proc/LoadTrophies()
trophy_sav = new /savefile("data/npc_saves/TrophyItems.sav")
@@ -175,9 +174,13 @@ SUBSYSTEM_DEF(persistence)
secret_satchels[SSmapping.config.map_name] << old_secret_satchels
/datum/controller/subsystem/persistence/proc/CollectChiselMessages()
var/savefile/chisel_messages_sav = new /savefile("data/npc_saves/ChiselMessages.sav")
for(var/obj/structure/chisel_message/M in chisel_messages)
saved_messages += list(M.pack())
log_world("Saved [saved_messages.len] engraved messages on map [SSmapping.config.map_name]")
chisel_messages_sav[SSmapping.config.map_name] << json_encode(saved_messages)
/datum/controller/subsystem/persistence/proc/SaveChiselMessage(obj/structure/chisel_message/M)
@@ -193,4 +196,4 @@ SUBSYSTEM_DEF(persistence)
data["path"] = T.showpiece.type
data["message"] = T.trophy_message
data["placer_key"] = T.placer_key
saved_trophies += list(data)
saved_trophies += list(data)
+4 -2
View File
@@ -75,10 +75,12 @@
if(GLOB.revdata.parentcommit)
to_chat(src, "<b>Server revision compiled on:</b> [GLOB.revdata.date]")
var/prefix = ""
if(GLOB.revdata.testmerge.len)
to_chat(src, GLOB.revdata.GetTestMergeInfo())
to_chat(src, "Based off master commit:")
to_chat(src, "<a href='[config.githuburl]/commit/[GLOB.revdata.parentcommit]'>[GLOB.revdata.parentcommit]</a>")
prefix = "Based off master commit: "
var/pc = GLOB.revdata.parentcommit
to_chat(src, "[prefix]<a href='[config.githuburl]/commit/[pc]'>[copytext(pc, 1, min(length(pc), 7))]</a>")
else
to_chat(src, "Revision unknown")
to_chat(src, "<b>Current Infomational Settings:</b>")
+4 -4
View File
@@ -35,6 +35,7 @@
if(!dialed_holopads.len)
calling_pad.say("Connection failure.")
qdel(src)
return
testing("Holocall started")
@@ -104,19 +105,18 @@
if(connected_holopad)
CRASH("Multi-connection holocall")
connected_holopad = H
for(var/I in dialed_holopads)
if(I == H)
continue
var/obj/machinery/holopad/Holo = I
LAZYREMOVE(Holo.holo_calls, src)
dialed_holopads -= Holo
Disconnect(I)
for(var/I in H.holo_calls)
var/datum/holocall/HC = I
if(HC != src)
HC.Disconnect(H)
connected_holopad = H
if(!Check())
return
+1 -1
View File
@@ -272,7 +272,7 @@
creator.faction |= current.faction
if(creator.mind.special_role)
message_admins("[key_name_admin(current)](<A HREF='?_src_=holder;adminmoreinfo=\ref[current]'>?</A>) has been created by [key_name_admin(creator)](<A HREF='?_src_=holder;adminmoreinfo=\ref[creator]'>?</A>), an antagonist.")
message_admins("[ADMIN_LOOKUPFLW(current)] has been created by [ADMIN_LOOKUPFLW(creator)], an antagonist.")
to_chat(current, "<span class='userdanger'>Despite your creators current allegiances, your true master remains [creator.real_name]. If their loyalities change, so do yours. This will never change unless your creator's body is destroyed.</span>")
/datum/mind/proc/show_memory(mob/recipient, window=1)
+86
View File
@@ -76,3 +76,89 @@
/datum/status_effect/belligerent/on_remove()
if(owner.m_intent == MOVE_INTENT_WALK)
owner.toggle_move_intent()
/datum/status_effect/maniamotor
id = "maniamotor"
duration = -1
tick_interval = 10
status_type = STATUS_EFFECT_MULTIPLE
alert_type = null
var/obj/structure/destructible/clockwork/powered/mania_motor/motor
var/severity = 0 //goes up to a maximum of MAX_MANIA_SEVERITY
var/warned_turnoff = FALSE //if we've warned that the motor is off
var/warned_outofsight = FALSE //if we've warned that the target is out of sight of the motor
var/static/list/mania_messages = list("Go nuts.", "Take a crack at crazy.", "Make a bid for insanity.", "Get kooky.", "Move towards mania.", "Become bewildered.", "Wax wild.", \
"Go round the bend.", "Land in lunacy.", "Try dementia.", "Strive to get a screw loose.", "Advance forward.", "Approach the transmitter.", "Touch the antennae.", \
"Move towards the mania motor.", "Come closer.", "Get over here already!", "Keep your eyes on the motor.")
var/static/list/flee_messages = list("Oh, NOW you flee.", "Get back here!", "If you were smarter, you'd come back.", "Only fools run.", "You'll be back.")
var/static/list/turnoff_messages = list("Why would they turn it-", "What are these idi-", "Fools, fools, all of-", "Are they trying to c-", "All this effort just f-")
var/static/list/powerloss_messages = list("\"Oh, the id**ts di***t s***e en**** pow**...\"", "\"D*dn't **ey mak* an **te***c*i*n le**?\"", "\"The** f**ls for**t t* make a ***** *f-\"", \
"\"No, *O, you **re so cl***-\"", "You hear a yell of frustration, cut off by static.")
/datum/status_effect/maniamotor/Destroy()
motor = null
return ..()
/datum/status_effect/maniamotor/tick()
var/is_servant = is_servant_of_ratvar(owner)
var/span_part = severity > 50 ? "" : "_small" //let's save like one check
if(QDELETED(motor))
if(!is_servant)
to_chat(owner, "<span class='sevtug[span_part]'>You feel a frustrated voice quietly fade from your mind...</span>")
qdel(src)
return
if(!motor.active) //it being off makes it fall off much faster
if(!is_servant && !warned_turnoff)
if(motor.total_accessable_power() > motor.mania_cost)
to_chat(owner, "<span class='sevtug[span_part]'>\"[text2ratvar(pick(turnoff_messages))]\"</span>")
else
to_chat(owner, "<span class='sevtug[span_part]'>[text2ratvar(pick(powerloss_messages))]</span>")
warned_turnoff = TRUE
severity = max(severity - 2, 0)
if(!severity)
qdel(src)
return
else
if(prob(severity * 2))
warned_turnoff = FALSE
if(!(owner in viewers(7, motor))) //not being in range makes it fall off slightly faster
if(!is_servant && !warned_outofsight)
to_chat(owner, "<span class='sevtug[span_part]'>\"[text2ratvar(pick(flee_messages))]\"</span>")
warned_outofsight = TRUE
severity = max(severity - 1, 0)
if(!severity)
qdel(src)
return
else if(prob(severity * 2))
warned_outofsight = FALSE
if(is_servant) //heals servants of braindamage, hallucination, druggy, dizziness, and confusion
if(owner.hallucination)
owner.hallucination = 0
if(owner.druggy)
owner.adjust_drugginess(-owner.druggy)
if(owner.dizziness)
owner.dizziness = 0
if(owner.confused)
owner.confused = 0
severity = 0
else if(!owner.null_rod_check() && owner.stat != DEAD && severity)
var/static/hum = get_sfx('sound/effects/screech.ogg') //same sound for every proc call
if(owner.getToxLoss() > MANIA_DAMAGE_TO_CONVERT)
if(is_eligible_servant(owner))
to_chat(owner, "<span class='sevtug[span_part]'>\"[text2ratvar("You are mine and his, now.")]\"</span>")
add_servant_of_ratvar(owner)
owner.Paralyse(5)
else
if(prob(severity * 0.15))
to_chat(owner, "<span class='sevtug[span_part]'>\"[text2ratvar(pick(mania_messages))]\"</span>")
owner.playsound_local(get_turf(motor), hum, severity, 1)
owner.adjust_drugginess(Clamp(max(severity * 0.075, 1), 0, max(0, 50 - owner.druggy))) //7.5% of severity per second, minimum 1
if(owner.hallucination < 50)
owner.hallucination = min(owner.hallucination + max(severity * 0.075, 1), 50) //7.5% of severity per second, minimum 1
if(owner.dizziness < 50)
owner.dizziness = min(owner.dizziness + round(severity * 0.05, 1), 50) //5% of severity per second above 10 severity
if(owner.confused < 25)
owner.confused = min(owner.confused + round(severity * 0.025, 1), 25) //2.5% of severity per second above 20 severity
owner.adjustToxLoss(severity * 0.02, TRUE, TRUE) //2% of severity per second
severity--
+75
View File
@@ -0,0 +1,75 @@
diff a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm (rejected hunks)
@@ -108,20 +108,6 @@
to_chat(owner, "<span class='sevtug[span_part]'>You feel a frustrated voice quietly fade from your mind...</span>")
qdel(src)
return
- if(!(owner in viewers(7, motor))) //not being in range makes it fall off much faster
- if(!is_servant && !warned_outofsight)
- to_chat(owner, "<span class='sevtug[span_part]'>\"[text2ratvar(pick(flee_messages))]\"</span>")
- warned_outofsight = TRUE
- if(severity)
- severity--
- if(!severity)
- qdel(src)
- return
- else
- qdel(src)
- return
- else if(prob(severity * 2))
- warned_outofsight = FALSE
if(!motor.active) //it being off makes it fall off much faster
if(!is_servant && !warned_turnoff)
if(motor.total_accessable_power() > motor.mania_cost)
@@ -129,20 +115,24 @@
else
to_chat(owner, "<span class='sevtug[span_part]'>[text2ratvar(pick(powerloss_messages))]</span>")
warned_turnoff = TRUE
- if(severity)
- severity--
+ severity = max(severity - 2, 0)
+ if(!severity)
+ qdel(src)
+ return
+ else
+ if(prob(severity * 2))
+ warned_turnoff = FALSE
+ if(!(owner in viewers(7, motor))) //not being in range makes it fall off slightly faster
+ if(!is_servant && !warned_outofsight)
+ to_chat(owner, "<span class='sevtug[span_part]'>\"[text2ratvar(pick(flee_messages))]\"</span>")
+ warned_outofsight = TRUE
+ severity = max(severity - 1, 0)
if(!severity)
qdel(src)
return
- else
- qdel(src)
- return
- else if(prob(severity * 2))
- warned_turnoff = FALSE
+ else if(prob(severity * 2))
+ warned_outofsight = FALSE
if(is_servant) //heals servants of braindamage, hallucination, druggy, dizziness, and confusion
- var/brainloss = owner.getBrainLoss()
- if(brainloss)
- owner.adjustBrainLoss(-brainloss)
if(owner.hallucination)
owner.hallucination = 0
if(owner.druggy)
@@ -163,14 +153,12 @@
if(prob(severity * 0.15))
to_chat(owner, "<span class='sevtug[span_part]'>\"[text2ratvar(pick(mania_messages))]\"</span>")
owner.playsound_local(get_turf(motor), hum, severity, 1)
- if(owner.getBrainLoss() <= 50)
- owner.adjustBrainLoss(severity * 0.025) //2.5% of severity per second
owner.adjust_drugginess(Clamp(max(severity * 0.075, 1), 0, max(0, 50 - owner.druggy))) //7.5% of severity per second, minimum 1
if(owner.hallucination < 50)
owner.hallucination = min(owner.hallucination + max(severity * 0.075, 1), 50) //7.5% of severity per second, minimum 1
- if(owner.dizziness < 25)
- owner.dizziness = min(owner.dizziness + Floor(severity * 0.025), 25) //2.5% of severity per second above 20 severity
+ if(owner.dizziness < 50)
+ owner.dizziness = min(owner.dizziness + round(severity * 0.05, 1), 50) //5% of severity per second above 10 severity
if(owner.confused < 25)
- owner.confused = min(owner.confused + Floor(severity * 0.025), 25) //2.5% of severity per second above 20 severity
+ owner.confused = min(owner.confused + round(severity * 0.025, 1), 25) //2.5% of severity per second above 20 severity
owner.adjustToxLoss(severity * 0.02, TRUE, TRUE) //2% of severity per second
severity--
@@ -106,3 +106,11 @@
for(var/datum/status_effect/S in status_effects)
if(initial(S1.id) == S.id)
return S
/mob/living/proc/has_status_effect_list(effect) //returns a list of effects with matching IDs that the mod owns; use for effects there can be multiple of
. = list()
if(status_effects)
var/datum/status_effect/S1 = effect
for(var/datum/status_effect/S in status_effects)
if(initial(S1.id) == S.id)
. += S
+1
View File
@@ -274,6 +274,7 @@
return
/atom/proc/ex_act(severity, target)
set waitfor = FALSE
contents_explosion(severity, target)
/atom/proc/blob_act(obj/structure/blob/B)
@@ -22,6 +22,12 @@
else
for(var/i in GLOB.clockwork_component_cache)
.[i] = max(MAX_COMPONENTS_BEFORE_RAND - LOWER_PROB_PER_COMPONENT*GLOB.clockwork_component_cache[i], 1)
for(var/obj/structure/destructible/clockwork/massive/celestial_gateway/G in GLOB.all_clockwork_objects)
if(G.still_needs_components())
for(var/i in G.required_components)
if(!G.required_components[i])
. -= i
break
. = pickweight(.)
//returns a component name from a component id
@@ -37,6 +43,8 @@
return "Replicant Alloy"
if(HIEROPHANT_ANSIBLE)
return "Hierophant Ansible"
else
return null
//returns a component acronym from a component id
/proc/get_component_acronym(id)
@@ -51,6 +59,8 @@
return "RA"
if(HIEROPHANT_ANSIBLE)
return "HA"
else
return null
//returns a component id from a component name
/proc/get_component_id(name)
@@ -65,6 +75,8 @@
return REPLICANT_ALLOY
if("Hierophant Ansible")
return HIEROPHANT_ANSIBLE
else
return null
//returns a component spanclass from a component id
/proc/get_component_span(id)
@@ -121,6 +133,8 @@
return /obj/effect/overlay/temp/ratvar/component/alloy
if(HIEROPHANT_ANSIBLE)
return /obj/effect/overlay/temp/ratvar/component/ansible
else
return null
//returns a type for a component from a component id
/proc/get_component_type(id)
@@ -134,4 +148,6 @@
if(REPLICANT_ALLOY)
return /obj/item/clockwork/component/replicant_alloy
if(HIEROPHANT_ANSIBLE)
return /obj/item/clockwork/component/hierophant_ansible
return /obj/item/clockwork/component/hierophant_ansible
else
return null
@@ -218,22 +218,22 @@
/datum/clockwork_scripture/create_object/mania_motor
descname = "Powered Structure, Area Denial"
name = "Mania Motor"
desc = "Creates a mania motor which will cause brain damage and hallucinations in nearby non-Servant humans. It will also try to convert humans directly adjecent to the motor."
desc = "Creates a mania motor which causes minor damage and a variety of negative mental effects in nearby non-Servant humans, potentially up to and including conversion."
invocations = list("May this transmitter...", "...break the will of all who oppose us!")
channel_time = 80
consumed_components = list(GEIS_CAPACITOR = 5, REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 2)
object_path = /obj/structure/destructible/clockwork/powered/mania_motor
creator_message = "<span class='brass'>You form a mania motor which will cause brain damage and hallucinations in nearby humans while active.</span>"
creator_message = "<span class='brass'>You form a mania motor, which causes minor damage and negative mental effects in non-Servants.</span>"
observer_message = "<span class='warning'>A two-pronged machine rises from the ground!</span>"
invokers_required = 2
multiple_invokers_used = TRUE
usage_tip = "Eligible non-Servant humans next to the motor will be converted at an additional power cost. It will also cure hallucinations and brain damage in nearby Servants."
usage_tip = "It will also cure hallucinations and brain damage in nearby Servants."
tier = SCRIPTURE_APPLICATION
one_per_tile = TRUE
primary_component = GEIS_CAPACITOR
sort_priority = 8
quickbind = TRUE
quickbind_desc = "Creates a Mania Motor, which can convert adjacent non-Servants with power."
quickbind_desc = "Creates a Mania Motor, which causes minor damage and negative mental effects in non-Servants."
//Tinkerer's Daemon: Creates an efficient machine that rapidly produces components at a power cost.
@@ -1,8 +1,8 @@
//Mania Motor: A pair of antenna that, while active, cause braindamage and hallucinations in nearby human mobs.
//Mania Motor: A pair of antenna that, while active, cause a variety of negative mental effects in nearby human mobs.
/obj/structure/destructible/clockwork/powered/mania_motor
name = "mania motor"
desc = "A pair of antenna with what appear to be sockets around the base. It reminds you of an antlion."
clockwork_desc = "A transmitter that allows Sevtug to whisper into the minds of nearby non-servants, causing hallucinations and brain damage as long as it remains powered."
clockwork_desc = "A transmitter that allows Sevtug to whisper into the minds of nearby non-servants, causing a variety of negative mental effects, up to and including conversion."
icon_state = "mania_motor_inactive"
active_icon = "mania_motor"
inactive_icon = "mania_motor_inactive"
@@ -16,22 +16,11 @@
/obj/item/clockwork/alloy_shards/small = 2, \
/obj/item/clockwork/component/geis_capacitor/antennae = 1)
var/mania_cost = 150
var/convert_cost = 150
var/static/list/mania_messages = list("Go nuts.", "Take a crack at crazy.", "Make a bid for insanity.", "Get kooky.", "Move towards mania.", "Become bewildered.", "Wax wild.", \
"Go round the bend.", "Land in lunacy.", "Try dementia.", "Strive to get a screw loose.")
var/static/list/compel_messages = list("Come closer.", "Approach the transmitter.", "Touch the antennae.", "I always have to deal with idiots. Move towards the mania motor.", \
"Advance forward and place your head between the antennae - that's all it's good for.", "If you were smarter, you'd be over here already.", "Move FORWARD, you fool.")
var/static/list/convert_messages = list("You won't do. Go to sleep while I tell these nitwits how to convert you.", "You are insufficient. I must instruct these idiots in the art of conversion.", \
"Oh of course, someone we can't convert. These servants are fools.", "How hard is it to use a Sigil, anyway? All it takes is dragging someone onto it.", \
"How do they fail to use a Sigil of Accession, anyway?", "Why is it that all servants are this inept?", "It's quite likely you'll be stuck here for a while.")
var/static/list/close_messages = list("Well, you can't reach the motor from THERE, you moron.", "Interesting location. I'd prefer if you went somewhere you could ACTUALLY TOUCH THE ANTENNAE!", \
"Amazing. You somehow managed to wedge yourself somewhere you can't actually reach the motor from.", "Such a show of idiocy is unparalleled. Perhaps I should put you on display?", \
"Did you do this on purpose? I can't imagine you doing so accidentally. Oh, wait, I can.", "How is it that such smart creatures can still do something AS STUPID AS THIS!")
/obj/structure/destructible/clockwork/powered/mania_motor/examine(mob/user)
..()
if(is_servant_of_ratvar(user) || isobserver(user))
to_chat(user, "<span class='sevtug_small'>It requires <b>[mania_cost]W</b> to run, and at least <b>[convert_cost]W</b> to attempt to convert humans adjacent to it.</span>")
to_chat(user, "<span class='sevtug_small'>It requires <b>[mania_cost]W</b> to run.</span>")
/obj/structure/destructible/clockwork/powered/mania_motor/forced_disable(bad_effects)
if(active)
@@ -60,82 +49,17 @@
if(!try_use_power(mania_cost))
forced_disable(FALSE)
return
var/turf/T = get_turf(src)
var/hum = get_sfx('sound/effects/screech.ogg') //like playsound, same sound for everyone affected
var/efficiency = get_efficiency_mod()
for(var/mob/living/carbon/human/H in viewers(7, src))
if(is_servant_of_ratvar(H)) //heals servants of braindamage, hallucination, druggy, dizziness, and confusion
var/brainloss = H.getBrainLoss()
if(brainloss)
H.adjustBrainLoss(-brainloss)
if(H.hallucination)
H.hallucination = 0
if(H.druggy)
H.adjust_drugginess(-H.druggy)
if(H.dizziness)
H.dizziness = 0
if(H.confused)
H.confused = 0
else if(!H.null_rod_check() && H.stat != DEAD)
var/distance = 0 + get_dist(T, get_turf(H))
var/falloff_distance = min((110) - distance * 10, 80)
var/sound_distance = falloff_distance * 0.5
var/targetbrainloss = H.getBrainLoss()
if(distance > 3 && prob(falloff_distance * 0.5))
to_chat(H, "<span class='sevtug_small'>\"[text2ratvar(pick(mania_messages))]\"</span>")
if(distance <= 1)
if(!H.Adjacent(src))
to_chat(H, "<span class='sevtug'>\"[text2ratvar(pick(close_messages))]\"</span>")
H.playsound_local(T, hum, sound_distance, 1)
else if(!try_use_power(convert_cost))
visible_message("<span class='warning'>[src]'s antennae fizzle quietly.</span>")
playsound(src, 'sound/effects/light_flicker.ogg', 50, 1)
else
H.playsound_local(T, hum, 80, 1)
if(!H.stat)
if(H.getBrainLoss() < 100)
H.adjustBrainLoss(20 * efficiency)
H.visible_message("<span class='warning'>[H] reaches out and touches [src].</span>", "<span class='sevtug'>You touch [src] involuntarily.</span>")
else
H.Paralyse(3)
else if(is_eligible_servant(H))
to_chat(H, "<span class='sevtug'>\"[text2ratvar("You are mine and his, now.")]\"</span>")
add_servant_of_ratvar(H)
H.Paralyse(5)
else
H.playsound_local(T, hum, sound_distance, 1)
switch(distance)
if(0 to 3)
if(prob(falloff_distance * 0.5))
if(prob(falloff_distance))
to_chat(H, "<span class='sevtug_small'>\"[text2ratvar(pick(mania_messages))]\"</span>")
else
to_chat(H, "<span class='sevtug'>\"[text2ratvar(pick(compel_messages))]\"</span>")
if(targetbrainloss <= 40)
H.adjustBrainLoss(3 * efficiency)
H.adjust_drugginess(Clamp(7 * efficiency, 0, 50 - H.druggy))
H.hallucination = min(H.hallucination + (7 * efficiency), 50)
H.dizziness = min(H.dizziness + (3 * efficiency), 20)
H.confused = min(H.confused + (3 * efficiency), 20)
if(3 to 5)
if(targetbrainloss <= 20)
H.adjustBrainLoss(2 * efficiency)
H.adjust_drugginess(Clamp(5 * efficiency, 0, 25 - H.druggy))
H.hallucination = min(H.hallucination + (5 * efficiency), 25)
H.dizziness = min(H.dizziness + (2 * efficiency), 10)
H.confused = min(H.confused + (2 * efficiency), 10)
if(5 to 6)
if(targetbrainloss <= 10)
H.adjustBrainLoss(1 * efficiency)
H.adjust_drugginess(Clamp(2 * efficiency, 0, 20 - H.druggy))
H.hallucination = min(H.hallucination + (2 * efficiency), 20)
H.dizziness = min(H.dizziness + (2 * efficiency), 5)
H.confused = min(H.confused + (2 * efficiency), 5)
if(6 to 7)
if(targetbrainloss <= 5)
H.adjustBrainLoss(1 * efficiency)
H.adjust_drugginess(Clamp(2 * efficiency, 0, 10 - H.druggy))
H.hallucination = min(H.hallucination + (2 * efficiency), 10)
if(7 to INFINITY)
H.adjust_drugginess(Clamp(2 * efficiency, 0, 5 - H.druggy))
H.hallucination = min(H.hallucination + (2 * efficiency), 5)
if(is_servant_of_ratvar(H))
continue
var/list/effects = H.has_status_effect_list(STATUS_EFFECT_MANIAMOTOR)
var/datum/status_effect/maniamotor/M
for(var/datum/status_effect/maniamotor/MM in effects)
if(MM.motor == src)
M = MM
break
if(!M)
M = H.apply_status_effect(STATUS_EFFECT_MANIAMOTOR)
M.motor = src
M.severity = Clamp(M.severity + ((11 - get_dist(src, H)) * efficiency * efficiency), 0, MAX_MANIA_SEVERITY)
+3 -3
View File
@@ -148,8 +148,7 @@ structure_check() searches for nearby cultist structures required for the invoca
/obj/effect/rune/proc/fail_invoke()
//This proc contains the effects of a rune if it is not invoked correctly, through either invalid wording or not enough cultists. By default, it's just a basic fizzle.
visible_message("<span class='warning'>The markings pulse with a \
small flash of red light, then fall dark.</span>")
visible_message("<span class='warning'>The markings pulse with a small flash of red light, then fall dark.</span>")
var/oldcolor = color
color = rgb(255, 0, 0)
animate(src, color = oldcolor, time = 5)
@@ -309,10 +308,11 @@ structure_check() searches for nearby cultist structures required for the invoca
A.forceMove(target)
if(movedsomething)
..()
visible_message("<span class='warning'>There is a sharp crack of inrushing air, and everything above the rune disappears!</span>")
visible_message("<span class='warning'>There is a sharp crack of inrushing air, and everything above the rune disappears!</span>", null, "<i>You hear a sharp crack.</i>")
to_chat(user, "<span class='cult'>You[moveuserlater ? "r vision blurs, and you suddenly appear somewhere else":" send everything above the rune away"].</span>")
if(moveuserlater)
user.forceMove(target)
target.visible_message("<span class='warning'>There is a boom of outrushing air as something appears above the rune!</span>", null, "<i>You hear a boom.</i>")
else
fail_invoke()
+3 -2
View File
@@ -147,9 +147,10 @@
if(is_blocked_turf(target, TRUE))
to_chat(user, "<span class='warning'>The target rune is blocked. Attempting to teleport to it would be massively unwise.</span>")
return ..(user, 0)
user.visible_message("<span class='warning'>Dust flows from [user]'s hand, and [user.p_they()] disappear in a flash of red light!</span>", \
"<span class='cultitalic'>You speak the words of the talisman and find yourself somewhere else!</span>")
user.visible_message("<span class='warning'>Dust flows from [user]'s hand, and [user.p_they()] disappear with a sharp crack!</span>", \
"<span class='cultitalic'>You speak the words of the talisman and find yourself somewhere else!</span>", "<i>You hear a sharp crack.</i>")
user.forceMove(target)
target.visible_message("<span class='warning'>There is a boom of outrushing air as something appears above the rune!</span>", null, "<i>You hear a boom.</i>")
return ..()
-1
View File
@@ -85,7 +85,6 @@
SSblackbox.set_details("game_mode","[SSticker.mode]")
if(GLOB.revdata.commit)
SSblackbox.set_details("revision","[GLOB.revdata.commit]")
SSblackbox.set_details("server_ip","[world.internet_address]:[world.port]")
if(report)
addtimer(CALLBACK(src, .proc/send_intercept, 0), rand(waittime_l, waittime_h))
generate_station_goals()
+23
View File
@@ -1,3 +1,5 @@
#define DOM_BLOCKED_SPAM_CAP 6
/obj/machinery/dominator
name = "dominator"
desc = "A visibly sinister device. Looks like you can break it if you hit it enough."
@@ -13,9 +15,20 @@
var/datum/gang/gang
var/operating = 0 //0=standby or broken, 1=takeover
var/warned = 0 //if this device has set off the warning at <3 minutes yet
var/spam_prevention = DOM_BLOCKED_SPAM_CAP //first message is immediate
var/datum/effect_system/spark_spread/spark_system
var/obj/effect/countdown/dominator/countdown
/proc/dominator_excessive_walls(atom/A)
var/open = 0
for(var/turf/T in circleviewturfs(center=A,radius=3))
if(!istype(T, /turf/closed))
open++
if(open < 40)
return TRUE
else
return FALSE
/obj/machinery/dominator/tesla_act()
qdel(src)
@@ -48,6 +61,16 @@
if(gang && gang.is_dominating)
var/time_remaining = gang.domination_time_remaining()
if(time_remaining > 0)
if(dominator_excessive_walls(src))
gang.domination_timer += 2
playsound(loc, 'sound/machines/buzz-two.ogg', 50, 0)
if(spam_prevention < DOM_BLOCKED_SPAM_CAP)
spam_prevention++
else
gang.message_gangtools("Warning: There are too many walls around your gang's dominator, its signal is being blocked!")
say("Error: Takeover signal is currently blocked! There are too many walls within 3 standard units of this device.")
spam_prevention = 0
return
. = TRUE
playsound(loc, 'sound/items/timer.ogg', 10, 0)
if(!warned && (time_remaining < 180))
+4 -2
View File
@@ -312,7 +312,9 @@ GLOBAL_LIST_INIT(gang_colors_pool, list("red","orange","yellow","green","blue","
G.domination(0.5)
priority_announce("Multiple station takeover attempts have made simultaneously. Conflicting takeover attempts appears to have restarted.","Network Alert")
else
var/datum/gang/G = winners[1]
G.is_dominating = FALSE
SSticker.mode.explosion_in_progress = 1
SSticker.station_explosion_cinematic(1)
SSticker.station_explosion_cinematic(1,"gang war", null)
SSticker.mode.explosion_in_progress = 0
SSticker.force_ending = pick(winners)
SSticker.force_ending = TRUE
+5 -1
View File
@@ -305,7 +305,11 @@
if(obj.density)
to_chat(user, "<span class='warning'>There's not enough room here!</span>")
return FALSE
if(dominator_excessive_walls(user))
to_chat(user, "span class='warning'>The <b>dominator</b> will not function here! The <b>dominator</b> requires an open space within three standard units so that walls do not interfere with the signal.</span>")
return FALSE
if(!(usrarea.type in gang.territory|gang.territory_new))
to_chat(user, "<span class='warning'>The <b>dominator</b> can be spawned only on territory controlled by your gang!</span>")
return FALSE
@@ -20,7 +20,7 @@
explanation_text = "Your brain is broken... you can only communicate in"
/datum/objective/abductee/speech/New()
var/style = pick(list("pantomime", "rhyme", "haiku", "extended metaphors", "riddles", "extremely literal terms", "sound effects", "military jargon"))
var/style = pick(list("pantomime", "rhyme", "haiku", "extended metaphors", "riddles", "extremely literal terms", "sound effects", "military jargon", "three word sentences"))
explanation_text+= " [style]."
/datum/objective/abductee/capture
@@ -146,3 +146,25 @@
/datum/objective/abductee/sixthsense
explanation_text = "You died back there and went to heaven... or is it hell? No one here seems to know they're dead. Convince them, and maybe you can escape this limbo."
/datum/objective/abductee/toupefallacy
explanation_text = "There are alien parasites masquerading as people's hair. Save people from this invasion."
/datum/objective/abductee/everyoneisthesame
explanation_text = "There is only one other person in existence, he is just really good at pretending to be multiple people."
/datum/objective/abductee/forbiddennumber
explanation_text = "Numbers, how do they work?" //Shouldn't ever see this.
/datum/objective/abductee/forbiddennumber/New()
var/number = rand(2,10)
explanation_text = "Ignore anything in a set of [number], they don't exist."
/datum/objective/abductee/foreignname
explanation_text = "No matter how they say it, other people keep mispronouncing your name. Be sure to correct them whenever possible."
/datum/objective/abductee/pairoff
explanation_text = "Being alone and in large groups are both frightening. Try to be alone with only one other person whenever possible."
/datum/objective/abductee/takeblame
explanation_text = "Try to get formally executed for a crime you didn't commit, without a false confession."
@@ -116,12 +116,13 @@
else
dat += "<h3>Subject Status : </h3>"
dat += "[occupant.name] => "
switch(occupant.stat)
if(0)
var/mob/living/mob_occupant = occupant
switch(mob_occupant.stat)
if(CONSCIOUS)
dat += "<span class='good'>Conscious</span>"
if(1)
if(UNCONSCIOUS)
dat += "<span class='average'>Unconscious</span>"
else
else // DEAD
dat += "<span class='bad'>Deceased</span>"
dat += "<br>"
dat += "[flash]"
@@ -146,9 +147,11 @@
if(href_list["close"])
close_machine()
return
if(occupant && occupant.stat != DEAD)
if(href_list["experiment"])
flash = Experiment(occupant,href_list["experiment"])
if(occupant)
var/mob/living/mob_occupant = occupant
if(mob_occupant.stat != DEAD)
if(href_list["experiment"])
flash = Experiment(occupant,href_list["experiment"])
updateUsrDialog()
add_fingerprint(usr)
+23 -18
View File
@@ -79,7 +79,8 @@
/obj/machinery/sleeper/close_machine(mob/user)
if((isnull(user) || istype(user)) && state_open && !panel_open)
..(user)
if(occupant && occupant.stat != DEAD)
var/mob/living/mob_occupant = occupant
if(mob_occupant && mob_occupant.stat != DEAD)
to_chat(occupant, "<span class='notice'><b>You feel cool air surround you. You go numb as your senses turn inward.</b></span>")
/obj/machinery/sleeper/emp_act(severity)
@@ -128,27 +129,30 @@
data["chems"] += list(list("name" = R.name, "id" = R.id, "allowed" = chem_allowed(chem)))
data["occupant"] = list()
if(occupant)
data["occupant"]["name"] = occupant.name
data["occupant"]["stat"] = occupant.stat
data["occupant"]["health"] = occupant.health
data["occupant"]["maxHealth"] = occupant.maxHealth
var/mob/living/mob_occupant = occupant
if(mob_occupant)
data["occupant"]["name"] = mob_occupant.name
data["occupant"]["stat"] = mob_occupant.stat
data["occupant"]["health"] = mob_occupant.health
data["occupant"]["maxHealth"] = mob_occupant.maxHealth
data["occupant"]["minHealth"] = HEALTH_THRESHOLD_DEAD
data["occupant"]["bruteLoss"] = occupant.getBruteLoss()
data["occupant"]["oxyLoss"] = occupant.getOxyLoss()
data["occupant"]["toxLoss"] = occupant.getToxLoss()
data["occupant"]["fireLoss"] = occupant.getFireLoss()
data["occupant"]["cloneLoss"] = occupant.getCloneLoss()
data["occupant"]["brainLoss"] = occupant.getBrainLoss()
data["occupant"]["bruteLoss"] = mob_occupant.getBruteLoss()
data["occupant"]["oxyLoss"] = mob_occupant.getOxyLoss()
data["occupant"]["toxLoss"] = mob_occupant.getToxLoss()
data["occupant"]["fireLoss"] = mob_occupant.getFireLoss()
data["occupant"]["cloneLoss"] = mob_occupant.getCloneLoss()
data["occupant"]["brainLoss"] = mob_occupant.getBrainLoss()
data["occupant"]["reagents"] = list()
if(occupant.reagents.reagent_list.len)
for(var/datum/reagent/R in occupant.reagents.reagent_list)
for(var/datum/reagent/R in mob_occupant.reagents.reagent_list)
data["occupant"]["reagents"] += list(list("name" = R.name, "volume" = R.volume))
return data
/obj/machinery/sleeper/ui_act(action, params)
if(..())
return
var/mob/living/mob_occupant = occupant
switch(action)
if("door")
if(state_open)
@@ -158,9 +162,9 @@
. = TRUE
if("inject")
var/chem = params["chem"]
if(!is_operational() || !occupant)
if(!is_operational() || !mob_occupant)
return
if(occupant.health < min_health && chem != "epinephrine")
if(mob_occupant.health < min_health && chem != "epinephrine")
return
if(inject_chem(chem))
. = TRUE
@@ -177,10 +181,11 @@
return TRUE
/obj/machinery/sleeper/proc/chem_allowed(chem)
if(!occupant)
var/mob/living/mob_occupant = occupant
if(!mob_occupant)
return
var/amount = occupant.reagents.get_reagent_amount(chem) + 10 <= 20 * efficiency
var/occ_health = occupant.health > min_health || chem == "epinephrine"
var/amount = mob_occupant.reagents.get_reagent_amount(chem) + 10 <= 20 * efficiency
var/occ_health = mob_occupant.health > min_health || chem == "epinephrine"
return amount && occ_health
/obj/machinery/sleeper/proc/reset_chem_buttons()
+67 -49
View File
@@ -121,10 +121,12 @@
/obj/machinery/clonepod/examine(mob/user)
..()
var/mob/living/mob_occupant = occupant
if(mess)
to_chat(user, "It's filled with blood and viscera. You swear you can see it moving...")
if (is_operational() && (!isnull(occupant)) && (occupant.stat != DEAD))
to_chat(user, "Current clone cycle is [round(get_completion())]% complete.")
if(is_operational() && mob_occupant)
if(mob_occupant.stat != DEAD)
to_chat(user, "Current clone cycle is [round(get_completion())]% complete.")
/obj/machinery/clonepod/return_air()
// We want to simulate the clone not being in contact with
@@ -136,7 +138,10 @@
return GM
/obj/machinery/clonepod/proc/get_completion()
. = (100 * ((occupant.health + 100) / (heal_level + 100)))
. = FALSE
var/mob/living/mob_occupant = occupant
if(mob_occupant)
. = (100 * ((mob_occupant.health + 100) / (heal_level + 100)))
/obj/machinery/clonepod/attack_ai(mob/user)
return examine(user)
@@ -172,11 +177,11 @@
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src)
if(clonemind.changeling)
var/obj/item/organ/brain/B = H.getorganslot("brain")
B.vital = FALSE
B.decoy_override = TRUE
if(clonemind.changeling)
var/obj/item/organ/brain/B = H.getorganslot("brain")
B.vital = FALSE
B.decoy_override = TRUE
H.hardset_dna(ui, se, H.real_name, null, mrace, features)
if(efficiency > 2)
@@ -204,13 +209,13 @@
clonemind.transfer_to(H)
if(grab_ghost_when == CLONER_FRESH_CLONE)
H.grab_ghost()
to_chat(H, "<span class='notice'><b>Consciousness slowly creeps over you as your body regenerates.</b><br><i>So this is what cloning feels like?</i></span>")
if(grab_ghost_when == CLONER_FRESH_CLONE)
H.grab_ghost()
to_chat(H, "<span class='notice'><b>Consciousness slowly creeps over you as your body regenerates.</b><br><i>So this is what cloning feels like?</i></span>")
if(grab_ghost_when == CLONER_MATURE_CLONE)
H.ghostize(TRUE) //Only does anything if they were still in their old body and not already a ghost
to_chat(H.get_ghost(TRUE), "<span class='notice'>Your body is beginning to regenerate in a cloning pod. You will become conscious when it is complete.</span>")
H.ghostize(TRUE) //Only does anything if they were still in their old body and not already a ghost
to_chat(H.get_ghost(TRUE), "<span class='notice'>Your body is beginning to regenerate in a cloning pod. You will become conscious when it is complete.</span>")
if(H)
H.faction |= factions
@@ -223,25 +228,26 @@
//Grow clones to maturity then kick them out. FREELOADERS
/obj/machinery/clonepod/process()
var/mob/living/mob_occupant = occupant
if(!is_operational()) //Autoeject if power is lost
if (occupant)
if(mob_occupant)
go_out()
connected_message("Clone Ejected: Loss of power.")
else if((occupant) && (occupant.loc == src))
if((occupant.stat == DEAD) || (occupant.suiciding) || occupant.hellbound) //Autoeject corpses and suiciding dudes.
else if(mob_occupant && (mob_occupant.loc == src))
if((mob_occupant.stat == DEAD) || (mob_occupant.suiciding) || mob_occupant.hellbound) //Autoeject corpses and suiciding dudes.
connected_message("Clone Rejected: Deceased.")
SPEAK("The cloning of [occupant.real_name] has been \
SPEAK("The cloning of [mob_occupant.real_name] has been \
aborted due to unrecoverable tissue failure.")
go_out()
else if(occupant.cloneloss > (100 - heal_level))
occupant.Paralyse(4)
else if(mob_occupant.cloneloss > (100 - heal_level))
mob_occupant.Paralyse(4)
//Slowly get that clone healed and finished.
occupant.adjustCloneLoss(-((speed_coeff/2) * config.damage_multiplier))
var/progress = CLONE_INITIAL_DAMAGE - occupant.getCloneLoss()
mob_occupant.adjustCloneLoss(-((speed_coeff/2) * config.damage_multiplier))
var/progress = CLONE_INITIAL_DAMAGE - mob_occupant.getCloneLoss()
// To avoid the default cloner making incomplete clones
progress += (100 - MINIMUM_HEAL_LEVEL)
var/milestone = CLONE_INITIAL_DAMAGE / flesh_number
@@ -252,24 +258,24 @@
var/obj/item/I = pick_n_take(unattached_flesh)
if(isorgan(I))
var/obj/item/organ/O = I
O.Insert(occupant)
O.Insert(mob_occupant)
else if(isbodypart(I))
var/obj/item/bodypart/BP = I
BP.attach_limb(occupant)
BP.attach_limb(mob_occupant)
//Premature clones may have brain damage.
occupant.adjustBrainLoss(-((speed_coeff/2) * config.damage_multiplier))
mob_occupant.adjustBrainLoss(-((speed_coeff/2) * config.damage_multiplier))
check_brine()
use_power(7500) //This might need tweaking.
else if((occupant.cloneloss <= (100 - heal_level)))
else if((mob_occupant.cloneloss <= (100 - heal_level)))
connected_message("Cloning Process Complete.")
SPEAK("The cloning cycle of [occupant.real_name] is complete.")
SPEAK("The cloning cycle of [mob_occupant.real_name] is complete.")
go_out()
else if ((!occupant) || (occupant.loc != src))
else if (!mob_occupant || mob_occupant.loc != src)
occupant = null
if (!mess && !panel_open)
icon_state = "pod_0"
@@ -305,16 +311,19 @@
to_chat(user, "<font color = #666633>-% Successfully stored \ref[P.buffer] [P.buffer.name] in buffer %-</font color>")
return
var/mob/living/mob_occupant = occupant
if(W.GetID())
if(!check_access(W))
to_chat(user, "<span class='danger'>Access Denied.</span>")
return
if(!(occupant || mess))
if(!(mob_occupant || mess))
to_chat(user, "<span class='danger'>Error: Pod has no occupant.</span>")
return
else
connected_message("Authorized Ejection")
SPEAK("An authorized ejection of [clonemind.name] has occurred.")
SPEAK("An authorized ejection of [clonemind.name] has occurred.")
to_chat(user, "<span class='notice'>You force an emergency ejection. </span>")
go_out()
else
@@ -339,54 +348,63 @@
/obj/machinery/clonepod/proc/go_out()
countdown.stop()
var/mob/living/mob_occupant = occupant
if(mess) //Clean that mess and dump those gibs!
mess = FALSE
new /obj/effect/gibspawner/generic(loc)
new /obj/effect/gibspawner/generic(loc)
audible_message("<span class='italics'>You hear a splat.</span>")
icon_state = "pod_0"
return
if(!occupant)
if(!mob_occupant)
return
if(grab_ghost_when == CLONER_MATURE_CLONE)
occupant.grab_ghost()
to_chat(occupant, "<span class='notice'><b>There is a bright flash!</b><br><i>You feel like a new being.</i></span>")
occupant.flash_act()
var/turf/T = get_turf(src)
if(grab_ghost_when == CLONER_MATURE_CLONE)
mob_occupant.grab_ghost()
to_chat(occupant, "<span class='notice'><b>There is a bright flash!</b><br><i>You feel like a new being.</i></span>")
mob_occupant.flash_act()
var/turf/T = get_turf(src)
occupant.forceMove(T)
icon_state = "pod_0"
occupant.domutcheck(1) //Waiting until they're out before possible monkeyizing. The 1 argument forces powers to manifest.
mob_occupant.domutcheck(1) //Waiting until they're out before possible monkeyizing. The 1 argument forces powers to manifest.
occupant = null
/obj/machinery/clonepod/proc/malfunction()
if(occupant)
var/mob/living/mob_occupant = occupant
if(mob_occupant)
connected_message("Critical Error!")
SPEAK("Critical error! Please contact a Thinktronic Systems \
technician, as your warranty may be affected.")
mess = TRUE
for(var/obj/item/O in unattached_flesh)
qdel(O)
for(var/obj/item/O in unattached_flesh)
qdel(O)
icon_state = "pod_g"
if(occupant.mind != clonemind)
clonemind.transfer_to(occupant)
occupant.grab_ghost() // We really just want to make you suffer.
flash_color(occupant, flash_color="#960000", flash_time=100)
to_chat(occupant, "<span class='warning'><b>Agony blazes across your consciousness as your body is torn apart.</b><br><i>Is this what dying is like? Yes it is.</i></span>")
if(mob_occupant.mind != clonemind)
clonemind.transfer_to(mob_occupant)
mob_occupant.grab_ghost() // We really just want to make you suffer.
flash_color(mob_occupant, flash_color="#960000", flash_time=100)
to_chat(mob_occupant, "<span class='warning'><b>Agony blazes across your consciousness as your body is torn apart.</b><br><i>Is this what dying is like? Yes it is.</i></span>")
playsound(src.loc, 'sound/machines/warning-buzzer.ogg', 50, 0)
occupant << sound('sound/hallucinations/veryfar_noise.ogg',0,1,50)
QDEL_IN(occupant, 40)
mob_occupant << sound('sound/hallucinations/veryfar_noise.ogg',0,1,50)
QDEL_IN(mob_occupant, 40)
/obj/machinery/clonepod/relaymove(mob/user)
if(user.stat == CONSCIOUS)
go_out()
/obj/machinery/clonepod/emp_act(severity)
if((occupant || mess) && prob(100/(severity*efficiency)))
var/mob/living/mob_occupant = occupant
if(mob_occupant && prob(100/(severity*efficiency)))
connected_message(Gibberish("EMP-caused Accidental Ejection", 0))
SPEAK(Gibberish("Exposure to electromagnetic fields has caused the ejection of [clonemind.name] prematurely." ,0))
SPEAK(Gibberish("Exposure to electromagnetic fields has caused the ejection of [mob_occupant.real_name] prematurely." ,0))
go_out()
..()
+38
View File
@@ -0,0 +1,38 @@
diff a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm (rejected hunks)
@@ -311,15 +311,15 @@
to_chat(user, "<font color = #666633>-% Successfully stored \ref[P.buffer] [P.buffer.name] in buffer %-</font color>")
return
+ var/mob/living/mob_occupant = occupant
if(W.GetID())
if(!check_access(W))
to_chat(user, "<span class='danger'>Access Denied.</span>")
return
- if(!(occupant || mess))
+ if(!(mob_occupant || mess))
to_chat(user, "<span class='danger'>Error: Pod has no occupant.</span>")
return
else
- var/mob/living/mob_occupant
connected_message("Authorized Ejection")
SPEAK("An authorized ejection of [clonemind.name] has occurred.")
to_chat(user, "<span class='notice'>You force an emergency ejection. </span>")
@@ -395,16 +395,10 @@
go_out()
/obj/machinery/clonepod/emp_act(severity)
-<<<<<<< HEAD
- if((occupant || mess) && prob(100/(severity*efficiency)))
- connected_message(Gibberish("EMP-caused Accidental Ejection", 0))
- SPEAK(Gibberish("Exposure to electromagnetic fields has caused the ejection of [clonemind.name] prematurely." ,0))
-=======
- if(isliving(occupant) && prob(100/(severity*efficiency)))
- var/mob/living/mob_occupant = occupant
+ var/mob/living/mob_occupant = occupant
+ if(mob_occupant && prob(100/(severity*efficiency)))
connected_message(Gibberish("EMP-caused Accidental Ejection", 0))
SPEAK(Gibberish("Exposure to electromagnetic fields has caused the ejection of [mob_occupant.real_name] prematurely." ,0))
->>>>>>> Changes /obj/machinery to have atom/movable occupants
go_out()
..()
+8 -6
View File
@@ -186,21 +186,23 @@
// Scanner
if (!isnull(src.scanner))
var/mob/living/scanner_occupant = scanner.occupant
dat += "<h3>Scanner Functions</h3>"
dat += "<div class='statusDisplay'>"
if (!src.scanner.occupant)
if(!scanner_occupant)
dat += "Scanner Unoccupied"
else if(loading)
dat += "[src.scanner.occupant] => Scanning..."
dat += "[scanner_occupant] => Scanning..."
else
if (src.scanner.occupant.ckey != scantemp_ckey)
if(scanner_occupant.ckey != scantemp_ckey)
scantemp = "Ready to Scan"
scantemp_ckey = src.scanner.occupant.ckey
dat += "[src.scanner.occupant] => [scantemp]"
scantemp_ckey = scanner_occupant.ckey
dat += "[scanner_occupant] => [scantemp]"
dat += "</div>"
if (src.scanner.occupant)
if(scanner_occupant)
dat += "<a href='byond://?src=\ref[src];scan=1'>Start Scan</a>"
dat += "<br><a href='byond://?src=\ref[src];lock=1'>[src.scanner.locked ? "Unlock Scanner" : "Lock Scanner"]</a>"
else
+3 -2
View File
@@ -113,7 +113,8 @@
to_chat(R.connected_ai, "<br><br><span class='alert'>ALERT - Cyborg detonation detected: [R.name]</span><br>")
R.ResetSecurityCodes()
else
message_admins("<span class='notice'>[key_name_admin(usr)] (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[usr]'>FLW</A>) detonated [key_name(R, R.client)](<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[R.x];Y=[R.y];Z=[R.z]'>JMP</a>)!</span>")
var/turf/T = get_turf(R)
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] detonated [key_name(R, R.client)][ADMIN_JMP(T)]!</span>")
log_game("\<span class='notice'>[key_name(usr)] detonated [key_name(R)]!</span>")
if(R.connected_ai)
to_chat(R.connected_ai, "<br><br><span class='alert'>ALERT - Cyborg detonation detected: [R.name]</span><br>")
@@ -127,7 +128,7 @@
if(can_control(usr, R))
var/choice = input("Are you certain you wish to [R.canmove ? "lock down" : "release"] [R.name]?") in list("Confirm", "Abort")
if(choice == "Confirm" && can_control(usr, R) && !..())
message_admins("<span class='notice'>[key_name_admin(usr)] (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[usr]'>FLW</A>) [R.canmove ? "locked down" : "released"] [key_name(R, R.client)](<A HREF='?_src_=holder;adminplayerobservefollow=\ref[R]'>FLW</A>)!</span>")
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] [R.canmove ? "locked down" : "released"] [key_name(R, R.client)][ADMIN_LOOKUPFLW(R)]!</span>")
log_game("[key_name(usr)] [R.canmove ? "locked down" : "released"] [key_name(R)]!")
R.SetLockdown(!R.lockcharge)
to_chat(R, "[!R.lockcharge ? "<span class='notice'>Your lockdown has been lifted!" : "<span class='alert'>You have been locked down!"]</span>")
+5 -4
View File
@@ -105,13 +105,14 @@
..()
// search for ghosts, if the corpse is empty and the scanner is connected to a cloner
if(occupant)
var/mob/living/mob_occupant = occupant
if(mob_occupant)
if(locate(/obj/machinery/computer/cloning, get_step(src, NORTH)) \
|| locate(/obj/machinery/computer/cloning, get_step(src, SOUTH)) \
|| locate(/obj/machinery/computer/cloning, get_step(src, EAST)) \
|| locate(/obj/machinery/computer/cloning, get_step(src, WEST)))
if(!occupant.suiciding && !(occupant.disabilities & NOCLONE) && !occupant.hellbound)
occupant.notify_ghost_cloning("Your corpse has been placed into a cloning scanner. Re-enter your corpse if you want to be cloned!", source = src)
if(!mob_occupant.suiciding && !(mob_occupant.disabilities & NOCLONE) && !mob_occupant.hellbound)
mob_occupant.notify_ghost_cloning("Your corpse has been placed into a cloning scanner. Re-enter your corpse if you want to be cloned!", source = src)
var/obj/machinery/computer/scan_consolenew/console
for(dir in list(NORTH,EAST,SOUTH,WEST))
@@ -157,4 +158,4 @@
if(..(user,1,0)) //don't set the machine, since there's no dialog
return
toggle_open(user)
toggle_open(user)
+4 -3
View File
@@ -136,13 +136,14 @@ The console is located at computer/gulag_teleporter.dm
/obj/machinery/gulag_teleporter/proc/strip_occupant()
if(linked_reclaimer)
linked_reclaimer.stored_items[occupant] = list()
for(var/obj/item/W in occupant)
if(!is_type_in_typecache(W, required_items) && occupant.temporarilyRemoveItemFromInventory(W))
var/mob/living/mob_occupant = occupant
for(var/obj/item/W in mob_occupant)
if(!is_type_in_typecache(W, required_items) && mob_occupant.temporarilyRemoveItemFromInventory(W))
if(istype(W, /obj/item/weapon/restraints/handcuffs))
W.forceMove(get_turf(src))
continue
if(linked_reclaimer)
linked_reclaimer.stored_items[occupant] += W
linked_reclaimer.stored_items[mob_occupant] += W
linked_reclaimer.contents += W
W.forceMove(linked_reclaimer)
else
+1
View File
@@ -61,6 +61,7 @@ GLOBAL_LIST_EMPTY(holopads)
/obj/machinery/holopad/Destroy()
if(outgoing_call)
LAZYADD(holo_calls, outgoing_call)
outgoing_call = null
for(var/I in holo_calls)
var/datum/holocall/HC = I
+22 -11
View File
@@ -1,8 +1,8 @@
/*
Overview:
Used to create objects that need a per step proc call. Default definition of 'New()'
Used to create objects that need a per step proc call. Default definition of 'Initialize()'
stores a reference to src machine in global 'machines list'. Default definition
of 'Del' removes reference to src machine in global 'machines list'.
of 'Destroy' removes reference to src machine in global 'machines list'.
Class Variables:
use_power (num)
@@ -44,7 +44,7 @@ Class Variables:
EMPED:16 -- temporary broken by EMP pulse
Class Procs:
New() 'game/machinery/machine.dm'
Initialize() 'game/machinery/machine.dm'
Destroy() 'game/machinery/machine.dm'
@@ -118,14 +118,15 @@ Class Procs:
var/panel_open = 0
var/state_open = 0
var/critical_machine = FALSE //If this machine is critical to station operation and should have the area be excempted from power failures.
var/mob/living/occupant = null
var/list/occupant_typecache = list(/mob/living) // turned into typecache in Initialize
var/atom/movable/occupant = null
var/unsecuring_tool = /obj/item/weapon/wrench
var/interact_open = 0 // Can the machine be interacted with when in maint/when the panel is open.
var/interact_offline = 0 // Can the machine be interacted with while de-powered.
var/speed_process = 0 // Process as fast as possible?
/obj/machinery/Initialize()
if (!armor)
if(!armor)
armor = list(melee = 25, bullet = 10, laser = 10, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 70)
. = ..()
GLOB.machines += src
@@ -135,6 +136,8 @@ Class Procs:
START_PROCESSING(SSfastprocess, src)
power_change()
occupant_typecache = typecacheof(occupant_typecache)
/obj/machinery/Destroy()
GLOB.machines.Remove(src)
if(!speed_process)
@@ -176,16 +179,24 @@ Class Procs:
L.update_canmove()
occupant = null
/obj/machinery/proc/close_machine(mob/living/target = null)
/obj/machinery/proc/close_machine(atom/movable/target = null)
state_open = 0
density = 1
if(!target)
for(var/mob/living/carbon/C in loc)
if(C.buckled || C.has_buckled_mobs())
for(var/am in loc)
if(!is_type_in_typecache(am, occupant_typecache))
continue
else
target = C
if(target && !target.buckled && !target.has_buckled_mobs())
var/atom/movable/AM = am
if(AM.has_buckled_mobs())
continue
if(isliving(AM))
var/mob/living/L = am
if(L.buckled)
continue
target = am
var/mob/living/mobtarget = target
if(target && !target.has_buckled_mobs() && (!isliving(target) || !mobtarget.buckled))
occupant = target
target.forceMove(src)
updateUsrDialog()
@@ -1,6 +1,9 @@
#define TURRET_STUN 0
#define TURRET_LETHAL 1
#define POPUP_ANIM_TIME 5
#define POPDOWN_ANIM_TIME 5 //Be sure to change the icon animation at the same time or it'll look bad
/obj/machinery/porta_turret
name = "turret"
icon = 'icons/obj/turrets.dmi'
@@ -422,7 +425,7 @@
raising = 1
if(cover)
flick("popup", cover)
sleep(10)
sleep(POPUP_ANIM_TIME)
raising = 0
if(cover)
cover.icon_state = "openTurretCover"
@@ -438,7 +441,7 @@
raising = 1
if(cover)
flick("popdown", cover)
sleep(10)
sleep(POPDOWN_ANIM_TIME)
raising = 0
if(cover)
cover.icon_state = "turretCover"
+1 -1
View File
@@ -121,7 +121,7 @@
var/atom/movable/AM = i
var/obj/item/bodypart/head/as_head = AM
var/obj/item/device/mmi/as_mmi = AM
var/brain_holder = istype(AM, /obj/item/organ/brain) || (istype(as_head) && as_head.brain) || (istype(as_mmi) && as_mmi.brain)
var/brain_holder = istype(AM, /obj/item/organ/brain) || (istype(as_head) && as_head.brain) || (istype(as_mmi) && as_mmi.brain) || istype(AM, /mob/living/brain)
if(isliving(AM) || brain_holder)
if(emagged)
if(!brain_holder)
+9 -8
View File
@@ -211,13 +211,13 @@
uv = TRUE
locked = TRUE
update_icon()
if(occupant)
if(occupant)
var/mob/living/mob_occupant = occupant
if(uv_super)
occupant.adjustFireLoss(rand(20, 36))
mob_occupant.adjustFireLoss(rand(20, 36))
else
occupant.adjustFireLoss(rand(10, 16))
if(iscarbon(occupant))
occupant.emote("scream")
mob_occupant.adjustFireLoss(rand(10, 16))
mob_occupant.emote("scream")
addtimer(CALLBACK(src, .proc/cook), 50)
else
uv_cycles = initial(uv_cycles)
@@ -368,14 +368,15 @@
else if(!helmet && !mask && !suit && !storage && !occupant)
return
else
if(occupant)
to_chat(occupant, "<span class='userdanger'>[src]'s confines grow warm, then hot, then scorching. You're being burned [!occupant.stat ? "alive" : "away"]!</span>")
if(occupant)
var/mob/living/mob_occupant = occupant
to_chat(mob_occupant, "<span class='userdanger'>[src]'s confines grow warm, then hot, then scorching. You're being burned [!mob_occupant.stat ? "alive" : "away"]!</span>")
cook()
. = TRUE
if("dispense")
if(!state_open)
return
var/static/list/valid_items = list("helmet", "suit", "mask", "storage")
var/item_name = params["item"]
if(item_name in valid_items)
+4 -4
View File
@@ -737,8 +737,8 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
icon_state = "sustenance"
products = list(/obj/item/weapon/reagent_containers/food/snacks/tofu = 24,
/obj/item/weapon/reagent_containers/food/drinks/ice = 12,
/obj/item/weapon/reagent_containers/food/snacks/candy_corn = 6,
/obj/item/weapon/reagent_containers/glass/beaker/waterbottle = 10)
/obj/item/weapon/reagent_containers/food/snacks/candy_corn = 6,
/obj/item/weapon/reagent_containers/glass/beaker/waterbottle = 10)
contraband = list(/obj/item/weapon/kitchen/knife = 6,
/obj/item/weapon/reagent_containers/food/drinks/coffee = 12,
/obj/item/weapon/tank/internals/emergency_oxygen = 6,
@@ -755,7 +755,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
products = list(/obj/item/weapon/reagent_containers/food/drinks/soda_cans/cola = 10,/obj/item/weapon/reagent_containers/food/drinks/soda_cans/space_mountain_wind = 10,
/obj/item/weapon/reagent_containers/food/drinks/soda_cans/dr_gibb = 10,/obj/item/weapon/reagent_containers/food/drinks/soda_cans/starkist = 10,
/obj/item/weapon/reagent_containers/food/drinks/soda_cans/space_up = 10,/obj/item/weapon/reagent_containers/food/drinks/soda_cans/pwr_game = 10,
/obj/item/weapon/reagent_containers/food/drinks/soda_cans/lemon_lime = 10,/obj/item/weapon/reagent_containers/glass/beaker/waterbottle = 10)
/obj/item/weapon/reagent_containers/food/drinks/soda_cans/lemon_lime = 10,/obj/item/weapon/reagent_containers/glass/beaker/waterbottle = 10)
contraband = list(/obj/item/weapon/reagent_containers/food/drinks/soda_cans/thirteenloko = 6,/obj/item/weapon/reagent_containers/food/drinks/soda_cans/shamblers = 6)
premium = list(/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/filled/nuka_cola = 1,/obj/item/weapon/reagent_containers/food/drinks/soda_cans/air = 1)
refill_canister = /obj/item/weapon/vending_refill/cola
@@ -1128,7 +1128,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
/obj/item/clothing/head/beanie=1, /obj/item/clothing/head/beanie/black=1, /obj/item/clothing/head/beanie/red=1, /obj/item/clothing/head/beanie/green=1, /obj/item/clothing/head/beanie/darkblue=1,
/obj/item/clothing/head/beanie/purple=1, /obj/item/clothing/head/beanie/yellow=1, /obj/item/clothing/head/beanie/orange=1, /obj/item/clothing/head/beanie/cyan=1, /obj/item/clothing/head/beanie/christmas=1,
/obj/item/clothing/head/beanie/striped=1, /obj/item/clothing/head/beanie/stripedred=1, /obj/item/clothing/head/beanie/stripedblue=1, /obj/item/clothing/head/beanie/stripedgreen=1,
/obj/item/clothing/suit/jacket/letterman_red=1)
/obj/item/clothing/suit/jacket/letterman_red=1, /obj/item/clothing/head/hunter=2)
contraband = list(/obj/item/clothing/under/syndicate/tacticool=1,/obj/item/clothing/mask/balaclava=1,/obj/item/clothing/head/ushanka=1,/obj/item/clothing/under/soviet=1,/obj/item/weapon/storage/belt/fannypack/black=2,/obj/item/clothing/suit/jacket/letterman_syndie=1,/obj/item/clothing/under/jabroni=1, /obj/item/clothing/suit/vapeshirt=1, /obj/item/clothing/under/geisha=1)
premium = list(/obj/item/clothing/under/suit_jacket/checkered=1,/obj/item/clothing/head/mailman=1,/obj/item/clothing/under/rank/mailman=1,/obj/item/clothing/suit/jacket/leather=1,/obj/item/clothing/suit/jacket/leather/overcoat=1,/obj/item/clothing/under/pants/mustangjeans=1,/obj/item/clothing/neck/necklace/dope=3,/obj/item/clothing/suit/jacket/letterman_nanotrasen=1)
refill_canister = /obj/item/weapon/vending_refill/clothing
+2 -2
View File
@@ -337,8 +337,8 @@
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/flashbang/proj_init(var/obj/item/weapon/grenade/flashbang/F)
var/turf/T = get_turf(src)
message_admins("[key_name(chassis.occupant, chassis.occupant.client)](<A HREF='?_src_=holder;adminmoreinfo=\ref[chassis.occupant]'>?</A>) fired a [src] in ([T.x],[T.y],[T.z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>JMP</a>)",0,1)
log_game("[key_name(chassis.occupant)] fired a [src] ([T.x],[T.y],[T.z])")
message_admins("[ADMIN_LOOKUPFLW(chassis.occupant)] fired a [src] in [ADMIN_COORDJMP(T)]",0,1)
log_game("[key_name(chassis.occupant)] fired a [src] [COORD(T)]")
addtimer(CALLBACK(F, /obj/item/weapon/grenade/flashbang.proc/prime), det_time)
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/flashbang/clusterbang //Because I am a heartless bastard -Sieve //Heartless? for making the poor man's honkblast? - Kaze
@@ -129,7 +129,7 @@
name = "footprints"
icon = 'icons/effects/footprints.dmi'
icon_state = "nothingwhatsoever"
desc = "where might they lead?"
desc = "WHOSE FOOTPRINTS ARE THESE?"
random_icon_states = null
var/entered_dirs = 0
var/exited_dirs = 0
@@ -74,7 +74,7 @@
/obj/effect/particle_effect/smoke/proc/spread_smoke()
var/turf/t_loc = get_turf(src)
if(!t_loc)
return
return
var/list/newsmokes = list()
for(var/turf/T in t_loc.GetAtmosAdjacentTurfs())
var/obj/effect/particle_effect/smoke/foundsmoke = locate() in T //Don't spread smoke where there's already smoke!
+12
View File
@@ -611,6 +611,18 @@
icon_state = "shieldsparkles"
duration = 6
/obj/effect/overlay/temp/heart
name = "heart"
icon = 'icons/mob/animal.dmi'
icon_state = "heart"
duration = 25
/obj/effect/overlay/temp/heart/Initialize(mapload)
. = ..()
pixel_x = rand(-4,4)
pixel_y = rand(-4,4)
animate(src, pixel_y = pixel_y + 32, alpha = 0, time = 25)
/obj/effect/overlay/palmtree_r
name = "Palm tree"
+1 -1
View File
@@ -63,7 +63,7 @@
return
if (istype(M, /atom/movable))
if(ismegafauna(M))
message_admins("[M] (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[M]'>FLW</A>) has teleported through [src].")
message_admins("[M] [ADMIN_FLW(M)] has teleported through [src].")
do_teleport(M, target, precision) ///You will appear adjacent to the beacon
+6 -1
View File
@@ -1,10 +1,15 @@
/proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, ignorecap = 0, flame_range = 0 ,silent = 0, smoke = 1)
/proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, ignorecap = 0, flame_range, silent = 0, smoke = 1)
set waitfor = 0
src = null //so we don't abort once src is deleted
epicenter = get_turf(epicenter)
if(!epicenter)
return
if(isnull(flame_range))
flame_range = light_impact_range
if(isnull(flash_range))
flash_range = devastation_range
// Archive the uncapped explosion for the doppler array
var/orig_dev_range = devastation_range
var/orig_heavy_range = heavy_impact_range
+27 -3
View File
@@ -7,6 +7,7 @@
desc = "An official document entrusting the governance of the station \
and surrounding space to the Captain. "
var/used = FALSE
var/name_type = "station"
var/unlimited_uses = FALSE
var/ignores_timeout = FALSE
@@ -33,10 +34,10 @@
/obj/item/station_charter/attack_self(mob/living/user)
if(used)
to_chat(user, "This charter has already been used to name the station.")
to_chat(user, "The [name_type] has already been named.")
return
if(!ignores_timeout && (world.time-SSticker.round_start_time > STATION_RENAME_TIME_LIMIT)) //5 minutes
to_chat(user, "The crew has already settled into the shift. It probably wouldn't be good to rename the station right now.")
to_chat(user, "The crew has already settled into the shift. It probably wouldn't be good to rename the [name_type] right now.")
return
if(response_timer_id)
to_chat(user, "You're still waiting for approval from your employers about your proposed name change, it'd be best to wait for now.")
@@ -60,7 +61,7 @@
to_chat(user, "Your name has been sent to your employers for approval.")
// Autoapproves after a certain time
response_timer_id = addtimer(CALLBACK(src, .proc/rename_station, new_name, user.name, user.real_name, key_name(user)), approval_time, TIMER_STOPPABLE)
to_chat(GLOB.admins, "<span class='adminnotice'><b><font color=orange>CUSTOM STATION RENAME:</font></b>[key_name_admin(user)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) proposes to rename the station to [new_name] (will autoapprove in [approval_time / 10] seconds). [ADMIN_SMITE(user)] (<A HREF='?_src_=holder;reject_custom_name=\ref[src]'>REJECT</A>) (<a href='?_src_=holder;CentcommReply=\ref[user]'>RPLY</a>)</span>")
to_chat(GLOB.admins, "<span class='adminnotice'><b><font color=orange>CUSTOM STATION RENAME:</font></b>[ADMIN_LOOKUPFLW(user)] proposes to rename the [name_type] to [new_name] (will autoapprove in [approval_time / 10] seconds). [ADMIN_SMITE(user)] (<A HREF='?_src_=holder;reject_custom_name=\ref[src]'>REJECT</A>) [ADMIN_CENTCOM_REPLY(user)]</span>")
/obj/item/station_charter/proc/reject_proposed(user)
if(!user)
@@ -94,4 +95,27 @@
unlimited_uses = TRUE
ignores_timeout = TRUE
/obj/item/weapon/station_charter/flag
name = "nanotrasen banner"
icon = 'icons/obj/items.dmi'
var/name_type = "planet"
icon_state = "banner"
item_state = "banner"
desc = "A cunning device used to claim ownership of planets."
w_class = 5
force = 15
/obj/item/station_charter/flag/rename_station(designation, uname, ureal_name, ukey)
set_station_name(designation)
minor_announce("[ureal_name] has designated the planet as [station_name()]", "Captain's Banner", 0)
log_game("[ukey] has renamed the planet as [station_name()].")
name = "banner of [station_name()]"
desc = "The banner bears the official coat of arms of Nanotrasen, signifying that [station_name()] has been claimed by Captain [uname] in the name of the company."
SSblackbox.set_details("station_renames","[station_name()]")
if(!unlimited_uses)
used = TRUE
#undef STATION_RENAME_TIME_LIMIT
+2 -2
View File
@@ -7,6 +7,7 @@ GLOBAL_LIST_EMPTY(GPS_list)
w_class = WEIGHT_CLASS_SMALL
slot_flags = SLOT_BELT
origin_tech = "materials=2;magnets=1;bluespace=2"
unique_rename = TRUE
var/gpstag = "COM0"
var/emped = FALSE
var/turf/locked_location
@@ -135,10 +136,9 @@ GLOBAL_LIST_EMPTY(GPS_list)
..()
if(href_list["tag"] )
var/a = input("Please enter desired tag.", name, gpstag) as text
a = uppertext(copytext(sanitize(a), 1, 5))
a = copytext(sanitize(a), 1, 20)
if(in_range(src, usr))
gpstag = a
name = "global positioning system ([gpstag])"
attack_self(usr)
/obj/item/device/gps/science
+2 -2
View File
@@ -95,8 +95,8 @@
"[user] activates \the [src]!", \
"<span class='notice'>You activate \the [src].</span>",
"<span class='italics'>You hear a click.</span>")
message_admins("Power sink activated by [key_name_admin(user)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) at ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
log_game("Power sink activated by [key_name(user)] at ([x],[y],[z])")
message_admins("Power sink activated by [ADMIN_LOOKUPFLW(user)] at [ADMIN_COORDJMP(src)]")
log_game("Power sink activated by [key_name(user)] at [COORD(src)]")
set_mode(OPERATING)
if(OPERATING)
@@ -296,6 +296,7 @@
// --- Cold, emotionless machines. ---
else if(isobj(M))
jobname = "Machine"
voice = capitalize(voice)
// --- Unidentifiable mob ---
else
@@ -178,21 +178,21 @@
var/log_attacher = ""
if(attacher)
log_attacher = "(<A HREF='?_src_=holder;adminmoreinfo=\ref[attacher]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[attacher]'>FLW</A>)"
log_attacher = "[ADMIN_QUE(attacher)] [ADMIN_FLW(attacher)]"
var/mob/mob = get_mob_by_key(src.fingerprintslast)
var/last_touch_info = ""
if(mob)
last_touch_info = "(<A HREF='?_src_=holder;adminmoreinfo=\ref[mob]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[mob]'>FLW</A>)"
last_touch_info = "[ADMIN_QUE(mob)] [ADMIN_FLW(mob)]"
var/log_str3 = " Last touched by: [key_name_admin(mob)]"
var/bomb_message = "[log_str1] <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[bombturf.x];Y=[bombturf.y];Z=[bombturf.z]'>[A.name]</a> [log_str2][log_attacher] [log_str3][last_touch_info]"
var/bomb_message = "[log_str1] [A.name][ADMIN_JMP(bombturf)] [log_str2][log_attacher] [log_str3][last_touch_info]"
GLOB.bombers += bomb_message
message_admins(bomb_message, 0, 1)
log_game("[log_str1] [A.name]([A.x],[A.y],[A.z]) [log_str2] [log_str3]")
log_game("[log_str1] [A.name][COORD(bombturf)] [log_str2] [log_str3]")
merge_gases()
spawn(20) // In case one tank bursts
for (var/i=0,i<5,i++)
@@ -155,8 +155,9 @@ GLOBAL_LIST_INIT(plasma_recipes, list ( \
/obj/item/stack/sheet/mineral/plasma/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
if(W.is_hot() > 300)//If the temperature of the object is over 300, then ignite
message_admins("Plasma sheets ignited by [key_name_admin(user)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) in ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
log_game("Plasma sheets ignited by [key_name(user)] in ([x],[y],[z])")
var/turf/T = get_turf(src)
message_admins("Plasma sheets ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_COORDJMP(T)]",0,1)
log_game("Plasma sheets ignited by [key_name(user)] in [COORD(T)]")
fire_act()
else
return ..()
+46
View File
@@ -0,0 +1,46 @@
/obj/item/weapon/pie_cannon
name = "pie cannon"
desc = "Load cream pie for optimal results"
force = 10
icon_state = "piecannon"
item_state = "powerfist"
var/obj/item/weapon/reagent_containers/food/snacks/pie/loaded = null
/obj/item/weapon/pie_cannon/attackby(obj/item/I, mob/living/L)
if(istype(I, /obj/item/weapon/reagent_containers/food/snacks/pie))
if(!loaded)
L.transferItemToLoc(I, src)
loaded = I
to_chat(L, "<span class='notice'>You load the [I] into the [src]!</span>")
return
return ..()
/obj/item/weapon/pie_cannon/afterattack(atom/target, mob/living/user, flag, params)
if(!loaded)
return ..()
var/obj/item/projectile/pie/launched = new /obj/item/projectile/pie(src)
launched.P = loaded
loaded.forceMove(launched)
launched.appearance = loaded.appearance
loaded = null
launched.preparePixelProjectile(target, get_turf(target), user, params, 0)
launched.forceMove(get_turf(src))
launched.fire()
user.visible_message("<span class='danger'>[user] fires the [src] at [target]!</span>")
/obj/item/projectile/pie
name = "pie"
desc = "Think fast!"
var/obj/item/weapon/reagent_containers/food/snacks/pie/P = null
/obj/item/projectile/pie/on_hit(atom/A)
. = ..()
if(P)
A.visible_message("<span class='danger'>[P] smashes into [A] at high velocity!</span>")
P.forceMove(get_turf(A))
P.throw_impact(A)
if(ismovableatom(A))
var/atom/movable/AM = A
if(!AM.anchored)
AM.throw_at(get_edge_target_turf(get_dir(src, AM), 3, 2))
@@ -158,7 +158,7 @@
if(lit)
START_PROCESSING(SSobj, src)
if(!warned_admins)
message_admins("[key_name_admin(usr)]<A HREF='?_src_=holder;adminmoreinfo=\ref[usr]'>?</A> (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[usr]'>FLW</A>) has lit a flamethrower.")
message_admins("[ADMIN_LOOKUPFLW(usr)] has lit a flamethrower.")
warned_admins = 1
if(href_list["amount"])
throw_amount = throw_amount + text2num(href_list["amount"])
@@ -36,8 +36,8 @@
else if(clown_check(user))
var/turf/bombturf = get_turf(src)
var/area/A = get_area(bombturf)
message_admins("[key_name_admin(usr)]<A HREF='?_src_=holder;adminmoreinfo=\ref[usr]'>?</A> (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[usr]'>FLW</A>) has primed a [name] for detonation at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[bombturf.x];Y=[bombturf.y];Z=[bombturf.z]'>[A.name] (JMP)</a>.")
log_game("[key_name(usr)] has primed a [name] for detonation at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z]).")
message_admins("[ADMIN_LOOKUPFLW(usr)] has primed a [name] for detonation at [A.name][ADMIN_JMP(bombturf)].")
log_game("[key_name(usr)] has primed a [name] for detonation at [A.name] [COORD(bombturf)].")
to_chat(user, "<span class='warning'>You prime the [name]! [det_time / 10] second\s!</span>")
playsound(user.loc, 'sound/weapons/armbomb.ogg', 60, 1)
active = 1
@@ -177,12 +177,12 @@
var/mob/last = get_mob_by_ckey(nadeassembly.fingerprintslast)
var/turf/T = get_turf(src)
var/area/A = get_area(T)
message_admins("grenade primed by an assembly, attached by [key_name_admin(M)]<A HREF='?_src_=holder;adminmoreinfo=\ref[M]'>(?)</A> (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[M]'>FLW</A>) and last touched by [key_name_admin(last)]<A HREF='?_src_=holder;adminmoreinfo=\ref[last]'>(?)</A> (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[last]'>FLW</A>) ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>[A.name] (JMP)</a>.")
log_game("grenade primed by an assembly, attached by [key_name(M)] and last touched by [key_name(last)] ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] ([T.x], [T.y], [T.z])")
message_admins("grenade primed by an assembly, attached by [ADMIN_LOOKUPFLW(M)] and last touched by [ADMIN_LOOKUPFLW(last)] ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] [ADMIN_JMP(T)]</a>.")
log_game("grenade primed by an assembly, attached by [key_name(M)] and last touched by [key_name(last)] ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] [COORD(T)]")
var/turf/DT = get_turf(src)
var/area/DA = get_area(DT)
log_game("A grenade detonated at [DA.name] ([DT.x], [DT.y], [DT.z])")
log_game("A grenade detonated at [DA.name] [COORD(DT)]")
update_mob()
@@ -119,8 +119,8 @@
qdel(src) //How?
/obj/item/weapon/grenade/plastic/suicide_act(mob/user)
message_admins("[key_name_admin(user)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) suicided with [src] at ([user.x],[user.y],[user.z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)",0,1)
message_admins("[key_name(user)] suicided with [src] at ([user.x],[user.y],[user.z])")
message_admins("[ADMIN_LOOKUPFLW(user)] suicided with [src] at [ADMIN_COORDJMP(user)]",0,1)
log_game("[key_name(user)] suicided with [src] at [COORD(user)]")
user.visible_message("<span class='suicide'>[user] activates the [src] and holds it above [user.p_their()] head! It looks like [user.p_theyre()] going out with a bang!</span>")
var/message_say = "FOR NO RAISIN!"
if(user.mind)
@@ -44,7 +44,7 @@
active = TRUE
var/turf/boomturf = get_turf(imp_in)
var/area/A = get_area(boomturf)
message_admins("[key_name_admin(imp_in)]<A HREF='?_src_=holder;adminmoreinfo=\ref[imp_in]'>?</A> (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[imp_in]'>FLW</A>) has activated their [name] at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[imp_in.x];Y=[imp_in.y];Z=[imp_in.z]'>[A.name] (JMP)</a>.")
message_admins("[ADMIN_LOOKUPFLW(imp_in)] has activated their [name] at [A.name] [ADMIN_JMP(boomturf)].")
//If the delay is short, just blow up already jeez
if(delay <= 7)
explosion(src,heavy,medium,weak,weak, flame_range = weak)
@@ -41,9 +41,10 @@
data["open"] = state_open
data["occupant"] = list()
if(occupant)
data["occupant"]["name"] = occupant.name
data["occupant"]["stat"] = occupant.stat
if(occupant)
var/mob/living/mob_occupant = occupant
data["occupant"]["name"] = mob_occupant.name
data["occupant"]["stat"] = mob_occupant.stat
data["special_name"] = special ? special_name : null
data["ready_implants"] = ready_implants
@@ -16,7 +16,7 @@
var/brightness_on = 3
/obj/item/weapon/melee/energy/Initialize()
..()
. = ..()
if(LAZYLEN(possible_colors))
item_color = pick(possible_colors)
switch(item_color)//Only run this check if the color was picked randomly, so that colors can be manually set for non-random colored energy weapons.
@@ -183,8 +183,8 @@
light_color = "#40ceff"
possible_colors = null
/obj/item/weapon/melee/energy/sword/cyborg/saw/New()
..()
/obj/item/weapon/melee/energy/sword/cyborg/saw/Initialize()
. = ..()
icon_state = "esaw_0"
item_color = null
@@ -207,19 +207,9 @@
/obj/item/weapon/melee/energy/sword/saber/attackby(obj/item/weapon/W, mob/living/user, params)
if(istype(W, /obj/item/weapon/melee/energy/sword/saber))
to_chat(user, "<span class='notice'>You attach the ends of the two energy swords, making a single double-bladed weapon! You're cool.</span>")
var/obj/item/weapon/melee/energy/sword/saber/other_esword = W
var/obj/item/weapon/twohanded/dualsaber/newSaber = new(user.loc)
if(hacked || other_esword.hacked)
newSaber.hacked = TRUE
newSaber.item_color = "rainbow"
qdel(W)
qdel(src)
user.put_in_hands(newSaber)
else if(istype(W, /obj/item/device/multitool))
if(hacked == 0)
hacked = 1
if(istype(W, /obj/item/device/multitool))
if(!hacked)
hacked = TRUE
item_color = "rainbow"
to_chat(user, "<span class='warning'>RNBW_ENGAGE</span>")
@@ -253,14 +243,12 @@
sharpness = IS_SHARP
//Most of the other special functions are handled in their own files. aka special snowflake code so kewl
/obj/item/weapon/melee/energy/blade/New()
/obj/item/weapon/melee/energy/blade/Initialize()
. = ..()
spark_system = new /datum/effect_system/spark_spread()
spark_system.set_up(5, 0, src)
spark_system.attach(src)
/obj/item/weapon/melee/energy/blade/dropped()
..()
/obj/item/weapon/melee/energy/blade/attack_self(mob/user)
return
@@ -1,3 +1,7 @@
#define PCANNON_FIREALL 1
#define PCANNON_FILO 2
#define PCANNON_FIFO 3
/obj/item/weapon/pneumatic_cannon
name = "pneumatic cannon"
desc = "A gas-powered cannon that can fire any object loaded into it."
@@ -16,7 +20,15 @@
var/gasPerThrow = 3 //How much gas is drawn from a tank's pressure to fire
var/list/loadedItems = list() //The items loaded into the cannon that will be fired out
var/pressureSetting = 1 //How powerful the cannon is - higher pressure = more gas but more powerful throws
var/checktank = TRUE
var/range_multiplier = 1
var/throw_amount = 20 //How many items to throw per fire
var/fire_mode = PCANNON_FIREALL
var/automatic = FALSE
var/clumsyCheck = TRUE
/obj/item/weapon/pneumatic_cannon/CanItemAutoclick()
return automatic
/obj/item/weapon/pneumatic_cannon/examine(mob/user)
..()
@@ -30,6 +42,8 @@
/obj/item/weapon/pneumatic_cannon/attackby(obj/item/weapon/W, mob/user, params)
if(user.a_intent == INTENT_HARM)
return ..()
if(istype(W, /obj/item/weapon/tank/internals))
if(!tank)
var/obj/item/weapon/tank/internals/IT = W
@@ -55,19 +69,31 @@
to_chat(user, "<span class='warning'>\The [src] can't hold any more items!</span>")
else if(istype(W, /obj/item))
var/obj/item/IW = W
if((loadedWeightClass + IW.w_class) > maxWeightClass)
to_chat(user, "<span class='warning'>\The [IW] won't fit into \the [src]!</span>")
return
if(IW.w_class > src.w_class)
to_chat(user, "<span class='warning'>\The [IW] is too large to fit into \the [src]!</span>")
return
if(!user.transferItemToLoc(W, src))
return
to_chat(user, "<span class='notice'>You load \the [IW] into \the [src].</span>")
loadedItems.Add(IW)
loadedWeightClass += IW.w_class
load_item(IW, user)
/obj/item/weapon/pneumatic_cannon/proc/can_load_item(obj/item/I, mob/user)
if((loadedWeightClass + I.w_class) > maxWeightClass) //Only make messages if there's a user
if(user)
to_chat(user, "<span class='warning'>\The [I] won't fit into \the [src]!</span>")
return FALSE
if(I.w_class > w_class)
if(user)
to_chat(user, "<span class='warning'>\The [I] is too large to fit into \the [src]!</span>")
return FALSE
return TRUE
/obj/item/weapon/pneumatic_cannon/proc/load_item(obj/item/I, mob/user)
if(!can_load_item(I, user))
return FALSE
if(user) //Only use transfer proc if there's a user, otherwise just set loc.
if(!user.transferItemToLoc(I, src))
return FALSE
to_chat(user, "<span class='notice'>You load \the [I] into \the [src].</span>")
else
I.forceMove(src)
loadedItems += I
loadedWeightClass += I.w_class
return TRUE
/obj/item/weapon/pneumatic_cannon/afterattack(atom/target, mob/living/carbon/human/user, flag, params)
if(flag && user.a_intent == INTENT_HARM) //melee attack
@@ -76,7 +102,6 @@
return
Fire(user, target)
/obj/item/weapon/pneumatic_cannon/proc/Fire(mob/living/carbon/human/user, var/atom/target)
if(!istype(user) && !target)
return
@@ -90,13 +115,13 @@
if(!loadedItems || !loadedWeightClass)
to_chat(user, "<span class='warning'>\The [src] has nothing loaded.</span>")
return
if(!tank)
if(!tank && checktank)
to_chat(user, "<span class='warning'>\The [src] can't fire without a source of gas.</span>")
return
if(tank && !tank.air_contents.remove(gasPerThrow * pressureSetting))
to_chat(user, "<span class='warning'>\The [src] lets out a weak hiss and doesn't react!</span>")
return
if(user.disabilities & CLUMSY && prob(75))
if(user.disabilities & CLUMSY && prob(75) && clumsyCheck)
user.visible_message("<span class='warning'>[user] loses their grip on [src], causing it to go off!</span>", "<span class='userdanger'>[src] slips out of your hands and goes off!</span>")
user.drop_item()
if(prob(10))
@@ -109,17 +134,48 @@
user.visible_message("<span class='danger'>[user] fires \the [src]!</span>", \
"<span class='danger'>You fire \the [src]!</span>")
add_logs(user, target, "fired at", src)
var/turf/T = get_target(target, get_turf(src))
playsound(src.loc, 'sound/weapons/sonic_jackhammer.ogg', 50, 1)
for(var/obj/item/ITD in loadedItems) //Item To Discharge
loadedItems.Remove(ITD)
loadedWeightClass -= ITD.w_class
ITD.throw_speed = pressureSetting * 2
ITD.loc = get_turf(src)
ITD.throw_at(target, pressureSetting * 5, pressureSetting * 2,user)
fire_items(T, user)
if(pressureSetting >= 3 && user)
user.visible_message("<span class='warning'>[user] is thrown down by the force of the cannon!</span>", "<span class='userdanger'>[src] slams into your shoulder, knocking you down!")
user.Weaken(3)
/obj/item/weapon/pneumatic_cannon/proc/fire_items(turf/target, mob/user)
if(fire_mode == PCANNON_FIREALL)
for(var/obj/item/ITD in loadedItems) //Item To Discharge
if(!throw_item(target, ITD, user))
break
else
for(var/i in 1 to throw_amount)
if(!loadedItems.len)
break
var/obj/item/I
if(fire_mode == PCANNON_FILO)
I = loadedItems[loadedItems.len]
else
I = loadedItems[1]
if(!throw_item(target, I, user))
break
/obj/item/weapon/pneumatic_cannon/proc/throw_item(turf/target, obj/item/I, mob/user)
if(!istype(I))
return FALSE
loadedItems -= I
loadedWeightClass -= I.w_class
I.forceMove(get_turf(src))
I.throw_at(target, pressureSetting * 10 * range_multiplier, pressureSetting * 2, user)
return TRUE
/obj/item/weapon/pneumatic_cannon/proc/get_target(turf/target, turf/starting)
if(range_multiplier == 1)
return target
var/x_o = (target.x - starting.x)
var/y_o = (target.y - starting.y)
var/new_x = Clamp((starting.x + (x_o * range_multiplier)), 0, world.maxx)
var/new_y = Clamp((starting.y + (y_o * range_multiplier)), 0, world.maxy)
var/turf/newtarget = locate(new_x, new_y, starting.z)
return newtarget
/obj/item/weapon/pneumatic_cannon/ghetto //Obtainable by improvised methods; more gas per use, less capacity, but smaller
name = "improvised pneumatic cannon"
@@ -164,3 +220,35 @@
return
add_overlay(tank.icon_state)
src.update_icon()
/obj/item/weapon/pneumatic_cannon/proc/fill_with_type(type, amount)
if(!ispath(type, /obj/item))
return FALSE
var/loaded = 0
for(var/i in 1 to amount)
var/obj/item/I = new type
if(!load_item(I, null))
qdel(I)
return loaded
loaded++
CHECK_TICK
return loaded
/obj/item/weapon/pneumatic_cannon/pie
name = "pie cannon"
desc = "Load cream pie for optimal results"
force = 10
icon_state = "piecannon"
gasPerThrow = 0
checktank = FALSE
range_multiplier = 3
fire_mode = PCANNON_FIFO
throw_amount = 1
maxWeightClass = 100 //50 pies. :^)
clumsyCheck = FALSE
/obj/item/weapon/pneumatic_cannon/pie/can_load_item(obj/item/I, mob/user)
if(istype(I, /obj/item/weapon/reagent_containers/food/snacks/pie))
return ..()
to_chat(user, "<span class='warning'>[src] only accepts pies!</span>")
return FALSE
@@ -0,0 +1,48 @@
//////////////////////////////////
//dakimakuras
//////////////////////////////////
/obj/item/weapon/storage/daki
name = "dakimakura"
desc = "A large pillow depicting a girl in a compromising position. Featuring as many dimensions as you."
icon = 'icons/obj/daki.dmi'
icon_state = "daki_base"
slot_flags = SLOT_BACK
storage_slots = 3
w_class = 4
max_w_class = 3
max_combined_w_class = 21
var/cooldowntime = 20
var/static/list/dakimakura_options = list("Callie","Casca","Chaika","Elisabeth","Foxy Grandpa","Haruko","Holo","Ian","Jolyne","Kurisu","Marie","Mugi","Nar'Sie","Patchouli","Plutia","Rei","Reisen","Naga","Squid","Squigly","Tomoko","Toriel","Umaru","Yaranaika","Yoko") //Kurisu is the ideal girl." - Me, Logos.
/obj/item/weapon/storage/daki/attack_self(mob/living/user)
var/body_choice
var/custom_name
if(icon_state == "daki_base")
body_choice = input("Pick a body.") in dakimakura_options
icon_state = "daki_[body_choice]"
custom_name = stripped_input(user, "What's her name?")
if(length(custom_name) > MAX_NAME_LEN)
to_chat(user,"<span class='danger'>Name is too long!</span>")
return FALSE
if(custom_name)
name = custom_name
desc = "A large pillow depicting [custom_name] in a compromising position. Featuring as many dimensions as you."
else
switch(user.a_intent)
if(INTENT_HELP)
user.visible_message("<span class='notice'>[user] hugs the [name].</span>")
playsound(src, "rustle", 50, 1, -5)
if(INTENT_DISARM)
user.visible_message("<span class='notice'>[user] kisses the [name].</span>")
playsound(src, "rustle", 50, 1, -5)
if(INTENT_GRAB)
user.visible_message("<span class='warning'>[user] holds the [name]!</span>")
playsound(src, 'sound/items/bikehorn.ogg', 50, 1)
if(INTENT_HARM)
user.visible_message("<span class='danger'>[user] punches the [name]!</span>")
playsound(src, 'sound/effects/shieldbash.ogg', 50, 1)
user.changeNext_move(CLICK_CD_MELEE)
////////////////////////////
@@ -5,10 +5,6 @@
w_class = WEIGHT_CLASS_BULKY
rustle_jimmies = FALSE
/obj/item/weapon/storage/internal/ClickAccessible(mob/user, depth=1)
if(loc)
return loc.ClickAccessible(user, depth)
/obj/item/weapon/storage/internal/Adjacent(A)
if(loc)
return loc.Adjacent(A)
@@ -38,7 +38,7 @@
return
// this must come before the screen objects only block, dunno why it wasn't before
if(over_object == M && (src.ClickAccessible(M, depth=STORAGE_VIEW_DEPTH) || Adjacent(M)))
if(over_object == M && M.CanReach(src,view_only = TRUE))
orient2hud(M)
if(M.s_active)
M.s_active.close(M)
@@ -92,8 +92,7 @@
new /obj/item/pizzabox/bomb
if("darklord") //20 tc + tk + summon item close enough for now
new /obj/item/weapon/melee/energy/sword/saber(src)
new /obj/item/weapon/melee/energy/sword/saber(src)
new /obj/item/weapon/twohanded/dualsaber(src)
new /obj/item/weapon/dnainjector/telemut/darkbundle(src)
new /obj/item/clothing/suit/hooded/chaplain_hoodie(src)
new /obj/item/weapon/card/id/syndicate(src)
@@ -219,8 +218,8 @@
new /obj/item/weapon/reagent_containers/glass/bottle/polonium(src)
new /obj/item/weapon/reagent_containers/glass/bottle/venom(src)
new /obj/item/weapon/reagent_containers/glass/bottle/neurotoxin2(src)
new /obj/item/weapon/reagent_containers/glass/bottle/formaldehyde(src)
new /obj/item/weapon/reagent_containers/glass/bottle/spewium(src)
new /obj/item/weapon/reagent_containers/glass/bottle/formaldehyde(src)
new /obj/item/weapon/reagent_containers/glass/bottle/spewium(src)
new /obj/item/weapon/reagent_containers/glass/bottle/cyanide(src)
new /obj/item/weapon/reagent_containers/glass/bottle/histamine(src)
new /obj/item/weapon/reagent_containers/glass/bottle/initropidril(src)
@@ -297,3 +296,10 @@
/obj/item/weapon/storage/box/syndie_kit/mimery/PopulateContents()
new /obj/item/weapon/spellbook/oneuse/mimery_blockade(src)
new /obj/item/weapon/spellbook/oneuse/mimery_guns(src)
/obj/item/weapon/storage/box/syndie_kit/holoparasite
name = "box"
/obj/item/weapon/storage/box/syndie_kit/holoparasite/PopulateContents()
new /obj/item/weapon/guardiancreator/tech/choose/traitor(src)
new /obj/item/weapon/paper/guardian(src)
+2 -2
View File
@@ -262,11 +262,11 @@
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 70)
resistance_flags = FIRE_PROOF
var/hacked = 0
var/brightness_on = 6//TWICE AS BRIGHT AS A REGULAR ESWORD
var/brightness_on = 6 //TWICE AS BRIGHT AS A REGULAR ESWORD
var/list/possible_colors = list("red", "blue", "green", "purple")
/obj/item/weapon/twohanded/dualsaber/Initialize()
..()
. = ..()
if(LAZYLEN(possible_colors))
item_color = pick(possible_colors)
switch(item_color)
+11 -4
View File
@@ -390,7 +390,7 @@
desc = "A chainsaw that has replaced your arm."
icon_state = "chainsaw_on"
item_state = "mounted_chainsaw"
flags = NODROP | ABSTRACT
flags = NODROP | ABSTRACT | DROPDEL
w_class = WEIGHT_CLASS_HUGE
force = 21
throwforce = 0
@@ -400,10 +400,17 @@
attack_verb = list("sawed", "torn", "cut", "chopped", "diced")
hitsound = 'sound/weapons/chainsawhit.ogg'
/obj/item/weapon/mounted_chainsaw/dropped()
..()
/obj/item/weapon/mounted_chainsaw/Destroy()
var/obj/item/bodypart/part
new /obj/item/weapon/twohanded/required/chainsaw(get_turf(src))
qdel(src)
if(iscarbon(loc))
var/mob/living/carbon/holder = loc
var/index = holder.get_held_index_of_item(src)
if(index)
part = holder.hand_bodyparts[index]
. = ..()
if(part)
part.drop_limb()
/obj/item/weapon/statuebust
name = "bust"
@@ -106,6 +106,11 @@ LINEN BINS
icon_state = "sheetrd"
item_color = "director"
// for Free Golems.
/obj/item/weapon/bedsheet/rd/royal_cape
name = "Royal Cape of the Liberator"
desc = "Majestic."
/obj/item/weapon/bedsheet/medical
name = "medical blanket"
desc = "It's a sterilized* blanket commonly used in the Medbay. *Sterilization is voided if a virologist is present onboard the station."
@@ -11,6 +11,7 @@
else
new /obj/item/weapon/storage/backpack/satchel/cap(src)
new /obj/item/clothing/neck/cloak/cap(src)
new /obj/item/weapon/storage/daki(src)
new /obj/item/weapon/storage/backpack/dufflebag/captain(src)
new /obj/item/clothing/head/crown/fancy(src)
new /obj/item/clothing/suit/captunic(src)
+3 -2
View File
@@ -234,8 +234,9 @@
/obj/structure/falsewall/plasma/attackby(obj/item/weapon/W, mob/user, params)
if(W.is_hot() > 300)
message_admins("Plasma falsewall ignited by [key_name_admin(user)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) in ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
log_game("Plasma falsewall ignited by [key_name(user)] in ([x],[y],[z])")
var/turf/T = get_turf(src)
message_admins("Plasma falsewall ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_COORDJMP(T)]",0,1)
log_game("Plasma falsewall ignited by [key_name(user)] in [COORD(T)]")
burnbabyburn()
else
return ..()
@@ -188,8 +188,9 @@
/obj/structure/mineral_door/transparent/plasma/attackby(obj/item/weapon/W, mob/user, params)
if(W.is_hot())
message_admins("Plasma mineral door ignited by [key_name_admin(user)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) in ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
log_game("Plasma mineral door ignited by [key_name(user)] in ([x],[y],[z])")
var/turf/T = get_turf(src)
message_admins("Plasma mineral door ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_COORDJMP(T)]",0,1)
log_game("Plasma mineral door ignited by [key_name(user)] in [COORD(T)]")
TemperatureAct()
else
return ..()
+8 -6
View File
@@ -163,18 +163,20 @@
PlasmaBurn(500)
burn = TRUE
if(burn)
var/turf/T = get_turf(src)
if(Proj.firer)
message_admins("Plasma statue ignited by [key_name_admin(Proj.firer)](<A HREF='?_src_=holder;adminmoreinfo=\ref[Proj.firer]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[Proj.firer]'>FLW</A>) in ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
log_game("Plasma statue ignited by [key_name(Proj.firer)] in ([x],[y],[z])")
message_admins("Plasma statue ignited by [ADMIN_LOOKUPFLW(Proj.firer)] in [ADMIN_COORDJMP(T)]",0,1)
log_game("Plasma statue ignited by [key_name(Proj.firer)] in [COORD(T)]")
else
message_admins("Plasma statue ignited by [Proj]. No known firer.(<A HREF='?_src_=holder;adminmoreinfo=\ref[Proj.firer]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[Proj.firer]'>FLW</A>) in ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
log_game("Plasma statue ignited by [Proj] in ([x],[y],[z]). No known firer.")
message_admins("Plasma statue ignited by [Proj]. No known firer, in [ADMIN_COORDJMP(T)]",0,1)
log_game("Plasma statue ignited by [Proj] in [COORD(T)]. No known firer.")
..()
/obj/structure/statue/plasma/attackby(obj/item/weapon/W, mob/user, params)
if(W.is_hot() > 300)//If the temperature of the object is over 300, then ignite
message_admins("Plasma statue ignited by [key_name_admin(user)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) in ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
log_game("Plasma statue ignited by [key_name(user)] in ([x],[y],[z])")
var/turf/T = get_turf(src)
message_admins("Plasma statue ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_COORDJMP(T)]",0,1)
log_game("Plasma statue ignited by [key_name(user)] in [COORD(T)]")
ignite(W.is_hot())
else
return ..()
@@ -44,8 +44,8 @@
/turf/open/floor/mineral/plasma/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
if(W.is_hot() > 300)//If the temperature of the object is over 300, then ignite
message_admins("Plasma flooring was ignited by [key_name_admin(user)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) in ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
log_game("Plasma flooring was ignited by [key_name(user)] in ([x],[y],[z])")
message_admins("Plasma flooring was ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_COORDJMP(src)]",0,1)
log_game("Plasma flooring was ignited by [key_name(user)] in [COORD(src)]")
ignite(W.is_hot())
return
..()
+4 -4
View File
@@ -407,14 +407,14 @@
if(z != 5)
notify_admins = 1
if(!triggered_by_explosion)
message_admins("[key_name_admin(user)]<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A> (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) has triggered a gibtonite deposit reaction at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[bombturf.x];Y=[bombturf.y];Z=[bombturf.z]'>[A.name] (JMP)</a>.")
message_admins("[ADMIN_LOOKUPFLW(user)] has triggered a gibtonite deposit reaction at [A.name] [ADMIN_JMP(bombturf)].")
else
message_admins("An explosion has triggered a gibtonite deposit reaction at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[bombturf.x];Y=[bombturf.y];Z=[bombturf.z]'>[A.name] (JMP)</a>.")
message_admins("An explosion has triggered a gibtonite deposit reaction at [A.name] [ADMIN_JMP(bombturf)].")
if(!triggered_by_explosion)
log_game("[key_name(user)] has triggered a gibtonite deposit reaction at [A.name] ([A.x], [A.y], [A.z]).")
log_game("[key_name(user)] has triggered a gibtonite deposit reaction at [A.name] [ADMIN_JMP(bombturf)].")
else
log_game("An explosion has triggered a gibtonite deposit reaction at [A.name]([bombturf.x],[bombturf.y],[bombturf.z])")
log_game("An explosion has triggered a gibtonite deposit reaction at [A.name] [COORD(bombturf)]")
countdown(notify_admins)
@@ -101,8 +101,8 @@
/turf/closed/wall/mineral/plasma/attackby(obj/item/weapon/W, mob/user, params)
if(W.is_hot() > 300)//If the temperature of the object is over 300, then ignite
message_admins("Plasma wall ignited by [key_name_admin(user)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) in ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
log_game("Plasma wall ignited by [key_name(user)] in ([x],[y],[z])")
message_admins("Plasma wall ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_COORDJMP(src)]",0,1)
log_game("Plasma wall ignited by [key_name(user)] in [COORD(src)]")
ignite(W.is_hot())
return
..()
+4 -2
View File
@@ -9,6 +9,7 @@
icon_state = "sleeper"
state_open = TRUE
anchored = TRUE
occupant_typecache = list(/mob/living/carbon/human) // turned into typecache in Initialize
var/you_die_in_the_game_you_die_for_real = FALSE
var/datum/effect_system/spark_spread/sparks
var/mob/living/carbon/human/virtual_reality/vr_human
@@ -92,11 +93,12 @@
return
switch(action)
if("vr_connect")
if(ishuman(occupant) && occupant.mind)
var/mob/living/carbon/human/human_occupant = occupant
if(human_occupant && human_occupant.mind)
to_chat(occupant, "<span class='warning'>Transfering to virtual reality...</span>")
if(vr_human)
vr_human.revert_to_reality(FALSE, FALSE)
occupant.mind.transfer_to(vr_human)
human_occupant.mind.transfer_to(vr_human)
vr_human.real_me = occupant
to_chat(vr_human, "<span class='notice'>Transfer successful! you are now playing as [vr_human] in VR!</span>")
SStgui.close_user_uis(vr_human, src)
+5 -8
View File
@@ -71,16 +71,13 @@
computerid = bancid
ip = banip
var/datum/DBQuery/query_add_ban_get_id = SSdbcore.NewQuery("SELECT id FROM [format_table_name("player")] WHERE ckey = '[ckey]'")
if(!query_add_ban_get_id.warn_execute())
var/datum/DBQuery/query_add_ban_get_ckey = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ckey = '[ckey]'")
if(!query_add_ban_get_ckey.warn_execute())
return
var/validckey = 0
if(query_add_ban_get_id.NextRow())
validckey = 1
if(!validckey)
if(!query_add_ban_get_ckey.NextRow())
if(!banned_mob || (banned_mob && !IsGuestKey(banned_mob.key)))
message_admins("<font color='red'>[key_name_admin(usr)] attempted to ban [ckey], but [ckey] has not been seen yet. Please only ban actual players.</font>",1)
return
if(alert(usr, "[ckey] has not been seen before, are you sure you want to create a ban for them?", "Unknown ckey", "Yes", "No", "Cancel") != "Yes")
return
var/a_ckey
var/a_computerid
+1 -1
View File
@@ -63,7 +63,7 @@
if(!SSdbcore.Connect())
log_world("Ban database connection failure. Key [ckeytext] not checked")
GLOB.diary << "Ban database connection failure. Key [ckeytext] not checked"
GLOB.world_game_log << "Ban database connection failure. Key [ckeytext] not checked"
return
var/ipquery = ""
+6 -1
View File
@@ -37,6 +37,11 @@
else
body += " \[<A href='?_src_=holder;revive=\ref[M]'>Heal</A>\] "
if(M.client)
body += "<br>\[<b>First Seen:</b> [M.client.player_join_date]\]\[<b>Byond account registered on:</b> [M.client.account_join_date]\]"
body += "<br><br>\[ "
body += "<a href='?_src_=vars;Vars=\ref[M]'>VV</a> - "
body += "<a href='?_src_=holder;traitor=\ref[M]'>TP</a> - "
@@ -804,7 +809,7 @@
return 1
/client/proc/adminGreet(logout)
if(SSticker.HasRoundStarted())
if(SSticker.HasRoundStarted())
var/string
if(logout && config && config.announce_admin_logout)
string = pick(
+11 -40
View File
@@ -1,50 +1,21 @@
//By Carnwennan
//This system was made as an alternative to all the in-game lists and variables used to log stuff in-game.
//lists and variables are great. However, they have several major flaws:
//Firstly, they use memory. TGstation has one of the highest memory usage of all the ss13 branches.
//Secondly, they are usually stored in an object. This means that they aren't centralised. It also means that
//the data is lost when the object is deleted! This is especially annoying for things like the singulo engine!
#define INVESTIGATE_DIR "data/investigate/"
//SYSTEM
/proc/investigate_subject2file(subject)
return file("[INVESTIGATE_DIR][subject].html")
/proc/investigate_reset()
if(fdel(INVESTIGATE_DIR))
return 1
return 0
/atom/proc/investigate_log(message, subject)
if(!message)
return
var/F = investigate_subject2file(subject)
if(!F)
atom/proc/investigate_log(message, subject)
if(!message || !subject)
return
var/F = file("[GLOB.log_directory]/[subject].html")
F << "<small>[time_stamp()] \ref[src] ([x],[y],[z])</small> || [src] [message]<br>"
//ADMINVERBS
/client/proc/investigate_show( subject in list("hrefs","notes, memos, watchlist","singulo","wires","telesci", "gravity", "records", "cargo", "supermatter", "atmos", "experimentor", "botany") )
/client/proc/investigate_show( subject in list("hrefs","notes, memos, watchlist","singulo","wires","telesci", "gravity", "records", "cargo", "supermatter", "atmos", "experimentor", "botany") )
set name = "Investigate"
set category = "Admin"
if(!holder)
return
switch(subject)
if("singulo", "wires", "telesci", "gravity", "records", "cargo", "supermatter", "atmos", "botany") //general one-round-only stuff
var/F = investigate_subject2file(subject)
if(!F)
to_chat(src, "<font color='red'>Error: admin_investigate: [INVESTIGATE_DIR][subject] is an invalid path or cannot be accessed.</font>")
return
src << browse(F,"window=investigate[subject];size=800x300")
if("hrefs") //persistent logs and stuff
if(GLOB.href_logfile)
src << browse(GLOB.href_logfile,"window=investigate[subject];size=800x300")
else if(!config.log_hrefs)
to_chat(src, "<span class='danger'>Href logging is off and no logfile was found.</span>")
return
else
to_chat(src, "<span class='danger'>No href logfile was found.</span>")
return
if("notes, memos, watchlist")
browse_messages()
else
var/F = file("[GLOB.log_directory]/[subject].html")
if(!fexists(F))
to_chat(src, "<span class='danger'>No [subject] logfile was found.</span>")
return
src << browse(F,"window=investigate[subject];size=800x300")
+2 -2
View File
@@ -127,7 +127,7 @@ GLOBAL_PROTECT(admin_ranks)
else
if(!SSdbcore.Connect())
log_world("Failed to connect to database in load_admin_ranks(). Reverting to legacy system.")
GLOB.diary << "Failed to connect to database in load_admin_ranks(). Reverting to legacy system."
GLOB.world_game_log << "Failed to connect to database in load_admin_ranks(). Reverting to legacy system."
config.admin_legacy_system = 1
load_admin_ranks()
return
@@ -202,7 +202,7 @@ GLOBAL_PROTECT(admin_ranks)
else
if(!SSdbcore.Connect())
log_world("Failed to connect to database in load_admins(). Reverting to legacy system.")
GLOB.diary << "Failed to connect to database in load_admins(). Reverting to legacy system."
GLOB.world_game_log << "Failed to connect to database in load_admins(). Reverting to legacy system."
config.admin_legacy_system = 1
load_admins()
return
+2 -36
View File
@@ -4,18 +4,12 @@ GLOBAL_PROTECT(admin_verbs_default)
GLOBAL_LIST_INIT(admin_verbs_default, world.AVerbsDefault())
/world/proc/AVerbsDefault()
return list(
/client/proc/toggleadminhelpsound, /*toggles whether we hear a sound when adminhelps/PMs are used*/
/client/proc/toggleannouncelogin, /*toggles if an admin's login is announced during a round*/
/client/proc/deadmin, /*destroys our own admin datum so we can play as a regular player*/
/client/proc/cmd_admin_say, /*admin-only ooc chat*/
/client/proc/hide_verbs, /*hides all our adminverbs*/
/client/proc/hide_most_verbs, /*hides all our hideable adminverbs*/
/client/proc/debug_variables, /*allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify*/
/client/proc/deadchat, /*toggles deadchat on/off*/
/client/proc/dsay, /*talk in deadchat using our ckey/fakekey*/
/client/proc/toggleprayers, /*toggles prayers on/off*/
/client/verb/toggleprayersounds, /*Toggles prayer sounds (HALLELUJAH!)*/
/client/proc/toggle_hear_radio, /*toggles whether we hear the radio*/
/client/proc/investigate_show, /*various admintools for investigation. Such as a singulo grief-log*/
/client/proc/secrets,
/client/proc/restart_controller,
@@ -32,7 +26,6 @@ GLOBAL_PROTECT(admin_verbs_admin)
GLOBAL_LIST_INIT(admin_verbs_admin, world.AVerbsAdmin())
/world/proc/AVerbsAdmin()
return list(
/client/proc/player_panel_new, /*shows an interface for all players, with links to various panels*/
/client/proc/invisimin, /*allows our mob to go invisible/visible*/
// /datum/admins/proc/show_traitor_panel, /*interface which shows a mob's mind*/ -Removed due to rare practical use. Moved to debug verbs ~Errorage
/datum/admins/proc/show_player_panel, /*shows an interface for individual players, with various links (links require additional flags*/
@@ -46,16 +39,14 @@ GLOBAL_LIST_INIT(admin_verbs_admin, world.AVerbsAdmin())
/datum/admins/proc/set_admin_notice,/*announcement all clients see when joining the server.*/
/client/proc/admin_ghost, /*allows us to ghost/reenter body at will*/
/client/proc/toggle_view_range, /*changes how far we can see*/
/datum/admins/proc/view_txt_log, /*shows the server log (diary) for today*/
/datum/admins/proc/view_txt_log, /*shows the server log (world_game_log) for today*/
/datum/admins/proc/view_atk_log, /*shows the server combat-log, doesn't do anything presently*/
/client/proc/cmd_admin_subtle_message, /*send an message to somebody as a 'voice in their head'*/
/client/proc/cmd_admin_delete, /*delete an instance/object/mob/etc*/
/client/proc/cmd_admin_check_contents, /*displays the contents of an instance*/
/client/proc/check_antagonists, /*shows all antags*/
/datum/admins/proc/access_news_network, /*allows access of newscasters*/
/client/proc/giveruntimelog, /*allows us to give access to runtime logs to somebody*/
/client/proc/getruntimelog, /*allows us to access runtime logs to somebody*/
/client/proc/getserverlog, /*allows us to fetch server logs (diary) for other days*/
/client/proc/getserverlog, /*allows us to fetch server logs (world_game_log) for other days*/
/client/proc/jumptocoord, /*we ghost and jump to a coordinate*/
/client/proc/Getmob, /*teleports a mob to our location*/
/client/proc/Getkey, /*teleports a mob with a certain ckey to our location*/
@@ -116,7 +107,6 @@ GLOBAL_LIST_INIT(admin_verbs_server, world.AVerbsServer())
/datum/admins/proc/end_round,
/datum/admins/proc/delay,
/datum/admins/proc/toggleaban,
/client/proc/toggle_log_hrefs,
/client/proc/everyone_random,
/datum/admins/proc/toggleAI,
/client/proc/cmd_admin_delete, /*delete an instance/object/mob/etc*/
@@ -182,9 +172,6 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
/client/proc/set_ooc,
/client/proc/reset_ooc,
/client/proc/deadmin,
/client/proc/deadchat,
/client/proc/toggleprayers,
/client/proc/toggle_hear_radio,
/datum/admins/proc/show_traitor_panel,
/datum/admins/proc/toggleenter,
/datum/admins/proc/toggleguests,
@@ -223,7 +210,6 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
/datum/admins/proc/restart,
/datum/admins/proc/delay,
/datum/admins/proc/toggleaban,
/client/proc/toggle_log_hrefs,
/client/proc/everyone_random,
/datum/admins/proc/toggleAI,
/client/proc/restart_controller,
@@ -398,13 +384,6 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
mob.invisibility = INVISIBILITY_OBSERVER
to_chat(mob, "<span class='adminnotice'><b>Invisimin on. You are now as invisible as a ghost.</b></span>")
/client/proc/player_panel_new()
set name = "Player Panel"
set category = "Admin"
if(holder)
holder.player_panel_new()
SSblackbox.add_details("admin_verb","Player Panel New") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/check_antagonists()
set name = "Check Antagonists"
set category = "Admin"
@@ -638,19 +617,6 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
togglebuildmode(src.mob)
SSblackbox.add_details("admin_verb","Toggle Build Mode") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/toggle_log_hrefs()
set name = "Toggle href logging"
set category = "Server"
if(!holder)
return
if(config)
if(config.log_hrefs)
config.log_hrefs = 0
to_chat(src, "<b>Stopped logging hrefs</b>")
else
config.log_hrefs = 1
to_chat(src, "<b>Started logging hrefs</b>")
/client/proc/check_ai_laws()
set name = "Check AI Laws"
set category = "Admin"
+11
View File
@@ -0,0 +1,11 @@
/datum/menu/Admin/Generate_list(client/C)
if (C.holder)
. = ..()
/datum/menu/Admin/verb/playerpanel()
set name = "Player Panel"
set desc = "Player Panel"
set category = "Admin"
usr.client.holder.player_panel_new()
SSblackbox.add_details("admin_verb","Player Panel New") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
+7 -26
View File
@@ -71,7 +71,7 @@
if("select", "delete", "update")
select_types = query_tree[query_tree[1]]
from_objs = SDQL_from_objs(query_tree["from"])
from_objs = world.SDQL_from_objs(query_tree["from"])
var/list/objs = list()
@@ -101,7 +101,7 @@
if("call")
for(var/datum/d in objs)
try
SDQL_var(d, query_tree["call"][1], source = d)
world.SDQL_var(d, query_tree["call"][1], source = d)
catch(var/exception/e)
runtime_tracker += SDQL_parse_exception(e)
runtimes++
@@ -177,15 +177,6 @@
returning += "Description: [E.desc]<BR>"
return returning
/proc/SDQL_callproc_global(procname,args_list)
set waitfor = FALSE
WrapAdminProcCall(GLOBAL_PROC, procname, args_list)
/proc/SDQL_callproc(thing, procname, args_list)
set waitfor = FALSE
if(hascall(thing, procname))
WrapAdminProcCall(thing, procname, args_list)
/proc/SDQL_parse(list/query_list)
var/datum/SDQL_parser/parser = new()
var/list/querys = list()
@@ -249,15 +240,10 @@
/proc/SDQL_from_objs(list/tree)
/world/proc/SDQL_from_objs(list/tree)
if("world" in tree)
if(IsAdminAdvancedProcCall())
var/msg = "WARNING: Attempt to retrieve world reference made by [usr]!"
log_admin(msg)
message_admins(msg)
return
return world
return SDQL_expression(world, tree)
return src
return SDQL_expression(src, tree)
/proc/SDQL_get_all(type, location)
var/list/out = list()
@@ -417,12 +403,12 @@
result = dummy
val += result
else
val = SDQL_var(object, expression, i, object)
val = world.SDQL_var(object, expression, i, object)
i = expression.len
return list("val" = val, "i" = i)
/proc/SDQL_var(datum/object, list/expression, start = 1, source)
/world/proc/SDQL_var(datum/object, list/expression, start = 1, source)
var/v
var/long = start < expression.len
if(object == world && long && expression[start + 1] == ".")
@@ -456,11 +442,6 @@
else
return null
if("world")
if(IsAdminAdvancedProcCall())
var/msg = "WARNING: Attempt to retrieve world reference made by [usr]!"
log_admin(msg)
message_admins(msg)
return
v = world
if("global")
v = GLOB
+1 -1
View File
@@ -479,7 +479,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
current_ticket.MessageNoRecipient(msg)
current_ticket.TimeoutVerb()
return
else
else
to_chat(usr, "<span class='warning'>Ticket not found, creating new one...</span>")
else
current_ticket.AddInteraction("[key_name_admin(usr)] opened a new ticket.")
+55
View File
@@ -0,0 +1,55 @@
diff a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm (rejected hunks)
@@ -67,7 +67,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
for(var/I in l2b)
var/datum/admin_help/AH = I
dat += "<span class='adminnotice'><span class='adminhelp'>Ticket #[AH.id]</span>: <A HREF='?_src_=holder;ahelp=\ref[AH];ahelp_action=ticket'>[AH.initiator_key_name]: [AH.name]</A></span><br>"
-
+
usr << browse(dat.Join(), "window=ahelp_list[state];size=600x480")
//Tickets statpanel
@@ -253,7 +253,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
if(state == AHELP_ACTIVE)
to_chat(usr, "<span class='warning'>This ticket is already open.</span>")
return
-
+
if(GLOB.ahelp_tickets.CKey2ActiveTicket(initiator_ckey))
to_chat(usr, "<span class='warning'>This user already has an active ticket, cannot reopen this one.</span>")
return
@@ -310,7 +310,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
RemoveActive()
state = AHELP_RESOLVED
GLOB.ahelp_tickets.ListInsert(src)
-
+
if(initiator)
initiator.giveadminhelpverb()
@@ -325,7 +325,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
/datum/admin_help/proc/Reject(key_name = key_name_admin(usr))
if(state != AHELP_ACTIVE)
return
-
+
if(initiator)
initiator.giveadminhelpverb()
@@ -494,7 +494,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
if(!check_rights(R_ADMIN, TRUE))
return
-
+
var/browse_to
switch(input("Display which ticket list?") as null|anything in list("Active Tickets", "Closed Tickets", "Resolved Tickets"))
@@ -506,7 +506,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
browse_to = AHELP_RESOLVED
else
return
-
+
GLOB.ahelp_tickets.BrowseTickets(browse_to)
//
+6 -65
View File
@@ -1,62 +1,3 @@
/*
HOW DO I LOG RUNTIMES?
Firstly, start dreamdeamon if it isn't already running. Then select "world>Log Session" (or press the F3 key)
navigate the popup window to the data/logs/runtimes/ folder from where your tgstation .dmb is located.
(you may have to make this folder yourself)
OPTIONAL: you can select the little checkbox down the bottom to make dreamdeamon save the log everytime you
start a world. Just remember to repeat these steps with a new name when you update to a new revision!
Save it with the name of the revision your server uses (e.g. r3459.txt).
Game Masters will now be able to grant access any runtime logs you have archived this way!
This will allow us to gather information on bugs across multiple servers and make maintaining the TG
codebase for the entire /TG/station commuity a TONNE easier :3 Thanks for your help!
*/
//This proc allows Game Masters to grant a client access to the .getruntimelog verb
//Permissions expire at the end of each round.
//Runtimes can be used to meta or spot game-crashing exploits so it's advised to only grant coders that
//you trust access. Also, it may be wise to ensure that they are not going to play in the current round.
/client/proc/giveruntimelog()
set name = ".giveruntimelog"
set desc = "Give somebody access to any session logfiles saved to the /log/runtime/ folder."
set category = null
if(!src.holder)
to_chat(src, "<font color='red'>Only Admins may use this command.</font>")
return
var/client/target = input(src,"Choose somebody to grant access to the server's runtime logs (permissions expire at the end of each round):","Grant Permissions",null) as null|anything in GLOB.clients
if(!istype(target,/client))
to_chat(src, "<font color='red'>Error: giveruntimelog(): Client not found.</font>")
return
target.verbs |= /client/proc/getruntimelog
to_chat(target, "<font color='red'>You have been granted access to runtime logs. Please use them responsibly or risk being banned.</font>")
return
//This proc allows download of runtime logs saved within the data/logs/ folder by dreamdeamon.
//It works similarly to show-server-log.
/client/proc/getruntimelog()
set name = ".getruntimelog"
set desc = "Retrieve any session logfiles saved by dreamdeamon."
set category = null
var/path = browse_files("data/logs/runtimes/")
if(!path)
return
if(file_spam_check())
return
message_admins("[key_name_admin(src)] accessed file: [path]")
src << ftp(file(path))
to_chat(src, "Attempting to send file, this may take a fair few minutes if the file is very large.")
return
//This proc allows download of past server logs saved within the data/logs/ folder.
//It works similarly to show-server-log.
/client/proc/getserverlog()
@@ -83,10 +24,10 @@
/datum/admins/proc/view_txt_log()
set category = "Admin"
set name = "Show Server Log"
set desc = "Shows today's server log."
set desc = "Shows server log for this round."
if(fexists("[GLOB.diary]"))
src << ftp(GLOB.diary)
if(fexists("[GLOB.world_game_log]"))
src << ftp(GLOB.world_game_log)
else
to_chat(src, "<font color='red'>Server log not found, try using .getserverlog.</font>")
return
@@ -97,10 +38,10 @@
/datum/admins/proc/view_atk_log()
set category = "Admin"
set name = "Show Server Attack Log"
set desc = "Shows today's server attack log."
set desc = "Shows server attack log for this round."
if(fexists("[GLOB.diaryofmeanpeople]"))
src << ftp(GLOB.diaryofmeanpeople)
if(fexists("[GLOB.world_attack_log]"))
src << ftp(GLOB.world_attack_log)
else
to_chat(src, "<font color='red'>Server attack log not found, try using .getserverlog.</font>")
return
@@ -19,7 +19,7 @@
usr.client.images += preview
if(alert(usr,"Confirm location.","Template Confirm","Yes","No") == "Yes")
if(template.load(T, centered = TRUE))
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has placed a map template ([template.name]) at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>(JMP)</a></span>")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has placed a map template ([template.name]) at [ADMIN_COORDJMP(T)]</span>")
else
to_chat(usr, "Failed to place map")
usr.client.images -= preview

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