Merge branch 'master' into mirror-38933
This commit is contained in:
@@ -102,20 +102,20 @@
|
||||
return FALSE
|
||||
data.network_id = src
|
||||
log_data_transfer(data)
|
||||
var/list/datum/component/ntnet_interface/recieving = list()
|
||||
var/list/datum/component/ntnet_interface/receiving = list()
|
||||
if((length(data.recipient_ids == 1) && data.recipient_ids[1] == NETWORK_BROADCAST_ID) || data.recipient_ids == NETWORK_BROADCAST_ID)
|
||||
data.broadcast = TRUE
|
||||
for(var/i in connected_interfaces_by_id)
|
||||
recieving |= connected_interfaces_by_id[i]
|
||||
receiving |= connected_interfaces_by_id[i]
|
||||
else
|
||||
for(var/i in data.recipient_ids)
|
||||
var/datum/component/ntnet_interface/reciever = find_interface_id(i)
|
||||
recieving |= reciever
|
||||
var/datum/component/ntnet_interface/receiver = find_interface_id(i)
|
||||
receiving |= receiver
|
||||
|
||||
for(var/i in recieving)
|
||||
var/datum/component/ntnet_interface/reciever = i
|
||||
if(reciever)
|
||||
reciever.__network_recieve(data)
|
||||
for(var/i in receiving)
|
||||
var/datum/component/ntnet_interface/receiver = i
|
||||
if(receiver)
|
||||
receiver.__network_receive(data)
|
||||
|
||||
for(var/i in services_by_id)
|
||||
var/datum/ntnet_service/serv = services_by_id[i]
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
idle_power_usage = 100
|
||||
icon = 'icons/obj/machines/telecomms.dmi'
|
||||
icon_state = "bus"
|
||||
anchored = TRUE
|
||||
density = TRUE
|
||||
circuit = /obj/item/circuitboard/machine/ntnet_relay
|
||||
var/datum/ntnet/NTNet = null // This is mostly for backwards reference and to allow varedit modifications from ingame.
|
||||
|
||||
+23
-20
@@ -1,47 +1,50 @@
|
||||
|
||||
|
||||
/mob/living/carbon/human/virtual_reality
|
||||
var/mob/living/carbon/human/real_me //The human controlling us, can be any human (including virtual ones... inception...)
|
||||
var/datum/mind/real_mind // where is my mind t. pixies
|
||||
var/obj/machinery/vr_sleeper/vr_sleeper
|
||||
var/datum/action/quit_vr/quit_action
|
||||
|
||||
|
||||
/mob/living/carbon/human/virtual_reality/Initialize()
|
||||
. = ..()
|
||||
quit_action = new()
|
||||
quit_action.Grant(src)
|
||||
|
||||
|
||||
/mob/living/carbon/human/virtual_reality/death()
|
||||
revert_to_reality()
|
||||
..()
|
||||
|
||||
|
||||
/mob/living/carbon/human/virtual_reality/Destroy()
|
||||
revert_to_reality()
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/virtual_reality/Life()
|
||||
. = ..()
|
||||
if(real_mind)
|
||||
var/mob/living/real_me = real_mind.current
|
||||
if (real_me && real_me.stat == CONSCIOUS)
|
||||
return
|
||||
revert_to_reality(FALSE)
|
||||
|
||||
/mob/living/carbon/human/virtual_reality/ghostize()
|
||||
stack_trace("Ghostize was called on a virtual reality mob")
|
||||
|
||||
/mob/living/carbon/human/virtual_reality/ghost()
|
||||
set category = "OOC"
|
||||
set name = "Ghost"
|
||||
set desc = "Relinquish your life and enter the land of the dead."
|
||||
var/mob/living/carbon/human/H = real_me
|
||||
revert_to_reality(FALSE, FALSE)
|
||||
if(H)
|
||||
H.ghost()
|
||||
revert_to_reality(FALSE)
|
||||
|
||||
|
||||
/mob/living/carbon/human/virtual_reality/proc/revert_to_reality(refcleanup = TRUE, deathchecks = TRUE)
|
||||
if(real_me && mind)
|
||||
mind.transfer_to(real_me)
|
||||
if(deathchecks && vr_sleeper && vr_sleeper.you_die_in_the_game_you_die_for_real)
|
||||
real_me.death(0)
|
||||
if(refcleanup)
|
||||
/mob/living/carbon/human/virtual_reality/proc/revert_to_reality(deathchecks = TRUE)
|
||||
if(real_mind && mind)
|
||||
real_mind.current.ckey = ckey
|
||||
real_mind.current.stop_sound_channel(CHANNEL_HEARTBEAT)
|
||||
if(deathchecks && vr_sleeper)
|
||||
if(vr_sleeper.you_die_in_the_game_you_die_for_real)
|
||||
to_chat(real_mind, "<span class='warning'>You feel everything fading away...</span>")
|
||||
real_mind.current.death(0)
|
||||
if(deathchecks && vr_sleeper)
|
||||
vr_sleeper.vr_human = null
|
||||
vr_sleeper = null
|
||||
real_me = null
|
||||
|
||||
real_mind = null
|
||||
|
||||
/datum/action/quit_vr
|
||||
name = "Quit Virtual Reality"
|
||||
@@ -52,6 +55,6 @@
|
||||
if(..())
|
||||
if(istype(owner, /mob/living/carbon/human/virtual_reality))
|
||||
var/mob/living/carbon/human/virtual_reality/VR = owner
|
||||
VR.revert_to_reality(FALSE, FALSE)
|
||||
VR.revert_to_reality(FALSE)
|
||||
else
|
||||
Remove(owner)
|
||||
|
||||
@@ -8,35 +8,33 @@
|
||||
icon = 'icons/obj/machines/sleeper.dmi'
|
||||
icon_state = "sleeper"
|
||||
state_open = TRUE
|
||||
anchored = TRUE
|
||||
occupant_typecache = list(/mob/living/carbon/human) // turned into typecache in Initialize
|
||||
circuit = /obj/item/circuitboard/machine/vr_sleeper
|
||||
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
|
||||
var/static/list/available_vr_spawnpoints
|
||||
var/vr_category = "default" //Specific category of spawn points to pick from
|
||||
var/allow_creating_vr_humans = TRUE //So you can have vr_sleepers that always spawn you as a specific person or 1 life/chance vr games
|
||||
var/outfit = /datum/outfit/vr_basic
|
||||
var/only_current_user_can_interact = FALSE
|
||||
|
||||
/obj/machinery/vr_sleeper/Initialize()
|
||||
. = ..()
|
||||
sparks = new /datum/effect_system/spark_spread()
|
||||
sparks.set_up(2,0)
|
||||
sparks.attach(src)
|
||||
build_spawnpoints()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/vr_sleeper/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
/obj/machinery/vr_sleeper/attackby(obj/item/I, mob/user, params)
|
||||
if(!state_open && !occupant)
|
||||
if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-o", initial(icon_state), I))
|
||||
return
|
||||
if(default_change_direction_wrench(user, I))
|
||||
return
|
||||
if(occupant)
|
||||
ui_interact(user)
|
||||
else
|
||||
if(state_open)
|
||||
close_machine()
|
||||
else
|
||||
open_machine()
|
||||
if(default_pry_open(I))
|
||||
return
|
||||
if(default_deconstruction_crowbar(I))
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/machinery/vr_sleeper/relaymove(mob/user)
|
||||
open_machine()
|
||||
@@ -50,12 +48,18 @@
|
||||
QDEL_NULL(sparks)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/vr_sleeper/hugbox
|
||||
desc = "A sleeper modified to alter the subconscious state of the user, allowing them to visit virtual worlds. Seems slightly more secure."
|
||||
flags_1 = NODECONSTRUCT_1
|
||||
only_current_user_can_interact = TRUE
|
||||
|
||||
/obj/machinery/vr_sleeper/hugbox/emag_act(mob/user)
|
||||
return
|
||||
|
||||
/obj/machinery/vr_sleeper/emag_act(mob/user)
|
||||
you_die_in_the_game_you_die_for_real = TRUE
|
||||
sparks.start()
|
||||
addtimer(CALLBACK(src, .proc/emagNotify), 150)
|
||||
|
||||
/obj/machinery/vr_sleeper/update_icon()
|
||||
icon_state = "[initial(icon_state)][state_open ? "-open" : ""]"
|
||||
@@ -63,15 +67,15 @@
|
||||
/obj/machinery/vr_sleeper/open_machine()
|
||||
if(!state_open)
|
||||
if(vr_human)
|
||||
vr_human.revert_to_reality(FALSE, FALSE)
|
||||
vr_human.revert_to_reality(FALSE)
|
||||
if(occupant)
|
||||
SStgui.close_user_uis(occupant, src)
|
||||
..()
|
||||
|
||||
/obj/machinery/vr_sleeper/close_machine()
|
||||
..()
|
||||
if(occupant)
|
||||
ui_interact(occupant)
|
||||
/obj/machinery/vr_sleeper/MouseDrop_T(mob/target, mob/user)
|
||||
if(user.stat || user.lying || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser())
|
||||
return
|
||||
close_machine(target)
|
||||
|
||||
/obj/machinery/vr_sleeper/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
@@ -85,20 +89,21 @@
|
||||
switch(action)
|
||||
if("vr_connect")
|
||||
var/mob/living/carbon/human/human_occupant = occupant
|
||||
if(human_occupant && human_occupant.mind)
|
||||
if(human_occupant && human_occupant.mind && usr == occupant)
|
||||
to_chat(occupant, "<span class='warning'>Transferring to virtual reality...</span>")
|
||||
if(vr_human)
|
||||
vr_human.revert_to_reality(FALSE, FALSE)
|
||||
human_occupant.mind.transfer_to(vr_human)
|
||||
vr_human.real_me = occupant
|
||||
if(vr_human && vr_human.stat == CONSCIOUS && !vr_human.real_mind)
|
||||
SStgui.close_user_uis(occupant, src)
|
||||
vr_human.real_mind = human_occupant.mind
|
||||
vr_human.ckey = human_occupant.ckey
|
||||
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)
|
||||
else
|
||||
if(allow_creating_vr_humans)
|
||||
to_chat(occupant, "<span class='warning'>Virtual avatar not found, attempting to create one...</span>")
|
||||
var/turf/T = get_vr_spawnpoint()
|
||||
var/obj/effect/landmark/vr_spawn/V = get_vr_spawnpoint()
|
||||
var/turf/T = get_turf(V)
|
||||
if(T)
|
||||
build_virtual_human(occupant, T)
|
||||
SStgui.close_user_uis(occupant, src)
|
||||
build_virtual_human(occupant, T, V.vr_outfit)
|
||||
to_chat(vr_human, "<span class='notice'>Transfer successful! you are now playing as [vr_human] in VR!</span>")
|
||||
else
|
||||
to_chat(occupant, "<span class='warning'>Virtual world misconfigured, aborting transfer</span>")
|
||||
@@ -108,14 +113,14 @@
|
||||
if("delete_avatar")
|
||||
if(!occupant || usr == occupant)
|
||||
if(vr_human)
|
||||
qdel(vr_human)
|
||||
cleanup_vr_human()
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>The VR Sleeper's safeties prevent you from doing that.</span>")
|
||||
. = TRUE
|
||||
if("toggle_open")
|
||||
if(state_open)
|
||||
close_machine()
|
||||
else
|
||||
else if ((!occupant || usr == occupant) || !only_current_user_can_interact)
|
||||
open_machine()
|
||||
. = TRUE
|
||||
|
||||
@@ -124,66 +129,102 @@
|
||||
if(vr_human && !QDELETED(vr_human))
|
||||
data["can_delete_avatar"] = TRUE
|
||||
var/status
|
||||
switch(user.stat)
|
||||
switch(vr_human.stat)
|
||||
if(CONSCIOUS)
|
||||
status = "Conscious"
|
||||
if(DEAD)
|
||||
status = "Dead"
|
||||
if(UNCONSCIOUS)
|
||||
status = "Unconscious"
|
||||
if(SOFT_CRIT)
|
||||
status = "Barely Conscious"
|
||||
data["vr_avatar"] = list("name" = vr_human.name, "status" = status, "health" = vr_human.health, "maxhealth" = vr_human.maxHealth)
|
||||
data["toggle_open"] = state_open
|
||||
data["emagged"] = you_die_in_the_game_you_die_for_real
|
||||
data["isoccupant"] = (user == occupant)
|
||||
return data
|
||||
|
||||
/obj/machinery/vr_sleeper/proc/get_vr_spawnpoint() //proc so it can be overriden for team games or something
|
||||
return safepick(available_vr_spawnpoints[vr_category])
|
||||
/obj/machinery/vr_sleeper/proc/get_vr_spawnpoint() //proc so it can be overridden for team games or something
|
||||
return safepick(GLOB.vr_spawnpoints[vr_category])
|
||||
|
||||
/obj/machinery/vr_sleeper/proc/build_spawnpoints(rebuild = FALSE)
|
||||
if (rebuild)
|
||||
available_vr_spawnpoints = null
|
||||
if(!available_vr_spawnpoints || !available_vr_spawnpoints.len) //(re)build spawnpoint lists
|
||||
available_vr_spawnpoints = list()
|
||||
for(var/obj/effect/landmark/vr_spawn/V in GLOB.landmarks_list)
|
||||
available_vr_spawnpoints[V.vr_category] = list()
|
||||
var/turf/T = get_turf(V)
|
||||
if(T)
|
||||
available_vr_spawnpoints[V.vr_category] |= T
|
||||
/obj/machinery/vr_sleeper/proc/build_spawnpoints() // used to rebuild the list for admins if need be
|
||||
GLOB.vr_spawnpoints = list()
|
||||
for(var/obj/effect/landmark/vr_spawn/V in GLOB.landmarks_list)
|
||||
GLOB.vr_spawnpoints[V.vr_category] = V
|
||||
|
||||
/obj/machinery/vr_sleeper/proc/build_virtual_human(mob/living/carbon/human/H, location, transfer = TRUE)
|
||||
/obj/machinery/vr_sleeper/proc/build_virtual_human(mob/living/carbon/human/H, location, var/datum/outfit/outfit, transfer = TRUE)
|
||||
if(H)
|
||||
cleanup_vr_human()
|
||||
vr_human = new /mob/living/carbon/human/virtual_reality(location)
|
||||
vr_human.mind_initialize()
|
||||
vr_human.vr_sleeper = src
|
||||
vr_human.real_me = H
|
||||
vr_human.real_mind = H.mind
|
||||
H.dna.transfer_identity(vr_human)
|
||||
vr_human.name = H.name
|
||||
vr_human.real_name = H.real_name
|
||||
vr_human.socks = H.socks
|
||||
vr_human.undershirt = H.undershirt
|
||||
vr_human.underwear = H.underwear
|
||||
vr_human.updateappearance(1,1,1)
|
||||
vr_human.updateappearance(TRUE, TRUE, TRUE)
|
||||
if(outfit)
|
||||
var/datum/outfit/O = new outfit()
|
||||
O.equip(vr_human)
|
||||
if(transfer && H.mind)
|
||||
H.mind.transfer_to(vr_human)
|
||||
|
||||
SStgui.close_user_uis(H, src)
|
||||
vr_human.ckey = H.ckey
|
||||
|
||||
/obj/machinery/vr_sleeper/proc/cleanup_vr_human()
|
||||
if(vr_human)
|
||||
vr_human.death(FALSE)
|
||||
vr_human.vr_sleeper = null // Prevents race condition where a new human could get created out of order and set to null.
|
||||
QDEL_NULL(vr_human)
|
||||
|
||||
/obj/machinery/vr_sleeper/proc/emagNotify()
|
||||
if(vr_human)
|
||||
vr_human.Dizzy(10)
|
||||
|
||||
/obj/effect/landmark/vr_spawn //places you can spawn in VR, auto selected by the vr_sleeper during get_vr_spawnpoint()
|
||||
var/vr_category = "default" //So we can have specific sleepers, eg: "Basketball VR Sleeper", etc.
|
||||
var/vr_outfit = /datum/outfit/vr
|
||||
|
||||
/obj/effect/landmark/vr_spawn/Initialize()
|
||||
. = ..()
|
||||
LAZYADD(GLOB.vr_spawnpoints[vr_category], src)
|
||||
|
||||
/obj/effect/landmark/vr_spawn/Destroy()
|
||||
LAZYREMOVE(GLOB.vr_spawnpoints[vr_category], src)
|
||||
return ..()
|
||||
|
||||
/obj/effect/landmark/vr_spawn/team_1
|
||||
vr_category = "team_1"
|
||||
|
||||
/obj/effect/landmark/vr_spawn/team_2
|
||||
vr_category = "team_2"
|
||||
vr_category = "team_2"
|
||||
|
||||
/datum/outfit/vr_basic
|
||||
name = "basic vr"
|
||||
uniform = /obj/item/clothing/under/color/random
|
||||
shoes = /obj/item/clothing/shoes/sneakers/black
|
||||
/obj/effect/landmark/vr_spawn/admin
|
||||
vr_category = "event"
|
||||
|
||||
/obj/effect/landmark/vr_spawn/syndicate // Multiple missions will use syndicate gear
|
||||
vr_outfit = /datum/outfit/vr/syndicate
|
||||
|
||||
/obj/effect/vr_clean_master // Will keep VR areas that have this relatively clean.
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
icon_state = "x2"
|
||||
color = "#00FF00"
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
var/area/vr_area
|
||||
|
||||
/obj/effect/vr_clean_master/Initialize()
|
||||
. = ..()
|
||||
vr_area = get_area(src)
|
||||
addtimer(CALLBACK(src, .proc/clean_up), 3 MINUTES)
|
||||
|
||||
/obj/effect/vr_clean_master/proc/clean_up()
|
||||
if (vr_area)
|
||||
for (var/obj/item/ammo_casing/casing in vr_area)
|
||||
qdel(casing)
|
||||
for(var/obj/effect/decal/cleanable/C in vr_area)
|
||||
qdel(C)
|
||||
for (var/mob/living/carbon/human/virtual_reality/H in vr_area)
|
||||
if (H.stat == DEAD && !H.vr_sleeper && !H.real_mind)
|
||||
qdel(H)
|
||||
addtimer(CALLBACK(src, .proc/clean_up), 3 MINUTES)
|
||||
@@ -74,12 +74,20 @@
|
||||
ckey = ckey(banckey)
|
||||
computerid = bancid
|
||||
ip = banip
|
||||
|
||||
var/had_banned_mob = banned_mob != null
|
||||
var/client/banned_client = banned_mob?.client
|
||||
var/banned_mob_guest_key = had_banned_mob && IsGuestKey(banned_mob.key)
|
||||
banned_mob = null
|
||||
|
||||
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())
|
||||
qdel(query_add_ban_get_ckey)
|
||||
return
|
||||
if(!query_add_ban_get_ckey.NextRow())
|
||||
if(!banned_mob || (banned_mob && !IsGuestKey(banned_mob.key)))
|
||||
var/seen_before = query_add_ban_get_ckey.NextRow()
|
||||
qdel(query_add_ban_get_ckey)
|
||||
if(!seen_before)
|
||||
if(!had_banned_mob || (had_banned_mob && !banned_mob_guest_key))
|
||||
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
|
||||
|
||||
@@ -116,6 +124,7 @@
|
||||
if(maxadminbancheck)
|
||||
var/datum/DBQuery/query_check_adminban_amt = SSdbcore.NewQuery("SELECT count(id) AS num FROM [format_table_name("ban")] WHERE (a_ckey = '[a_ckey]') AND (bantype = 'ADMIN_PERMABAN' OR (bantype = 'ADMIN_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)")
|
||||
if(!query_check_adminban_amt.warn_execute())
|
||||
qdel(query_check_adminban_amt)
|
||||
return
|
||||
if(query_check_adminban_amt.NextRow())
|
||||
var/adm_bans = text2num(query_check_adminban_amt.item[1])
|
||||
@@ -124,7 +133,9 @@
|
||||
max_bans = MAX_ADMIN_BANS_PER_HEADMIN
|
||||
if(adm_bans >= max_bans)
|
||||
to_chat(usr, "<span class='danger'>You already logged [max_bans] admin ban(s) or more. Do not abuse this function!</span>")
|
||||
qdel(query_check_adminban_amt)
|
||||
return
|
||||
qdel(query_check_adminban_amt)
|
||||
if(!computerid)
|
||||
computerid = "0"
|
||||
if(!ip)
|
||||
@@ -132,7 +143,9 @@
|
||||
var/sql = "INSERT INTO [format_table_name("ban")] (`bantime`,`server_ip`,`server_port`,`round_id`,`bantype`,`reason`,`job`,`duration`,`expiration_time`,`ckey`,`computerid`,`ip`,`a_ckey`,`a_computerid`,`a_ip`,`who`,`adminwho`) VALUES (Now(), INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]', '[GLOB.round_id]', '[bantype_str]', '[reason]', '[job]', [(duration)?"[duration]":"0"], Now() + INTERVAL [(duration>0) ? duration : 0] MINUTE, '[ckey]', '[computerid]', INET_ATON('[ip]'), '[a_ckey]', '[a_computerid]', INET_ATON('[a_ip]'), '[who]', '[adminwho]')"
|
||||
var/datum/DBQuery/query_add_ban = SSdbcore.NewQuery(sql)
|
||||
if(!query_add_ban.warn_execute())
|
||||
qdel(query_add_ban)
|
||||
return
|
||||
qdel(query_add_ban)
|
||||
to_chat(usr, "<span class='adminnotice'>Ban saved to database.</span>")
|
||||
var/msg = "[key_name_admin(usr)] has added a [bantype_str] for [ckey] [(job)?"([job])":""] [(duration > 0)?"([duration] minutes)":""] with the reason: \"[reason]\" to the ban database."
|
||||
message_admins(msg,1)
|
||||
@@ -144,8 +157,8 @@
|
||||
if(kickbannedckey)
|
||||
if(AH)
|
||||
AH.Resolve() //with prejudice
|
||||
if(banned_mob && banned_mob.client && banned_mob.client.ckey == banckey)
|
||||
qdel(banned_mob.client)
|
||||
if(banned_client && banned_client.ckey == banckey)
|
||||
qdel(banned_client)
|
||||
return 1
|
||||
|
||||
/datum/admins/proc/DB_ban_unban(ckey, bantype, job = "")
|
||||
@@ -204,10 +217,12 @@
|
||||
|
||||
var/datum/DBQuery/query_unban_get_id = SSdbcore.NewQuery(sql)
|
||||
if(!query_unban_get_id.warn_execute())
|
||||
qdel(query_unban_get_id)
|
||||
return
|
||||
while(query_unban_get_id.NextRow())
|
||||
ban_id = query_unban_get_id.item[1]
|
||||
ban_number++;
|
||||
qdel(query_unban_get_id)
|
||||
|
||||
if(ban_number == 0)
|
||||
to_chat(usr, "<span class='danger'>Database update failed due to no bans fitting the search criteria. If this is not a legacy ban you should contact the database admin.</span>")
|
||||
@@ -236,6 +251,7 @@
|
||||
|
||||
var/datum/DBQuery/query_edit_ban_get_details = SSdbcore.NewQuery("SELECT ckey, duration, reason FROM [format_table_name("ban")] WHERE id = [banid]")
|
||||
if(!query_edit_ban_get_details.warn_execute())
|
||||
qdel(query_edit_ban_get_details)
|
||||
return
|
||||
|
||||
var/eckey = usr.ckey //Editing admin ckey
|
||||
@@ -249,7 +265,9 @@
|
||||
reason = query_edit_ban_get_details.item[3]
|
||||
else
|
||||
to_chat(usr, "Invalid ban id. Contact the database admin")
|
||||
qdel(query_edit_ban_get_details)
|
||||
return
|
||||
qdel(query_edit_ban_get_details)
|
||||
|
||||
reason = sanitizeSQL(reason)
|
||||
var/value
|
||||
@@ -265,8 +283,10 @@
|
||||
|
||||
var/datum/DBQuery/query_edit_ban_reason = SSdbcore.NewQuery("UPDATE [format_table_name("ban")] SET reason = '[value]', edits = CONCAT(edits,'- [eckey] changed ban reason from <cite><b>\\\"[reason]\\\"</b></cite> to <cite><b>\\\"[value]\\\"</b></cite><BR>') WHERE id = [banid]")
|
||||
if(!query_edit_ban_reason.warn_execute())
|
||||
qdel(query_edit_ban_reason)
|
||||
return
|
||||
message_admins("[key_name_admin(usr)] has edited a ban for [pckey]'s reason from [reason] to [value]",1)
|
||||
qdel(query_edit_ban_reason)
|
||||
message_admins("[key_name_admin(usr)] has edited a ban for [pckey]'s reason from [reason] to [value]")
|
||||
if("duration")
|
||||
if(!value)
|
||||
value = input("Insert the new duration (in minutes) for [pckey]'s ban", "New Duration", "[duration]", null) as null|num
|
||||
@@ -276,8 +296,10 @@
|
||||
|
||||
var/datum/DBQuery/query_edit_ban_duration = SSdbcore.NewQuery("UPDATE [format_table_name("ban")] SET duration = [value], edits = CONCAT(edits,'- [eckey] changed ban duration from [duration] to [value]<br>'), expiration_time = DATE_ADD(bantime, INTERVAL [value] MINUTE) WHERE id = [banid]")
|
||||
if(!query_edit_ban_duration.warn_execute())
|
||||
qdel(query_edit_ban_duration)
|
||||
return
|
||||
message_admins("[key_name_admin(usr)] has edited a ban for [pckey]'s duration from [duration] to [value]",1)
|
||||
qdel(query_edit_ban_duration)
|
||||
message_admins("[key_name_admin(usr)] has edited a ban for [pckey]'s duration from [duration] to [value]")
|
||||
if("unban")
|
||||
if(alert("Unban [pckey]?", "Unban?", "Yes", "No") == "Yes")
|
||||
DB_ban_unban_by_id(banid)
|
||||
@@ -304,10 +326,12 @@
|
||||
var/pckey
|
||||
var/datum/DBQuery/query_unban_get_ckey = SSdbcore.NewQuery(sql)
|
||||
if(!query_unban_get_ckey.warn_execute())
|
||||
qdel(query_unban_get_ckey)
|
||||
return
|
||||
while(query_unban_get_ckey.NextRow())
|
||||
pckey = query_unban_get_ckey.item[1]
|
||||
ban_number++;
|
||||
qdel(query_unban_get_ckey)
|
||||
|
||||
if(ban_number == 0)
|
||||
to_chat(usr, "<span class='danger'>Database update failed due to a ban id not being present in the database.</span>")
|
||||
@@ -327,8 +351,10 @@
|
||||
var/sql_update = "UPDATE [format_table_name("ban")] SET unbanned = 1, unbanned_datetime = Now(), unbanned_ckey = '[unban_ckey]', unbanned_computerid = '[unban_computerid]', unbanned_ip = INET_ATON('[unban_ip]') WHERE id = [id]"
|
||||
var/datum/DBQuery/query_unban = SSdbcore.NewQuery(sql_update)
|
||||
if(!query_unban.warn_execute())
|
||||
qdel(query_unban)
|
||||
return
|
||||
message_admins("[key_name_admin(usr)] has lifted [pckey]'s ban.",1)
|
||||
qdel(query_unban)
|
||||
message_admins("[key_name_admin(usr)] has lifted [pckey]'s ban.")
|
||||
|
||||
/client/proc/DB_ban_panel()
|
||||
set category = "Admin"
|
||||
@@ -422,9 +448,11 @@
|
||||
page = text2num(page)
|
||||
var/datum/DBQuery/query_count_bans = SSdbcore.NewQuery("SELECT COUNT(id) FROM [format_table_name("ban")] WHERE [search]")
|
||||
if(!query_count_bans.warn_execute())
|
||||
qdel(query_count_bans)
|
||||
return
|
||||
if(query_count_bans.NextRow())
|
||||
bancount = text2num(query_count_bans.item[1])
|
||||
qdel(query_count_bans)
|
||||
if(bancount > bansperpage)
|
||||
output += "<br><b>Page: </b>"
|
||||
while(bancount > 0)
|
||||
@@ -448,6 +476,7 @@
|
||||
var/limit = " LIMIT [bansperpage * page], [bansperpage]"
|
||||
var/datum/DBQuery/query_search_bans = SSdbcore.NewQuery("SELECT id, bantime, bantype, reason, job, duration, expiration_time, ckey, a_ckey, unbanned, unbanned_ckey, unbanned_datetime, edits, round_id FROM [format_table_name("ban")] WHERE [search] ORDER BY bantime DESC[limit]")
|
||||
if(!query_search_bans.warn_execute())
|
||||
qdel(query_search_bans)
|
||||
return
|
||||
|
||||
while(query_search_bans.NextRow())
|
||||
@@ -511,7 +540,7 @@
|
||||
output += "<tr>"
|
||||
output += "<td colspan='5' bgcolor='white'> </td>"
|
||||
output += "</tr>"
|
||||
|
||||
qdel(query_search_bans)
|
||||
output += "</table></div>"
|
||||
|
||||
usr << browse(output,"window=lookupbans;size=900x500")
|
||||
|
||||
@@ -80,6 +80,7 @@
|
||||
|
||||
var/datum/DBQuery/query_ban_check = SSdbcore.NewQuery("SELECT ckey, a_ckey, reason, expiration_time, duration, bantime, bantype, id, round_id FROM [format_table_name("ban")] WHERE (ckey = '[ckeytext]' [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR bantype = 'ADMIN_PERMABAN' OR ((bantype = 'TEMPBAN' OR bantype = 'ADMIN_TEMPBAN') AND expiration_time > Now())) AND isnull(unbanned)")
|
||||
if(!query_ban_check.Execute())
|
||||
qdel(query_ban_check)
|
||||
return
|
||||
while(query_ban_check.NextRow())
|
||||
var/pckey = query_ban_check.item[1]
|
||||
@@ -117,7 +118,9 @@
|
||||
|
||||
|
||||
log_access("Failed Login: [key] [computer_id] [address] - Banned (#[banid]) [.["reason"]]")
|
||||
qdel(query_ban_check)
|
||||
return .
|
||||
qdel(query_ban_check)
|
||||
|
||||
var/list/ban = ..() //default pager ban stuff
|
||||
if (ban)
|
||||
|
||||
+23
-12
@@ -1,11 +1,11 @@
|
||||
|
||||
////////////////////////////////
|
||||
/proc/message_admins(msg)
|
||||
msg = "<span class=\"admin\"><span class=\"prefix\">ADMIN LOG:</span> <span class=\"message\">[msg]</span></span>"
|
||||
msg = "<span class=\"admin\"><span class=\"prefix\">ADMIN LOG:</span> <span class=\"message linkify\">[msg]</span></span>"
|
||||
to_chat(GLOB.admins, msg)
|
||||
|
||||
/proc/relay_msg_admins(msg)
|
||||
msg = "<span class=\"admin\"><span class=\"prefix\">RELAY:</span> <span class=\"message\">[msg]</span></span>"
|
||||
msg = "<span class=\"admin\"><span class=\"prefix\">RELAY:</span> <span class=\"message linkify\">[msg]</span></span>"
|
||||
to_chat(GLOB.admins, msg)
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
body += "<body>Options panel for <b>[M]</b>"
|
||||
if(M.client)
|
||||
body += " played by <b>[M.client]</b> "
|
||||
body += "\[<A href='?_src_=holder;[HrefToken()];editrights=rank;ckey=[M.ckey]'>[M.client.holder ? M.client.holder.rank : "Player"]</A>\]"
|
||||
body += "\[<A href='?_src_=holder;[HrefToken()];editrights=[(GLOB.admin_datums[M.client.ckey] || GLOB.deadmins[M.client.ckey]) ? "rank" : "add"];ckey=[M.ckey]'>[M.client.holder ? M.client.holder.rank : "Player"]</A>\]"
|
||||
if(CONFIG_GET(flag/use_exp_tracking))
|
||||
body += "\[<A href='?_src_=holder;[HrefToken()];getplaytimewindow=[REF(M)]'>" + M.client.get_exp_living() + "</a>\]"
|
||||
|
||||
@@ -62,8 +62,14 @@
|
||||
body += "<a href='?_src_=holder;[HrefToken()];borgpanel=[REF(M)]'>BP</a> - "
|
||||
body += "<a href='?priv_msg=[M.ckey]'>PM</a> - "
|
||||
body += "<a href='?_src_=holder;[HrefToken()];subtlemessage=[REF(M)]'>SM</a> - "
|
||||
if (ishuman(M) && M.mind)
|
||||
body += "<a href='?_src_=holder;[HrefToken()];HeadsetMessage=[REF(M)]'>HM</a> - "
|
||||
body += "<a href='?_src_=holder;[HrefToken()];adminplayerobservefollow=[REF(M)]'>FLW</a> - "
|
||||
body += "<a href='?_src_=holder;[HrefToken()];individuallog=[REF(M)]'>LOGS</a>\] <br>"
|
||||
//Default to client logs if available
|
||||
var/source = LOGSRC_MOB
|
||||
if(M.client)
|
||||
source = LOGSRC_CLIENT
|
||||
body += "<a href='?_src_=holder;[HrefToken()];individuallog=[REF(M)];log_src=[source]'>LOGS</a>\] <br>"
|
||||
|
||||
body += "<b>Mob type</b> = [M.type]<br><br>"
|
||||
|
||||
@@ -71,14 +77,19 @@
|
||||
body += "<A href='?_src_=holder;[HrefToken()];newban=[REF(M)]'>Ban</A> | "
|
||||
body += "<A href='?_src_=holder;[HrefToken()];jobban2=[REF(M)]'>Jobban</A> | "
|
||||
body += "<A href='?_src_=holder;[HrefToken()];appearanceban=[REF(M)]'>Identity Ban</A> | "
|
||||
var/rm = REF(M)
|
||||
if(jobban_isbanned(M, "OOC"))
|
||||
body+= "<A href='?_src_=holder;[HrefToken()];jobban3=OOC;jobban4=[REF(M)]'><font color=red>OOCBan</font></A> | "
|
||||
body+= "<A href='?_src_=holder;[HrefToken()];jobban3=OOC;jobban4=[rm]'><font color=red>OOCBan</font></A> | "
|
||||
else
|
||||
body+= "<A href='?_src_=holder;[HrefToken()];jobban3=OOC;jobban4=[REF(M)]'>OOCBan</A> | "
|
||||
body+= "<A href='?_src_=holder;[HrefToken()];jobban3=OOC;jobban4=[rm]'>OOCBan</A> | "
|
||||
if(QDELETED(M) || QDELETED(usr))
|
||||
return
|
||||
if(jobban_isbanned(M, "emote"))
|
||||
body+= "<A href='?_src_=holder;[HrefToken()];jobban3=emote;jobban4=[REF(M)]'><font color=red>EmoteBan</font></A> | "
|
||||
body+= "<A href='?_src_=holder;[HrefToken()];jobban3=emote;jobban4=[rm]'><font color=red>EmoteBan</font></A> | "
|
||||
else
|
||||
body+= "<A href='?_src_=holder;[HrefToken()];jobban3=emote;jobban4=[REF(M)]'>Emoteban</A> | "
|
||||
body+= "<A href='?_src_=holder;[HrefToken()];jobban3=emote;jobban4=[rm]'>Emoteban</A> | "
|
||||
if(QDELETED(M) || QDELETED(usr))
|
||||
return
|
||||
|
||||
body += "<A href='?_src_=holder;[HrefToken()];showmessageckey=[M.ckey]'>Notes | Messages | Watchlist</A> | "
|
||||
if(M.client)
|
||||
@@ -645,9 +656,9 @@
|
||||
T.ChangeTurf(chosen)
|
||||
else
|
||||
var/atom/A = new chosen(usr.loc)
|
||||
A.admin_spawned = TRUE
|
||||
A.flags_1 |= ADMIN_SPAWNED_1
|
||||
|
||||
log_admin("[key_name(usr)] spawned [chosen] at ([usr.x],[usr.y],[usr.z])")
|
||||
log_admin("[key_name(usr)] spawned [chosen] at [AREACOORD(usr)]")
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Spawn Atom") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/datum/admins/proc/spawn_cargo(object as text)
|
||||
@@ -665,7 +676,7 @@
|
||||
S.admin_spawned = TRUE
|
||||
S.generate(get_turf(usr))
|
||||
|
||||
log_admin("[key_name(usr)] spawned cargo pack [chosen] at ([usr.x],[usr.y],[usr.z])")
|
||||
log_admin("[key_name(usr)] spawned cargo pack [chosen] at [AREACOORD(usr)]")
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Spawn Cargo") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
|
||||
@@ -721,7 +732,7 @@
|
||||
to_chat(usr, "<b>AI [key_name(S, usr)]'s laws:</b>")
|
||||
else if(iscyborg(S))
|
||||
var/mob/living/silicon/robot/R = S
|
||||
to_chat(usr, "<b>CYBORG [key_name(S, usr)] [R.connected_ai?"(Slaved to: [R.connected_ai])":"(Independent)"]: laws:</b>")
|
||||
to_chat(usr, "<b>CYBORG [key_name(S, usr)] [R.connected_ai?"(Slaved to: [key_name(R.connected_ai)])":"(Independent)"]: laws:</b>")
|
||||
else if (ispAI(S))
|
||||
to_chat(usr, "<b>pAI [key_name(S, usr)]'s laws:</b>")
|
||||
else
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
var/F = file("[GLOB.log_directory]/[subject].html")
|
||||
WRITE_FILE(F, "<small>[time_stamp()] [REF(src)] ([x],[y],[z])</small> || [src] [message]<br>")
|
||||
|
||||
/client/proc/investigate_show(subject in list("notes, memos, watchlist", INVESTIGATE_RESEARCH, INVESTIGATE_EXONET, INVESTIGATE_PORTAL, INVESTIGATE_SINGULO, INVESTIGATE_WIRES, INVESTIGATE_TELESCI, INVESTIGATE_GRAVITY, INVESTIGATE_RECORDS, INVESTIGATE_CARGO, INVESTIGATE_SUPERMATTER, INVESTIGATE_ATMOS, INVESTIGATE_EXPERIMENTOR, INVESTIGATE_BOTANY, INVESTIGATE_HALLUCINATIONS, INVESTIGATE_RADIATION) )
|
||||
/client/proc/investigate_show(subject in list("notes, memos, watchlist", INVESTIGATE_RESEARCH, INVESTIGATE_EXONET, INVESTIGATE_PORTAL, INVESTIGATE_SINGULO, INVESTIGATE_WIRES, INVESTIGATE_TELESCI, INVESTIGATE_GRAVITY, INVESTIGATE_RECORDS, INVESTIGATE_CARGO, INVESTIGATE_SUPERMATTER, INVESTIGATE_ATMOS, INVESTIGATE_EXPERIMENTOR, INVESTIGATE_BOTANY, INVESTIGATE_HALLUCINATIONS, INVESTIGATE_RADIATION, INVESTIGATE_CIRCUIT) )
|
||||
set name = "Investigate"
|
||||
set category = "Admin"
|
||||
if(!holder)
|
||||
|
||||
@@ -146,7 +146,7 @@ GLOBAL_PROTECT(protected_ranks)
|
||||
var/sql_exclude_flags = sanitizeSQL(R.exclude_rights)
|
||||
var/sql_can_edit_flags = sanitizeSQL(R.can_edit_rights)
|
||||
sql_ranks += list(list("rank" = "'[sql_rank]'", "flags" = "[sql_flags]", "exclude_flags" = "[sql_exclude_flags]", "can_edit_flags" = "[sql_can_edit_flags]"))
|
||||
SSdbcore.MassInsert(format_table_name("admin_ranks"), sql_ranks, duplicate_key = TRUE)
|
||||
SSdbcore.MassInsert(format_table_name("admin_ranks"), sql_ranks, duplicate_key = TRUE, blocking = TRUE)
|
||||
else
|
||||
var/datum/DBQuery/query_load_admin_ranks = SSdbcore.NewQuery("SELECT rank, flags, exclude_flags, can_edit_flags FROM [format_table_name("admin_ranks")]")
|
||||
if(!query_load_admin_ranks.Execute())
|
||||
@@ -169,6 +169,7 @@ GLOBAL_PROTECT(protected_ranks)
|
||||
if(!R)
|
||||
continue
|
||||
GLOB.admin_ranks += R
|
||||
qdel(query_load_admin_ranks)
|
||||
//load ranks from backup file
|
||||
if(dbfail)
|
||||
var/backup_file = file("data/admins_backup.json")
|
||||
@@ -247,6 +248,7 @@ GLOBAL_PROTECT(protected_ranks)
|
||||
skip = 1
|
||||
if(!skip)
|
||||
new /datum/admins(rank_names[admin_rank], admin_ckey)
|
||||
qdel(query_load_admins)
|
||||
//load admins from backup file
|
||||
if(dbfail)
|
||||
var/backup_file = file("data/admins_backup.json")
|
||||
@@ -258,7 +260,7 @@ GLOBAL_PROTECT(protected_ranks)
|
||||
for(var/A in GLOB.admin_datums + GLOB.deadmins)
|
||||
if(A == "[J]") //this admin was already loaded from txt override
|
||||
continue
|
||||
new /datum/admins(ckeyEx(rank_names[json["admins"]["[J]"]]), ckey("[J]"))
|
||||
new /datum/admins(rank_names[ckeyEx(json["admins"]["[J]"])], ckey("[J]"))
|
||||
#ifdef TESTING
|
||||
var/msg = "Admins Built:\n"
|
||||
for(var/ckey in GLOB.admin_datums)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//admin verb groups - They can overlap if you so wish. Only one of each verb will exist in the verbs list regardless
|
||||
//admin verb groups - They can overlap if you so wish. Only one of each verb will exist in the verbs list regardless
|
||||
//the procs are cause you can't put the comments in the GLOB var define
|
||||
GLOBAL_PROTECT(admin_verbs_default)
|
||||
GLOBAL_LIST_INIT(admin_verbs_default, world.AVerbsDefault())
|
||||
@@ -34,6 +33,7 @@ GLOBAL_LIST_INIT(admin_verbs_admin, world.AVerbsAdmin())
|
||||
/client/proc/toggle_view_range, /*changes how far we can see*/
|
||||
/client/proc/getserverlogs, /*for accessing server logs*/
|
||||
/client/proc/cmd_admin_subtle_message, /*send an message to somebody as a 'voice in their head'*/
|
||||
/client/proc/cmd_admin_headset_message, /*send an message to somebody through their headset as CentCom*/
|
||||
/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*/
|
||||
@@ -99,7 +99,8 @@ GLOBAL_LIST_INIT(admin_verbs_fun, list(
|
||||
/client/proc/polymorph_all,
|
||||
/client/proc/show_tip,
|
||||
/client/proc/smite,
|
||||
/client/proc/admin_away
|
||||
/client/proc/admin_away,
|
||||
/client/proc/roll_dices //CIT CHANGE - Adds dice verb
|
||||
))
|
||||
GLOBAL_PROTECT(admin_verbs_spawn)
|
||||
GLOBAL_LIST_INIT(admin_verbs_spawn, list(/datum/admins/proc/spawn_atom, /datum/admins/proc/spawn_cargo, /datum/admins/proc/spawn_objasmob, /client/proc/respawn_character))
|
||||
@@ -182,6 +183,7 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
|
||||
/client/proc/admin_ghost,
|
||||
/client/proc/toggle_view_range,
|
||||
/client/proc/cmd_admin_subtle_message,
|
||||
/client/proc/cmd_admin_headset_message,
|
||||
/client/proc/cmd_admin_check_contents,
|
||||
/datum/admins/proc/access_news_network,
|
||||
/client/proc/admin_call_shuttle,
|
||||
@@ -597,8 +599,8 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
|
||||
if(!message)
|
||||
return
|
||||
O.say(message)
|
||||
log_admin("[key_name(usr)] made [O] at [O.x], [O.y], [O.z] say \"[message]\"")
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] made [O] at [O.x], [O.y], [O.z]. say \"[message]\"</span>")
|
||||
log_admin("[key_name(usr)] made [O] at [AREACOORD(O)] say \"[message]\"")
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] made [O] at [AREACOORD(O)]. say \"[message]\"</span>")
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Object Say") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
/client/proc/togglebuildmodeself()
|
||||
set name = "Toggle Build Mode Self"
|
||||
@@ -689,7 +691,7 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
|
||||
if (tile)
|
||||
var/mob/living/carbon/human/hooman = new(tile)
|
||||
hooman.equipOutfit(pick(subtypesof(/datum/outfit)))
|
||||
testing("Spawned test mob at [tile.x],[tile.y],[tile.z]")
|
||||
testing("Spawned test mob at [COORD(tile)]")
|
||||
while (!area && --j > 0)
|
||||
|
||||
/client/proc/toggle_AI_interact()
|
||||
|
||||
@@ -6,12 +6,14 @@
|
||||
if(!M.client) //no cache. fallback to a datum/DBQuery
|
||||
var/datum/DBQuery/query_jobban_check_ban = SSdbcore.NewQuery("SELECT reason FROM [format_table_name("ban")] WHERE ckey = '[sanitizeSQL(M.ckey)]' AND (bantype = 'JOB_PERMABAN' OR (bantype = 'JOB_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned) AND job = '[sanitizeSQL(rank)]'")
|
||||
if(!query_jobban_check_ban.warn_execute())
|
||||
qdel(query_jobban_check_ban)
|
||||
return
|
||||
if(query_jobban_check_ban.NextRow())
|
||||
var/reason = query_jobban_check_ban.item[1]
|
||||
qdel(query_jobban_check_ban)
|
||||
return reason ? reason : TRUE //we don't want to return "" if there is no ban reason, as that would evaluate to false
|
||||
else
|
||||
return FALSE
|
||||
qdel(query_jobban_check_ban)
|
||||
return FALSE
|
||||
|
||||
if(!M.client.jobbancache)
|
||||
jobban_buildcache(M.client)
|
||||
@@ -31,6 +33,7 @@
|
||||
return
|
||||
while(query_jobban_build_cache.NextRow())
|
||||
C.jobbancache[query_jobban_build_cache.item[1]] = query_jobban_build_cache.item[2]
|
||||
qdel(query_jobban_build_cache)
|
||||
|
||||
/proc/ban_unban_log_save(var/formatted_log)
|
||||
text2file(formatted_log,"data/ban_unban_log.txt")
|
||||
|
||||
@@ -110,6 +110,10 @@ GLOBAL_LIST(round_end_notifiees)
|
||||
admin_only = TRUE
|
||||
|
||||
/datum/tgs_chat_command/reload_admins/Run(datum/tgs_chat_user/sender, params)
|
||||
load_admins()
|
||||
ReloadAsync()
|
||||
log_admin("[sender.friendly_name] reloaded admins via chat command.")
|
||||
return "Admins reloaded."
|
||||
|
||||
/datum/tgs_chat_command/reload_admins/proc/ReloadAsync()
|
||||
set waitfor = FALSE
|
||||
load_admins()
|
||||
@@ -36,7 +36,8 @@
|
||||
return
|
||||
endtime = sanitizeSQL(endtime)
|
||||
var/datum/DBQuery/query_validate_time = SSdbcore.NewQuery("SELECT IF(STR_TO_DATE('[endtime]','%Y-%c-%d %T') > NOW(), STR_TO_DATE('[endtime]','%Y-%c-%d %T'), 0)")
|
||||
if(!query_validate_time.warn_execute())
|
||||
if(!query_validate_time.warn_execute() || QDELETED(usr) || !src)
|
||||
qdel(query_validate_time)
|
||||
return
|
||||
if(query_validate_time.NextRow())
|
||||
var/checktime = text2num(query_validate_time.item[1])
|
||||
@@ -44,6 +45,7 @@
|
||||
to_chat(src, "Datetime entered is improperly formatted or not later than current server time.")
|
||||
return
|
||||
endtime = query_validate_time.item[1]
|
||||
qdel(query_validate_time)
|
||||
var/adminonly
|
||||
switch(alert("Admin only poll?",,"Yes","No","Cancel"))
|
||||
if("Yes")
|
||||
@@ -124,18 +126,24 @@
|
||||
add_option = 0
|
||||
else
|
||||
return 0
|
||||
var/m1 = "[key_name(usr)] has created a new server poll. Poll type: [polltype] - Admin Only: [adminonly ? "Yes" : "No"] - Question: [question]"
|
||||
var/m2 = "[key_name_admin(usr)] has created a new server poll. Poll type: [polltype] - Admin Only: [adminonly ? "Yes" : "No"]<br>Question: [question]"
|
||||
var/datum/DBQuery/query_polladd_question = SSdbcore.NewQuery("INSERT INTO [format_table_name("poll_question")] (polltype, starttime, endtime, question, adminonly, multiplechoiceoptions, createdby_ckey, createdby_ip, dontshow) VALUES ('[polltype]', '[starttime]', '[endtime]', '[question]', '[adminonly]', '[choice_amount]', '[sql_ckey]', INET_ATON('[address]'), '[dontshow]')")
|
||||
if(!query_polladd_question.warn_execute())
|
||||
qdel(query_polladd_question)
|
||||
return
|
||||
qdel(query_polladd_question)
|
||||
if(polltype != POLLTYPE_TEXT)
|
||||
var/pollid = 0
|
||||
var/datum/DBQuery/query_get_id = SSdbcore.NewQuery("SELECT LAST_INSERT_ID()")
|
||||
if(!query_get_id.warn_execute())
|
||||
qdel(query_get_id)
|
||||
return
|
||||
if(query_get_id.NextRow())
|
||||
pollid = query_get_id.item[1]
|
||||
qdel(query_get_id)
|
||||
for(var/list/i in sql_option_list)
|
||||
i |= list("pollid" = "'[pollid]'")
|
||||
SSdbcore.MassInsert(format_table_name("poll_option"), sql_option_list, warn = 1)
|
||||
log_admin("[key_name(usr)] has created a new server poll. Poll type: [polltype] - Admin Only: [adminonly ? "Yes" : "No"] - Question: [question]")
|
||||
message_admins("[key_name_admin(usr)] has created a new server poll. Poll type: [polltype] - Admin Only: [adminonly ? "Yes" : "No"]<br>Question: [question]")
|
||||
log_admin(m1)
|
||||
message_admins(m2)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
anchored = TRUE
|
||||
var/popped = FALSE
|
||||
|
||||
/obj/effect/fun_balloon/New()
|
||||
/obj/effect/fun_balloon/Initialize()
|
||||
. = ..()
|
||||
SSobj.processing |= src
|
||||
|
||||
@@ -177,5 +177,5 @@
|
||||
|
||||
/area/shuttle_arena
|
||||
name = "arena"
|
||||
has_gravity = TRUE
|
||||
has_gravity = STANDARD_GRAVITY
|
||||
requires_power = FALSE
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
))
|
||||
"})
|
||||
if(!query_get_ip_intel.Execute())
|
||||
qdel(query_get_ip_intel)
|
||||
return
|
||||
if (query_get_ip_intel.NextRow())
|
||||
res.cache = TRUE
|
||||
@@ -59,14 +60,16 @@
|
||||
res.cacheminutesago = text2num(query_get_ip_intel.item[3])
|
||||
res.cacherealtime = world.realtime - (text2num(query_get_ip_intel.item[3])*10*60)
|
||||
SSipintel.cache[ip] = res
|
||||
qdel(query_get_ip_intel)
|
||||
return
|
||||
qdel(query_get_ip_intel)
|
||||
res.intel = ip_intel_query(ip)
|
||||
if (updatecache && res.intel >= 0)
|
||||
SSipintel.cache[ip] = res
|
||||
if(SSdbcore.Connect())
|
||||
var/datum/DBQuery/query_add_ip_intel = SSdbcore.NewQuery("INSERT INTO [format_table_name("ipintel")] (ip, intel) VALUES (INET_ATON('[ip]'), [res.intel]) ON DUPLICATE KEY UPDATE intel = VALUES(intel), date = NOW()")
|
||||
query_add_ip_intel.Execute()
|
||||
|
||||
qdel(query_add_ip_intel)
|
||||
|
||||
|
||||
/proc/ip_intel_query(ip, var/retryed=0)
|
||||
|
||||
@@ -31,9 +31,11 @@
|
||||
page = text2num(page)
|
||||
var/datum/DBQuery/query_count_admin_logs = SSdbcore.NewQuery("SELECT COUNT(id) FROM [format_table_name("admin_log")][search]")
|
||||
if(!query_count_admin_logs.warn_execute())
|
||||
qdel(query_count_admin_logs)
|
||||
return
|
||||
if(query_count_admin_logs.NextRow())
|
||||
logcount = text2num(query_count_admin_logs.item[1])
|
||||
qdel(query_count_admin_logs)
|
||||
if(logcount > logssperpage)
|
||||
output += "<br><b>Page: </b>"
|
||||
while(logcount > 0)
|
||||
@@ -44,6 +46,7 @@
|
||||
var/limit = " LIMIT [logssperpage * page], [logssperpage]"
|
||||
var/datum/DBQuery/query_search_admin_logs = SSdbcore.NewQuery("SELECT datetime, round_id, adminckey, operation, target, log FROM [format_table_name("admin_log")][search] ORDER BY datetime DESC[limit]")
|
||||
if(!query_search_admin_logs.warn_execute())
|
||||
qdel(query_search_admin_logs)
|
||||
return
|
||||
while(query_search_admin_logs.NextRow())
|
||||
var/datetime = query_search_admin_logs.item[1]
|
||||
@@ -53,19 +56,23 @@
|
||||
target = query_search_admin_logs.item[5]
|
||||
var/log = query_search_admin_logs.item[6]
|
||||
output += "<p style='margin:0px'><b>[datetime] | Round ID [round_id] | Admin [admin_ckey] | Operation [operation] on [target]</b><br>[log]</p><hr style='background:#000000; border:0; height:3px'>"
|
||||
qdel(query_search_admin_logs)
|
||||
if(action == 2)
|
||||
output += "<h3>Admin ckeys with invalid ranks</h3>"
|
||||
var/datum/DBQuery/query_check_admin_errors = SSdbcore.NewQuery("SELECT ckey, [format_table_name("admin")].rank FROM [format_table_name("admin")] LEFT JOIN [format_table_name("admin_ranks")] ON [format_table_name("admin_ranks")].rank = [format_table_name("admin")].rank WHERE [format_table_name("admin_ranks")].rank IS NULL")
|
||||
if(!query_check_admin_errors.warn_execute())
|
||||
qdel(query_check_admin_errors)
|
||||
return
|
||||
while(query_check_admin_errors.NextRow())
|
||||
var/admin_ckey = query_check_admin_errors.item[1]
|
||||
var/admin_rank = query_check_admin_errors.item[2]
|
||||
output += "[admin_ckey] has non-existant rank [admin_rank] | <a href='?_src_=holder;[HrefToken()];editrightsbrowsermanage=1;editrightschange=[admin_ckey]'>\[Change Rank\]</a> | <a href='?_src_=holder;[HrefToken()];editrightsbrowsermanage=1;editrightsremove=[admin_ckey]'>\[Remove\]</a>"
|
||||
output += "[admin_ckey] has non-existent rank [admin_rank] | <a href='?_src_=holder;[HrefToken()];editrightsbrowsermanage=1;editrightschange=[admin_ckey]'>\[Change Rank\]</a> | <a href='?_src_=holder;[HrefToken()];editrightsbrowsermanage=1;editrightsremove=[admin_ckey]'>\[Remove\]</a>"
|
||||
output += "<hr style='background:#000000; border:0; height:1px'>"
|
||||
qdel(query_check_admin_errors)
|
||||
output += "<h3>Unused ranks</h3>"
|
||||
var/datum/DBQuery/query_check_unused_rank = SSdbcore.NewQuery("SELECT [format_table_name("admin_ranks")].rank, flags, exclude_flags, can_edit_flags FROM [format_table_name("admin_ranks")] LEFT JOIN [format_table_name("admin")] ON [format_table_name("admin")].rank = [format_table_name("admin_ranks")].rank WHERE [format_table_name("admin")].rank IS NULL")
|
||||
if(!query_check_unused_rank.warn_execute())
|
||||
qdel(query_check_unused_rank)
|
||||
return
|
||||
while(query_check_unused_rank.NextRow())
|
||||
var/admin_rank = query_check_unused_rank.item[1]
|
||||
@@ -74,6 +81,7 @@
|
||||
<br>Denied: [rights2text(text2num(query_check_unused_rank.item[3])," ", "-")]
|
||||
<br>Allowed to edit: [rights2text(text2num(query_check_unused_rank.item[4])," ", "*")]
|
||||
<hr style='background:#000000; border:0; height:1px'>"}
|
||||
qdel(query_check_unused_rank)
|
||||
else if(!action)
|
||||
output += {"<head>
|
||||
<title>Permissions Panel</title>
|
||||
@@ -108,6 +116,8 @@
|
||||
output += "<td><a class='small' href='?src=[REF(src)];[HrefToken()];editrights=permissions;ckey=[adm_ckey]'>[rights2text(D.rank.can_edit_rights," ", "*")]</a></td>"
|
||||
output += "</tr>"
|
||||
output += "</table></div><div id='top'><b>Search:</b> <input type='text' id='filter' value='' style='width:70%;' onkeyup='updateSearch();'></div></body>"
|
||||
if(QDELETED(usr))
|
||||
return
|
||||
usr << browse("<!DOCTYPE html><html>[jointext(output, "")]</html>","window=editrights;size=1000x650")
|
||||
|
||||
/datum/admins/proc/edit_rights_topic(list/href_list)
|
||||
@@ -125,6 +135,7 @@
|
||||
var/use_db
|
||||
var/task = href_list["editrights"]
|
||||
var/skip
|
||||
var/legacy_only
|
||||
if(task == "activate" || task == "deactivate" || task == "sync")
|
||||
skip = TRUE
|
||||
if(!CONFIG_GET(flag/admin_legacy_system) && CONFIG_GET(flag/protect_legacy_admins) && task == "rank")
|
||||
@@ -135,10 +146,9 @@
|
||||
if(D.rank in GLOB.protected_ranks)
|
||||
to_chat(usr, "<span class='admin prefix'>Editing the flags of this rank is blocked by server configuration.</span>")
|
||||
return
|
||||
if(CONFIG_GET(flag/load_legacy_ranks_only) && (task == "rank" || task == "permissions"))
|
||||
to_chat(usr, "<span class='admin prefix'>Database rank loading is disabled, only temporary changes can be made to an admin's rank or permissions.</span>")
|
||||
use_db = FALSE
|
||||
skip = TRUE
|
||||
if(CONFIG_GET(flag/load_legacy_ranks_only) && (task == "add" || task == "rank" || task == "permissions"))
|
||||
to_chat(usr, "<span class='admin prefix'>Database rank loading is disabled, only temporary changes can be made to a rank's permissions and permanently creating a new rank is blocked.</span>")
|
||||
legacy_only = TRUE
|
||||
if(check_rights(R_DBRANKS, FALSE))
|
||||
if(!skip)
|
||||
if(!SSdbcore.Connect())
|
||||
@@ -153,6 +163,8 @@
|
||||
admin_ckey = sanitizeSQL(admin_ckey)
|
||||
else
|
||||
use_db = FALSE
|
||||
if(QDELETED(usr))
|
||||
return
|
||||
if(task != "add")
|
||||
D = GLOB.admin_datums[admin_ckey]
|
||||
if(!D)
|
||||
@@ -165,16 +177,16 @@
|
||||
return
|
||||
switch(task)
|
||||
if("add")
|
||||
admin_ckey = add_admin(null, use_db)
|
||||
admin_ckey = add_admin(admin_ckey, use_db)
|
||||
if(!admin_ckey)
|
||||
return
|
||||
change_admin_rank(admin_ckey, use_db)
|
||||
change_admin_rank(admin_ckey, use_db, null, legacy_only)
|
||||
if("remove")
|
||||
remove_admin(admin_ckey, use_db, D)
|
||||
if("rank")
|
||||
change_admin_rank(admin_ckey, use_db, D)
|
||||
change_admin_rank(admin_ckey, use_db, D, legacy_only)
|
||||
if("permissions")
|
||||
change_admin_flags(admin_ckey, use_db, D)
|
||||
change_admin_flags(admin_ckey, use_db, D, legacy_only)
|
||||
if("activate")
|
||||
force_readmin(admin_ckey, D)
|
||||
if("deactivate")
|
||||
@@ -198,16 +210,23 @@
|
||||
//if an admin exists without a datum they won't be caught by the above
|
||||
var/datum/DBQuery/query_admin_in_db = SSdbcore.NewQuery("SELECT 1 FROM [format_table_name("admin")] WHERE ckey = '[.]'")
|
||||
if(!query_admin_in_db.warn_execute())
|
||||
qdel(query_admin_in_db)
|
||||
return FALSE
|
||||
if(query_admin_in_db.NextRow())
|
||||
qdel(query_admin_in_db)
|
||||
to_chat(usr, "<span class='danger'>[.] already listed in admin database. Check the Management tab if they don't appear in the list of admins.</span>")
|
||||
return FALSE
|
||||
qdel(query_admin_in_db)
|
||||
var/datum/DBQuery/query_add_admin = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin")] (ckey, rank) VALUES ('[.]', 'NEW ADMIN')")
|
||||
if(!query_add_admin.warn_execute())
|
||||
qdel(query_add_admin)
|
||||
return FALSE
|
||||
qdel(query_add_admin)
|
||||
var/datum/DBQuery/query_add_admin_log = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin_log")] (datetime, round_id, adminckey, adminip, operation, target, log) VALUES ('[SQLtime()]', '[GLOB.round_id]', '[sanitizeSQL(usr.ckey)]', INET_ATON('[sanitizeSQL(usr.client.address)]'), 'add admin', '[.]', 'New admin added: [.]')")
|
||||
if(!query_add_admin_log.warn_execute())
|
||||
qdel(query_add_admin_log)
|
||||
return FALSE
|
||||
qdel(query_add_admin_log)
|
||||
|
||||
/datum/admins/proc/remove_admin(admin_ckey, use_db, datum/admins/D)
|
||||
if(alert("Are you sure you want to remove [admin_ckey]?","Confirm Removal","Do it","Cancel") == "Do it")
|
||||
@@ -215,16 +234,22 @@
|
||||
GLOB.deadmins -= admin_ckey
|
||||
if(D)
|
||||
D.disassociate()
|
||||
var/m1 = "[key_name_admin(usr)] removed [admin_ckey] from the admins list [use_db ? "permanently" : "temporarily"]"
|
||||
var/m2 = "[key_name(usr)] removed [admin_ckey] from the admins list [use_db ? "permanently" : "temporarily"]"
|
||||
if(use_db)
|
||||
var/datum/DBQuery/query_add_rank = SSdbcore.NewQuery("DELETE FROM [format_table_name("admin")] WHERE ckey = '[admin_ckey]'")
|
||||
if(!query_add_rank.warn_execute())
|
||||
qdel(query_add_rank)
|
||||
return
|
||||
qdel(query_add_rank)
|
||||
var/datum/DBQuery/query_add_rank_log = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin_log")] (datetime, round_id, adminckey, adminip, operation, target, log) VALUES ('[SQLtime()]', '[GLOB.round_id]', '[sanitizeSQL(usr.ckey)]', INET_ATON('[sanitizeSQL(usr.client.address)]'), 'remove admin', '[admin_ckey]', 'Admin removed: [admin_ckey]')")
|
||||
if(!query_add_rank_log.warn_execute())
|
||||
qdel(query_add_rank_log)
|
||||
return
|
||||
qdel(query_add_rank_log)
|
||||
sync_lastadminrank(admin_ckey)
|
||||
message_admins("[key_name_admin(usr)] removed [admin_ckey] from the admins list [use_db ? "permanently" : "temporarily"]")
|
||||
log_admin("[key_name(usr)] removed [admin_ckey] from the admins list [use_db ? "permanently" : "temporarily"]")
|
||||
message_admins(m1)
|
||||
log_admin(m2)
|
||||
|
||||
/datum/admins/proc/force_readmin(admin_ckey, datum/admins/D)
|
||||
if(!D || !D.deadmined)
|
||||
@@ -240,9 +265,11 @@
|
||||
log_admin("[key_name(usr)] forcefully deadmined [admin_ckey]")
|
||||
D.deactivate() //after logs so the deadmined admin can see the message.
|
||||
|
||||
/datum/admins/proc/change_admin_rank(admin_ckey, use_db, datum/admins/D)
|
||||
/datum/admins/proc/change_admin_rank(admin_ckey, use_db, datum/admins/D, legacy_only)
|
||||
var/datum/admin_rank/R
|
||||
var/list/rank_names = list("*New Rank*")
|
||||
var/list/rank_names = list()
|
||||
if(!use_db || (use_db && !legacy_only))
|
||||
rank_names += "*New Rank*"
|
||||
for(R in GLOB.admin_ranks)
|
||||
if((R.rights & usr.client.holder.rank.can_edit_rights) == R.rights)
|
||||
rank_names[R.name] = R
|
||||
@@ -258,35 +285,50 @@
|
||||
else
|
||||
R = new(new_rank) //blank new admin_rank
|
||||
GLOB.admin_ranks += R
|
||||
var/m1 = "[key_name_admin(usr)] edited the admin rank of [admin_ckey] to [new_rank] [use_db ? "permanently" : "temporarily"]"
|
||||
var/m2 = "[key_name(usr)] edited the admin rank of [admin_ckey] to [new_rank] [use_db ? "permanently" : "temporarily"]"
|
||||
if(use_db)
|
||||
new_rank = sanitizeSQL(new_rank)
|
||||
//if a player was tempminned before having a permanent change made to their rank they won't yet be in the db
|
||||
var/old_rank
|
||||
var/datum/DBQuery/query_admin_in_db = SSdbcore.NewQuery("SELECT rank FROM [format_table_name("admin")] WHERE ckey = '[admin_ckey]'")
|
||||
if(!query_admin_in_db.warn_execute())
|
||||
qdel(query_admin_in_db)
|
||||
return
|
||||
if(!query_admin_in_db.NextRow())
|
||||
add_admin(admin_ckey, TRUE)
|
||||
old_rank = "NEW ADMIN"
|
||||
else
|
||||
old_rank = query_admin_in_db.item[1]
|
||||
qdel(query_admin_in_db)
|
||||
//similarly if a temp rank is created it won't be in the db if someone is permanently changed to it
|
||||
var/datum/DBQuery/query_rank_in_db = SSdbcore.NewQuery("SELECT 1 FROM [format_table_name("admin_ranks")] WHERE rank = '[new_rank]'")
|
||||
if(!query_rank_in_db.warn_execute())
|
||||
qdel(query_rank_in_db)
|
||||
return
|
||||
if(!query_rank_in_db.NextRow())
|
||||
QDEL_NULL(query_rank_in_db)
|
||||
var/datum/DBQuery/query_add_rank = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin_ranks")] (rank, flags, exclude_flags, can_edit_flags) VALUES ('[new_rank]', '0', '0', '0')")
|
||||
if(!query_add_rank.warn_execute())
|
||||
qdel(query_add_rank)
|
||||
return
|
||||
qdel(query_add_rank)
|
||||
var/datum/DBQuery/query_add_rank_log = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin_log")] (datetime, round_id, adminckey, adminip, operation, target, log) VALUES ('[SQLtime()]', '[GLOB.round_id]', '[sanitizeSQL(usr.ckey)]', INET_ATON('[sanitizeSQL(usr.client.address)]'), 'add rank', '[new_rank]', 'New rank added: [new_rank]')")
|
||||
if(!query_add_rank_log.warn_execute())
|
||||
qdel(query_add_rank_log)
|
||||
return
|
||||
qdel(query_add_rank_log)
|
||||
qdel(query_rank_in_db)
|
||||
var/datum/DBQuery/query_change_rank = SSdbcore.NewQuery("UPDATE [format_table_name("admin")] SET rank = '[new_rank]' WHERE ckey = '[admin_ckey]'")
|
||||
if(!query_change_rank.warn_execute())
|
||||
qdel(query_change_rank)
|
||||
return
|
||||
qdel(query_change_rank)
|
||||
var/datum/DBQuery/query_change_rank_log = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin_log")] (datetime, round_id, adminckey, adminip, operation, target, log) VALUES ('[SQLtime()]', '[GLOB.round_id]', '[sanitizeSQL(usr.ckey)]', INET_ATON('[sanitizeSQL(usr.client.address)]'), 'change admin rank', '[admin_ckey]', 'Rank of [admin_ckey] changed from [old_rank] to [new_rank]')")
|
||||
if(!query_change_rank_log.warn_execute())
|
||||
qdel(query_change_rank_log)
|
||||
return
|
||||
qdel(query_change_rank_log)
|
||||
if(D) //they were previously an admin
|
||||
D.disassociate() //existing admin needs to be disassociated
|
||||
D.rank = R //set the admin_rank as our rank
|
||||
@@ -294,10 +336,10 @@
|
||||
D.associate(C)
|
||||
else
|
||||
D = new(R, admin_ckey, TRUE) //new admin
|
||||
message_admins("[key_name_admin(usr)] edited the admin rank of [admin_ckey] to [new_rank] [use_db ? "permanently" : "temporarily"]")
|
||||
log_admin("[key_name(usr)] edited the admin rank of [admin_ckey] to [new_rank] [use_db ? "permanently" : "temporarily"]")
|
||||
message_admins(m1)
|
||||
log_admin(m2)
|
||||
|
||||
/datum/admins/proc/change_admin_flags(admin_ckey, use_db, datum/admins/D)
|
||||
/datum/admins/proc/change_admin_flags(admin_ckey, use_db, datum/admins/D, legacy_only)
|
||||
var/new_flags = input_bitfield(usr, "Include permission flags<br>[use_db ? "This will affect ALL admins with this rank." : "This will affect only the current admin [admin_ckey]"]", "admin_flags", D.rank.include_rights, 350, 590, allowed_edit_list = usr.client.holder.rank.can_edit_rights)
|
||||
if(isnull(new_flags))
|
||||
return
|
||||
@@ -307,23 +349,31 @@
|
||||
var/new_can_edit_flags = input_bitfield(usr, "Editable permission flags<br>These are the flags this rank is allowed to edit if they have access to the permissions panel.<br>They will be unable to modify admins to a rank that has a flag not included here.<br>[use_db ? "This will affect ALL admins with this rank." : "This will affect only the current admin [admin_ckey]"]", "admin_flags", D.rank.can_edit_rights, 350, 710, allowed_edit_list = usr.client.holder.rank.can_edit_rights)
|
||||
if(isnull(new_can_edit_flags))
|
||||
return
|
||||
if(use_db)
|
||||
var/m1 = "[key_name_admin(usr)] edited the permissions of [use_db ? " rank [D.rank.name] permanently" : "[admin_ckey] temporarily"]"
|
||||
var/m2 = "[key_name(usr)] edited the permissions of [use_db ? " rank [D.rank.name] permanently" : "[admin_ckey] temporarily"]"
|
||||
if(use_db || legacy_only)
|
||||
var/old_flags
|
||||
var/old_exclude_flags
|
||||
var/old_can_edit_flags
|
||||
var/datum/DBQuery/query_get_rank_flags = SSdbcore.NewQuery("SELECT flags, exclude_flags, can_edit_flags FROM [format_table_name("admin_ranks")] WHERE rank = '[D.rank.name]'")
|
||||
if(!query_get_rank_flags.warn_execute())
|
||||
qdel(query_get_rank_flags)
|
||||
return
|
||||
if(query_get_rank_flags.NextRow())
|
||||
old_flags = text2num(query_get_rank_flags.item[1])
|
||||
old_exclude_flags = text2num(query_get_rank_flags.item[2])
|
||||
old_can_edit_flags = text2num(query_get_rank_flags.item[3])
|
||||
qdel(query_get_rank_flags)
|
||||
var/datum/DBQuery/query_change_rank_flags = SSdbcore.NewQuery("UPDATE [format_table_name("admin_ranks")] SET flags = '[new_flags]', exclude_flags = '[new_exclude_flags]', can_edit_flags = '[new_can_edit_flags]' WHERE rank = '[D.rank.name]'")
|
||||
if(!query_change_rank_flags.warn_execute())
|
||||
qdel(query_change_rank_flags)
|
||||
return
|
||||
qdel(query_change_rank_flags)
|
||||
var/datum/DBQuery/query_change_rank_flags_log = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin_log")] (datetime, round_id, adminckey, adminip, operation, target, log) VALUES ('[SQLtime()]', '[GLOB.round_id]', '[sanitizeSQL(usr.ckey)]', INET_ATON('[sanitizeSQL(usr.client.address)]'), 'change rank flags', '[D.rank.name]', 'Permissions of [D.rank.name] changed from[rights2text(old_flags," ")][rights2text(old_exclude_flags," ", "-")][rights2text(old_can_edit_flags," ", "*")] to[rights2text(new_flags," ")][rights2text(new_exclude_flags," ", "-")][rights2text(new_can_edit_flags," ", "*")]')")
|
||||
if(!query_change_rank_flags_log.warn_execute())
|
||||
qdel(query_change_rank_flags_log)
|
||||
return
|
||||
qdel(query_change_rank_flags_log)
|
||||
for(var/datum/admin_rank/R in GLOB.admin_ranks)
|
||||
if(R.name != D.rank.name)
|
||||
continue
|
||||
@@ -351,10 +401,11 @@
|
||||
D.rank.rights = new_flags &= ~new_exclude_flags
|
||||
D.rank.include_rights = new_flags
|
||||
D.rank.exclude_rights = new_exclude_flags
|
||||
D.rank.can_edit_rights = new_can_edit_flags
|
||||
var/client/C = GLOB.directory[admin_ckey] //find the client with the specified ckey (if they are logged in)
|
||||
D.associate(C) //link up with the client and add verbs
|
||||
message_admins("[key_name_admin(usr)] edited the permissions of [use_db ? " rank [D.rank.name] permanently" : "[admin_ckey] temporarily"]")
|
||||
log_admin("[key_name(usr)] edited the permissions of [use_db ? " rank [D.rank.name] permanently" : "[admin_ckey] temporarily"]")
|
||||
message_admins(m1)
|
||||
log_admin(m2)
|
||||
|
||||
/datum/admins/proc/remove_rank(admin_rank)
|
||||
if(!admin_rank)
|
||||
@@ -372,19 +423,28 @@
|
||||
admin_rank = sanitizeSQL(admin_rank)
|
||||
var/datum/DBQuery/query_admins_with_rank = SSdbcore.NewQuery("SELECT 1 FROM [format_table_name("admin")] WHERE rank = '[admin_rank]'")
|
||||
if(!query_admins_with_rank.warn_execute())
|
||||
qdel(query_admins_with_rank)
|
||||
return
|
||||
if(query_admins_with_rank.NextRow())
|
||||
qdel(query_admins_with_rank)
|
||||
to_chat(usr, "<span class='danger'>Error: Rank deletion attempted while rank still used; Tell a coder, this shouldn't happen.</span>")
|
||||
return
|
||||
qdel(query_admins_with_rank)
|
||||
if(alert("Are you sure you want to remove [admin_rank]?","Confirm Removal","Do it","Cancel") == "Do it")
|
||||
var/m1 = "[key_name_admin(usr)] removed rank [admin_rank] permanently"
|
||||
var/m2 = "[key_name(usr)] removed rank [admin_rank] permanently"
|
||||
var/datum/DBQuery/query_add_rank = SSdbcore.NewQuery("DELETE FROM [format_table_name("admin_ranks")] WHERE rank = '[admin_rank]'")
|
||||
if(!query_add_rank.warn_execute())
|
||||
qdel(query_add_rank)
|
||||
return
|
||||
qdel(query_add_rank)
|
||||
var/datum/DBQuery/query_add_rank_log = SSdbcore.NewQuery("INSERT INTO [format_table_name("admin_log")] (datetime, round_id, adminckey, adminip, operation, target, log) VALUES ('[SQLtime()]', '[GLOB.round_id]', '[sanitizeSQL(usr.ckey)]', INET_ATON('[sanitizeSQL(usr.client.address)]'), 'remove rank', '[admin_rank]', 'Rank removed: [admin_rank]')")
|
||||
if(!query_add_rank_log.warn_execute())
|
||||
qdel(query_add_rank_log)
|
||||
return
|
||||
message_admins("[key_name_admin(usr)] removed rank [admin_rank] permanently")
|
||||
log_admin("[key_name(usr)] removed rank [admin_rank] permanently")
|
||||
qdel(query_add_rank_log)
|
||||
message_admins(m1)
|
||||
log_admin(m2)
|
||||
|
||||
/datum/admins/proc/sync_lastadminrank(admin_ckey, datum/admins/D)
|
||||
var/sqlrank = "Player"
|
||||
@@ -393,5 +453,7 @@
|
||||
admin_ckey = sanitizeSQL(admin_ckey)
|
||||
var/datum/DBQuery/query_sync_lastadminrank = SSdbcore.NewQuery("UPDATE [format_table_name("player")] SET lastadminrank = '[sqlrank]' WHERE ckey = '[admin_ckey]'")
|
||||
if(!query_sync_lastadminrank.warn_execute())
|
||||
qdel(query_sync_lastadminrank)
|
||||
return
|
||||
qdel(query_sync_lastadminrank)
|
||||
to_chat(usr, "<span class='admin'>Sync of [admin_ckey] successful.</span>")
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
dat +={"
|
||||
<B>General Secrets</B><BR>
|
||||
<BR>
|
||||
<A href='?src=[REF(src)];[HrefToken()];secrets=list_job_debug'>Show Job Debug</A><BR>
|
||||
<A href='?src=[REF(src)];[HrefToken()];secrets=admin_log'>Admin Log</A><BR>
|
||||
<A href='?src=[REF(src)];[HrefToken()];secrets=mentor_log'>Mentor Log</A><BR>
|
||||
<A href='?src=[REF(src)];[HrefToken()];secrets=show_admins'>Show Admin List</A><BR>
|
||||
@@ -111,18 +110,6 @@
|
||||
|
||||
if("mentor_log")
|
||||
CitadelMentorLogSecret()
|
||||
|
||||
if("list_job_debug")
|
||||
var/dat = "<B>Job Debug info.</B><HR>"
|
||||
for(var/line in SSjob.job_debug)
|
||||
dat += "[line]<BR>"
|
||||
dat+= "*******<BR><BR>"
|
||||
for(var/datum/job/job in SSjob.occupations)
|
||||
if(!job)
|
||||
continue
|
||||
dat += "job: [job.title], current_positions: [job.current_positions], total_positions: [job.total_positions] <BR>"
|
||||
usr << browse(dat, "window=jobdebug;size=600x500")
|
||||
|
||||
if("show_admins")
|
||||
var/dat = "<B>Current admins:</B><HR>"
|
||||
if(GLOB.admin_datums)
|
||||
@@ -367,7 +354,7 @@
|
||||
continue
|
||||
if(is_special_character(H))
|
||||
continue
|
||||
var/datum/antagonist/traitor/human/T = new()
|
||||
var/datum/antagonist/traitor/T = new()
|
||||
T.give_objectives = FALSE
|
||||
var/datum/objective/new_objective = new
|
||||
new_objective.owner = H
|
||||
@@ -433,7 +420,7 @@
|
||||
H.equip_to_slot_or_del(I, SLOT_W_UNIFORM)
|
||||
qdel(olduniform)
|
||||
if(droptype == "Yes")
|
||||
I.flags_1 |= NODROP_1
|
||||
I.item_flags |= NODROP
|
||||
else
|
||||
to_chat(H, "You're not kawaii enough for this.")
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
if(M.client.prefs.toggles & SOUND_MIDI)
|
||||
M.playsound_local(M, sound_file, sound_volume, FALSE, channel = CHANNEL_ADMIN, pressure_affected = FALSE)
|
||||
if(user)
|
||||
log_admin("[ADMIN_LOOKUPFLW(user)] activated a sound emitter with file \"[sound_file]\" at [COORD(src)]")
|
||||
log_admin("[ADMIN_LOOKUPFLW(user)] activated a sound emitter with file \"[sound_file]\" at [AREACOORD(src)]")
|
||||
flick("shield1", src)
|
||||
|
||||
#undef SOUND_EMITTER_LOCAL
|
||||
|
||||
@@ -11,11 +11,16 @@
|
||||
new_ckey = sanitizeSQL(new_ckey)
|
||||
var/datum/DBQuery/query_find_ckey = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ckey = '[new_ckey]'")
|
||||
if(!query_find_ckey.warn_execute())
|
||||
qdel(query_find_ckey)
|
||||
return
|
||||
if(!query_find_ckey.NextRow())
|
||||
if(alert(usr, "[new_ckey] has not been seen before, are you sure you want to create a [type] for them?", "Unknown ckey", "Yes", "No", "Cancel") != "Yes")
|
||||
qdel(query_find_ckey)
|
||||
return
|
||||
qdel(query_find_ckey)
|
||||
target_ckey = new_ckey
|
||||
if(QDELETED(usr))
|
||||
return
|
||||
if(target_ckey)
|
||||
target_ckey = sanitizeSQL(target_ckey)
|
||||
if(!admin_ckey)
|
||||
@@ -46,11 +51,14 @@
|
||||
else
|
||||
return
|
||||
var/datum/DBQuery/query_create_message = SSdbcore.NewQuery("INSERT INTO [format_table_name("messages")] (type, targetckey, adminckey, text, timestamp, server, server_ip, server_port, round_id, secret) VALUES ('[type]', '[target_ckey]', '[admin_ckey]', '[text]', '[timestamp]', '[server]', INET_ATON(IF('[world.internet_address]' LIKE '', '0', '[world.internet_address]')), '[world.port]', '[GLOB.round_id]','[secret]')")
|
||||
var/pm = "[key_name(usr)] has created a [type][(type == "note" || type == "message" || type == "watchlist entry") ? " for [target_ckey]" : ""]: [text]"
|
||||
var/header = "[key_name_admin(usr)] has created a [type][(type == "note" || type == "message" || type == "watchlist entry") ? " for [target_ckey]" : ""]"
|
||||
if(!query_create_message.warn_execute())
|
||||
qdel(query_create_message)
|
||||
return
|
||||
qdel(query_create_message)
|
||||
if(logged)
|
||||
log_admin_private("[key_name(usr)] has created a [type][(type == "note" || type == "message" || type == "watchlist entry") ? " for [target_ckey]" : ""]: [text]")
|
||||
var/header = "[key_name_admin(usr)] has created a [type][(type == "note" || type == "message" || type == "watchlist entry") ? " for [target_ckey]" : ""]"
|
||||
log_admin_private(pm)
|
||||
message_admins("[header]:<br>[text]")
|
||||
admin_ticket_log(target_ckey, "<font color='blue'>[header]</font>")
|
||||
admin_ticket_log(target_ckey, text)
|
||||
@@ -69,19 +77,25 @@
|
||||
var/type
|
||||
var/target_ckey
|
||||
var/text
|
||||
var/m1 = "[key_name(usr)] has deleted a [type][(type == "note" || type == "message" || type == "watchlist entry") ? " for" : " made by"] [target_ckey]: [text]"
|
||||
var/m2 = "[key_name_admin(usr)] has deleted a [type][(type == "note" || type == "message" || type == "watchlist entry") ? " for" : " made by"] [target_ckey]:<br>[text]"
|
||||
var/datum/DBQuery/query_find_del_message = SSdbcore.NewQuery("SELECT type, targetckey, adminckey, text FROM [format_table_name("messages")] WHERE id = [message_id] AND deleted = 0")
|
||||
if(!query_find_del_message.warn_execute())
|
||||
qdel(query_find_del_message)
|
||||
return
|
||||
if(query_find_del_message.NextRow())
|
||||
type = query_find_del_message.item[1]
|
||||
target_ckey = query_find_del_message.item[2]
|
||||
text = query_find_del_message.item[4]
|
||||
qdel(query_find_del_message)
|
||||
var/datum/DBQuery/query_del_message = SSdbcore.NewQuery("UPDATE [format_table_name("messages")] SET deleted = 1 WHERE id = [message_id]")
|
||||
if(!query_del_message.warn_execute())
|
||||
qdel(query_del_message)
|
||||
return
|
||||
qdel(query_del_message)
|
||||
if(logged)
|
||||
log_admin_private("[key_name(usr)] has deleted a [type][(type == "note" || type == "message" || type == "watchlist entry") ? " for" : " made by"] [target_ckey]: [text]")
|
||||
message_admins("[key_name_admin(usr)] has deleted a [type][(type == "note" || type == "message" || type == "watchlist entry") ? " for" : " made by"] [target_ckey]:<br>[text]")
|
||||
log_admin_private(m1)
|
||||
message_admins(m2)
|
||||
if(browse)
|
||||
browse_messages("[type]")
|
||||
else
|
||||
@@ -96,6 +110,7 @@
|
||||
return
|
||||
var/datum/DBQuery/query_find_edit_message = SSdbcore.NewQuery("SELECT type, targetckey, adminckey, text FROM [format_table_name("messages")] WHERE id = [message_id] AND deleted = 0")
|
||||
if(!query_find_edit_message.warn_execute())
|
||||
qdel(query_find_edit_message)
|
||||
return
|
||||
if(query_find_edit_message.NextRow())
|
||||
var/type = query_find_edit_message.item[1]
|
||||
@@ -105,11 +120,13 @@
|
||||
var/editor_ckey = sanitizeSQL(usr.ckey)
|
||||
var/new_text = input("Input new [type]", "New [type]", "[old_text]") as null|message
|
||||
if(!new_text)
|
||||
qdel(query_find_edit_message)
|
||||
return
|
||||
new_text = sanitizeSQL(new_text)
|
||||
var/edit_text = sanitizeSQL("Edited by [editor_ckey] on [SQLtime()] from<br>[old_text]<br>to<br>[new_text]<hr>")
|
||||
var/datum/DBQuery/query_edit_message = SSdbcore.NewQuery("UPDATE [format_table_name("messages")] SET text = '[new_text]', lasteditor = '[editor_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE id = [message_id] AND deleted = 0")
|
||||
if(!query_edit_message.warn_execute())
|
||||
qdel(query_find_edit_message)
|
||||
return
|
||||
log_admin_private("[key_name(usr)] has edited a [type] [(type == "note" || type == "message" || type == "watchlist entry") ? " for [target_ckey]" : ""] made by [admin_ckey] from [old_text] to [new_text]")
|
||||
message_admins("[key_name_admin(usr)] has edited a [type] [(type == "note" || type == "message" || type == "watchlist entry") ? " for [target_ckey]" : ""] made by [admin_ckey] from<br>[old_text]<br>to<br>[new_text]")
|
||||
@@ -117,6 +134,7 @@
|
||||
browse_messages("[type]")
|
||||
else
|
||||
browse_messages(target_ckey = target_ckey, agegate = TRUE)
|
||||
qdel(query_find_edit_message)
|
||||
|
||||
/proc/toggle_message_secrecy(message_id)
|
||||
if(!SSdbcore.Connect())
|
||||
@@ -125,30 +143,38 @@
|
||||
message_id = text2num(message_id)
|
||||
if(!message_id)
|
||||
return
|
||||
var/editor_ckey = usr.ckey
|
||||
var/kn = key_name(usr)
|
||||
var/kna = key_name_admin(usr)
|
||||
var/datum/DBQuery/query_find_message_secret = SSdbcore.NewQuery("SELECT type, targetckey, adminckey, secret FROM [format_table_name("messages")] WHERE id = [message_id] AND deleted = 0")
|
||||
if(!query_find_message_secret.warn_execute())
|
||||
qdel(query_find_message_secret)
|
||||
return
|
||||
if(query_find_message_secret.NextRow())
|
||||
var/type = query_find_message_secret.item[1]
|
||||
var/target_ckey = query_find_message_secret.item[2]
|
||||
var/admin_ckey = query_find_message_secret.item[3]
|
||||
var/secret = text2num(query_find_message_secret.item[4])
|
||||
var/editor_ckey = sanitizeSQL(usr.ckey)
|
||||
editor_ckey = sanitizeSQL(editor_ckey)
|
||||
var/edit_text = "Made [secret ? "not secret" : "secret"] by [editor_ckey] on [SQLtime()]<hr>"
|
||||
var/datum/DBQuery/query_message_secret = SSdbcore.NewQuery("UPDATE [format_table_name("messages")] SET secret = NOT secret, lasteditor = '[editor_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE id = [message_id]")
|
||||
if(!query_message_secret.warn_execute())
|
||||
qdel(query_find_message_secret)
|
||||
qdel(query_message_secret)
|
||||
return
|
||||
log_admin_private("[key_name(usr)] has toggled [target_ckey]'s [type] made by [admin_ckey] to [secret ? "not secret" : "secret"]")
|
||||
message_admins("[key_name_admin(usr)] has toggled [target_ckey]'s [type] made by [admin_ckey] to [secret ? "not secret" : "secret"]")
|
||||
qdel(query_message_secret)
|
||||
log_admin_private("[kn] has toggled [target_ckey]'s [type] made by [admin_ckey] to [secret ? "not secret" : "secret"]")
|
||||
message_admins("[kna] has toggled [target_ckey]'s [type] made by [admin_ckey] to [secret ? "not secret" : "secret"]")
|
||||
browse_messages(target_ckey = target_ckey, agegate = TRUE)
|
||||
qdel(query_find_message_secret)
|
||||
|
||||
/proc/browse_messages(type, target_ckey, index, linkless = FALSE, filter, agegate = FALSE)
|
||||
if(!SSdbcore.Connect())
|
||||
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
|
||||
return
|
||||
var/output
|
||||
var/list/output = list()
|
||||
var/ruler = "<hr style='background:#000000; border:0; height:3px'>"
|
||||
var/navbar = "<a href='?_src_=holder;[HrefToken()];nonalpha=1'>\[All\]</a>|<a href='?_src_=holder;[HrefToken()];nonalpha=2'>\[#\]</a>"
|
||||
var/list/navbar = list("<a href='?_src_=holder;[HrefToken()];nonalpha=1'>\[All\]</a>|<a href='?_src_=holder;[HrefToken()];nonalpha=2'>\[#\]</a>")
|
||||
for(var/letter in GLOB.alphabet)
|
||||
navbar += "|<a href='?_src_=holder;[HrefToken()];showmessages=[letter]'>\[[letter]\]</a>"
|
||||
navbar += "|<a href='?_src_=holder;[HrefToken()];showmemo=1'>\[Memos\]</a>|<a href='?_src_=holder;[HrefToken()];showwatch=1'>\[Watchlist\]</a>"
|
||||
@@ -173,8 +199,11 @@
|
||||
output += ruler
|
||||
var/datum/DBQuery/query_get_type_messages = SSdbcore.NewQuery("SELECT id, targetckey, adminckey, text, timestamp, server, lasteditor FROM [format_table_name("messages")] WHERE type = '[type]' AND deleted = 0")
|
||||
if(!query_get_type_messages.warn_execute())
|
||||
qdel(query_get_type_messages)
|
||||
return
|
||||
while(query_get_type_messages.NextRow())
|
||||
if(QDELETED(usr))
|
||||
return
|
||||
var/id = query_get_type_messages.item[1]
|
||||
var/t_ckey = query_get_type_messages.item[2]
|
||||
if(type == "watchlist entry" && filter && !(t_ckey in GLOB.directory))
|
||||
@@ -193,16 +222,20 @@
|
||||
if(editor_ckey)
|
||||
output += " <font size='2'>Last edit by [editor_ckey] <a href='?_src_=holder;[HrefToken()];messageedits=[id]'>(Click here to see edit log)</a></font>"
|
||||
output += "<br>[text]<hr style='background:#000000; border:0; height:1px'>"
|
||||
qdel(query_get_type_messages)
|
||||
if(target_ckey)
|
||||
target_ckey = sanitizeSQL(target_ckey)
|
||||
var/datum/DBQuery/query_get_messages = SSdbcore.NewQuery("SELECT type, secret, id, adminckey, text, timestamp, server, lasteditor, DATEDIFF(NOW(), timestamp) AS `age` FROM [format_table_name("messages")] WHERE type <> 'memo' AND targetckey = '[target_ckey]' AND deleted = 0 ORDER BY timestamp DESC")
|
||||
if(!query_get_messages.warn_execute())
|
||||
qdel(query_get_messages)
|
||||
return
|
||||
var/messagedata
|
||||
var/watchdata
|
||||
var/notedata
|
||||
var/list/messagedata = list()
|
||||
var/list/watchdata = list()
|
||||
var/list/notedata = list()
|
||||
var/skipped = 0
|
||||
while(query_get_messages.NextRow())
|
||||
if(QDELETED(usr))
|
||||
return
|
||||
type = query_get_messages.item[1]
|
||||
if(type == "memo")
|
||||
continue
|
||||
@@ -230,8 +263,7 @@
|
||||
skipped = TRUE
|
||||
alphatext = "filter: alpha(opacity=[alpha]); opacity: [alpha/100];"
|
||||
|
||||
var/data
|
||||
data += "<p style='margin:0px;[alphatext]'> <b>[timestamp] | [server] | [admin_ckey]</b>"
|
||||
var/list/data = list("<p style='margin:0px;[alphatext]'> <b>[timestamp] | [server] | [admin_ckey]</b>")
|
||||
if(!linkless)
|
||||
data += " <a href='?_src_=holder;[HrefToken()];deletemessage=[id]'>\[Delete\]</a>"
|
||||
if(type == "note")
|
||||
@@ -254,6 +286,7 @@
|
||||
watchdata += data
|
||||
if("note")
|
||||
notedata += data
|
||||
qdel(query_get_messages)
|
||||
output += "<h2><center>[target_ckey]</center></h2><center>"
|
||||
if(!linkless)
|
||||
output += "<a href='?_src_=holder;[HrefToken()];addnote=[target_ckey]'>\[Add note\]</a>"
|
||||
@@ -297,16 +330,20 @@
|
||||
search = "^[index]"
|
||||
var/datum/DBQuery/query_list_messages = SSdbcore.NewQuery("SELECT DISTINCT targetckey FROM [format_table_name("messages")] WHERE type <> 'memo' AND targetckey REGEXP '[search]' AND deleted = 0 ORDER BY targetckey")
|
||||
if(!query_list_messages.warn_execute())
|
||||
qdel(query_list_messages)
|
||||
return
|
||||
while(query_list_messages.NextRow())
|
||||
if(QDELETED(usr))
|
||||
return
|
||||
index_ckey = query_list_messages.item[1]
|
||||
output += "<a href='?_src_=holder;[HrefToken()];showmessageckey=[index_ckey]'>[index_ckey]</a><br>"
|
||||
qdel(query_list_messages)
|
||||
else if(!type && !target_ckey && !index)
|
||||
output += "<center></a> <a href='?_src_=holder;[HrefToken()];addmessageempty=1'>\[Add message\]</a><a href='?_src_=holder;[HrefToken()];addwatchempty=1'>\[Add watchlist entry\]</a><a href='?_src_=holder;[HrefToken()];addnoteempty=1'>\[Add note\]</a></center>"
|
||||
output += ruler
|
||||
usr << browse({"<!DOCTYPE html><html><head><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /></head><body>[output]</body></html>"}, "window=browse_messages;size=900x500")
|
||||
usr << browse({"<!DOCTYPE html><html><head><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /></head><body>[jointext(output, "")]</body></html>"}, "window=browse_messages;size=900x500")
|
||||
|
||||
proc/get_message_output(type, target_ckey)
|
||||
/proc/get_message_output(type, target_ckey)
|
||||
if(!SSdbcore.Connect())
|
||||
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
|
||||
return
|
||||
@@ -320,6 +357,7 @@ proc/get_message_output(type, target_ckey)
|
||||
query += " AND targetckey = '[target_ckey]'"
|
||||
var/datum/DBQuery/query_get_message_output = SSdbcore.NewQuery(query)
|
||||
if(!query_get_message_output.warn_execute())
|
||||
qdel(query_get_message_output)
|
||||
return
|
||||
while(query_get_message_output.NextRow())
|
||||
var/message_id = query_get_message_output.item[1]
|
||||
@@ -333,7 +371,10 @@ proc/get_message_output(type, target_ckey)
|
||||
output += "<br><font color='red'>[text]</font><br>"
|
||||
var/datum/DBQuery/query_message_read = SSdbcore.NewQuery("UPDATE [format_table_name("messages")] SET type = 'message sent' WHERE id = [message_id]")
|
||||
if(!query_message_read.warn_execute())
|
||||
qdel(query_get_message_output)
|
||||
qdel(query_message_read)
|
||||
return
|
||||
qdel(query_message_read)
|
||||
if("watchlist entry")
|
||||
message_admins("<font color='red'><B>Notice: </B></font><font color='blue'>[key_name_admin(target_ckey)] has been on the watchlist since [timestamp] and has just connected - Reason: [text]</font>")
|
||||
send2irc_adminless_only("Watchlist", "[key_name(target_ckey)] is on the watchlist and has just connected - Reason: [text]")
|
||||
@@ -342,6 +383,7 @@ proc/get_message_output(type, target_ckey)
|
||||
if(editor_ckey)
|
||||
output += "<br><span class='memoedit'>Last edit by [editor_ckey] <A href='?_src_=holder;[HrefToken()];messageedits=[message_id]'>(Click here to see edit log)</A></span>"
|
||||
output += "<br>[text]</span><br>"
|
||||
qdel(query_get_message_output)
|
||||
return output
|
||||
|
||||
#define NOTESFILE "data/player_notes.sav"
|
||||
@@ -366,9 +408,11 @@ proc/get_message_output(type, target_ckey)
|
||||
var/admin_ckey = note.group[3]
|
||||
var/datum/DBQuery/query_convert_time = SSdbcore.NewQuery("SELECT ADDTIME(STR_TO_DATE('[timestamp]','%d-%b-%Y'), '0')")
|
||||
if(!query_convert_time.Execute())
|
||||
qdel(query_convert_time)
|
||||
return
|
||||
if(query_convert_time.NextRow())
|
||||
timestamp = query_convert_time.item[1]
|
||||
qdel(query_convert_time)
|
||||
if(ckey && notetext && timestamp && admin_ckey && server)
|
||||
create_message("note", ckey, admin_ckey, notetext, timestamp, server, 1, 0)
|
||||
notesfile.cd = "/"
|
||||
|
||||
+35
-43
@@ -74,7 +74,7 @@
|
||||
message_admins("[key_name_admin(usr)] tried to create traitors. Unfortunately, there were no candidates available.")
|
||||
log_admin("[key_name(usr)] failed to create traitors.")
|
||||
if("changelings")
|
||||
if(src.makeChanglings())
|
||||
if(src.makeChangelings())
|
||||
message_admins("[key_name(usr)] created changelings.")
|
||||
log_admin("[key_name(usr)] created changelings.")
|
||||
else
|
||||
@@ -447,6 +447,8 @@
|
||||
if("Yes")
|
||||
delmob = 1
|
||||
|
||||
log_admin("[key_name(usr)] has used rudimentary transformation on [key_name(M)]. Transforming to [href_list["simplemake"]].; deletemob=[delmob]")
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has used rudimentary transformation on [key_name_admin(M)]. Transforming to [href_list["simplemake"]].; deletemob=[delmob]</span>")
|
||||
switch(href_list["simplemake"])
|
||||
if("observer")
|
||||
M.change_mob_type( /mob/dead/observer , null, null, delmob )
|
||||
@@ -499,8 +501,6 @@
|
||||
M.change_mob_type( /mob/living/simple_animal/hostile/construct/wraith , null, null, delmob )
|
||||
if("shade")
|
||||
M.change_mob_type( /mob/living/simple_animal/shade , null, null, delmob )
|
||||
log_admin("[key_name(usr)] has used rudimentary transformation on [key_name(M)]. Transforming to [href_list["simplemake"]].; deletemob=[delmob]")
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has used rudimentary transformation on [key_name_admin(M)]. Transforming to [href_list["simplemake"]].; deletemob=[delmob]</span>")
|
||||
|
||||
|
||||
/////////////////////////////////////new ban stuff
|
||||
@@ -1058,14 +1058,21 @@
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
var/mob/M = locate(href_list["boot2"])
|
||||
if (ismob(M))
|
||||
if(ismob(M))
|
||||
if(!check_if_greater_rights_than(M.client))
|
||||
to_chat(usr, "<span class='danger'>Error: They have more rights than you do.</span>")
|
||||
return
|
||||
if(alert(usr, "Kick [key_name(M)]?", "Confirm", "Yes", "No") != "Yes")
|
||||
return
|
||||
if(!M)
|
||||
to_chat(usr, "<span class='danger'>Error: [M] no longer exists!</span>")
|
||||
return
|
||||
if(!M.client)
|
||||
to_chat(usr, "<span class='danger'>Error: [M] no longer has a client!</span>")
|
||||
return
|
||||
to_chat(M, "<span class='danger'>You have been kicked from the server by [usr.client.holder.fakekey ? "an Administrator" : "[usr.client.ckey]"].</span>")
|
||||
log_admin("[key_name(usr)] kicked [key_name(M)].")
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] kicked [key_name_admin(M)].</span>")
|
||||
//M.client = null
|
||||
qdel(M.client)
|
||||
|
||||
else if(href_list["addmessage"])
|
||||
@@ -1193,10 +1200,13 @@
|
||||
var/message_id = sanitizeSQL("[href_list["messageedits"]]")
|
||||
var/datum/DBQuery/query_get_message_edits = SSdbcore.NewQuery("SELECT edits FROM [format_table_name("messages")] WHERE id = '[message_id]'")
|
||||
if(!query_get_message_edits.warn_execute())
|
||||
qdel(query_get_message_edits)
|
||||
return
|
||||
if(query_get_message_edits.NextRow())
|
||||
var/edit_log = query_get_message_edits.item[1]
|
||||
usr << browse(edit_log,"window=noteedits")
|
||||
if(!QDELETED(usr))
|
||||
usr << browse(edit_log,"window=noteedits")
|
||||
qdel(query_get_message_edits)
|
||||
|
||||
else if(href_list["newban"])
|
||||
if(!check_rights(R_BAN))
|
||||
@@ -1815,43 +1825,25 @@
|
||||
usr.client.smite(H)
|
||||
|
||||
else if(href_list["CentComReply"])
|
||||
var/mob/living/carbon/human/H = locate(href_list["CentComReply"]) in GLOB.mob_list
|
||||
if(!istype(H))
|
||||
to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human")
|
||||
return
|
||||
if(!istype(H.ears, /obj/item/radio/headset))
|
||||
to_chat(usr, "The person you are trying to contact is not wearing a headset.")
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
message_admins("[src.owner] has started answering [key_name(H)]'s CentCom request.")
|
||||
var/input = input(src.owner, "Please enter a message to reply to [key_name(H)] via their headset.","Outgoing message from CentCom", "")
|
||||
if(!input)
|
||||
message_admins("[src.owner] decided not to answer [key_name(H)]'s CentCom request.")
|
||||
return
|
||||
|
||||
log_admin("[src.owner] replied to [key_name(H)]'s CentCom message with the message [input].")
|
||||
message_admins("[src.owner] replied to [key_name(H)]'s CentCom message with: \"[input]\"")
|
||||
to_chat(H, "You hear something crackle in your ears for a moment before a voice speaks. \"Please stand by for a message from Central Command. Message as follows. [input]. Message ends.\"")
|
||||
var/mob/M = locate(href_list["CentComReply"])
|
||||
usr.client.admin_headset_message(M, "CentCom")
|
||||
|
||||
else if(href_list["SyndicateReply"])
|
||||
var/mob/living/carbon/human/H = locate(href_list["SyndicateReply"])
|
||||
if(!istype(H))
|
||||
to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human.")
|
||||
return
|
||||
if(!istype(H.ears, /obj/item/radio/headset))
|
||||
to_chat(usr, "The person you are trying to contact is not wearing a headset.")
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
message_admins("[src.owner] has started answering [key_name(H)]'s syndicate request.")
|
||||
var/input = input(src.owner, "Please enter a message to reply to [key_name(H)] via their headset.","Outgoing message from The Syndicate", "")
|
||||
if(!input)
|
||||
message_admins("[src.owner] decided not to answer [key_name(H)]'s syndicate request.")
|
||||
var/mob/M = locate(href_list["SyndicateReply"])
|
||||
usr.client.admin_headset_message(M, "Syndicate")
|
||||
|
||||
else if(href_list["HeadsetMessage"])
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
to_chat(src.owner, "You sent [input] to [H] via a secure channel.")
|
||||
log_admin("[src.owner] replied to [key_name(H)]'s Syndicate message with the message [input].")
|
||||
message_admins("[src.owner] replied to [key_name(H)]'s Syndicate message with: \"[input]\"")
|
||||
to_chat(H, "You hear something crackle in your ears for a moment before a voice speaks. \"Please stand by for a message from your benefactor. Message as follows, agent. [input]. Message ends.\"")
|
||||
var/mob/M = locate(href_list["HeadsetMessage"])
|
||||
usr.client.admin_headset_message(M)
|
||||
|
||||
else if(href_list["reject_custom_name"])
|
||||
if(!check_rights(R_ADMIN))
|
||||
@@ -1905,7 +1897,7 @@
|
||||
to_chat(usr, "This can only be used on instances of type /mob.")
|
||||
return
|
||||
|
||||
show_individual_logging_panel(M, href_list["log_type"])
|
||||
show_individual_logging_panel(M, href_list["log_src"], href_list["log_type"])
|
||||
else if(href_list["languagemenu"])
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
@@ -2014,10 +2006,9 @@
|
||||
var/X = offset.len > 0 ? text2num(offset[1]) : 0
|
||||
var/Y = offset.len > 1 ? text2num(offset[2]) : 0
|
||||
var/Z = offset.len > 2 ? text2num(offset[3]) : 0
|
||||
var/tmp_dir = href_list["object_dir"]
|
||||
var/obj_dir = tmp_dir ? text2num(tmp_dir) : 2
|
||||
if(!obj_dir || !(obj_dir in list(1,2,4,8,5,6,9,10)))
|
||||
obj_dir = 2
|
||||
var/obj_dir = text2num(href_list["object_dir"])
|
||||
if(obj_dir && !(obj_dir in list(1,2,4,8,5,6,9,10)))
|
||||
obj_dir = null
|
||||
var/obj_name = sanitize(href_list["object_name"])
|
||||
|
||||
|
||||
@@ -2060,9 +2051,10 @@
|
||||
N.name = obj_name
|
||||
else
|
||||
var/atom/O = new path(target)
|
||||
if(O)
|
||||
O.admin_spawned = TRUE
|
||||
O.setDir(obj_dir)
|
||||
if(!QDELETED(O))
|
||||
O.flags_1 |= ADMIN_SPAWNED_1
|
||||
if(obj_dir)
|
||||
O.setDir(obj_dir)
|
||||
if(obj_name)
|
||||
O.name = obj_name
|
||||
if(ismob(O))
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
return
|
||||
|
||||
var/list/refs = list()
|
||||
var/where_used = FALSE
|
||||
for(var/list/query_tree in querys)
|
||||
var/list/from_objs = list()
|
||||
var/list/select_types = list()
|
||||
@@ -82,6 +83,7 @@
|
||||
objs_all = objs.len
|
||||
|
||||
if("where" in query_tree)
|
||||
where_used = TRUE
|
||||
var/objs_temp = objs
|
||||
objs = list()
|
||||
for(var/datum/d in objs_temp)
|
||||
@@ -119,7 +121,7 @@
|
||||
var/end_time = REALTIMEOFDAY
|
||||
end_time -= start_time
|
||||
return list("<span class='admin'>SDQL query results: [query_text]</span>",\
|
||||
"<span class='admin'>SDQL query completed: [objs_all] objects selected by path, and [objs_eligible] objects executed on after WHERE filtering if applicable.</span>",\
|
||||
"<span class='admin'>SDQL query completed: [objs_all] objects selected by path, and [where_used ? objs_eligible : objs_all] objects executed on after WHERE filtering if applicable.</span>",\
|
||||
"<span class='admin'>SDQL query took [DisplayTimeText(end_time)] to complete.</span>") + refs
|
||||
|
||||
/proc/SDQL_qdel_datum(datum/d)
|
||||
|
||||
@@ -256,7 +256,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
|
||||
/datum/admin_help/proc/MessageNoRecipient(msg)
|
||||
var/ref_src = "[REF(src)]"
|
||||
//Message to be sent to all admins
|
||||
var/admin_msg = "<span class='adminnotice'><span class='adminhelp'>Ticket [TicketHref("#[id]", ref_src)]</span><b>: [LinkedReplyName(ref_src)] [FullMonty(ref_src)]:</b> [keywords_lookup(msg)]</span>"
|
||||
var/admin_msg = "<span class='adminnotice'><span class='adminhelp'>Ticket [TicketHref("#[id]", ref_src)]</span><b>: [LinkedReplyName(ref_src)] [FullMonty(ref_src)]:</b> <span class='linkify'>[keywords_lookup(msg)]</span></span>"
|
||||
|
||||
AddInteraction("<font color='red'>[LinkedReplyName(ref_src)]: [msg]</font>")
|
||||
|
||||
@@ -268,7 +268,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
|
||||
to_chat(X, admin_msg)
|
||||
|
||||
//show it to the person adminhelping too
|
||||
to_chat(initiator, "<span class='adminnotice'>PM to-<b>Admins</b>: [msg]</span>")
|
||||
to_chat(initiator, "<span class='adminnotice'>PM to-<b>Admins</b>: <span class='linkify'>[msg]</span></span>")
|
||||
|
||||
//Reopen a closed ticket
|
||||
/datum/admin_help/proc/Reopen()
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
to_chat(src, "Nowhere to jump to!")
|
||||
return
|
||||
usr.forceMove(T)
|
||||
log_admin("[key_name(usr)] jumped to [A]")
|
||||
message_admins("[key_name_admin(usr)] jumped to [A]")
|
||||
log_admin("[key_name(usr)] jumped to [AREACOORD(A)]")
|
||||
message_admins("[key_name_admin(usr)] jumped to [AREACOORD(A)]")
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Jump To Area") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/jumptoturf(turf/T in world)
|
||||
@@ -31,8 +31,8 @@
|
||||
to_chat(src, "Only administrators may use this command.")
|
||||
return
|
||||
|
||||
log_admin("[key_name(usr)] jumped to [T.x],[T.y],[T.z] in [T.loc]")
|
||||
message_admins("[key_name_admin(usr)] jumped to [T.x],[T.y],[T.z] in [T.loc]")
|
||||
log_admin("[key_name(usr)] jumped to [AREACOORD(T)]")
|
||||
message_admins("[key_name_admin(usr)] jumped to [AREACOORD(T)]")
|
||||
usr.forceMove(T)
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Jump To Turf") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
return
|
||||
@@ -46,7 +46,7 @@
|
||||
return
|
||||
|
||||
log_admin("[key_name(usr)] jumped to [key_name(M)]")
|
||||
message_admins("[key_name_admin(usr)] jumped to [key_name_admin(M)]")
|
||||
message_admins("[key_name_admin(usr)] jumped to [ADMIN_LOOKUPFLW(M)] at [AREACOORD(M)]")
|
||||
if(src.mob)
|
||||
var/mob/A = src.mob
|
||||
var/turf/T = get_turf(M)
|
||||
@@ -89,7 +89,7 @@
|
||||
return
|
||||
var/mob/M = selection.mob
|
||||
log_admin("[key_name(usr)] jumped to [key_name(M)]")
|
||||
message_admins("[key_name_admin(usr)] jumped to [key_name_admin(M)]")
|
||||
message_admins("[key_name_admin(usr)] jumped to [ADMIN_LOOKUPFLW(M)]")
|
||||
|
||||
usr.forceMove(M.loc)
|
||||
|
||||
@@ -104,8 +104,8 @@
|
||||
return
|
||||
|
||||
var/atom/loc = get_turf(usr)
|
||||
log_admin("[key_name(usr)] teleported [key_name(M)] to [COORD(loc)]")
|
||||
var/msg = "[key_name_admin(usr)] teleported [key_name_admin(M)] to [ADMIN_COORDJMP(loc)]"
|
||||
log_admin("[key_name(usr)] teleported [key_name(M)] to [AREACOORD(loc)]")
|
||||
var/msg = "[key_name_admin(usr)] teleported [ADMIN_LOOKUPFLW(M)] to [ADMIN_VERBOSEJMP(loc)]"
|
||||
message_admins(msg)
|
||||
admin_ticket_log(M, msg)
|
||||
M.forceMove(loc)
|
||||
@@ -131,7 +131,7 @@
|
||||
if(!M)
|
||||
return
|
||||
log_admin("[key_name(usr)] teleported [key_name(M)]")
|
||||
var/msg = "[key_name_admin(usr)] teleported [key_name_admin(M)]"
|
||||
var/msg = "[key_name_admin(usr)] teleported [ADMIN_LOOKUPFLW(M)]"
|
||||
message_admins(msg)
|
||||
admin_ticket_log(M, msg)
|
||||
if(M)
|
||||
@@ -149,8 +149,8 @@
|
||||
if(A && istype(A))
|
||||
if(M.forceMove(safepick(get_area_turfs(A))))
|
||||
|
||||
log_admin("[key_name(usr)] teleported [key_name(M)] to [A]")
|
||||
var/msg = "[key_name_admin(usr)] teleported [key_name_admin(M)] to [A]"
|
||||
log_admin("[key_name(usr)] teleported [key_name(M)] to [AREACOORD(A)]")
|
||||
var/msg = "[key_name_admin(usr)] teleported [ADMIN_LOOKUPFLW(M)] to [AREACOORD(A)]"
|
||||
message_admins(msg)
|
||||
admin_ticket_log(M, msg)
|
||||
else
|
||||
|
||||
@@ -8,9 +8,6 @@
|
||||
if(!holder)
|
||||
to_chat(src, "<font color='red'>Error: Admin-PM-Context: Only administrators may use this command.</font>")
|
||||
return
|
||||
if(holder && !check_rights(R_ADMIN, TRUE))
|
||||
to_chat(src, "<font color='red'>Error: Admin-PM-Context: Only administrators may use this command.</font>")
|
||||
return
|
||||
if( !ismob(M) || !M.client )
|
||||
return
|
||||
cmd_admin_pm(M.client,null)
|
||||
@@ -23,9 +20,6 @@
|
||||
if(!holder)
|
||||
to_chat(src, "<font color='red'>Error: Admin-PM-Panel: Only administrators may use this command.</font>")
|
||||
return
|
||||
if(holder && !check_rights(R_ADMIN, TRUE))
|
||||
to_chat(src, "<font color='red'>Error: Admin-PM-Context: Only administrators may use this command.</font>")
|
||||
return
|
||||
var/list/client/targets[0]
|
||||
for(var/client/T)
|
||||
if(T.mob)
|
||||
@@ -151,15 +145,15 @@
|
||||
var/keywordparsedmsg = keywords_lookup(msg)
|
||||
|
||||
if(irc)
|
||||
to_chat(src, "<font color='blue'>PM to-<b>Admins</b>: [rawmsg]</font>")
|
||||
to_chat(src, "<font color='blue'>PM to-<b>Admins</b>: <span class='linkify'>[rawmsg]</span></font>")
|
||||
var/datum/admin_help/AH = admin_ticket_log(src, "<font color='red'>Reply PM from-<b>[key_name(src, TRUE, TRUE)] to <i>IRC</i>: [keywordparsedmsg]</font>")
|
||||
ircreplyamount--
|
||||
send2irc("[AH ? "#[AH.id] " : ""]Reply: [ckey]", rawmsg)
|
||||
else
|
||||
if(recipient.holder)
|
||||
if(holder) //both are admins
|
||||
to_chat(recipient, "<font color='red'>Admin PM from-<b>[key_name(src, recipient, 1)]</b>: [keywordparsedmsg]</font>")
|
||||
to_chat(src, "<font color='blue'>Admin PM to-<b>[key_name(recipient, src, 1)]</b>: [keywordparsedmsg]</font>")
|
||||
to_chat(recipient, "<font color='red'>Admin PM from-<b>[key_name(src, recipient, 1)]</b>: <span class='linkify'>[keywordparsedmsg]</span></font>")
|
||||
to_chat(src, "<font color='blue'>Admin PM to-<b>[key_name(recipient, src, 1)]</b>: <span class='linkify'>[keywordparsedmsg]</span></font>")
|
||||
|
||||
//omg this is dumb, just fill in both their tickets
|
||||
var/interaction_message = "<font color='purple'>PM from-<b>[key_name(src, recipient, 1)]</b> to-<b>[key_name(recipient, src, 1)]</b>: [keywordparsedmsg]</font>"
|
||||
@@ -168,12 +162,12 @@
|
||||
admin_ticket_log(recipient, interaction_message)
|
||||
|
||||
else //recipient is an admin but sender is not
|
||||
var/replymsg = "<font color='red'>Reply PM from-<b>[key_name(src, recipient, 1)]</b>: [keywordparsedmsg]</font>"
|
||||
var/replymsg = "<font color='red'>Reply PM from-<b>[key_name(src, recipient, 1)]</b>: <span class='linkify'>[keywordparsedmsg]</span></font>"
|
||||
admin_ticket_log(src, replymsg)
|
||||
to_chat(recipient, replymsg)
|
||||
to_chat(src, "<font color='blue'>PM to-<b>Admins</b>: [msg]</font>")
|
||||
to_chat(src, "<font color='blue'>PM to-<b>Admins</b>: <span class='linkify'>[msg]</span></font>")
|
||||
|
||||
//play the recieving admin the adminhelp sound (if they have them enabled)
|
||||
//play the receiving admin the adminhelp sound (if they have them enabled)
|
||||
if(recipient.prefs.toggles & SOUND_ADMINHELP)
|
||||
SEND_SOUND(recipient, sound('sound/effects/adminhelp.ogg'))
|
||||
|
||||
@@ -183,9 +177,9 @@
|
||||
new /datum/admin_help(msg, recipient, TRUE)
|
||||
|
||||
to_chat(recipient, "<font color='red' size='4'><b>-- Administrator private message --</b></font>")
|
||||
to_chat(recipient, "<font color='red'>Admin PM from-<b>[key_name(src, recipient, 0)]</b>: [msg]</font>")
|
||||
to_chat(recipient, "<font color='red'>Admin PM from-<b>[key_name(src, recipient, 0)]</b>: <span class='linkify'>[msg]</span></font>")
|
||||
to_chat(recipient, "<font color='red'><i>Click on the administrator's name to reply.</i></font>")
|
||||
to_chat(src, "<font color='blue'>Admin PM to-<b>[key_name(recipient, src, 1)]</b>: [msg]</font>")
|
||||
to_chat(src, "<font color='blue'>Admin PM to-<b>[key_name(recipient, src, 1)]</b>: <span class='linkify'>[msg]</span></font>")
|
||||
|
||||
admin_ticket_log(recipient, "<font color='blue'>PM From [key_name_admin(src)]: [keywordparsedmsg]</font>")
|
||||
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
log_talk(mob,"[key_name(src)] : [msg]",LOGASAY)
|
||||
msg = keywords_lookup(msg)
|
||||
if(check_rights(R_ADMIN,0))
|
||||
msg = "<span class='admin'><span class='prefix'>ADMIN:</span> <EM>[key_name(usr, 1)]</EM> [ADMIN_FLW(mob)]: <span class='message'>[msg]</span></span>"
|
||||
msg = "<span class='admin'><span class='prefix'>ADMIN:</span> <EM>[key_name(usr, 1)]</EM> [ADMIN_FLW(mob)]: <span class='message linkify'>[msg]</span></span>"
|
||||
to_chat(GLOB.admins, msg)
|
||||
else
|
||||
msg = "<span class='adminobserver'><span class='prefix'>ADMIN:</span> <EM>[key_name(usr, 1)]</EM> [ADMIN_FLW(mob)]: <span class='message'>[msg]</span></span>"
|
||||
msg = "<span class='adminobserver'><span class='prefix'>ADMIN:</span> <EM>[key_name(usr, 1)]</EM> [ADMIN_FLW(mob)]: <span class='message linkify'>[msg]</span></span>"
|
||||
to_chat(GLOB.admins, msg)
|
||||
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Asay") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
@@ -17,6 +17,6 @@ GLOBAL_VAR_INIT(terrorism, FALSE)
|
||||
qdel(I)
|
||||
var/obj/item/gun/energy/laser/LaserAK/AK = new(src)
|
||||
if(!GLOB.terrorism)
|
||||
AK.admin_spawned = TRUE //To prevent announcing
|
||||
AK.flags_1 |= ADMIN_SPAWNED_1 //To prevent announcing
|
||||
put_in_hands(AK)
|
||||
AK.pickup(src) //For the stun shielding
|
||||
|
||||
@@ -9,17 +9,17 @@
|
||||
//all plumbing - yes, some things might get stated twice, doesn't matter.
|
||||
for (var/obj/machinery/atmospherics/plumbing in GLOB.machines)
|
||||
if (plumbing.nodealert)
|
||||
to_chat(usr, "Unconnected [plumbing.name] located at [ADMIN_COORDJMP(plumbing)] ([get_area(plumbing.loc)])")
|
||||
to_chat(usr, "Unconnected [plumbing.name] located at [ADMIN_VERBOSEJMP(plumbing)]")
|
||||
|
||||
//Manifolds
|
||||
for (var/obj/machinery/atmospherics/pipe/manifold/pipe in GLOB.machines)
|
||||
if (!pipe.nodes[1] || !pipe.nodes[2] || !pipe.nodes[3])
|
||||
to_chat(usr, "Unconnected [pipe.name] located at [ADMIN_COORDJMP(pipe)] ([get_area(pipe.loc)])")
|
||||
to_chat(usr, "Unconnected [pipe.name] located at [ADMIN_VERBOSEJMP(pipe)]")
|
||||
|
||||
//Pipes
|
||||
for (var/obj/machinery/atmospherics/pipe/simple/pipe in GLOB.machines)
|
||||
if (!pipe.nodes[1] || !pipe.nodes[2])
|
||||
to_chat(usr, "Unconnected [pipe.name] located at [ADMIN_COORDJMP(pipe)] ([get_area(pipe.loc)])")
|
||||
to_chat(usr, "Unconnected [pipe.name] located at [ADMIN_VERBOSEJMP(pipe)]")
|
||||
|
||||
/client/proc/powerdebug()
|
||||
set category = "Mapping"
|
||||
@@ -33,9 +33,9 @@
|
||||
if (!PN.nodes || !PN.nodes.len)
|
||||
if(PN.cables && (PN.cables.len > 1))
|
||||
var/obj/structure/cable/C = PN.cables[1]
|
||||
to_chat(usr, "Powernet with no nodes! (number [PN.number]) - example cable at [ADMIN_COORDJMP(C)] in area [get_area(C.loc)]")
|
||||
to_chat(usr, "Powernet with no nodes! (number [PN.number]) - example cable at [ADMIN_VERBOSEJMP(C)]")
|
||||
|
||||
if (!PN.cables || (PN.cables.len < 10))
|
||||
if(PN.cables && (PN.cables.len > 1))
|
||||
var/obj/structure/cable/C = PN.cables[1]
|
||||
to_chat(usr, "Powernet with fewer than 10 cables! (number [PN.number]) - example cable at [ADMIN_COORDJMP(C)] in area [get_area(C.loc)]")
|
||||
to_chat(usr, "Powernet with fewer than 10 cables! (number [PN.number]) - example cable at [ADMIN_VERBOSEJMP(C)]")
|
||||
|
||||
@@ -87,11 +87,11 @@
|
||||
var/newcharge = input("New charge (0-[borg.cell.maxcharge]):", borg.name, borg.cell.charge) as num|null
|
||||
if (newcharge)
|
||||
borg.cell.charge = CLAMP(newcharge, 0, borg.cell.maxcharge)
|
||||
message_admins("[key_name_admin(user)] set the charge of [key_name_admin(borg)][ADMIN_FLW(borg)] to [borg.cell.charge].")
|
||||
message_admins("[key_name_admin(user)] set the charge of [ADMIN_LOOKUPFLW(borg)] to [borg.cell.charge].")
|
||||
log_admin("[key_name(user)] set the charge of [key_name(borg)] to [borg.cell.charge].")
|
||||
if ("remove_cell")
|
||||
QDEL_NULL(borg.cell)
|
||||
message_admins("[key_name_admin(user)] deleted the cell of [key_name_admin(borg)][ADMIN_FLW(borg)].")
|
||||
message_admins("[key_name_admin(user)] deleted the cell of [ADMIN_LOOKUPFLW(borg)].")
|
||||
log_admin("[key_name(user)] deleted the cell of [key_name(borg)].")
|
||||
if ("change_cell")
|
||||
var/chosen = pick_closest_path(null, make_types_fancy(typesof(/obj/item/stock_parts/cell)))
|
||||
@@ -104,45 +104,45 @@
|
||||
borg.cell = new_cell
|
||||
borg.cell.charge = borg.cell.maxcharge
|
||||
borg.diag_hud_set_borgcell()
|
||||
message_admins("[key_name_admin(user)] changed the cell of [key_name_admin(borg)][ADMIN_FLW(borg)] to [new_cell].")
|
||||
message_admins("[key_name_admin(user)] changed the cell of [ADMIN_LOOKUPFLW(borg)] to [new_cell].")
|
||||
log_admin("[key_name(user)] changed the cell of [key_name(borg)] to [new_cell].")
|
||||
if ("toggle_emagged")
|
||||
borg.SetEmagged(!borg.emagged)
|
||||
if (borg.emagged)
|
||||
message_admins("[key_name_admin(user)] emagged [key_name_admin(borg)][ADMIN_FLW(borg)].")
|
||||
message_admins("[key_name_admin(user)] emagged [ADMIN_LOOKUPFLW(borg)].")
|
||||
log_admin("[key_name(user)] emagged [key_name(borg)].")
|
||||
else
|
||||
message_admins("[key_name_admin(user)] un-emagged [key_name_admin(borg)][ADMIN_FLW(borg)].")
|
||||
message_admins("[key_name_admin(user)] un-emagged [ADMIN_LOOKUPFLW(borg)].")
|
||||
log_admin("[key_name(user)] un-emagged [key_name(borg)].")
|
||||
if ("toggle_lawupdate")
|
||||
borg.lawupdate = !borg.lawupdate
|
||||
if (borg.lawupdate)
|
||||
message_admins("[key_name_admin(user)] enabled lawsync on [key_name_admin(borg)][ADMIN_FLW(borg)].")
|
||||
message_admins("[key_name_admin(user)] enabled lawsync on [ADMIN_LOOKUPFLW(borg)].")
|
||||
log_admin("[key_name(user)] enabled lawsync on [key_name(borg)].")
|
||||
else
|
||||
message_admins("[key_name_admin(user)] disabled lawsync on [key_name_admin(borg)][ADMIN_FLW(borg)].")
|
||||
message_admins("[key_name_admin(user)] disabled lawsync on [ADMIN_LOOKUPFLW(borg)].")
|
||||
log_admin("[key_name(user)] disabled lawsync on [key_name(borg)].")
|
||||
if ("toggle_lockdown")
|
||||
borg.SetLockdown(!borg.lockcharge)
|
||||
if (borg.lockcharge)
|
||||
message_admins("[key_name_admin(user)] locked down [key_name_admin(borg)][ADMIN_FLW(borg)].")
|
||||
message_admins("[key_name_admin(user)] locked down [ADMIN_LOOKUPFLW(borg)].")
|
||||
log_admin("[key_name(user)] locked down [key_name(borg)].")
|
||||
else
|
||||
message_admins("[key_name_admin(user)] released [key_name_admin(borg)][ADMIN_FLW(borg)] from lockdown.")
|
||||
message_admins("[key_name_admin(user)] released [ADMIN_LOOKUPFLW(borg)] from lockdown.")
|
||||
log_admin("[key_name(user)] released [key_name(borg)] from lockdown.")
|
||||
if ("toggle_scrambledcodes")
|
||||
borg.scrambledcodes = !borg.scrambledcodes
|
||||
if (borg.scrambledcodes)
|
||||
message_admins("[key_name_admin(user)] enabled scrambled codes on [key_name_admin(borg)][ADMIN_FLW(borg)].")
|
||||
message_admins("[key_name_admin(user)] enabled scrambled codes on [ADMIN_LOOKUPFLW(borg)].")
|
||||
log_admin("[key_name(user)] enabled scrambled codes on [key_name(borg)].")
|
||||
else
|
||||
message_admins("[key_name_admin(user)] disabled scrambled codes on [key_name_admin(borg)][ADMIN_FLW(borg)].")
|
||||
message_admins("[key_name_admin(user)] disabled scrambled codes on [ADMIN_LOOKUPFLW(borg)].")
|
||||
log_admin("[key_name(user)] disabled scrambled codes on [key_name(borg)].")
|
||||
if ("rename")
|
||||
var/new_name = stripped_input(user,"What would you like to name this cyborg?","Input a name",borg.real_name,MAX_NAME_LEN)
|
||||
if(!new_name)
|
||||
return
|
||||
message_admins("[key_name_admin(user)] renamed [key_name_admin(borg)][ADMIN_FLW(borg)] to [new_name].")
|
||||
message_admins("[key_name_admin(user)] renamed [ADMIN_LOOKUPFLW(borg)] to [new_name].")
|
||||
log_admin("[key_name(user)] renamed [key_name(borg)] to [new_name].")
|
||||
borg.fully_replace_character_name(borg.real_name,new_name)
|
||||
if ("toggle_upgrade")
|
||||
@@ -151,14 +151,14 @@
|
||||
if (installedupgrade)
|
||||
installedupgrade.deactivate(borg, user)
|
||||
borg.upgrades -= installedupgrade
|
||||
message_admins("[key_name_admin(user)] removed the [installedupgrade] upgrade from [key_name_admin(borg)][ADMIN_FLW(borg)].")
|
||||
message_admins("[key_name_admin(user)] removed the [installedupgrade] upgrade from [ADMIN_LOOKUPFLW(borg)].")
|
||||
log_admin("[key_name(user)] removed the [installedupgrade] upgrade from [key_name(borg)].")
|
||||
qdel(installedupgrade)
|
||||
else
|
||||
var/obj/item/borg/upgrade/upgrade = new upgradepath(borg)
|
||||
upgrade.action(borg, user)
|
||||
borg.upgrades += upgrade
|
||||
message_admins("[key_name_admin(user)] added the [upgrade] borg upgrade to [key_name_admin(borg)][ADMIN_FLW(borg)].")
|
||||
message_admins("[key_name_admin(user)] added the [upgrade] borg upgrade to [ADMIN_LOOKUPFLW(borg)].")
|
||||
log_admin("[key_name(user)] added the [upgrade] borg upgrade to [key_name(borg)].")
|
||||
if ("toggle_radio")
|
||||
var/channel = params["channel"]
|
||||
@@ -175,7 +175,7 @@
|
||||
borg.radio.keyslot.syndie = FALSE
|
||||
else if (channel == "CentCom")
|
||||
borg.radio.keyslot.independent = FALSE
|
||||
message_admins("[key_name_admin(user)] removed the [channel] radio channel from [key_name_admin(borg)][ADMIN_FLW(borg)].")
|
||||
message_admins("[key_name_admin(user)] removed the [channel] radio channel from [ADMIN_LOOKUPFLW(borg)].")
|
||||
log_admin("[key_name(user)] removed the [channel] radio channel from [key_name(borg)].")
|
||||
else // We're adding a channel
|
||||
if (!borg.radio.keyslot) // Assert that an encryption key exists
|
||||
@@ -185,14 +185,14 @@
|
||||
borg.radio.keyslot.syndie = TRUE
|
||||
else if (channel == "CentCom")
|
||||
borg.radio.keyslot.independent = TRUE
|
||||
message_admins("[key_name_admin(user)] added the [channel] radio channel to [key_name_admin(borg)][ADMIN_FLW(borg)].")
|
||||
message_admins("[key_name_admin(user)] added the [channel] radio channel to [ADMIN_LOOKUPFLW(borg)].")
|
||||
log_admin("[key_name(user)] added the [channel] radio channel to [key_name(borg)].")
|
||||
borg.radio.recalculateChannels()
|
||||
if ("setmodule")
|
||||
var/newmodulepath = text2path(params["module"])
|
||||
if (ispath(newmodulepath))
|
||||
borg.module.transform_to(newmodulepath)
|
||||
message_admins("[key_name_admin(user)] changed the module of [key_name_admin(borg)][ADMIN_FLW(borg)] to [newmodulepath].")
|
||||
message_admins("[key_name_admin(user)] changed the module of [ADMIN_LOOKUPFLW(borg)] to [newmodulepath].")
|
||||
log_admin("[key_name(user)] changed the module of [key_name(borg)] to [newmodulepath].")
|
||||
if ("slavetoai")
|
||||
var/mob/living/silicon/ai/newai = locate(params["slavetoai"]) in GLOB.ai_list
|
||||
@@ -202,14 +202,14 @@
|
||||
borg.undeploy()
|
||||
borg.connected_ai = newai
|
||||
borg.notify_ai(TRUE)
|
||||
message_admins("[key_name_admin(user)] slaved [key_name_admin(borg)][ADMIN_FLW(borg)] to the AI [key_name_admin(newai)][ADMIN_FLW(newai)].")
|
||||
message_admins("[key_name_admin(user)] slaved [ADMIN_LOOKUPFLW(borg)] to the AI [ADMIN_LOOKUPFLW(newai)].")
|
||||
log_admin("[key_name(user)] slaved [key_name(borg)] to the AI [key_name(newai)].")
|
||||
else if (params["slavetoai"] == "null")
|
||||
borg.notify_ai(DISCONNECT)
|
||||
if(borg.shell)
|
||||
borg.undeploy()
|
||||
borg.connected_ai = null
|
||||
message_admins("[key_name_admin(user)] freed [key_name_admin(borg)][ADMIN_FLW(borg)] from being slaved to an AI.")
|
||||
message_admins("[key_name_admin(user)] freed [ADMIN_LOOKUPFLW(borg)] from being slaved to an AI.")
|
||||
log_admin("[key_name(user)] freed [key_name(borg)] from being slaved to an AI.")
|
||||
if (borg.lawupdate)
|
||||
borg.lawsync()
|
||||
|
||||
@@ -278,10 +278,10 @@
|
||||
T.PlaceOnTop(/turf/closed/wall)
|
||||
else if(iswallturf(object))
|
||||
T.PlaceOnTop(/turf/closed/wall/r_wall)
|
||||
log_admin("Build Mode: [key_name(user)] built [T] at ([T.x],[T.y],[T.z])")
|
||||
log_admin("Build Mode: [key_name(user)] built [T] at [AREACOORD(T)]")
|
||||
return
|
||||
else if(right_click)
|
||||
log_admin("Build Mode: [key_name(user)] deleted [object] at ([object.x],[object.y],[object.z])")
|
||||
log_admin("Build Mode: [key_name(user)] deleted [object] at [AREACOORD(object)]")
|
||||
if(isturf(object))
|
||||
var/turf/T = object
|
||||
T.ScrapeAway()
|
||||
@@ -289,7 +289,7 @@
|
||||
qdel(object)
|
||||
return
|
||||
else if(isturf(object) && alt_click && left_click)
|
||||
log_admin("Build Mode: [key_name(user)] built an airlock at ([object.x],[object.y],[object.z])")
|
||||
log_admin("Build Mode: [key_name(user)] built an airlock at [AREACOORD(object)]")
|
||||
new/obj/machinery/door/airlock(get_turf(object))
|
||||
else if(isturf(object) && ctrl_click && left_click)
|
||||
var/obj/structure/window/reinforced/window
|
||||
@@ -298,7 +298,7 @@
|
||||
else
|
||||
window = new /obj/structure/window/reinforced(get_turf(object))
|
||||
window.setDir(build_dir)
|
||||
log_admin("Build Mode: [key_name(user)] built a window at ([object.x],[object.y],[object.z])")
|
||||
log_admin("Build Mode: [key_name(user)] built a window at [AREACOORD(object)]")
|
||||
if(ADV_BUILDMODE)
|
||||
if(left_click && alt_click)
|
||||
objholder = object.type
|
||||
@@ -306,15 +306,15 @@
|
||||
else if(left_click)
|
||||
if(ispath(objholder, /turf))
|
||||
var/turf/T = get_turf(object)
|
||||
log_admin("Build Mode: [key_name(user)] modified [T] ([T.x],[T.y],[T.z]) to [objholder]")
|
||||
log_admin("Build Mode: [key_name(user)] modified [T] in [AREACOORD(object)] to [objholder]")
|
||||
T.PlaceOnTop(objholder)
|
||||
else
|
||||
var/obj/A = new objholder (get_turf(object))
|
||||
A.setDir(build_dir)
|
||||
log_admin("Build Mode: [key_name(user)] modified [A]'s ([A.x],[A.y],[A.z]) dir to [build_dir]")
|
||||
log_admin("Build Mode: [key_name(user)] modified [A]'s [COORD(A)] dir to [build_dir]")
|
||||
else if(right_click)
|
||||
if(isobj(object))
|
||||
log_admin("Build Mode: [key_name(user)] deleted [object] at ([object.x],[object.y],[object.z])")
|
||||
log_admin("Build Mode: [key_name(user)] deleted [object] at [AREACOORD(object)]")
|
||||
qdel(object)
|
||||
|
||||
if(VAR_BUILDMODE)
|
||||
@@ -343,7 +343,7 @@
|
||||
if(right_click)
|
||||
if(throw_atom)
|
||||
throw_atom.throw_at(object, 10, 1,user)
|
||||
log_admin("Build Mode: [key_name(user)] threw [throw_atom] at [object] ([object.x],[object.y],[object.z])")
|
||||
log_admin("Build Mode: [key_name(user)] threw [throw_atom] at [object] in [AREACOORD(object)]")
|
||||
if(AREA_BUILDMODE)
|
||||
if(left_click) //rectangular
|
||||
if(!cornerA)
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
return
|
||||
var/static/nicknames = world.file2list("[global.config.directory]/admin_nicknames.txt")
|
||||
|
||||
var/rendered = "<span class='game deadsay'><span class='prefix'>DEAD:</span> <span class='name'>ADMIN([src.holder.fakekey ? pick(nicknames) : src.key])</span> says, <span class='message'>\"[msg]\"</span></span>"
|
||||
var/rendered = "<span class='game deadsay'><span class='prefix'>DEAD:</span> <span class='name'>[uppertext(holder.rank)]([src.holder.fakekey ? pick(nicknames) : src.key])</span> says, <span class='message'>\"[msg]\"</span></span>"
|
||||
|
||||
for (var/mob/M in GLOB.player_list)
|
||||
if(isnewplayer(M))
|
||||
|
||||
@@ -333,8 +333,8 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
if(ishuman(M))
|
||||
INVOKE_ASYNC(M, /mob/living/carbon/human/proc/Alienize)
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Make Alien") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
log_admin("[key_name(usr)] made [key_name(M)] into an alien.")
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] made [key_name(M)] into an alien.</span>")
|
||||
log_admin("[key_name(usr)] made [key_name(M)] into an alien at [AREACOORD(M)].")
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] made [ADMIN_LOOKUPFLW(M)] into an alien.</span>")
|
||||
else
|
||||
alert("Invalid mob")
|
||||
|
||||
@@ -348,8 +348,8 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
if(ishuman(M))
|
||||
INVOKE_ASYNC(M, /mob/living/carbon/human/proc/slimeize)
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Make Slime") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
log_admin("[key_name(usr)] made [key_name(M)] into a slime.")
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] made [key_name(M)] into a slime.</span>")
|
||||
log_admin("[key_name(usr)] made [key_name(M)] into a slime at [AREACOORD(M)].")
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] made [ADMIN_LOOKUPFLW(M)] into a slime.</span>")
|
||||
else
|
||||
alert("Invalid mob")
|
||||
|
||||
@@ -434,7 +434,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
qdel(O)
|
||||
CHECK_TICK
|
||||
log_admin("[key_name(src)] has deleted all ([counter]) instances of [hsbitem].")
|
||||
message_admins("[key_name_admin(src)] has deleted all ([counter]) instances of [hsbitem].", 0)
|
||||
message_admins("[key_name_admin(src)] has deleted all ([counter]) instances of [hsbitem].")
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Delete All") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
|
||||
@@ -443,7 +443,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
set name = "Make Powernets"
|
||||
SSmachines.makepowernets()
|
||||
log_admin("[key_name(src)] has remade the powernet. makepowernets() called.")
|
||||
message_admins("[key_name_admin(src)] has remade the powernets. makepowernets() called.", 0)
|
||||
message_admins("[key_name_admin(src)] has remade the powernets. makepowernets() called.")
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Make Powernets") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/cmd_admin_grantfullaccess(mob/M in GLOB.mob_list)
|
||||
@@ -522,7 +522,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
|
||||
var/bad_shit = 0
|
||||
for(var/obj/machinery/computer/atmos_control/tank/console in GLOB.atmos_air_controllers)
|
||||
dat += "<h1>[console] at [get_area_name(console, TRUE)] [COORD(console)]:</h1><br>"
|
||||
dat += "<h1>[console] at [AREACOORD(console)]:</h1><br>"
|
||||
if(console.input_tag == console.output_tag)
|
||||
dat += "Error: input_tag is the same as the output_tag, \"[console.input_tag]\"!<br>"
|
||||
bad_shit++
|
||||
@@ -734,14 +734,17 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
if(!dresscode)
|
||||
return
|
||||
|
||||
var/delete_pocket
|
||||
var/mob/living/carbon/human/H
|
||||
if(isobserver(M))
|
||||
H = M.change_mob_type(/mob/living/carbon/human, null, null, TRUE)
|
||||
else
|
||||
H = M
|
||||
if(alert("Drop Items in Pockets? No will delete them.", "Robust quick dress shop", "Yes", "No") == "No")
|
||||
delete_pocket = TRUE
|
||||
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Select Equipment") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
for (var/obj/item/I in H.get_equipped_items())
|
||||
for (var/obj/item/I in H.get_equipped_items(delete_pocket))
|
||||
qdel(I)
|
||||
if(dresscode != "Naked")
|
||||
H.equipOutfit(dresscode)
|
||||
@@ -749,7 +752,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
H.regenerate_icons()
|
||||
|
||||
log_admin("[key_name(usr)] changed the equipment of [key_name(H)] to [dresscode].")
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] changed the equipment of [key_name_admin(H)] to [dresscode].</span>")
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] changed the equipment of [ADMIN_LOOKUPFLW(H)] to [dresscode].</span>")
|
||||
|
||||
/client/proc/robust_dress_shop()
|
||||
var/list/outfits = list("Cancel","Naked","Custom","As Job...")
|
||||
@@ -958,15 +961,17 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
|
||||
/client/proc/clear_dynamic_transit()
|
||||
set category = "Debug"
|
||||
set name = "Clear Dynamic Transit"
|
||||
set desc = "Deallocates all transit space, restoring it to round start conditions."
|
||||
set name = "Clear Dynamic Turf Reservations"
|
||||
set desc = "Deallocates all reserved space, restoring it to round start conditions."
|
||||
if(!holder)
|
||||
return
|
||||
SSshuttle.clear_transit = TRUE
|
||||
var/answer = alert("WARNING: THIS WILL WIPE ALL RESERVED SPACE TO A CLEAN SLATE! ANY MOVING SHUTTLES, ELEVATORS, OR IN-PROGRESS PHOTOGRAPHY WILL BE DELETED!", "Really wipe dynamic turfs?", "YES", "NO")
|
||||
if(answer != "YES")
|
||||
return
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(src)] cleared dynamic transit space.</span>")
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Clear Dynamic Transit") // If...
|
||||
log_admin("[key_name(src)] cleared dynamic transit space.")
|
||||
|
||||
SSmapping.wipe_reservations() //this goes after it's logged, incase something horrible happens.
|
||||
|
||||
/client/proc/toggle_medal_disable()
|
||||
set category = "Debug"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
if(T.active_hotspot)
|
||||
burning = TRUE
|
||||
|
||||
var/list/lines = list("<span class='adminnotice'>[COORD(target)]: [env.temperature] K ([env.temperature - T0C] C), [env.return_pressure()] kPa[(burning)?(", <font color='red'>burning</font>"):(null)]</span>")
|
||||
var/list/lines = list("<span class='adminnotice'>[AREACOORD(target)]: [env.temperature] K ([env.temperature - T0C] C), [env.return_pressure()] kPa[(burning)?(", <font color='red'>burning</font>"):(null)]</span>")
|
||||
for(var/id in env_gases)
|
||||
var/gas = env_gases[id]
|
||||
var/moles = gas[MOLES]
|
||||
@@ -49,8 +49,8 @@
|
||||
log_admin("DEBUG: [key_name(M)] next_move = [M.next_move] lastDblClick = [M.next_click] world.time = [world.time]")
|
||||
M.next_move = 1
|
||||
M.next_click = 0
|
||||
message_admins("[key_name_admin(largest_move_mob)] had the largest move delay with [largest_move_time] frames / [DisplayTimeText(largest_move_time)]!")
|
||||
message_admins("[key_name_admin(largest_click_mob)] had the largest click delay with [largest_click_time] frames / [DisplayTimeText(largest_click_time)]!")
|
||||
message_admins("[ADMIN_LOOKUPFLW(largest_move_mob)] had the largest move delay with [largest_move_time] frames / [DisplayTimeText(largest_move_time)]!")
|
||||
message_admins("[ADMIN_LOOKUPFLW(largest_click_mob)] had the largest click delay with [largest_click_time] frames / [DisplayTimeText(largest_click_time)]!")
|
||||
message_admins("world.time = [world.time]")
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Unfreeze Everyone") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
return
|
||||
@@ -75,7 +75,7 @@
|
||||
for (var/device in f)
|
||||
if (istype(device, /atom))
|
||||
var/atom/A = device
|
||||
output += " [device] ([A.x],[A.y],[A.z] in area [get_area(device)])<br>"
|
||||
output += " [device] ([AREACOORD(A)])<br>"
|
||||
else
|
||||
output += " [device]<br>"
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/client/proc/roll_dices()
|
||||
set category = "Fun"
|
||||
set name = "Roll Dice"
|
||||
if(!check_rights(R_FUN))
|
||||
return
|
||||
|
||||
var/sum = input("How many times should we throw?") as num
|
||||
var/side = input("Select the number of sides.") as num
|
||||
if(!side)
|
||||
side = 6
|
||||
if(!sum)
|
||||
sum = 2
|
||||
|
||||
var/dice = num2text(sum) + "d" + num2text(side)
|
||||
|
||||
if(alert("Do you want to inform the world about your game?",,"Yes", "No") == "Yes")
|
||||
to_chat(world, "<h2 style=\"color:#A50400\">The dice have been rolled by Gods!</h2>")
|
||||
|
||||
var/result = roll(dice)
|
||||
|
||||
if(alert("Do you want to inform the world about the result?",,"Yes", "No") == "Yes")
|
||||
to_chat(world, "<h2 style=\"color:#A50400\">Gods rolled [dice], result is [result]</h2>")
|
||||
|
||||
message_admins("[key_name_admin(src)] rolled dice [dice], result is [result]")
|
||||
log_admin("[key_name_admin(src)] rolled dice [dice], result is [result]")
|
||||
@@ -1,32 +1,52 @@
|
||||
/proc/show_individual_logging_panel(mob/M, type = INDIVIDUAL_ATTACK_LOG)
|
||||
/proc/show_individual_logging_panel(mob/M, source = LOGSRC_CLIENT, type = INDIVIDUAL_ATTACK_LOG)
|
||||
if(!M || !ismob(M))
|
||||
return
|
||||
var/dat = "<center><a href='?_src_=holder;[HrefToken()];individuallog=[REF(M)];log_type=[INDIVIDUAL_ATTACK_LOG]'>Attack log</a> | "
|
||||
dat += "<a href='?_src_=holder;[HrefToken()];individuallog=[REF(M)];log_type=[INDIVIDUAL_SAY_LOG]'>Say log</a> | "
|
||||
dat += "<a href='?_src_=holder;[HrefToken()];individuallog=[REF(M)];log_type=[INDIVIDUAL_EMOTE_LOG]'>Emote log</a> | "
|
||||
dat += "<a href='?_src_=holder;[HrefToken()];individuallog=[REF(M)];log_type=[INDIVIDUAL_OOC_LOG]'>OOC log</a> | "
|
||||
dat += "<a href='?_src_=holder;[HrefToken()];individuallog=[REF(M)];log_type=[INDIVIDUAL_SHOW_ALL_LOG]'>Show all</a> | "
|
||||
dat += "<a href='?_src_=holder;[HrefToken()];individuallog=[REF(M)];log_type=[type]'>Refresh</a></center>"
|
||||
|
||||
//Add client links
|
||||
var/dat = ""
|
||||
if(M.client)
|
||||
dat += "<center><p>Client</p></center>"
|
||||
dat += "<center><a href='?_src_=holder;[HrefToken()];individuallog=[REF(M)];log_type=[INDIVIDUAL_ATTACK_LOG];log_src=[LOGSRC_CLIENT]'>Attack log</a> | "
|
||||
dat += "<a href='?_src_=holder;[HrefToken()];individuallog=[REF(M)];log_type=[INDIVIDUAL_SAY_LOG];log_src=[LOGSRC_CLIENT]'>Say log</a> | "
|
||||
dat += "<a href='?_src_=holder;[HrefToken()];individuallog=[REF(M)];log_type=[INDIVIDUAL_EMOTE_LOG];log_src=[LOGSRC_CLIENT]'>Emote log</a> | "
|
||||
dat += "<a href='?_src_=holder;[HrefToken()];individuallog=[REF(M)];log_type=[INDIVIDUAL_OOC_LOG];log_src=[LOGSRC_CLIENT]'>OOC log</a> | "
|
||||
dat += "<a href='?_src_=holder;[HrefToken()];individuallog=[REF(M)];log_type=[INDIVIDUAL_SHOW_ALL_LOG];log_src=[LOGSRC_CLIENT]'>Show all</a> | "
|
||||
dat += "<a href='?_src_=holder;[HrefToken()];individuallog=[REF(M)];log_type=[type];log_src=[LOGSRC_CLIENT]'>Refresh</a></center>"
|
||||
else
|
||||
dat += "<p> No client attached to mob </p>"
|
||||
|
||||
dat += "<hr style='background:#000000; border:0; height:1px'>"
|
||||
dat += "<center><p>Mob</p></center>"
|
||||
//Add the links for the mob specific log
|
||||
dat += "<center><a href='?_src_=holder;[HrefToken()];individuallog=[REF(M)];log_type=[INDIVIDUAL_ATTACK_LOG];log_src=[LOGSRC_MOB]'>Attack log</a> | "
|
||||
dat += "<a href='?_src_=holder;[HrefToken()];individuallog=[REF(M)];log_type=[INDIVIDUAL_SAY_LOG];log_src=[LOGSRC_MOB]'>Say log</a> | "
|
||||
dat += "<a href='?_src_=holder;[HrefToken()];individuallog=[REF(M)];log_type=[INDIVIDUAL_EMOTE_LOG];log_src=[LOGSRC_MOB]'>Emote log</a> | "
|
||||
dat += "<a href='?_src_=holder;[HrefToken()];individuallog=[REF(M)];log_type=[INDIVIDUAL_OOC_LOG];log_src=[LOGSRC_MOB]'>OOC log</a> | "
|
||||
dat += "<a href='?_src_=holder;[HrefToken()];individuallog=[REF(M)];log_type=[INDIVIDUAL_SHOW_ALL_LOG];log_src=[LOGSRC_MOB]'>Show all</a> | "
|
||||
dat += "<a href='?_src_=holder;[HrefToken()];individuallog=[REF(M)];log_type=[type];log_src=[LOGSRC_MOB]'>Refresh</a></center>"
|
||||
|
||||
dat += "<hr style='background:#000000; border:0; height:1px'>"
|
||||
|
||||
var/log_source = M.logging;
|
||||
if(source == LOGSRC_CLIENT && M.client) //if client doesn't exist just fall back to the mob log
|
||||
log_source = M.client.player_details.logging //should exist, if it doesn't that's a bug, don't check for it not existing
|
||||
|
||||
if(type == INDIVIDUAL_SHOW_ALL_LOG)
|
||||
dat += "<center>Displaying all logs of [key_name(M)]</center><br><hr>"
|
||||
for(var/log_type in M.logging)
|
||||
dat += "<center>Displaying all [source] logs of [key_name(M)]</center><br><hr>"
|
||||
for(var/log_type in log_source)
|
||||
dat += "<center><b>[log_type]</b></center><br>"
|
||||
var/list/reversed = M.logging[log_type]
|
||||
var/list/reversed = log_source[log_type]
|
||||
if(islist(reversed))
|
||||
reversed = reverseRange(reversed.Copy())
|
||||
for(var/entry in reversed)
|
||||
dat += "<font size=2px>[entry]: [reversed[entry]]</font><br>"
|
||||
dat += "<hr>"
|
||||
else
|
||||
dat += "<center>[type] of [key_name(M)]</center><br>"
|
||||
var/list/reversed = M.logging[type]
|
||||
dat += "<center>[source] [type] of [key_name(M)]</center><br>"
|
||||
var/list/reversed = log_source[type]
|
||||
if(reversed)
|
||||
reversed = reverseRange(reversed.Copy())
|
||||
for(var/entry in reversed)
|
||||
dat += "<font size=2px>[entry]: [reversed[entry]]</font><hr>"
|
||||
|
||||
usr << browse(dat, "window=invidual_logging_[M];size=600x480")
|
||||
usr << browse(dat, "window=invidual_logging_[key_name(M)];size=600x480")
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
/client/proc/manipulate_organs(mob/living/carbon/C in world)
|
||||
set name = "Manipulate Organs"
|
||||
set category = "Debug"
|
||||
var/operation = input("Select organ operation.", "Organ Manipulation", "cancel") in list("add organ", "add implant", "drop organ/implant", "remove organ/implant", "cancel")
|
||||
var/operation = input("Select organ operation.", "Organ Manipulation", "cancel") as null|anything in list("add organ", "add implant", "drop organ/implant", "remove organ/implant", "cancel")
|
||||
if (!operation)
|
||||
return
|
||||
|
||||
var/list/organs = list()
|
||||
switch(operation)
|
||||
@@ -10,24 +12,28 @@
|
||||
var/dat = replacetext("[path]", "/obj/item/organ/", ":")
|
||||
organs[dat] = path
|
||||
|
||||
var/obj/item/organ/organ = input("Select organ type:", "Organ Manipulation", null) in organs
|
||||
var/obj/item/organ/organ = input("Select organ type:", "Organ Manipulation", null) as null|anything in organs
|
||||
if(!organ)
|
||||
return
|
||||
organ = organs[organ]
|
||||
organ = new organ
|
||||
organ.Insert(C)
|
||||
log_admin("[key_name(usr)] has added organ [organ.type] to [key_name(C)]")
|
||||
message_admins("[key_name_admin(usr)] has added organ [organ.type] to [key_name(C)]")
|
||||
message_admins("[key_name_admin(usr)] has added organ [organ.type] to [ADMIN_LOOKUPFLW(C)]")
|
||||
|
||||
if("add implant")
|
||||
for(var/path in subtypesof(/obj/item/implant))
|
||||
var/dat = replacetext("[path]", "/obj/item/implant/", ":")
|
||||
organs[dat] = path
|
||||
|
||||
var/obj/item/implant/organ = input("Select implant type:", "Organ Manipulation", null) in organs
|
||||
var/obj/item/implant/organ = input("Select implant type:", "Organ Manipulation", null) as null|anything in organs
|
||||
if(!organ)
|
||||
return
|
||||
organ = organs[organ]
|
||||
organ = new organ
|
||||
organ.implant(C)
|
||||
log_admin("[key_name(usr)] has added implant [organ.type] to [key_name(C)]")
|
||||
message_admins("[key_name_admin(usr)] has added implant [organ.type] to [key_name(C)]")
|
||||
message_admins("[key_name_admin(usr)] has added implant [organ.type] to [ADMIN_LOOKUPFLW(C)]")
|
||||
|
||||
if("drop organ/implant", "remove organ/implant")
|
||||
for(var/X in C.internal_organs)
|
||||
@@ -38,7 +44,9 @@
|
||||
var/obj/item/implant/I = X
|
||||
organs["[I.name] ([I.type])"] = I
|
||||
|
||||
var/obj/item/organ = input("Select organ/implant:", "Organ Manipulation", null) in organs
|
||||
var/obj/item/organ = input("Select organ/implant:", "Organ Manipulation", null) as null|anything in organs
|
||||
if(!organ)
|
||||
return
|
||||
organ = organs[organ]
|
||||
if(!organ)
|
||||
return
|
||||
@@ -46,7 +54,7 @@
|
||||
var/obj/item/implant/I
|
||||
|
||||
log_admin("[key_name(usr)] has removed [organ.type] from [key_name(C)]")
|
||||
message_admins("[key_name_admin(usr)] has removed [organ.type] from [key_name(C)]")
|
||||
message_admins("[key_name_admin(usr)] has removed [organ.type] from [ADMIN_LOOKUPFLW(C)]")
|
||||
|
||||
if(isorgan(organ))
|
||||
O = organ
|
||||
|
||||
@@ -105,11 +105,11 @@ GLOBAL_LIST_INIT(admin_verbs_debug_mapping, list(
|
||||
for(var/obj/machinery/camera/C2 in CL)
|
||||
if(C1 != C2)
|
||||
if(C1.c_tag == C2.c_tag)
|
||||
output += "<li><font color='red'>c_tag match for cameras at [ADMIN_COORDJMP(C1)] ([C1.loc.loc]) and [ADMIN_COORDJMP(C2)] ([C2.loc.loc]) - c_tag is [C1.c_tag]</font></li>"
|
||||
output += "<li><font color='red'>c_tag match for cameras at [ADMIN_VERBOSEJMP(C1)] and [ADMIN_VERBOSEJMP(C2)] - c_tag is [C1.c_tag]</font></li>"
|
||||
if(C1.loc == C2.loc && C1.dir == C2.dir && C1.pixel_x == C2.pixel_x && C1.pixel_y == C2.pixel_y)
|
||||
output += "<li><font color='red'>FULLY overlapping cameras at [ADMIN_COORDJMP(C1)] ([C1.loc.loc]) Networks: [json_encode(C1.network)] and [json_encode(C2.network)]</font></li>"
|
||||
output += "<li><font color='red'>FULLY overlapping cameras at [ADMIN_VERBOSEJMP(C1)] Networks: [json_encode(C1.network)] and [json_encode(C2.network)]</font></li>"
|
||||
if(C1.loc == C2.loc)
|
||||
output += "<li>Overlapping cameras at [ADMIN_COORDJMP(C1)] ([C1.loc.loc]) Networks: [json_encode(C1.network)] and [json_encode(C2.network)]</li>"
|
||||
output += "<li>Overlapping cameras at [ADMIN_VERBOSEJMP(C1)] Networks: [json_encode(C1.network)] and [json_encode(C2.network)]</li>"
|
||||
var/turf/T = get_step(C1,turn(C1.dir,180))
|
||||
if(!T || !isturf(T) || !T.density )
|
||||
if(!(locate(/obj/structure/grille) in T))
|
||||
@@ -119,7 +119,7 @@ GLOBAL_LIST_INIT(admin_verbs_debug_mapping, list(
|
||||
window_check = 1
|
||||
break
|
||||
if(!window_check)
|
||||
output += "<li><font color='red'>Camera not connected to wall at [ADMIN_COORDJMP(C1)] ([C1.loc.loc]) Network: [json_encode(C1.network)]</font></li>"
|
||||
output += "<li><font color='red'>Camera not connected to wall at [ADMIN_VERBOSEJMP(C1)] Network: [json_encode(C1.network)]</font></li>"
|
||||
|
||||
output += "</ul>"
|
||||
usr << browse(output,"window=airreport;size=1000x500")
|
||||
@@ -153,7 +153,7 @@ GLOBAL_LIST_INIT(admin_verbs_debug_mapping, list(
|
||||
|
||||
for(var/t in GLOB.active_turfs_startlist)
|
||||
var/turf/T = t
|
||||
dat += "[ADMIN_COORDJMP(T)]\n"
|
||||
dat += "[ADMIN_VERBOSEJMP(T)]\n"
|
||||
dat += "<br>"
|
||||
|
||||
usr << browse(dat, "window=at_list")
|
||||
|
||||
@@ -629,8 +629,9 @@ GLOBAL_PROTECT(VVpixelmovement)
|
||||
if (O.vv_edit_var(variable, var_new) == FALSE)
|
||||
to_chat(src, "Your edit was rejected by the object.")
|
||||
return
|
||||
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_VAR_EDIT, args)
|
||||
log_world("### VarEdit by [key_name(src)]: [O.type] [variable]=[var_value] => [var_new]")
|
||||
log_admin("[key_name(src)] modified [original_name]'s [variable] to from [html_encode("[var_value]")] to [html_encode("[var_new]")]")
|
||||
log_admin("[key_name(src)] modified [original_name]'s [variable] from [html_encode("[var_value]")] to [html_encode("[var_new]")]")
|
||||
var/msg = "[key_name_admin(src)] modified [original_name]'s [variable] from [var_value] to [var_new]"
|
||||
message_admins(msg)
|
||||
admin_ticket_log(O, msg)
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
var/mob/living/carbon/human/H = null
|
||||
|
||||
for(var/mob/living/carbon/human/applicant in GLOB.player_list)
|
||||
if(isReadytoRumble(applicant, ROLE_TRAITOR, FALSE))
|
||||
if(isReadytoRumble(applicant, ROLE_TRAITOR))
|
||||
if(temp.age_check(applicant.client))
|
||||
if(!(applicant.job in temp.restricted_jobs))
|
||||
candidates += applicant
|
||||
@@ -76,7 +76,7 @@
|
||||
return 0
|
||||
|
||||
|
||||
/datum/admins/proc/makeChanglings()
|
||||
/datum/admins/proc/makeChangelings()
|
||||
|
||||
var/datum/game_mode/changeling/temp = new
|
||||
if(CONFIG_GET(flag/protect_roles_from_antagonist))
|
||||
@@ -95,11 +95,11 @@
|
||||
candidates += applicant
|
||||
|
||||
if(candidates.len)
|
||||
var/numChanglings = min(candidates.len, 3)
|
||||
var/numChangelings = min(candidates.len, 3)
|
||||
|
||||
for(var/i = 0, i<numChanglings, i++)
|
||||
for(var/i = 0, i<numChangelings, i++)
|
||||
H = pick(candidates)
|
||||
H.mind.make_Changling()
|
||||
H.mind.make_Changeling()
|
||||
candidates.Remove(H)
|
||||
|
||||
return 1
|
||||
@@ -290,7 +290,7 @@
|
||||
|
||||
|
||||
/datum/admins/proc/equipAntagOnDummy(mob/living/carbon/human/dummy/mannequin, datum/antagonist/antag)
|
||||
for(var/I in mannequin.get_equipped_items())
|
||||
for(var/I in mannequin.get_equipped_items(TRUE))
|
||||
qdel(I)
|
||||
if (ispath(antag, /datum/antagonist/ert))
|
||||
var/datum/antagonist/ert/ert = antag
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
var/turf/T = get_turf(O)
|
||||
|
||||
if(T)
|
||||
log_admin("[key_name(usr)] has possessed [O] ([O.type]) at ([T.x], [T.y], [T.z])")
|
||||
message_admins("[key_name(usr)] has possessed [O] ([O.type]) at ([T.x], [T.y], [T.z])")
|
||||
log_admin("[key_name(usr)] has possessed [O] ([O.type]) at [AREACOORD(T)]")
|
||||
message_admins("[key_name(usr)] has possessed [O] ([O.type]) at [AREACOORD(T)]")
|
||||
else
|
||||
log_admin("[key_name(usr)] has possessed [O] ([O.type]) at an unknown location")
|
||||
message_admins("[key_name(usr)] has possessed [O] ([O.type]) at an unknown location")
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
font_color = "blue"
|
||||
prayer_type = "SPIRITUAL PRAYER"
|
||||
|
||||
msg = "<span class='adminnotice'>[icon2html(cross, GLOB.admins)]<b><font color=[font_color]>[prayer_type][deity ? " (to [deity])" : ""]: </font>[ADMIN_FULLMONTY(src)] [ADMIN_SC(src)]:</b> [msg]</span>"
|
||||
msg = "<span class='adminnotice'>[icon2html(cross, GLOB.admins)]<b><font color=[font_color]>[prayer_type][deity ? " (to [deity])" : ""]: </font>[ADMIN_FULLMONTY(src)] [ADMIN_SC(src)]:</b> <span class='linkify'>[msg]</span></span>"
|
||||
|
||||
for(var/client/C in GLOB.admins)
|
||||
if(C.prefs.chat_toggles & CHAT_PRAYER)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
M.regenerate_icons()
|
||||
|
||||
log_admin("[key_name(usr)] made [key_name(M)] drop everything!")
|
||||
var/msg = "[key_name_admin(usr)] made [key_name_admin(M)] drop everything!"
|
||||
var/msg = "[key_name_admin(usr)] made [ADMIN_LOOKUPFLW(M)] drop everything!"
|
||||
message_admins(msg)
|
||||
admin_ticket_log(M, msg)
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Drop Everything") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
@@ -28,11 +28,11 @@
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
message_admins("[key_name_admin(src)] has started answering [key_name(M.key, 0, 0)]'s prayer.")
|
||||
message_admins("[key_name_admin(src)] has started answering [ADMIN_LOOKUPFLW(M)]'s prayer.")
|
||||
var/msg = input("Message:", text("Subtle PM to [M.key]")) as text|null
|
||||
|
||||
if (!msg)
|
||||
message_admins("[key_name_admin(src)] decided not to answer [key_name(M.key, 0, 0)]'s prayer")
|
||||
message_admins("[key_name_admin(src)] decided not to answer [ADMIN_LOOKUPFLW(M)]'s prayer")
|
||||
return
|
||||
if(usr)
|
||||
if (usr.client)
|
||||
@@ -45,6 +45,42 @@
|
||||
admin_ticket_log(M, msg)
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Subtle Message") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/cmd_admin_headset_message(mob/M in GLOB.mob_list)
|
||||
set category = "Special Verbs"
|
||||
set name = "Headset Message"
|
||||
|
||||
admin_headset_message(M)
|
||||
|
||||
/client/proc/admin_headset_message(mob/M in GLOB.mob_list, sender = null)
|
||||
var/mob/living/carbon/human/H = M
|
||||
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
if(!istype(H))
|
||||
to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human")
|
||||
return
|
||||
if(!istype(H.ears, /obj/item/radio/headset))
|
||||
to_chat(usr, "The person you are trying to contact is not wearing a headset.")
|
||||
return
|
||||
|
||||
if (!sender)
|
||||
sender = input("Who is the message from?", "Sender") as null|anything in list("CentCom","Syndicate")
|
||||
if(!sender)
|
||||
return
|
||||
|
||||
message_admins("[key_name_admin(src)] has started answering [key_name_admin(H)]'s [sender] request.")
|
||||
var/input = input("Please enter a message to reply to [key_name(H)] via their headset.","Outgoing message from [sender]", "") as text|null
|
||||
if(!input)
|
||||
message_admins("[key_name_admin(src)] decided not to answer [key_name_admin(H)]'s [sender] request.")
|
||||
return
|
||||
|
||||
log_admin("[key_name(src)] replied to [key_name(H)]'s [sender] message with the message [input].")
|
||||
message_admins("[key_name_admin(src)] replied to [key_name_admin(H)]'s [sender] message with: \"[input]\"")
|
||||
to_chat(H, "You hear something crackle in your ears for a moment before a voice speaks. \"Please stand by for a message from [sender == "Syndicate" ? "your benefactor" : "Central Command"]. Message as follows[sender == "Syndicate" ? ", agent." : ":"] <span class='bold'>[input].</span> Message ends.\"")
|
||||
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Headset Message") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/cmd_admin_mod_antag_rep(client/C in GLOB.clients, var/operation)
|
||||
set category = "Special Verbs"
|
||||
set name = "Modify Antagonist Reputation"
|
||||
@@ -149,8 +185,8 @@
|
||||
for(var/mob/M in view(range,A))
|
||||
to_chat(M, msg)
|
||||
|
||||
log_admin("LocalNarrate: [key_name(usr)] at [get_area(A)][COORD(A)]: [msg]")
|
||||
message_admins("<span class='adminnotice'><b> LocalNarrate: [key_name_admin(usr)] at [get_area(A)][ADMIN_JMP(A)]:</b> [msg]<BR></span>")
|
||||
log_admin("LocalNarrate: [key_name(usr)] at [AREACOORD(A)]: [msg]")
|
||||
message_admins("<span class='adminnotice'><b> LocalNarrate: [key_name_admin(usr)] at [ADMIN_VERBOSEJMP(A)]:</b> [msg]<BR></span>")
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Local Narrate") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/cmd_admin_godmode(mob/M in GLOB.mob_list)
|
||||
@@ -163,7 +199,7 @@
|
||||
to_chat(usr, "<span class='adminnotice'>Toggled [(M.status_flags & GODMODE) ? "ON" : "OFF"]</span>")
|
||||
|
||||
log_admin("[key_name(usr)] has toggled [key_name(M)]'s nodamage to [(M.status_flags & GODMODE) ? "On" : "Off"]")
|
||||
var/msg = "[key_name_admin(usr)] has toggled [key_name_admin(M)]'s nodamage to [(M.status_flags & GODMODE) ? "On" : "Off"]"
|
||||
var/msg = "[key_name_admin(usr)] has toggled [ADMIN_LOOKUPFLW(M)]'s nodamage to [(M.status_flags & GODMODE) ? "On" : "Off"]"
|
||||
message_admins(msg)
|
||||
admin_ticket_log(M, msg)
|
||||
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Godmode", "[M.status_flags & GODMODE ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
@@ -504,7 +540,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
|
||||
M.revive(full_heal = 1, admin_revive = 1)
|
||||
|
||||
log_admin("[key_name(usr)] healed / revived [key_name(M)]")
|
||||
var/msg = "<span class='danger'>Admin [key_name_admin(usr)] healed / revived [key_name_admin(M)]!</span>"
|
||||
var/msg = "<span class='danger'>Admin [key_name_admin(usr)] healed / revived [ADMIN_LOOKUPFLW(M)]!</span>"
|
||||
message_admins(msg)
|
||||
admin_ticket_log(M, msg)
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Rejuvinate") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
@@ -609,8 +645,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
|
||||
return
|
||||
|
||||
explosion(O, devastation, heavy, light, flash, null, null,flames)
|
||||
log_admin("[key_name(usr)] created an explosion ([devastation],[heavy],[light],[flames]) at ([O.x],[O.y],[O.z])")
|
||||
message_admins("[key_name_admin(usr)] created an explosion ([devastation],[heavy],[light],[flames]) at ([O.x],[O.y],[O.z])")
|
||||
log_admin("[key_name(usr)] created an explosion ([devastation],[heavy],[light],[flames]) at [AREACOORD(O)]")
|
||||
message_admins("[key_name_admin(usr)] created an explosion ([devastation],[heavy],[light],[flames]) at [AREACOORD(O)]")
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Explosion") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
return
|
||||
else
|
||||
@@ -633,8 +669,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
|
||||
if (heavy || light)
|
||||
|
||||
empulse(O, heavy, light)
|
||||
log_admin("[key_name(usr)] created an EM Pulse ([heavy],[light]) at ([O.x],[O.y],[O.z])")
|
||||
message_admins("[key_name_admin(usr)] created an EM Pulse ([heavy],[light]) at ([O.x],[O.y],[O.z])")
|
||||
log_admin("[key_name(usr)] created an EM Pulse ([heavy],[light]) at [AREACOORD(O)]")
|
||||
message_admins("[key_name_admin(usr)] created an EM Pulse ([heavy],[light]) at [AREACOORD(O)]")
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "EM Pulse") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
return
|
||||
@@ -820,8 +856,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
|
||||
N.set_safety()
|
||||
N.set_active()
|
||||
|
||||
log_admin("[key_name(usr)] [N.timing ? "activated" : "deactivated"] a nuke at ([N.x],[N.y],[N.z]).")
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] [N.timing ? "activated" : "deactivated"] a nuke at [ADMIN_COORDJMP(N)].")
|
||||
log_admin("[key_name(usr)] [N.timing ? "activated" : "deactivated"] a nuke at [AREACOORD(N)].")
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] [N.timing ? "activated" : "deactivated"] a nuke at [ADMIN_VERBOSEJMP(N)].")
|
||||
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Nuke", "[N.timing]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
|
||||
@@ -1277,7 +1313,7 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
var/list/punishment_list = list(ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_GIB, ADMIN_PUNISHMENT_BSA, ADMIN_PUNISHMENT_FIREBALL, ADMIN_PUNISHMENT_ROD)
|
||||
var/list/punishment_list = list(ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_GIB, ADMIN_PUNISHMENT_BSA, ADMIN_PUNISHMENT_FIREBALL, ADMIN_PUNISHMENT_ROD, ADMIN_PUNISHMENT_SUPPLYPOD)
|
||||
|
||||
var/punishment = input("Choose a punishment", "DIVINE SMITING") as null|anything in punishment_list
|
||||
|
||||
@@ -1305,6 +1341,24 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
|
||||
var/turf/startT = spaceDebrisStartLoc(startside, T.z)
|
||||
var/turf/endT = spaceDebrisFinishLoc(startside, T.z)
|
||||
new /obj/effect/immovablerod(startT, endT,target)
|
||||
if(ADMIN_PUNISHMENT_SUPPLYPOD)
|
||||
///////load the supply pod up with something!
|
||||
var/target_path = input(usr,"Enter typepath of an atom you'd like to send with the pod (type \"empty\" to send an empty pod):" ,"Typepath","/obj/item/reagent_containers/food/snacks/grown/harebell") as null|text
|
||||
if (isnull(target_path))
|
||||
return
|
||||
if (target_path == "empty")//if you type "empty", spawn an empty pod
|
||||
new /obj/effect/DPtarget(get_turf(target), null, POD_CENTCOM)
|
||||
return
|
||||
var/delivery = text2path(target_path)
|
||||
if(!ispath(delivery))
|
||||
delivery = pick_closest_path(target_path)
|
||||
if(!delivery)
|
||||
alert("ERROR: Incorrect / improper path given.")
|
||||
return
|
||||
//send the pod
|
||||
if(iscarbon(target))
|
||||
target.Stun(10)//takes 0.53 seconds for CentCom pod to land
|
||||
new /obj/effect/DPtarget(get_turf(target), delivery, POD_CENTCOM)
|
||||
|
||||
var/msg = "[key_name_admin(usr)] punished [key_name_admin(target)] with [punishment]."
|
||||
message_admins(msg)
|
||||
|
||||
@@ -66,5 +66,5 @@
|
||||
basemob.ckey = mainsettings["ckey"]["value"]
|
||||
|
||||
|
||||
log_admin("[key_name(usr)] spawned a sentient object-mob [basemob] from [chosen_obj] at ([usr.x],[usr.y],[usr.z])")
|
||||
log_admin("[key_name(usr)] spawned a sentient object-mob [basemob] from [chosen_obj] at [AREACOORD(usr)]")
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Spawn object-mob") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
@@ -75,7 +75,7 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
/datum/antagonist/proc/is_banned(mob/M)
|
||||
if(!M)
|
||||
return FALSE
|
||||
. = (jobban_isbanned(M, ROLE_SYNDICATE) || (job_rank && jobban_isbanned(M,job_rank)))
|
||||
. = (jobban_isbanned(M, ROLE_SYNDICATE) || QDELETED(M) || (job_rank && (jobban_isbanned(M,job_rank) || QDELETED(M))))
|
||||
|
||||
/datum/antagonist/proc/replace_banned_player()
|
||||
set waitfor = FALSE
|
||||
@@ -110,12 +110,12 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
/datum/antagonist/proc/give_antag_moodies()
|
||||
if(!antag_moodlet)
|
||||
return
|
||||
owner.current.SendSignal(COMSIG_ADD_MOOD_EVENT, "antag_moodlet", antag_moodlet)
|
||||
SEND_SIGNAL(owner.current, COMSIG_ADD_MOOD_EVENT, "antag_moodlet", antag_moodlet)
|
||||
|
||||
/datum/antagonist/proc/clear_antag_moodies()
|
||||
if(!antag_moodlet)
|
||||
return
|
||||
owner.current.SendSignal(COMSIG_CLEAR_MOOD_EVENT, "antag_moodlet")
|
||||
SEND_SIGNAL(owner.current, COMSIG_CLEAR_MOOD_EVENT, "antag_moodlet")
|
||||
|
||||
//Returns the team antagonist belongs to if any.
|
||||
/datum/antagonist/proc/get_team()
|
||||
|
||||
@@ -58,6 +58,8 @@
|
||||
return
|
||||
var/list/candidates = pollCandidatesForMob("Do you want to play as a wizard's [href_list["school"]] apprentice?", ROLE_WIZARD, null, ROLE_WIZARD, 150, src)
|
||||
if(LAZYLEN(candidates))
|
||||
if(QDELETED(src))
|
||||
return
|
||||
if(used)
|
||||
to_chat(H, "You already used this contract!")
|
||||
return
|
||||
@@ -121,7 +123,7 @@
|
||||
to_chat(user, "<span class='notice'>You activate [src] and wait for confirmation.</span>")
|
||||
var/list/nuke_candidates = pollGhostCandidates("Do you want to play as a syndicate [borg_to_spawn ? "[lowertext(borg_to_spawn)] cyborg":"operative"]?", ROLE_OPERATIVE, null, ROLE_OPERATIVE, 150, POLL_IGNORE_SYNDICATE)
|
||||
if(LAZYLEN(nuke_candidates))
|
||||
if(!(check_usability(user)))
|
||||
if(QDELETED(src) || !check_usability(user))
|
||||
return
|
||||
used = TRUE
|
||||
var/mob/dead/observer/G = pick(nuke_candidates)
|
||||
@@ -235,7 +237,7 @@
|
||||
return
|
||||
var/list/candidates = pollCandidatesForMob("Do you want to play as a [initial(demon_type.name)]?", ROLE_ALIEN, null, ROLE_ALIEN, 50, src)
|
||||
if(LAZYLEN(candidates))
|
||||
if(used)
|
||||
if(used || QDELETED(src))
|
||||
return
|
||||
used = TRUE
|
||||
var/mob/dead/observer/C = pick(candidates)
|
||||
|
||||
@@ -30,9 +30,9 @@
|
||||
var/combat_armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 50, "bio" = 50, "rad" = 50, "fire" = 90, "acid" = 90)
|
||||
|
||||
/obj/item/clothing/suit/armor/abductor/vest/proc/toggle_nodrop()
|
||||
flags_1 ^= NODROP_1
|
||||
item_flags ^= NODROP
|
||||
if(ismob(loc))
|
||||
to_chat(loc, "<span class='notice'>Your vest is now [flags_1 & NODROP_1 ? "locked" : "unlocked"].</span>")
|
||||
to_chat(loc, "<span class='notice'>Your vest is now [item_flags & NODROP ? "locked" : "unlocked"].</span>")
|
||||
|
||||
/obj/item/clothing/suit/armor/abductor/vest/proc/flip_mode()
|
||||
switch(mode)
|
||||
@@ -359,7 +359,7 @@
|
||||
|
||||
to_chat(L, "<span class='italics'>You hear a voice in your head saying: </span><span class='abductor'>[message]</span>")
|
||||
to_chat(user, "<span class='notice'>You send the message to your target.</span>")
|
||||
log_talk(user,"[key_name(user)] sent an abductor mind message to [L]/[L.ckey]: '[message]'", LOGSAY)
|
||||
log_talk(user,"[key_name(user)] sent an abductor mind message to [key_name(L)]: '[message]'", LOGSAY)
|
||||
|
||||
|
||||
/obj/item/firing_pin/abductor
|
||||
@@ -589,9 +589,10 @@ Congratulations! You are now trained for invasive xenobiology research!"}
|
||||
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
|
||||
breakouttime = 450
|
||||
trashtype = /obj/item/restraints/handcuffs/energy/used
|
||||
flags_1 = NONE
|
||||
|
||||
/obj/item/restraints/handcuffs/energy/used
|
||||
flags_1 = DROPDEL_1
|
||||
item_flags = DROPDEL
|
||||
|
||||
/obj/item/restraints/handcuffs/energy/used/dropped(mob/user)
|
||||
user.visible_message("<span class='danger'>[user]'s [name] breaks in a discharge of energy!</span>", \
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
var/obj/item/clothing/suit/armor/abductor/vest/V = locate() in H
|
||||
if(V)
|
||||
console.AddVest(V)
|
||||
V.flags_1 |= NODROP_1
|
||||
V.item_flags |= NODROP
|
||||
|
||||
var/obj/item/storage/backpack/B = locate() in H
|
||||
if(B)
|
||||
|
||||
@@ -285,7 +285,7 @@
|
||||
addtimer(CALLBACK(src, .proc/zap), rand(30, 100))
|
||||
|
||||
/obj/item/organ/heart/gland/electric/proc/zap()
|
||||
tesla_zap(owner, 4, 8000, FALSE, TRUE)
|
||||
tesla_zap(owner, 4, 8000, TESLA_MOB_DAMAGE | TESLA_OBJ_DAMAGE | TESLA_MOB_STUN)
|
||||
playsound(get_turf(owner), 'sound/magic/lightningshock.ogg', 50, 1)
|
||||
|
||||
/obj/item/organ/heart/gland/chem
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
icon = 'icons/obj/abductor.dmi'
|
||||
icon_state = "console"
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
var/obj/item/abductor/gizmo/gizmo
|
||||
var/obj/item/clothing/suit/armor/abductor/vest/vest
|
||||
var/obj/machinery/abductor/experiment/experiment
|
||||
@@ -76,7 +75,7 @@
|
||||
|
||||
dat+="<br>"
|
||||
dat += "<a href='?src=[REF(src)];select_disguise=1'>Select Agent Vest Disguise</a><br>"
|
||||
dat += "<a href='?src=[REF(src)];toggle_vest=1'>[vest.flags_1 & NODROP_1 ? "Unlock" : "Lock"] Vest</a><br>"
|
||||
dat += "<a href='?src=[REF(src)];toggle_vest=1'>[vest.item_flags & NODROP ? "Unlock" : "Lock"] Vest</a><br>"
|
||||
else
|
||||
dat += "<span class='bad'>NO AGENT VEST DETECTED</span>"
|
||||
var/datum/browser/popup = new(user, "computer", "Abductor Console", 400, 500)
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
icon = 'icons/obj/abductor.dmi'
|
||||
icon_state = "dispenser"
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
var/list/gland_types
|
||||
var/list/gland_colors
|
||||
var/list/amounts
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
icon = 'icons/obj/abductor.dmi'
|
||||
icon_state = "experiment-open"
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
state_open = TRUE
|
||||
var/points = 0
|
||||
var/credits = 0
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
desc = "Use this to transport to and from the humans' habitat."
|
||||
icon = 'icons/obj/abductor.dmi'
|
||||
icon_state = "alien-pad-idle"
|
||||
anchored = TRUE
|
||||
var/turf/teleport_target
|
||||
|
||||
/obj/machinery/abductor/pad/proc/Warp(mob/living/target)
|
||||
|
||||
@@ -78,3 +78,11 @@
|
||||
B.change_to(/obj/structure/blob/shield/core, overmind)
|
||||
..()
|
||||
|
||||
/obj/structure/blob/core/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/stationloving, FALSE, TRUE)
|
||||
|
||||
/obj/structure/blob/core/onTransitZ(old_z, new_z)
|
||||
if(overmind && is_station_level(new_z))
|
||||
overmind.forceMove(get_turf(src))
|
||||
return ..()
|
||||
|
||||
@@ -123,7 +123,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
|
||||
else
|
||||
L.fully_heal()
|
||||
|
||||
for(var/V in GLOB.sortedAreas)
|
||||
for(var/V in GLOB.the_station_areas)
|
||||
var/area/A = V
|
||||
if(!A.blob_allowed)
|
||||
continue
|
||||
|
||||
@@ -204,6 +204,9 @@
|
||||
return null
|
||||
|
||||
/obj/structure/blob/emp_act(severity)
|
||||
. = ..()
|
||||
if(. & EMP_PROTECT_SELF)
|
||||
return
|
||||
if(severity > 0)
|
||||
if(overmind)
|
||||
overmind.blob_reagent_datum.emp_reaction(src, severity)
|
||||
|
||||
@@ -451,7 +451,7 @@
|
||||
/datum/antagonist/changeling/proc/update_changeling_icons_added()
|
||||
var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_CHANGELING]
|
||||
hud.join_hud(owner.current)
|
||||
set_antag_hud(owner.current, "changling")
|
||||
set_antag_hud(owner.current, "changeling")
|
||||
|
||||
/datum/antagonist/changeling/proc/update_changeling_icons_removed()
|
||||
var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_CHANGELING]
|
||||
|
||||
@@ -112,10 +112,3 @@
|
||||
target.death(0)
|
||||
target.Drain()
|
||||
return TRUE
|
||||
|
||||
|
||||
|
||||
//Absorbs the target DNA.
|
||||
//datum/changeling/proc/absorb_dna(mob/living/carbon/T, mob/user)
|
||||
|
||||
//datum/changeling/proc/store_dna(datum/dna/new_dna, mob/user)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//Augmented Eyesight: Gives you x-ray vision or protection from flashes. Also, high DNA cost because of how powerful it is.
|
||||
//Augmented Eyesight: Gives you X-ray vision or protection from flashes. Also, high DNA cost because of how powerful it is.
|
||||
//Possible todo: make a custom message for directing a penlight/flashlight at the eyes - not sure what would display though.
|
||||
|
||||
/obj/effect/proc_holder/changeling/augmented_eyesight
|
||||
@@ -41,7 +41,7 @@
|
||||
return 1
|
||||
|
||||
|
||||
/obj/effect/proc_holder/changeling/augmented_eyesight/on_refund(mob/user) //Get rid of x-ray vision and flash protection when the user refunds this ability
|
||||
/obj/effect/proc_holder/changeling/augmented_eyesight/on_refund(mob/user) //Get rid of X-ray vision and flash protection when the user refunds this ability
|
||||
var/obj/item/organ/eyes/E = user.getorganslot(ORGAN_SLOT_EYES)
|
||||
if(E)
|
||||
if (active)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/obj/effect/proc_holder/changeling/digitalcamo
|
||||
name = "Digital Camouflage"
|
||||
desc = "By evolving the ability to distort our form and proprotions, we defeat common altgorithms used to detect lifeforms on cameras."
|
||||
desc = "By evolving the ability to distort our form and proportions, we defeat common algorithms used to detect lifeforms on cameras."
|
||||
helptext = "We cannot be tracked by camera or seen by AI units while using this skill. However, humans looking at us will find us... uncanny."
|
||||
dna_cost = 1
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
/obj/effect/proc_holder/changeling/weapon/proc/check_weapon(mob/user, obj/item/hand_item)
|
||||
if(istype(hand_item, weapon_type))
|
||||
user.temporarilyRemoveItemFromInventory(hand_item, TRUE) //DROPDEL_1 will delete the item
|
||||
user.temporarilyRemoveItemFromInventory(hand_item, TRUE) //DROPDEL will delete the item
|
||||
if(!silent)
|
||||
playsound(user, 'sound/effects/blobattack.ogg', 30, 1)
|
||||
user.visible_message("<span class='warning'>With a sickening crunch, [user] reforms [user.p_their()] [weapon_name_simple] into an arm!</span>", "<span class='notice'>We assimilate the [weapon_name_simple] back into our body.</span>", "<span class='italics>You hear organic matter ripping and tearing!</span>")
|
||||
@@ -149,7 +149,7 @@
|
||||
item_state = "arm_blade"
|
||||
lefthand_file = 'icons/mob/inhands/antag/changeling_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/antag/changeling_righthand.dmi'
|
||||
flags_1 = ABSTRACT_1 | NODROP_1 | DROPDEL_1
|
||||
item_flags = NEEDS_PERMIT | ABSTRACT | NODROP | DROPDEL
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
force = 25
|
||||
throwforce = 0 //Just to be on the safe side
|
||||
@@ -229,7 +229,8 @@
|
||||
item_state = "tentacle"
|
||||
lefthand_file = 'icons/mob/inhands/antag/changeling_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/antag/changeling_righthand.dmi'
|
||||
flags_1 = ABSTRACT_1 | NODROP_1 | DROPDEL_1 | NOBLUDGEON_1
|
||||
item_flags = NEEDS_PERMIT | ABSTRACT | NODROP | DROPDEL | NOBLUDGEON
|
||||
flags_1 = NONE
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
ammo_type = /obj/item/ammo_casing/magic/tentacle
|
||||
fire_sound = 'sound/effects/splat.ogg'
|
||||
@@ -397,7 +398,7 @@
|
||||
/obj/item/shield/changeling
|
||||
name = "shield-like mass"
|
||||
desc = "A mass of tough, boney tissue. You can still see the fingers as a twisted pattern in the shield."
|
||||
flags_1 = ABSTRACT_1 | NODROP_1 | DROPDEL_1
|
||||
item_flags = ABSTRACT | NODROP | DROPDEL
|
||||
icon = 'icons/obj/items_and_weapons.dmi'
|
||||
icon_state = "ling_shield"
|
||||
lefthand_file = 'icons/mob/inhands/antag/changeling_lefthand.dmi'
|
||||
@@ -445,7 +446,7 @@
|
||||
name = "flesh mass"
|
||||
icon_state = "lingspacesuit"
|
||||
desc = "A huge, bulky mass of pressure and temperature-resistant organic tissue, evolved to facilitate space travel."
|
||||
flags_1 = NODROP_1 | DROPDEL_1
|
||||
item_flags = NODROP | DROPDEL
|
||||
clothing_flags = STOPSPRESSUREDAMAGE //Not THICKMATERIAL because it's organic tissue, so if somebody tries to inject something into it, it still ends up in your blood. (also balance but muh fluff)
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/oxygen)
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90) //No armor at all.
|
||||
@@ -465,7 +466,7 @@
|
||||
name = "flesh mass"
|
||||
icon_state = "lingspacehelmet"
|
||||
desc = "A covering of pressure and temperature-resistant organic tissue with a glass-like chitin front."
|
||||
flags_1 = NODROP_1 | DROPDEL_1
|
||||
item_flags = NODROP | DROPDEL
|
||||
clothing_flags = STOPSPRESSUREDAMAGE
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
|
||||
flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
|
||||
@@ -491,7 +492,7 @@
|
||||
name = "chitinous mass"
|
||||
desc = "A tough, hard covering of black chitin."
|
||||
icon_state = "lingarmor"
|
||||
flags_1 = NODROP_1 | DROPDEL_1
|
||||
item_flags = NODROP | DROPDEL
|
||||
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
|
||||
armor = list("melee" = 40, "bullet" = 40, "laser" = 40, "energy" = 20, "bomb" = 10, "bio" = 4, "rad" = 0, "fire" = 90, "acid" = 90)
|
||||
flags_inv = HIDEJUMPSUIT
|
||||
@@ -507,6 +508,6 @@
|
||||
name = "chitinous mass"
|
||||
desc = "A tough, hard covering of black chitin with transparent chitin in front."
|
||||
icon_state = "lingarmorhelmet"
|
||||
flags_1 = NODROP_1 | DROPDEL_1
|
||||
item_flags = NODROP | DROPDEL
|
||||
armor = list("melee" = 40, "bullet" = 40, "laser" = 40, "energy" = 20, "bomb" = 10, "bio" = 4, "rad" = 0, "fire" = 90, "acid" = 90)
|
||||
flags_inv = HIDEEARS|HIDEHAIR|HIDEEYES|HIDEFACIALHAIR|HIDEFACE
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#define CHANGELING_PHEROMONE_MIN_DISTANCE 10 //More generous than the agent pinpointer because you don't know who you're looking for.
|
||||
#define CHANGELING_PHEROMONE_MAX_DISTANCE 25 //They can smell your fear a mile away. Well, 50 meters.
|
||||
#define CHANGELING_PHEROMONE_PING_TIME 20 //2s update time.
|
||||
|
||||
|
||||
/obj/effect/proc_holder/changeling/pheromone_receptors
|
||||
name = "Pheromone Receptors"
|
||||
desc = "We attune our senses to track other changelings by scent. The closer they are, the easier we can find them."
|
||||
helptext = "We will know the general direction of nearby changelings, with closer scents being stronger. Our chemical generation is slowed while this is active."
|
||||
chemical_cost = 0 //Reduces regain rate while active.
|
||||
dna_cost = 2
|
||||
var/receptors_active = FALSE
|
||||
|
||||
/obj/effect/proc_holder/changeling/pheromone_receptors/sting_action(mob/living/carbon/user)
|
||||
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
if(!receptors_active)
|
||||
to_chat(user, "<span class='warning'>We search for the scent of any nearby changelings.</span>")
|
||||
changeling.chem_recharge_slowdown += 0.5
|
||||
user.apply_status_effect(/datum/status_effect/agent_pinpointer/changeling)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>We stop searching for now.</span>")
|
||||
changeling.chem_recharge_slowdown -= 0.5
|
||||
user.remove_status_effect(/datum/status_effect/agent_pinpointer/changeling)
|
||||
|
||||
receptors_active = !receptors_active
|
||||
|
||||
//Modified IA pinpointer - Points to the NEAREST changeling, but will only get you within a few tiles of the target.
|
||||
//You'll still have to rely on intuition and observation to make the identification. Lings can 'hide' in public places.
|
||||
/datum/status_effect/agent_pinpointer/changeling
|
||||
alert_type = /obj/screen/alert/status_effect/agent_pinpointer/changeling
|
||||
minimum_range = CHANGELING_PHEROMONE_MIN_DISTANCE
|
||||
tick_interval = CHANGELING_PHEROMONE_PING_TIME
|
||||
range_fuzz_factor = 0
|
||||
|
||||
/datum/status_effect/agent_pinpointer/changeling/scan_for_target()
|
||||
var/turf/my_loc = get_turf(owner)
|
||||
|
||||
var/list/mob/living/carbon/changelings = list()
|
||||
|
||||
for(var/mob/living/carbon/C in GLOB.alive_mob_list)
|
||||
if(C != owner && C.mind)
|
||||
var/datum/antagonist/changeling/antag_datum = C.mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
if(istype(antag_datum))
|
||||
var/their_loc = get_turf(C)
|
||||
var/distance = get_dist_euclidian(my_loc, their_loc)
|
||||
if (distance < CHANGELING_PHEROMONE_MAX_DISTANCE)
|
||||
changelings[C] = (CHANGELING_PHEROMONE_MAX_DISTANCE ** 2) - (distance ** 2)
|
||||
|
||||
if(changelings.len)
|
||||
scan_target = pickweight(changelings) //Point at a 'random' changeling, biasing heavily towards closer ones.
|
||||
else
|
||||
scan_target = null
|
||||
|
||||
|
||||
/obj/screen/alert/status_effect/agent_pinpointer/changeling
|
||||
name = "Pheromone Scent"
|
||||
desc = "The nose always knows."
|
||||
@@ -134,7 +134,7 @@
|
||||
return 1
|
||||
|
||||
/obj/effect/proc_holder/changeling/sting/false_armblade/sting_action(mob/user, mob/target)
|
||||
add_logs(user, target, "stung", object="falso armblade sting")
|
||||
add_logs(user, target, "stung", object="false armblade sting")
|
||||
|
||||
var/obj/item/held = target.get_active_held_item()
|
||||
if(held && !target.dropItemToGround(held))
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
/obj/item/clothing/glasses/changeling
|
||||
name = "flesh"
|
||||
flags_1 = NODROP_1
|
||||
item_flags = NODROP
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/item/clothing/glasses/changeling/attack_hand(mob/user)
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
/obj/item/clothing/under/changeling
|
||||
name = "flesh"
|
||||
flags_1 = NODROP_1
|
||||
item_flags = NODROP
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/item/clothing/under/changeling/attack_hand(mob/user)
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
/obj/item/clothing/suit/changeling
|
||||
name = "flesh"
|
||||
flags_1 = NODROP_1
|
||||
item_flags = NODROP
|
||||
allowed = list(/obj/item/changeling)
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
/obj/item/clothing/head/changeling
|
||||
name = "flesh"
|
||||
flags_1 = NODROP_1
|
||||
item_flags = NODROP
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/item/clothing/head/changeling/attack_hand(mob/user)
|
||||
@@ -57,7 +57,7 @@
|
||||
|
||||
/obj/item/clothing/shoes/changeling
|
||||
name = "flesh"
|
||||
flags_1 = NODROP_1
|
||||
item_flags = NODROP
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/item/clothing/shoes/changeling/attack_hand(mob/user)
|
||||
@@ -69,7 +69,7 @@
|
||||
|
||||
/obj/item/clothing/gloves/changeling
|
||||
name = "flesh"
|
||||
flags_1 = NODROP_1
|
||||
item_flags = NODROP
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/item/clothing/gloves/changeling/attack_hand(mob/user)
|
||||
@@ -81,7 +81,7 @@
|
||||
|
||||
/obj/item/clothing/mask/changeling
|
||||
name = "flesh"
|
||||
flags_1 = NODROP_1
|
||||
item_flags = NODROP
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/item/clothing/mask/changeling/attack_hand(mob/user)
|
||||
@@ -93,7 +93,7 @@
|
||||
|
||||
/obj/item/changeling
|
||||
name = "flesh"
|
||||
flags_1 = NODROP_1
|
||||
item_flags = NODROP
|
||||
slot_flags = ALL
|
||||
allowed = list(/obj/item/changeling)
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
icon = 'icons/turf/floors.dmi'
|
||||
icon_state = "clockwork_floor"
|
||||
layer = TURF_LAYER
|
||||
plane = FLOOR_PLANE
|
||||
|
||||
/obj/effect/clockwork/overlay/floor/bloodcult //this is used by BLOOD CULT, it shouldn't use such a path...
|
||||
icon_state = "cult"
|
||||
@@ -254,8 +254,8 @@
|
||||
var/list/repair_values = list()
|
||||
if(!fabricator.fabricator_repair_checks(repair_values, src, user))
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user]'s [fabricator.name] starts coverin[src == user ? "g [user.p_them()]" : "g [src]"] in glowing orange energy...</span>", \
|
||||
"<span class='alloy'>You start repairin[src == user ? "g yourself" : "g [src]"]...</span>")
|
||||
user.visible_message("<span class='notice'>[user]'s [fabricator.name] starts covering [src == user ? "[user.p_them()]" : "[src]"] in glowing orange energy...</span>", \
|
||||
"<span class='alloy'>You start repairing [src == user ? "yourself" : "[src]"]...</span>")
|
||||
fabricator.repairing = src
|
||||
while(fabricator && user && src)
|
||||
if(!do_after(user, repair_values["healing_for_cycle"] * fabricator.speed_multiplier, target = src, \
|
||||
@@ -283,7 +283,7 @@
|
||||
if(health == maxHealth) //if we're at maximum health, replace the turf under us
|
||||
return FALSE
|
||||
else if(fabricator_heal(user, fabricator) && user)
|
||||
user.visible_message("<span class='notice'>[user]'s [fabricator.name] stops coverin[src == user ? "g [user.p_them()]" : "g [src]"] with glowing orange energy.</span>", \
|
||||
user.visible_message("<span class='notice'>[user]'s [fabricator.name] stops covering [src == user ? "[user.p_them()]" : "[src]"] with glowing orange energy.</span>", \
|
||||
"<span class='alloy'>You finish repairin[src == user ? "g yourself. You are":"g [src]. [p_theyre(TRUE)]"] now at <b>[abs(HEALTH_THRESHOLD_DEAD - health)]/[abs(HEALTH_THRESHOLD_DEAD - maxHealth)]</b> health.</span>")
|
||||
|
||||
//Same with clockwork mobs.
|
||||
@@ -292,7 +292,7 @@
|
||||
if(health == maxHealth) //if we're at maximum health, replace the turf under us
|
||||
return FALSE
|
||||
else if(fabricator_heal(user, fabricator) && user)
|
||||
user.visible_message("<span class='notice'>[user]'s [fabricator.name] stops coverin[src == user ? "g [user.p_them()]" : "g [src]"] with glowing orange energy.</span>", \
|
||||
user.visible_message("<span class='notice'>[user]'s [fabricator.name] stops covering [src == user ? "[user.p_them()]" : "[src]"] with glowing orange energy.</span>", \
|
||||
"<span class='alloy'>You finish repairin[src == user ? "g yourself. You are":"g [src]. [p_theyre(TRUE)]"] now at <b>[health]/[maxHealth]</b> health.</span>")
|
||||
|
||||
//Cogscarabs get special interaction because they're drones and have innate self-heals/revives.
|
||||
@@ -304,13 +304,13 @@
|
||||
if(health == maxHealth)
|
||||
return FALSE
|
||||
else if(!(flags_1 & GODMODE))
|
||||
user.visible_message("<span class='notice'>[user]'s [fabricator.name] starts coverin[src == user ? "g [user.p_them()]" : "g [src]"] in glowing orange energy...</span>", \
|
||||
"<span class='alloy'>You start repairin[src == user ? "g yourself" : "g [src]"]...</span>")
|
||||
user.visible_message("<span class='notice'>[user]'s [fabricator.name] starts covering [src == user ? "[user.p_them()]" : "[src]"] in glowing orange energy...</span>", \
|
||||
"<span class='alloy'>You start repairing [src == user ? "yourself" : "[src]"]...</span>")
|
||||
fabricator.repairing = src
|
||||
if(do_after(user, (maxHealth - health)*2, target=src))
|
||||
adjustHealth(-maxHealth)
|
||||
user.visible_message("<span class='notice'>[user]'s [fabricator.name] stops coverin[src == user ? "g [user.p_them()]" : "g [src]"] with glowing orange energy.</span>", \
|
||||
"<span class='alloy'>You finish repairin[src == user ? "g yourself" : "g [src]"].</span>")
|
||||
user.visible_message("<span class='notice'>[user]'s [fabricator.name] stops covering [src == user ? "[user.p_them()]" : "[src]"] with glowing orange energy.</span>", \
|
||||
"<span class='alloy'>You finish repairing [src == user ? "yourself" : "[src]"].</span>")
|
||||
if(fabricator)
|
||||
fabricator.repairing = null
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
name = "replicant manacles"
|
||||
desc = "Heavy manacles made out of freezing-cold metal. It looks like brass, but feels much more solid."
|
||||
icon_state = "brass_manacles"
|
||||
flags_1 = DROPDEL_1
|
||||
item_flags = DROPDEL
|
||||
|
||||
/obj/item/restraints/handcuffs/clockwork/dropped(mob/user)
|
||||
user.visible_message("<span class='danger'>[user]'s [name] come apart at the seams!</span>", \
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
user.emote("scream")
|
||||
user.apply_damage(30, BRUTE, BODY_ZONE_HEAD)
|
||||
user.adjustBrainLoss(30)
|
||||
addtimer(CALLBACK(user, /mob/living.proc/dropItemToGround), src, 1) //equipped happens before putting stuff on(but not before picking items up), 1). thus, we need to wait for it to be on before forcing it off.
|
||||
addtimer(CALLBACK(user, /mob/living.proc/dropItemToGround, src, TRUE), 1) //equipped happens before putting stuff on(but not before picking items up), 1). thus, we need to wait for it to be on before forcing it off.
|
||||
|
||||
/obj/item/clothing/head/helmet/clockwork/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0)
|
||||
if(equipper && !is_servant_of_ratvar(equipper))
|
||||
@@ -106,13 +106,13 @@
|
||||
if(slot == SLOT_WEAR_SUIT && !is_servant_of_ratvar(user))
|
||||
if(!iscultist(user))
|
||||
to_chat(user, "<span class='heavy_brass'>\"Now now, this is for my servants, not you.\"</span>")
|
||||
user.visible_message("<span class='warning'>As [user] puts [src] on, it flickers off [user.p_their()] body!</span>", "<span class='warning'>The curiass flickers off your body, leaving only nausea!</span>")
|
||||
user.visible_message("<span class='warning'>As [user] puts [src] on, it flickers off [user.p_their()] body!</span>", "<span class='warning'>The cuirass flickers off your body, leaving only nausea!</span>")
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/C = user
|
||||
C.vomit(20)
|
||||
else
|
||||
to_chat(user, "<span class='heavy_brass'>\"I think this armor is too hot for you to handle.\"</span>")
|
||||
to_chat(user, "<span class='userdanger'>The curiass emits a burst of flame as you scramble to get it off!</span>")
|
||||
to_chat(user, "<span class='userdanger'>The cuirass emits a burst of flame as you scramble to get it off!</span>")
|
||||
user.emote("scream")
|
||||
user.apply_damage(15, BURN, BODY_ZONE_CHEST)
|
||||
user.adjust_fire_stacks(2)
|
||||
|
||||
@@ -278,7 +278,7 @@
|
||||
dat += "<font color=#BE8700 size=3>Items</font><br>"
|
||||
dat += "<font color=#BE8700><b>Slab:</b></font> A clockwork slab, a Servant's most important tool. You're holding one! Keep it safe and hidden.<br>"
|
||||
dat += "<font color=#BE8700><b>Visor:</b></font> A judicial visor, which is a pair of glasses that can smite an area for a brief stun and delayed explosion.<br>"
|
||||
dat += "<font color=#BE8700><b>Wraith Specs:</b></font> Wraith spectacles, which provide true sight (x-ray, night vision) but damage the wearer's eyes.<br>"
|
||||
dat += "<font color=#BE8700><b>Wraith Specs:</b></font> Wraith spectacles, which provide true sight (X-ray, night vision) but damage the wearer's eyes.<br>"
|
||||
dat += "<font color=#BE8700><b>Spear:</b></font> A Ratvarian spear, which is a very powerful melee weapon that produces Vitality.<br>"
|
||||
dat += "<font color=#BE8700><b>Fabricator:</b></font> A replica fabricator, which converts objects into clockwork versions.<br><br>"
|
||||
dat += "<font color=#BE8700 size=3>Constructs</font><br>"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<span class='brass'>Siphons <b>5 W</b> of power per second while in an APC.</span>"
|
||||
icon_state = "wall_gear"
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
flags_1 = NOBLUDGEON_1
|
||||
item_flags = NOBLUDGEON
|
||||
var/obj/machinery/power/apc/apc
|
||||
|
||||
/obj/item/clockwork/integration_cog/Initialize()
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
righthand_file = 'icons/mob/inhands/antag/clockwork_righthand.dmi'
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
force = 5
|
||||
flags_1 = NOBLUDGEON_1
|
||||
item_flags = NOBLUDGEON
|
||||
var/speed_multiplier = 1 //The speed ratio the fabricator operates at
|
||||
var/uses_power = TRUE
|
||||
var/repairing = null //what we're currently repairing, if anything
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//Wraith spectacles: Grants x-ray and night vision at the eventual cost of the wearer's sight if worn too long. Nar-Sian cultists are instantly blinded.
|
||||
//Wraith spectacles: Grants X-ray and night vision at the eventual cost of the wearer's sight if worn too long. Nar-Sian cultists are instantly blinded.
|
||||
/obj/item/clothing/glasses/wraith_spectacles
|
||||
name = "antique spectacles"
|
||||
desc = "Unnerving glasses with opaque yellow lenses."
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
descname = "Trap, Stunning"
|
||||
name = "Sigil of Transgression"
|
||||
desc = "Wards a tile with a sigil, which will briefly stun the next non-Servant to cross it and apply Belligerent to them."
|
||||
invocations = list("Divinity, smite...", "...those who tresspass here!")
|
||||
invocations = list("Divinity, smite...", "...those who trespass here!")
|
||||
channel_time = 50
|
||||
power_cost = 50
|
||||
whispered = TRUE
|
||||
|
||||
@@ -117,6 +117,9 @@
|
||||
to_chat(user, "<span class='warning'>As you unsecure [src] from the floor, you see cracks appear in its surface!</span>")
|
||||
|
||||
/obj/structure/destructible/clockwork/emp_act(severity)
|
||||
. = ..()
|
||||
if(. & EMP_PROTECT_SELF)
|
||||
return
|
||||
if(anchored && unanchored_icon)
|
||||
anchored = FALSE
|
||||
update_anchored(null, obj_integrity > max_integrity * 0.25)
|
||||
@@ -203,6 +206,9 @@
|
||||
toggle()
|
||||
|
||||
/obj/structure/destructible/clockwork/powered/emp_act(severity)
|
||||
. = ..()
|
||||
if(. & EMP_PROTECT_SELF)
|
||||
return
|
||||
if(forced_disable(TRUE))
|
||||
new /obj/effect/temp_visual/emp(loc)
|
||||
|
||||
|
||||
+1
-1
@@ -335,7 +335,7 @@
|
||||
sleep(3)
|
||||
GLOB.clockwork_gateway_activated = TRUE
|
||||
var/turf/T = SSmapping.get_station_center()
|
||||
new /obj/structure/destructible/clockwork/massive/ratvar(T)
|
||||
new /obj/structure/destructible/clockwork/massive/ratvar(T, TRUE) //Citadel edit - hugboxes ratvar spawning by admins
|
||||
SSticker.force_ending = TRUE
|
||||
var/x0 = T.x
|
||||
var/y0 = T.y
|
||||
|
||||
+3
-2
@@ -17,7 +17,7 @@
|
||||
var/convert_range = 10
|
||||
obj_flags = CAN_BE_HIT | DANGEROUS_POSSESSION
|
||||
|
||||
/obj/structure/destructible/clockwork/massive/ratvar/Initialize()
|
||||
/obj/structure/destructible/clockwork/massive/ratvar/Initialize(mapload, is_from_gateway = FALSE)
|
||||
. = ..()
|
||||
GLOB.ratvar_awakens++
|
||||
for(var/obj/O in GLOB.all_clockwork_objects)
|
||||
@@ -29,7 +29,8 @@
|
||||
sound_to_playing_players('sound/effects/ratvar_reveal.ogg')
|
||||
var/mutable_appearance/alert_overlay = mutable_appearance('icons/effects/clockwork_effects.dmi', "ratvar_alert")
|
||||
notify_ghosts("The Justiciar's light calls to you! Reach out to Ratvar in [get_area_name(src)] to be granted a shell to spread his glory!", null, source = src, alert_overlay = alert_overlay)
|
||||
INVOKE_ASYNC(SSshuttle.emergency, /obj/docking_port/mobile/emergency.proc/request, null, 10, null, FALSE, 0)
|
||||
if(is_from_gateway) //citadel edit - hugbox
|
||||
INVOKE_ASYNC(SSshuttle.emergency, /obj/docking_port/mobile/emergency.proc/request, null, 10, null, FALSE, 0)
|
||||
|
||||
/obj/structure/destructible/clockwork/massive/ratvar/Destroy()
|
||||
GLOB.ratvar_awakens--
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
return
|
||||
if(!is_servant_of_ratvar(user))
|
||||
return
|
||||
if(!isprocessing)
|
||||
if(!(datum_flags & DF_ISPROCESSING))
|
||||
START_PROCESSING(SSprocessing, src)
|
||||
to_chat(user, "<span class='notice'>You activate [src].</span>")
|
||||
icon_state = "[icon_state]_on"
|
||||
|
||||
@@ -159,7 +159,7 @@
|
||||
SSticker.mode.servants_of_ratvar -= owner
|
||||
SSticker.mode.update_servant_icons_removed(owner)
|
||||
if(!silent)
|
||||
owner.current.visible_message("<span class='deconversion_message'>[owner] seems to have remembered [owner.p_their()] true allegiance!</span>", null, null, null, owner.current)
|
||||
owner.current.visible_message("<span class='deconversion_message'>[owner.current] seems to have remembered [owner.current.p_their()] true allegiance!</span>", null, null, null, owner.current)
|
||||
to_chat(owner, "<span class='userdanger'>A cold, cold darkness flows through your mind, extinguishing the Justiciar's light and all of your memories as his servant.</span>")
|
||||
owner.current.log_message("<font color=#BE8700>Has renounced the cult of Ratvar!</font>", INDIVIDUAL_ATTACK_LOG)
|
||||
owner.special_role = null
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
qdel(nullify_spell)
|
||||
return
|
||||
BS = possible_spells[entered_spell_name]
|
||||
if(QDELETED(src) || owner.incapacitated() || !BS)
|
||||
if(QDELETED(src) || owner.incapacitated() || !BS || (rune && !(locate(/obj/effect/rune/empower) in range(1, owner))) || (spells.len >= limit))
|
||||
return
|
||||
to_chat(owner,"<span class='warning'>You begin to carve unnatural symbols into your flesh!</span>")
|
||||
SEND_SOUND(owner, sound('sound/weapons/slice.ogg',0,1,10))
|
||||
@@ -271,7 +271,6 @@
|
||||
attached_action.desc += "<br><b><u>Has [attached_action.charges] use\s remaining</u></b>."
|
||||
attached_action.UpdateButtonIcon()
|
||||
if(attached_action.charges <= 0)
|
||||
remove_mousepointer(ranged_ability_user.client)
|
||||
remove_ranged_ability("<span class='cult'>You have exhausted the spell's power!</span>")
|
||||
qdel(src)
|
||||
|
||||
@@ -340,7 +339,8 @@
|
||||
icon = 'icons/obj/items_and_weapons.dmi'
|
||||
icon_state = "disintegrate"
|
||||
item_state = null
|
||||
flags_1 = ABSTRACT_1 | NODROP_1 | DROPDEL_1
|
||||
item_flags = NEEDS_PERMIT | ABSTRACT | NODROP | DROPDEL
|
||||
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
throwforce = 0
|
||||
throw_range = 0
|
||||
@@ -520,7 +520,7 @@
|
||||
name = "shadow shackles"
|
||||
desc = "Shackles that bind the wrists with sinister magic."
|
||||
trashtype = /obj/item/restraints/handcuffs/energy/used
|
||||
flags_1 = DROPDEL_1
|
||||
item_flags = DROPDEL
|
||||
|
||||
/obj/item/restraints/handcuffs/energy/cult/used/dropped(mob/user)
|
||||
user.visible_message("<span class='danger'>[user]'s shackles shatter in a discharge of dark magic!</span>", \
|
||||
@@ -542,7 +542,7 @@
|
||||
var/obj/item/stack/sheet/candidate = target
|
||||
if(candidate.use(50))
|
||||
uses--
|
||||
to_chat(user, "<span class='warning'>A dark cloud eminates from your hand and swirls around the metal, twisting it into a construct shell!</span>")
|
||||
to_chat(user, "<span class='warning'>A dark cloud emanates from your hand and swirls around the metal, twisting it into a construct shell!</span>")
|
||||
new /obj/structure/constructshell(T)
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
else
|
||||
@@ -553,12 +553,12 @@
|
||||
if(candidate.use(quantity))
|
||||
uses --
|
||||
new /obj/item/stack/sheet/runed_metal(T,quantity)
|
||||
to_chat(user, "<span class='warning'>A dark cloud eminates from you hand and swirls around the plasteel, transforming it into runed metal!</span>")
|
||||
to_chat(user, "<span class='warning'>A dark cloud emanates from you hand and swirls around the plasteel, transforming it into runed metal!</span>")
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
else if(istype(target,/mob/living/silicon/robot))
|
||||
var/mob/living/silicon/robot/candidate = target
|
||||
if(candidate.mmi)
|
||||
user.visible_message("<span class='danger'>A dark cloud eminates from [user]'s hand and swirls around [candidate]!</span>")
|
||||
user.visible_message("<span class='danger'>A dark cloud emanates from [user]'s hand and swirls around [candidate]!</span>")
|
||||
playsound(T, 'sound/machines/airlock_alien_prying.ogg', 80, 1)
|
||||
var/prev_color = candidate.color
|
||||
candidate.color = "black"
|
||||
@@ -581,7 +581,7 @@
|
||||
candidate.color = prev_color
|
||||
else
|
||||
uses--
|
||||
to_chat(user, "<span class='warning'>A dark cloud eminates from you hand and swirls around [candidate] - twisting it into a construct shell!</span>")
|
||||
to_chat(user, "<span class='warning'>A dark cloud emanates from you hand and swirls around [candidate] - twisting it into a construct shell!</span>")
|
||||
new /obj/structure/constructshell(T)
|
||||
SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25))
|
||||
else if(istype(target,/obj/machinery/door/airlock))
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
else
|
||||
to_chat(mob, "<span class='danger'>You have a [item_name] in your [where].</span>")
|
||||
if(where == "backpack")
|
||||
mob.back.SendSignal(COMSIG_TRY_STORAGE_SHOW, mob)
|
||||
SEND_SIGNAL(mob.back, COMSIG_TRY_STORAGE_SHOW, mob)
|
||||
return TRUE
|
||||
|
||||
/datum/antagonist/cult/apply_innate_effects(mob/living/mob_override)
|
||||
@@ -128,7 +128,7 @@
|
||||
SSticker.mode.cult -= owner
|
||||
SSticker.mode.update_cult_icons_removed(owner)
|
||||
if(!silent)
|
||||
owner.current.visible_message("<span class='deconversion_message'>[owner.current] looks like [owner.current.p_theyve()] just reverted to [owner.p_their()] old faith!</span>", null, null, null, owner.current)
|
||||
owner.current.visible_message("<span class='deconversion_message'>[owner.current] looks like [owner.current.p_theyve()] just reverted to [owner.current.p_their()] old faith!</span>", null, null, null, owner.current)
|
||||
to_chat(owner.current, "<span class='userdanger'>An unfamiliar white light flashes through your mind, cleansing the taint of the Geometer and all your memories as her servant.</span>")
|
||||
owner.current.log_message("<font color=#960000>Has renounced the cult of Nar'Sie!</font>", INDIVIDUAL_ATTACK_LOG)
|
||||
if(cult_team.blood_target && cult_team.blood_target_image && owner.current.client)
|
||||
@@ -228,7 +228,7 @@
|
||||
target_candidates += player.mind
|
||||
|
||||
if(target_candidates.len == 0)
|
||||
message_admins("Cult Sacrifice: Could not find unconvertable target, checking for convertable target.")
|
||||
message_admins("Cult Sacrifice: Could not find unconvertible target, checking for convertible target.")
|
||||
for(var/mob/living/carbon/human/player in GLOB.player_list)
|
||||
if(player.mind && !player.mind.has_antag_datum(/datum/antagonist/cult) && player.stat != DEAD)
|
||||
target_candidates += player.mind
|
||||
@@ -248,7 +248,7 @@
|
||||
|
||||
objectives += sac_objective
|
||||
else
|
||||
message_admins("Cult Sacrifice: Could not find unconvertable or convertable target. WELP!")
|
||||
message_admins("Cult Sacrifice: Could not find unconvertible or convertible target. WELP!")
|
||||
|
||||
|
||||
//SUMMON OBJECTIVE
|
||||
|
||||
@@ -215,7 +215,7 @@
|
||||
var/cooldown = 0
|
||||
var/base_cooldown = 1200
|
||||
|
||||
/datum/action/innate/cult/master/cultmark/New()
|
||||
/datum/action/innate/cult/master/cultmark/New(Target)
|
||||
CM = new()
|
||||
CM.attached_action = src
|
||||
..()
|
||||
@@ -299,7 +299,7 @@
|
||||
name = "Mark a Blood Target for the Cult"
|
||||
desc = "Marks a target for the entire cult to track."
|
||||
|
||||
/datum/action/innate/cult/master/cultmark/IsAvailable()
|
||||
/datum/action/innate/cult/master/cultmark/ghost/IsAvailable()
|
||||
if(istype(owner, /mob/dead/observer) && iscultist(owner.mind.current))
|
||||
return TRUE
|
||||
else
|
||||
@@ -457,7 +457,6 @@
|
||||
new /obj/effect/temp_visual/cult/sparks(get_turf(target), ranged_ability_user.dir)
|
||||
attached_action.throwing = FALSE
|
||||
attached_action.cooldown = world.time + attached_action.base_cooldown
|
||||
remove_mousepointer(ranged_ability_user.client)
|
||||
remove_ranged_ability("<span class='cult'>A pulse of blood magic surges through you as you shift [attached_action.throwee] through time and space.</span>")
|
||||
caller.update_action_buttons_icon()
|
||||
addtimer(CALLBACK(caller, /mob.proc/update_action_buttons_icon), attached_action.base_cooldown)
|
||||
|
||||
@@ -64,7 +64,8 @@
|
||||
/obj/item/melee/cultblade/ghost
|
||||
name = "eldritch sword"
|
||||
force = 19 //can't break normal airlocks
|
||||
flags_1 = NODROP_1|DROPDEL_1
|
||||
item_flags = NEEDS_PERMIT | NODROP | DROPDEL
|
||||
flags_1 = NONE
|
||||
|
||||
/obj/item/melee/cultblade/pickup(mob/living/user)
|
||||
..()
|
||||
@@ -301,7 +302,7 @@
|
||||
item_state = "cult_hoodalt"
|
||||
|
||||
/obj/item/clothing/head/culthood/alt/ghost
|
||||
flags_1 = NODROP_1|DROPDEL_1
|
||||
item_flags = NODROP | DROPDEL
|
||||
|
||||
/obj/item/clothing/suit/cultrobes/alt
|
||||
name = "cultist robes"
|
||||
@@ -310,7 +311,7 @@
|
||||
item_state = "cultrobesalt"
|
||||
|
||||
/obj/item/clothing/suit/cultrobes/alt/ghost
|
||||
flags_1 = NODROP_1|DROPDEL_1
|
||||
item_flags = NODROP | DROPDEL
|
||||
|
||||
|
||||
/obj/item/clothing/head/magus
|
||||
@@ -333,7 +334,7 @@
|
||||
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/cult
|
||||
name = "nar-sien hardened helmet"
|
||||
name = "\improper Nar-Sien hardened helmet"
|
||||
desc = "A heavily-armored helmet worn by warriors of the Nar-Sien cult. It can withstand hard vacuum."
|
||||
icon_state = "cult_helmet"
|
||||
item_state = "cult_helmet"
|
||||
@@ -342,7 +343,7 @@
|
||||
actions_types = list()
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/cult
|
||||
name = "nar-sien hardened armor"
|
||||
name = "\improper Nar-Sien hardened armor"
|
||||
icon_state = "cult_armor"
|
||||
item_state = "cult_armor"
|
||||
desc = "A heavily-armored exosuit worn by warriors of the Nar-Sien cult. It can withstand hard vacuum."
|
||||
@@ -520,7 +521,7 @@
|
||||
sleep(20)
|
||||
var/global/list/curses
|
||||
if(!curses)
|
||||
curses = list("A fuel technician just slit his own throat and begged for death. The shuttle will be delayed by three minutes.",
|
||||
curses = list("A fuel technician just slit his own throat and begged for death.",
|
||||
"The shuttle's navigation programming was replaced by a file containing just two words: IT COMES.",
|
||||
"The shuttle's custodian was found washing the windows with their own blood.",
|
||||
"A shuttle engineer began screaming 'DEATH IS NOT THE END' and ripped out wires until an arc flash seared off her flesh.",
|
||||
@@ -754,7 +755,7 @@
|
||||
guns_left = 24
|
||||
mag_type = /obj/item/ammo_box/magazine/internal/boltaction/enchanted/arcane_barrage/blood
|
||||
fire_sound = 'sound/magic/wand_teleport.ogg'
|
||||
flags_1 = NOBLUDGEON_1 | DROPDEL_1
|
||||
item_flags = NEEDS_PERMIT | NOBLUDGEON | DROPDEL
|
||||
|
||||
|
||||
/obj/item/ammo_box/magazine/internal/boltaction/enchanted/arcane_barrage/blood
|
||||
@@ -792,7 +793,7 @@
|
||||
icon = 'icons/obj/items_and_weapons.dmi'
|
||||
icon_state = "disintegrate"
|
||||
item_state = null
|
||||
flags_1 = ABSTRACT_1 | NODROP_1 | DROPDEL_1
|
||||
item_flags = ABSTRACT | NODROP | DROPDEL
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
throwforce = 0
|
||||
throw_range = 0
|
||||
|
||||
@@ -496,13 +496,13 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
if((istype(I, /obj/item/melee/cultblade/dagger) && iscultist(user)))
|
||||
user.visible_message("<span class='warning'>[user.name] begins erasing [src]...</span>", "<span class='notice'>You begin erasing [src]...</span>")
|
||||
if(do_after(user, 50, target = src)) //Prevents accidental erasures.
|
||||
log_game("Summon Narsie rune erased by [user.mind.key] (ckey) with [I.name]")
|
||||
message_admins("[key_name_admin(user)] erased a Narsie rune with [I.name]")
|
||||
log_game("Summon Narsie rune erased by [key_name(user)] with [I.name]")
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] erased a Narsie rune with [I.name]")
|
||||
..()
|
||||
else
|
||||
if(istype(I, /obj/item/nullrod)) //Begone foul magiks. You cannot hinder me.
|
||||
log_game("Summon Narsie rune erased by [user.mind.key] (ckey) using a null rod")
|
||||
message_admins("[key_name_admin(user)] erased a Narsie rune with a null rod")
|
||||
log_game("Summon Narsie rune erased by [key_name(user)] using a null rod")
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] erased a Narsie rune with a null rod")
|
||||
..()
|
||||
|
||||
//Rite of Resurrection: Requires a dead or inactive cultist. When reviving the dead, you can only perform one revival for every sacrifice your cult has carried out.
|
||||
@@ -804,7 +804,7 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
construct_invoke = FALSE
|
||||
color = RUNE_COLOR_DARKRED
|
||||
var/mob/living/affecting = null
|
||||
var/ghost_limit = 4
|
||||
var/ghost_limit = 3
|
||||
var/ghosts = 0
|
||||
|
||||
/obj/effect/rune/manifest/Initialize()
|
||||
@@ -834,10 +834,15 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
if(A.map_name == "Space" || is_mining_level(T.z))
|
||||
to_chat(user, "<span class='cultitalic'><b>The veil is not weak enough here to manifest spirits, you must be on station!</b></span>")
|
||||
return
|
||||
if(ghosts >= ghost_limit)
|
||||
to_chat(user, "<span class='cultitalic'>You are sustaining too many ghosts to summon more!</span>")
|
||||
fail_invoke()
|
||||
log_game("Manifest rune failed - too many summoned ghosts")
|
||||
return list()
|
||||
notify_ghosts("Manifest rune invoked in [get_area(src)].", 'sound/effects/ghost2.ogg', source = src)
|
||||
var/list/ghosts_on_rune = list()
|
||||
for(var/mob/dead/observer/O in T)
|
||||
if(O.client && !jobban_isbanned(O, ROLE_CULTIST))
|
||||
if(O.client && !jobban_isbanned(O, ROLE_CULTIST) && !QDELETED(src) && !QDELETED(O))
|
||||
ghosts_on_rune += O
|
||||
if(!ghosts_on_rune.len)
|
||||
to_chat(user, "<span class='cultitalic'>There are no spirits near [src]!</span>")
|
||||
@@ -852,11 +857,6 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
new_human.apply_status_effect(STATUS_EFFECT_SUMMONEDGHOST) //ghosts can't summon more ghosts
|
||||
new_human.see_invisible = SEE_INVISIBLE_OBSERVER
|
||||
ghosts++
|
||||
if(ghosts >= ghost_limit)
|
||||
to_chat(user, "<span class='cultitalic'>You are sustaining too many ghosts to summon more!</span>")
|
||||
fail_invoke()
|
||||
log_game("Manifest rune failed - too many summoned ghosts")
|
||||
return list()
|
||||
playsound(src, 'sound/magic/exit_blood.ogg', 50, 1)
|
||||
visible_message("<span class='warning'>A cloud of red mist forms above [src], and from within steps... a [new_human.gender == FEMALE ? "wo":""]man.</span>")
|
||||
to_chat(user, "<span class='cultitalic'>Your blood begins flowing into [src]. You must remain in place and conscious to maintain the forms of those summoned. This will hurt you slowly but surely...</span>")
|
||||
|
||||
@@ -387,7 +387,7 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
|
||||
return H.reagents.has_reagent("holy water")
|
||||
return 0
|
||||
if(BANISH_COFFIN)
|
||||
return (body && istype(body.loc, /obj/structure/closet/coffin))
|
||||
return (body && istype(body.loc, /obj/structure/closet/crate/coffin))
|
||||
if(BANISH_FORMALDYHIDE)
|
||||
if(iscarbon(body))
|
||||
var/mob/living/carbon/H = body
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
var/boost = 0
|
||||
bloodcrawl = BLOODCRAWL_EAT
|
||||
var/list/consumed_mobs = list()
|
||||
var/playstyle_string = "<span class='big bold'>You are an imp,</span><B> a mischevious creature from hell. You are the lowest rank on the hellish totem pole \
|
||||
var/playstyle_string = "<span class='big bold'>You are an imp,</span><B> a mischievous creature from hell. You are the lowest rank on the hellish totem pole \
|
||||
Though you are not obligated to help, perhaps by aiding a higher ranking devil, you might just get a promotion. However, you are incapable \
|
||||
of intentionally harming a fellow devil.</B>"
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
|
||||
//Left hand items
|
||||
for(var/obj/item/I in held_items)
|
||||
if(!(I.flags_1 & ABSTRACT_1))
|
||||
if(!(I.item_flags & ABSTRACT))
|
||||
msg += "It is holding [I.get_examine_string(user)] in its [get_held_index_name(get_held_index_of_item(I))].\n"
|
||||
|
||||
//Braindead
|
||||
|
||||
@@ -54,7 +54,7 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
stage_speed += initial(S.stage_speed)
|
||||
transmittable += initial(S.transmittable)
|
||||
threshold_block += "<br><br>[initial(S.threshold_desc)]"
|
||||
stat_block = "Resistance: [resistance]<br>Stealth: [stealth]<br>Stage Speed: [stage_speed]<br>Transmittability: [transmittable]<br><br>"
|
||||
stat_block = "Resistance: [resistance]<br>Stealth: [stealth]<br>Stage Speed: [stage_speed]<br>Transmissibility: [transmittable]<br><br>"
|
||||
|
||||
/datum/disease_ability/proc/CanBuy(mob/camera/disease/D)
|
||||
if(world.time < D.next_adaptation_time)
|
||||
@@ -130,14 +130,14 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
required_total_points = 0
|
||||
start_with = TRUE
|
||||
short_desc = "Force the host you are following to cough, spreading your infection to those nearby."
|
||||
long_desc = "Force the host you are following to cough with extra force, spreading your infection to those within two meters of your host even if your transmitability is low.<br>Cooldown: 10 seconds"
|
||||
long_desc = "Force the host you are following to cough with extra force, spreading your infection to those within two meters of your host even if your transmissibility is low.<br>Cooldown: 10 seconds"
|
||||
|
||||
|
||||
/datum/action/cooldown/disease_cough
|
||||
name = "Cough"
|
||||
icon_icon = 'icons/mob/actions/actions_minor_antag.dmi'
|
||||
button_icon_state = "cough"
|
||||
desc = "Force the host you are following to cough with extra force, spreading your infection to those within two meters of your host even if your transmitability is low.<br>Cooldown: 10 seconds"
|
||||
desc = "Force the host you are following to cough with extra force, spreading your infection to those within two meters of your host even if your transmissibility is low.<br>Cooldown: 10 seconds"
|
||||
cooldown_time = 100
|
||||
|
||||
/datum/action/cooldown/disease_cough/Trigger()
|
||||
@@ -148,7 +148,7 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
if(!L)
|
||||
return FALSE
|
||||
if(L.stat != CONSCIOUS)
|
||||
to_chat(D, "<span class='warning'>Your host must be concious to cough.</span>")
|
||||
to_chat(D, "<span class='warning'>Your host must be conscious to cough.</span>")
|
||||
return FALSE
|
||||
to_chat(D, "<span class='notice'>You force [L.real_name] to cough.</span>")
|
||||
L.emote("cough")
|
||||
@@ -170,7 +170,7 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
name = "Sneeze"
|
||||
icon_icon = 'icons/mob/actions/actions_minor_antag.dmi'
|
||||
button_icon_state = "sneeze"
|
||||
desc = "Force the host you are following to sneeze with extra force, spreading your infection to any victims in a 4 meter cone in front of your host even if your transmitability is low.<br>Cooldown: 20 seconds"
|
||||
desc = "Force the host you are following to sneeze with extra force, spreading your infection to any victims in a 4 meter cone in front of your host even if your transmissibility is low.<br>Cooldown: 20 seconds"
|
||||
cooldown_time = 200
|
||||
|
||||
/datum/action/cooldown/disease_sneeze/Trigger()
|
||||
@@ -181,7 +181,7 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
if(!L)
|
||||
return FALSE
|
||||
if(L.stat != CONSCIOUS)
|
||||
to_chat(D, "<span class='warning'>Your host must be concious to sneeze.</span>")
|
||||
to_chat(D, "<span class='warning'>Your host must be conscious to sneeze.</span>")
|
||||
return FALSE
|
||||
to_chat(D, "<span class='notice'>You force [L.real_name] to sneeze.</span>")
|
||||
L.emote("sneeze")
|
||||
@@ -243,7 +243,7 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
cost = 2
|
||||
required_total_points = 4
|
||||
short_desc = "Cause victims to cough intermittently."
|
||||
long_desc = "Cause victims to cough intermittently, spreading your infection if your transmitability is high."
|
||||
long_desc = "Cause victims to cough intermittently, spreading your infection if your transmissibility is high."
|
||||
|
||||
/datum/disease_ability/symptom/sneeze
|
||||
name = "Involuntary Sneezing"
|
||||
@@ -251,7 +251,7 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
cost = 2
|
||||
required_total_points = 4
|
||||
short_desc = "Cause victims to sneeze intermittently."
|
||||
long_desc = "Cause victims to sneeze intermittently, spreading your infection and also increasing transmitability and resistance, at the cost of stealth."
|
||||
long_desc = "Cause victims to sneeze intermittently, spreading your infection and also increasing transmissibility and resistance, at the cost of stealth."
|
||||
|
||||
/datum/disease_ability/symptom/beard
|
||||
//I don't think I need to justify the fact that this is the best symptom
|
||||
@@ -277,7 +277,7 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
cost = 4
|
||||
required_total_points = 8
|
||||
short_desc = "Cause victims to choke."
|
||||
long_desc = "Cause victims to choke, threatening asphyxiation. Decreases stats, especially transmittability."
|
||||
long_desc = "Cause victims to choke, threatening asphyxiation. Decreases stats, especially transmissibility."
|
||||
|
||||
|
||||
/datum/disease_ability/symptom/confusion
|
||||
@@ -295,7 +295,7 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
cost = 4
|
||||
required_total_points = 8
|
||||
short_desc = "Cause victims to become eternally young."
|
||||
long_desc = "Cause victims to become eternally young. Provides boosts to all stats except transmittability."
|
||||
long_desc = "Cause victims to become eternally young. Provides boosts to all stats except transmissibility."
|
||||
|
||||
|
||||
/datum/disease_ability/symptom/vomit
|
||||
@@ -304,7 +304,7 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
cost = 4
|
||||
required_total_points = 8
|
||||
short_desc = "Cause victims to vomit."
|
||||
long_desc = "Cause victims to vomit. Slightly increases transmittability. Vomiting also also causes the victims to lose nutrition and removes some toxin damage."
|
||||
long_desc = "Cause victims to vomit. Slightly increases transmissibility. Vomiting also also causes the victims to lose nutrition and removes some toxin damage."
|
||||
|
||||
|
||||
/datum/disease_ability/symptom/voice_change
|
||||
@@ -367,7 +367,7 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
cost = 4
|
||||
required_total_points = 8
|
||||
short_desc = "Cause victims to lose weight."
|
||||
long_desc = "Cause victims to lose weight, and make it almost immpossible for them to gain nutrition from food. Reduced nutrition allows your infection to spread more easily from hosts, especially by sneezing."
|
||||
long_desc = "Cause victims to lose weight, and make it almost impossible for them to gain nutrition from food. Reduced nutrition allows your infection to spread more easily from hosts, especially by sneezing."
|
||||
|
||||
|
||||
/datum/disease_ability/symptom/metabolism_heal
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
var/mob/camera/disease/virus = new /mob/camera/disease(SSmapping.get_station_center())
|
||||
virus.key = selected.key
|
||||
INVOKE_ASYNC(virus, /mob/camera/disease/proc/pick_name)
|
||||
message_admins("[key_name_admin(virus)] has been made into a sentient disease by an event.")
|
||||
message_admins("[ADMIN_LOOKUPFLW(virus)] has been made into a sentient disease by an event.")
|
||||
log_game("[key_name(virus)] was spawned as a sentient disease by an event.")
|
||||
spawned_mobs += virus
|
||||
return SUCCESSFUL_SPAWN
|
||||
|
||||
@@ -81,7 +81,7 @@ the new instance inside the host to be updated to the template's stats.
|
||||
/mob/camera/disease/Login()
|
||||
..()
|
||||
if(freemove)
|
||||
to_chat(src, "<span class='warning'>You have [round((freemove_end - world.time)/10)] seconds to select your first host. Click on a human to select your host.</span>")
|
||||
to_chat(src, "<span class='warning'>You have [DisplayTimeText(freemove_end - world.time)] to select your first host. Click on a human to select your host.</span>")
|
||||
|
||||
|
||||
/mob/camera/disease/Stat()
|
||||
@@ -285,7 +285,7 @@ the new instance inside the host to be updated to the template's stats.
|
||||
..()
|
||||
|
||||
/mob/camera/disease/proc/adapt_cooldown()
|
||||
to_chat(src, "<span class='notice'>You have altered your genetic structure. You will be unable to adapt again for [adaptation_cooldown/10] seconds.</span>")
|
||||
to_chat(src, "<span class='notice'>You have altered your genetic structure. You will be unable to adapt again for [DisplayTimeText(adaptation_cooldown)].</span>")
|
||||
next_adaptation_time = world.time + adaptation_cooldown
|
||||
addtimer(CALLBACK(src, .proc/notify_adapt_ready), adaptation_cooldown)
|
||||
|
||||
@@ -310,7 +310,7 @@ the new instance inside the host to be updated to the template's stats.
|
||||
Resistance: [DT.totalResistance()]<br>\
|
||||
Stealth: [DT.totalStealth()]<br>\
|
||||
Stage Speed: [DT.totalStageSpeed()]<br>\
|
||||
Transmittability: [DT.totalTransmittable()]<hr>\
|
||||
Transmissibility: [DT.totalTransmittable()]<hr>\
|
||||
Cure: [DT.cure_text]"
|
||||
dat += "<hr><h1>Adaptations</h1>\
|
||||
Points: [points] / [total_points]\
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
if(!istype(H))
|
||||
return
|
||||
|
||||
for(var/obj/item/I in H.get_equipped_items())
|
||||
for(var/obj/item/I in H.get_equipped_items(TRUE))
|
||||
qdel(I)
|
||||
for(var/obj/item/I in H.held_items)
|
||||
qdel(I)
|
||||
@@ -59,13 +59,13 @@
|
||||
W.access += get_all_centcom_access()
|
||||
W.assignment = "Highlander"
|
||||
W.registered_name = H.real_name
|
||||
W.flags_1 |= NODROP_1
|
||||
W.item_flags |= NODROP
|
||||
W.update_label(H.real_name)
|
||||
H.equip_to_slot_or_del(W, SLOT_WEAR_ID)
|
||||
|
||||
sword = new(H)
|
||||
if(!GLOB.highlander)
|
||||
sword.admin_spawned = TRUE //To prevent announcing
|
||||
sword.flags_1 |= ADMIN_SPAWNED_1 //To prevent announcing
|
||||
sword.pickup(H) //For the stun shielding
|
||||
H.put_in_hands(sword)
|
||||
|
||||
|
||||
@@ -238,7 +238,7 @@
|
||||
player_mind.add_antag_datum(/datum/antagonist/morph)
|
||||
to_chat(S, S.playstyle_string)
|
||||
SEND_SOUND(S, sound('sound/magic/mutate.ogg'))
|
||||
message_admins("[key_name_admin(S)] has been made into a morph by an event.")
|
||||
message_admins("[ADMIN_LOOKUPFLW(S)] has been made into a morph by an event.")
|
||||
log_game("[key_name(S)] was spawned as a morph by an event.")
|
||||
spawned_mobs += S
|
||||
return SUCCESSFUL_SPAWN
|
||||
|
||||
@@ -7,6 +7,7 @@ GLOBAL_LIST_EMPTY(jam_on_wardec)
|
||||
|
||||
/obj/item/nuclear_challenge
|
||||
name = "Declaration of War (Challenge Mode)"
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "gangtool-red"
|
||||
item_state = "radio"
|
||||
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
|
||||
@@ -15,7 +16,7 @@ GLOBAL_LIST_EMPTY(jam_on_wardec)
|
||||
Such a brazen move will attract the attention of powerful benefactors within the Syndicate, who will supply your team with a massive amount of bonus telecrystals. \
|
||||
Must be used within five minutes, or your benefactors will lose interest."
|
||||
var/declaring_war = FALSE
|
||||
var/uplink_type = /obj/item/radio/uplink/nuclear
|
||||
var/uplink_type = /obj/item/uplink/nuclear
|
||||
|
||||
/obj/item/nuclear_challenge/attack_self(mob/living/user)
|
||||
if(!check_allowed(user))
|
||||
@@ -87,7 +88,7 @@ GLOBAL_LIST_EMPTY(jam_on_wardec)
|
||||
return TRUE
|
||||
|
||||
/obj/item/nuclear_challenge/clownops
|
||||
uplink_type = /obj/item/radio/uplink/clownop
|
||||
uplink_type = /obj/item/uplink/clownop
|
||||
|
||||
#undef CHALLENGE_TELECRYSTALS
|
||||
#undef CHALLENGE_TIME_LIMIT
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
desc = "You probably shouldn't stick around to see if this is armed."
|
||||
icon = 'icons/obj/machines/nuke.dmi'
|
||||
icon_state = "nuclearbomb_base"
|
||||
anchored = FALSE
|
||||
density = TRUE
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
|
||||
@@ -15,6 +16,7 @@
|
||||
var/numeric_input = ""
|
||||
var/timing = FALSE
|
||||
var/exploding = FALSE
|
||||
var/exploded = FALSE
|
||||
var/detonation_timer = null
|
||||
var/r_code = "ADMIN"
|
||||
var/yes_code = FALSE
|
||||
@@ -254,7 +256,7 @@
|
||||
first_status = "Set"
|
||||
else
|
||||
first_status = "Auth S1."
|
||||
var/second_status = safety ? "Safe" : "Engaged"
|
||||
var/second_status = exploded ? "Warhead triggered, thanks for flying Nanotrasen" : (safety ? "Safe" : "Engaged")
|
||||
data["status1"] = first_status
|
||||
data["status2"] = second_status
|
||||
data["anchored"] = anchored
|
||||
@@ -331,13 +333,13 @@
|
||||
timer_set = CLAMP(N,minimum_timer_set,maximum_timer_set)
|
||||
. = TRUE
|
||||
if("safety")
|
||||
if(auth && yes_code)
|
||||
if(auth && yes_code && !exploded)
|
||||
set_safety()
|
||||
if("anchor")
|
||||
if(auth && yes_code)
|
||||
set_anchor()
|
||||
if("toggle_timer")
|
||||
if(auth && yes_code && !safety)
|
||||
if(auth && yes_code && !safety && !exploded)
|
||||
set_active()
|
||||
|
||||
|
||||
@@ -369,11 +371,11 @@
|
||||
if(timing)
|
||||
previous_level = get_security_level()
|
||||
bomb_set = TRUE
|
||||
set_security_level("delta")
|
||||
detonation_timer = world.time + (timer_set * 10)
|
||||
for(var/obj/item/pinpointer/nuke/syndicate/S in GLOB.pinpointer_list)
|
||||
S.switch_mode_to(TRACK_INFILTRATOR)
|
||||
countdown.start()
|
||||
set_security_level("delta")
|
||||
else
|
||||
bomb_set = FALSE
|
||||
detonation_timer = null
|
||||
@@ -395,9 +397,9 @@
|
||||
return
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/nuclearbomb/tesla_act(power, explosive)
|
||||
/obj/machinery/nuclearbomb/tesla_act(power, tesla_flags)
|
||||
..()
|
||||
if(explosive)
|
||||
if(tesla_flags & TESLA_MACHINE_EXPLOSIVE)
|
||||
qdel(src)//like the singulo, tesla deletes it. stops it from exploding over and over
|
||||
|
||||
#define NUKERANGE 127
|
||||
@@ -455,6 +457,71 @@
|
||||
else
|
||||
return CINEMATIC_SELFDESTRUCT_MISS
|
||||
|
||||
/obj/machinery/nuclearbomb/beer
|
||||
name = "Nanotrasen-brand nuclear fission explosive"
|
||||
desc = "One of the more successful achievements of the Nanotrasen Corporate Warfare Division, their nuclear fission explosives are renowned for being cheap to produce and devastatingly effective. Signs explain that though this particular device has been decommissioned, every Nanotrasen station is equipped with an equivalent one, just in case. All Captains carefully guard the disk needed to detonate them - at least, the sign says they do. There seems to be a tap on the back."
|
||||
var/obj/structure/reagent_dispensers/beerkeg/keg
|
||||
|
||||
/obj/machinery/nuclearbomb/beer/Initialize()
|
||||
. = ..()
|
||||
keg = new(src)
|
||||
QDEL_NULL(core)
|
||||
|
||||
/obj/machinery/nuclearbomb/beer/examine(mob/user)
|
||||
. = ..()
|
||||
if(keg.reagents.total_volume)
|
||||
to_chat(user, "<span class='notice'>It has [keg.reagents.total_volume] unit\s left.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='danger'>It's empty.</span>")
|
||||
|
||||
/obj/machinery/nuclearbomb/beer/attackby(obj/item/W, mob/user, params)
|
||||
if(W.is_refillable())
|
||||
W.afterattack(keg, user, TRUE) // redirect refillable containers to the keg, allowing them to be filled
|
||||
return TRUE // pretend we handled the attack, too.
|
||||
if(istype(W, /obj/item/nuke_core_container))
|
||||
to_chat(user, "<span class='notice'>[src] has had its plutonium core removed as a part of being decommissioned.</span>")
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/nuclearbomb/beer/actually_explode()
|
||||
var/turf/bomb_location = get_turf(src)
|
||||
if(!bomb_location)
|
||||
disarm()
|
||||
return
|
||||
if(is_station_level(bomb_location.z))
|
||||
var/datum/round_event_control/E = locate(/datum/round_event_control/vent_clog/beer) in SSevents.control
|
||||
if(E)
|
||||
E.runEvent()
|
||||
addtimer(CALLBACK(src, .proc/really_actually_explode), 110)
|
||||
else
|
||||
visible_message("<span class='notice'>[src] fizzes ominously.</span>")
|
||||
addtimer(CALLBACK(src, .proc/fizzbuzz), 110)
|
||||
|
||||
/obj/machinery/nuclearbomb/beer/proc/disarm()
|
||||
bomb_set = FALSE
|
||||
detonation_timer = null
|
||||
exploding = FALSE
|
||||
exploded = TRUE
|
||||
set_security_level(previous_level)
|
||||
for(var/obj/item/pinpointer/nuke/syndicate/S in GLOB.pinpointer_list)
|
||||
S.switch_mode_to(initial(S.mode))
|
||||
S.alert = FALSE
|
||||
countdown.stop()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/nuclearbomb/beer/proc/fizzbuzz()
|
||||
var/datum/reagents/R = new/datum/reagents(1000)
|
||||
R.my_atom = src
|
||||
R.add_reagent("beer", 100)
|
||||
|
||||
var/datum/effect_system/foam_spread/foam = new
|
||||
foam.set_up(200, get_turf(src), R)
|
||||
foam.start()
|
||||
disarm()
|
||||
|
||||
/obj/machinery/nuclearbomb/beer/really_actually_explode()
|
||||
disarm()
|
||||
|
||||
/proc/KillEveryoneOnZLevel(z)
|
||||
if(!z)
|
||||
return
|
||||
@@ -521,7 +588,7 @@ This is here to make the tiles around the station mininuke change when it's arme
|
||||
CRASH("A fake nuke disk tried to call process(). Who the fuck and how the fuck")
|
||||
var/turf/newturf = get_turf(src)
|
||||
if(newturf && lastlocation == newturf)
|
||||
if(last_disk_move < world.time - 5000 && prob((world.time - 5000 - last_disk_move)*0.00001))
|
||||
if(last_disk_move < world.time - 5000 && prob((world.time - 5000 - last_disk_move)*0.0001))
|
||||
var/datum/round_event_control/operative/loneop = locate(/datum/round_event_control/operative) in SSevents.control
|
||||
if(istype(loneop))
|
||||
loneop.weight += 1
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
/obj/item/pinpointer/nuke/proc/switch_mode_to(new_mode)
|
||||
if(isliving(loc))
|
||||
var/mob/living/L = loc
|
||||
to_chat(L, "<span class='userdanger'>Your [name] beeps as it reconfigures its tracking algorithms.</span>")
|
||||
to_chat(L, "<span class='userdanger'>Your [name] beeps as it reconfigures it's tracking algorithms.</span>")
|
||||
playsound(L, 'sound/machines/triple_beep.ogg', 50, 1)
|
||||
mode = new_mode
|
||||
scan_for_target()
|
||||
@@ -65,7 +65,8 @@
|
||||
/obj/item/pinpointer/syndicate_cyborg // Cyborg pinpointers just look for a random operative.
|
||||
name = "cyborg syndicate pinpointer"
|
||||
desc = "An integrated tracking device, jury-rigged to search for living Syndicate operatives."
|
||||
flags_1 = NODROP_1
|
||||
item_flags = NODROP
|
||||
flags_1 = NONE
|
||||
|
||||
/obj/item/pinpointer/syndicate_cyborg/scan_for_target()
|
||||
target = null
|
||||
@@ -79,4 +80,3 @@
|
||||
if(closest_operative)
|
||||
target = closest_operative
|
||||
..()
|
||||
|
||||
|
||||
@@ -65,6 +65,8 @@
|
||||
nuke.r_code = nuke_team.memorized_code
|
||||
else //Already set by admins/something else?
|
||||
nuke_team.memorized_code = nuke.r_code
|
||||
for(var/obj/machinery/nuclearbomb/beer/beernuke in GLOB.nuke_list)
|
||||
beernuke.r_code = nuke_team.memorized_code
|
||||
else
|
||||
stack_trace("Syndicate nuke not found during nuke team creation.")
|
||||
nuke_team.memorized_code = null
|
||||
@@ -256,7 +258,8 @@
|
||||
|
||||
/datum/team/nuclear/proc/syndies_escaped()
|
||||
var/obj/docking_port/mobile/S = SSshuttle.getShuttle("syndicate")
|
||||
return S && (is_centcom_level(S.z) || is_transit_level(S.z))
|
||||
var/obj/docking_port/stationary/transit/T = locate() in S.loc
|
||||
return S && (is_centcom_level(S.z) || T)
|
||||
|
||||
/datum/team/nuclear/proc/get_result()
|
||||
var/evacuation = SSshuttle.emergency.mode == SHUTTLE_ENDGAME
|
||||
@@ -275,7 +278,7 @@
|
||||
return NUKE_RESULT_WRONG_STATION
|
||||
else if (!disk_rescued && !station_was_nuked && nuke_off_station && syndies_didnt_escape)
|
||||
return NUKE_RESULT_WRONG_STATION_DEAD
|
||||
else if ((disk_rescued || evacuation) && operatives_dead())
|
||||
else if ((disk_rescued && evacuation) && operatives_dead())
|
||||
return NUKE_RESULT_CREW_WIN_SYNDIES_DEAD
|
||||
else if (disk_rescued)
|
||||
return NUKE_RESULT_CREW_WIN
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
else if (!mission)
|
||||
var/datum/objective/missionobj = new
|
||||
missionobj.owner = owner
|
||||
missionobj.explanation_text = "Conduct a routine preformance review of [station_name()] and its Captain."
|
||||
missionobj.explanation_text = "Conduct a routine performance review of [station_name()] and its Captain."
|
||||
missionobj.completed = 1
|
||||
mission = missionobj
|
||||
objectives |= mission
|
||||
|
||||
@@ -109,11 +109,6 @@
|
||||
revealed = FALSE
|
||||
incorporeal_move = INCORPOREAL_MOVE_JAUNT
|
||||
invisibility = INVISIBILITY_REVENANT
|
||||
if(staticOverlays.len)
|
||||
for(var/mob/living/simple_animal/drone/D in GLOB.drones_list)
|
||||
if(D && D.client && D.seeStatic)
|
||||
D.staticOverlays.Remove(staticOverlays)
|
||||
D.client.images.Remove(staticOverlays)
|
||||
to_chat(src, "<span class='revenboldnotice'>You are once more concealed.</span>")
|
||||
if(unstun_time && world.time >= unstun_time)
|
||||
unstun_time = 0
|
||||
@@ -250,15 +245,6 @@
|
||||
else
|
||||
to_chat(src, "<span class='revenwarning'>You have been revealed!</span>")
|
||||
unreveal_time = unreveal_time + time
|
||||
if(staticOverlays.len)
|
||||
for(var/mob/living/simple_animal/drone/D in GLOB.drones_list)
|
||||
if(D && D.client && D.seeStatic)
|
||||
if(D.staticChoice in staticOverlays)
|
||||
D.staticOverlays |= staticOverlays[D.staticChoice]
|
||||
D.client.images |= staticOverlays[D.staticChoice]
|
||||
else
|
||||
D.staticOverlays |= staticOverlays["static"]
|
||||
D.client.images |= staticOverlays["static"]
|
||||
update_spooky_icon()
|
||||
|
||||
/mob/living/simple_animal/revenant/proc/stun(time)
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
|
||||
var/mob/living/simple_animal/revenant/revvie = new(pick(spawn_locs))
|
||||
revvie.key = selected.key
|
||||
message_admins("[key_name_admin(revvie)] [ADMIN_FLW(revvie)] has been made into a revenant by an event.")
|
||||
message_admins("[ADMIN_LOOKUPFLW(revvie)] has been made into a revenant by an event.")
|
||||
log_game("[key_name(revvie)] was spawned as a revenant by an event.")
|
||||
spawned_mobs += revvie
|
||||
return SUCCESSFUL_SPAWN
|
||||
|
||||
@@ -201,7 +201,7 @@
|
||||
|
||||
/datum/antagonist/rev/farewell()
|
||||
if(ishuman(owner.current))
|
||||
owner.current.visible_message("<span class='deconversion_message'>[owner.current] looks like [owner.p_theyve()] just remembered [owner.p_their()] real allegiance!</span>", null, null, null, owner.current)
|
||||
owner.current.visible_message("<span class='deconversion_message'>[owner.current] looks like [owner.current.p_theyve()] just remembered [owner.current.p_their()] real allegiance!</span>", null, null, null, owner.current)
|
||||
to_chat(owner, "<span class='userdanger'>You are no longer a brainwashed revolutionary! Your memory is hazy from the time you were a rebel...the only thing you remember is the name of the one who brainwashed you...</span>")
|
||||
else if(issilicon(owner.current))
|
||||
owner.current.visible_message("<span class='deconversion_message'>The frame beeps contentedly, purging the hostile memory engram from the MMI before initalizing it.</span>", null, null, null, owner.current)
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
to_chat(S, S.playstyle_string)
|
||||
to_chat(S, "<B>You are currently not currently in the same plane of existence as the station. Blood Crawl near a blood pool to manifest.</B>")
|
||||
SEND_SOUND(S, 'sound/magic/demon_dies.ogg')
|
||||
message_admins("[key_name_admin(S)] has been made into a slaughter demon by an event.")
|
||||
message_admins("[ADMIN_LOOKUPFLW(S)] has been made into a slaughter demon by an event.")
|
||||
log_game("[key_name(S)] was spawned as a slaughter demon by an event.")
|
||||
spawned_mobs += S
|
||||
return SUCCESSFUL_SPAWN
|
||||
|
||||
@@ -128,6 +128,9 @@
|
||||
return ..() | SPAN_ROBOT
|
||||
|
||||
/mob/living/simple_animal/hostile/swarmer/emp_act()
|
||||
. = ..()
|
||||
if(. & EMP_PROTECT_SELF)
|
||||
return
|
||||
if(health > 1)
|
||||
adjustHealth(health-1)
|
||||
else
|
||||
@@ -370,6 +373,10 @@
|
||||
to_chat(S, "<span class='warning'>Attempting to dismantle this machine would result in an immediate counterattack. Aborting.</span>")
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/porta_turret_cover/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
|
||||
to_chat(S, "<span class='warning'>Attempting to dismantle this machine would result in an immediate counterattack. Aborting.</span>")
|
||||
return FALSE
|
||||
|
||||
/mob/living/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
|
||||
S.DisperseTarget(src)
|
||||
return TRUE
|
||||
@@ -402,6 +409,10 @@
|
||||
to_chat(S, "<span class='warning'>This object does not contain enough materials to work with.</span>")
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/field/generator/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
|
||||
to_chat(S, "<span class='warning'>Destroying this object would cause a catastrophic chain reaction. Aborting.</span>")
|
||||
return FALSE
|
||||
|
||||
////END CTRL CLICK FOR SWARMERS////
|
||||
|
||||
/mob/living/simple_animal/hostile/swarmer/proc/Fabricate(atom/fabrication_object,fabrication_cost = 0)
|
||||
@@ -554,6 +565,9 @@
|
||||
playsound(src, 'sound/items/welder.ogg', 100, 1)
|
||||
|
||||
/obj/structure/swarmer/emp_act()
|
||||
. = ..()
|
||||
if(. & EMP_PROTECT_SELF)
|
||||
return
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/swarmer/trap
|
||||
|
||||
@@ -5,12 +5,6 @@
|
||||
#define TRAITOR_AGENT_ROLE "Syndicate External Affairs Agent"
|
||||
|
||||
/datum/antagonist/traitor/internal_affairs
|
||||
name = "Internal Affairs Agent"
|
||||
human_datum = /datum/antagonist/traitor/human/internal_affairs
|
||||
ai_datum = /datum/antagonist/traitor/AI/internal_affairs
|
||||
antagpanel_category = "IAA"
|
||||
|
||||
/datum/antagonist/traitor/AI/internal_affairs
|
||||
name = "Internal Affairs Agent"
|
||||
employer = "Nanotrasen"
|
||||
special_role = "internal affairs agent"
|
||||
@@ -20,47 +14,29 @@
|
||||
var/list/datum/mind/targets_stolen
|
||||
|
||||
|
||||
/datum/antagonist/traitor/human/internal_affairs
|
||||
name = "Internal Affairs Agent"
|
||||
employer = "Nanotrasen"
|
||||
special_role = "internal affairs agent"
|
||||
antagpanel_category = "IAA"
|
||||
var/syndicate = FALSE
|
||||
var/last_man_standing = FALSE
|
||||
var/list/datum/mind/targets_stolen
|
||||
|
||||
|
||||
/datum/antagonist/traitor/human/internal_affairs/proc/give_pinpointer()
|
||||
/datum/antagonist/traitor/internal_affairs/proc/give_pinpointer()
|
||||
if(owner && owner.current)
|
||||
owner.current.apply_status_effect(/datum/status_effect/agent_pinpointer)
|
||||
|
||||
/datum/antagonist/traitor/human/internal_affairs/apply_innate_effects()
|
||||
/datum/antagonist/traitor/internal_affairs/apply_innate_effects()
|
||||
.=..() //in case the base is used in future
|
||||
if(owner && owner.current)
|
||||
give_pinpointer(owner.current)
|
||||
|
||||
/datum/antagonist/traitor/human/internal_affairs/remove_innate_effects()
|
||||
/datum/antagonist/traitor/internal_affairs/remove_innate_effects()
|
||||
.=..()
|
||||
if(owner && owner.current)
|
||||
owner.current.remove_status_effect(/datum/status_effect/agent_pinpointer)
|
||||
|
||||
/datum/antagonist/traitor/human/internal_affairs/on_gain()
|
||||
/datum/antagonist/traitor/internal_affairs/on_gain()
|
||||
START_PROCESSING(SSprocessing, src)
|
||||
.=..()
|
||||
/datum/antagonist/traitor/human/internal_affairs/on_removal()
|
||||
/datum/antagonist/traitor/internal_affairs/on_removal()
|
||||
STOP_PROCESSING(SSprocessing,src)
|
||||
.=..()
|
||||
/datum/antagonist/traitor/human/internal_affairs/process()
|
||||
/datum/antagonist/traitor/internal_affairs/process()
|
||||
iaa_process()
|
||||
|
||||
/datum/antagonist/traitor/AI/internal_affairs/on_gain()
|
||||
START_PROCESSING(SSprocessing, src)
|
||||
.=..()
|
||||
/datum/antagonist/traitor/AI/internal_affairs/on_removal()
|
||||
STOP_PROCESSING(SSprocessing,src)
|
||||
.=..()
|
||||
/datum/antagonist/traitor/AI/internal_affairs/process()
|
||||
iaa_process()
|
||||
|
||||
/datum/status_effect/agent_pinpointer
|
||||
id = "agent_pinpointer"
|
||||
@@ -68,6 +44,7 @@
|
||||
tick_interval = PINPOINTER_PING_TIME
|
||||
alert_type = /obj/screen/alert/status_effect/agent_pinpointer
|
||||
var/minimum_range = PINPOINTER_MINIMUM_RANGE
|
||||
var/range_fuzz_factor = PINPOINTER_EXTRA_RANDOM_RANGE
|
||||
var/mob/scan_target = null
|
||||
|
||||
/obj/screen/alert/status_effect/agent_pinpointer
|
||||
@@ -85,7 +62,7 @@
|
||||
if(here.z != there.z)
|
||||
linked_alert.icon_state = "pinonnull"
|
||||
return
|
||||
if(get_dist_euclidian(here,there)<=minimum_range + rand(0, PINPOINTER_EXTRA_RANDOM_RANGE))
|
||||
if(get_dist_euclidian(here,there)<=minimum_range + rand(0, range_fuzz_factor))
|
||||
linked_alert.icon_state = "pinondirect"
|
||||
else
|
||||
linked_alert.setDir(get_dir(here, there))
|
||||
@@ -142,21 +119,14 @@
|
||||
continue
|
||||
remove_objective(objective_)
|
||||
|
||||
/datum/antagonist/traitor/human/internal_affairs/reinstate_escape_objective()
|
||||
/datum/antagonist/traitor/internal_affairs/reinstate_escape_objective()
|
||||
..()
|
||||
var/datum/objective/escape/escape_objective = new
|
||||
var/objtype = traitor_kind == TRAITOR_HUMAN ? /datum/objective/escape : /datum/objective/survive
|
||||
var/datum/objective/escape_objective = new objtype
|
||||
escape_objective.owner = owner
|
||||
add_objective(escape_objective)
|
||||
|
||||
/datum/antagonist/traitor/AI/internal_affairs/reinstate_escape_objective()
|
||||
..()
|
||||
var/datum/objective/survive/survive_objective = new
|
||||
survive_objective.owner = owner
|
||||
add_objective(survive_objective)
|
||||
|
||||
/datum/antagonist/traitor/proc/steal_targets(datum/mind/victim)
|
||||
var/datum/antagonist/traitor/human/internal_affairs/this = src //Should only use this if IAA
|
||||
|
||||
/datum/antagonist/traitor/internal_affairs/proc/steal_targets(datum/mind/victim)
|
||||
if(!owner.current||owner.current.stat==DEAD)
|
||||
return
|
||||
to_chat(owner.current, "<span class='userdanger'> Target eliminated: [victim.name]</span>")
|
||||
@@ -165,13 +135,13 @@
|
||||
var/datum/objective/assassinate/internal/objective = objective_
|
||||
if(objective.target==owner)
|
||||
continue
|
||||
else if(this.targets_stolen.Find(objective.target) == 0)
|
||||
else if(targets_stolen.Find(objective.target) == 0)
|
||||
var/datum/objective/assassinate/internal/new_objective = new
|
||||
new_objective.owner = owner
|
||||
new_objective.target = objective.target
|
||||
new_objective.update_explanation_text()
|
||||
add_objective(new_objective)
|
||||
this.targets_stolen += objective.target
|
||||
targets_stolen += objective.target
|
||||
var/status_text = objective.check_completion() ? "neutralised" : "active"
|
||||
to_chat(owner.current, "<span class='userdanger'> New target added to database: [objective.target.name] ([status_text]) </span>")
|
||||
else if(istype(objective_, /datum/objective/destroy/internal))
|
||||
@@ -179,31 +149,30 @@
|
||||
var/datum/objective/destroy/internal/new_objective = new
|
||||
if(objective.target==owner)
|
||||
continue
|
||||
else if(this.targets_stolen.Find(objective.target) == 0)
|
||||
else if(targets_stolen.Find(objective.target) == 0)
|
||||
new_objective.owner = owner
|
||||
new_objective.target = objective.target
|
||||
new_objective.update_explanation_text()
|
||||
add_objective(new_objective)
|
||||
this.targets_stolen += objective.target
|
||||
targets_stolen += objective.target
|
||||
var/status_text = objective.check_completion() ? "neutralised" : "active"
|
||||
to_chat(owner.current, "<span class='userdanger'> New target added to database: [objective.target.name] ([status_text]) </span>")
|
||||
this.last_man_standing = TRUE
|
||||
last_man_standing = TRUE
|
||||
for(var/objective_ in owner.objectives)
|
||||
if(!is_internal_objective(objective_))
|
||||
continue
|
||||
var/datum/objective/assassinate/internal/objective = objective_
|
||||
if(!objective.check_completion())
|
||||
this.last_man_standing = FALSE
|
||||
last_man_standing = FALSE
|
||||
return
|
||||
if(this.last_man_standing)
|
||||
if(this.syndicate)
|
||||
if(last_man_standing)
|
||||
if(syndicate)
|
||||
to_chat(owner.current,"<span class='userdanger'> All the loyalist agents are dead, and no more is required of you. Die a glorious death, agent. </span>")
|
||||
else
|
||||
to_chat(owner.current,"<span class='userdanger'> All the other agents are dead, and you're the last loose end. Stage a Syndicate terrorist attack to cover up for today's events. You no longer have any limits on collateral damage.</span>")
|
||||
replace_escape_objective(owner)
|
||||
|
||||
/datum/antagonist/traitor/proc/iaa_process()
|
||||
var/datum/antagonist/traitor/human/internal_affairs/this = src //Should only use this if IAA
|
||||
/datum/antagonist/traitor/internal_affairs/proc/iaa_process()
|
||||
if(owner&&owner.current&&owner.current.stat!=DEAD)
|
||||
for(var/objective_ in owner.objectives)
|
||||
if(!is_internal_objective(objective_))
|
||||
@@ -220,20 +189,18 @@
|
||||
else
|
||||
if(objective.stolen)
|
||||
var/fail_msg = "<span class='userdanger'>Your sensors tell you that [objective.target.current.real_name], one of the targets you were meant to have killed, pulled one over on you, and is still alive - do the job properly this time! </span>"
|
||||
if(this.last_man_standing)
|
||||
if(this.syndicate)
|
||||
if(last_man_standing)
|
||||
if(syndicate)
|
||||
fail_msg += "<span class='userdanger'> You no longer have permission to die. </span>"
|
||||
else
|
||||
fail_msg += "<span class='userdanger'> The truth could still slip out!</font><B><font size=5 color=red> Cease any terrorist actions as soon as possible, unneeded property damage or loss of employee life will lead to your contract being terminated.</span>"
|
||||
reinstate_escape_objective(owner)
|
||||
this.last_man_standing = FALSE
|
||||
last_man_standing = FALSE
|
||||
to_chat(owner.current, fail_msg)
|
||||
objective.stolen = FALSE
|
||||
|
||||
/datum/antagonist/traitor/proc/forge_iaa_objectives()
|
||||
var/datum/antagonist/traitor/human/internal_affairs/this = src //Should only use this if IAA
|
||||
/datum/antagonist/traitor/internal_affairs/proc/forge_iaa_objectives()
|
||||
if(SSticker.mode.target_list.len && SSticker.mode.target_list[owner]) // Is a double agent
|
||||
|
||||
// Assassinate
|
||||
var/datum/mind/target_mind = SSticker.mode.target_list[owner]
|
||||
if(issilicon(target_mind.current))
|
||||
@@ -241,6 +208,7 @@
|
||||
destroy_objective.owner = owner
|
||||
destroy_objective.target = target_mind
|
||||
destroy_objective.update_explanation_text()
|
||||
add_objective(destroy_objective)
|
||||
else
|
||||
var/datum/objective/assassinate/internal/kill_objective = new
|
||||
kill_objective.owner = owner
|
||||
@@ -253,31 +221,25 @@
|
||||
employer = "The Syndicate"
|
||||
owner.special_role = TRAITOR_AGENT_ROLE
|
||||
special_role = TRAITOR_AGENT_ROLE
|
||||
this.syndicate = TRUE
|
||||
syndicate = TRUE
|
||||
forge_single_objective()
|
||||
|
||||
else
|
||||
..() // Give them standard objectives.
|
||||
return
|
||||
|
||||
/datum/antagonist/traitor/human/internal_affairs/forge_traitor_objectives()
|
||||
/datum/antagonist/traitor/internal_affairs/forge_traitor_objectives()
|
||||
forge_iaa_objectives()
|
||||
var/datum/objective/escape/escape_objective = new
|
||||
|
||||
var/objtype = traitor_kind == TRAITOR_HUMAN ? /datum/objective/escape : /datum/objective/survive
|
||||
var/datum/objective/escape_objective = new objtype
|
||||
escape_objective.owner = owner
|
||||
add_objective(escape_objective)
|
||||
|
||||
/datum/antagonist/traitor/AI/internal_affairs/forge_traitor_objectives()
|
||||
forge_iaa_objectives()
|
||||
var/datum/objective/survive/survive_objective = new
|
||||
survive_objective.owner = owner
|
||||
add_objective(survive_objective)
|
||||
|
||||
/datum/antagonist/traitor/proc/greet_iaa()
|
||||
var/datum/antagonist/traitor/human/internal_affairs/this = src //Should only use this if IAA
|
||||
var/crime = pick("distribution of contraband" , "unauthorized erotic action on duty", "embezzlement", "piloting under the influence", "dereliction of duty", "syndicate collaboration", "mutiny", "multiple homicides", "corporate espionage", "recieving bribes", "malpractice", "worship of prohbited life forms", "possession of profane texts", "murder", "arson", "insulting their manager", "grand theft", "conspiracy", "attempting to unionize", "vandalism", "gross incompetence")
|
||||
/datum/antagonist/traitor/internal_affairs/proc/greet_iaa()
|
||||
var/crime = pick("distribution of contraband" , "unauthorized erotic action on duty", "embezzlement", "piloting under the influence", "dereliction of duty", "syndicate collaboration", "mutiny", "multiple homicides", "corporate espionage", "receiving bribes", "malpractice", "worship of prohibited life forms", "possession of profane texts", "murder", "arson", "insulting their manager", "grand theft", "conspiracy", "attempting to unionize", "vandalism", "gross incompetence")
|
||||
|
||||
to_chat(owner.current, "<span class='userdanger'>You are the [special_role].</span>")
|
||||
if(this.syndicate)
|
||||
if(syndicate)
|
||||
to_chat(owner.current, "<span class='userdanger'>Your target has been framed for [crime], and you have been tasked with eliminating them to prevent them defending themselves in court.</span>")
|
||||
to_chat(owner.current, "<B><font size=5 color=red>Any damage you cause will be a further embarrassment to Nanotrasen, so you have no limits on collateral damage.</font></B>")
|
||||
to_chat(owner.current, "<span class='userdanger'> You have been provided with a standard uplink to accomplish your task. </span>")
|
||||
@@ -289,13 +251,9 @@
|
||||
to_chat(owner.current, "<span class='userdanger'>Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.</span>")
|
||||
owner.announce_objectives()
|
||||
|
||||
/datum/antagonist/traitor/AI/internal_affairs/greet()
|
||||
/datum/antagonist/traitor/internal_affairs/greet()
|
||||
greet_iaa()
|
||||
|
||||
/datum/antagonist/traitor/human/internal_affairs/greet()
|
||||
greet_iaa()
|
||||
|
||||
|
||||
#undef PROB_ACTUAL_TRAITOR
|
||||
#undef PINPOINTER_EXTRA_RANDOM_RANGE
|
||||
#undef PINPOINTER_MINIMUM_RANGE
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user