mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-21 12:04:48 +01:00
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:
@@ -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" = (
|
||||
|
||||
@@ -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
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 <)
|
||||
|
||||
// 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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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 ..()
|
||||
+126
-111
@@ -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].")
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
@@ -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(), \
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
@@ -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!
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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]")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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://"))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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>")
|
||||
|
||||
@@ -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)]->[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,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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>")
|
||||
@@ -14,7 +14,3 @@
|
||||
|
||||
/mob/camera/experience_pressure_difference()
|
||||
return
|
||||
|
||||
/mob/camera/Login()
|
||||
..()
|
||||
update_interface()
|
||||
|
||||
@@ -7,5 +7,3 @@
|
||||
if(GLOB.non_respawnable_keys[ckey])
|
||||
can_reenter_corpse = 0
|
||||
GLOB.respawnable_list -= src
|
||||
|
||||
update_interface()
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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()
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user