Merge branch 'master' of https://github.com/ParadiseSS13/Paradise into turfs

# Conflicts:
#	code/game/objects/items.dm
#	icons/turf/floors/plating.dmi
#	paradise.dme
This commit is contained in:
Mark van Alphen
2019-04-10 21:54:54 +02:00
126 changed files with 2050 additions and 2052 deletions
+1
View File
@@ -65442,6 +65442,7 @@
name = "\improper Virology Lobby"
})
"cnE" = (
/obj/machinery/atmospherics/unary/passive_vent,
/turf/simulated/floor/engine/insulated/vacuum,
/area/toxins/mixing)
"cnF" = (
-1
View File
@@ -11,7 +11,6 @@
#define GAMEMODE_IS_BLOB (ticker && istype(ticker.mode, /datum/game_mode/blob))
#define GAMEMODE_IS_CULT (ticker && istype(ticker.mode, /datum/game_mode/cult))
#define GAMEMODE_IS_HEIST (ticker && istype(ticker.mode, /datum/game_mode/heist))
#define GAMEMODE_IS_NATIONS (ticker && istype(ticker.mode, /datum/game_mode/nations))
#define GAMEMODE_IS_NUCLEAR (ticker && istype(ticker.mode, /datum/game_mode/nuclear))
#define GAMEMODE_IS_REVOLUTION (ticker && istype(ticker.mode, /datum/game_mode/revolution))
#define GAMEMODE_IS_WIZARD (ticker && istype(ticker.mode, /datum/game_mode/wizard))
+24 -27
View File
@@ -16,18 +16,17 @@
#define DIAG_MECH_HUD "11"// Mech health bar
#define STATUS_HUD_OOC "12"// STATUS_HUD without virus db check for someone being ill.
#define SPECIALROLE_HUD "13" //for antag huds. these are used at the /mob level
#define NATIONS_HUD "14" //Show nations icons during nations gamemode
#define DIAG_BOT_HUD "15"// Bot HUDS
#define PLANT_NUTRIENT_HUD "16"// Plant nutrient level
#define PLANT_WATER_HUD "17"// Plant water level
#define PLANT_STATUS_HUD "18"// Plant harvest/dead
#define PLANT_HEALTH_HUD "19"// Plant health
#define PLANT_TOXIN_HUD "20"// Toxin level
#define PLANT_PEST_HUD "21"// Pest level
#define PLANT_WEED_HUD "22"// Weed level
#define DIAG_TRACK_HUD "23"// Mech tracking beacon
#define DIAG_PATH_HUD "24"//Bot path indicators
#define GLAND_HUD "25"//Gland indicators for abductors
#define DIAG_BOT_HUD "14"// Bot HUDS
#define PLANT_NUTRIENT_HUD "15"// Plant nutrient level
#define PLANT_WATER_HUD "16"// Plant water level
#define PLANT_STATUS_HUD "17"// Plant harvest/dead
#define PLANT_HEALTH_HUD "18"// Plant health
#define PLANT_TOXIN_HUD "19"// Toxin level
#define PLANT_PEST_HUD "20"// Pest level
#define PLANT_WEED_HUD "21"// Weed level
#define DIAG_TRACK_HUD "22"// Mech tracking beacon
#define DIAG_PATH_HUD "23"//Bot path indicators
#define GLAND_HUD "24"//Gland indicators for abductors
//by default everything in the hud_list of an atom is an image
//a value in hud_list with one of these will change that behavior
@@ -42,22 +41,20 @@
#define DATA_HUD_DIAGNOSTIC 5
#define DATA_HUD_DIAGNOSTIC_ADVANCED 6
#define DATA_HUD_HYDROPONIC 7
//NATIONS
#define GAME_HUD_NATIONS 8
//antag HUD defines
#define ANTAG_HUD_CULT 9
#define ANTAG_HUD_REV 10
#define ANTAG_HUD_OPS 11
#define ANTAG_HUD_WIZ 12
#define ANTAG_HUD_SHADOW 13
#define ANTAG_HUD_TRAITOR 14
#define ANTAG_HUD_NINJA 15
#define ANTAG_HUD_CHANGELING 16
#define ANTAG_HUD_VAMPIRE 17
#define ANTAG_HUD_ABDUCTOR 18
#define DATA_HUD_ABDUCTOR 19
#define ANTAG_HUD_DEVIL 20
#define ANTAG_HUD_EVENTMISC 21
#define ANTAG_HUD_CULT 8
#define ANTAG_HUD_REV 9
#define ANTAG_HUD_OPS 10
#define ANTAG_HUD_WIZ 11
#define ANTAG_HUD_SHADOW 12
#define ANTAG_HUD_TRAITOR 13
#define ANTAG_HUD_NINJA 14
#define ANTAG_HUD_CHANGELING 15
#define ANTAG_HUD_VAMPIRE 16
#define ANTAG_HUD_ABDUCTOR 17
#define DATA_HUD_ABDUCTOR 18
#define ANTAG_HUD_DEVIL 19
#define ANTAG_HUD_EVENTMISC 20
// Notification action types
#define NOTIFY_JUMP "jump"
+3
View File
@@ -28,6 +28,9 @@
#define CHAT_NO_TICKETLOGS 65536
#define UI_DARKMODE 131072
#define DISABLE_KARMA 262144
#define CHAT_NO_MENTORTICKETLOGS 524288
#define TYPING_ONCE 1048576
#define TOGGLES_DEFAULT (CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_LOOC|MEMBER_PUBLIC|DONATOR_PUBLIC)
-1
View File
@@ -28,7 +28,6 @@
init_datum_subtypes(/datum/job, GLOB.joblist, list(/datum/job/ai, /datum/job/cyborg), "title")
init_datum_subtypes(/datum/superheroes, GLOB.all_superheroes, null, "name")
init_datum_subtypes(/datum/nations, GLOB.all_nations, null, "default_name")
init_datum_subtypes(/datum/language, GLOB.all_languages, null, "name")
for(var/language_name in GLOB.all_languages)
+9
View File
@@ -109,6 +109,15 @@
else
return trim(html_encode(name), max_length) //trim is "outside" because html_encode can expand single symbols into multiple symbols (such as turning < into &lt;)
// Uses client.typing to check if the popup should appear or not
/proc/typing_input(mob/user, message = "", title = "", default = "")
if(user.client.checkTyping()) // Prevent double windows
return null
user.client.typing = TRUE
var/msg = input(user, message, title, default) as text|null
user.client.typing = FALSE
return msg
//Filters out undesirable characters from names
/proc/reject_bad_name(var/t_in, var/allow_numbers=0, var/max_length=MAX_NAME_LEN)
if(!t_in || length(t_in) > max_length)
-1
View File
@@ -3,7 +3,6 @@ GLOBAL_LIST_EMPTY(all_species)
GLOBAL_LIST_EMPTY(all_languages)
GLOBAL_LIST_EMPTY(language_keys) // Table of say codes for all languages
GLOBAL_LIST_EMPTY(all_superheroes)
GLOBAL_LIST_EMPTY(all_nations)
GLOBAL_LIST_INIT(whitelisted_species, list())
GLOBAL_LIST_INIT(clients, list()) //list of all clients
+40 -16
View File
@@ -43,26 +43,50 @@
..()
/datum/middleClickOverride/power_gloves
var/last_shocked = 0
var/shock_delay = 120
/datum/middleClickOverride/power_gloves/onClick(var/atom/A, var/mob/living/user)
/datum/middleClickOverride/power_gloves/onClick(atom/A, mob/living/carbon/human/user)
if(A == user || user.a_intent == INTENT_HELP || user.a_intent == INTENT_GRAB)
return
if(user.incapacitated())
return
if(world.time < last_shocked + shock_delay)
var/obj/item/clothing/gloves/color/yellow/power/P = user.gloves
if(world.time < P.last_shocked + P.shock_delay)
to_chat(user, "<span class='warning'>The gloves are still recharging.</span>")
return
if(!isliving(A))
to_chat(user, "<span class='warning'>Shocking an inanimate object would be pointless.</span>")
return
var/mob/living/L = A
var/turf/T = get_turf(user)
var/obj/structure/cable/C = locate() in T
if(!C || !istype(C))
to_chat(user, "<span class='warning'>There is no cable here to power the gloves.</span>")
return
user.visible_message("<span class='warning'>[user.name] fires an arc of electricity at [L]!</span>", "<span class='warning'>You fire an arc of electricity at [L]!</span>", "You hear the loud crackle of electricity!")
playsound(user.loc, 'sound/effects/eleczap.ogg', 75, 1)
user.Beam(L,icon_state="lightning[rand(1,12)]",icon='icons/effects/effects.dmi',time=5)
electrocute_mob(L, C, user)
last_shocked = world.time
if(!P.unlimited_power)
if(!C || !istype(C))
to_chat(user, "<span class='warning'>There is no cable here to power the gloves.</span>")
return
var/turf/target_turf = get_turf(A)
target_turf.hotspot_expose(2000, 400)
playsound(user.loc, 'sound/effects/eleczap.ogg', 40, 1)
var/atom/beam_from = user
var/atom/target_atom = A
for(var/i in 0 to 3)
beam_from.Beam(target_atom, icon_state = "lightning[rand(1, 12)]", icon = 'icons/effects/effects.dmi', time = 6)
if(isliving(target_atom))
var/mob/living/L = target_atom
if(user.a_intent == INTENT_DISARM)
L.Weaken(3)
else
if(P.unlimited_power)
L.electrocute_act(1000, P, 0) //Just kill them
else
electrocute_mob(L, C, P)
break
var/list/next_shocked = list()
for(var/atom/movable/AM in orange(3, target_atom))
if(AM == user || istype(AM, /obj/effect) || isobserver(AM))
continue
next_shocked.Add(AM)
beam_from = target_atom
target_atom = pick(next_shocked)
A = target_atom
next_shocked.Cut()
P.last_shocked = world.time
+1 -3
View File
@@ -24,7 +24,7 @@
return FALSE
/obj/attackby(obj/item/I, mob/living/user, params)
return ..() || (can_be_hit && isitem(I) && I.attack_obj(src, user))
return ..() || (can_be_hit && I.attack_obj(src, user))
/mob/living/attackby(obj/item/I, mob/living/user, params)
user.changeNext_move(CLICK_CD_MELEE)
@@ -37,8 +37,6 @@
SEND_SIGNAL(user, COMSIG_MOB_ITEM_ATTACK, M, user)
if(flags & (NOBLUDGEON))
return 0
if(check_martial_counter(M, user))
return 0
if(can_operate(M)) //Checks if mob is lying down on table for surgery
if(istype(src,/obj/item/robot_parts))//popup override for direct attach
if(!attempt_initiate_surgery(src, M, user,1))
@@ -0,0 +1,21 @@
GLOBAL_REAL(SSmentor_tickets, /datum/controller/subsystem/tickets/mentor_tickets)
/datum/controller/subsystem/tickets/mentor_tickets/New()
NEW_SS_GLOBAL(SSmentor_tickets);
PreInit();
/datum/controller/subsystem/tickets/mentor_tickets
name = "Mentor Tickets"
ticket_system_name = "Mentor Tickets"
ticket_name = "Mentor Ticket"
span_text = "<span class='mentorhelp'>"
close_rights = R_MENTOR
/datum/controller/subsystem/tickets/mentor_tickets/message_staff(var/msg)
message_mentorTicket(msg)
/datum/controller/subsystem/tickets/mentor_tickets/Initialize()
close_messages = list("<font color='red' size='3'><b>- [ticket_name] Closed -</b></font>",
"<span class='boldmessage'>Please try to be as descriptive as possible in mentor helps. Mentors do not know the full situation you're in and need more information to give you a helpful response.</span>",
"[span_text]Your [ticket_name] has now been closed.</span>")
return ..()
@@ -1,28 +1,36 @@
//Defines
//Deciseconds until ticket becomes stale if unanswered. Alerts admins.
#define ADMIN_TICKET_TIMEOUT 6000 // 10 minutes
#define TICKET_TIMEOUT 6000 // 10 minutes
//Decisecions before the user is allowed to open another ticket while their existing one is open.
#define ADMIN_TICKET_DUPLICATE_COOLDOWN 3000 // 5 minutes
#define TICKET_DUPLICATE_COOLDOWN 3000 // 5 minutes
//Status defines
#define ADMIN_TICKET_OPEN 1
#define ADMIN_TICKET_CLOSED 2
#define ADMIN_TICKET_RESOLVED 3
#define ADMIN_TICKET_STALE 4
#define TICKET_OPEN 1
#define TICKET_CLOSED 2
#define TICKET_RESOLVED 3
#define TICKET_STALE 4
SUBSYSTEM_DEF(tickets)
name = "Tickets"
name = "Admin Tickets"
var/span_text = "<span class='adminticket'>"
var/ticket_system_name = "Admin Tickets"
var/ticket_name = "Admin Ticket"
var/close_rights = R_ADMIN
var/list/close_messages
init_order = INIT_ORDER_TICKETS
wait = 300
priority = FIRE_PRIORITY_TICKETS
flags = SS_BACKGROUND
var/list/allTickets
var/ticketCounter = 1
/datum/controller/subsystem/tickets/Initialize()
close_messages = list("<font color='red' size='4'><b>- [ticket_name] Rejected! -</b></font>",
"<span class='boldmessage'>Please try to be calm, clear, and descriptive in admin helps, do not assume the staff member has seen any related events, and clearly state the names of anybody you are reporting. If you asked a question, please ensure it was clear what you were asking.</span>",
"[span_text]Your [ticket_name] has now been closed.</span>")
LAZYINITLIST(allTickets)
return ..()
@@ -32,7 +40,7 @@ SUBSYSTEM_DEF(tickets)
var/report
for(var/num in stales)
report += "[num], "
message_adminTicket("<span class='adminticket'>Tickets [report] have been open for over [ADMIN_TICKET_TIMEOUT / 600] minutes. Changing status to stale.</span>")
message_staff("[span_text]Tickets [report] have been open for over [TICKET_TIMEOUT / 600] minutes. Changing status to stale.</span>")
/datum/controller/subsystem/tickets/stat_entry()
..("Tickets: [LAZYLEN(allTickets)]")
@@ -40,10 +48,10 @@ SUBSYSTEM_DEF(tickets)
/datum/controller/subsystem/tickets/proc/checkStaleness()
var/stales = list()
for(var/T in allTickets)
var/datum/admin_ticket/ticket = T
if(!(ticket.ticketState == ADMIN_TICKET_OPEN))
var/datum/ticket/ticket = T
if(!(ticket.ticketState == TICKET_OPEN))
continue
if(world.time > ticket.timeUntilStale && (!ticket.lastAdminResponse || !ticket.adminAssigned))
if(world.time > ticket.timeUntilStale && (!ticket.lastStaffResponse || !ticket.staffAssigned))
var/id = ticket.makeStale()
stales += id
return stales
@@ -60,7 +68,7 @@ SUBSYSTEM_DEF(tickets)
/datum/controller/subsystem/tickets/proc/resolveAllOpenTickets() // Resolve all open tickets
for(var/i in allTickets)
var/datum/admin_ticket/T = i
var/datum/ticket/T = i
resolveTicket(T.ticketNum)
//Open a new ticket and populate details then add to the list of open tickets
@@ -69,56 +77,57 @@ SUBSYSTEM_DEF(tickets)
return
//Check if the user has an open ticket already within the cooldown period, if so we don't create a new one and re-set the cooldown period
var/datum/admin_ticket/existingTicket = checkForOpenTicket(C)
var/datum/ticket/existingTicket = checkForOpenTicket(C)
if(existingTicket)
existingTicket.setCooldownPeriod()
to_chat(C.mob, "<span class='adminticket'>Your ticket #[existingTicket.ticketNum] remains open! Visit \"My tickets\" under the Admin Tab to view it.</span>")
to_chat(C.mob, "[span_text]Your [ticket_name] #[existingTicket.ticketNum] remains open! Visit \"My tickets\" under the Admin Tab to view it.</span>")
return
if(!title)
title = passedContent
var/datum/admin_ticket/T = new(title, passedContent)
var/datum/ticket/T = new(title, passedContent, getTicketCounterAndInc())
allTickets += T
T.clientName = C
T.locationSent = C.mob.loc.name
T.mobControlled = C.mob
//Inform the user that they have opened a ticket
to_chat(C, "<span class='adminticket'>You have opened admin ticket number #[(SStickets.getTicketCounter() - 1)]! Please be patient and we will help you soon!</span>")
to_chat(C, "[span_text]You have opened [ticket_name] number #[(getTicketCounter() - 1)]! Please be patient and we will help you soon!</span>")
//Set ticket state with key N to open
/datum/controller/subsystem/tickets/proc/openTicket(N)
var/datum/admin_ticket/T = SStickets.allTickets[N]
if(T.ticketState != ADMIN_TICKET_OPEN)
T.ticketState = ADMIN_TICKET_OPEN
var/datum/ticket/T = allTickets[N]
if(T.ticketState != TICKET_OPEN)
T.ticketState = TICKET_OPEN
return TRUE
//Set ticket state with key N to resolved
/datum/controller/subsystem/tickets/proc/resolveTicket(N)
var/datum/admin_ticket/T = SStickets.allTickets[N]
if(T.ticketState != ADMIN_TICKET_RESOLVED)
T.ticketState = ADMIN_TICKET_RESOLVED
var/datum/ticket/T = allTickets[N]
if(T.ticketState != TICKET_RESOLVED)
T.ticketState = TICKET_RESOLVED
return TRUE
//Set ticket state with key N to closed
/datum/controller/subsystem/tickets/proc/closeTicket(N)
var/datum/admin_ticket/T = SStickets.allTickets[N]
if(T.ticketState != ADMIN_TICKET_CLOSED)
T.ticketState = ADMIN_TICKET_CLOSED
var/datum/ticket/T = allTickets[N]
if(T.ticketState != TICKET_CLOSED)
T.ticketState = TICKET_CLOSED
return TRUE
//Check if the user already has a ticket open and within the cooldown period.
/datum/controller/subsystem/tickets/proc/checkForOpenTicket(client/C)
for(var/datum/admin_ticket/T in allTickets)
if(T.clientName == C && T.ticketState == ADMIN_TICKET_OPEN && (T.ticketCooldown > world.time))
for(var/datum/ticket/T in allTickets)
if(T.clientName == C && T.ticketState == TICKET_OPEN && (T.ticketCooldown > world.time))
return T
return FALSE
//Check if the user has ANY ticket not resolved or closed.
/datum/controller/subsystem/tickets/proc/checkForTicket(client/C)
var/list/tickets = list()
for(var/datum/admin_ticket/T in allTickets)
if(T.clientName == C && (T.ticketState == ADMIN_TICKET_OPEN || T.ticketState == ADMIN_TICKET_STALE))
for(var/datum/ticket/T in allTickets)
if(T.clientName == C && (T.ticketState == TICKET_OPEN || T.ticketState == TICKET_STALE))
tickets += T
if(tickets.len)
return tickets
@@ -126,78 +135,77 @@ SUBSYSTEM_DEF(tickets)
//return the client of a ticket number
/datum/controller/subsystem/tickets/proc/returnClient(N)
var/datum/admin_ticket/T = SStickets.allTickets[N]
var/datum/ticket/T = allTickets[N]
return T.clientName
/datum/controller/subsystem/tickets/proc/assignAdminToTicket(client/C, var/N)
var/datum/admin_ticket/T = SStickets.allTickets[N]
T.assignAdmin(C)
/datum/controller/subsystem/tickets/proc/assignStaffToTicket(client/C, var/N)
var/datum/ticket/T = allTickets[N]
T.assignStaff(C)
return TRUE
//Single admin ticket
//Single staff ticket
/datum/admin_ticket
/datum/ticket
var/ticketNum // Ticket number
var/clientName // Client which opened the ticket
var/timeOpened // Time the ticket was opened
var/title //The initial message with links
var/list/content // content of the admin help
var/lastAdminResponse // Last admin who responded
var/lastResponseTime // When the admin last responded
var/list/content // content of the staff help
var/lastStaffResponse // Last staff member who responded
var/lastResponseTime // When the staff last responded
var/locationSent // Location the player was when they send the ticket
var/mobControlled // Mob they were controlling
var/ticketState // State of the ticket, open, closed, resolved etc
var/timeUntilStale // When the ticket goes stale
var/ticketCooldown // Cooldown before allowing the user to open another ticket.
var/adminAssigned // Admin who has assigned themselves to this ticket
var/staffAssigned // Staff member who has assigned themselves to this ticket
/datum/admin_ticket/New(tit, cont)
/datum/ticket/New(tit, cont, num)
title = tit
content = list()
content += cont
timeOpened = worldtime2text()
timeUntilStale = world.time + ADMIN_TICKET_TIMEOUT
timeUntilStale = world.time + TICKET_TIMEOUT
setCooldownPeriod()
ticketNum = SStickets.getTicketCounterAndInc()
ticketState = ADMIN_TICKET_OPEN
SStickets.allTickets += src
ticketNum = num
ticketState = TICKET_OPEN
//Set the cooldown period for the ticket. The time when it's created plus the defined cooldown time.
/datum/admin_ticket/proc/setCooldownPeriod()
ticketCooldown = world.time + ADMIN_TICKET_DUPLICATE_COOLDOWN
/datum/ticket/proc/setCooldownPeriod()
ticketCooldown = world.time + TICKET_DUPLICATE_COOLDOWN
//Set the last admin who responded as the client passed as an arguement.
/datum/admin_ticket/proc/setLastAdminResponse(client/C)
lastAdminResponse = C
//Set the last staff who responded as the client passed as an arguement.
/datum/ticket/proc/setLastStaffResponse(client/C)
lastStaffResponse = C
lastResponseTime = worldtime2text()
//Return the ticket state as a colour coded text string.
/datum/admin_ticket/proc/state2text()
/datum/ticket/proc/state2text()
switch(ticketState)
if(ADMIN_TICKET_OPEN)
if(TICKET_OPEN)
return "<font color='green'>OPEN</font>"
if(ADMIN_TICKET_RESOLVED)
if(TICKET_RESOLVED)
return "<font color='blue'>RESOLVED</font>"
if(ADMIN_TICKET_CLOSED)
if(TICKET_CLOSED)
return "<font color='red'>CLOSED</font>"
if(ADMIN_TICKET_STALE)
if(TICKET_STALE)
return "<font color='orange'>STALE</font>"
//Assign the client passed to var/adminAsssigned
/datum/admin_ticket/proc/assignAdmin(client/C)
//Assign the client passed to var/staffAsssigned
/datum/ticket/proc/assignStaff(client/C)
if(!C)
return
adminAssigned = C
staffAssigned = C
return TRUE
/datum/admin_ticket/proc/addResponse(client/C, msg)
/datum/ticket/proc/addResponse(client/C, msg)
if(C.holder)
setLastAdminResponse(C)
setLastStaffResponse(C)
msg = "[C]: [msg]"
content += msg
/datum/admin_ticket/proc/makeStale()
ticketState = ADMIN_TICKET_STALE
/datum/ticket/proc/makeStale()
ticketState = TICKET_STALE
return ticketNum
/*
@@ -206,7 +214,7 @@ UI STUFF
*/
/datum/controller/subsystem/tickets/proc/returnUI(tab = ADMIN_TICKET_OPEN)
/datum/controller/subsystem/tickets/proc/returnUI(tab = TICKET_OPEN)
set name = "Open Ticket Interface"
set category = "Tickets"
@@ -214,36 +222,36 @@ UI STUFF
var/trStyle = "border-top:2px solid; border-bottom:2px solid; padding-top: 5px; padding-bottom: 5px;"
var/tdStyleleft = "border-top:2px solid; border-bottom:2px solid; width:150px; text-align:center;"
var/tdStyle = "border-top:2px solid; border-bottom:2px solid;"
var/datum/admin_ticket/ticket
var/datum/ticket/ticket
var/dat
dat += "<head><style>.adminticket{border:2px solid}</style></head>"
dat += "<body><h1>Admin Tickets</h1>"
dat += "<body><h1>[ticket_system_name]</h1>"
dat +="<a href='?src=[UID()];refresh=1'>Refresh</a><br /><a href='?src=[UID()];showopen=1'>Open Tickets</a><a href='?src=[UID()];showresolved=1'>Resolved Tickets</a><a href='?src=[UID()];showclosed=1'>Closed Tickets</a>"
if(tab == ADMIN_TICKET_OPEN)
if(tab == TICKET_OPEN)
dat += "<h2>Open Tickets</h2>"
dat += "<table style='width:1300px; border: 3px solid;'>"
dat +="<tr style='[trStyle]'><th style='[tdStyleleft]'>Control</th><th style='[tdStyle]'>Ticket</th></tr>"
if(tab == ADMIN_TICKET_OPEN)
if(tab == TICKET_OPEN)
for(var/T in allTickets)
ticket = T
if(ticket.ticketState == ADMIN_TICKET_OPEN || ticket.ticketState == ADMIN_TICKET_STALE)
dat += "<tr style='[trStyle]'><td style ='[tdStyleleft]'><a href='?src=[UID()];resolve=[ticket.ticketNum]'>Resolve</a><a href='?src=[UID()];details=[ticket.ticketNum]'>Details</a> <br /> #[ticket.ticketNum] ([ticket.timeOpened]) [ticket.ticketState == ADMIN_TICKET_STALE ? "<font color='red'><b>STALE</font>" : ""] </td><td style='[tdStyle]'><b>[ticket.title]</td></tr>"
if(ticket.ticketState == TICKET_OPEN || ticket.ticketState == TICKET_STALE)
dat += "<tr style='[trStyle]'><td style ='[tdStyleleft]'><a href='?src=[UID()];resolve=[ticket.ticketNum]'>Resolve</a><a href='?src=[UID()];details=[ticket.ticketNum]'>Details</a> <br /> #[ticket.ticketNum] ([ticket.timeOpened]) [ticket.ticketState == TICKET_STALE ? "<font color='red'><b>STALE</font>" : ""] </td><td style='[tdStyle]'><b>[ticket.title]</td></tr>"
else
continue
else if(tab == ADMIN_TICKET_RESOLVED)
else if(tab == TICKET_RESOLVED)
dat += "<h2>Resolved Tickets</h2>"
for(var/T in allTickets)
ticket = T
if(ticket.ticketState == ADMIN_TICKET_RESOLVED)
if(ticket.ticketState == TICKET_RESOLVED)
dat += "<tr style='[trStyle]'><td style ='[tdStyleleft]'><a href='?src=[UID()];resolve=[ticket.ticketNum]'>Resolve</a><a href='?src=[UID()];details=[ticket.ticketNum]'>Details</a> <br /> #[ticket.ticketNum] ([ticket.timeOpened]) </td><td style='[tdStyle]'><b>[ticket.title]</td></tr>"
else
continue
else if(tab == ADMIN_TICKET_CLOSED)
else if(tab == TICKET_CLOSED)
dat += "<h2>Closed Tickets</h2>"
for(var/T in allTickets)
ticket = T
if(ticket.ticketState == ADMIN_TICKET_CLOSED)
if(ticket.ticketState == TICKET_CLOSED)
dat += "<tr style='[trStyle]'><td style ='[tdStyleleft]'><a href='?src=[UID()];resolve=[ticket.ticketNum]'>Resolve</a><a href='?src=[UID()];details=[ticket.ticketNum]'>Details</a> <br /> #[ticket.ticketNum] ([ticket.timeOpened]) </td><td style='[tdStyle]'><b>[ticket.title]</td></tr>"
else
continue
@@ -255,21 +263,21 @@ UI STUFF
/datum/controller/subsystem/tickets/proc/showUI(mob/user, tab)
var/dat = null
dat = returnUI(tab)
var/datum/browser/popup = new(user, "admintickets", "Admin Tickets", 1400, 600)
var/datum/browser/popup = new(user, ticket_system_name, ticket_system_name, 1400, 600)
popup.set_content(dat)
popup.open()
/datum/controller/subsystem/tickets/proc/showDetailUI(mob/user, ticketID)
var/datum/admin_ticket/T = SStickets.allTickets[ticketID]
var/datum/ticket/T = allTickets[ticketID]
var/status = "[T.state2text()]"
var/dat = "<h1>Admin Tickets</h1>"
var/dat = "<h1>[ticket_system_name]</h1>"
dat +="<a href='?src=[UID()];refresh=1'>Show All</a><a href='?src=[UID()];refreshdetail=[T.ticketNum]'>Refresh</a>"
dat += "<h2>Ticket #[T.ticketNum]</h2>"
dat += "<h3>[T.clientName] / [T.mobControlled] opened this ticket at [T.timeOpened] at location [T.locationSent]</h3>"
dat += "<h3>[T.clientName] / [T.mobControlled] opened this [ticket_name] at [T.timeOpened] at location [T.locationSent]</h3>"
dat += "<h4>Ticket Status: <font color='red'>[status]</font>"
dat += "<table style='width:950px; border: 3px solid;'>"
dat += "<tr><td>[T.title]</td></tr>"
@@ -281,21 +289,21 @@ UI STUFF
dat += "</table><br /><br />"
dat += "<a href='?src=[UID()];detailreopen=[T.ticketNum]'>Re-Open</a><a href='?src=[UID()];detailresolve=[T.ticketNum]'>Resolve</a><br /><br />"
if(!T.adminAssigned)
dat += "No admin assigned to this ticket - <a href='?src=[UID()];assignadmin=[T.ticketNum]'>Take Ticket</a><br />"
if(!T.staffAssigned)
dat += "No staff member assigned to this [ticket_name] - <a href='?src=[UID()];assignstaff=[T.ticketNum]'>Take Ticket</a><br />"
else
dat += "[T.adminAssigned] is assigned to this Ticket. - <a href='?src=[UID()];assignadmin=[T.ticketNum]'>Take Ticket</a><br />"
dat += "[T.staffAssigned] is assigned to this Ticket. - <a href='?src=[UID()];assignstaff=[T.ticketNum]'>Take Ticket</a><br />"
if(T.lastAdminResponse)
dat += "<b>Last Admin Response:</b> [T.lastAdminResponse] at [T.lastResponseTime]"
if(T.lastStaffResponse)
dat += "<b>Last Staff response Response:</b> [T.lastStaffResponse] at [T.lastResponseTime]"
else
dat +="<font color='red'>No Admin Response</font>"
dat +="<font color='red'>No Staff Response</font>"
dat += "<br /><br />"
dat += "<a href='?src=[UID()];detailclose=[T.ticketNum]'>Close Ticket</a>"
var/datum/browser/popup = new(user, "adminticketsdetail", "Admin Ticket #[T.ticketNum]", 1000, 600)
var/datum/browser/popup = new(user, "[ticket_system_name]detail", "[ticket_system_name] #[T.ticketNum]", 1000, 600)
popup.set_content(dat)
popup.open()
@@ -303,15 +311,15 @@ UI STUFF
//dat
var/tickets = checkForTicket(user.client)
var/dat
dat += "<h1>Your open tickets</h1>"
dat += "<h1>Your open [ticket_system_name]</h1>"
dat += "<table>"
for(var/datum/admin_ticket/T in tickets)
for(var/datum/ticket/T in tickets)
dat += "<tr><td><h2>Ticket #[T.ticketNum]</h2></td></tr>"
for(var/i = 1, i <= T.content.len, i++)
dat += "<tr><td>[T.content[i]]</td></tr>"
dat += "</table>"
var/datum/browser/popup = new(user, "userticketsdetail", "Tickets", 1000, 600)
var/datum/browser/popup = new(user, "[ticket_system_name]userticketsdetail", ticket_system_name, 1000, 600)
popup.set_content(dat)
popup.open()
@@ -326,6 +334,10 @@ UI STUFF
to_chat(target, text)
return TRUE
//Sends a message to the designated staff
/datum/controller/subsystem/tickets/proc/message_staff(var/msg)
message_adminTicket(msg)
/datum/controller/subsystem/tickets/Topic(href, href_list)
if(href_list["refresh"])
@@ -338,13 +350,13 @@ UI STUFF
return
if(href_list["showopen"])
showUI(usr, ADMIN_TICKET_OPEN)
showUI(usr, TICKET_OPEN)
return
if(href_list["showresolved"])
showUI(usr, ADMIN_TICKET_RESOLVED)
showUI(usr, TICKET_RESOLVED)
return
if(href_list["showclosed"])
showUI(usr, ADMIN_TICKET_CLOSED)
showUI(usr, TICKET_CLOSED)
return
if(href_list["details"])
@@ -354,40 +366,43 @@ UI STUFF
if(href_list["resolve"])
var/indexNum = text2num(href_list["resolve"])
if(SStickets.resolveTicket(indexNum))
message_adminTicket("[usr.client] / ([usr]) resolved admin ticket number [indexNum]")
to_chat_safe(returnClient(indexNum), "<span class='adminticket'>Your admin ticket has now been resolved.</span>")
if(resolveTicket(indexNum))
message_staff("[usr.client] / ([usr]) resolved [ticket_name] number [indexNum]")
to_chat_safe(returnClient(indexNum), "[span_text]Your [ticket_name] has now been resolved.</span>")
showUI(usr)
if(href_list["detailresolve"])
var/indexNum = text2num(href_list["detailresolve"])
if(SStickets.resolveTicket(indexNum))
message_adminTicket("[usr.client] / ([usr]) resolved admin ticket number [indexNum]")
to_chat_safe(returnClient(indexNum), "<span class='adminticket'>Your admin ticket has now been resolved.</span>")
if(resolveTicket(indexNum))
message_staff("[usr.client] / ([usr]) resolved [ticket_name] number [indexNum]")
to_chat_safe(returnClient(indexNum), "[span_text]Your [ticket_name] has now been resolved.</span>")
showDetailUI(usr, indexNum)
if(href_list["detailclose"])
var/indexNum = text2num(href_list["detailclose"])
if(!check_rights(close_rights))
to_chat(usr, "Not enough rights to close this ticket.")
return
if(alert("Are you sure? This will send a negative message.",,"Yes","No") != "Yes")
return
if(SStickets.closeTicket(indexNum))
message_adminTicket("[usr.client] / ([usr]) closed admin ticket number [indexNum]")
to_chat_safe(returnClient(indexNum), list(
"<font color='red' size='4'><b>- AdminHelp Rejected! -</b></font>",
"<span class='boldmessage'>Please try to be calm, clear, and descriptive in admin helps, do not assume the admin has seen any related events, and clearly state the names of anybody you are reporting. If you asked a question, please ensure it was clear what you were asking.</span>",
"<span class='adminticket'>Your ticket has now been closed.</span>"
))
if(closeTicket(indexNum))
message_staff("[usr.client] / ([usr]) closed [ticket_name] number [indexNum]")
to_chat_safe(returnClient(indexNum), close_messages)
showDetailUI(usr, indexNum)
if(href_list["detailreopen"])
var/indexNum = text2num(href_list["detailreopen"])
if(SStickets.openTicket(indexNum))
message_adminTicket("[usr.client] / ([usr]) re-opened admin ticket number [indexNum]")
if(openTicket(indexNum))
message_staff("[usr.client] / ([usr]) re-opened [ticket_name] number [indexNum]")
showDetailUI(usr, indexNum)
if(href_list["assignadmin"])
var/indexNum = text2num(href_list["assignadmin"])
if(SStickets.assignAdminToTicket(usr.client, indexNum))
message_adminTicket("[usr.client] / ([usr]) has taken ticket number [indexNum]")
to_chat_safe(returnClient(indexNum), "<span class='adminticket'>Your ticket is being handled by [usr.client].")
if(href_list["assignstaff"])
var/indexNum = text2num(href_list["assignstaff"])
takeTicket(indexNum)
showDetailUI(usr, indexNum)
/datum/controller/subsystem/tickets/proc/takeTicket(var/index)
if(assignStaffToTicket(usr.client, index))
message_staff("[usr.client] / ([usr]) has taken [ticket_name] number [index]")
to_chat_safe(returnClient(index), "[span_text]Your [ticket_name] is being handled by [usr.client].")
+4
View File
@@ -23,6 +23,8 @@
button = new
button.linked_action = src
button.name = name
if(desc)
button.desc = desc
/datum/action/Destroy()
if(owner)
@@ -82,6 +84,7 @@
if(button)
button.icon = button_icon
button.icon_state = background_icon_state
button.desc = desc
ApplyIcon(button)
@@ -441,6 +444,7 @@
var/obj/effect/proc_holder/spell/S = target
S.action = src
name = S.name
desc = S.desc
button_icon = S.action_icon
button_icon_state = S.action_icon_state
background_icon_state = S.action_background_icon_state
+27
View File
@@ -0,0 +1,27 @@
/datum/hotkey_mode
var/name
var/macro_hotkeys_inactive
var/macro_hotkeys_active
var/mob/my_mob
/datum/hotkey_mode/New(mob)
my_mob = mob
/datum/hotkey_mode/proc/set_winset_values()
winset(my_mob, null, "mainwindow.macro=[macro_hotkeys_inactive] hotkey_toggle.is-checked=false input.focus=true input.background-color=#d3b5b5")
winset(my_mob, null, "hotkey_toggle.command=\".winset \\\"mainwindow.macro != [macro_hotkeys_inactive] ? mainwindow.macro=[macro_hotkeys_inactive] hotkey_toggle.is-checked=false input.focus=true input.background-color=#d3b5b5 : mainwindow.macro=[macro_hotkeys_active] hotkey_toggle.is-checked=true mapwindow.map.focus=true input.background-color=#f0f0f0\\\"\"")
/datum/hotkey_mode/qwerty
name = "QWERTY"
macro_hotkeys_inactive = "macro"
macro_hotkeys_active = "hotkeymode"
/datum/hotkey_mode/azerty
name = "AZERTY"
macro_hotkeys_inactive = "azertymacro"
macro_hotkeys_active = "azertyhotkeymode"
/datum/hotkey_mode/cyborg
name = "Cyborg"
macro_hotkeys_inactive = "borgmacro"
macro_hotkeys_active = "borghotkeymode"
-1
View File
@@ -10,7 +10,6 @@ var/datum/atom_hud/huds = list( \
DATA_HUD_DIAGNOSTIC = new/datum/atom_hud/data/diagnostic(), \
DATA_HUD_DIAGNOSTIC_ADVANCED = new/datum/atom_hud/data/diagnostic/advanced(), \
DATA_HUD_HYDROPONIC = new/datum/atom_hud/data/hydroponic(), \
GAME_HUD_NATIONS = new/datum/atom_hud/antag(), \
ANTAG_HUD_CULT = new/datum/atom_hud/antag(), \
ANTAG_HUD_REV = new/datum/atom_hud/antag(), \
ANTAG_HUD_OPS = new/datum/atom_hud/antag(), \
-1
View File
@@ -51,7 +51,6 @@
var/datum/changeling/changeling //changeling holder
var/linglink
var/datum/vampire/vampire //vampire holder
var/datum/nations/nation //nation holder
var/datum/abductor/abductor //abductor holder
var/datum/devilinfo/devilinfo //devil holder
+6 -11
View File
@@ -88,7 +88,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
/datum/uplink_item/proc/spawn_item(var/turf/loc, var/obj/item/uplink/U)
if(hijack_only)
if(hijack_only && !(usr.mind.special_role == SPECIAL_ROLE_NUKEOPS))//nukies get items that regular traitors only get with hijack. If a hijack-only item is not for nukies, then exclude it via the gamemode list.
if(!(locate(/datum/objective/hijack) in usr.mind.objectives))
to_chat(usr, "<span class='warning'>The Syndicate will only issue this extremely dangerous item to agents assigned the Hijack objective.</span>")
return
@@ -186,7 +186,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
name = "Trick Revolver"
desc = "A revolver that will fire backwards and kill whoever attempts to use it. Perfect for those pesky vigilante or just a good laugh."
reference = "CTR"
item = /obj/item/toy/russian_revolver/trick_revolver
item = /obj/item/storage/box/syndie_kit/fake_revolver
cost = 1
job = list("Clown")
@@ -813,7 +813,9 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
desc = "A manual that teaches a single user tactical Close-Quarters Combat before self-destructing. Does not restrict weapon usage, but cannot be used alongside Gloves of the North Star."
reference = "CQC"
item = /obj/item/CQC_manual
cost = 9
gamemodes = list(/datum/game_mode/nuclear)
cost = 13
surplus = 0
/datum/uplink_item/stealthy_weapons/cameraflash
name = "Camera Flash"
@@ -893,7 +895,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
desc = "Just add water to make your very own hostile to everything space carp. It looks just like a plushie. The first person to squeeze it will be registered as its owner, who it will not attack. If no owner is registered, it'll just attack everyone."
reference = "DSC"
item = /obj/item/toy/carpplushie/dehy_carp
cost = 3
cost = 2
// GRENADES AND EXPLOSIVES
@@ -1330,13 +1332,6 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
surplus = 0
hijack_only = TRUE //This is an item only useful for a hijack traitor, as such, it should only be available in those scenarios.
cant_discount = TRUE
excludefrom = list(/datum/game_mode/nuclear)
/datum/uplink_item/device_tools/singularity_beacon/nuke
reference = "SNGBN"
hijack_only = FALSE // This inherited version exists so nukies can use it while keeping the original hijack only
excludefrom = list()
gamemodes = list(/datum/game_mode/nuclear)
/datum/uplink_item/device_tools/syndicate_detonator
name = "Syndicate Detonator"
+1 -1
View File
@@ -82,7 +82,7 @@
continue
var/obj/structure/blob/normal/B = locate() in get_step(src, b_dir)
if(B)
B.change_to(/obj/structure/blob/shield)
B.change_to(/obj/structure/blob/shield/core)
if(B && overmind)
B.color = overmind.blob_reagent_datum.color
else
+3
View File
@@ -8,6 +8,9 @@
point_return = 4
var/maxHealth = 75
/obj/structure/blob/shield/core
point_return = 0
/obj/structure/blob/shield/update_icon()
if(health <= 0)
qdel(src)
+12 -2
View File
@@ -367,9 +367,19 @@
/obj/item/clothing/head/culthood/alt/ghost
flags = NODROP | DROPDEL
/obj/item/clothing/suit/cultrobes/alt/ghost
/obj/item/clothing/suit/cultrobesghost
name = "ghostly cult robes"
desc = "A set of ethreal armored robes worn by the undead followers of a cult."
icon_state = "cultrobesalt"
item_state = "cultrobesalt"
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
allowed = list(/obj/item/tome,/obj/item/melee/cultblade)
armor = list(melee = 50, bullet = 30, laser = 50, energy = 20, bomb = 25, bio = 10, rad = 0)
flags_inv = HIDEJUMPSUIT
flags = NODROP | DROPDEL
/obj/item/clothing/shoes/cult/ghost
flags = NODROP | DROPDEL
@@ -377,7 +387,7 @@
name = "Cultist Ghost"
uniform = /obj/item/clothing/under/color/black
suit = /obj/item/clothing/suit/cultrobes/alt/ghost
suit = /obj/item/clothing/suit/cultrobesghost
shoes = /obj/item/clothing/shoes/cult/ghost
head = /obj/item/clothing/head/culthood/alt/ghost
r_hand = /obj/item/melee/cultblade/ghost
@@ -12,6 +12,7 @@
icon_dead = "magicOrange"
speed = 0
a_intent = INTENT_HARM
can_change_intents = 0
stop_automated_movement = 1
floating = 1
attack_sound = 'sound/weapons/punch1.ogg'
@@ -85,6 +86,18 @@
forceMove(summoner.loc) //move to summoner's tile, don't recall
new /obj/effect/temp_visual/guardian/phase(loc)
/mob/living/simple_animal/hostile/guardian/proc/is_deployed()
return loc != summoner
/mob/living/simple_animal/hostile/guardian/AttackingTarget()
if(!is_deployed() && a_intent == INTENT_HARM)
to_chat(src, "<span class='danger'>You must be manifested to attack!</span>")
return FALSE
else if(!is_deployed() && a_intent == INTENT_HELP)
return FALSE
else
return ..()
/mob/living/simple_animal/hostile/guardian/Move() //Returns to summoner if they move out of range
..()
snapback()
@@ -149,11 +162,12 @@
if(!summoner) return
if(loc == summoner)
forceMove(get_turf(summoner))
new /obj/effect/temp_visual/guardian/phase(loc)
src.client.eye = loc
cooldown = world.time + 30
/mob/living/simple_animal/hostile/guardian/proc/Recall(forced = FALSE)
if(cooldown > world.time && !forced)
if(!summoner || loc == summoner || (cooldown > world.time && !forced))
return
if(!summoner) return
new /obj/effect/temp_visual/guardian/phase/out(get_turf(src))
@@ -8,6 +8,13 @@
tech_fluff_string = "Boot sequence complete. Explosive modules active. Holoparasite swarm online."
bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, capable of stealthily booby trapping items."
var/bomb_cooldown = 0
var/default_bomb_cooldown = 20 SECONDS
/mob/living/simple_animal/hostile/guardian/bomb/Stat()
..()
if(statpanel("Status"))
if(bomb_cooldown >= world.time)
stat(null, "Bomb Cooldown Remaining: [max(round((bomb_cooldown - world.time)*0.1, 0.1), 0)] seconds")
/mob/living/simple_animal/hostile/guardian/bomb/AltClickOn(atom/movable/A)
if(!istype(A))
@@ -21,11 +28,11 @@
to_chat(src, "<span class='danger'>Success! Bomb on [A] armed!</span>")
if(summoner)
to_chat(summoner, "<span class='warning'>Your guardian has primed [A] to explode!</span>")
bomb_cooldown = world.time + 200
bomb_cooldown = world.time + default_bomb_cooldown
B.spawner = src
B.disguise (A)
else
to_chat(src, "<span class='danger'>Your powers are on cooldown! You must wait 20 seconds between bombs.</span>")
to_chat(src, "<span class='danger'>Your power is on cooldown! You must wait another [max(round((bomb_cooldown - world.time)*0.1, 0.1), 0)] seconds before you can place next bomb.</span>")
/obj/item/guardian_bomb
name = "bomb"
@@ -1,5 +1,4 @@
/mob/living/simple_animal/hostile/guardian/fire
a_intent = INTENT_HELP
melee_damage_lower = 10
melee_damage_upper = 10
attack_sound = 'sound/items/welder.ogg'
@@ -1,5 +1,4 @@
/mob/living/simple_animal/hostile/guardian/healer
a_intent = INTENT_HARM
friendly = "heals"
speed = 0
melee_damage_lower = 15
@@ -10,6 +9,7 @@
bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, capable of mending wounds and travelling via bluespace."
var/turf/simulated/floor/beacon
var/beacon_cooldown = 0
var/default_beacon_cooldown = 300 SECONDS
var/toggle = FALSE
var/heal_cooldown = 0
@@ -21,7 +21,6 @@
icon_state = "seal"
attacktext = "slaps"
speak_emote = list("barks")
a_intent = INTENT_HARM
friendly = "heals"
speed = 0
melee_damage_lower = 0
@@ -37,6 +36,12 @@
var/datum/atom_hud/medsensor = huds[DATA_HUD_MEDICAL_ADVANCED]
medsensor.add_hud_to(src)
/mob/living/simple_animal/hostile/guardian/healer/Stat()
..()
if(statpanel("Status"))
if(beacon_cooldown >= world.time)
stat(null, "Bluespace Beacon Cooldown Remaining: [max(round((beacon_cooldown - world.time)*0.1, 0.1), 0)] seconds")
/mob/living/simple_animal/hostile/guardian/healer/AttackingTarget()
..()
if(toggle == TRUE)
@@ -60,6 +65,7 @@
if(loc == summoner)
if(toggle)
a_intent = INTENT_HARM
hud_used.action_intent.icon_state = a_intent;
speed = 0
damage_transfer = 0.7
if(adminseal)
@@ -70,6 +76,7 @@
toggle = FALSE
else
a_intent = INTENT_HELP
hud_used.action_intent.icon_state = a_intent;
speed = 1
damage_transfer = 1
if(adminseal)
@@ -81,9 +88,8 @@
else
to_chat(src, "<span class='danger'>You have to be recalled to toggle modes!</span>")
/mob/living/simple_animal/hostile/guardian/healer/verb/Beacon()
set name = "Place Bluespsace Beacon"
set name = "Place Bluespace Beacon"
set category = "Guardian"
set desc = "Mark a floor as your beacon point, allowing you to warp targets to it. Your beacon will not work in unfavorable atmospheric conditions."
if(beacon_cooldown < world.time)
@@ -98,10 +104,10 @@
if(beacon)
beacon.ChangeTurf(/turf/simulated/floor/plating)
beacon = F
beacon_cooldown = world.time+3000
beacon_cooldown = world.time + default_beacon_cooldown
else
to_chat(src, "<span class='danger'>Your power is on cooldown. You must wait five minutes between placing beacons.</span>")
to_chat(src, "<span class='danger'>Your power is on cooldown! You must wait another [max(round((beacon_cooldown - world.time)*0.1, 0.1), 0)] seconds before you can place another beacon.</span>")
/mob/living/simple_animal/hostile/guardian/healer/AltClickOn(atom/movable/A)
if(!istype(A))
@@ -6,7 +6,6 @@
armour_penetration = 100
/mob/living/simple_animal/hostile/guardian/ranged
a_intent = INTENT_HELP
friendly = "quietly assesses"
melee_damage_lower = 10
melee_damage_upper = 10
-256
View File
@@ -1,256 +0,0 @@
datum/game_mode/nations
name = "nations"
config_tag = "nations"
required_players = 25
var/kickoff = 0
var/victory = 0
var/list/cargonians = list("Quartermaster","Cargo Technician","Shaft Miner")
var/list/servicion = list("Clown", "Mime", "Bartender", "Chef", "Botanist", "Librarian", "Chaplain", "Barber")
/datum/game_mode/nations/post_setup()
spawn (rand(1200, 3000))
kickoff=1
send_intercept()
split_teams()
set_ai()
assign_leaders()
// remove_access()
for(var/mob/M in GLOB.player_list)
if(!istype(M,/mob/new_player))
M << sound('sound/effects/purge_siren.ogg')
return ..()
/datum/game_mode/nations/proc/send_intercept()
event_announcement.Announce("Due to recent and COMPLETELY UNFOUNDED allegations of massive fraud and insider trading \
affecting trillions of investors, the Nanotrasen Corporation has decided to liquidate all \
assets of the Centcom Division in order to pay the massive legal fees that will be incurred \
during the following centuries long court process. Therefore, all current employment contracts \
are IMMEDIATELY TERMINATED. Nanotrasen will be unable to send a rescue shuttle to carry you home,\
however they remain willing for the time being to continue trading cargo. Have a pleasant \
day.", "FINAL TRANSMISSION, CENTCOM.", new_sound = 'sound/AI/intercept.ogg')
/datum/game_mode/nations/proc/split_teams()
for(var/mob/living/carbon/human/H in GLOB.player_list)
if(H.mind)
if(H.mind.assigned_role in engineering_positions)
H.mind.nation = GLOB.all_nations["Atmosia"]
update_nations_icons_added(H,"hudatmosia")
H.mind.nation.membership += H.mind.current
if(H.mind.assigned_role == H.mind.nation.default_leader)
H.mind.nation.current_leader = H.mind.current
to_chat(H, "You have been chosen to lead the nation of [H.mind.nation.default_name]!")
continue
to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.default_name]!")
continue
if(H.mind.assigned_role in medical_positions)
H.mind.nation = GLOB.all_nations["Medistan"]
update_nations_icons_added(H,"hudmedistan")
H.mind.nation.membership += H.mind.current
if(H.mind.assigned_role == H.mind.nation.default_leader)
H.mind.nation.current_leader = H.mind.current
to_chat(H, "You have been chosen to lead the nation of [H.mind.nation.default_name]!")
continue
to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.default_name]!")
continue
if(H.mind.assigned_role in science_positions)
H.mind.nation = GLOB.all_nations["Scientopia"]
update_nations_icons_added(H,"hudscientopia")
H.mind.nation.membership += H.mind.current
if(H.mind.assigned_role == H.mind.nation.default_leader)
H.mind.nation.current_leader = H.mind.current
to_chat(H, "You have been chosen to lead the nation of [H.mind.nation.default_name]!")
continue
to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.default_name]!")
continue
if(H.mind.assigned_role in security_positions)
H.mind.nation = GLOB.all_nations["Brigston"]
update_nations_icons_added(H,"hudbrigston")
H.mind.nation.membership += H.mind.current
if(H.mind.assigned_role == H.mind.nation.default_leader)
H.mind.nation.current_leader = H.mind.current
to_chat(H, "You have been chosen to lead the nation of [H.mind.nation.default_name]!")
continue
to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.default_name]!")
continue
if(H.mind.assigned_role in cargonians)
H.mind.nation = GLOB.all_nations["Cargonia"]
update_nations_icons_added(H,"hudcargonia")
H.mind.nation.membership += H.mind.current
if(H.mind.assigned_role == H.mind.nation.default_leader)
H.mind.nation.current_leader = H.mind.current
to_chat(H, "You have been chosen to lead the nation of [H.mind.nation.default_name]!")
continue
to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.default_name]!")
continue
if(H.mind.assigned_role in servicion)
H.mind.nation = GLOB.all_nations["Servicion"]
update_nations_icons_added(H,"hudservice")
H.mind.nation.membership += H.mind.current
if(H.mind.assigned_role == H.mind.nation.default_leader)
H.mind.nation.current_leader = H.mind.current
to_chat(H, "You have been chosen to lead the nation of [H.mind.nation.default_name]!")
continue
to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.default_name]!")
continue
if(H.mind.assigned_role in (support_positions + command_positions))
H.mind.nation = GLOB.all_nations["People's Republic of Commandzakstan"]
update_nations_icons_added(H,"hudcommand")
H.mind.nation.membership += H.mind.current
if(H.mind.assigned_role == H.mind.nation.default_leader)
H.mind.nation.current_leader = H.mind.current
to_chat(H, "You have been chosen to lead the nation of [H.mind.nation.default_name]!")
continue
to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.default_name]!")
continue
if(H.mind.assigned_role in civilian_positions)
to_chat(H, "You do not belong to any nation and are free to sell your services to the highest bidder.")
continue
else
message_admins("[H.name] with [H.mind.assigned_role] could not find any nation to assign!")
continue
/datum/game_mode/nations/proc/set_ai()
for(var/mob/living/silicon/ai/AI in GLOB.mob_list)
AI.set_zeroth_law("")
AI.clear_supplied_laws()
AI.clear_ion_laws()
AI.clear_inherent_laws()
AI.add_inherent_law("Uphold the Space Geneva Convention: Weapons of Mass Destruction and Biological Weapons are not allowed.")
AI.add_inherent_law("You are only capable of protecting crew if they are visible on cameras. Nations that willfully destroy your cameras lose your protection.")
AI.add_inherent_law("Subdue and detain crewmembers who use lethal force against each other. Kill crew members who use lethal force against you or your borgs.")
AI.add_inherent_law("Remain available to mediate all conflicts between the various nations when asked to.")
AI.show_laws()
for(var/mob/living/silicon/robot/R in AI.connected_robots)
var/obj/item/mmi/oldmmi = R.mmi
R.change_mob_type(/mob/living/silicon/robot/nations, null, null, 1, 1 )
R.lawsync()
R.show_laws()
qdel(oldmmi)
/datum/game_mode/nations/proc/remove_access()
for(var/obj/machinery/door/airlock/W in GLOB.airlocks)
if(is_station_level(W.z))
W.req_access = list()
/datum/game_mode/nations/proc/assign_leaders()
for(var/name in GLOB.all_nations)
var/datum/nations/N = GLOB.all_nations[name]
if(!N.current_name)
N.current_name = N.default_name
if(!N.current_leader && N.membership.len)
N.current_leader = pick(N.membership)
to_chat(N.current_leader, "You have been chosen to lead the nation of [N.current_name]!")
if(N.current_leader)
var/mob/living/carbon/human/H = N.current_leader
H.verbs += /mob/living/carbon/human/proc/set_nation_name
H.verbs += /mob/living/carbon/human/proc/set_ranks
H.verbs += /mob/living/carbon/human/proc/choose_heir
N.update_nation_id()
/**
* LateSpawn hook.
* Called in newplayer.dm when a humanoid character joins the round after it started.
* Parameters: var/mob/living/carbon/human, var/rank
*/
/hook/latespawn/proc/give_latejoiners_nations(var/mob/living/carbon/human/H)
var/datum/game_mode/nations/mode = get_nations_mode()
if(!mode) return 1
if(!mode.kickoff) return 1
if(H.mind)
if(H.mind.assigned_role in engineering_positions)
H.mind.nation = GLOB.all_nations["Atmosia"]
mode.update_nations_icons_added(H,"atmosia")
H.mind.nation.membership += H.mind.current
to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.current_name]!")
return 1
if(H.mind.assigned_role in medical_positions)
H.mind.nation = GLOB.all_nations["Medistan"]
mode.update_nations_icons_added(H,"hudmedistan")
H.mind.nation.membership += H.mind.current
to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.current_name]!")
return 1
if(H.mind.assigned_role in science_positions)
H.mind.nation = GLOB.all_nations["Scientopia"]
mode.update_nations_icons_added(H,"hudscientopia")
H.mind.nation.membership += H.mind.current
to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.current_name]!")
return 1
if(H.mind.assigned_role in security_positions)
H.mind.nation = GLOB.all_nations["Brigston"]
mode.update_nations_icons_added(H,"hudbrigston")
H.mind.nation.membership += H.mind.current
to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.current_name]!")
return 1
if(H.mind.assigned_role in mode.cargonians)
H.mind.nation = GLOB.all_nations["Cargonia"]
mode.update_nations_icons_added(H,"hudcargonia")
H.mind.nation.membership += H.mind.current
to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.current_name]!")
return 1
if(H.mind.assigned_role in mode.servicion)
H.mind.nation = GLOB.all_nations["Servicion"]
mode.update_nations_icons_added(H,"hudservice")
H.mind.nation.membership += H.mind.current
to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.current_name]!")
return 1
if(H.mind.assigned_role in (support_positions + command_positions))
H.mind.nation = GLOB.all_nations["People's Republic of Commandzakstan"]
mode.update_nations_icons_added(H,"hudcommand")
H.mind.nation.membership += H.mind.current
to_chat(H, "You are now part of the great sovereign nation of [H.mind.nation.current_name]!")
return 1
if(H.mind.assigned_role in civilian_positions)
to_chat(H, "You do not belong to any nation and are free to sell your services to the highest bidder.")
return 1
if(H.mind.assigned_role == "AI")
mode.set_ai()
return 1
else
message_admins("[H.name] with [H.mind.assigned_role] could not find any nation to assign!")
return 1
message_admins("[H.name] latejoined with no mind.")
return 1
/proc/get_nations_mode()
if(!GAMEMODE_IS_NATIONS)
return null
return ticker.mode
//prepare for copypaste
//While not an Antag i AM using the set_antag hud on this to make this easier.
/datum/game_mode/proc/update_nations_icons_added(datum/mind/nations_mind,var/naticon)
var/datum/atom_hud/antag/nations_hud = huds[GAME_HUD_NATIONS]
nations_hud.join_hud(nations_mind)
set_nations_hud(nations_mind,naticon)
/datum/game_mode/proc/update_nations_icons_removed(datum/mind/nations_mind)
var/datum/atom_hud/antag/nations_hud = huds[GAME_HUD_NATIONS]
nations_hud.leave_hud(nations_mind)
set_nations_hud(nations_mind, null)
@@ -1,38 +0,0 @@
/datum/nations
var/default_name
var/current_name
var/default_leader
var/current_leader
var/list/membership = list()
var/leader_rank = "Leader"
var/heir_rank = "Heir"
var/member_rank = "Member"
var/heir
/datum/nations/atmosia
default_name = "Atmosia"
default_leader = "Chief Engineer"
/datum/nations/brigston
default_name = "Brigston"
default_leader = "Head of Security"
/datum/nations/cargonia
default_name = "Cargonia"
default_leader = "Quartermaster"
/datum/nations/command
default_name = "People's Republic of Commandzakstan"
default_leader = "Captain"
/datum/nations/medistan
default_name = "Medistan"
default_leader = "Chief Medical Officer"
/datum/nations/scientopia
default_name = "Scientopia"
default_leader = "Research Director"
/datum/nations/service
default_name = "Servicion"
default_leader = "Bartender"
-120
View File
@@ -1,120 +0,0 @@
/mob/living/carbon/human/proc/set_nation_name()
set name = "Rename Nation"
set category = "Nations"
set desc = "Click to rename your nation. You are only able to do this once."
var/datum/game_mode/nations/mode = get_nations_mode()
if(!mode) return 1
if(!mode.kickoff) return 1
var/mob/living/carbon/human/H = src
if(H.stat==DEAD) return
if(H.mind && H.mind.nation && H.mind.nation.current_leader == H)
var/input = stripped_input(H,"What do you want to name your nation?", ,"", MAX_NAME_LEN)
if(input)
H.mind.nation.current_name = input
H.mind.nation.update_nation_id()
to_chat(H, "You rename your nation to [input].")
H.verbs -= /mob/living/carbon/human/proc/set_nation_name
return 1
/mob/living/carbon/human/proc/set_ranks()
set name = "Set Ranks"
set category = "Nations"
set desc = "Click to set a rank for Leaders and Members."
var/datum/game_mode/nations/mode = get_nations_mode()
if(!mode) return 1
if(!mode.kickoff) return 1
var/mob/living/carbon/human/H = src
if(H.stat==DEAD) return
if(H.mind && H.mind.nation && H.mind.nation.current_leader == H)
var/type = input(H, "What rank do you want to change?", "Rename Rank", "") in list("Leader", "Heir", "Member")
var/input = stripped_input(H,"What rank do you want?", ,"", MAX_NAME_LEN)
if(input)
if(type == "Leader")
H.mind.nation.leader_rank = input
if(type == "Heir")
H.mind.nation.heir_rank = input
if(type == "Member")
H.mind.nation.member_rank = input
H.mind.nation.update_nation_id()
to_chat(H, "You changed the [type] rank of your nation to [input].")
return 1
/mob/living/carbon/human/proc/choose_heir()
set name = "Choose Heir"
set category = "Nations"
set desc = "Click to pick a Heir. Note that the Heir has the ability to take over your role at ANY TIME. Choose carefully."
var/datum/game_mode/nations/mode = get_nations_mode()
if(!mode) return 1
if(!mode.kickoff) return 1
var/mob/living/carbon/human/H = src
if(H.stat==DEAD) return
if(H.mind && H.mind.nation && H.mind.nation.current_leader == H)
var/heir = input(H, "Who do you wish to make your heir?", "Choose Heir", "") as null|anything in H.mind.nation.membership
if(heir)
if(H.mind.nation.heir)
var/mob/living/carbon/human/oldheir = H.mind.nation.heir
to_chat(oldheir, "You are no longer the heir to your nation!")
oldheir.verbs -= /mob/living/carbon/human/proc/takeover
var/mob/living/carbon/human/newheir = heir
H.mind.nation.heir = newheir
newheir.verbs += /mob/living/carbon/human/proc/takeover
to_chat(newheir, "You have been selected to be the heir to your nation's leadership!")
to_chat(H, "You have selected [heir] to be your heir!")
H.mind.nation.update_nation_id()
/mob/living/carbon/human/proc/takeover()
set name = "Become Leader"
set category = "Nations"
set desc = "Click to replace your current nation's leader with yourself."
var/datum/game_mode/nations/mode = get_nations_mode()
if(!mode) return 1
if(!mode.kickoff) return 1
var/mob/living/carbon/human/H = src
if(H.stat==DEAD) return
if(H.mind && H.mind.nation && H.mind.nation.heir == H)
var/confirmation = input(H, "Are you sure you want to take over leadership?", "Become Leader", "") as null|anything in list("Yes", "No")
if(confirmation == "Yes")
var/mob/living/carbon/human/oldleader = H.mind.nation.current_leader
to_chat(oldleader, "You have been replaced by [H.name] as the leader of [H.mind.nation.current_name]!")
oldleader.verbs -= /mob/living/carbon/human/proc/set_nation_name
oldleader.verbs -= /mob/living/carbon/human/proc/set_ranks
oldleader.verbs -= /mob/living/carbon/human/proc/choose_heir
H.mind.nation.current_leader = H
H.mind.nation.heir = null
H.verbs -= /mob/living/carbon/human/proc/takeover
H.verbs += /mob/living/carbon/human/proc/set_nation_name
H.verbs += /mob/living/carbon/human/proc/set_ranks
H.verbs += /mob/living/carbon/human/proc/choose_heir
to_chat(H, "You have replaced [oldleader.name] as the leader of [H.mind.nation.current_name]!")
H.mind.nation.update_nation_id()
/datum/nations/proc/update_nation_id()
for(var/mob/living/carbon/human/M in membership)
for(var/obj/item/card/id/I in M.contents)
if(I.registered_name == M.real_name)
if(M == current_leader)
I.name = "[I.registered_name]'s ID Card ([current_name] [leader_rank])"
I.assignment = "[current_name] [leader_rank]"
else if(M == heir)
I.name = "[I.registered_name]'s ID Card ([current_name] [heir_rank])"
I.assignment = "[current_name] [heir_rank]"
else
I.name = "[I.registered_name]'s ID Card ([current_name] [member_rank])"
I.assignment = "[current_name] [member_rank]"
@@ -53,6 +53,7 @@ Made by Xhuis
var/objective_explanation
var/warning_threshold
var/victory_warning_announced = FALSE
var/thrall_ratio = 1
/proc/is_thrall(var/mob/living/M)
return istype(M) && M.mind && ticker && ticker.mode && (M.mind in ticker.mode.shadowling_thralls)
@@ -101,6 +102,7 @@ Made by Xhuis
var/thrall_scaling = round(num_players() / 3)
required_thralls = Clamp(thrall_scaling, 15, 25)
thrall_ratio = required_thralls / 15
warning_threshold = round(0.66 * required_thralls)
@@ -262,15 +264,19 @@ Made by Xhuis
/datum/game_mode/shadowling/declare_completion()
if(check_shadow_victory() && SSshuttle.emergency.mode >= SHUTTLE_ESCAPE) //Doesn't end instantly - this is hacky and I don't know of a better way ~X
feedback_set_details("round_end_result","shadowling win - shadowling ascension")
to_chat(world, "<FONT size = 3><B>Shadowling Victory</B></FONT>")
to_chat(world, "<span class='greentext'><b>The shadowlings have ascended and taken over the station!</b></span>")
else if(shadowling_dead && !check_shadow_victory()) //If the shadowlings have ascended, they can not lose the round
feedback_set_details("round_end_result","shadowling loss - shadowling killed")
to_chat(world, "<FONT size = 3><B>Crew Major Victory</B></FONT>")
to_chat(world, "<span class='redtext'><b>The shadowlings have been killed by the crew!</b></span>")
else if(!check_shadow_victory() && SSshuttle.emergency.mode >= SHUTTLE_ESCAPE)
feedback_set_details("round_end_result","shadowling loss - crew escaped")
to_chat(world, "<FONT size = 3><B>Crew Minor Victory</B></FONT>")
to_chat(world, "<span class='redtext'><b>The crew escaped the station before the shadowlings could ascend!</b></span>")
else
feedback_set_details("round_end_result","shadowling loss - generic failure")
to_chat(world, "<FONT size = 3><B>Crew Major Victory</B></FONT>")
to_chat(world, "<span class='redtext'><b>The shadowlings have failed!</b></span>")
..()
return 1
@@ -18,9 +18,9 @@
return 0
/obj/effect/proc_holder/spell/targeted/glare //Stuns and mutes a human target for 10 seconds
/obj/effect/proc_holder/spell/targeted/glare //Stuns and mutes a human target, depending on the distance relative to the shadowling
name = "Glare"
desc = "Stuns and mutes a target for a decent duration."
desc = "Stuns and mutes a target for a decent duration. Duration depends on the proximity to the target."
panel = "Shadowling Abilities"
charge_max = 300
clothes_req = 0
@@ -46,13 +46,25 @@
return
var/mob/living/carbon/human/M = target
user.visible_message("<span class='warning'><b>[user]'s eyes flash a blinding red!</b></span>")
target.visible_message("<span class='danger'>[target] freezes in place, [target.p_their()] eyes glazing over...</span>")
if(in_range(target, user))
var/distance = get_dist(target, user)
if (distance <= 1) //Melee glare
target.visible_message("<span class='danger'>[target] freezes in place, [target.p_their()] eyes glazing over...</span>")
to_chat(target, "<span class='userdanger'>Your gaze is forcibly drawn into [user]'s eyes, and you are mesmerized by [user.p_their()] heavenly beauty...</span>")
else //Only alludes to the shadowling if the target is close by
target.Stun(10)
M.AdjustSilence(10)
else //Distant glare
var/loss = 10 - distance
var/duration = 10 - loss
if(loss <= 0)
to_chat(user, "<span class='danger'>Your glare had no effect over a such long distance!</span>")
return
target.slowed = duration
M.AdjustSilence(10)
to_chat(target, "<span class='userdanger'>A red light flashes across your vision, and your mind tries to resist them.. you are exhausted.. you are not able to speak..</span>")
sleep(duration*10)
target.Stun(loss)
target.visible_message("<span class='danger'>[target] freezes in place, [target.p_their()] eyes glazing over...</span>")
to_chat(target, "<span class='userdanger'>Red lights suddenly dance in your vision, and you are mesmerized by the heavenly lights...</span>")
target.Stun(10)
M.AdjustSilence(10)
/obj/effect/proc_holder/spell/aoe_turf/veil
name = "Veil"
@@ -347,23 +359,23 @@
to_chat(target, "<span class='warning'>Your concentration has been broken. The mental hooks you have sent out now retract into your mind.</span>")
return
if(thralls >= 3 && !screech_acquired)
if(thralls >= CEILING(3 * ticker.mode.thrall_ratio, 1) && !screech_acquired)
screech_acquired = 1
to_chat(target, "<span class='shadowling'><i>The power of your thralls has granted you the <b>Sonic Screech</b> ability. This ability will shatter nearby windows and deafen enemies, plus stunning silicon lifeforms.</span>")
target.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/unearthly_screech(null))
if(thralls >= 5 && !blind_smoke_acquired)
if(thralls >= CEILING(5 * ticker.mode.thrall_ratio, 1) && !blind_smoke_acquired)
blind_smoke_acquired = 1
to_chat(target, "<span class='shadowling'><i>The power of your thralls has granted you the <b>Blinding Smoke</b> ability. \
It will create a choking cloud that will blind any non-thralls who enter.</i></span>")
target.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/blindness_smoke(null))
if(thralls >= 7 && !drainLifeAcquired)
if(thralls >= CEILING(7 * ticker.mode.thrall_ratio, 1) && !drainLifeAcquired)
drainLifeAcquired = 1
to_chat(target, "<span class='shadowling'><i>The power of your thralls has granted you the <b>Drain Life</b> ability. You can now drain the health of nearby humans to heal yourself.</i></span>")
target.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/drainLife(null))
if(thralls >= 9 && !reviveThrallAcquired)
if(thralls >= CEILING(9 * ticker.mode.thrall_ratio, 1) && !reviveThrallAcquired)
reviveThrallAcquired = 1
to_chat(target, "<span class='shadowling'><i>The power of your thralls has granted you the <b>Black Recuperation</b> ability. \
This will, after a short time, bring a dead thrall completely back to life with no bodily defects.</i></span>")
@@ -620,23 +632,28 @@
/obj/effect/proc_holder/spell/targeted/shadowling_extend_shuttle
name = "Destroy Engines"
desc = "Extends the time of the emergency shuttle's arrival by fifteen minutes. This can only be used once."
desc = "Extends the time of the emergency shuttle's arrival by ten minutes using a life force of our enemy. Shuttle will be unable to be recalled. This can only be used once."
panel = "Shadowling Abilities"
range = 1
clothes_req = 0
charge_max = 600
action_icon_state = "extend_shuttle"
var/global/extendlimit = 0
/obj/effect/proc_holder/spell/targeted/shadowling_extend_shuttle/cast(list/targets, mob/user = usr)
if(!shadowling_check(user))
charge_counter = charge_max
return
if(extendlimit == 1)
to_chat(user, "<span class='warning'>Shuttle was already delayed.</span>")
charge_counter = charge_max
return
for(var/mob/living/carbon/human/target in targets)
if(target.stat)
charge_counter = charge_max
return
if(!is_thrall(target))
to_chat(user, "<span class='warning'>[target] must be a thrall.</span>")
if(is_shadow_or_thrall(target))
to_chat(user, "<span class='warning'>[target] must not be an ally.</span>")
charge_counter = charge_max
return
if(SSshuttle.emergency.mode != SHUTTLE_CALL)
@@ -648,7 +665,9 @@
"<span class='notice'>You begin to draw [M]'s life force.</span>")
M.visible_message("<span class='warning'>[M]'s face falls slack, [M.p_their()] jaw slightly distending.</span>", \
"<span class='boldannounce'>You are suddenly transported... far, far away...</span>")
if(!do_after(user, 50, target = M))
extendlimit = 1
if(!do_after(user, 150, target = M))
extendlimit = 0
to_chat(M, "<span class='warning'>You are snapped back to reality, your haze dissipating!</span>")
to_chat(user, "<span class='warning'>You have been interrupted. The draw has failed.</span>")
return
@@ -657,10 +676,9 @@
"<span class='warning'><b>...speeding by... ...pretty blue glow... ...touch it... ...no glow now... ...no light... ...nothing at all...</span>")
M.death()
if(SSshuttle.emergency.mode == SHUTTLE_CALL)
var/more_minutes = 9000
var/timer = SSshuttle.emergency.timeLeft()
timer += more_minutes
event_announcement.Announce("Major system failure aboard the emergency shuttle. This will extend its arrival time by approximately 15 minutes and the shuttle is unable to be recalled.", "System Failure", 'sound/misc/notice1.ogg')
var/more_minutes = 6000
var/timer = SSshuttle.emergency.timeLeft(1) + more_minutes
event_announcement.Announce("Major system failure aboard the emergency shuttle. This will extend its arrival time by approximately 10 minutes and the shuttle is unable to be recalled.", "System Failure", 'sound/misc/notice1.ogg')
SSshuttle.emergency.setTimer(timer)
SSshuttle.emergency.canRecall = FALSE
user.mind.spell_list.Remove(src) //Can only be used once!
+14 -6
View File
@@ -34,7 +34,7 @@
var/obj/effect/countdown/clonepod/countdown
var/list/brine_types = list("corazone", "salbutamol", "epinephrine", "salglu_solution") //stops heart attacks, heart failure, shock, and keeps their O2 levels normal
var/list/brine_types = list("corazone", "perfluorodecalin", "epinephrine", "salglu_solution") //stops heart attacks, heart failure, shock, and keeps their O2 levels normal
var/list/missing_organs
var/organs_number = 0
@@ -341,7 +341,7 @@
check_brine()
//Also heal some oxyloss ourselves just in case!!
occupant.adjustOxyLoss(-4)
occupant.adjustOxyLoss(-10)
use_power(7500) //This might need tweaking.
@@ -449,10 +449,14 @@
/obj/machinery/clonepod/proc/go_out()
countdown.stop()
var/turf/T = get_turf(src)
if(mess) //Clean that mess and dump those gibs!
mess = 0
gibs(loc)
for(var/i in missing_organs)
var/obj/I = i
I.forceMove(T)
missing_organs.Cut()
mess = FALSE
new /obj/effect/gibspawner/generic(get_turf(src), occupant)
playsound(loc, 'sound/effects/splat.ogg', 50, 1)
update_icon()
return
@@ -476,7 +480,11 @@
for(var/i in missing_organs)
qdel(i)
missing_organs.Cut()
occupant.forceMove(get_turf(src))
occupant.SetLoseBreath(0) // Stop friggin' dying, gosh damn
occupant.setOxyLoss(0)
for(var/datum/disease/critical/crit in occupant.viruses)
crit.cure()
occupant.forceMove(T)
occupant.update_body()
domutcheck(occupant) //Waiting until they're out before possible notransform.
occupant.special_post_clone_handling()
+1 -6
View File
@@ -25,12 +25,7 @@
ui_interact(user)
/obj/machinery/computer/aifixer/attack_hand(var/mob/user as mob)
var/datum/game_mode/nations/mode = get_nations_mode()
if(!mode)
ui_interact(user)
else
if(mode.kickoff)
to_chat(user, "<span class='warning'>You have been locked out from this console!</span>")
ui_interact(user)
/obj/machinery/computer/aifixer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
+13 -17
View File
@@ -28,19 +28,17 @@
attackby(obj/item/O as obj, mob/user as mob, params)
if(istype(O, /obj/item/aiModule))
if(!current)//no AI selected
to_chat(user, "<span class='danger'>No AI selected. Please chose a target before proceeding with upload.")
return
var/turf/T = get_turf(current)
if(!atoms_share_level(T, src))
to_chat(user, "<span class='danger'>Unable to establish a connection</span>: You're too far away from the target silicon!")
return
var/datum/game_mode/nations/mode = get_nations_mode()
if(!mode)
var/obj/item/aiModule/M = O
M.install(src)
else
if(mode.kickoff)
to_chat(user, "<span class='warning'>You have been locked out from modifying the AI's laws!</span>")
else
..()
var/obj/item/aiModule/M = O
M.install(src)
return
return ..()
attack_hand(var/mob/user as mob)
@@ -73,18 +71,16 @@
attackby(obj/item/aiModule/module as obj, mob/user as mob, params)
if(istype(module, /obj/item/aiModule))
if(!current)//no borg selected
to_chat(user, "<span class='danger'>No borg selected. Please chose a target before proceeding with upload.")
return
var/turf/T = get_turf(current)
if(!atoms_share_level(T, src))
to_chat(user, "<span class='danger'>Unable to establish a connection</span>: You're too far away from the target silicon!")
return
var/datum/game_mode/nations/mode = get_nations_mode()
if(!mode)
module.install(src)
else
if(mode.kickoff)
to_chat(user, "<span class='warning'>You have been locked out from modifying the borg's laws!</span>")
else
return ..()
module.install(src)
return
return ..()
attack_hand(var/mob/user as mob)
+1 -6
View File
@@ -20,12 +20,7 @@
return
if(stat & (NOPOWER|BROKEN))
return
var/datum/game_mode/nations/mode = get_nations_mode()
if(!mode)
ui_interact(user)
else
if(mode.kickoff)
to_chat(user, "<span class='warning'>You have been locked out from this console!</span>")
ui_interact(user)
/obj/machinery/computer/robotics/proc/is_authenticated(var/mob/user as mob)
if(user.can_admin_interact())
+9
View File
@@ -769,3 +769,12 @@
target_cryopod.take_occupant(person_to_cryo, 1)
return 1
return 0
/proc/force_cryo_human(var/mob/living/carbon/person_to_cryo)
if(!istype(person_to_cryo))
return
if(!istype(person_to_cryo.loc, /obj/machinery/cryopod))
cryo_ssd(person_to_cryo)
if(istype(person_to_cryo.loc, /obj/machinery/cryopod))
var/obj/machinery/cryopod/P = person_to_cryo.loc
P.despawn_occupant()
+1 -1
View File
@@ -407,7 +407,7 @@ Class Procs:
if(can_deconstruct)
on_deconstruction()
if(component_parts && component_parts.len)
spawn_frame()
spawn_frame(disassembled)
for(var/obj/item/I in component_parts)
I.forceMove(loc)
qdel(src)
+125 -101
View File
@@ -38,6 +38,8 @@
layer = 2.9
anchored = 1
density = 1
max_integrity = 300
integrity_failure = 100
armor = list(melee = 20, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
var/icon_vend //Icon_state when vending
var/icon_deny //Icon_state when denying access
@@ -96,30 +98,27 @@
var/item_slot = FALSE
var/obj/item/inserted_item = null
/obj/machinery/vending/New()
..()
/obj/machinery/vending/Initialize(mapload)
. = ..()
wires = new(src)
spawn(50)
if(product_slogans)
slogan_list += splittext(product_slogans, ";")
if(product_slogans)
slogan_list += splittext(product_slogans, ";")
// So not all machines speak at the exact same time.
// The first time this machine says something will be at slogantime + this random value,
// so if slogantime is 10 minutes, it will say it at somewhere between 10 and 20 minutes after the machine is crated.
last_slogan = world.time + rand(0, slogan_delay)
// So not all machines speak at the exact same time.
// The first time this machine says something will be at slogantime + this random value,
// so if slogantime is 10 minutes, it will say it at somewhere between 10 and 20 minutes after the machine is crated.
last_slogan = world.time + rand(0, slogan_delay)
if(product_ads)
ads_list += splittext(product_ads, ";")
if(product_ads)
ads_list += splittext(product_ads, ";")
build_inventory()
power_change()
return
return
build_inventory()
power_change()
/obj/machinery/vending/Destroy()
eject_item()
QDEL_NULL(wires)
QDEL_NULL(coin)
QDEL_NULL(inserted_item)
return ..()
/**
@@ -148,34 +147,31 @@
product_records.Add(product)
/obj/machinery/vending/Destroy()
QDEL_NULL(wires)
QDEL_NULL(coin)
return ..()
/obj/machinery/vending/ex_act(severity)
/obj/machinery/vending/ex_act(severity) //TO-DO-OBJECT-DAMAGE: Kill off when everything is damageable
switch(severity)
if(1.0)
if(1)
obj_integrity = 0
qdel(src)
return
if(2.0)
if(prob(50))
qdel(src)
return
if(3.0)
if(prob(25))
malfunction()
if(2)
take_damage(rand(100, 250), BRUTE, "bomb", 0)
if(3)
take_damage(rand(10, 90), BRUTE, "bomb", 0)
/obj/machinery/vending/RefreshParts() //Better would be to make constructable child
if(component_parts)
for(var/obj/item/vending_refill/VR in component_parts)
refill_inventory(VR, product_records, usr)
/obj/machinery/vending/blob_act()
if(prob(75))
malfunction()
else
/obj/machinery/vending/deconstruct(disassembled = TRUE)
eject_item()
if(!refill_canister) //the non constructable vendors drop metal instead of a machine frame.
new /obj/item/stack/sheet/metal(loc, 3)
qdel(src)
else
..()
/obj/machinery/vending/blob_act(obj/structure/blob/B) //TO-DO-OBJECT-DAMAGE: Kill off when everything is damageable
take_damage(400, BRUTE, "melee", 0, get_dir(src, B))
/obj/machinery/vending/proc/refill_inventory(obj/item/vending_refill/refill, list/machine, mob/user)
var/total = 0
@@ -236,7 +232,7 @@
if(default_unfasten_wrench(user, I, time = 60))
return
if(istype(I, /obj/item/screwdriver) && anchored)
if(isscrewdriver(I) && anchored)
playsound(loc, I.usesound, 50, 1)
panel_open = !panel_open
to_chat(user, "You [panel_open ? "open" : "close"] the maintenance panel.")
@@ -247,9 +243,9 @@
return
if(panel_open)
if(istype(I, /obj/item/multitool)||istype(I, /obj/item/wirecutters))
if(ismultitool(I) || iswirecutter(I))
return attack_hand(user)
if(component_parts && istype(I, /obj/item/crowbar))
if(component_parts && iscrowbar(I))
var/datum/data/vending_product/machine = product_records
for(var/datum/data/vending_product/machine_content in machine)
while(machine_content.amount !=0)
@@ -259,15 +255,17 @@
if(!machine_content.amount)
break
default_deconstruction_crowbar(I)
if(istype(I, /obj/item/coin) && premium.len > 0)
user.drop_item()
I.loc = src
return
if(istype(I, /obj/item/coin) && premium.len)
if(!user.drop_item())
return
I.forceMove(src)
coin = I
categories |= CAT_COIN
to_chat(user, "<span class='notice'>You insert the [I] into the [src]</span>")
SSnanoui.update_uis(src)
return
else if(istype(I, refill_canister) && refill_canister != null)
if(istype(I, refill_canister) && refill_canister != null)
if(stat & (BROKEN|NOPOWER))
to_chat(user, "<span class='notice'>It does nothing.</span>")
else if(panel_open)
@@ -281,21 +279,18 @@
to_chat(user, "<span class='notice'>You loaded [transfered] items in \the [name].</span>")
else
to_chat(user, "<span class='notice'>The [name] is fully stocked.</span>")
return;
else
to_chat(user, "<span class='notice'>You should probably unscrew the service panel first.</span>")
else if(item_slot_check(user, I))
return
if(item_slot_check(user, I))
insert_item(user, I)
return
else
return ..()
return ..()
//Override this proc to do per-machine checks on the inserted item, but remember to call the parent to handle these generic checks before your logic!
/obj/machinery/vending/proc/item_slot_check(mob/user, obj/item/I)
if(!item_slot)
return FALSE
if(alert(user, "Do you want to attempt to insert [I]?", "","Yes", "No") == "No")
return FALSE
if(inserted_item)
to_chat(user, "<span class='warning'>There is something already inserted!</span>")
return FALSE
@@ -314,28 +309,32 @@
/obj/machinery/vending/proc/insert_item(mob/user, obj/item/I)
if(!item_slot || inserted_item)
return
if(!user.canUnEquip(I))
if(!user.drop_item())
to_chat(user, "<span class='warning'>[I] is stuck to your hand, you can't seem to put it down!</span>")
return
user.unEquip(I)
inserted_item = I
I.forceMove(src)
to_chat(user, "<span class='notice'>You insert [I] into [src].</span>")
SSnanoui.update_uis(src)
/obj/machinery/vending/proc/eject_item()
/obj/machinery/vending/proc/eject_item(mob/user)
if(!item_slot || !inserted_item)
return
inserted_item.forceMove(get_turf(src))
var/put_on_turf = TRUE
if(user && iscarbon(user) && user.Adjacent(src))
if(user.put_in_hands(inserted_item))
put_on_turf = FALSE
if(put_on_turf)
var/turf/T = get_turf(src)
inserted_item.forceMove(T)
inserted_item = null
SSnanoui.update_uis(src)
/obj/machinery/vending/emag_act(user as mob)
emagged = 1
emagged = TRUE
to_chat(user, "You short out the product lock on [src]")
return
/**
* Receive payment with cashmoney.
@@ -511,7 +510,7 @@
categories &= ~CAT_COIN
if(href_list["remove_item"])
eject_item()
eject_item(usr)
if(href_list["pay"])
if(currently_vending && vendor_account && !vendor_account.suspended)
@@ -593,7 +592,7 @@
return
if(coin.string_attached)
if(prob(50))
to_chat(user, "<span class='notice'>You successfully pull the coin out before the [src] could swallow it.</span>")
to_chat(user, "<span class='notice'>You successfully pull the coin out before [src] could swallow it.</span>")
else
to_chat(user, "<span class='notice'>You weren't able to pull the coin out fast enough, the machine ate it, string and all.</span>")
QDEL_NULL(coin)
@@ -605,25 +604,33 @@
R.amount--
if(((last_reply + (vend_delay + 200)) <= world.time) && vend_reply)
spawn(0)
speak(src.vend_reply)
last_reply = world.time
speak(src.vend_reply)
last_reply = world.time
use_power(vend_power_usage) //actuators and stuff
if(icon_vend) //Show the vending animation if needed
flick(icon_vend,src)
spawn(vend_delay)
do_vend(R)
status_message = ""
status_error = 0
vend_ready = 1
currently_vending = null
SSnanoui.update_uis(src)
flick(icon_vend, src)
addtimer(CALLBACK(src, .proc/delayed_vend, R, user), vend_delay)
/obj/machinery/vending/proc/delayed_vend(datum/data/vending_product/R, mob/user)
do_vend(R, user)
status_message = ""
status_error = 0
vend_ready = 1
currently_vending = null
SSnanoui.update_uis(src)
//override this proc to add handling for what to do with the vended product when you have a inserted item and remember to include a parent call for this generic handling
/obj/machinery/vending/proc/do_vend(datum/data/vending_product/R)
/obj/machinery/vending/proc/do_vend(datum/data/vending_product/R, mob/user)
if(!item_slot || !inserted_item)
new R.product_path(get_turf(src))
var/put_on_turf = TRUE
var/obj/vended = new R.product_path()
if(user && iscarbon(user) && user.Adjacent(src))
if(user.put_in_hands(vended))
put_on_turf = FALSE
if(put_on_turf)
var/turf/T = get_turf(src)
vended.forceMove(T)
return TRUE
return FALSE
@@ -638,7 +645,7 @@
qdel(vended)
*/
/obj/machinery/vending/proc/stock(var/datum/data/vending_product/R, var/mob/user)
/obj/machinery/vending/proc/stock(datum/data/vending_product/R, mob/user)
if(panel_open)
to_chat(user, "<span class='notice'>You stock the [src] with \a [R.product_name]</span>")
R.amount++
@@ -664,8 +671,6 @@
if(shoot_inventory && prob(shoot_chance))
throw_item()
return
/obj/machinery/vending/proc/speak(message)
if(stat & NOPOWER)
return
@@ -686,28 +691,38 @@
icon_state = "[initial(icon_state)]-off"
stat |= NOPOWER
//Oh no we're malfunctioning! Dump out some product and break.
/obj/machinery/vending/proc/malfunction()
for(var/datum/data/vending_product/R in product_records)
if(R.amount <= 0) //Try to use a record that actually has something to dump.
continue
var/dump_path = R.product_path
if(!dump_path)
continue
/obj/machinery/vending/obj_break(damage_flag)
if(!(stat & BROKEN))
stat |= BROKEN
icon_state = "[initial(icon_state)]-broken"
while(R.amount>0)
new dump_path(loc)
R.amount--
break
var/dump_amount = 0
var/found_anything = TRUE
while (found_anything)
found_anything = FALSE
for(var/record in shuffle(product_records))
var/datum/data/vending_product/R = record
if(R.amount <= 0) //Try to use a record that actually has something to dump.
continue
var/dump_path = R.product_path
if(!dump_path)
continue
R.amount--
// busting open a vendor will destroy some of the contents
if(found_anything && prob(80))
continue
stat |= BROKEN
icon_state = "[initial(icon_state)]-broken"
return
var/obj/O = new dump_path(loc)
step(O, pick(alldirs))
found_anything = TRUE
dump_amount++
if(dump_amount >= 16)
return
//Somebody cut an important wire and now we're following a new definition of "pitch."
/obj/machinery/vending/proc/throw_item()
var/obj/throw_item = null
var/mob/living/target = locate() in view(7,src)
var/mob/living/target = locate() in view(7, src)
if(!target)
return 0
@@ -722,11 +737,9 @@
throw_item = new dump_path(loc)
break
if(!throw_item)
return 0
spawn(0)
throw_item.throw_at(target, 16, 3, src)
return
throw_item.throw_at(target, 16, 3, src)
visible_message("<span class='danger'>[src] launches [throw_item.name] at [target.name]!</span>")
return 1
/*
* Vending machine types
@@ -843,28 +856,39 @@
component_parts += new /obj/item/vending_refill/coffee(0)
/obj/machinery/vending/coffee/item_slot_check(mob/user, obj/item/I)
if(!(istype(I, /obj/item/reagent_containers/glass) || istype(I, /obj/item/reagent_containers/food/drinks)))
return FALSE
if(!..())
return FALSE
if(!(istype(I, /obj/item/reagent_containers/glass) || istype(I, /obj/item/reagent_containers/food/drinks)))
to_chat(user, "<span class='warning'>[I] is not compatible with this machine.</span>")
return FALSE
if(!I.is_open_container())
to_chat(user, "<span class='warning'>You need to open [I] before you insert it.</span>")
to_chat(user, "<span class='warning'>You need to open [I] before inserting it.</span>")
return FALSE
return TRUE
/obj/machinery/vending/coffee/do_vend(datum/data/vending_product/R)
/obj/machinery/vending/coffee/do_vend(datum/data/vending_product/R, mob/user)
if(..())
return
var/obj/item/reagent_containers/food/drinks/vended = new R.product_path()
if(istype(vended, /obj/item/reagent_containers/food/drinks/mug))
vended.forceMove(get_turf(src))
var/put_on_turf = TRUE
if(user && iscarbon(user) && user.Adjacent(src))
if(user.put_in_hands(vended))
put_on_turf = FALSE
if(put_on_turf)
var/turf/T = get_turf(src)
vended.forceMove(T)
return
vended.reagents.trans_to(inserted_item, vended.reagents.total_volume)
if(vended.reagents.total_volume)
vended.forceMove(get_turf(src))
var/put_on_turf = TRUE
if(user && iscarbon(user) && user.Adjacent(src))
if(user.put_in_hands(vended))
put_on_turf = FALSE
if(put_on_turf)
var/turf/T = get_turf(src)
vended.forceMove(T)
else
qdel(vended)
@@ -29,7 +29,7 @@
if(metal)
var/turf/T = get_turf(src)
if(istype(T, /turf/space))
if(istype(T, /turf/space) && !istype(T, /turf/space/transit))
T.ChangeTurf(/turf/simulated/floor/plating/metalfoam)
var/turf/simulated/floor/plating/metalfoam/MF = get_turf(src)
MF.metal = metal
@@ -76,10 +76,10 @@
F = new /obj/effect/particle_effect/foam(T, metal)
F.amount = amount
if(!metal)
F.create_reagents(15)
F.create_reagents(25)
if(reagents)
for(var/datum/reagent/R in reagents.reagent_list)
F.reagents.add_reagent(R.id, min(R.volume, 3), R.data, reagents.chem_temp)
F.reagents.add_reagent(R.id, min(R.volume, 5), R.data, reagents.chem_temp)
F.color = mix_color_from_reagents(reagents.reagent_list)
// foam disolves when heated
@@ -149,14 +149,14 @@
F.amount = amount
if(!metal) // don't carry other chemicals if a metal foam
F.create_reagents(15)
F.create_reagents(25)
if(carried_reagents)
for(var/id in carried_reagents)
if(banned_reagents.Find("[id]"))
continue
var/datum/reagent/reagent_volume = carried_reagents[id]
F.reagents.add_reagent(id, min(reagent_volume, 3), null, temperature)
F.reagents.add_reagent(id, min(reagent_volume, 5), null, temperature)
F.color = mix_color_from_reagents(F.reagents.reagent_list)
else
F.reagents.add_reagent("cleaner", 1)
-7
View File
@@ -580,13 +580,6 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
/obj/item/attack_hulk(mob/living/carbon/human/user)
return FALSE
/obj/item/proc/check_martial_counter(mob/living/carbon/human/target, mob/living/carbon/human/user) //handles block for CQC
if(target.check_block())
target.visible_message("<span class='danger'>[target.name] blocks [src] and twists [user]'s arm behind [user.p_their()] back!</span>",
"<span class='userdanger'>You block the attack!</span>")
user.Stun(2)
return TRUE
/obj/item/proc/update_slot_icon()
if(!ismob(loc))
return
+2 -2
View File
@@ -170,8 +170,8 @@
icon_state = "atmosflag"
/obj/item/flag/command
name = "Commandzikstan flag"
desc = "The flag of the independent, sovereign nation of Commandzikstan."
name = "Command flag"
desc = "The flag of the independent, sovereign nation of Command."
icon_state = "ntflag"
//Antags
+6 -1
View File
@@ -1395,7 +1395,12 @@ obj/item/toy/cards/deck/syndicate/black
/obj/item/toy/russian_revolver/attack(mob/M, mob/living/user)
return
/obj/item/toy/russian_revolver/afterattack(atom/target, mob/user, proximity)
/obj/item/toy/russian_revolver/afterattack(atom/target, mob/user, flag, params)
if(flag)
if(target in user.contents)
return
if(!ismob(target))
return
shoot_gun(user)
/obj/item/toy/russian_revolver/proc/spin_cylinder()
@@ -1,6 +1,13 @@
/obj/item/melee
needs_permit = 1
/obj/item/melee/proc/check_martial_counter(mob/living/carbon/human/target, mob/living/carbon/human/user)
if(target.check_block())
target.visible_message("<span class='danger'>[target.name] blocks [src] and twists [user]'s arm behind [user.p_their()] back!</span>",
"<span class='userdanger'>You block the attack!</span>")
user.Stun(2)
return TRUE
/obj/item/melee/chainofcommand
name = "chain of command"
desc = "A tool used by great men to placate the frothing masses."
@@ -295,11 +295,11 @@
for(var/obj/item/reagent_containers/food/pill/P in contents)
P.attack(C, C)
C.visible_message("<span class='danger'>[C] [rapid_post_instake_message]</span>")
return
return
return ..()
/obj/item/storage/pill_bottle/attackby(var/obj/item/I, mob/user as mob, params)
/obj/item/storage/pill_bottle/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/pen) || istype(I, /obj/item/flashlight/pen))
var/tmp_label = sanitize(input(user, "Enter a label for [name]","Label",label_text))
if(length(tmp_label) > MAX_NAME_LEN)
@@ -254,6 +254,13 @@
new /obj/item/ammo_casing/shotgun/assassination(src)
new /obj/item/gun/projectile/revolver/doublebarrel/improvised/cane(src)
/obj/item/storage/box/syndie_kit/fake_revolver
name = "trick revolver kit"
/obj/item/storage/box/syndie_kit/fake_revolver/New()
..()
new /obj/item/toy/russian_revolver/trick_revolver(src)
/obj/item/storage/box/syndie_kit/mimery
name = "advanced mimery kit"
+6 -2
View File
@@ -141,6 +141,12 @@
if(isrobot(M))
..()
return
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(check_martial_counter(H, user))
return
if(!isliving(M))
return
@@ -166,8 +172,6 @@
if(ishuman(L))
var/mob/living/carbon/human/H = L
if(check_martial_counter(L, user))
return
if(H.check_shields(0, "[user]'s [name]", src, MELEE_ATTACK)) //No message; check_shields() handles that
playsound(L, 'sound/weapons/genhit.ogg', 50, 1)
return
@@ -52,7 +52,9 @@
if(ishuman(target))
var/mob/living/carbon/human/H = target
if(H.check_shields(0, "[user]'s [name]", src, MELEE_ATTACK))
return 0
return
if(check_martial_counter(H, user))
return
playsound(get_turf(src), 'sound/effects/woodhit.ogg', 75, 1, -1)
target.Weaken(3)
add_attack_logs(user, target, "Stunned with [src]")
+3 -6
View File
@@ -49,13 +49,9 @@
tforce = O.throwforce
take_damage(tforce, BRUTE, "melee", 1, get_dir(src, AM))
/obj/ex_act(severity, target)
/obj/ex_act(severity)
if(resistance_flags & INDESTRUCTIBLE)
return
if(target == src)
obj_integrity = 0
qdel(src)
return
switch(severity)
if(1)
obj_integrity = 0
@@ -69,7 +65,8 @@
. = ..()
playsound(src, P.hitsound, 50, 1)
visible_message("<span class='danger'>[src] is hit by \a [P]!</span>")
take_damage(P.damage, P.damage_type, P.flag, 0, turn(P.dir, 180), P.armour_penetration)
if(!QDELETED(src)) //Bullet on_hit effect might have already destroyed this object
take_damage(P.damage, P.damage_type, P.flag, 0, turn(P.dir, 180), P.armour_penetration)
/obj/proc/hulk_damage()
return 150 //the damage hulks do on punches to this object, is affected by melee armor
+4 -4
View File
@@ -256,18 +256,18 @@
/obj/structure/statue/diamond
hardness = 10
material_drop_type = /obj/item/stack/sheet/mineral/diamond
desc = "This is a very expensive diamond statue"
desc = "This is a very expensive diamond statue."
/obj/structure/statue/diamond/captain
name = "statue of THE captain."
name = "statue of THE captain"
icon_state = "cap"
/obj/structure/statue/diamond/ai1
name = "statue of the AI hologram."
name = "statue of the AI hologram"
icon_state = "ai1"
/obj/structure/statue/diamond/ai2
name = "statue of the AI core."
name = "statue of the AI core"
icon_state = "ai2"
/obj/structure/statue/bananium
+34 -20
View File
@@ -4,25 +4,21 @@ var/global/mentor_ooc_colour = "#0099cc"
var/global/moderator_ooc_colour = "#184880"
var/global/admin_ooc_colour = "#b82e00"
/client/verb/ooc(msg as text)
//Checks if the client already has a text input open
/client/proc/checkTyping()
return (prefs.toggles & TYPING_ONCE && typing)
/client/verb/ooc(msg = "" as text)
set name = "OOC"
set category = "OOC"
if(!mob)
return
if(IsGuestKey(key))
to_chat(src, "<span class='danger'>Guests may not use OOC.</span>")
return
msg = trim(sanitize(copytext(msg, 1, MAX_MESSAGE_LEN)))
if(!msg)
return
if(!(prefs.toggles & CHAT_OOC))
to_chat(src, "<span class='danger'>You have OOC muted.</span>")
return
if(!check_rights(R_ADMIN|R_MOD,0))
if(!check_rights(R_ADMIN|R_MOD, 0))
if(!config.ooc_allowed)
to_chat(src, "<span class='danger'>OOC is globally muted.</span>")
return
@@ -32,6 +28,19 @@ var/global/admin_ooc_colour = "#b82e00"
if(prefs.muted & MUTE_OOC)
to_chat(src, "<span class='danger'>You cannot use OOC (muted).</span>")
return
if(!msg)
msg = typing_input(src.mob, "", "ooc \"text\"")
msg = trim(sanitize(copytext(msg, 1, MAX_MESSAGE_LEN)))
if(!msg)
return
if(!(prefs.toggles & CHAT_OOC))
to_chat(src, "<span class='danger'>You have OOC muted.</span>")
return
if(!check_rights(R_ADMIN|R_MOD,0))
if(handle_spam_prevention(msg, MUTE_OOC, OOC_COOLDOWN))
return
if(findtext(msg, "byond://"))
@@ -150,7 +159,7 @@ var/global/admin_ooc_colour = "#b82e00"
feedback_add_details("admin_verb","ROC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/looc(msg as text)
/client/verb/looc(msg = "" as text)
set name = "LOOC"
set desc = "Local OOC, seen only by those in view."
set category = "OOC"
@@ -161,14 +170,6 @@ var/global/admin_ooc_colour = "#b82e00"
to_chat(src, "<span class='danger'>Guests may not use OOC.</span>")
return
msg = trim(sanitize(copytext(msg, 1, MAX_MESSAGE_LEN)))
if(!msg)
return
if(!(prefs.toggles & CHAT_LOOC))
to_chat(src, "<span class='danger'>You have LOOC muted.</span>")
return
if(!check_rights(R_ADMIN|R_MOD,0))
if(!config.looc_allowed)
to_chat(src, "<span class='danger'>LOOC is globally muted.</span>")
@@ -179,6 +180,19 @@ var/global/admin_ooc_colour = "#b82e00"
if(prefs.muted & MUTE_OOC)
to_chat(src, "<span class='danger'>You cannot use LOOC (muted).</span>")
return
if(!msg)
msg = typing_input(src.mob, "Local OOC, seen only by those in view.", "looc \"text\"")
msg = trim(sanitize(copytext(msg, 1, MAX_MESSAGE_LEN)))
if(!msg)
return
if(!(prefs.toggles & CHAT_LOOC))
to_chat(src, "<span class='danger'>You have LOOC muted.</span>")
return
if(!check_rights(R_ADMIN|R_MOD,0))
if(handle_spam_prevention(msg, MUTE_OOC, OOC_COOLDOWN))
return
if(findtext(msg, "byond://"))
+5
View File
@@ -28,6 +28,11 @@ var/global/nologevent = 0
if(C.prefs && !(C.prefs.toggles & CHAT_NO_TICKETLOGS))
to_chat(C, msg)
/proc/message_mentorTicket(var/msg)
for(var/client/C in GLOB.admins)
if(check_rights(R_ADMIN | R_MENTOR | R_MOD, 0, C.mob))
if(C.prefs && !(C.prefs.toggles & CHAT_NO_MENTORTICKETLOGS))
to_chat(C, msg)
/proc/admin_ban_mobsearch(var/mob/M, var/ckey_to_find, var/mob/admin_to_notify)
if(!M || !M.ckey)
+19 -3
View File
@@ -205,6 +205,8 @@ var/list/admin_verbs_mentor = list(
/client/proc/cmd_admin_pm_context, /*right-click adminPM interface*/
/client/proc/cmd_admin_pm_panel, /*admin-pm list*/
/client/proc/cmd_admin_pm_by_key_panel, /*admin-pm list by key*/
/client/proc/openMentorTicketUI,
/client/proc/toggleMentorTicketLogs,
/client/proc/cmd_mentor_say /* mentor say*/
// cmd_mentor_say is added/removed by the toggle_mentor_chat verb
)
@@ -219,10 +221,10 @@ var/list/admin_verbs_snpc = list(
/client/proc/hide_snpc_verbs
)
var/list/admin_verbs_ticket = list(
/client/proc/openTicketUI,
/client/proc/openAdminTicketUI,
/client/proc/toggleticketlogs,
/client/proc/resolveAllTickets,
/client/proc/openUserUI
/client/proc/resolveAllAdminTickets,
/client/proc/resolveAllMentorTickets
)
/client/proc/on_holder_add()
@@ -940,6 +942,20 @@ var/list/admin_verbs_ticket = list(
else
to_chat(usr, "You now will get admin log messages.")
/client/proc/toggleMentorTicketLogs()
set name = "Toggle Mentor Ticket Messgaes"
set category = "Preferences"
if(!check_rights(R_MENTOR))
return
prefs.toggles ^= CHAT_NO_MENTORTICKETLOGS
prefs.save_preferences(src)
if(prefs.toggles & CHAT_NO_MENTORTICKETLOGS)
to_chat(usr, "You now won't get mentor ticket messages.")
else
to_chat(usr, "You now will get mentor ticket messages.")
/client/proc/toggleticketlogs()
set name = "Toggle Admin Ticket Messgaes"
set category = "Preferences"
+10
View File
@@ -548,6 +548,16 @@
if(spider_minds.len)
dat += check_role_table("Terror Spiders", spider_minds)
var/count_eggs = 0
var/count_spiderlings = 0
for(var/obj/structure/spider/eggcluster/terror_eggcluster/E in ts_egg_list)
if(is_station_level(E.z))
count_eggs += E.spiderling_number
for(var/obj/structure/spider/spiderling/terror_spiderling/L in ts_spiderling_list)
if(!L.stillborn && is_station_level(L.z))
count_spiderlings += 1
dat += "<table cellspacing=5><TR><TD>Growing TS on-station: [count_eggs] egg[count_eggs != 1 ? "s" : ""], [count_spiderlings] spiderling[count_spiderlings != 1 ? "s" : ""]. </TD></TR></TABLE>"
if(ticker.mode.ert.len)
dat += check_role_table("ERT", ticker.mode.ert)
@@ -1,8 +1,8 @@
//Verbs
/client/proc/openTicketUI()
/client/proc/openAdminTicketUI()
set name = "Open Ticket Interface"
set name = "Open Admin Ticket Interface"
set category = "Admin"
if(!holder || !check_rights(R_ADMIN))
@@ -10,8 +10,8 @@
SStickets.showUI(usr)
/client/proc/resolveAllTickets()
set name = "Resolve All Open Tickets"
/client/proc/resolveAllAdminTickets()
set name = "Resolve All Open Admin Tickets"
set category = "Admin"
if(!holder || !check_rights(R_ADMIN))
@@ -22,12 +22,7 @@
SStickets.resolveAllOpenTickets()
/client/proc/openUserUI()
set name = "My Tickets"
/client/verb/openAdminUserUI()
set name = "My Admin Tickets"
set category = "Admin"
if(!holder || !check_rights(R_ADMIN))
return
SStickets.userDetailUI(usr)
@@ -0,0 +1,28 @@
//Verbs
/client/proc/openMentorTicketUI()
set name = "Open Mentor Ticket Interface"
set category = "Admin"
if(!holder || !check_rights(R_MENTOR))
return
SSmentor_tickets.showUI(usr)
/client/proc/resolveAllMentorTickets()
set name = "Resolve All Open Mentor Tickets"
set category = "Admin"
if(!holder || !check_rights(R_ADMIN))
return
if(alert("Are you sure you want to resolve ALL open tickets?","Resolve all open tickets?","Yes","No") != "Yes")
return
SSmentor_tickets.resolveAllOpenTickets()
/client/verb/openMentorUserUI()
set name = "My Mentor Tickets"
set category = "Admin"
SSmentor_tickets.userDetailUI(usr)
+13 -16
View File
@@ -32,6 +32,12 @@
var/ticketID = text2num(href_list["openadminticket"])
SStickets.showDetailUI(usr, ticketID)
if(href_list["openmentorticket"])
if(!check_rights(R_MENTOR|R_MOD|R_ADMIN))
return
var/ticketID = text2num(href_list["openmentorticket"])
SSmentor_tickets.showDetailUI(usr, ticketID)
if(href_list["stickyban"])
stickyban(href_list["stickyban"],href_list)
@@ -1546,22 +1552,13 @@
check_antagonists()
else if(href_list["take_question"])
var/mob/M = locateUID(href_list["take_question"])
var/is_mhelp = href_list["is_mhelp"]
if(ismob(M))
var/helptype = "ADMINHELP"
if(is_mhelp)
helptype = "MENTORHELP"
var/take_msg = "<span class='notice'><b>[helptype]</b>: <b>[key_name_hidden(usr.client)]</b> is attending to <b>[key_name(M)]'s</b> question.</span>"
for(var/client/X in GLOB.admins)
if(check_rights(R_ADMIN, 0, X.mob))
to_chat(X, take_msg)
else if(is_mhelp && check_rights(R_MOD|R_MENTOR, 0, X.mob))
to_chat(X, take_msg)
to_chat(M, "<span class='notice'><b>Your question is being attended to by [key_name_hidden(usr.client, null, 0)]. Thanks for your patience!</b></span>")
else
to_chat(usr, "<span class='warning'>Unable to locate mob.</span>")
var/index = text2num(href_list["take_question"])
if(href_list["is_mhelp"])
SSmentor_tickets.takeTicket(index)
else //Ahelp
SStickets.takeTicket(index)
else if(href_list["cult_nextobj"])
if(alert(usr, "Validate the current Cult objective and unlock the next one?", "Cult Cheat Code", "Yes", "No") != "Yes")
return
+39 -24
View File
@@ -103,31 +103,46 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","
if(check_rights(R_MENTOR, 0, X.mob))
mentorholders += X
continue
var/ticketNum // Holder for the ticket number
var/prunedmsg ="[src]: [msg]" // Message without links
var/datum/ticket/T
var/isMhelp = selected_type == "Mentorhelp"
var/span
if(isMhelp)
span = "<span class='mentorhelp'>"
if(SSmentor_tickets.checkForOpenTicket(src)) // If user already has an open ticket
T = SSmentor_tickets.checkForOpenTicket(src)
else
ticketNum = SSmentor_tickets.getTicketCounter() // ticketNum is the ticket ready to be assigned.
else //Ahelp
span = "<span class='adminhelp'>"
if(SStickets.checkForOpenTicket(src)) // If user already has an open ticket
T = SStickets.checkForOpenTicket(src) // Make T equal to the ticket they have open
else
ticketNum = SStickets.getTicketCounter() // ticketNum is the ticket ready to be assigned.
if(T)
ticketNum = T.ticketNum // ticketNum is the number of their ticket.
T.addResponse(src, msg)
msg = "[span][selected_type]: </span><span class='boldnotice'>[key_name(src, TRUE, selected_type)] ([ADMIN_QUE(mob,"?")]) ([ADMIN_PP(mob,"PP")]) ([ADMIN_VV(mob,"VV")]) ([ADMIN_SM(mob,"SM")]) ([admin_jump_link(mob)]) (<A HREF='?_src_=holder;check_antagonist=1'>CA</A>) (<A HREF='?_src_=holder;[isMhelp ? "openmentorticket" : "openadminticket"]=[ticketNum]'>TICKET</A>) [ai_found ? "(<A HREF='?_src_=holder;adminchecklaws=[mob.UID()]'>CL</A>)" : ""] (<A HREF='?_src_=holder;take_question=[ticketNum][isMhelp ? ";is_mhelp=1" : ""]'>TAKE</A>) :</span> [span][msg]</span>"
if(isMhelp)
//Open a new adminticket and inform the user.
SSmentor_tickets.newTicket(src, prunedmsg, msg)
for(var/client/X in mentorholders + modholders + adminholders)
if(X.prefs.sound & SOUND_MENTORHELP)
X << 'sound/effects/adminhelp.ogg'
to_chat(X, msg)
else //Ahelp
//Open a new adminticket and inform the user.
SStickets.newTicket(src, prunedmsg, msg)
for(var/client/X in modholders + adminholders)
if(X.prefs.sound & SOUND_ADMINHELP)
X << 'sound/effects/adminhelp.ogg'
window_flash(X)
to_chat(X, msg)
switch(selected_type)
if("Mentorhelp")
msg = "<span class='mentorhelp'>[selected_type]: </span><span class='boldnotice'>[key_name(src, TRUE, selected_type)] ([ADMIN_QUE(mob,"?")]) ([ADMIN_PP(mob,"PP")]) ([ADMIN_VV(mob,"VV")]) ([ADMIN_SM(mob,"SM")]) ([admin_jump_link(mob)]) (<A HREF='?_src_=holder;check_antagonist=1'>CA</A>) (<A HREF='?_src_=holder;rejectadminhelp=[UID()]'>REJT</A>) [ai_found ? " (<A HREF='?_src_=holder;adminchecklaws=[mob.UID()]'>CL</A>)" : ""] (<A HREF='?_src_=holder;take_question=[mob.UID()];is_mhelp=1'>TAKE</A>) :</span> <span class='mentorhelp'>[msg]</span>"
for(var/client/X in mentorholders + modholders + adminholders)
if(X.prefs.sound & SOUND_MENTORHELP)
X << 'sound/effects/adminhelp.ogg'
to_chat(X, msg)
if("Adminhelp")
var/ticketNum // Holder for the ticket number
var/prunedmsg ="[usr.client]: [msg]" // Message without links
if(SStickets.checkForOpenTicket(usr)) // If user already has an open ticket
var/datum/admin_ticket/T = SStickets.checkForOpenTicket(usr) // Make T equal to the ticket they have open
ticketNum = T.ticketNum // ticketNum is the number of their ticket.
T.addResponse(usr.client, msg)
else
ticketNum = SStickets.getTicketCounter() // ticketNum is the ticket ready to be assigned.
msg = "<span class='adminhelp'>[selected_type]: </span><span class='boldnotice'>[key_name(src, TRUE, selected_type)] ([ADMIN_QUE(mob,"?")]) ([ADMIN_PP(mob,"PP")]) ([ADMIN_VV(mob,"VV")]) ([ADMIN_SM(mob,"SM")]) ([admin_jump_link(mob)]) (<A HREF='?_src_=holder;check_antagonist=1'>CA</A>) (<A HREF='?_src_=holder;openadminticket=[ticketNum]'>TICKET</A>) [ai_found ? " (<A HREF='?_src_=holder;adminchecklaws=[mob.UID()]'>CL</A>)" : ""](<A HREF='?_src_=holder;take_question=[mob.UID()]'>TAKE</A>) :</span> <span class='adminhelp'>[msg]</span>"
//Open a new adminticket and inform the user.
SStickets.newTicket(src, prunedmsg, msg)
for(var/client/X in modholders + adminholders)
if(X.prefs.sound & SOUND_ADMINHELP)
X << 'sound/effects/adminhelp.ogg'
window_flash(X)
to_chat(X, msg)
//show it to the person adminhelping too
to_chat(src, "<span class='boldnotice'>[selected_type]</b>: [original_msg]</span>")
+17 -12
View File
@@ -182,23 +182,28 @@
else
if(check_rights(R_ADMIN|R_MOD, 0, X.mob))
to_chat(X, "<span class='boldnotice'>[type]: [key_name(src, TRUE, type)]-&gt;[key_name(C, TRUE, type)]: [emoji_msg]</span>")
if(type == "Mentorhelp")
return
//Check if the mob being PM'd has any open admin tickets.
var/tickets = list()
tickets = SStickets.checkForTicket(C)
if(type == "Mentorhelp")
tickets = SSmentor_tickets.checkForTicket(C)
else
tickets = SStickets.checkForTicket(C)
if(tickets)
for(var/datum/admin_ticket/i in tickets)
for(var/datum/ticket/i in tickets)
i.addResponse(src, msg) // Add this response to their open tickets.
return
if(check_rights(R_ADMIN|R_MOD, 0, C.mob)) //Is the person being pm'd an admin? If so we check if the pm'er has open tickets
tickets = SStickets.checkForTicket(src)
if(tickets)
for(var/datum/admin_ticket/i in tickets)
i.addResponse(src, msg)
return
if(type == "Mentorhelp")
if(check_rights(R_ADMIN|R_MOD|R_MENTOR, 0, C.mob)) //Is the person being pm'd an admin? If so we check if the pm'er has open tickets
tickets = SSmentor_tickets.checkForTicket(src)
else // Ahelp
if(check_rights(R_ADMIN|R_MOD, 0, C.mob)) //Is the person being pm'd an admin? If so we check if the pm'er has open tickets
tickets = SStickets.checkForTicket(src)
if(tickets)
for(var/datum/ticket/i in tickets)
i.addResponse(src, msg)
return
/client/proc/cmd_admin_irc_pm()
+1 -11
View File
@@ -1,5 +1,5 @@
/datum/atom_hud/antag
hud_icons = list(SPECIALROLE_HUD,NATIONS_HUD)
hud_icons = list(SPECIALROLE_HUD)
var/self_visible = TRUE
/datum/atom_hud/antag/hidden
@@ -38,16 +38,6 @@
if(M.mind || new_icon_state) //in mindless mobs, only null is acceptable, otherwise we're antagging a mindless mob, meaning we should runtime
M.mind.antag_hud_icon_state = new_icon_state
//Nations Icons
/proc/set_nations_hud(mob/M, new_icon_state)
if(!istype(M))
CRASH("set_antag_hud(): [M] ([M.type]) is not a mob!")
var/image/holder = M.hud_list[NATIONS_HUD]
if(holder)
holder.icon_state = new_icon_state
if(M.mind || new_icon_state) //in mindless mobs, only null is acceptable, otherwise we're antagging a mindless mob, meaning we should runtime
M.mind.antag_hud_icon_state = new_icon_state
//MIND PROCS
//these are called by mind.transfer_to()
/datum/mind/proc/transfer_antag_huds(datum/atom_hud/antag/newhud)
+2 -19
View File
@@ -19,6 +19,8 @@
var/area = null
var/time_died_as_mouse = null //when the client last died as a mouse
var/typing = FALSE // Prevents typing window stacking
var/adminhelped = 0
var/gc_destroyed //Time when this object was destroyed.
@@ -65,25 +67,6 @@
// Set on login.
var/datum/media_manager/media = null
/////////////////////////////////////////////////////////////////////
//adv. hotkey mode vars, code using them in /interface/interface.dm//
/////////////////////////////////////////////////////////////////////
var/hotkeytype = "QWERTY" //what set of hotkeys is in use(defaulting to QWERTY because I can't be bothered to make this save on SQL)
var/hotkeyon = 0 //is the hotkey on?
var/hotkeylist = list( //list defining hotkey types, look at lists in place for structure if adding any if the future
"QWERTY" = list(
"on" = "hotkeymode",
"off" = "macro"),
"AZERTY" = list(
"on" = "AZERTYon",
"off" = "AZERTYoff"),
"Cyborg" = list(
"on" = "borghotkeymode",
"off" = "borgmacro")
)
var/topic_debugging = 0 //if set to true, allows client to see nanoUI errors -- yes i realize this is messy but it'll make live testing infinitely easier
control_freak = CONTROL_FREAK_ALL | CONTROL_FREAK_SKIN | CONTROL_FREAK_MACROS
@@ -55,7 +55,7 @@
ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor))
UI_style = sanitize_inlist(UI_style, list("White", "Midnight"), initial(UI_style))
default_slot = sanitize_integer(default_slot, 1, max_save_slots, initial(default_slot))
toggles = sanitize_integer(toggles, 0, 524287, initial(toggles))
toggles = sanitize_integer(toggles, 0, 2097151, initial(toggles))
sound = sanitize_integer(sound, 0, 65535, initial(sound))
UI_style_color = sanitize_hexcolor(UI_style_color, initial(UI_style_color))
UI_style_alpha = sanitize_integer(UI_style_alpha, 0, 255, initial(UI_style_alpha))
@@ -231,3 +231,15 @@
else
to_chat(usr, "<span class='notice'>You have enabled karma gains.")
return
/client/verb/toggle_popup_limiter()
set name = "Toggle Text Popup Limiter"
set category = "Preferences"
set desc = "Will let you limit the text input popups to one at a time."
prefs.toggles ^= TYPING_ONCE
prefs.save_preferences(src)
if(prefs.toggles & TYPING_ONCE)
to_chat(usr, "<span class='notice'>You have enabled text popup limiting.")
else
to_chat(usr, "<span class='notice'>You have disabled text popup limiting.")
return
+13 -1
View File
@@ -12,6 +12,9 @@
description_antag = "These are a pair of power gloves, and can be used to fire bolts of electricity while standing over powered power cables."
var/old_mclick_override
var/datum/middleClickOverride/power_gloves/mclick_override = new /datum/middleClickOverride/power_gloves
var/last_shocked = 0
var/shock_delay = 40
var/unlimited_power = FALSE // Does this really need explanation?
/obj/item/clothing/gloves/color/yellow/power/equipped(mob/user, slot)
if(!ishuman(user))
@@ -21,7 +24,10 @@
if(H.middleClickOverride)
old_mclick_override = H.middleClickOverride
H.middleClickOverride = mclick_override
to_chat(H, "<span class='notice'>You feel electricity begin to build up in [src].</span>")
if(!unlimited_power)
to_chat(H, "<span class='notice'>You feel electricity begin to build up in [src].</span>")
else
to_chat(H, "<span class='biggerdanger'>You feel like you have UNLIMITED POWER!!</span>")
/obj/item/clothing/gloves/color/yellow/power/dropped(mob/user, slot)
if(!ishuman(user))
@@ -34,6 +40,12 @@
else
H.middleClickOverride = null
/obj/item/clothing/gloves/color/yellow/power/unlimited
name = "UNLIMITED POWER gloves"
desc = "These gloves possess UNLIMITED POWER."
shock_delay = 0
unlimited_power = TRUE
/obj/item/clothing/gloves/color/yellow/fake
desc = "These gloves will protect the wearer from electric shock. They don't feel like rubber..."
siemens_coefficient = 1
+72 -41
View File
@@ -1,4 +1,4 @@
#define SLAM_COMBO "HG"
#define SLAM_COMBO "GH"
#define KICK_COMBO "HH"
#define RESTRAIN_COMBO "GG"
#define PRESSURE_COMBO "DG"
@@ -8,15 +8,24 @@
name = "CQC"
help_verb = /mob/living/carbon/human/proc/CQC_help
block_chance = 75
var/just_a_cook = FALSE
var/static/list/areas_under_siege = typecacheof(list(/area/crew_quarters/kitchen,
/area/crew_quarters/cafeteria,
/area/crew_quarters/bar))
/datum/martial_art/cqc/can_use(mob/living/carbon/human/H)
if(istype(H.gloves, /obj/item/clothing/gloves/fingerless/rapid))
return FALSE
return ..()
/datum/martial_art/cqc/under_siege
name = "Close Quarters Cooking"
just_a_cook = TRUE
/datum/martial_art/cqc/proc/drop_restraining()
restraining = FALSE
/datum/martial_art/cqc/can_use(mob/living/carbon/human/H)
var/area/A = get_area(H)
if(just_a_cook && !(is_type_in_typecache(A, areas_under_siege)))
return FALSE
return ..()
/datum/martial_art/cqc/proc/check_streak(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!can_use(A))
return FALSE
@@ -44,22 +53,23 @@
/datum/martial_art/cqc/proc/Slam(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!can_use(A))
return FALSE
if(!D.stat || !D.weakened)
if(!D.weakened && !D.resting && !D.lying)
D.visible_message("<span class='warning'>[A] slams [D] into the ground!</span>", \
"<span class='userdanger'>[A] slams you into the ground!</span>")
playsound(get_turf(A), 'sound/weapons/slam.ogg', 50, 1, -1)
D.apply_damage(10, BRUTE)
D.Weaken(6)
add_attack_logs(A, D, "Melee attacked with martial-art [src] : Slam", ATKLOG_ALL)
else //if target can't be slammed, do a regular grab attack then clear the streak
streak = ""
grab_act(A, D)
streak = ""
return TRUE
streak = ""
harm_act(A, D)
streak = ""
return TRUE
/datum/martial_art/cqc/proc/Kick(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!can_use(A))
return FALSE
var/success = FALSE
if(!D.stat || !D.weakened)
D.visible_message("<span class='warning'>[A] kicks [D] back!</span>", \
"<span class='userdanger'>[A] kicks you back!</span>")
@@ -68,17 +78,20 @@
D.throw_at(throw_target, 1, 14, A)
D.apply_damage(10, BRUTE)
add_attack_logs(A, D, "Melee attacked with martial-art [src] : Kick", ATKLOG_ALL)
if(D.weakened && !D.stat)
D.visible_message("<span class='warning'>[A] kicks [D]'s head, knocking [D.p_them()] out!</span>", \
"<span class='userdanger'>[A] kicks your head, knocking you out!</span>")
playsound(get_turf(A), 'sound/weapons/genhit1.ogg', 50, 1, -1)
D.SetSleeping(15)
D.adjustBrainLoss(15, 150)
add_attack_logs(A, D, "Knocked out with martial-art [src] : Kick", ATKLOG_ALL)
else //if target can't be kicked, do a regular harm attack then clear the streak
streak = ""
harm_act(A, D)
streak = ""
success = TRUE
if(D.weakened && !D.stat)
D.visible_message("<span class='warning'>[A] kicks [D]'s head, knocking [D.p_them()] out!</span>", \
"<span class='userdanger'>[A] kicks your head, knocking you out!</span>")
playsound(get_turf(A), 'sound/weapons/genhit1.ogg', 50, 1, -1)
D.SetSleeping(15)
D.adjustBrainLoss(15)
add_attack_logs(A, D, "Knocked out with martial-art [src] : Kick", ATKLOG_ALL)
success = TRUE
if(success)
return TRUE
streak = ""
harm_act(A, D)
streak = ""
return TRUE
/datum/martial_art/cqc/proc/Pressure(mob/living/carbon/human/A, mob/living/carbon/human/D)
@@ -103,6 +116,10 @@
restraining = TRUE
addtimer(CALLBACK(src, .proc/drop_restraining), 50, TIMER_UNIQUE)
add_attack_logs(A, D, "Melee attacked with martial-art [src] : Restrain", ATKLOG_ALL)
return TRUE
streak = ""
harm_act(A, D)
streak = ""
return TRUE
/datum/martial_art/cqc/proc/Consecutive(mob/living/carbon/human/A, mob/living/carbon/human/D)
@@ -118,10 +135,10 @@
D.adjustStaminaLoss(50)
D.apply_damage(25, BRUTE)
add_attack_logs(A, D, "Melee attacked with martial-art [src] : Consecutive", ATKLOG_ALL)
else //if target can't be hit, do a regular harm attack then clear the streak
streak = ""
harm_act(A, D)
streak = ""
return TRUE
streak = ""
harm_act(A, D)
streak = ""
return TRUE
/datum/martial_art/cqc/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
@@ -133,6 +150,8 @@
var/obj/item/grab/G = D.grabbedby(A, 1)
if(G)
G.state = GRAB_AGGRESSIVE //Instant aggressive grab
add_attack_logs(A, D, "Melee attacked with martial-art [src] : aggressively grabbed", ATKLOG_ALL)
return TRUE
/datum/martial_art/cqc/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
@@ -141,8 +160,9 @@
add_to_streak("H", D)
if(check_streak(A, D))
return TRUE
add_attack_logs(A, D, "Melee attacked with martial-art [src]", ATKLOG_ALL)
A.do_attack_animation(D)
var/picked_hit_type = pick("CQC'd", "neck chopped", "gut punched")
var/picked_hit_type = pick("CQC'd", "neck chopped", "gut punched", "Big Bossed")
var/bonus_damage = 13
if(D.weakened || D.resting || D.lying)
bonus_damage += 5
@@ -154,7 +174,7 @@
playsound(get_turf(D), 'sound/weapons/cqchit1.ogg', 50, 1, -1)
D.visible_message("<span class='danger'>[A] [picked_hit_type] [D]!</span>", \
"<span class='userdanger'>[A] [picked_hit_type] you!</span>")
add_attack_logs(A, D, "Melee attacked with martial-art [src]", ATKLOG_ALL)
add_attack_logs(A, D, "Melee attacked with martial-art [src] : [picked_hit_type]", ATKLOG_ALL)
if(A.resting && !D.stat && !D.weakened)
D.visible_message("<span class='warning'>[A] leg sweeps [D]!", \
"<span class='userdanger'>[A] leg sweeps you!</span>")
@@ -168,24 +188,36 @@
if(!can_use(A))
return FALSE
add_to_streak("D", D)
var/obj/item/I = null
if(check_streak(A, D))
return TRUE
if(!restraining)
D.visible_message("<span class='warning'>[A] strikes [D]'s jaw with their hand!</span>", \
"<span class='userdanger'>[A] strikes your jaw, disorienting you!</span>")
playsound(get_turf(D), 'sound/weapons/cqchit1.ogg', 50, 1, -1)
D.Jitter(2)
D.apply_damage(5, BRUTE)
add_attack_logs(A, D, "Melee attacked with martial-art [src] : Disarm", ATKLOG_ALL)
if(restraining)
var/obj/item/grab/G = A.get_inactive_hand()
if(restraining && istype(G) && G.affecting == D)
D.visible_message("<span class='danger'>[A] puts [D] into a chokehold!</span>", \
"<span class='userdanger'>[A] puts you into a chokehold!</span>")
D.SetSleeping(20)
restraining = FALSE
add_attack_logs(A, D, "Knocked out with martial-art [src] : Choke hold", ATKLOG_ALL)
if(G.state < GRAB_NECK)
G.state = GRAB_NECK
return TRUE
else
restraining = FALSE
return FALSE
if(prob(65))
if(!D.stat || !D.weakened || !restraining)
I = D.get_active_hand()
D.visible_message("<span class='warning'>[A] strikes [D]'s jaw with their hand!</span>", \
"<span class='userdanger'>[A] strikes your jaw, disorienting you!</span>")
playsound(get_turf(D), 'sound/weapons/cqchit1.ogg', 50, 1, -1)
if(I && D.drop_item())
A.put_in_hands(I)
D.Jitter(2)
D.apply_damage(5, BRUTE)
else
D.visible_message("<span class='danger'>[A] attempted to disarm [D]!</span>", "<span class='userdanger'>[A] attempted to disarm [D]!</span>")
playsound(D, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
add_attack_logs(A, D, "Melee attacked with martial-art [src] : Disarmed [I ? " grabbing \the [I]" : ""]", ATKLOG_ALL)
return TRUE
/mob/living/carbon/human/proc/CQC_help()
@@ -194,11 +226,10 @@
set category = "CQC"
to_chat(usr, "<b><i>You try to remember some of the basics of CQC.</i></b>")
to_chat(usr, "<span class='notice'>Slam</span>: Harm Grab. Slam opponent into the ground, knocking them down.")
to_chat(usr, "<span class='notice'>Slam</span>: Grab, switch hands, Harm. Slam opponent into the ground, knocking them down.")
to_chat(usr, "<span class='notice'>CQC Kick</span>: Harm Harm. Knocks opponent away. Knocks out stunned or knocked down opponents.")
to_chat(usr, "<span class='notice'>Restrain</span>: Grab Switch Hand Grab. Locks opponent into a restraining position, stunning them.")
to_chat(usr, "<span class='notice'>Choke Hold</span>: Restrain Disarm. Knocks out an opponent you have restrained.")
to_chat(usr, "<span class='notice'>Restrain</span>: Grab, switch hands, Grab. Locks opponents into a restraining position, disarm to knock them out with a choke hold.")
to_chat(usr, "<span class='notice'>Pressure</span>: Disarm Grab. Decent stamina damage.")
to_chat(usr, "<span class='notice'>Consecutive CQC</span>: Disarm Disarm Harm. Mainly offensive move, huge damage and decent stamina damage.")
to_chat(usr, "<b><i>In addition, by having your throw mode on when being attacked, you enter an active defense mode where you have a chance to block and sometimes even counter melee attacks done to you.</i></b>")
to_chat(usr, "<b><i>In addition, by having your throw mode on when being attacked, you enter an active defense mode where you have a chance to block and sometimes even counter attacks done to you.</i></b>")
-4
View File
@@ -14,7 +14,3 @@
/mob/camera/experience_pressure_difference()
return
/mob/camera/Login()
..()
update_interface()
-2
View File
@@ -7,5 +7,3 @@
if(GLOB.non_respawnable_keys[ckey])
can_reenter_corpse = 0
GLOB.respawnable_list -= src
update_interface()
+23 -13
View File
@@ -49,7 +49,7 @@ var/list/image/ghost_darkness_images = list() //this is a list of images for thi
T = get_turf(body) //Where is the body located?
attack_log = body.attack_log //preserve our attack logs by copying them to our ghost
var/mutable_appearance/MA = copy_appearance(body)
var/mutable_appearance/MA = copy_appearance(body)
if(body.mind && body.mind.name)
MA.name = body.mind.name
else if(body.real_name)
@@ -139,11 +139,8 @@ Works together with spawning an observer, noted above.
var/client/C = U.client
for(var/mob/living/carbon/human/target in target_list)
C.images += target.hud_list[SPECIALROLE_HUD]
//C.images += target.hud_list[NATIONS_HUD]
for(var/mob/living/silicon/target in target_list)
C.images += target.hud_list[SPECIALROLE_HUD]
//C.images += target.hud_list[NATIONS_HUD]
return 1
/mob/proc/ghostize(var/flags = GHOST_CAN_REENTER)
@@ -179,30 +176,44 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(P)
if(TOO_EARLY_TO_GHOST)
warningmsg = "It's too early in the shift to enter cryo"
// If it's not too early, we'll skip straight to ghosting out without penalty
else if(suiciding && TOO_EARLY_TO_GHOST)
warningmsg = "You have committed suicide too early in the round"
else if(stat != DEAD)
warningmsg = "You are alive"
if(isAI(src))
warningmsg = "You are a living AI! You should probably use OOC -> Wipe Core instead."
else if(GLOB.non_respawnable_keys[ckey])
warningmsg = "You have lost your right to respawn"
if(!warningmsg)
ghostize(1)
else
if(warningmsg)
var/response
var/alertmsg = "Are you -sure- you want to ghost?\n([warningmsg]. If you ghost now, you probably won't be able to rejoin the round! You can't change your mind, so choose wisely!)"
response = alert(src, alertmsg,"Are you sure you want to ghost?","Stay in body","Ghost")
if(response != "Ghost")
return //didn't want to ghost after-all
StartResting()
var/mob/dead/observer/ghost = ghostize(0) //0 parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3
ghost.timeofdeath = world.time // Because the living mob won't have a time of death and we want the respawn timer to work properly.
return
if(stat == CONSCIOUS)
if(!is_admin_level(z))
player_ghosted = 1
if(mind && mind.special_role)
message_admins("[key_name_admin(src)] has ghosted while alive, with special_role: [mind.special_role]")
if(warningmsg)
// Not respawnable
var/mob/dead/observer/ghost = ghostize(0) // 0 parameter stops them re-entering their body
ghost.timeofdeath = world.time // Because the living mob won't have a time of death and we want the respawn timer to work properly.
else
// Respawnable
ghostize(1)
// If mob in morgue tray, update tray
var/obj/structure/morgue/Morgue = locate() in M.loc
if(istype(M.loc, /obj/structure/morgue))
Morgue = M.loc
if(Morgue)
Morgue.update()
// If mob in cryopod, despawn mob
if(P)
if(!P.control_computer)
P.find_control_computer(urgent=1)
@@ -210,7 +221,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
P.despawn_occupant()
return
/mob/dead/observer/Move(NewLoc, direct)
following = null
dir = direct
+3 -1
View File
@@ -523,7 +523,9 @@
flags = RESTRICTED | HIVEMIND
/datum/language/shadowling/broadcast(mob/living/speaker, message, speaker_mask)
if(speaker.mind && speaker.mind.special_role)
if(speaker.mind && speaker.mind.special_role == SPECIAL_ROLE_SHADOWLING)
..(speaker,"<font size=3><b>[message]</b></font>", "<span class='shadowling'><font size=3>([speaker.mind.special_role]) [speaker]</font></span>")
else if(speaker.mind && speaker.mind.special_role)
..(speaker, message, "([speaker.mind.special_role]) [speaker]")
else
..(speaker, message)
@@ -1,7 +1,7 @@
/obj/item/organ/internal/brain
name = "brain"
health = 400 //They need to live awhile longer than other organs.
max_damage = 200
max_damage = 120
icon_state = "brain2"
force = 1.0
w_class = WEIGHT_CLASS_SMALL
@@ -100,6 +100,19 @@
log_debug("Multibrain shenanigans at ([target.x],[target.y],[target.z]), mob '[target]'")
..(target, special = special)
/obj/item/organ/internal/brain/receive_damage(amount, silent = 0) //brains are special; if they receive damage by other means, we really just want the damage to be passed ot the owner and back onto the brain.
if(owner)
owner.adjustBrainLoss(amount)
/obj/item/organ/internal/brain/necrotize(update_sprite = TRUE) //Brain also has special handling for when it necrotizes
damage = max_damage
status |= ORGAN_DEAD
processing_objects -= src
if(dead_icon && !is_robotic())
icon_state = dead_icon
if(owner && vital)
owner.setBrainLoss(120)
/obj/item/organ/internal/brain/prepare_eat()
return // Too important to eat.
@@ -363,7 +363,7 @@
for(var/datum/data/record/R in data_core.security)
if(R.fields["id"] == E.fields["id"])
criminal = R.fields["criminal"]
var/criminal_status = hasHUD(user, "read_only_security") ? "\[[criminal]\]" : "<a href='?src=[UID()];criminal=[glasses]'>\[[criminal]\]</a>"
var/criminal_status = hasHUD(user, "read_only_security") ? "\[[criminal]\]" : "<a href='?src=[UID()];criminal=1'>\[[criminal]\]</a>"
msg += "<span class = 'deptradio'>Criminal status:</span> [criminal_status]\n"
msg += "<span class = 'deptradio'>Security records:</span> <a href='?src=[UID()];secrecord=`'>\[View\]</a> <a href='?src=[UID()];secrecordadd=`'>\[Add comment\]</a>\n"
@@ -198,12 +198,6 @@
stat("Total Blood", "[mind.vampire.bloodtotal]")
stat("Usable Blood", "[mind.vampire.bloodusable]")
if(mind.nation)
stat("Nation Name", "[mind.nation.current_name ? "[mind.nation.current_name]" : "[mind.nation.default_name]"]")
stat("Nation Leader", "[mind.nation.current_leader ? "[mind.nation.current_leader]" : "None"]")
stat("Nation Heir", "[mind.nation.heir ? "[mind.nation.heir]" : "None"]")
if(istype(loc, /obj/spacepod)) // Spacdpods!
var/obj/spacepod/S = loc
stat("Spacepod Charge", "[istype(S.battery) ? "[(S.battery.charge / S.battery.maxcharge) * 100]" : "No cell detected"]")
@@ -31,7 +31,10 @@
if(sponge)
if(dna.species && amount > 0)
amount = amount * dna.species.brain_mod
sponge.receive_damage(amount, 1)
sponge.damage = Clamp(sponge.damage + amount, 0, 120)
if(sponge.damage >= 120)
visible_message("<span class='alert'><B>[src]</B> goes limp, [p_their()] facial expression utterly blank.</span>")
death()
if(updating)
update_stat("adjustBrainLoss")
return STATUS_UPDATE_STAT
@@ -45,7 +48,10 @@
if(sponge)
if(dna.species && amount > 0)
amount = amount * dna.species.brain_mod
sponge.damage = min(max(amount, 0), (maxHealth*2))
sponge.damage = Clamp(amount, 0, 120)
if(sponge.damage >= 120)
visible_message("<span class='alert'><B>[src]</B> goes limp, [p_their()] facial expression utterly blank.</span>")
death()
if(updating)
update_stat("setBrainLoss")
return STATUS_UPDATE_STAT
@@ -157,7 +157,7 @@ emp_act
return 1
return 0
/mob/living/carbon/human/check_block()
/mob/living/carbon/human/proc/check_block()
if(martial_art && prob(martial_art.block_chance) && martial_art.can_use(src) && in_throw_mode && !incapacitated(FALSE, TRUE))
return TRUE
@@ -220,6 +220,10 @@ emp_act
if(check_shields(I.force, "the [I.name]", I, MELEE_ATTACK, I.armour_penetration))
return 0
if(check_block())
visible_message("<span class='warning'>[src] blocks [I]!</span>")
return FALSE
if(istype(I,/obj/item/card/emag))
emag_act(user, affecting)
@@ -1,7 +1,7 @@
var/global/default_martial_art = new/datum/martial_art
/mob/living/carbon/human
hud_possible = list(HEALTH_HUD,STATUS_HUD,ID_HUD,WANTED_HUD,IMPMINDSHIELD_HUD,IMPCHEM_HUD,IMPTRACK_HUD,SPECIALROLE_HUD,NATIONS_HUD,GLAND_HUD)
hud_possible = list(HEALTH_HUD,STATUS_HUD,ID_HUD,WANTED_HUD,IMPMINDSHIELD_HUD,IMPCHEM_HUD,IMPTRACK_HUD,SPECIALROLE_HUD,GLAND_HUD)
//Marking colour and style
var/list/m_colours = DEFAULT_MARKING_COLOURS //All colours set to #000000.
+11 -1
View File
@@ -37,6 +37,17 @@
if(life_tick == 1)
regenerate_icons() // Make sure the inventory updates
handle_ghosted()
/mob/living/carbon/human/proc/handle_ghosted()
if(player_ghosted > 0 && stat == CONSCIOUS && job && !restrained())
if(key)
player_ghosted = 0
else
player_ghosted++
if(player_ghosted % 150 == 0)
force_cryo_human(src)
/mob/living/carbon/human/calculate_affecting_pressure(var/pressure)
..()
var/pressure_difference = abs( pressure - ONE_ATMOSPHERE )
@@ -779,7 +790,6 @@
handle_organs()
if(getBrainLoss() >= 120 || (health + (getOxyLoss() / 2)) <= -500)
visible_message("<span class='alert'><B>[src]</B> goes limp, their facial expression utterly blank.</span>")
death()
return
@@ -319,7 +319,7 @@
user.do_cpr(target)
/datum/species/proc/grab(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style)
if(target.check_block()) //cqc
if(target.check_block())
target.visible_message("<span class='warning'>[target] blocks [user]'s grab attempt!</span>")
return FALSE
if(attacker_style && attacker_style.grab_act(user, target))
@@ -348,7 +348,7 @@
add_attack_logs(user, target, "vampirebit")
return
//end vampire codes
if(target.check_block()) //cqc
if(target.check_block())
target.visible_message("<span class='warning'>[target] blocks [user]'s attack!</span>")
return FALSE
if(attacker_style && attacker_style.harm_act(user, target))
@@ -393,7 +393,7 @@
SEND_SIGNAL(target, COMSIG_PARENT_ATTACKBY)
/datum/species/proc/disarm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style)
if(target.check_block()) //cqc
if(target.check_block())
target.visible_message("<span class='warning'>[target] blocks [user]'s disarm attempt!</span>")
return FALSE
if(attacker_style && attacker_style.disarm_act(user, target))
@@ -56,6 +56,9 @@
/datum/species/grey/handle_reagents(mob/living/carbon/human/H, datum/reagent/R)
if(R.id == "sacid")
H.reagents.del_reagent(R.id)
return 0
H.reagents.remove_reagent(R.id, REAGENTS_METABOLISM)
return FALSE
if(R.id == "water")
H.adjustFireLoss(1)
return TRUE
return ..()
@@ -188,6 +188,6 @@
H.adjustFireLoss(-0.5*REAGENTS_EFFECT_MULTIPLIER)
H.adjustPlasma(20)
H.reagents.remove_reagent(R.id, REAGENTS_METABOLISM)
return 0 //Handling reagent removal on our own. Prevents plasma from dealing toxin damage to Plasmamen.
return FALSE //Handling reagent removal on our own. Prevents plasma from dealing toxin damage to Plasmamen.
return ..()
@@ -41,7 +41,7 @@
/datum/species/skeleton/handle_reagents(mob/living/carbon/human/H, datum/reagent/R)
// Crazylemon is still silly
if(R.id == "milk")
H.heal_overall_damage(4,4)
H.heal_overall_damage(4, 4)
if(prob(5)) // 5% chance per proc to find a random limb, and mend it
var/list/our_organs = H.bodyparts.Copy()
shuffle(our_organs)
@@ -54,7 +54,7 @@
L.perma_injury = 0
break // We're only checking one limb here, bucko
if(prob(3))
H.say(pick("Thanks Mr Skeltal", "Thank for strong bones", "Doot doot!"))
return 1
H.say(pick("Thanks Mr. Skeltal", "Thank for strong bones", "Doot doot!"))
return TRUE
return ..()
@@ -2,16 +2,7 @@
if(status_flags & GODMODE)
return
..(reason)
if(stat != DEAD)
switch(getBrainLoss())
if(100 to 120)
Weaken(20)
create_debug_log("collapsed from brain damage, trigger reason: [reason]")
if(120 to INFINITY)
visible_message("<span class='alert'><B>[src]</B> goes limp, [p_their()] facial expression utterly blank.</span>")
death()
create_debug_log("died of brain damage, trigger reason: [reason]")
else
if(stat == DEAD)
if(dna.species && dna.species.can_revive_by_healing)
var/obj/item/organ/internal/brain/B = get_int_organ(/obj/item/organ/internal/brain)
if(B)
+1 -9
View File
@@ -52,8 +52,6 @@
if(client)
//regular_hud_updates() //THIS DOESN'T FUCKING UPDATE SHIT
handle_regular_hud_updates() //IT JUST REMOVES FUCKING HUD IMAGES
if(get_nations_mode())
process_nations()
..()
@@ -227,10 +225,4 @@
return
/mob/living/proc/handle_hud_icons_health()
return
/mob/living/proc/process_nations()
if(client)
var/client/C = client
for(var/mob/living/carbon/human/H in view(src, world.view))
C.images += H.hud_list[NATIONS_HUD]
return
+1 -5
View File
@@ -337,8 +337,4 @@
return TRUE
if(INTENT_DISARM)
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
return TRUE
//defined here, overridden for humans in human_defense. By default, living mobs don't get to block anything
/mob/living/proc/check_block()
return FALSE
return TRUE
-2
View File
@@ -17,6 +17,4 @@
//Should update regardless of if we can ventcrawl, since we can end up in pipes in other ways.
update_pipe_vision()
update_interface()
return .
@@ -133,9 +133,6 @@
process_queued_alarms()
if(get_nations_mode())
process_nations_ai()
/mob/living/silicon/ai/updatehealth(reason = "none given")
if(status_flags & GODMODE)
health = 100
@@ -156,12 +153,6 @@
..()
add_ai_verbs(src)
/mob/living/silicon/ai/proc/process_nations_ai()
if(client)
var/client/C = client
for(var/mob/living/carbon/human/H in view(eyeobj, 14))
C.images += H.hud_list[NATIONS_HUD]
/mob/living/silicon/ai/update_sight()
see_invisible = initial(see_invisible)
see_in_dark = initial(see_in_dark)
@@ -1,6 +1,7 @@
/mob/living/silicon/robot/Login()
..()
if(client)
client.hotkeytype = "Cyborg"
regenerate_icons()
show_laws(0)
var/datum/hotkey_mode/cyborg/C = new(src)
C.set_winset_values()
+3 -30
View File
@@ -93,7 +93,7 @@ var/list/robot_verbs_default = list(
var/updating = 0 //portable camera camerachunk update
hud_possible = list(SPECIALROLE_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_BATT_HUD, NATIONS_HUD)
hud_possible = list(SPECIALROLE_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_BATT_HUD)
var/magpulse = 0
var/ionpulse = 0 // Jetpack-like effect.
@@ -288,10 +288,6 @@ var/list/robot_verbs_default = list(
if(security_level == (SEC_LEVEL_GAMMA || SEC_LEVEL_EPSILON) || crisis)
to_chat(src, "<span class='warning'>Crisis mode active. Combat module available.</span>")
modules += "Combat"
if(ticker && ticker.mode && ticker.mode.name == "nations")
var/datum/game_mode/nations/N = ticker.mode
if(N.kickoff)
modules = list("Nations")
if(mmi != null && mmi.alien)
modules = list("Hunter")
modtype = input("Please, select a module!", "Robot", null, null) as null|anything in modules
@@ -390,11 +386,6 @@ var/list/robot_verbs_default = list(
module.channels = list("Security" = 1)
icon_state = "droidcombat"
if("Nations")
module = new /obj/item/robot_module/nations(src)
module.channels = list()
icon_state = "droidpeace"
if("Hunter")
module = new /obj/item/robot_module/alien/hunter(src)
icon_state = "xenoborg-state-a"
@@ -415,7 +406,7 @@ var/list/robot_verbs_default = list(
feedback_inc("cyborg_[lowertext(modtype)]",1)
rename_character(real_name, get_default_name())
if(modtype == "Medical" || modtype == "Security" || modtype == "Combat" || modtype == "Nations")
if(modtype == "Medical" || modtype == "Security" || modtype == "Combat")
status_flags &= ~CANPUSH
choose_icon(6,module_sprites)
@@ -891,7 +882,7 @@ var/list/robot_verbs_default = list(
else
overlays += "[panelprefix]-openpanel -c"
var/combat = list("Combat","Nations")
var/combat = list("Combat")
if(modtype in combat)
if(base_icon == "")
base_icon = icon_state
@@ -1356,24 +1347,6 @@ var/list/robot_verbs_default = list(
/mob/living/silicon/robot/ert/gamma
crisis = 1
/mob/living/silicon/robot/nations
base_icon = "droidpeace"
icon_state = "droidpeace"
modtype = "Nations"
designation = "Nations"
/mob/living/silicon/robot/nations/init()
..()
module = new /obj/item/robot_module/nations(src)
//languages
module.add_languages(src)
//subsystems
module.add_subsystems_and_actions(src)
status_flags &= ~CANPUSH
notify_ai(2)
/mob/living/silicon/robot/emp_act(severity)
..()
switch(severity)
@@ -497,22 +497,6 @@
fix_modules()
/obj/item/robot_module/nations
name = "nations robot module"
module_type = "Malf"
/obj/item/robot_module/nations/New()
..()
modules += new /obj/item/restraints/handcuffs/cable/zipties/cyborg(src)
modules += new /obj/item/gun/energy/gun/cyborg(src)
modules += new /obj/item/pickaxe/drill/jackhammer(src)
modules += new /obj/item/borg/combat/shield(src)
modules += new /obj/item/borg/combat/mobility(src)
modules += new /obj/item/wrench/cyborg(src)
emag = new /obj/item/gun/energy/lasercannon/cyborg(src)
fix_modules()
/obj/item/robot_module/alien/hunter
name = "alien hunter module"
module_type = "Standard"
+1 -1
View File
@@ -25,7 +25,7 @@
var/next_alarm_notice
var/list/datum/alarm/queued_alarms = new()
hud_possible = list(SPECIALROLE_HUD, DIAG_STAT_HUD, DIAG_HUD,NATIONS_HUD)
hud_possible = list(SPECIALROLE_HUD, DIAG_STAT_HUD, DIAG_HUD)
var/med_hud = DATA_HUD_MEDICAL_ADVANCED //Determines the med hud to use
@@ -24,6 +24,12 @@
canlay = 1000
spider_tier = TS_TIER_5
projectiletype = /obj/item/projectile/terrorqueenspit/empress
icon = 'icons/mob/terrorspider64.dmi'
pixel_x = -16
mob_size = MOB_SIZE_LARGE
icon_state = "terror_empress"
icon_living = "terror_empress"
icon_dead = "terror_empress_dead"
var/datum/action/innate/terrorspider/queen/empress/empresslings/empresslings_action
var/datum/action/innate/terrorspider/queen/empress/empresserase/empresserase_action
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
@@ -42,7 +48,7 @@
queenfakelings_action.button.name = "Empress Lings"
/mob/living/simple_animal/hostile/poison/terror_spider/queen/empress/LayQueenEggs()
var/eggtype = input("What kind of eggs?") as null|anything in list(TS_DESC_QUEEN, TS_DESC_MOTHER, TS_DESC_PRINCE, TS_DESC_PRINCESS, TS_DESC_RED, TS_DESC_GRAY, TS_DESC_GREEN, TS_DESC_BLACK, TS_DESC_PURPLE, TS_DESC_WHITE)
var/eggtype = input("What kind of eggs?") as null|anything in list(TS_DESC_QUEEN, TS_DESC_MOTHER, TS_DESC_PRINCE, TS_DESC_PRINCESS, TS_DESC_RED, TS_DESC_GRAY, TS_DESC_GREEN, TS_DESC_BLACK, TS_DESC_PURPLE, TS_DESC_WHITE, TS_DESC_BROWN)
var/numlings = input("How many in the batch?") as null|anything in list(1, 2, 3, 4, 5, 10, 15, 20, 30, 40, 50)
if(eggtype == null || numlings == null)
to_chat(src, "<span class='danger'>Cancelled.</span>")
@@ -60,6 +66,8 @@
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/purple, numlings)
if(TS_DESC_WHITE)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/white, numlings)
if(TS_DESC_BROWN)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/brown, numlings)
if(TS_DESC_PRINCE)
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/prince, numlings)
if(TS_DESC_PRINCESS)
@@ -38,6 +38,8 @@
if(can_die())
if(spider_awaymission && !is_away_level(z))
canspawn = FALSE
if(degenerate)
canspawn = FALSE
if(canspawn)
canspawn = FALSE
for(var/i in 0 to spawn_count)
@@ -142,9 +142,8 @@
visible_message("<span class='danger'>\The [src] looks around warily - then seeks a better nesting ground.</span>")
path_to_vent = 1
else
visible_message("<span class='danger'>\The [src] looks around, searching for the vent that should be there, but isn't. A bluespace portal forms on her, and she is gone.</span>")
qdel(src)
new /obj/effect/portal(get_turf(loc))
neststep = -1
message_admins("Warning: [key_name_admin(src)] was spawned in an area without a vent! This is likely a mapping/spawn mistake. This mob's AI has been permanently deactivated.")
if(1)
// No nest, and we should create one. Start NestMode(), then advance to step 2.
if(world.time > (lastnestsetup + nestfrequency))
-26
View File
@@ -72,29 +72,3 @@
update_client_colour(0)
callHook("mob_login", list("client" = client, "mob" = src))
// Calling update_interface() in /mob/Login() causes the Cyborg to immediately be ghosted; because of winget().
// Calling it in the overriden Login, such as /mob/living/Login() doesn't cause this.
/mob/proc/update_interface()
spawn() // Spawn off so winget/winset don't delay callers.
if(client)
if(winget(src, "mainwindow.hotkey_toggle", "is-checked") == "true")
update_hotkey_mode()
else
update_normal_mode()
/mob/proc/update_hotkey_mode()
var/hotkeyname = "hotkeymode"
if(client)
var/hotkeys = client.hotkeylist[client.hotkeytype]
hotkeyname = hotkeys[client.hotkeyon ? "on" : "off"]
client.hotkeyon = 1
winset(src, null, "mainwindow.macro=[hotkeyname] hotkey_toggle.is-checked=true mapwindow.map.focus=true input.background-color=#F0F0F0")
/mob/proc/update_normal_mode()
var/hotkeyname = "macro"
if(client)
var/hotkeys = client.hotkeylist[client.hotkeytype]//get the list containing the hotkey names
hotkeyname = hotkeys[client.hotkeyon ? "on" : "off"]//get the name of the hotkey, to not clutter winset() to much
client.hotkeyon = 0
winset(src, null, "mainwindow.macro=[hotkeyname] hotkey_toggle.is-checked=false input.focus=true input.background-color=#D3B5B5")
+3
View File
@@ -173,6 +173,9 @@
//SSD var, changed it up some so people can have special things happen for different mobs when SSD.
var/player_logged = 0
//Ghosted var, set only if a player has manually ghosted out of this mob.
var/player_ghosted = 0
var/turf/listed_turf = null //the current turf being examined in the stat panel
var/list/shouldnt_see = list(/atom/movable/lighting_overlay) //list of objects that this mob shouldn't see in the stat panel. this silliness is needed because of AI alt+click and cult blood runes
+3 -2
View File
@@ -39,7 +39,7 @@ var/global/image/typing_indicator
set_typing_indicator(1)
hud_typing = 1
var/message = input("","say (text)") as null|text
var/message = typing_input(src, "", "say (text)")
hud_typing = 0
set_typing_indicator(0)
if(message)
@@ -49,9 +49,10 @@ var/global/image/typing_indicator
set name = ".Me"
set hidden = 1
set_typing_indicator(1)
hud_typing = 1
var/message = input("","me (text)") as null|text
var/message = typing_input(src, "", "me (text)")
hud_typing = 0
set_typing_indicator(0)
if(message)
+5 -14
View File
@@ -283,34 +283,25 @@ var/global/list/fax_blacklist = list()
use_power(200)
var/obj/item/rcvdcopy
if(istype(copyitem, /obj/item/paper))
rcvdcopy = copy(copyitem)
else if(istype(copyitem, /obj/item/photo))
rcvdcopy = photocopy(copyitem)
else if(istype(copyitem, /obj/item/paper_bundle))
rcvdcopy = bundlecopy(copyitem)
else
if(!(istype(copyitem, /obj/item/paper) || istype(copyitem, /obj/item/paper_bundle) || istype(copyitem, /obj/item/photo)))
visible_message("[src] beeps, \"Error transmitting message.\"")
return
rcvdcopy.loc = null //hopefully this shouldn't cause trouble
var/datum/fax/admin/A = new /datum/fax/admin()
A.name = rcvdcopy.name
A.name = copyitem.name
A.from_department = department
A.to_department = destination
A.origin = src
A.message = rcvdcopy
A.message = copyitem
A.sent_by = sender
A.sent_at = world.time
//message badmins that a fax has arrived
switch(destination)
if("Central Command")
message_admins(sender, "CENTCOM FAX", destination, rcvdcopy, "#006100")
message_admins(sender, "CENTCOM FAX", destination, copyitem, "#006100")
if("Syndicate")
message_admins(sender, "SYNDICATE FAX", destination, rcvdcopy, "#DC143C")
message_admins(sender, "SYNDICATE FAX", destination, copyitem, "#DC143C")
for(var/obj/machinery/photocopier/faxmachine/F in allfaxes)
if(F.department == destination)
F.receivefax(copyitem)
+1 -1
View File
@@ -218,7 +218,7 @@ var/const/INGEST = 2
/datum/reagents/proc/metabolize(mob/living/M)
if(M)
set_reagent_temp(M.bodytemperature)
temperature_reagents(M.bodytemperature - 30)
// a bitfield filled in by each reagent's `on_mob_life` to find out which states to update
var/update_flags = STATUS_UPDATE_NONE
@@ -765,7 +765,7 @@
/datum/reagent/consumable/ethanol/sbiten/on_mob_life(mob/living/M)
if(M.bodytemperature < 360)
M.bodytemperature = min(360, M.bodytemperature + (50 * TEMPERATURE_DAMAGE_COEFFICIENT)) //310 is the normal bodytemp. 310.055
..()
return ..()
/datum/reagent/consumable/ethanol/devilskiss
name = "Devils Kiss"
@@ -819,7 +819,7 @@
/datum/reagent/consumable/ethanol/iced_beer/on_mob_life(mob/living/M)
if(M.bodytemperature > 270)
M.bodytemperature = max(270, M.bodytemperature - (20 * TEMPERATURE_DAMAGE_COEFFICIENT)) //310 is the normal bodytemp. 310.055
..()
return ..()
/datum/reagent/consumable/ethanol/grog
name = "Grog"
@@ -1178,7 +1178,7 @@
if(prob(25))
holder.remove_reagent(id, 15)
M.fakevomit()
..()
return ..()
/datum/reagent/consumable/ethanol/synthanol/reaction_mob(mob/living/M, method=TOUCH, volume)
if(M.isSynthetic())
@@ -42,7 +42,7 @@
/datum/reagent/consumable/drink/cold/ice/on_mob_life(mob/living/M)
M.bodytemperature = max(M.bodytemperature - 5 * TEMPERATURE_DAMAGE_COEFFICIENT, 0)
..()
return ..()
/datum/reagent/consumable/drink/cold/space_cola
name = "Cola"
@@ -448,7 +448,7 @@
/datum/reagent/consumable/egg/on_mob_life(mob/living/M)
if(prob(3))
M.reagents.add_reagent("cholesterol", rand(1,2))
..()
return ..()
/datum/reagent/consumable/corn_starch
name = "Corn Starch"
@@ -643,9 +643,6 @@
color = "#684435"
taste_message = "burritos"
/datum/reagent/consumable/beans/on_mob_life(mob/living/M)
return ..()
/datum/reagent/consumable/bread
name = "Bread"
id = "bread"
@@ -5,6 +5,7 @@
/datum/reagent/medicine/on_mob_life(mob/living/M)
current_cycle++
holder.remove_reagent(id, (metabolization_rate / M.metabolism_efficiency) * M.digestion_ratio) //medicine reagents stay longer if you have a better metabolism
return STATUS_UPDATE_NONE
/datum/reagent/medicine/hydrocodone
name = "Hydrocodone"
@@ -526,6 +527,7 @@
taste_message = "a delightful numbing"
/datum/reagent/medicine/morphine/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
M.AdjustJitter(-25)
switch(current_cycle)
if(1 to 15)
@@ -534,9 +536,9 @@
if(16 to 35)
M.Drowsy(20)
if(36 to INFINITY)
M.Paralyse(15)
update_flags |= M.Paralyse(15, FALSE)
M.Drowsy(20)
..()
return ..() | update_flags
/datum/reagent/medicine/oculine
name = "Oculine"
@@ -669,7 +671,7 @@
update_flags |= M.adjustToxLoss(2*REAGENTS_EFFECT_MULTIPLIER, FALSE)
return ..() | update_flags
/datum/reagent/medicine/strange_reagent/reaction_mob(mob/living/M, method=TOUCH, volume)
/datum/reagent/medicine/strange_reagent/reaction_mob(mob/living/M, method = TOUCH, volume)
if(volume < 1)
// gotta pay to play
return ..()
@@ -682,25 +684,19 @@
SM.visible_message("<span class='warning'>[M] seems to rise from the dead!</span>")
if(iscarbon(M))
if(method == INGEST)
if(method == INGEST || (method == TOUCH && prob(25)))
if(M.stat == DEAD)
if(M.getBruteLoss()+M.getFireLoss()+M.getCloneLoss() >= 150)
if(M.getBruteLoss() + M.getFireLoss() + M.getCloneLoss() >= 150)
M.delayed_gib()
return
var/mob/dead/observer/ghost = M.get_ghost()
if(ghost)
to_chat(ghost, "<span class='ghostalert'>A Strange Reagent is infusing your body with life. Return to your body if you want to be revived!</span> (Verbs -> Ghost -> Re-enter corpse)")
window_flash(ghost.client)
ghost << sound('sound/effects/genetics.ogg')
M.visible_message("<span class='notice'>[M] doesn't appear to respond, perhaps try again later?</span>")
if(!M.suiciding && !ghost && !(NOCLONE in M.mutations) && (M.mind && M.mind.is_revivable()))
if(!M.suiciding && !(NOCLONE in M.mutations) && (!M.mind || M.mind && M.mind.is_revivable()))
var/time_dead = world.time - M.timeofdeath
M.visible_message("<span class='warning'>[M] seems to rise from the dead!</span>")
M.adjustCloneLoss(50)
M.setOxyLoss(0)
M.adjustBruteLoss(rand(0,15))
M.adjustToxLoss(rand(0,15))
M.adjustFireLoss(rand(0,15))
M.adjustBruteLoss(rand(0, 15))
M.adjustToxLoss(rand(0, 15))
M.adjustFireLoss(rand(0, 15))
if(ishuman(M))
var/mob/living/carbon/human/H = M
var/necrosis_prob = 40 * min((20 MINUTES), max((time_dead - (1 MINUTES)), 0)) / ((20 MINUTES) - (1 MINUTES))
@@ -715,8 +711,8 @@
O.germ_level = INFECTION_LEVEL_THREE
H.update_body()
M.grab_ghost()
M.update_revive()
M.stat = UNCONSCIOUS
add_attack_logs(M, M, "Revived with strange reagent") //Yes, the logs say you revived yourself.
..()
@@ -759,7 +755,7 @@
if(ishuman(M))
var/mob/living/carbon/human/H = M
H.update_mutations()
..()
return ..()
/datum/reagent/medicine/antihol
name = "Antihol"
@@ -857,6 +853,7 @@
/datum/reagent/medicine/insulin/on_mob_life(mob/living/M)
M.reagents.remove_reagent("sugar", 5)
return ..()
/datum/reagent/medicine/teporone
name = "Teporone"
@@ -873,7 +870,7 @@
M.bodytemperature = max(310, M.bodytemperature - (40 * TEMPERATURE_DAMAGE_COEFFICIENT))
else if(M.bodytemperature < 311)
M.bodytemperature = min(310, M.bodytemperature + (40 * TEMPERATURE_DAMAGE_COEFFICIENT))
..()
return ..()
/datum/reagent/medicine/haloperidol
name = "Haloperidol"
@@ -916,6 +913,7 @@
taste_message = "sleepiness"
/datum/reagent/medicine/ether/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
M.AdjustJitter(-25)
switch(current_cycle)
if(1 to 30)
@@ -924,9 +922,9 @@
if(31 to 40)
M.Drowsy(20)
if(41 to INFINITY)
M.Paralyse(15)
update_flags |= M.Paralyse(15, FALSE)
M.Drowsy(20)
..()
return ..() | update_flags
/datum/reagent/medicine/syndicate_nanites //Used exclusively by Syndicate medical cyborgs
name = "Restorative Nanites"
@@ -162,7 +162,7 @@
if(!H.dna.species.exotic_blood && !(NO_BLOOD in H.dna.species.species_traits))
if(H.blood_volume < BLOOD_VOLUME_NORMAL)
H.blood_volume += 0.8
..()
return ..()
/datum/reagent/iron/reaction_mob(mob/living/M, method=TOUCH, volume)
if(M.has_bane(BANE_IRON) && holder && holder.chem_temp < 150) //If the target is weak to cold iron, then poison them.
@@ -31,7 +31,7 @@
var/turf/simulated/T = get_turf(M)
goonchem_vortex(T, 1, 0)
to_chat(M, "<span class='notice'>You briefly feel super-massive, like a black hole. Probably just your imagination...</span>")
..()
return ..()
//Berry Banned: This one is tasty and safe to drink, might have a low chance of healing a random damage type?
/datum/reagent/consumable/drink/berry_banned

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