Merge branch 'master' into set_species

# Conflicts:
#	code/game/gamemodes/changeling/powers/transform.dm
This commit is contained in:
Birdtalon
2018-10-05 23:41:34 +01:00
504 changed files with 22781 additions and 10346 deletions
+3 -3
View File
@@ -60,9 +60,9 @@ var/global/nologevent = 0
body += "<a href='?_src_=holder;traitor=\ref[M]'>TP</a> - "
body += "<a href='?src=[usr.UID()];priv_msg=\ref[M]'>PM</a> - "
body += "<a href='?_src_=holder;subtlemessage=\ref[M]'>SM</a> - "
body += "[admin_jump_link(M)]\] </b><br>"
if(ishuman(M) && M.mind)
body += "<a href='?_src_=holder;HeadsetMessage=[M.UID()]'>HM</a>"
body += "<a href='?_src_=holder;HeadsetMessage=[M.UID()]'>HM</a> -"
body += "[admin_jump_link(M)]\] </b><br>"
body += "<b>Mob type:</b> [M.type]<br>"
if(M.client)
if(M.client.related_accounts_cid.len)
@@ -566,7 +566,7 @@ var/global/nologevent = 0
if(!check_rights(R_SERVER,0))
message = adminscrub(message,500)
message = replacetext(message, "\n", "<br>") // required since we're putting it in a <p> tag
to_chat(world, "<span class=notice><b>[usr.client.holder.fakekey ? "Administrator" : usr.key] Announces:</b><p style='text-indent: 50px'>[message]</p></span>")
to_chat(world, "<span class='notice'><b>[usr.client.holder.fakekey ? "Administrator" : usr.key] Announces:</b><p style='text-indent: 50px'>[message]</p></span>")
log_admin("Announce: [key_name(usr)] : [message]")
feedback_add_details("admin_verb","A") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-1
View File
@@ -170,7 +170,6 @@ var/list/admin_verbs_debug = list(
/client/proc/admin_serialize,
/client/proc/jump_to_ruin,
/client/proc/toggle_medal_disable,
/client/proc/startadmintickets,
)
var/list/admin_verbs_possess = list(
/proc/possess,
+3 -3
View File
@@ -407,11 +407,11 @@
dat += "Current Game Mode: <B>[ticker.mode.name]</B><BR>"
dat += "Round Duration: <B>[round(ROUND_TIME / 36000)]:[add_zero(num2text(ROUND_TIME / 600 % 60), 2)]:[add_zero(num2text(ROUND_TIME / 10 % 60), 2)]</B><BR>"
dat += "<B>Emergency shuttle</B><BR>"
if(shuttle_master.emergency.mode < SHUTTLE_CALL)
if(SSshuttle.emergency.mode < SHUTTLE_CALL)
dat += "<a href='?src=[UID()];call_shuttle=1'>Call Shuttle</a><br>"
else
var/timeleft = shuttle_master.emergency.timeLeft()
if(shuttle_master.emergency.mode < SHUTTLE_DOCKED)
var/timeleft = SSshuttle.emergency.timeLeft()
if(SSshuttle.emergency.mode < SHUTTLE_DOCKED)
dat += "ETA: <a href='?_src_=holder;edit_shuttle_time=1'>[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]</a><BR>"
dat += "<a href='?_src_=holder;call_shuttle=2'>Send Back</a><br>"
else
-185
View File
@@ -1,185 +0,0 @@
/*
Admin ticket system by Birdtalon
*/
//Global holder
var/global/datum/adminTicketHolder/globAdminTicketHolder = new /datum/adminTicketHolder
//Defines
//Deciseconds until ticket becomes stale if unanswered. Alerts admins.
#define ADMIN_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
//Status defines
#define ADMIN_TICKET_OPEN 1
#define ADMIN_TICKET_CLOSED 2
#define ADMIN_TICKET_RESOLVED 3
#define ADMIN_TICKET_STALE 4
//Datum holding all tickets
/datum/adminTicketHolder
var/ticketCounter = 1 // Counts the tickets and used to assign the id number
var/list/allTickets = list()
//Return the current ticket number ready to be called off.
/datum/adminTicketHolder/proc/getTicketCounter()
return ticketCounter
//Return the ticket counter and increment
/datum/adminTicketHolder/proc/getTicketCounterAndInc()
. = ticketCounter
ticketCounter++
return
/datum/adminTicketHolder/proc/resolveAllOpenTickets() // Resolve all open tickets
for(var/i in allTickets)
var/datum/admin_ticket/T = i
resolveTicket(T.ticketNum)
//Open a new ticket and populate details then add to the list of open tickets
/datum/adminTicketHolder/proc/newTicket(var/client/C, var/passedContent, var/title)
if(!C || !passedContent)
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)
if(existingTicket)
existingTicket.setCooldownPeriod()
to_chat(C, "<span class='adminticket'>Your ticket #[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 /datum/admin_ticket
T.clientName = C
T.timeOpened = worldtime2text()
T.title = title
T.content += passedContent
T.locationSent = C.mob.loc.loc.name
T.mobControlled = C.mob
T.ticketState = ADMIN_TICKET_OPEN
T.timeUntilStale = world.time + ADMIN_TICKET_TIMEOUT
T.setCooldownPeriod()
T.ticketNum = getTicketCounterAndInc()
allTickets += T
//Inform the user that they have opened a ticket
to_chat(C, "<span class='adminticket'>You have opened admin ticket number #[(globAdminTicketHolder.getTicketCounter() - 1)]! Please be patient and we will help you soon!</span>")
//Begin the stale count for this ticket.
spawn(0)
T.beginStaleCount()
//Set ticket state with key N to open
/datum/adminTicketHolder/proc/openTicket(var/N)
var/datum/admin_ticket/T = globAdminTicketHolder.allTickets[N]
if(T.ticketState != ADMIN_TICKET_OPEN)
T.ticketState = ADMIN_TICKET_OPEN
return TRUE
//Set ticket state with key N to resolved
/datum/adminTicketHolder/proc/resolveTicket(var/N)
var/datum/admin_ticket/T = globAdminTicketHolder.allTickets[N]
if(T.ticketState != ADMIN_TICKET_RESOLVED)
T.ticketState = ADMIN_TICKET_RESOLVED
return TRUE
//Set ticket state with key N to closed
/datum/adminTicketHolder/proc/closeTicket(var/N)
var/datum/admin_ticket/T = globAdminTicketHolder.allTickets[N]
if(T.ticketState != ADMIN_TICKET_CLOSED)
T.ticketState = ADMIN_TICKET_CLOSED
return TRUE
//Check if the user already has a ticket open and within the cooldown period.
/datum/adminTicketHolder/proc/checkForOpenTicket(var/client/C)
for(var/datum/admin_ticket/T in allTickets)
if(T.clientName == C && T.ticketState == ADMIN_TICKET_OPEN && (T.ticketCooldown > world.time))
return T
return FALSE
//Check if the user has ANY ticket not resolved or closed.
/datum/adminTicketHolder/proc/checkForTicket(var/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))
tickets += T
if(tickets.len)
return tickets
return FALSE
//return the client of a ticket number
/datum/adminTicketHolder/proc/returnClient(var/N)
var/datum/admin_ticket/T = globAdminTicketHolder.allTickets[N]
return T.clientName
/datum/adminTicketHolder/proc/assignAdminToTicket(var/client/C, var/N)
var/datum/admin_ticket/T = globAdminTicketHolder.allTickets[N]
T.assignAdmin(C)
return TRUE
//Single admin ticket
/datum/admin_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 = list() // content of the admin help
var/lastAdminResponse // Last admin who responded
var/lastResponseTime // When the admin 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
//Ticker called when a ticket is created, checks for stale-ness.
/datum/admin_ticket/proc/beginStaleCount()
while(world.time < timeUntilStale || !lastAdminResponse || !adminAssigned) // While within the stale period OR no admin responded OR no admin assigned.
if(!src)
return
sleep(200) // Check every 20 seconds.
if(ticketState == ADMIN_TICKET_OPEN && world.time > timeUntilStale)
message_adminTicket("<span class='adminticket'>Ticket #[ticketNum] has been open for [ADMIN_TICKET_TIMEOUT * 0.1] seconds. Changing status to stale.</span>")
ticketState = ADMIN_TICKET_STALE
break
//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
//Set the last admin who responded as the client passed as an arguement.
/datum/admin_ticket/proc/setLastAdminResponse(var/client/C)
lastAdminResponse = C
lastResponseTime = worldtime2text()
//Return the ticket state as a colour coded text string.
/datum/admin_ticket/proc/state2text()
switch(ticketState)
if(ADMIN_TICKET_OPEN)
return "<font color='green'>OPEN</font>"
if(ADMIN_TICKET_RESOLVED)
return "<font color='blue'>RESOLVED</font>"
if(ADMIN_TICKET_CLOSED)
return "<font color='red'>CLOSED</font>"
if(ADMIN_TICKET_STALE)
return "<font color='orange'>STALE</font>"
//Assign the client passed to var/adminAsssigned
/datum/admin_ticket/proc/assignAdmin(var/client/C, var/N)
if(!C)
return
adminAssigned = C
return TRUE
/datum/admin_ticket/proc/addResponse(var/client/C, var/M as text)
if(C.holder)
setLastAdminResponse(C)
M = "[C]: [M]"
content += M
@@ -1,172 +0,0 @@
/datum/adminTicketHolder/proc/returnUI(var/tab = ADMIN_TICKET_OPEN)
set name = "Open Ticket Interface"
set category = "Tickets"
//dat
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/dat
dat += "<head><style>.adminticket{border:2px solid}</style></head>"
dat += "<body><h1>Admin Tickets</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)
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)
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>"
else
continue
else if(tab == ADMIN_TICKET_RESOLVED)
dat += "<h2>Resolved Tickets</h2>"
for(var/T in allTickets)
ticket = T
if(ticket.ticketState == ADMIN_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)
dat += "<h2>Closed Tickets</h2>"
for(var/T in allTickets)
ticket = T
if(ticket.ticketState == ADMIN_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
dat += "</table></body>"
return dat
/datum/adminTicketHolder/proc/showUI(var/client/user, var/tab)
var/dat = null
dat = returnUI(tab)
var/datum/browser/popup = new(user, "admintickets", "Admin Tickets", 1400, 600)
popup.set_content(dat)
popup.open()
/datum/adminTicketHolder/proc/showDetailUI(var/client/user, var/ticketID)
var/datum/admin_ticket/T = globAdminTicketHolder.allTickets[ticketID]
var/status = "[T.state2text()]"
var/dat = "<h1>Admin Tickets</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 += "<h4>Ticket Status: <font color='red'>[status]</font>"
dat += "<table style='width:950px; border: 3px solid;'>"
dat += "<tr><td>[T.title]</td></tr>"
if(T.content.len > 1)
for(var/i = 2, i <= T.content.len, i++)
dat += "<tr><td>[T.content[i]]</td></tr>"
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 />"
else
dat += "[T.adminAssigned] is assigned to this Ticket. - <a href='?src=[UID()];assignadmin=[T.ticketNum]'>Take Ticket</a><br />"
if(T.lastAdminResponse)
dat += "<b>Last Admin Response:</b> [T.lastAdminResponse] at [T.lastResponseTime]"
else
dat +="<font color='red'>No Admin 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)
popup.set_content(dat)
popup.open()
/datum/adminTicketHolder/proc/userDetailUI(var/client/user)
//dat
var/tickets = checkForTicket(user)
var/dat
dat += "<h1>Your open tickets</h1>"
dat += "<table>"
for(var/datum/admin_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)
popup.set_content(dat)
popup.open()
/datum/adminTicketHolder/Topic(href, href_list)
if(href_list["refresh"])
showUI(usr)
return
if(href_list["refreshdetail"])
var/indexNum = text2num(href_list["refreshdetail"])
showDetailUI(usr, indexNum)
return
if(href_list["showopen"])
showUI(usr, ADMIN_TICKET_OPEN)
return
if(href_list["showresolved"])
showUI(usr, ADMIN_TICKET_RESOLVED)
return
if(href_list["showclosed"])
showUI(usr, ADMIN_TICKET_CLOSED)
return
if(href_list["details"])
var/indexNum = text2num(href_list["details"])
showDetailUI(usr.client, indexNum)
return
if(href_list["resolve"])
var/indexNum = text2num(href_list["resolve"])
if(globAdminTicketHolder.resolveTicket(indexNum))
message_adminTicket("[usr.client] / ([usr]) resolved admin ticket number [indexNum]")
to_chat(returnClient(indexNum), "<span class='adminticket'>Your admin ticket has now been resolved.</span>")
showUI(usr)
if(href_list["detailresolve"])
var/indexNum = text2num(href_list["detailresolve"])
if(globAdminTicketHolder.resolveTicket(indexNum))
message_adminTicket("[usr.client] / ([usr]) resolved admin ticket number [indexNum]")
to_chat(returnClient(indexNum), "<span class='adminticket'>Your admin ticket has now been resolved.</span>")
showDetailUI(usr, indexNum)
if(href_list["detailclose"])
var/indexNum = text2num(href_list["detailclose"])
if(alert("Are you sure? This will send a negative message.",,"Yes","No") != "Yes")
return
if(globAdminTicketHolder.closeTicket(indexNum))
message_adminTicket("[usr.client] / ([usr]) closed admin ticket number [indexNum]")
to_chat(returnClient(indexNum), "<font color='red' size='4'><b>- AdminHelp Rejected! -</b></font>")
to_chat(returnClient(indexNum), "<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>")
to_chat(returnClient(indexNum), "<span class='adminticket'>Your ticket has now been closed.</span>")
showDetailUI(usr, indexNum)
if(href_list["detailreopen"])
var/indexNum = text2num(href_list["detailreopen"])
if(globAdminTicketHolder.openTicket(indexNum))
message_adminTicket("[usr.client] / ([usr]) re-opened admin ticket number [indexNum]")
showDetailUI(usr, indexNum)
if(href_list["assignadmin"])
var/indexNum = text2num(href_list["assignadmin"])
if(globAdminTicketHolder.assignAdminToTicket(usr.client, indexNum))
message_adminTicket("[usr.client] / ([usr]) has taken ticket number [indexNum]")
to_chat(returnClient(indexNum), "<span class='adminticket'>Your ticket is being handled by [usr.client].")
showDetailUI(usr, indexNum)
@@ -1,51 +1,33 @@
//Verbs
/client/proc/startadmintickets()
set name = "Restart Admin Ticket System"
set category = "Debug"
if(!holder && !check_rights(R_DEBUG))
return
if(!globAdminTicketHolder)
var/global/datum/adminTicketHolder/globAdminTicketHolder = new /datum/adminTicketHolder
else
if(alert("Are you sure you want to reboot the admin ticket system?","Reboot Admin Tickets?","Yes","No") != "Yes")
return
message_admins("<span class='admintickets'>Restarting Admin Ticket System!</span>")
globAdminTicketHolder = new /datum/adminTicketHolder
message_admins("<span class='admintickets'>Admin Ticket System Restarted!</span>")
/client/proc/openTicketUI()
set name = "Open Ticket Interface"
set category = "Admin"
if(!holder && !check_rights(R_ADMIN))
if(!holder || !check_rights(R_ADMIN))
return
globAdminTicketHolder.showUI(usr)
SStickets.showUI(usr)
/client/proc/resolveAllTickets()
set name = "Resolve All Open Tickets"
set category = "Admin"
if(!holder && !check_rights(R_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
globAdminTicketHolder.resolveAllOpenTickets()
SStickets.resolveAllOpenTickets()
/client/proc/openUserUI()
set name = "My Tickets"
set category = "Admin"
if(!holder && !check_rights(R_ADMIN))
if(!holder || !check_rights(R_ADMIN))
return
globAdminTicketHolder.userDetailUI(usr.client)
SStickets.userDetailUI(usr)
+14 -15
View File
@@ -30,7 +30,7 @@
if(!check_rights(R_ADMIN))
return
var/ticketID = text2num(href_list["openadminticket"])
globAdminTicketHolder.showDetailUI(usr, ticketID)
SStickets.showDetailUI(usr, ticketID)
if(href_list["stickyban"])
stickyban(href_list["stickyban"],href_list)
@@ -274,22 +274,22 @@
switch(href_list["call_shuttle"])
if("1")
if(shuttle_master.emergency.mode >= SHUTTLE_DOCKED)
if(SSshuttle.emergency.mode >= SHUTTLE_DOCKED)
return
shuttle_master.emergency.request()
SSshuttle.emergency.request()
log_admin("[key_name(usr)] called the Emergency Shuttle")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] called the Emergency Shuttle to the station</span>")
if("2")
if(shuttle_master.emergency.mode >= SHUTTLE_DOCKED)
if(SSshuttle.emergency.mode >= SHUTTLE_DOCKED)
return
switch(shuttle_master.emergency.mode)
switch(SSshuttle.emergency.mode)
if(SHUTTLE_CALL)
shuttle_master.emergency.cancel()
SSshuttle.emergency.cancel()
log_admin("[key_name(usr)] sent the Emergency Shuttle back")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] sent the Emergency Shuttle back</span>")
else
shuttle_master.emergency.cancel()
SSshuttle.emergency.cancel()
log_admin("[key_name(usr)] called the Emergency Shuttle")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] called the Emergency Shuttle to the station</span>")
@@ -299,10 +299,10 @@
else if(href_list["edit_shuttle_time"])
if(!check_rights(R_SERVER)) return
var/timer = input("Enter new shuttle duration (seconds):","Edit Shuttle Timeleft", shuttle_master.emergency.timeLeft() ) as num
shuttle_master.emergency.setTimer(timer*10)
var/timer = input("Enter new shuttle duration (seconds):","Edit Shuttle Timeleft", SSshuttle.emergency.timeLeft() ) as num
SSshuttle.emergency.setTimer(timer*10)
log_admin("[key_name(usr)] edited the Emergency Shuttle's timeleft to [timer] seconds")
minor_announcement.Announce("The emergency shuttle will reach its destination in [round(shuttle_master.emergency.timeLeft(600))] minutes.")
minor_announcement.Announce("The emergency shuttle will reach its destination in [round(SSshuttle.emergency.timeLeft(600))] minutes.")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] edited the Emergency Shuttle's timeleft to [timer] seconds</span>")
href_list["secrets"] = "check_antagonist"
@@ -1216,8 +1216,7 @@
//strip their stuff and stick it in the crate
for(var/obj/item/I in M)
M.unEquip(I)
if(I)
if(M.unEquip(I))
I.loc = locker
I.layer = initial(I.layer)
I.plane = initial(I.plane)
@@ -2860,21 +2859,21 @@
if("moveminingshuttle")
feedback_inc("admin_secrets_fun_used",1)
feedback_add_details("admin_secrets_fun_used","ShM")
if(!shuttle_master.toggleShuttle("mining","mining_home","mining_away"))
if(!SSshuttle.toggleShuttle("mining","mining_home","mining_away"))
message_admins("[key_name_admin(usr)] moved mining shuttle")
log_admin("[key_name(usr)] moved the mining shuttle")
if("movelaborshuttle")
feedback_inc("admin_secrets_fun_used",1)
feedback_add_details("admin_secrets_fun_used","ShL")
if(!shuttle_master.toggleShuttle("laborcamp","laborcamp_home","laborcamp_away"))
if(!SSshuttle.toggleShuttle("laborcamp","laborcamp_home","laborcamp_away"))
message_admins("[key_name_admin(usr)] moved labor shuttle")
log_admin("[key_name(usr)] moved the labor shuttle")
if("moveferry")
feedback_inc("admin_secrets_fun_used",1)
feedback_add_details("admin_secrets_fun_used","ShF")
if(!shuttle_master.toggleShuttle("ferry","ferry_home","ferry_away"))
if(!SSshuttle.toggleShuttle("ferry","ferry_home","ferry_away"))
message_admins("[key_name_admin(usr)] moved the centcom ferry")
log_admin("[key_name(usr)] moved the centcom ferry")
+4 -4
View File
@@ -117,15 +117,15 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","
if("Adminhelp")
var/ticketNum // Holder for the ticket number
var/prunedmsg ="[usr.client]: [msg]" // Message without links
if(globAdminTicketHolder.checkForOpenTicket(usr.client)) // If user already has an open ticket
var/datum/admin_ticket/T = globAdminTicketHolder.checkForOpenTicket(usr.client) // Make T equal to the ticket they have open
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 = globAdminTicketHolder.getTicketCounter() // ticketNum is the ticket ready to be assigned.
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)] (<A HREF='?_src_=holder;adminmoreinfo=[ref_mob]'>?</A>) (<A HREF='?_src_=holder;adminplayeropts=[ref_mob]'>PP</A>) (<A HREF='?_src_=vars;Vars=[mob.UID()]'>VV</A>) (<A HREF='?_src_=holder;subtlemessage=[ref_mob]'>SM</A>) ([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=[ref_mob]'>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.
globAdminTicketHolder.newTicket(src, prunedmsg, msg)
SStickets.newTicket(src, prunedmsg, msg)
for(var/client/X in modholders + adminholders)
if(X.prefs.sound & SOUND_ADMINHELP)
X << 'sound/effects/adminhelp.ogg'
+3 -3
View File
@@ -187,15 +187,15 @@
return
//Check if the mob being PM'd has any open admin tickets.
var/tickets = list()
tickets = globAdminTicketHolder.checkForTicket(C)
tickets = SStickets.checkForTicket(C)
if(tickets)
for(var/datum/admin_ticket/i in tickets)
i.addResponse(src, msg) // Add this response to their open tickets.
return
tickets = globAdminTicketHolder.checkForTicket(src)
tickets = SStickets.checkForTicket(C)
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 = globAdminTicketHolder.checkForTicket(src)
tickets = SStickets.checkForTicket(C)
if(tickets)
for(var/datum/admin_ticket/i in tickets)
i.addResponse(src, msg)
+7 -1
View File
@@ -271,7 +271,13 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
return 0
var/obj/item/paicard/card = new(T)
var/mob/living/silicon/pai/pai = new(card)
pai.name = input(choice, "Enter your pAI name:", "pAI Name", "Personal AI") as text
var/raw_name = input(choice, "Enter your pAI name:", "pAI Name", "Personal AI") as text
var/new_name = reject_bad_name(raw_name, 1)
if(new_name)
pai.name = new_name
pai.real_name = new_name
else
to_chat(usr, "<font color='red'>Invalid name. Your name should be at least 2 and at most [MAX_NAME_LEN] characters long. It may only contain the characters A-Z, a-z, -, ' and .</font>")
pai.real_name = pai.name
pai.key = choice.key
card.setPersonality(pai)
+1 -1
View File
@@ -32,7 +32,7 @@ client/proc/one_click_antag()
if(M.stat || !M.mind || M.mind.special_role)
return FALSE
if(temp)
if(M.mind.assigned_role in temp.restricted_jobs || M.client.prefs.species in temp.protected_species)
if((M.mind.assigned_role in temp.restricted_jobs) || (M.client.prefs.species in temp.protected_species))
return FALSE
if(role) // Don't even bother evaluating if there's no role
if(player_old_enough_antag(M.client,role) && (role in M.client.prefs.be_special) && (!jobban_isbanned(M, role)))
+1 -1
View File
@@ -28,6 +28,7 @@
prayer_type = "CULTIST PRAYER"
deity = ticker.cultdat.entity_name
log_say("(PRAYER) [msg]", usr)
msg = "<span class='notice'>[bicon(cross)]<b><font color=[font_color]>[prayer_type][deity ? " (to [deity])" : ""]:</font>[key_name(src, 1)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[src]'>?</A>) (<A HREF='?_src_=holder;adminplayeropts=\ref[src]'>PP</A>) (<A HREF='?_src_=vars;Vars=[UID()]'>VV</A>) (<A HREF='?_src_=holder;subtlemessage=\ref[src]'>SM</A>) ([admin_jump_link(src)]) (<A HREF='?_src_=holder;secretsadmin=check_antagonist'>CA</A>) (<A HREF='?_src_=holder;adminspawncookie=\ref[src]'>SC</a>) (<A HREF='?_src_=holder;Bless=[UID()]'>BLESS</A>) (<A HREF='?_src_=holder;Smite=[UID()]'>SMITE</A>):</b> [msg]</span>"
for(var/client/X in admins)
@@ -36,7 +37,6 @@
to_chat(usr, "Your prayers have been received by the gods.")
feedback_add_details("admin_verb","PR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
//log_admin("HELP: [key_name(src)]: [msg]")
/proc/Centcomm_announce(var/text , var/mob/Sender)
var/msg = sanitize(copytext(text, 1, MAX_MESSAGE_LEN))
+16 -14
View File
@@ -435,6 +435,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
//Now for special roles and equipment.
switch(new_character.mind.special_role)
if("traitor")
job_master.AssignRank(new_character, new_character.mind.assigned_role, 0)
job_master.EquipRank(new_character, new_character.mind.assigned_role, 1)
ticker.mode.equip_traitor(new_character)
if("Wizard")
@@ -465,6 +466,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
call(/datum/game_mode/proc/add_law_zero)(new_character)
//Add aliens.
else
job_master.AssignRank(new_character, new_character.mind.assigned_role, 0)
job_master.EquipRank(new_character, new_character.mind.assigned_role, 1)//Or we simply equip them.
//Announces the character on all the systems, based on the record.
@@ -794,7 +796,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
set category = "Admin"
set name = "Call Shuttle"
if(shuttle_master.emergency.mode >= SHUTTLE_DOCKED)
if(SSshuttle.emergency.mode >= SHUTTLE_DOCKED)
return
if(!check_rights(R_ADMIN))
@@ -804,11 +806,11 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(confirm != "Yes") return
if(alert("Set Shuttle Recallable (Select Yes unless you know what this does)", "Recallable?", "Yes", "No") == "Yes")
shuttle_master.emergency.canRecall = TRUE
SSshuttle.emergency.canRecall = TRUE
else
shuttle_master.emergency.canRecall = FALSE
SSshuttle.emergency.canRecall = FALSE
shuttle_master.emergency.request()
SSshuttle.emergency.request()
feedback_add_details("admin_verb","CSHUT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] admin-called the emergency shuttle.")
@@ -823,20 +825,20 @@ Traitors and the like can also be revived with the previous role mostly intact.
return
if(alert(src, "You sure?", "Confirm", "Yes", "No") != "Yes") return
if(shuttle_master.emergency.mode >= SHUTTLE_DOCKED)
if(SSshuttle.emergency.mode >= SHUTTLE_DOCKED)
return
if(shuttle_master.emergency.canRecall == FALSE)
if(SSshuttle.emergency.canRecall == FALSE)
if(alert("Shuttle is currently set to be nonrecallable. Recalling may break things. Respect Recall Status?", "Override Recall Status?", "Yes", "No") == "Yes")
return
else
var/keepStatus = alert("Maintain recall status on future shuttle calls?", "Maintain Status?", "Yes", "No") == "Yes" //Keeps or drops recallability
shuttle_master.emergency.canRecall = TRUE // must be true for cancel proc to work
shuttle_master.emergency.cancel()
SSshuttle.emergency.canRecall = TRUE // must be true for cancel proc to work
SSshuttle.emergency.cancel()
if(keepStatus)
shuttle_master.emergency.canRecall = FALSE // restores original status
SSshuttle.emergency.canRecall = FALSE // restores original status
else
shuttle_master.emergency.cancel()
SSshuttle.emergency.cancel()
feedback_add_details("admin_verb","CCSHUT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] admin-recalled the emergency shuttle.")
@@ -853,11 +855,11 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(!check_rights(R_ADMIN))
return
if(shuttle_master)
shuttle_master.emergencyNoEscape = !shuttle_master.emergencyNoEscape
if(SSshuttle)
SSshuttle.emergencyNoEscape = !SSshuttle.emergencyNoEscape
log_admin("[key_name(src)] has [shuttle_master.emergencyNoEscape ? "denied" : "allowed"] the shuttle to be called.")
message_admins("[key_name_admin(usr)] has [shuttle_master.emergencyNoEscape ? "denied" : "allowed"] the shuttle to be called.")
log_admin("[key_name(src)] has [SSshuttle.emergencyNoEscape ? "denied" : "allowed"] the shuttle to be called.")
message_admins("[key_name_admin(usr)] has [SSshuttle.emergencyNoEscape ? "denied" : "allowed"] the shuttle to be called.")
/client/proc/cmd_admin_attack_log(mob/M as mob in mob_list)
set category = "Admin"
@@ -45,7 +45,7 @@
spawn_antag(C, get_turf(src.loc), "syndieborg")
else
checking = FALSE
to_chat(user, "<span class='notice'>Unable to connect to Syndicate command. Please wait and try again later or use the teleporter on your uplink to get your points refunded.</span>")
to_chat(user, "<span class='notice'>Unable to connect to Syndicate command. Please wait and try again later or refund your teleporter through your uplink.</span>")
return
/obj/item/antag_spawner/borg_tele/spawn_antag(client/C, turf/T, type = "")
+3 -24
View File
@@ -6,7 +6,7 @@
icon_state = "clawmachine_on"
density = 1
anchored = 1
use_power = 1
use_power = IDLE_POWER_USE
idle_power_usage = 40
var/tokens = 0
var/freeplay = 0 //for debugging and admin kindness
@@ -112,28 +112,7 @@
to_chat(user, "Unable to access account: incorrect credentials.")
return 0
if(token_price > customer_account.money)
to_chat(user, "Insufficient funds in account.")
return 0
else
// Okay to move the money at this point
// debit money from the purchaser's account
customer_account.money -= token_price
// create entry in the purchaser's account log
var/datum/transaction/T = new()
T.target_name = "[src.name]"
T.purpose = "Purchase of [src.name] credit"
if(token_price > 0)
T.amount = "([token_price])"
else
T.amount = "[token_price]"
T.source_terminal = src.name
T.date = current_date_string
T.time = station_time_timestamp()
customer_account.transaction_log.Add(T)
return 1
return customer_account.charge(token_price, null, "Purchase of [name] credit", name, name)
/obj/machinery/arcade/proc/start_play(mob/user as mob)
user.set_machine(src)
@@ -159,4 +138,4 @@
/obj/machinery/arcade/Destroy()
src.close_game()
return ..()
return ..()
+7 -9
View File
@@ -9,7 +9,6 @@
window_name = "Claw Game"
var/machine_image = "_1"
var/bonus_prize_chance = 5 //chance to dispense a SECOND prize if you win, increased by matter bin rating
//This is to make sure the images are available
var/list/img_resources = list('icons/obj/arcade_images/backgroundsprite.png',
'icons/obj/arcade_images/clawpieces.png',
@@ -49,26 +48,25 @@
icon_state = "clawmachine[machine_image]_off"
else
icon_state = "clawmachine[machine_image]_on"
return
/obj/machinery/arcade/claw/win()
icon_state = "clawmachine[machine_image]_win"
visible_message("<span class='game say'><span class='name'>[src.name]</span> beeps, \"WINNER!\"</span>")
if(prob(bonus_prize_chance))
//double prize mania!
if(prob(bonus_prize_chance)) //double prize mania!
atom_say("DOUBLE PRIZE!")
new /obj/item/toy/prizeball(get_turf(src))
else
atom_say("WINNER!")
new /obj/item/toy/prizeball(get_turf(src))
playsound(src.loc, 'sound/arcade/Win.ogg', 50, 1, extrarange = -3, falloff = 10)
spawn(10)
update_icon()
addtimer(CALLBACK(src, .update_icon), 10)
/obj/machinery/arcade/claw/start_play(mob/user as mob)
..()
user << browse_rsc('page.css')
for(var/i=1, i<=img_resources.len, i++)
for(var/i in 1 to img_resources.len)
user << browse_rsc(img_resources[i])
var/my_game_html = replacetext(claw_game_html, "/* ref src */", UID())
user << browse(my_game_html, "window=[window_name];size=700x600")
user << browse(my_game_html, "window=[window_name];size=915x600;can_resize=0")
/obj/machinery/arcade/claw/Topic(href, list/href_list)
if(..())
+71 -78
View File
@@ -2,7 +2,7 @@
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Crane game</title>
<title>Claw Game</title>
<link rel="stylesheet" type="text/css" href="page.css" />
<script src="libraries.min.js"></script>
<!-- Prize.js --><script>
@@ -22,7 +22,6 @@
$(pic).append(ball);
$('#game').append(pic);
//console.log(crane);
this.GetState = function() {return state};
var CheckBoundaries = function () {
@@ -38,12 +37,11 @@
top = 347;
state = 'resting';
} else if(top > 500 && state =='won') {
top=500;
top = 500;
}
};
var CheckGrabbed = function() {
var tmp = Math.floor(Math.random()*100);
if(tmp>error) {
setTimeout(function(){
@@ -51,8 +49,9 @@
$('#debug-streak').html(0); //reset streak
setTimeout(gameShutDown,500); //end game because you dropped it
},4*error+300);
}
}else{
prizeWon = true; // Incase you are interupted, you still get a prize.
}
state = 'is grabbed';
};
@@ -63,7 +62,7 @@
top = 347;
left = crane.GetLeft()+23;
if(left <= 60) {
if(left <= 60) { // Claw has reached the drop-off with payload.
left = 60;
state = 'won';
}
@@ -95,10 +94,8 @@
top += vspd;
if(state=='won' && top > 460) {
$('#prize'+id).remove();//css({visibility:'hidden'});
$('#prize'+id).remove();
state='hidden';
prizeWon = true;
gameShutDown();
}
@@ -107,16 +104,14 @@
this.Repaint = function () {
$('#prize'+id).css({'top':top, 'left':left});
//$('#'+id+' #crane-handle-top').css({height: handleHeight});
};
}</script>
<!-- Crane.js --><script>
function Crane(id) {
//console.log("crane created");
var top = 131; //private
var left = 100;
var hspd = 6;
var hspd = 5;
var vspd = 4;
var state = false;
var handleHeight = 83;
@@ -131,34 +126,39 @@
this.GetTop = function() {return top};
var Grab = function () {
top += (state == 'down')?vspd:-vspd;
handleHeight += (state == 'down')?vspd:-vspd;
if(top > 300 && state == 'down') { //when going down
top = 300;
//handleHeight = ;
state = 'up';
$('#'+id+' #crane-claw').css(frames['half']);
} else if(top < 131 && state == 'up') { //when going up
top = 131;
handleHeight = 83;
state = 'drop';
} else if(state == 'drop') { //when up and dropping
left -= hspd;
top = 131;
handleHeight = 83;
if(left < 30) {
left = 30;
$('#'+id+' #crane-claw').css(frames['open']);
setTimeout(function(){$('#'+id+' #crane-claw').css(frames['normal']);state = false;},500);
}
switch (state) {
case 'up':
top -= vspd;
handleHeight -= vspd;
if(top < 131) { // when going up
top = 131;
handleHeight = 83;
state = 'drop';
}
break;
case 'down': // when going down
top += vspd;
handleHeight += vspd;
if(top > 300) {
top = 300;
state = 'up';
$('#'+id+' #crane-claw').css(frames['half']);
}
break;
case 'drop': // when up and dropping
left -= hspd;
top = 131;
handleHeight = 83;
if(left < 30) {
left = 30;
$('#'+id+' #crane-claw').css(frames['open']);
setTimeout(function(){$('#'+id+' #crane-claw').css(frames['normal']);state = false;},500);
}
break;
}
};
var CheckBoundaries = function () {
if(left < 30)
left = 30;
else if(left > 788)
@@ -166,20 +166,18 @@
};
this.Update = function () {
//console.log(left);
if(keys["left"] && !state) //left
left -= hspd;
if(keys["right"] && !state) //right
left += hspd;
if(keys["down"] && !state) { //drop
state = 'down';
$('#'+id+' #crane-claw').css(frames['open']);
}
if(state) {
if(!state){
if(keys["left"]) //Move claw left
left -= hspd;
if(keys["right"]) // Move claw right
left += hspd;
if(keys["down"]){ // Drop claw.
state = 'down';
$('#'+id+' #crane-claw').css(frames['open']);
}
}else{
Grab();
}
@@ -204,57 +202,49 @@
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback){
window.setTimeout(callback, 1000 / 30);
window.setTimeout(callback, 33.333); //1000 / 30
};
})();
function animate(){
//console.log("animate called");
crane.Update();
for(var i = 0; i< prizes.length; i++)
for(var i=0; i<prizes.length; i++){
prizes[i].Update();
for(var i = 0; i< prizes.length; i++)
prizes[i].Repaint();
}
crane.Repaint();
requestAnimFrame(function(){
animate();
});
}
function joystickControlOn(direction){
//console.log(direction);
keys[direction] = true;
}
function joystickControlOff(direction){
//console.log(direction);
keys[direction] = false;
}
function gameStartUp(){ //main function
//console.log("game start!");
document.getElementById("play_btn").disabled = true; //to prevent button-mashing the start button.
for(var i = 0; i< 5; i++)
for(var i=0; i<5; i++){ // Creates prize balls.
prizes[i] = new Prize(i,{top: Math.ceil(Math.random()*100),left: 400+i*100-Math.ceil(Math.random()*50)},crane);
//console.log("prize made");
//crane.Repaint();
}
animate();
}
function gameShutDown(){
document.getElementById("play_btn").disabled = true;
var close_game_link = '<h2>TRY AGAIN!</h2><br><a href="byond://?src=/* ref src */;prizeWon=0">\[Close Game\]</a>'
if(prizeWon)
close_game_link = '<h2>YOU WON!</h2><br><a href="byond://?src=/* ref src */;prizeWon=1">\[Close Game\]</a>'
document.getElementById('game').innerHTML = '<center><h1> GAME OVER!</h1><br>'+close_game_link+'</center>'
function checkPrize(){
// Tells the machine if it should drop a prize.
prizeWon?document.getElementById("close_nao").href = "byond://?src=/* ref src */;prizeWon=1":document.getElementById("close_nao").href = "byond://?src=/* ref src */;prizeWon=0";
}
function gameShutDown(){
checkPrize();
if(prizeWon){ emergencyShutDown(); }else{
document.getElementById('game').innerHTML = '<br><br><br><div class="end-text"><center><h1> GAME OVER!</h1><br><h2>BETTER LUCK NEXT TIME!</h2></center></div>';
}
}
// Runs if close window or press close button.
function emergencyShutDown(){
checkPrize();
document.getElementById("close_nao").click();
}
</script>
@@ -278,11 +268,14 @@
</div>
<div id='controls' style='position: absolute; top: 550px'>
<br><button id="play_btn" onclick="gameStartUp()">Play Now!</button> <button id="close_btn" onclick="gameShutDown()">Close Game.</button><a id="close_nao" hidden="true" href="byond://?src=/* ref src */;prizeWon=0"></a>
<div id='controls' style='position: absolute; top: 515px; left: 385px;'>
<br>
<button class="button" id="play_btn" onclick="gameStartUp()">Play Now!</button>
<button class="button" id="close_btn" onclick="emergencyShutDown()">Close.</button>
<a id="close_nao" hidden="true" href="byond://?src=/* ref src */;prizeWon=0"></a>
<br>
<button onmouseover="joystickControlOn('left')" onmouseout="joystickControlOff('left')">/==<br>\==</button>
<button onmousedown="joystickControlOn('down')" onmouseup="joystickControlOff('down')">DROP<br>CLAW</button>
<button class="button" onmousedown="joystickControlOn('down')" onmouseup="joystickControlOff('down')">DROP<br>CLAW</button>
<button onmouseover="joystickControlOn('right')" onmouseout="joystickControlOff('right')">==\<br>==/</button>
</div>
</body>
+20 -20
View File
@@ -44,13 +44,13 @@
/obj/machinery/computer/mob_battle_terminal/Destroy()
eject_card(1)
if(mob_hunt_server)
if(mob_hunt_server.battle_turn)
mob_hunt_server.battle_turn = null
if(mob_hunt_server.red_terminal == src)
mob_hunt_server.red_terminal = null
if(mob_hunt_server.blue_terminal == src)
mob_hunt_server.blue_terminal = null
if(SSmob_hunt)
if(SSmob_hunt.battle_turn)
SSmob_hunt.battle_turn = null
if(SSmob_hunt.red_terminal == src)
SSmob_hunt.red_terminal = null
if(SSmob_hunt.blue_terminal == src)
SSmob_hunt.blue_terminal = null
QDEL_NULL(avatar)
return ..()
@@ -80,7 +80,7 @@
/obj/machinery/computer/mob_battle_terminal/proc/eject_card(override = 0)
if(!override)
if(ready && mob_hunt_server.battle_turn != team)
if(ready && SSmob_hunt.battle_turn != team)
audible_message("You can't recall on your rival's turn!", null, 2)
return
card.mob_data = mob_info
@@ -126,7 +126,7 @@
dat += "<h1>No Nano-Mob card loaded.</h1>"
dat += "</td>"
dat += "</tr>"
if(ready && mob_hunt_server.battle_turn) //offer the surrender option if they are in a battle (ready), but don't have a card loaded
if(ready && SSmob_hunt.battle_turn) //offer the surrender option if they are in a battle (ready), but don't have a card loaded
dat += "<tr>"
dat += "<td><a href='?src=[UID()];surrender=1'>Surrender!</a></td>"
dat += "</tr>"
@@ -170,7 +170,7 @@
dat += "<tr>"
dat += "<td><a href='?src=[UID()];ready=1'>Battle!</a></td>"
dat += "</tr>"
if(ready && !mob_hunt_server.battle_turn)
if(ready && !SSmob_hunt.battle_turn)
dat += "<tr>"
dat += "<td><a href='?src=[UID()];ready=2'>Cancel Battle!</a></td>"
dat += "</tr>"
@@ -205,23 +205,23 @@
/obj/machinery/computer/mob_battle_terminal/proc/check_connection()
if(team == "Red")
if(mob_hunt_server && !mob_hunt_server.red_terminal)
mob_hunt_server.red_terminal = src
if(SSmob_hunt && !SSmob_hunt.red_terminal)
SSmob_hunt.red_terminal = src
else if(team == "Blue")
if(mob_hunt_server && !mob_hunt_server.blue_terminal)
mob_hunt_server.blue_terminal = src
if(SSmob_hunt && !SSmob_hunt.blue_terminal)
SSmob_hunt.blue_terminal = src
/obj/machinery/computer/mob_battle_terminal/proc/do_attack()
if(!ready) //no attacking if you arent ready to fight (duh)
return
if(!mob_hunt_server || team != mob_hunt_server.battle_turn) //don't attack unless it is actually our turn
if(!SSmob_hunt || team != SSmob_hunt.battle_turn) //don't attack unless it is actually our turn
return
else
var/message = "[mob_info.mob_name] attacks!"
if(mob_info.nickname)
message = "[mob_info.nickname] attacks!"
audible_message(message, null, 5)
mob_hunt_server.launch_attack(team, mob_info.get_raw_damage(), mob_info.get_attack_type())
SSmob_hunt.launch_attack(team, mob_info.get_raw_damage(), mob_info.get_attack_type())
/obj/machinery/computer/mob_battle_terminal/proc/start_battle()
if(ready) //don't do anything if we are still ready
@@ -230,20 +230,20 @@
return
ready = 1
audible_message("[team] Player is ready for battle! Waiting for rival...", null, 5)
mob_hunt_server.start_check()
SSmob_hunt.start_check()
/obj/machinery/computer/mob_battle_terminal/proc/receive_attack(raw_damage, datum/mob_type/attack_type)
var/message = mob_info.take_damage(raw_damage, attack_type)
avatar.audible_message(message, null, 5)
if(!mob_info.cur_health)
mob_hunt_server.end_battle(team)
SSmob_hunt.end_battle(team)
eject_card(1) //force the card out, they were defeated
else
mob_hunt_server.end_turn()
SSmob_hunt.end_turn()
/obj/machinery/computer/mob_battle_terminal/proc/surrender()
audible_message("[team] Player surrenders the battle!", null, 5)
mob_hunt_server.end_battle(team, 1)
SSmob_hunt.end_battle(team, 1)
//////////////////////////////
// Mob Healing Terminal //
+11 -11
View File
@@ -94,33 +94,33 @@
P.audible_message(message, null, 4)
/obj/effect/nanomob/proc/despawn()
if(mob_hunt_server)
if(SSmob_hunt)
if(mob_info.is_trap)
mob_hunt_server.trap_spawns -= src
SSmob_hunt.trap_spawns -= src
else
mob_hunt_server.normal_spawns -= src
SSmob_hunt.normal_spawns -= src
qdel(src)
/obj/effect/nanomob/proc/reveal()
if(!mob_hunt_server)
if(!SSmob_hunt)
return
var/list/show_to = list()
for(var/A in mob_hunt_server.connected_clients)
if((A in clients_encountered) || !mob_hunt_server.connected_clients[A])
for(var/A in SSmob_hunt.connected_clients)
if((A in clients_encountered) || !SSmob_hunt.connected_clients[A])
continue
show_to |= mob_hunt_server.connected_clients[A]
show_to |= SSmob_hunt.connected_clients[A]
display_alt_appearance("nanomob_avatar", show_to)
/obj/effect/nanomob/proc/conceal(list/hide_from)
if(!mob_hunt_server)
if(!SSmob_hunt)
return
var/list/hiding_from = list()
if(hide_from)
hiding_from = hide_from
else
for(var/A in mob_hunt_server.connected_clients)
if((A in clients_encountered) && mob_hunt_server.connected_clients[A])
hiding_from |= mob_hunt_server.connected_clients[A]
for(var/A in SSmob_hunt.connected_clients)
if((A in clients_encountered) && SSmob_hunt.connected_clients[A])
hiding_from |= SSmob_hunt.connected_clients[A]
hide_alt_appearance("nanomob_avatar", hiding_from)
// BATTLE MOB AVATARS
+3 -3
View File
@@ -72,12 +72,12 @@
secondary_type = new secondary_type()
if(no_register) //for booster pack cards
return
if(mob_hunt_server)
if(SSmob_hunt)
if(set_trap)
if(mob_hunt_server.register_trap(src))
if(SSmob_hunt.register_trap(src))
return
else if(select_spawn())
if(mob_hunt_server.register_spawn(src))
if(SSmob_hunt.register_spawn(src))
return
qdel(src) //if you reach this, the datum is just pure clutter, so delete it
+8
View File
@@ -1,3 +1,7 @@
body {
/* Disables scroll bars */
overflow:hidden;
}
#background {
width:900px;
height:406px;
@@ -81,4 +85,8 @@
//-webkit-border-radius: 30px;
//border-radius: 30px;
position: absolute;
}
.button {
cursor: pointer;
}
+2 -2
View File
@@ -6,7 +6,7 @@
icon_state = "prize_counter-on"
density = 1
anchored = 1
use_power = 1
use_power = IDLE_POWER_USE
idle_power_usage = 40
var/tickets = 0
@@ -205,4 +205,4 @@ th.cost.toomuch {background:maroon;}
print_tickets()
else
new /obj/item/stack/tickets(get_turf(src), tickets)
tickets = 0
tickets = 0
+54 -33
View File
@@ -10,46 +10,67 @@
bomb_name = "voice-activated bomb"
describe()
if(recorded || listening)
return "A meter on [src] flickers with every nearby sound."
else
return "[src] is deactivated."
/obj/item/assembly/voice/describe()
if(recorded || listening)
return "A meter on [src] flickers with every nearby sound."
else
return "[src] is deactivated."
hear_talk(mob/living/M as mob, msg)
hear_input(M, msg, 0)
/obj/item/assembly/voice/hear_talk(mob/living/M as mob, msg)
hear_input(M, msg, 0)
hear_message(mob/living/M as mob, msg)
/obj/item/assembly/voice/hear_message(mob/living/M as mob, msg)
hear_input(M, msg, 1)
proc/hear_input(mob/living/M as mob, msg, type)
if(!istype(M,/mob/living))
return
if(listening)
recorded = msg
recorded_type = type
listening = 0
var/turf/T = get_turf(src) //otherwise it won't work in hand
T.visible_message("[bicon(src)] beeps, \"Activation message is [type ? "the sound when one [recorded]" : "'[recorded]'."]\"")
else
if(findtext(msg, recorded) && type == recorded_type)
pulse(0)
var/turf/T = get_turf(src) //otherwise it won't work in hand
T.visible_message("<span class='warning'>[bicon(src)] beeps!</span>")
/obj/item/assembly/voice/proc/hear_input(mob/living/M as mob, msg, type)
if(!istype(M,/mob/living))
return
if(listening)
recorded = msg
recorded_type = type
listening = 0
var/turf/T = get_turf(src) //otherwise it won't work in hand
T.visible_message("[bicon(src)] beeps, \"Activation message is [type ? "the sound when one [recorded]" : "'[recorded]'."]\"")
else if(findtext(msg, recorded) && type == recorded_type)
pulse(0)
var/turf/T = get_turf(src) //otherwise it won't work in hand
T.visible_message("<span class='warning'>[bicon(src)] beeps!</span>")
activate()
return // previously this toggled listning when not in a holder, that's a little silly. It was only called in attack_self that way.
/obj/item/assembly/voice/activate()
return // previously this toggled listning when not in a holder, that's a little silly. It was only called in attack_self that way.
attack_self(mob/user)
if(!user || !secured) return 0
/obj/item/assembly/voice/attack_self(mob/user)
if(!user || !secured) return 0
listening = !listening
var/turf/T = get_turf(src)
T.visible_message("[bicon(src)] beeps, \"[listening ? "Now" : "No longer"] recording input.\"")
return 1
listening = !listening
var/turf/T = get_turf(src)
T.visible_message("[bicon(src)] beeps, \"[listening ? "Now" : "No longer"] recording input.\"")
return 1
toggle_secure()
. = ..()
listening = 0
/obj/item/assembly/voice/toggle_secure()
. = ..()
listening = 0
/obj/item/assembly/voice/noise
name = "noise sensor"
desc = "A simple noise sensor that triggers on vocalizations other then speech."
icon_state = "voice"
materials = list(MAT_METAL=100, MAT_GLASS=10)
origin_tech = "magnets=1;engineering=1"
bomb_name = "noise-activated bomb"
/obj/item/assembly/voice/noise/attack_self(mob/user)
return
/obj/item/assembly/voice/noise/describe()
return "[src] does not appear to have any controls."
/obj/item/assembly/voice/noise/hear_talk(mob/living/M as mob, msg)
return
/obj/item/assembly/voice/hear_message(mob/living/M as mob, msg)
pulse(0)
var/turf/T = get_turf(src) //otherwise it won't work in hand
T.visible_message("<span class='warning'>[bicon(src)] beeps!</span>")
+497 -250
View File
@@ -4,295 +4,542 @@
//To do: Allow corpses to appear mangled, bloody, etc. Allow customizing the bodies appearance (they're all bald and white right now).
/obj/effect/landmark/corpse
/obj/effect/mob_spawn
name = "Unknown"
var/mobname = "Unknown" //Unused now but it'd fuck up maps to remove it now
var/mob_species = null //Set to make a mob of another race, currently used only in ruins
var/corpseuniform = null //Set this to an object path to have the slot filled with said object on the corpse.
var/corpsesuit = null
var/corpseshoes = null
var/corpsegloves = null
var/corpseradio = null
var/corpseglasses = null
var/corpsemask = null
var/corpsehelmet = null
var/corpsebelt = null
var/corpsepocket1 = null
var/corpsepocket2 = null
var/corpseback = null
var/corpseid = 0 //Just set to 1 if you want them to have an ID
var/corpseidjob = null // Needs to be in quotes, such as "Clown" or "Chef." This just determines what the ID reads as, not their access
var/corpseidaccess = null //This is for access. See access.dm for which jobs give what access. Again, put in quotes. Use "Captain" if you want it to be all access.
var/corpseidicon = null //For setting it to be a gold, silver, centcomm etc ID
var/timeofdeath = null
var/coffin = 0
icon = 'icons/effects/blood.dmi'
icon_state = "remains"
var/mob_type = null
var/mob_name = ""
var/mob_gender = null
var/death = TRUE //Kill the mob
var/roundstart = TRUE //fires on initialize
var/instant = FALSE //fires on New
var/flavour_text = "The mapper forgot to set this!"
var/faction = null
var/permanent = FALSE //If true, the spawner will not disappear upon running out of uses.
var/random = FALSE //Don't set a name or gender, just go random
var/objectives = null
var/uses = 1 //how many times can we spawn from it. set to -1 for infinite.
var/brute_damage = 0
var/oxy_damage = 0
var/burn_damage = 0
var/datum/disease/disease = null //Do they start with a pre-spawned disease?
var/mob_color //Change the mob's color
var/assignedrole
density = TRUE
anchored = TRUE
var/banType = "lavaland"
/obj/effect/landmark/corpse/Initialize()
..()
if(istype(src,/obj/effect/landmark/corpse/clown))
var/obj/effect/landmark/corpse/clown/C = src
C.chooseRank()
createCorpse()
/obj/effect/landmark/corpse/proc/createCorpse() //Creates a mob and checks for gear in each slot before attempting to equip it.
var/mob/living/carbon/human/M = new /mob/living/carbon/human(src.loc)
M.real_name = src.name
M.death(1) //Kills the new mob
/obj/effect/mob_spawn/attack_ghost(mob/user)
if(ticker.current_state != GAME_STATE_PLAYING || !loc)
return
if(!uses)
to_chat(user, "<span class='warning'>This spawner is out of charges!</span>")
return
if(jobban_isbanned(user, banType))
to_chat(user, "<span class='warning'>You are jobanned!</span>")
return
var/ghost_role = alert("Become [mob_name]? (Warning, You can no longer be cloned!)",,"Yes","No")
if(ghost_role == "No" || !loc)
return
log_game("[user.ckey] became [mob_name]")
create(ckey = user.ckey)
/obj/effect/mob_spawn/Initialize(mapload)
. = ..()
if(instant || (roundstart && (ticker && ticker.current_state > GAME_STATE_SETTING_UP)))
create()
else
poi_list |= src
LAZYADD(GLOB.mob_spawners[name], src)
/obj/effect/mob_spawn/Destroy()
poi_list -= src
var/list/spawners = GLOB.mob_spawners[name]
LAZYREMOVE(spawners, src)
if(!LAZYLEN(spawners))
GLOB.mob_spawners -= name
return ..()
/obj/effect/mob_spawn/proc/special(mob/M)
return
/obj/effect/mob_spawn/proc/equip(mob/M)
return
/obj/effect/mob_spawn/proc/create(ckey, flavour = TRUE, name)
var/mob/living/M = new mob_type(get_turf(src)) //living mobs only
if(!random)
M.real_name = mob_name ? mob_name : M.name
if(!mob_gender)
mob_gender = pick(MALE, FEMALE)
M.gender = mob_gender
if(faction)
M.faction = list(faction)
if(disease)
M.ForceContractDisease(new disease)
if(death)
M.death(1) //Kills the new mob
M.adjustOxyLoss(oxy_damage)
M.adjustBruteLoss(brute_damage)
M.timeofdeath = timeofdeath
if(mob_species)
M.set_species(mob_species)
if(corpseuniform)
M.equip_to_slot_or_del(new corpseuniform(M), slot_w_uniform)
if(corpsesuit)
M.equip_to_slot_or_del(new corpsesuit(M), slot_wear_suit)
if(corpseshoes)
M.equip_to_slot_or_del(new corpseshoes(M), slot_shoes)
if(corpsegloves)
M.equip_to_slot_or_del(new corpsegloves(M), slot_gloves)
if(corpseradio)
M.equip_to_slot_or_del(new corpseradio(M), slot_l_ear)
if(corpseglasses)
M.equip_to_slot_or_del(new corpseglasses(M), slot_glasses)
if(corpsemask)
M.equip_to_slot_or_del(new corpsemask(M), slot_wear_mask)
if(corpsehelmet)
M.equip_to_slot_or_del(new corpsehelmet(M), slot_head)
if(corpsebelt)
M.equip_to_slot_or_del(new corpsebelt(M), slot_belt)
if(corpsepocket1)
M.equip_to_slot_or_del(new corpsepocket1(M), slot_r_store)
if(corpsepocket2)
M.equip_to_slot_or_del(new corpsepocket2(M), slot_l_store)
if(corpseback)
M.equip_to_slot_or_del(new corpseback(M), slot_back)
if(corpseid == 1)
var/obj/item/card/id/W = new(M)
W.name = "[M.real_name]'s ID Card"
var/datum/job/jobdatum
for(var/jobtype in typesof(/datum/job))
var/datum/job/J = new jobtype
if(J.title == corpseidaccess)
jobdatum = J
break
if(corpseidicon)
W.icon_state = corpseidicon
if(corpseidaccess)
if(jobdatum)
W.access = jobdatum.get_access()
else
W.access = list()
if(corpseidjob)
W.assignment = corpseidjob
W.registered_name = M.real_name
M.equip_to_slot_or_del(W, slot_wear_id)
if(coffin == 1)
var/obj/structure/closet/coffin/sarcophagus/sarc = locate(/obj/structure/closet/coffin/sarcophagus) in loc
if(sarc) M.loc = sarc
qdel(src)
M.adjustFireLoss(burn_damage)
M.color = mob_color
equip(M, TRUE)
// I'll work on making a list of corpses people request for maps, or that I think will be commonly used. Syndicate operatives for example.
/obj/effect/landmark/corpse/damaged
if(ckey)
M.ckey = ckey
if(flavour)
to_chat(M, "[flavour_text]")
var/datum/mind/MM = M.mind
if(objectives)
for(var/objective in objectives)
MM.objectives += new/datum/objective(objective)
if(assignedrole)
M.mind.assigned_role = assignedrole
special(M, name)
MM.name = M.real_name
if(uses > 0)
uses--
if(!permanent && !uses)
qdel(src)
// Base version - place these on maps/templates.
/obj/effect/mob_spawn/human
mob_type = /mob/living/carbon/human
//Human specific stuff.
var/mob_species = null //Set species
var/datum/outfit/outfit = /datum/outfit //If this is a path, it will be instanced in Initialize()
var/disable_pda = TRUE
var/disable_sensors = TRUE
//All of these only affect the ID that the outfit has placed in the ID slot
var/id_job = null //Such as "Clown" or "Chef." This just determines what the ID reads as, not their access
var/id_access = null //This is for access. See access.dm for which jobs give what access. Use "Captain" if you want it to be all access.
var/id_access_list = null //Allows you to manually add access to an ID card.
assignedrole = "Ghost Role"
var/husk = null
//these vars are for lazy mappers to override parts of the outfit
//these cannot be null by default, or mappers cannot set them to null if they want nothing in that slot
var/uniform = -1
var/r_hand = -1
var/l_hand = -1
var/suit = -1
var/shoes = -1
var/gloves = -1
var/ears = -1
var/glasses = -1
var/mask = -1
var/head = -1
var/belt = -1
var/r_pocket = -1
var/l_pocket = -1
var/back = -1
var/id = -1
var/neck = -1
var/pda = -1
var/backpack_contents = -1
var/suit_store = -1
var/hair_style
var/facial_hair_style
var/skin_tone
/obj/effect/mob_spawn/human/Initialize()
if(ispath(outfit))
outfit = new outfit()
if(!outfit)
outfit = new /datum/outfit
return ..()
/obj/effect/mob_spawn/human/equip(mob/living/carbon/human/H)
if(mob_species)
if(H.set_species(mob_species))
H.regenerate_icons()
if(husk)
H.ChangeToHusk()
else //Because for some reason I can't track down, things are getting turned into husks even if husk = false. It's in some damage proc somewhere.
H.mutations.Remove(HUSK)
H.underwear = "Nude"
H.undershirt = "Nude"
H.socks = "Nude"
var/obj/item/organ/external/head/D = H.get_organ("head")
if(istype(D))
if(hair_style)
D.h_style = hair_style
else
D.h_style = random_hair_style(gender)
D.hair_colour = rand_hex_color()
if(facial_hair_style)
D.f_style = facial_hair_style
else
D.f_style = random_facial_hair_style(gender)
D.facial_colour = rand_hex_color()
if(skin_tone)
H.s_tone = skin_tone
else
H.s_tone = random_skin_tone()
H.update_hair()
H.update_body()
if(outfit)
var/static/list/slots = list("uniform", "r_hand", "l_hand", "suit", "shoes", "gloves", "ears", "glasses", "mask", "head", "belt", "r_pocket", "l_pocket", "back", "id", "neck", "backpack_contents", "suit_store")
for(var/slot in slots)
var/T = vars[slot]
if(!isnum(T))
outfit.vars[slot] = T
H.equipOutfit(outfit, TRUE)
var/list/del_types = list(/obj/item/pda, /obj/item/radio/headset)
for(var/del_type in del_types)
var/obj/item/I = locate(del_type) in H
qdel(I)
if(disable_pda)
// We don't want corpse PDAs to show up in the messenger list.
var/obj/item/pda/PDA = locate(/obj/item/pda) in H
if(PDA)
var/datum/data/pda/app/messenger/M = PDA.find_program(/datum/data/pda/app/messenger)
M.toff = 1
if(disable_sensors)
// Using crew monitors to find corpses while creative makes finding certain ruins too easy.
var/obj/item/clothing/under/C = H.w_uniform
if(istype(C))
C.sensor_mode = SUIT_SENSOR_OFF
var/obj/item/card/id/W = H.wear_id
if(W)
if(id_access)
for(var/jobtype in typesof(/datum/job))
var/datum/job/J = new jobtype
if(J.title == id_access)
W.access = J.get_access()
break
if(id_access_list)
if(!islist(W.access))
W.access = list()
W.access |= id_access_list
if(id_job)
W.assignment = id_job
W.registered_name = H.real_name
W.update_label()
//Instant version - use when spawning corpses during runtime
/obj/effect/mob_spawn/human/corpse
roundstart = FALSE
instant = TRUE
/obj/effect/mob_spawn/human/corpse/damaged
brute_damage = 1000
/obj/effect/landmark/corpse/syndicatesoldier
name = "Syndicate Operative"
corpseuniform = /obj/item/clothing/under/syndicate
corpsesuit = /obj/item/clothing/suit/armor/vest
corpseshoes = /obj/item/clothing/shoes/combat
corpsegloves = /obj/item/clothing/gloves/combat
corpseradio = /obj/item/radio/headset
corpsemask = /obj/item/clothing/mask/gas
corpsehelmet = /obj/item/clothing/head/helmet/swat
corpseback = /obj/item/storage/backpack
corpseid = 1
corpseidjob = "Operative"
corpseidaccess = "Syndicate"
/obj/effect/mob_spawn/human/alive
icon = 'icons/obj/Cryogenic2.dmi'
icon_state = "sleeper"
death = FALSE
roundstart = FALSE //you could use these for alive fake humans on roundstart but this is more common scenario
//Non-human spawners
/obj/effect/landmark/corpse/syndicatecommando
name = "Syndicate Commando"
corpseuniform = /obj/item/clothing/under/syndicate
corpsesuit = /obj/item/clothing/suit/space/hardsuit/syndi
corpseshoes = /obj/item/clothing/shoes/magboots/syndie
corpsegloves = /obj/item/clothing/gloves/combat
corpseradio = /obj/item/radio/headset
corpsemask = /obj/item/clothing/mask/gas/syndicate
corpsehelmet = /obj/item/clothing/head/helmet/space/hardsuit/syndi
corpseback = /obj/item/tank/jetpack/oxygen
corpsepocket1 = /obj/item/tank/emergency_oxygen
corpseid = 1
corpseidjob = "Operative"
corpseidaccess = "Syndicate"
/obj/effect/mob_spawn/mouse
name = "sleeper"
mob_name = "space mouse"
mob_type = /mob/living/simple_animal/mouse
death = FALSE
roundstart = FALSE
icon = 'icons/obj/Cryogenic2.dmi'
icon_state = "sleeper"
flavour_text = "Squeak!"
/obj/effect/mob_spawn/cow
name = "sleeper"
mob_name = "space cow"
mob_type = /mob/living/simple_animal/cow
death = FALSE
roundstart = FALSE
mob_gender = FEMALE
icon = 'icons/obj/Cryogenic2.dmi'
icon_state = "sleeper"
flavour_text = "Moo!"
///////////Civilians//////////////////////
///////////Support//////////////////////
/obj/effect/mob_spawn/human/corpse/assistant
name = "Assistant"
id_job = "Assistant"
outfit = /datum/outfit/job/assistant
/obj/effect/landmark/corpse/chef
name = "Chef"
corpseuniform = /obj/item/clothing/under/rank/chef
corpsesuit = /obj/item/clothing/suit/chef/classic
corpseshoes = /obj/item/clothing/shoes/black
corpsehelmet = /obj/item/clothing/head/chefhat
corpseback = /obj/item/storage/backpack
corpseradio = /obj/item/radio/headset
corpseid = 1
corpseidjob = "Chef"
corpseidaccess = "Chef"
/obj/effect/mob_spawn/human/corpse/assistant/beesease_infection
disease = /datum/disease/beesease
/obj/effect/mob_spawn/human/corpse/assistant/brainrot_infection
disease = /datum/disease/brainrot
/obj/effect/landmark/corpse/doctor
/obj/effect/mob_spawn/human/corpse/assistant/spanishflu_infection
disease = /datum/disease/fluspanish
/obj/effect/mob_spawn/human/cook
name = "Cook"
id_job = "Chef"
outfit = /datum/outfit/job/chef
/obj/effect/mob_spawn/human/doctor
name = "Doctor"
corpseradio = /obj/item/radio/headset/headset_med
corpseuniform = /obj/item/clothing/under/rank/medical
corpsesuit = /obj/item/clothing/suit/storage/labcoat
corpseback = /obj/item/storage/backpack/medic
corpsepocket1 = /obj/item/flashlight/pen
corpseshoes = /obj/item/clothing/shoes/black
corpseid = 1
corpseidjob = "Medical Doctor"
corpseidaccess = "Medical Doctor"
id_job = "Medical Doctor"
outfit = /datum/outfit/job/doctor
/obj/effect/landmark/corpse/engineer
/obj/effect/mob_spawn/human/doctor/alive
death = FALSE
roundstart = FALSE
random = TRUE
name = "sleeper"
icon = 'icons/obj/Cryogenic2.dmi'
icon_state = "sleeper"
flavour_text = "You are a space doctor!"
assignedrole = "Space Doctor"
/obj/effect/mob_spawn/human/doctor/alive/equip(mob/living/carbon/human/H)
..()
// Remove radio and PDA so they wouldn't annoy station crew.
var/list/del_types = list(/obj/item/pda, /obj/item/radio/headset)
for(var/del_type in del_types)
var/obj/item/I = locate(del_type) in H
qdel(I)
/obj/effect/mob_spawn/human/engineer
name = "Engineer"
corpseradio = /obj/item/radio/headset/headset_eng
corpseuniform = /obj/item/clothing/under/rank/engineer
corpseback = /obj/item/storage/backpack/industrial
corpseshoes = /obj/item/clothing/shoes/workboots
corpsebelt = /obj/item/storage/belt/utility/full
corpsegloves = /obj/item/clothing/gloves/color/yellow
corpsehelmet = /obj/item/clothing/head/hardhat
corpseid = 1
corpseidjob = "Station Engineer"
corpseidaccess = "Station Engineer"
id_job = "Engineer"
outfit = /datum/outfit/job/engineer
/obj/effect/landmark/corpse/engineer/hardsuit
corpsesuit = /obj/item/clothing/suit/space/hardsuit
corpsemask = /obj/item/clothing/mask/breath
corpsehelmet = /obj/item/clothing/head/helmet/space/hardsuit
/obj/effect/mob_spawn/human/engineer/hardsuit
outfit = /datum/outfit/job/engineer/suit
/obj/effect/landmark/corpse/clown
/datum/outfit/job/engineer/suit
name = "Station Engineer"
/obj/effect/landmark/corpse/clown/proc/chooseRank()
if(prob(10))
name = "Clown Officer"
corpseuniform = /obj/item/clothing/under/officeruniform
corpsesuit = /obj/item/clothing/suit/officercoat
corpseshoes = /obj/item/clothing/shoes/clown_shoes
corpseradio = /obj/item/radio/headset
corpsemask = /obj/item/clothing/mask/gas/clown_hat
corpsepocket1 = /obj/item/bikehorn
corpseback = /obj/item/storage/backpack/clown
corpsehelmet = /obj/item/clothing/head/naziofficer
corpseid = 1
corpseidjob = "Clown Officer"
corpseidaccess = "Clown"
timeofdeath = -50000
else
name = "Clown Soldier"
corpseuniform = /obj/item/clothing/under/soldieruniform
corpsesuit = /obj/item/clothing/suit/soldiercoat
corpseshoes = /obj/item/clothing/shoes/clown_shoes
corpseradio = /obj/item/radio/headset
corpsemask = /obj/item/clothing/mask/gas/clown_hat
corpsepocket1 = /obj/item/bikehorn
corpseback = /obj/item/storage/backpack/clown
corpsehelmet = /obj/item/clothing/head/stalhelm
corpseid = 1
corpseidjob = "Clown Soldier"
corpseidaccess = "Clown"
timeofdeath = -50000
uniform = /obj/item/clothing/under/rank/engineer
belt = /obj/item/storage/belt/utility/full
suit = /obj/item/clothing/suit/space/hardsuit
shoes = /obj/item/clothing/shoes/workboots
head = /obj/item/clothing/head/helmet/space/hardsuit
mask = /obj/item/clothing/mask/breath
id = /obj/item/card/id/engineering
l_pocket = /obj/item/t_scanner
/obj/effect/landmark/corpse/clownking
name = "Clown King"
corpseuniform = /obj/item/clothing/under/rank/clown
corpseshoes = /obj/item/clothing/shoes/clown_shoes
corpseradio = /obj/item/radio/headset
corpsemask = /obj/item/clothing/mask/gas/clown_hat
corpsehelmet = /obj/item/clothing/head/crown
corpsepocket1 = /obj/item/bikehorn
corpseback = /obj/item/bedsheet/clown
corpseid = 1
corpseidjob = "Clown King"
corpseidaccess = "Clown"
timeofdeath = -50000
coffin = 1
backpack = /obj/item/storage/backpack/industrial
/obj/effect/landmark/corpse/mime
/obj/effect/mob_spawn/human/clown
name = "Clown"
mob_name = "Clown"
id_job = "Clown"
outfit = /datum/outfit/job/clown
/obj/effect/mob_spawn/human/clown/Initialize()
mob_name = pick(clown_names)
..()
/obj/effect/mob_spawn/human/corpse/clownmili
name = "Clown Soldier"
outfit = /datum/outfit/clownsoldier
/obj/effect/mob_spawn/human/corpse/clownmili/Initialize()
mob_name = "Officer [pick(clown_names)]"
..()
/obj/effect/mob_spawn/human/corpse/clownoff
name = "Clown Officer"
outfit = /datum/outfit/clownofficer
/obj/effect/mob_spawn/human/corpse/clownoff/Initialize()
mob_name = "Honk Specialist [pick(clown_names)]"
..()
/datum/outfit/clownsoldier
uniform = /obj/item/clothing/under/soldieruniform
suit = /obj/item/clothing/suit/soldiercoat
shoes = /obj/item/clothing/shoes/clown_shoes
l_ear = /obj/item/radio/headset
mask = /obj/item/clothing/mask/gas/clown_hat
l_pocket = /obj/item/bikehorn
back = /obj/item/storage/backpack/clown
head = /obj/item/clothing/head/stalhelm
/datum/outfit/clownofficer
uniform = /obj/item/clothing/under/officeruniform
suit = /obj/item/clothing/suit/officercoat
shoes = /obj/item/clothing/shoes/clown_shoes
l_ear = /obj/item/radio/headset
mask = /obj/item/clothing/mask/gas/clown_hat
l_pocket = /obj/item/bikehorn
back = /obj/item/storage/backpack/clown
head = /obj/item/clothing/head/naziofficer
/obj/effect/mob_spawn/human/mime
name = "Mime"
corpseuniform = /obj/item/clothing/under/mime
corpseshoes = /obj/item/clothing/shoes/black
corpseradio = /obj/item/radio/headset
corpsemask = /obj/item/clothing/mask/gas/mime
corpseback = /obj/item/storage/backpack
corpseid = 1
corpseidjob = "Mime"
corpseidaccess = "Mime"
timeofdeath = -50000
mob_name = "Mime"
id_job = "Mime"
outfit = /datum/outfit/job/mime
/obj/effect/landmark/corpse/scientist
/obj/effect/mob_spawn/human/mime/Initialize()
mob_name = pick(mime_names)
..()
/obj/effect/mob_spawn/human/scientist
name = "Scientist"
corpseradio = /obj/item/radio/headset/headset_sci
corpseuniform = /obj/item/clothing/under/rank/scientist
corpsesuit = /obj/item/clothing/suit/storage/labcoat/science
corpseback = /obj/item/storage/backpack
corpseshoes = /obj/item/clothing/shoes/white
corpseid = 1
corpseidjob = "Scientist"
corpseidaccess = "Scientist"
id_job = "Scientist"
outfit = /datum/outfit/job/scientist
/obj/effect/landmark/corpse/miner
corpseradio = /obj/item/radio/headset/headset_cargo
corpseuniform = /obj/item/clothing/under/rank/miner
corpsegloves = /obj/item/clothing/gloves/fingerless
corpseback = /obj/item/storage/backpack/industrial
corpseshoes = /obj/item/clothing/shoes/black
corpseid = 1
corpseidjob = "Shaft Miner"
corpseidaccess = "Shaft Miner"
/obj/effect/mob_spawn/human/miner
name = "Shaft Miner"
id_job = "Shaft Miner"
outfit = /datum/outfit/job/mining/suit
/obj/effect/landmark/corpse/miner/hardsuit
corpsesuit = /obj/item/clothing/suit/space/hardsuit/mining
corpsemask = /obj/item/clothing/mask/breath
corpsehelmet = /obj/item/clothing/head/helmet/space/hardsuit/mining
/datum/outfit/job/mining/suit
name = "Station Engineer"
suit = /obj/item/clothing/suit/space/hardsuit/mining
head = /obj/item/clothing/head/helmet/space/hardsuit/mining
uniform = /obj/item/clothing/under/rank/miner
gloves = /obj/item/clothing/gloves/fingerless
shoes = /obj/item/clothing/shoes/workboots
l_ear = /obj/item/radio/headset/headset_cargo/mining
id = /obj/item/card/id/supply
l_pocket = /obj/item/reagent_containers/food/pill/patch/styptic
r_pocket = /obj/item/flashlight/seclite
/obj/effect/mob_spawn/human/bartender
name = "Space Bartender"
id_job = "Bartender"
id_access_list = list(access_bar)
outfit = /datum/outfit/spacebartender
/obj/effect/mob_spawn/human/bartender/alive
death = FALSE
roundstart = FALSE
random = TRUE
name = "bartender sleeper"
icon = 'icons/obj/Cryogenic2.dmi'
icon_state = "sleeper"
flavour_text = "You are a space bartender!"
assignedrole = "Space Bartender"
/datum/outfit/spacebartender
name = "Space Bartender"
uniform = /obj/item/clothing/under/rank/bartender
suit = /obj/item/clothing/suit/armor/vest
belt = /obj/item/storage/belt/bandolier/full
shoes = /obj/item/clothing/shoes/black
glasses = /obj/item/clothing/glasses/sunglasses/reagent
id = /obj/item/card/id
/obj/effect/mob_spawn/human/beach
outfit = /datum/outfit/beachbum
/obj/effect/mob_spawn/human/beach/alive
death = FALSE
roundstart = FALSE
random = TRUE
mob_name = "Beach Bum"
name = "beach bum sleeper"
icon = 'icons/obj/Cryogenic2.dmi'
icon_state = "sleeper"
flavour_text = "You are a beach bum!"
assignedrole = "Beach Bum"
/datum/outfit/beachbum
name = "Beach Bum"
glasses = /obj/item/clothing/glasses/sunglasses
uniform = /obj/item/clothing/under/shorts/red
/////////////////Spooky Undead//////////////////////
/obj/effect/mob_spawn/human/skeleton
name = "skeletal remains"
mob_name = "skeleton"
mob_species = /datum/species/skeleton
mob_gender = NEUTER
/obj/effect/mob_spawn/human/skeleton/alive
death = FALSE
roundstart = FALSE
icon = 'icons/effects/blood.dmi'
icon_state = "remains"
flavour_text = "By unknown powers, your skeletal remains have been reanimated! Walk this mortal plain and terrorize all living adventurers who dare cross your path."
assignedrole = "Skeleton"
/////////////////Officers//////////////////////
/obj/effect/landmark/corpse/bridgeofficer
/obj/effect/mob_spawn/human/bridgeofficer
name = "Bridge Officer"
corpseradio = /obj/item/radio/headset/heads/hop
corpseuniform = /obj/item/clothing/under/rank/centcom_officer
corpsesuit = /obj/item/clothing/suit/armor/bulletproof
corpseshoes = /obj/item/clothing/shoes/black
corpseglasses = /obj/item/clothing/glasses/sunglasses
corpseid = 1
corpseidjob = "Bridge Officer"
corpseidaccess = "Captain"
id_job = "Bridge Officer"
id_access = "Captain"
outfit = /datum/outfit/nanotrasenbridgeofficercorpse
/obj/effect/landmark/corpse/commander
/datum/outfit/nanotrasenbridgeofficercorpse
name = "Bridge Officer Corpse"
l_ear = /obj/item/radio/headset/heads/hop
uniform = /obj/item/clothing/under/rank/centcom_officer
suit = /obj/item/clothing/suit/armor/bulletproof
shoes = /obj/item/clothing/shoes/black
glasses = /obj/item/clothing/glasses/sunglasses
id = /obj/item/card/id
/obj/effect/mob_spawn/human/commander
name = "Commander"
corpseuniform = /obj/item/clothing/under/rank/centcom_commander
corpsesuit = /obj/item/clothing/suit/armor/bulletproof
corpseradio = /obj/item/radio/headset/heads/captain
corpseglasses = /obj/item/clothing/glasses/eyepatch
corpsemask = /obj/item/clothing/mask/cigarette/cigar/cohiba
corpsehelmet = /obj/item/clothing/head/centhat
corpsegloves = /obj/item/clothing/gloves/combat
corpseshoes = /obj/item/clothing/shoes/combat
corpsepocket1 = /obj/item/lighter/zippo
corpseid = 1
corpseidjob = "Commander"
corpseidaccess = "Captain"
id_job = "Commander"
id_access = "Captain"
outfit = /datum/outfit/nanotrasencommandercorpse
/obj/effect/landmark/corpse/abductor //Connected to ruins, for some reason?
/datum/outfit/nanotrasencommandercorpse
name = "Commander Corpse"
uniform = /obj/item/clothing/under/rank/centcom/officer
gloves = /obj/item/clothing/gloves/color/white
shoes = /obj/item/clothing/shoes/centcom
head = /obj/item/clothing/head/beret/centcom/officer
glasses = /obj/item/clothing/glasses/hud/security/sunglasses
id = /obj/item/card/id/centcom
/obj/effect/mob_spawn/human/abductor
name = "abductor"
mobname = "???"
mob_name = "alien"
mob_species = /datum/species/abductor
corpseuniform = /obj/item/clothing/under/color/grey
corpseshoes = /obj/item/clothing/shoes/combat
outfit = /datum/outfit/abductorcorpse
/datum/outfit/abductorcorpse
name = "Abductor Corpse"
uniform = /obj/item/clothing/under/color/grey
shoes = /obj/item/clothing/shoes/combat
//For ghost bar.
/obj/effect/mob_spawn/human/alive/space_bar_patron
name = "Bar cryogenics"
mob_name = "Bar patron"
random = TRUE
permanent = TRUE
uses = -1
outfit = /datum/outfit/spacebartender
assignedrole = "Space Bar Patron"
/obj/effect/mob_spawn/human/alive/space_bar_patron/attack_hand(mob/user)
var/despawn = alert("Return to cryosleep? (Warning, Your mob will be deleted!)",,"Yes","No")
if(despawn == "No" || !loc || !Adjacent(user))
return
user.visible_message("<span class='notice'>[user.name] climbs back into cryosleep...</span>")
qdel(user)
/datum/outfit/cryobartender
name = "Cryogenic Bartender"
uniform = /obj/item/clothing/under/rank/bartender
back = /obj/item/storage/backpack
shoes = /obj/item/clothing/shoes/black
suit = /obj/item/clothing/suit/armor/vest
glasses = /obj/item/clothing/glasses/sunglasses/reagent
+29 -14
View File
@@ -31,7 +31,7 @@ var/obj/machinery/gateway/centerstation/the_gateway = null
/obj/machinery/gateway/centerstation
density = 1
icon_state = "offcenter"
use_power = 1
use_power = IDLE_POWER_USE
//warping vars
var/list/linked = list()
@@ -96,9 +96,12 @@ var/obj/machinery/gateway/centerstation/the_gateway = null
/obj/machinery/gateway/centerstation/proc/toggleon(mob/user as mob)
if(!ready) return
if(linked.len != 8) return
if(!powered()) return
if(!ready)
return
if(linked.len != 8)
return
if(!powered())
return
if(!awaygate)
awaygate = locate(/obj/machinery/gateway/centeraway) in world
if(!awaygate)
@@ -135,9 +138,12 @@ var/obj/machinery/gateway/centerstation/the_gateway = null
//okay, here's the good teleporting stuff
/obj/machinery/gateway/centerstation/Bumped(atom/movable/M as mob|obj)
if(!ready) return
if(!active) return
if(!awaygate) return
if(!ready)
return
if(!active)
return
if(!awaygate)
return
if(awaygate.calibrated)
M.forceMove(get_step(awaygate.loc, SOUTH))
@@ -163,7 +169,7 @@ var/obj/machinery/gateway/centerstation/the_gateway = null
/obj/machinery/gateway/centeraway
density = 1
icon_state = "offcenter"
use_power = 0
use_power = NO_POWER_USE
var/calibrated = 1
var/list/linked = list() //a list of the connected gateway chunks
var/ready = 0
@@ -207,8 +213,10 @@ var/obj/machinery/gateway/centerstation/the_gateway = null
/obj/machinery/gateway/centeraway/proc/toggleon(mob/user as mob)
if(!ready) return
if(linked.len != 8) return
if(!ready)
return
if(linked.len != 8)
return
if(!stationgate)
stationgate = locate(/obj/machinery/gateway/centerstation) in world
if(!stationgate)
@@ -241,13 +249,20 @@ var/obj/machinery/gateway/centerstation/the_gateway = null
/obj/machinery/gateway/centeraway/Bumped(atom/movable/M as mob|obj)
if(!ready) return
if(!active) return
if(!ready)
return
if(!active)
return
if(istype(M, /mob/living/carbon))
if(exilecheck(M)) return
if(exilecheck(M))
return
if(istype(M, /obj))
if(M.can_buckle && M.has_buckled_mobs())
if(exilecheck(M.buckled_mob))
return
for(var/mob/living/carbon/F in M)
if(exilecheck(F)) return
if(exilecheck(F))
return
M.forceMove(get_step(stationgate.loc, SOUTH))
M.dir = SOUTH
@@ -1,677 +0,0 @@
/*
SwapMaps library by Lummox JR
developed for digitalBYOND
http://www.digitalbyond.org
Version 2.1
The purpose of this library is to make it easy for authors to swap maps
in and out of their game using savefiles. Swapped-out maps can be
transferred between worlds for an MMORPG, sent to the client, etc.
This is facilitated by the use of a special datum and a global list.
Uses of swapmaps:
- Temporary battle arenas
- House interiors
- Individual custom player houses
- Virtually unlimited terrain
- Sharing maps between servers running different instances of the same
game
- Loading and saving pieces of maps for reusable room templates
*/
/*
User Interface:
VARS:
swapmaps_iconcache
An associative list of icon files with names, like
'player.dmi' = "player"
swapmaps_mode
This must be set at runtime, like in world/New().
SWAPMAPS_SAV 0 (default)
Uses .sav files for raw /savefile output.
SWAPMAPS_TEXT 1
Uses .txt files via ExportText() and ImportText(). These maps
are easily editable and appear to take up less space in the
current version of BYOND.
PROCS:
SwapMaps_Find(id)
Find a map by its id
SwapMaps_Load(id)
Load a map by its id
SwapMaps_Save(id)
Save a map by its id (calls swapmap.Save())
SwapMaps_Unload(id)
Save and unload a map by its id (calls swapmap.Unload())
SwapMaps_Save_All()
Save all maps
SwapMaps_DeleteFile(id)
Delete a map file
SwapMaps_CreateFromTemplate(id)
Create a new map by loading another map to use as a template.
This map has id==src and will not be saved. To make it savable,
change id with swapmap.SetID(newid).
SwapMaps_LoadChunk(id,turf/locorner)
Load a swapmap as a "chunk", at a specific place. A new datum is
created but it's not added to the list of maps to save or unload.
The new datum can be safely deleted without affecting the turfs
it loaded. The purpose of this is to load a map file onto part of
another swapmap or an existing part of the world.
locorner is the corner turf with the lowest x,y,z values.
SwapMaps_SaveChunk(id,turf/corner1,turf/corner2)
Save a piece of the world as a "chunk". A new datum is created
for the chunk, but it can be deleted without destroying any turfs.
The chunk file can be reloaded as a swapmap all its own, or loaded
via SwapMaps_LoadChunk() to become part of another map.
SwapMaps_GetSize(id)
Return a list corresponding to the x,y,z sizes of a map file,
without loading the map.
Returns null if the map is not found.
SwapMaps_AddIconToCache(name,icon)
Cache an icon file by name for space-saving storage
swapmap.New(id,x,y,z)
Create a new map; specify id, width (x), height (y), and
depth (z)
Default size is world.maxx,world.maxy,1
swapmap.New(id,turf1,turf2)
Create a new map; specify id and 2 corners
This becomes a /swapmap for one of the compiled-in maps, for
easy saving.
swapmap.New()
Create a new map datum, but does not allocate space or assign an
ID (used for loading).
swapmap.Del()
Deletes a map but does not save
swapmap.Save()
Saves to map_[id].sav
Maps with id==src are not saved.
swapmap.Unload()
Saves the map and then deletes it
Maps with id==src are not saved.
swapmap.SetID(id)
Change the map's id and make changes to the lookup list
swapmap.AllTurfs(z)
Returns a block of turfs encompassing the entire map, or on just
one z-level
z is in world coordinates; it is optional
swapmap.Contains(turf/T)
Returns nonzero if T is inside the map's boundaries.
Also works for objs and mobs, but the proc is not area-safe.
swapmap.InUse()
Returns nonzero if a mob with a key is within the map's
boundaries.
swapmap.LoCorner(z=z1)
Returns locate(x1,y1,z), where z=z1 if none is specified.
swapmap.HiCorner(z=z2)
Returns locate(x2,y2,z), where z=z2 if none is specified.
swapmap.BuildFilledRectangle(turf/corner1,turf/corner2,item)
Builds a filled rectangle of item from one corner turf to the
other, on multiple z-levels if necessary. The corners may be
specified in any order.
item is a type path like /turf/wall or /obj/barrel{full=1}.
swapmap.BuildRectangle(turf/corner1,turf/corner2,item)
Builds an unfilled rectangle of item from one corner turf to
the other, on multiple z-levels if necessary.
swapmap.BuildInTurfs(list/turfs,item)
Builds item on all of the turfs listed. The list need not
contain only turfs, or even only atoms.
*/
swapmap
var/id // a string identifying this map uniquely
var/x1 // minimum x,y,z coords
var/y1
var/z1
var/x2 // maximum x,y,z coords (also used as width,height,depth until positioned)
var/y2
var/z2
var/tmp/locked // don't move anyone to this map; it's saving or loading
var/tmp/mode // save as text-mode
var/ischunk // tells the load routine to load to the specified location
New(_id,x,y,z)
if(isnull(_id)) return
id=_id
mode=swapmaps_mode
if(isturf(x) && isturf(y))
/*
Special format: Defines a map as an existing set of turfs;
this is useful for saving a compiled map in swapmap format.
Because this is a compiled-in map, its turfs are not deleted
when the datum is deleted.
*/
x1=min(x:x,y:x);x2=max(x:x,y:x)
y1=min(x:y,y:y);y2=max(x:y,y:y)
z1=min(x:z,y:z);z2=max(x:z,y:z)
InitializeSwapMaps()
if(z2>swapmaps_compiled_maxz ||\
y2>swapmaps_compiled_maxy ||\
x2>swapmaps_compiled_maxx)
qdel(src)
return
x2=x?(x):world.maxx
y2=y?(y):world.maxy
z2=z?(z):1
AllocateSwapMap()
Destroy()
// a temporary datum for a chunk can be deleted outright
// for others, some cleanup is necessary
if(!ischunk)
swapmaps_loaded-=src
swapmaps_byname-=id
if(z2>swapmaps_compiled_maxz ||\
y2>swapmaps_compiled_maxy ||\
x2>swapmaps_compiled_maxx)
var/list/areas=new
for(var/atom/A in block(locate(x1,y1,z1),locate(x2,y2,z2)))
for(var/obj/O in A) qdel(O)
for(var/mob/M in A)
if(!M.key) qdel(M)
else M.loc=null
areas[A.loc]=null
qdel(A)
// delete areas that belong only to this map
for(var/area/a in areas)
if(a && !a.contents.len) qdel(a)
if(x2>=world.maxx || y2>=world.maxy || z2>=world.maxz) CutXYZ()
qdel(areas)
..()
return QDEL_HINT_HARDDEL_NOW
/*
Savefile format:
map
id
x // size, not coords
y
z
areas // list of areas, not including default
[each z; 1 to depth]
[each y; 1 to height]
[each x; 1 to width]
type // of turf
AREA // if non-default; saved as a number (index into areas list)
vars // all other changed vars
*/
Write(savefile/S)
var/x
var/y
var/z
var/n
var/list/areas
var/area/defarea=locate(world.area)
if(!defarea) defarea=new world.area
areas=list()
for(var/turf/T in block(locate(x1,y1,z1),locate(x2,y2,z2)))
areas[T.loc]=null
for(n in areas) // quickly eliminate associations for smaller storage
areas-=n
areas+=n
areas-=defarea
InitializeSwapMaps()
locked=1
S["id"] << id
S["z"] << z2-z1+1
S["y"] << y2-y1+1
S["x"] << x2-x1+1
S["areas"] << areas
for(n in 1 to areas.len) areas[areas[n]]=n
var/oldcd=S.cd
for(z in z1 to z2)
S.cd="[z-z1+1]"
for(y in y1 to y2)
S.cd="[y-y1+1]"
for(x in x1 to x2)
S.cd="[x-x1+1]"
var/turf/T=locate(x,y,z)
S["type"] << T.type
if(T.loc!=defarea) S["AREA"] << areas[T.loc]
T.Write(S)
S.cd=".."
S.cd=".."
sleep()
S.cd=oldcd
locked=0
qdel(areas)
Read(savefile/S,_id,turf/locorner)
var/x
var/y
var/z
var/n
var/list/areas
var/area/defarea=locate(world.area)
id=_id
if(locorner)
ischunk=1
x1=locorner.x
y1=locorner.y
z1=locorner.z
if(!defarea) defarea=new world.area
if(!_id)
S["id"] >> id
else
var/dummy
S["id"] >> dummy
S["z"] >> z2 // these are depth,
S["y"] >> y2 // height,
S["x"] >> x2 // width
S["areas"] >> areas
locked=1
AllocateSwapMap() // adjust x1,y1,z1 - x2,y2,z2 coords
var/oldcd=S.cd
for(z in z1 to z2)
S.cd="[z-z1+1]"
for(y in y1 to y2)
S.cd="[y-y1+1]"
for(x in x1 to x2)
S.cd="[x-x1+1]"
var/tp
S["type"]>>tp
var/turf/T=locate(x,y,z)
T.loc.contents-=T
T=new tp(locate(x,y,z))
if("AREA" in S.dir)
S["AREA"]>>n
var/area/A=areas[n]
A.contents+=T
else defarea.contents+=T
// clear the turf
for(var/obj/O in T) qdel(O)
for(var/mob/M in T)
if(!M.key) qdel(M)
else M.loc=null
// finish the read
T.Read(S)
S.cd=".."
S.cd=".."
sleep()
S.cd=oldcd
locked=0
qdel(areas)
/*
Find an empty block on the world map in which to load this map.
If no space is found, increase world.maxz as necessary. (If the
map is greater in x,y size than the current world, expand
world.maxx and world.maxy too.)
Ignore certain operations if loading a map as a chunk. Use the
x1,y1,z1 position for it, and *don't* count it as a loaded map.
*/
proc/AllocateSwapMap()
InitializeSwapMaps()
world.maxx=max(x2,world.maxx) // stretch x/y if necessary
world.maxy=max(y2,world.maxy)
if(!ischunk)
if(world.maxz<=swapmaps_compiled_maxz)
z1=swapmaps_compiled_maxz+1
x1=1;y1=1
else
var/list/l=ConsiderRegion(1,1,world.maxx,world.maxy,swapmaps_compiled_maxz+1)
x1=l[1]
y1=l[2]
z1=l[3]
qdel(l)
x2+=x1-1
y2+=y1-1
z2+=z1-1
space_manager.increase_max_zlevel_to(z2) // stretch z if necessary
if(!ischunk)
swapmaps_loaded[src]=null
swapmaps_byname[id]=src
proc/ConsiderRegion(X1,Y1,X2,Y2,Z1,Z2)
while(1)
var/nextz=0
var/swapmap/M
for(M in swapmaps_loaded)
if(M.z2<Z1 || (Z2 && M.z1>Z2) || M.z1>=Z1+z2 ||\
M.x1>X2 || M.x2<X1 || M.x1>=X1+x2 ||\
M.y1>Y2 || M.y2<Y1 || M.y1>=Y1+y2) continue
// look for sub-regions with a defined ceiling
var/nz2=Z2?(Z2):Z1+z2-1+M.z2-M.z1
if(M.x1>=X1+x2)
.=ConsiderRegion(X1,Y1,M.x1-1,Y2,Z1,nz2)
if(.) return
else if(M.x2<=X2-x2)
.=ConsiderRegion(M.x2+1,Y1,X2,Y2,Z1,nz2)
if(.) return
if(M.y1>=Y1+y2)
.=ConsiderRegion(X1,Y1,X2,M.y1-1,Z1,nz2)
if(.) return
else if(M.y2<=Y2-y2)
.=ConsiderRegion(X1,M.y2+1,X2,Y2,Z1,nz2)
if(.) return
nextz=nextz?min(nextz,M.z2+1):(M.z2+1)
if(!M)
/* If nextz is not 0, then at some point there was an overlap that
could not be resolved by using an area to the side */
if(nextz) Z1=nextz
if(!nextz || (Z2 && Z2-Z1+1<z2))
return (!Z2 || Z2-Z1+1>=z2)?list(X1,Y1,Z1):null
X1=1;X2=world.maxx
Y1=1;Y2=world.maxy
proc/CutXYZ()
var/mx=swapmaps_compiled_maxx
var/my=swapmaps_compiled_maxy
var/mz=swapmaps_compiled_maxz
for(var/swapmap/M in swapmaps_loaded) // may not include src
mx=max(mx,M.x2)
my=max(my,M.y2)
mz=max(mz,M.z2)
world.maxx=mx
world.maxy=my
space_manager.cut_levels_downto(mz)
// save and delete
proc/Unload()
Save()
qdel(src)
proc/Save()
if(id==src) return 0
var/savefile/S=mode?(new):new("map_[id].sav")
S << src
while(locked) sleep(1)
if(mode)
fdel("map_[id].txt")
S.ExportText("/","map_[id].txt")
return 1
// this will not delete existing savefiles for this map
proc/SetID(newid)
swapmaps_byname-=id
id=newid
swapmaps_byname[id]=src
proc/AllTurfs(z)
if(isnum(z) && (z<z1 || z>z2)) return null
return block(LoCorner(z),HiCorner(z))
// this could be safely called for an obj or mob as well, but
// probably not an area
proc/Contains(turf/T)
return (T && T.x>=x1 && T.x<=x2\
&& T.y>=y1 && T.y<=y2\
&& T.z>=z1 && T.z<=z2)
proc/InUse()
for(var/turf/T in AllTurfs())
for(var/mob/M in T) if(M.key) return 1
proc/LoCorner(z=z1)
return locate(x1,y1,z)
proc/HiCorner(z=z2)
return locate(x2,y2,z)
/*
Build procs: Take 2 turfs as corners, plus an item type.
An item may be like:
/turf/wall
/obj/fence{icon_state="iron"}
*/
proc/BuildFilledRectangle(turf/T1,turf/T2,item)
if(!Contains(T1) || !Contains(T2)) return
var/turf/T=T1
// pick new corners in a block()-friendly form
T1=locate(min(T1.x,T2.x),min(T1.y,T2.y),min(T1.z,T2.z))
T2=locate(max(T.x,T2.x),max(T.y,T2.y),max(T.z,T2.z))
for(T in block(T1,T2)) new item(T)
proc/BuildRectangle(turf/T1,turf/T2,item)
if(!Contains(T1) || !Contains(T2)) return
var/turf/T=T1
// pick new corners in a block()-friendly form
T1=locate(min(T1.x,T2.x),min(T1.y,T2.y),min(T1.z,T2.z))
T2=locate(max(T.x,T2.x),max(T.y,T2.y),max(T.z,T2.z))
if(T2.x-T1.x<2 || T2.y-T1.y<2) BuildFilledRectangle(T1,T2,item)
else
//for(T in block(T1,T2)-block(locate(T1.x+1,T1.y+1,T1.z),locate(T2.x-1,T2.y-1,T2.z)))
for(T in block(T1,locate(T2.x,T1.y,T2.z))) new item(T)
for(T in block(locate(T1.x,T2.y,T1.z),T2)) new item(T)
for(T in block(locate(T1.x,T1.y+1,T1.z),locate(T1.x,T2.y-1,T2.z))) new item(T)
for(T in block(locate(T2.x,T1.y+1,T1.z),locate(T2.x,T2.y-1,T2.z))) new item(T)
/*
Supplementary build proc: Takes a list of turfs, plus an item
type. Actually the list doesn't have to be just turfs.
*/
proc/BuildInTurfs(list/turfs,item)
for(var/T in turfs) new item(T)
atom
Write(savefile/S)
for(var/V in vars-"x"-"y"-"z"-"contents"-"icon"-"overlays"-"underlays")
if(issaved(vars[V]))
if(vars[V]!=initial(vars[V])) S[V]<<vars[V]
else S.dir.Remove(V)
if(icon!=initial(icon))
if(swapmaps_iconcache && swapmaps_iconcache[icon])
S["icon"]<<swapmaps_iconcache[icon]
else S["icon"]<<icon
// do not save mobs with keys; do save other mobs
var/mob/M
for(M in src) if(M.key) break
if(overlays.len) S["overlays"]<<overlays
if(underlays.len) S["underlays"]<<underlays
if(contents.len && !isarea(src))
var/list/l=contents
if(M)
l=l.Copy()
for(M in src) if(M.key) l-=M
if(l.len) S["contents"]<<l
if(l!=contents) qdel(l)
Read(savefile/S)
var/list/l
if(contents.len) l=contents
..()
// if the icon was a text string, it would not have loaded properly
// replace it from the cache list
if(!icon && ("icon" in S.dir))
var/ic
S["icon"]>>ic
if(istext(ic)) icon=swapmaps_iconcache[ic]
if(l && contents!=l)
contents+=l
qdel(l)
// set this up (at runtime) as follows:
// list(\
// 'player.dmi'="player",\
// 'monster.dmi'="monster",\
// ...
// 'item.dmi'="item")
var/list/swapmaps_iconcache
// preferred mode; sav or text
var/const/SWAPMAPS_SAV=0
var/const/SWAPMAPS_TEXT=1
var/swapmaps_mode=SWAPMAPS_SAV
var/swapmaps_compiled_maxx
var/swapmaps_compiled_maxy
var/swapmaps_compiled_maxz
var/swapmaps_initialized
var/swapmaps_loaded
var/swapmaps_byname
proc/InitializeSwapMaps()
if(swapmaps_initialized) return
swapmaps_initialized=1
swapmaps_compiled_maxx=world.maxx
swapmaps_compiled_maxy=world.maxy
swapmaps_compiled_maxz=world.maxz
swapmaps_loaded=list()
swapmaps_byname=list()
if(swapmaps_iconcache)
for(var/V in swapmaps_iconcache)
// reverse-associate everything
// so you can look up an icon file by name or vice-versa
swapmaps_iconcache[swapmaps_iconcache[V]]=V
proc/SwapMaps_AddIconToCache(name,icon)
if(!swapmaps_iconcache) swapmaps_iconcache=list()
swapmaps_iconcache[name]=icon
swapmaps_iconcache[icon]=name
proc/SwapMaps_Find(id)
InitializeSwapMaps()
return swapmaps_byname[id]
proc/SwapMaps_Load(id)
InitializeSwapMaps()
var/swapmap/M=swapmaps_byname[id]
if(!M)
var/savefile/S
var/text=0
if(swapmaps_mode==SWAPMAPS_TEXT && fexists("map_[id].txt"))
text=1
else if(fexists("map_[id].sav"))
S=new("map_[id].sav")
else if(swapmaps_mode!=SWAPMAPS_TEXT && fexists("map_[id].txt"))
text=1
else return // no file found
if(text)
S=new
S.ImportText("/",file("map_[id].txt"))
S >> M
while(M.locked) sleep(1)
M.mode=text
return M
proc/SwapMaps_Save(id)
InitializeSwapMaps()
var/swapmap/M=swapmaps_byname[id]
if(M) M.Save()
return M
proc/SwapMaps_Save_All()
InitializeSwapMaps()
for(var/swapmap/M in swapmaps_loaded)
if(M) M.Save()
proc/SwapMaps_Unload(id)
InitializeSwapMaps()
var/swapmap/M=swapmaps_byname[id]
if(!M) return // return silently from an error
M.Unload()
return 1
proc/SwapMaps_DeleteFile(id)
fdel("map_[id].sav")
fdel("map_[id].txt")
proc/SwapMaps_CreateFromTemplate(template_id)
var/swapmap/M=new
var/savefile/S
var/text=0
if(swapmaps_mode==SWAPMAPS_TEXT && fexists("map_[template_id].txt"))
text=1
else if(fexists("map_[template_id].sav"))
S=new("map_[template_id].sav")
else if(swapmaps_mode!=SWAPMAPS_TEXT && fexists("map_[template_id].txt"))
text=1
else
log_world("SwapMaps error in SwapMaps_CreateFromTemplate(): map_[template_id] file not found.")
return
if(text)
S=new
S.ImportText("/",file("map_[template_id].txt"))
/*
This hacky workaround is needed because S >> M will create a brand new
M to fill with data. There's no way to control the Read() process
properly otherwise. The //.0 path should always match the map, however.
*/
S.cd="//.0"
M.Read(S,M)
M.mode=text
while(M.locked) sleep(1)
return M
proc/SwapMaps_LoadChunk(chunk_id,turf/locorner)
var/swapmap/M=new
var/savefile/S
var/text=0
if(swapmaps_mode==SWAPMAPS_TEXT && fexists("map_[chunk_id].txt"))
text=1
else if(fexists("map_[chunk_id].sav"))
S=new("map_[chunk_id].sav")
else if(swapmaps_mode!=SWAPMAPS_TEXT && fexists("map_[chunk_id].txt"))
text=1
else
log_world("SwapMaps error in SwapMaps_LoadChunk(): map_[chunk_id] file not found.")
return
if(text)
S=new
S.ImportText("/",file("map_[chunk_id].txt"))
/*
This hacky workaround is needed because S >> M will create a brand new
M to fill with data. There's no way to control the Read() process
properly otherwise. The //.0 path should always match the map, however.
*/
S.cd="//.0"
M.Read(S,M,locorner)
while(M.locked) sleep(1)
qdel(M)
return 1
proc/SwapMaps_SaveChunk(chunk_id,turf/corner1,turf/corner2)
if(!corner1 || !corner2)
log_world("SwapMaps error in SwapMaps_SaveChunk():")
if(!corner1) log_world(" corner1 turf is null")
if(!corner2) log_world(" corner2 turf is null")
return
var/swapmap/M=new
M.id=chunk_id
M.ischunk=1 // this is a chunk
M.x1=min(corner1.x,corner2.x)
M.y1=min(corner1.y,corner2.y)
M.z1=min(corner1.z,corner2.z)
M.x2=max(corner1.x,corner2.x)
M.y2=max(corner1.y,corner2.y)
M.z2=max(corner1.z,corner2.z)
M.mode=swapmaps_mode
M.Save()
while(M.locked) sleep(1)
qdel(M)
return 1
proc/SwapMaps_GetSize(id)
var/savefile/S
var/text=0
if(swapmaps_mode==SWAPMAPS_TEXT && fexists("map_[id].txt"))
text=1
else if(fexists("map_[id].sav"))
S=new("map_[id].sav")
else if(swapmaps_mode!=SWAPMAPS_TEXT && fexists("map_[id].txt"))
text=1
else
log_world("SwapMaps error in SwapMaps_GetSize(): map_[id] file not found.")
return
if(text)
S=new
S.ImportText("/",file("map_[id].txt"))
/*
The //.0 path should always be the map. There's no other way to
read this data.
*/
S.cd="//.0"
var/x
var/y
var/z
S["x"] >> x
S["y"] >> y
S["z"] >> z
return list(x,y,z)
@@ -181,7 +181,7 @@
/obj/item/paper/terrorspiders9
name = "paper - 'Research Notes'"
info = "<b>The notes appear gibberish to you. Perhaps a destructive analyser in R&D could make sense of them.</b>"
info = "<b>The notes appear gibberish to you. Perhaps a destructive analyzer in R&D could make sense of them.</b>"
origin_tech = "combat=4;materials=4;engineering=4;biotech=4"
/obj/item/gun/energy/laser/awaymission_aeg
@@ -257,5 +257,3 @@
else
to_chat(user, "<span class='notice'>Your ID card already has all the access this machine can give.</span>")
. = 1
@@ -19,4 +19,9 @@
/area/awaymission/BMPship/Fore
name = "\improper Fore Block"
icon_state = "away3"
requires_power = 1
/area/awaymission/BMPship/Gate
name = "\improper Gateway Block"
icon_state = "away4"
requires_power = 1
@@ -28,10 +28,10 @@
anchored = 1
density = 1
use_power = 0
use_power = NO_POWER_USE
idle_power_usage = 0
active_power_usage = 0
active = 1
locked = 1
state = 2
state = 2
@@ -234,7 +234,7 @@
D.account = get_card_account(id, occupant)
if(!D.account)
return null
if(!D.account.charge(100, transaction_purpose = "10 minutes", dest_name = name))
if(!D.account.charge(100, null, "10 minutes hotel stay", "Biesel GalaxyNet Terminal [rand(111,1111)]", "[name]"))
return null
D.occupant = occupant
@@ -251,7 +251,7 @@
if(!D || !D.occupant)
return
if(D.account.charge(100, transaction_purpose = "10 minutes", dest_name = name))
if(D.account.charge(100, null, "10 minutes hotel stay extension", "Biesel GalaxyNet Terminal [rand(111,1111)]", "[name]"))
D.roomtimer = addtimer(CALLBACK(src, .proc/process_room, roomid), PAY_INTERVAL, TIMER_STOPPABLE)
else
force_checkout(roomid)
@@ -299,4 +299,4 @@
return
S.retal_target = target
S.retal = 1
S.retal = 1
@@ -46,7 +46,7 @@
anchored = 1
density = 1
use_power = 0
use_power = NO_POWER_USE
var/chargesa = 1
var/insistinga = 0
@@ -72,7 +72,7 @@
else
chargesa--
insistinga = 0
var/wish = input("You want...","Wish") as null|anything in list("Power","Wealth","Immortality","To Kill","Peace")
var/wish = input("You want...","Wish") as null|anything in list("Power","Wealth","Immortality","Peace")
switch(wish)
if("Power")
to_chat(user, "<B>Your wish is granted, but at a terrible cost...</B>")
@@ -115,28 +115,6 @@
to_chat(user, "Aside from your new traits, you are mentally unchanged and retain your prior obligations.")
human.set_species(/datum/species/shadow)
user.regenerate_icons()
if("To Kill")
to_chat(user, "<B>Your wish is granted, but at a terrible cost...</B>")
to_chat(user, "The Wish Granter punishes you for your wickedness, claiming your soul and warping your body to match the darkness in your heart.")
ticker.mode.traitors += user.mind
user.mind.special_role = SPECIAL_ROLE_TRAITOR
var/datum/objective/hijack/hijack = new
hijack.owner = user.mind
user.mind.objectives += hijack
to_chat(user, "<B>Your inhibitions are swept away, the bonds of loyalty broken, you are free to murder as you please!</B>")
var/obj_count = 1
for(var/datum/objective/OBJ in user.mind.objectives)
to_chat(user, "<B>Objective #[obj_count]</B>: [OBJ.explanation_text]")
obj_count++
if(ishuman(user))
var/mob/living/carbon/human/human = user
if(!isshadowperson(human))
to_chat(user, "<span class='warning'>Your flesh rapidly mutates!</span>")
to_chat(user, "<b>You are now a Shadow Person, a mutant race of darkness-dwelling humanoids.</b>")
to_chat(user, "<span class='warning'>Your body reacts violently to light.</span> <span class='notice'>However, it naturally heals in darkness.</span>")
to_chat(user, "Aside from your new traits, you are mentally unchanged and retain your prior obligations.")
human.set_species(/datum/species/shadow)
user.regenerate_icons()
if("Peace")
to_chat(user, "<B>Whatever alien sentience that the Wish Granter possesses is satisfied with your wish. There is a distant wailing as the last of the Faithless begin to die, then silence.</B>")
to_chat(user, "You feel as if you just narrowly avoided a terrible fate...")
@@ -288,4 +266,4 @@
say("How could you betray the Syndicate?")
for(var/mob/living/simple_animal/hostile/syndicate/ranged/wildwest/W in living_mob_list)
W.on_alert = TRUE
..(gibbed)
..(gibbed)
+2 -1
View File
@@ -200,6 +200,7 @@ proc/getFilesSlow(var/client/client, var/list/files, var/register_asset = TRUE)
"large_stamp-law.png" = 'icons/paper_icons/large_stamp-law.png',
"large_stamp-cent.png" = 'icons/paper_icons/large_stamp-cent.png',
"large_stamp-syndicate.png" = 'icons/paper_icons/large_stamp-syndicate.png',
"large_stamp-rep.png" = 'icons/paper_icons/large_stamp-rep.png',
"talisman.png" = 'icons/paper_icons/talisman.png',
"ntlogo.png" = 'icons/paper_icons/ntlogo.png'
)
@@ -348,4 +349,4 @@ proc/getFilesSlow(var/client/client, var/list/files, var/register_asset = TRUE)
register_asset(asset_name, assets[asset_name])
/datum/asset/mob_hunt/send(client)
send_asset_list(client, assets, verify)
send_asset_list(client, assets, verify)
+18 -112
View File
@@ -109,136 +109,42 @@
if("shop")
if(href_list["KarmaBuy"])
var/karma=verify_karma()
if(isnull(karma)) //Doesn't display anything if karma database is down.
return
switch(href_list["KarmaBuy"])
if("1")
if(karma <5)
to_chat(usr, "You do not have enough karma!")
return
else
if(alert("Are you sure you want to unlock Barber?", "Confirmation", "No", "Yes") != "Yes")
return
DB_job_unlock("Barber",5)
return
karma_purchase(karma,5,"job","Barber")
if("2")
if(karma <5)
to_chat(usr, "You do not have enough karma!")
return
else
if(alert("Are you sure you want to unlock Brig Physician?", "Confirmation", "No", "Yes") != "Yes")
return
DB_job_unlock("Brig Physician",5)
return
karma_purchase(karma,5,"job","Brig Physician")
if("3")
if(karma <30)
to_chat(usr, "You do not have enough karma!")
return
else
if(alert("Are you sure you want to unlock Nanotrasen Representative?", "Confirmation", "No", "Yes") != "Yes")
return
DB_job_unlock("Nanotrasen Representative",30)
return
karma_purchase(karma,30,"job","Nanotrasen Representative")
if("5")
if(karma <30)
to_chat(usr, "You do not have enough karma!")
return
else
if(alert("Are you sure you want to unlock Blueshield?", "Confirmation", "No", "Yes") != "Yes")
return
DB_job_unlock("Blueshield",30)
return
karma_purchase(karma,30,"job","Blueshield")
if("6")
if(karma <30)
to_chat(usr, "You do not have enough karma!")
return
else
if(alert("Are you sure you want to unlock Mechanic?", "Confirmation", "No", "Yes") != "Yes")
return
DB_job_unlock("Mechanic",30)
return
karma_purchase(karma,30,"job","Mechanic")
if("7")
if(karma <45)
to_chat(usr, "You do not have enough karma!")
return
else
if(alert("Are you sure you want to unlock Magistrate?", "Confirmation", "No", "Yes") != "Yes")
return
DB_job_unlock("Magistrate",45)
return
karma_purchase(karma,45,"job","Magistrate")
if("9")
if(karma <30)
to_chat(usr, "You do not have enough karma!")
return
else
if(alert("Are you sure you want to unlock Security Pod Pilot?", "Confirmation", "No", "Yes") != "Yes")
return
DB_job_unlock("Security Pod Pilot",30)
return
karma_purchase(karma,30,"job","Security Pod Pilot")
if(href_list["KarmaBuy2"])
var/karma=verify_karma()
if(isnull(karma)) //Doesn't display anything if karma database is down.
return
switch(href_list["KarmaBuy2"])
if("1")
if(karma <15)
to_chat(usr, "You do not have enough karma!")
return
else
if(alert("Are you sure you want to unlock Machine People?", "Confirmation", "No", "Yes") != "Yes")
return
DB_species_unlock("Machine",15)
return
karma_purchase(karma,15,"species","Machine People","Machine")
if("2")
if(karma <30)
to_chat(usr, "You do not have enough karma!")
return
else
if(alert("Are you sure you want to unlock Kidan?", "Confirmation", "No", "Yes") != "Yes")
return
DB_species_unlock("Kidan",30)
return
karma_purchase(karma,30,"species","Kidan")
if("3")
if(karma <30)
to_chat(usr, "You do not have enough karma!")
return
else
if(alert("Are you sure you want to unlock Grey?", "Confirmation", "No", "Yes") != "Yes")
return
DB_species_unlock("Grey",30)
return
karma_purchase(karma,30,"species","Grey")
if("4")
if(karma <45)
to_chat(usr, "You do not have enough karma!")
return
else
if(alert("Are you sure you want to unlock Vox?", "Confirmation", "No", "Yes") != "Yes")
return
DB_species_unlock("Vox",45)
return
karma_purchase(karma,45,"species","Vox")
if("5")
if(karma <45)
to_chat(usr, "You do not have enough karma!")
return
else
if(alert("Are you sure you want to unlock Slime People?", "Confirmation", "No", "Yes") != "Yes")
return
DB_species_unlock("Slime People",45)
return
karma_purchase(karma,45,"species","Slime People")
if("6")
if(karma <100)
to_chat(usr, "You do not have enough karma!")
return
else
if(alert("Are you sure you want to unlock Plasmaman?", "Confirmation", "No", "Yes") != "Yes")
return
DB_species_unlock("Plasmaman",100)
return
karma_purchase(karma,100,"species","Plasmaman")
if("7")
if(karma <30)
to_chat(usr, "You do not have enough karma!")
return
else
if(alert("Are you sure you want to unlock Drask?", "Confirmation", "No", "Yes") != "Yes")
return
DB_species_unlock("Drask",30)
return
karma_purchase(karma,30,"species","Drask")
if(href_list["KarmaRefund"])
var/type = href_list["KarmaRefundType"]
var/job = href_list["KarmaRefund"]
@@ -1,7 +1,11 @@
/datum/gear/lipstick
display_name = "lipstick, red"
path = /obj/item/lipstick
sort_category = "Cosmetics"
/datum/gear/lipstick/black
display_name = "lipstick, black"
path = /obj/item/lipstick/black
sort_category = "Cosmetics"
/datum/gear/lipstick/jade
display_name = "lipstick, jade"
@@ -11,9 +15,13 @@
display_name = "lipstick, purple"
path = /obj/item/lipstick/purple
/datum/gear/lipstick/red
display_name = "lipstick, red"
path = /obj/item/lipstick
/datum/gear/lipstick/blue
display_name = "lipstick, blue"
path = /obj/item/lipstick/blue
/datum/gear/lipstick/lime
display_name = "lipstick, lime"
path = /obj/item/lipstick/lime
/datum/gear/monocle
display_name = "monocle"
+1
View File
@@ -561,6 +561,7 @@ BLIND // can't see anything
strip_delay = 80
put_on_delay = 80
burn_state = FIRE_PROOF
hide_tail_by_species = null
species_restricted = list("exclude","Diona","Vox","Wryn")
//Under clothing
+50 -186
View File
@@ -202,7 +202,27 @@
var/aggressiveness = 1
var/safety = 1
actions_types = list(/datum/action/item_action/halt, /datum/action/item_action/adjust, /datum/action/item_action/selectphrase)
var/phrase_list = list(
"halt" = "HALT! HALT! HALT! HALT!",
"bobby" = "Stop in the name of the Law.",
"compliance" = "Compliance is in your best interest.",
"justice" = "Prepare for justice!",
"running" = "Running will only increase your sentence.",
"dontmove" = "Don't move, Creep!",
"floor" = "Down on the floor, Creep!",
"robocop" = "Dead or alive you're coming with me.",
"god" = "God made today for the crooks we could not catch yesterday.",
"freeze" = "Freeze, Scum Bag!",
"imperial" = "Stop right there, criminal scum!",
"bash" = "Stop or I'll bash you.",
"harry" = "Go ahead, make my day.",
"asshole" = "Stop breaking the law, asshole.",
"stfu" = "You have the right to shut the fuck up",
"shutup" = "Shut up crime!",
"super" = "Face the wrath of the golden bolt.",
"dredd" = "I am, the LAW!"
)
/obj/item/clothing/mask/gas/sechailer/hos
name = "\improper HOS SWAT mask"
desc = "A close-fitting tactical mask with an especially aggressive Compli-o-nator 3000. It has a tan stripe."
@@ -250,133 +270,34 @@
else if(actiontype == /datum/action/item_action/adjust)
adjustmask(user)
else if(actiontype == /datum/action/item_action/selectphrase)
var/key = phrase_list[phrase]
var/message = phrase_list[key]
if (!safety)
to_chat(user, "<span class='notice'>You set the restrictor to: FUCK YOUR CUNT YOU SHIT EATING COCKSUCKER MAN EAT A DONG FUCKING ASS RAMMING SHIT FUCK EAT PENISES IN YOUR FUCK FACE AND SHIT OUT ABORTIONS OF FUCK AND DO SHIT IN YOUR ASS YOU COCK FUCK SHIT MONKEY FUCK ASS WANKER FROM THE DEPTHS OF SHIT.</span>")
return
switch(aggressiveness)
if(1)
switch(phrase)
if(1)
to_chat(user, "<span class='notice'>You set the restrictor to: Stop in the name of the Law.</span>")
phrase = 2
if(2)
to_chat(user, "<span class='notice'>You set the restrictor to: Compliance is in your best interest.</span>")
phrase = 3
if(3)
to_chat(user, "<span class='notice'>You set the restrictor to: Prepare for justice.</span>")
phrase = 4
if(4)
to_chat(user, "<span class='notice'>You set the restrictor to: Running will only increase your sentence.</span>")
phrase = 5
if(5)
to_chat(user, "<span class='notice'>You set the restrictor to: Don't move, Creep!</span>")
phrase = 6
if(6)
to_chat(user, "<span class='notice'>You set the restrictor to: HALT! HALT! HALT! HALT!</span>")
phrase = 1
else
to_chat(user, "<span class='notice'>You set the restrictor to: HALT! HALT! HALT! HALT!</span>")
phrase = 1
phrase = (phrase < 6) ? (phrase + 1) : 1
key = phrase_list[phrase]
message = phrase_list[key]
to_chat(user,"<span class='notice'>You set the restrictor to: [message]</span>")
if(2)
switch(phrase)
if(7)
to_chat(user, "<span class='notice'>You set the restrictor to: Dead or alive you're coming with me.</span>")
phrase = 8
if(8)
to_chat(user, "<span class='notice'>You set the restrictor to: God made today for the crooks we could not catch yesterday.</span>")
phrase = 9
if(9)
to_chat(user, "<span class='notice'>You set the restrictor to: Freeze, Scum Bag!</span>")
phrase = 10
if(10)
to_chat(user, "<span class='notice'>You set the restrictor to: Stop right there, criminal scum!</span>")
phrase = 11
if(11)
to_chat(user, "<span class='notice'>You set the restrictor to: Down on the floor, Creep!</span>")
phrase = 7
else
to_chat(user, "<span class='notice'>You set the restrictor to: Down on the floor, Creep!</span>")
phrase = 7
phrase = (phrase < 11 && phrase >= 7) ? (phrase + 1) : 7
key = phrase_list[phrase]
message = phrase_list[key]
to_chat(user,"<span class='notice'>You set the restrictor to: [message]</span>")
if(3)
switch(phrase)
if(12)
to_chat(user, "<span class='notice'>You set the restrictor to: Go ahead, make my day.</span>")
phrase = 13
if(13)
to_chat(user, "<span class='notice'>You set the restrictor to: Stop breaking the law, ass hole.</span>")
phrase = 14
if(14)
to_chat(user, "<span class='notice'>You set the restrictor to: You have the right to shut the fuck up.</span>")
phrase = 15
if(15)
to_chat(user, "<span class='notice'>You set the restrictor to: Shut up crime!</span>")
phrase = 16
if(16)
to_chat(user, "<span class='notice'>You set the restrictor to: Face the wrath of the golden bolt.</span>")
phrase = 17
if(17)
to_chat(user, "<span class='notice'>You set the restrictor to: I am, the LAW!</span>")
phrase = 18
if(18)
to_chat(user, "<span class='notice'>You set the restrictor to: Stop or I'll bash you.</span>")
phrase = 12
else
to_chat(user, "<span class='notice'>You set the restrictor to: Go ahead, make my day.</span>")
phrase = 13
phrase = (phrase < 18 && phrase >= 12 ) ? (phrase + 1) : 12
key = phrase_list[phrase]
message = phrase_list[key]
to_chat(user,"<span class='notice'>You set the restrictor to: [message]</span>")
if(4)
switch(phrase)
if(1)
to_chat(user, "<span class='notice'>You set the restrictor to: Stop in the name of the Law.</span>")
phrase = 2
if(2)
to_chat(user, "<span class='notice'>You set the restrictor to: Compliance is in your best interest.</span>")
phrase = 3
if(3)
to_chat(user, "<span class='notice'>You set the restrictor to: Prepare for justice.</span>")
phrase = 4
if(4)
to_chat(user, "<span class='notice'>You set the restrictor to: Running will only increase your sentence.</span>")
phrase = 5
if(5)
to_chat(user, "<span class='notice'>You set the restrictor to: Don't move, Creep!</span>")
phrase = 6
if(6)
to_chat(user, "<span class='notice'>You set the restrictor to: Down on the floor, Creep!</span>")
phrase = 7
if(7)
to_chat(user, "<span class='notice'>You set the restrictor to: Dead or alive you're coming with me.</span>")
phrase = 8
if(8)
to_chat(user, "<span class='notice'>You set the restrictor to: God made today for the crooks we could not catch yesterday.</span>")
phrase = 9
if(9)
to_chat(user, "<span class='notice'>You set the restrictor to: Freeze, Scum Bag!</span>")
phrase = 10
if(10)
to_chat(user, "<span class='notice'>You set the restrictor to: Stop right there, criminal scum!</span>")
phrase = 11
if(11)
to_chat(user, "<span class='notice'>You set the restrictor to: Stop or I'll bash you.</span>")
phrase = 12
if(12)
to_chat(user, "<span class='notice'>You set the restrictor to: Go ahead, make my day.</span>")
phrase = 13
if(13)
to_chat(user, "<span class='notice'>You set the restrictor to: Stop breaking the law, ass hole.</span>")
phrase = 14
if(14)
to_chat(user, "<span class='notice'>You set the restrictor to: You have the right to shut the fuck up.</span>")
phrase = 15
if(15)
to_chat(user, "<span class='notice'>You set the restrictor to: Shut up crime!</span>")
phrase = 16
if(16)
to_chat(user, "<span class='notice'>You set the restrictor to: Face the wrath of the golden bolt.</span>")
phrase = 17
if(17)
to_chat(user, "<span class='notice'>You set the restrictor to: I am, the LAW!</span>")
phrase = 18
if(18)
to_chat(user, "<span class='notice'>You set the restrictor to: HALT! HALT! HALT! HALT!</span>")
phrase = 1
phrase = (phrase < 18 && phrase >= 1 ) ? (phrase + 1) : 1
key = phrase_list[phrase]
message = phrase_list[key]
to_chat(user,"<span class='notice'>You set the restrictor to: [message]</span>")
else
to_chat(user, "<span class='notice'>It's broken.</span>")
@@ -419,77 +340,20 @@
return
/obj/item/clothing/mask/gas/sechailer/proc/halt()
var/phrase_text = null
var/phrase_sound = null
var/key = phrase_list[phrase]
var/message = phrase_list[key]
if(cooldown < world.time - 35) // A cooldown, to stop people being jerks
if(!safety)
phrase_text = "FUCK YOUR CUNT YOU SHIT EATING COCKSUCKER MAN EAT A DONG FUCKING ASS RAMMING SHIT FUCK EAT PENISES IN YOUR FUCK FACE AND SHIT OUT ABORTIONS OF FUCK AND DO SHIT IN YOUR ASS YOU COCK FUCK SHIT MONKEY FUCK ASS WANKER FROM THE DEPTHS OF SHIT."
usr.visible_message("[usr]'s Compli-o-Nator: <font color='red' size='4'><b>[phrase_text]</b></font>")
message = "FUCK YOUR CUNT YOU SHIT EATING COCKSUCKER MAN EAT A DONG FUCKING ASS RAMMING SHIT FUCK EAT PENISES IN YOUR FUCK FACE AND SHIT OUT ABORTIONS OF FUCK AND DO SHIT IN YOUR ASS YOU COCK FUCK SHIT MONKEY FUCK ASS WANKER FROM THE DEPTHS OF SHIT."
usr.visible_message("[usr]'s Compli-o-Nator: <font color='red' size='4'><b>[message]</b></font>")
playsound(src.loc, 'sound/voice/binsult.ogg', 100, 0, 4)
cooldown = world.time
return
switch(phrase) //sets the properties of the chosen phrase
if(1) // good cop
phrase_text = "HALT! HALT! HALT! HALT!"
phrase_sound = "halt"
if(2)
phrase_text = "Stop in the name of the Law."
phrase_sound = "bobby"
if(3)
phrase_text = "Compliance is in your best interest."
phrase_sound = "compliance"
if(4)
phrase_text = "Prepare for justice!"
phrase_sound = "justice"
if(5)
phrase_text = "Running will only increase your sentence."
phrase_sound = "running"
if(6) // bad cop
phrase_text = "Don't move, Creep!"
phrase_sound = "dontmove"
if(7)
phrase_text = "Down on the floor, Creep!"
phrase_sound = "floor"
if(8)
phrase_text = "Dead or alive you're coming with me."
phrase_sound = "robocop"
if(9)
phrase_text = "God made today for the crooks we could not catch yesterday."
phrase_sound = "god"
if(10)
phrase_text = "Freeze, Scum Bag!"
phrase_sound = "freeze"
if(11)
phrase_text = "Stop right there, criminal scum!"
phrase_sound = "imperial"
if(12) // LA-PD
phrase_text = "Stop or I'll bash you."
phrase_sound = "bash"
if(13)
phrase_text = "Go ahead, make my day."
phrase_sound = "harry"
if(14)
phrase_text = "Stop breaking the law, ass hole."
phrase_sound = "asshole"
if(15)
phrase_text = "You have the right to shut the fuck up."
phrase_sound = "stfu"
if(16)
phrase_text = "Shut up crime!"
phrase_sound = "shutup"
if(17)
phrase_text = "Face the wrath of the golden bolt."
phrase_sound = "super"
if(18)
phrase_text = "I am, the LAW!"
phrase_sound = "dredd"
usr.visible_message("[usr]'s Compli-o-Nator: <font color='red' size='4'><b>[phrase_text]</b></font>")
playsound(src.loc, "sound/voice/complionator/[phrase_sound].ogg", 100, 0, 4)
usr.visible_message("[usr]'s Compli-o-Nator: <font color='red' size='4'><b>[message]</b></font>")
playsound(src.loc, "sound/voice/complionator/[key].ogg", 100, 0, 4)
cooldown = world.time
@@ -120,6 +120,78 @@
mute = MUZZLE_MUTE_NONE
security_lock = TRUE
locked = FALSE
materials = list(MAT_METAL=500, MAT_GLASS=50)
/obj/item/clothing/mask/muzzle/safety/shock
name = "shock muzzle"
desc = "A muzzle designed to prevent biting. This one is fitted with a behavior correction system."
var/obj/item/assembly/trigger = null
origin_tech = "materials=1;engineering=1"
materials = list(MAT_METAL=500, MAT_GLASS=50)
/obj/item/clothing/mask/muzzle/safety/shock/attackby(obj/item/W, mob/user, params)
if(isscrewdriver(W) && trigger)
to_chat(user, "<span class='notice'>You disassemble [src].</span>")
trigger.forceMove(get_turf(user))
trigger.master = null
trigger.holder = null
trigger = null
return TRUE
else if(istype(W, /obj/item/assembly/signaler) || istype(W, /obj/item/assembly/voice))
if(istype(trigger, /obj/item/assembly/signaler) || istype(trigger, /obj/item/assembly/voice))
to_chat(user, "<span class='notice'>Something is already attached to [src].</span>")
return FALSE
if(!user.drop_item())
to_chat(user, "<span class='warning'>You are unable to insert [W] into [src].</span>")
return FALSE
trigger = W
trigger.forceMove(src)
trigger.master = src
trigger.holder = src
to_chat(user, "<span class='notice'>You attach the [W] to [src].</span>")
return TRUE
else if(istype(W, /obj/item/assembly))
to_chat(user, "<span class='notice'>That won't fit in [src]. Perhaps a signaler or voice analyzer would?</span>")
return FALSE
return ..()
/obj/item/clothing/mask/muzzle/safety/shock/proc/can_shock(obj/item/clothing/C)
if(istype(C))
if(isliving(C.loc))
return C.loc
else if(isliving(loc))
return loc
return FALSE
/obj/item/clothing/mask/muzzle/safety/shock/proc/process_activation(var/obj/D, var/normal = 1, var/special = 1)
visible_message("[bicon(src)] *beep* *beep*", "*beep* *beep*")
var/mob/M = can_shock(loc)
if(M)
to_chat(M, "<span class='danger'>You feel a sharp shock!</span>")
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(3, 1, M)
s.start()
M.Weaken(5)
M.Stuttering(1)
M.Jitter(20)
return
/obj/item/clothing/mask/muzzle/safety/shock/HasProximity(atom/movable/AM as mob|obj)
if(trigger)
trigger.HasProximity(AM)
/obj/item/clothing/mask/muzzle/safety/shock/hear_talk(mob/living/M as mob, msg)
if(trigger)
trigger.hear_talk(M, msg)
/obj/item/clothing/mask/muzzle/safety/shock/hear_message(mob/living/M as mob, msg)
if(trigger)
trigger.hear_message(M, msg)
/obj/item/clothing/mask/surgical
+1 -1
View File
@@ -40,7 +40,7 @@
allowed = list(/obj/item/flashlight, /obj/item/tank, /obj/item/t_scanner, /obj/item/rcd, /obj/item/crowbar, \
/obj/item/screwdriver, /obj/item/weldingtool, /obj/item/wirecutters, /obj/item/wrench, /obj/item/multitool, \
/obj/item/radio, /obj/item/analyzer, /obj/item/gun/energy/laser, /obj/item/gun/energy/pulse, \
/obj/item/gun/energy/gun/advtaser, /obj/item/melee/baton, /obj/item/gun/energy/gun)
/obj/item/gun/energy/gun/advtaser, /obj/item/melee/baton, /obj/item/gun/energy/gun, /obj/item/gun/projectile/automatic/lasercarbine, /obj/item/gun/energy/gun/blueshield)
strip_delay = 130
species_fit = list("Drask", "Vox")
sprite_sheets = list(
+3 -2
View File
@@ -70,6 +70,7 @@
allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/t_scanner, /obj/item/rcd)
siemens_coefficient = 0
hide_tail_by_species = list("Vox" , "Vulpkanin" , "Unathi" , "Tajaran")
species_restricted = list("exclude","Diona","Wryn")
sprite_sheets = list(
"Unathi" = 'icons/mob/species/unathi/suit.dmi',
@@ -313,7 +314,7 @@
on = 1
actions_types = list(/datum/action/item_action/toggle_helmet_mode)
flags = BLOCKHAIR | STOPSPRESSUREDMAGE | THICKMATERIAL
visor_flags_inv = HIDEMASK|HIDEEYES|HIDEFACE
visor_flags_inv = HIDEMASK|HIDEEYES|HIDEFACE|HIDETAIL
/obj/item/clothing/head/helmet/space/hardsuit/syndi/update_icon()
icon_state = "hardsuit[on]-[item_color]"
@@ -379,7 +380,7 @@
desc = "A dual-mode advanced hardsuit designed for work in special operations. It is in travel mode. Property of Gorlex Marauders."
slowdown = 1
flags = STOPSPRESSUREDMAGE | THICKMATERIAL
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL
cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS
else
to_chat(user, "<span class='notice'>You switch your hardsuit to combat mode. You will take damage in zero pressure environments, but you are more suited for a fight.</span>")
@@ -110,7 +110,7 @@
slowdown = 0
flags = STOPSPRESSUREDMAGE
flags_size = ONESIZEFITSALL
allowed = list(/obj/item) //for stuffing exta special presents
allowed = list(/obj/item) //for stuffing extra special presents
//Space pirate outfit
/obj/item/clothing/head/helmet/space/pirate
@@ -139,13 +139,20 @@
//Paramedic EVA suit
/obj/item/clothing/head/helmet/space/eva/paramedic
name = "Paramedic EVA helmet"
desc = "A paramedic EVA helmet. Used in the recovery of bodies from space."
desc = "A brand new paramedic EVA helmet. It seems to mold to your head shape. Used for retrieving bodies in space."
icon_state = "paramedic-eva-helmet"
item_state = "paramedic-eva-helmet"
species_fit = list("Vox", "Grey")
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 20)
species_restricted = list("exclude", "Diona", "Wryn")
species_fit = list("Vox", "Grey" , "Skrell" , "Tajaran" , "Drask" , "Unathi" , "Vulpkanin")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/helmet.dmi',
"Grey" = 'icons/mob/species/grey/helmet.dmi'
"Grey" = 'icons/mob/species/grey/helmet.dmi',
"Skrell" = 'icons/mob/species/skrell/helmet.dmi',
"Tajaran" = 'icons/mob/species/tajaran/helmet.dmi',
"Drask" = 'icons/mob/species/drask/helmet.dmi',
"Unathi" = 'icons/mob/species/unathi/helmet.dmi',
"Vulpkanin" = 'icons/mob/species/vulpkanin/helmet.dmi',
)
sprite_sheets_obj = list(
"Vox" = 'icons/obj/clothing/species/vox/hats.dmi'
@@ -155,10 +162,18 @@
name = "Paramedic EVA suit"
icon_state = "paramedic-eva"
item_state = "paramedic-eva"
desc = "A paramedic EVA suit. Used in the recovery of bodies from space."
species_fit = list("Vox")
desc = "A brand new paramedic EVA suit. The nitrile seems a bit too thin to be space proof. Used for retrieving bodies in space."
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 20)
species_restricted = list("exclude", "Diona", "Wryn")
species_fit = list("Vox", "Grey" , "Skrell" , "Tajaran" , "Drask" , "Unathi" , "Vulpkanin")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/suit.dmi'
"Vox" = 'icons/mob/species/vox/suit.dmi',
"Grey" = 'icons/mob/species/grey/suit.dmi',
"Skrell" = 'icons/mob/species/skrell/suit.dmi',
"Tajaran" = 'icons/mob/species/tajaran/suit.dmi',
"Drask" = 'icons/mob/species/drask/suit.dmi',
"Unathi" = 'icons/mob/species/unathi/suit.dmi',
"Vulpkanin" = 'icons/mob/species/vulpkanin/suit.dmi',
)
sprite_sheets_obj = list(
"Vox" = 'icons/obj/clothing/species/vox/suits.dmi'
@@ -243,7 +243,6 @@
/obj/item/clothing/accessory/holobadge/cord
icon_state = "holobadge-cord"
item_color = "holobadge-cord"
slot_flags = SLOT_MASK | SLOT_TIE
/obj/item/clothing/accessory/holobadge/attack_self(mob/user as mob)
if(!stored_name)
@@ -44,7 +44,7 @@
return
if(!user.canUnEquip(W, 0))
to_chat(user, "<span class='warning'>You can't let go of the [W]!<span>")
to_chat(user, "<span class='warning'>You can't let go of the [W]!</span>")
return
holstered = W
@@ -3,7 +3,7 @@
desc = "It's a high visibility jumpsuit given to those engineers insane enough to achieve the rank of \"Chief engineer\". It has minor radiation shielding."
name = "chief engineer's jumpsuit"
icon_state = "chiefengineer"
item_state = "g_suit"
item_state = "chief"
item_color = "chief"
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 10)
flags_size = ONESIZEFITSALL
+13 -5
View File
@@ -103,7 +103,7 @@
item_color = "centcom"
/obj/item/clothing/under/rank/centcom/officer
desc = "Gold trim on space-black cloth, this uniform displays the rank of \"Lieutenant-Commander\" and bears \"N.C.V. Fearless CV-286\" on the left shounder."
desc = "Gold trim on space-black cloth, this uniform displays the rank of \"Lieutenant-Commander\" and bears \"N.C.V. Fearless CV-286\" on the left shoulder."
name = "\improper Nanotrasen Officers Uniform"
icon_state = "officer"
item_state = "g_suit"
@@ -112,7 +112,7 @@
flags_size = ONESIZEFITSALL
/obj/item/clothing/under/rank/centcom/captain
desc = "Gold trim on space-black cloth, this uniform displays the rank of \"Captain\" and bears \"N.C.V. Fearless CV-286\" on the left shounder."
desc = "Gold trim on space-black cloth, this uniform displays the rank of \"Captain\" and bears \"N.C.V. Fearless CV-286\" on the left shoulder."
name = "\improper Nanotrasen Captains Uniform"
icon_state = "centcom"
item_state = "dg_suit"
@@ -120,7 +120,7 @@
displays_id = 0
/obj/item/clothing/under/rank/centcom/blueshield
desc = "Gold trim on space-black cloth, this uniform displays the rank of \"Lieutenant\" and bears \"N.S.S. Cyberiad\" on the left shounder."
desc = "Gold trim on space-black cloth, this uniform displays the rank of \"Lieutenant\" and bears \"N.S.S. Cyberiad\" on the left shoulder."
name = "\improper Nanotrasen Navy Uniform"
icon_state = "officer"
item_state = "g_suit"
@@ -128,8 +128,12 @@
displays_id = 0
flags_size = ONESIZEFITSALL
/obj/item/clothing/under/rank/centcom/blueshield/New()
..()
desc = "Gold trim on space-black cloth, this uniform displays the rank of \"Lieutenant\" and bears [station_name()] on the left shoulder."
/obj/item/clothing/under/rank/centcom/representative
desc = "Gold trim on space-black cloth, this uniform displays the rank of \"Ensign\" and bears \"N.S.S. Cyberiad\" on the left shounder."
desc = "Gold trim on space-black cloth, this uniform displays the rank of \"Ensign\" and bears \"N.S.S. Cyberiad\" on the left shoulder."
name = "\improper Nanotrasen Navy Uniform"
icon_state = "officer"
item_state = "g_suit"
@@ -137,6 +141,10 @@
displays_id = 0
flags_size = ONESIZEFITSALL
/obj/item/clothing/under/rank/centcom/representative/New()
..()
desc = "Gold trim on space-black cloth, this uniform displays the rank of \"Ensign\" and bears [station_name()] on the left shoulder."
/obj/item/clothing/under/rank/centcom/diplomatic
desc = "A very gaudy and official looking uniform of the Nanotrasen Diplomatic Corps."
name = "\improper Nanotrasen Diplomatic Uniform"
@@ -831,4 +839,4 @@
icon_state = "medicalgown"
item_state = "medicalgown"
item_color = "medicalgown"
body_parts_covered = UPPER_TORSO|LOWER_TORSO
body_parts_covered = UPPER_TORSO|LOWER_TORSO
+97
View File
@@ -563,6 +563,61 @@
else
to_chat(user, "<span class='warning'>You can't modify [target]!</span>")
#define USED_MOD_HELM 1
#define USED_MOD_SUIT 2
/obj/item/fluff/pyro_wintersec_kit //DarkLordpyro: Valthorne Haliber
name = "winter sec conversion kit"
desc = "A securirty hardsuit conversion kit."
icon_state = "modkit"
w_class = WEIGHT_CLASS_SMALL
/obj/item/fluff/pyro_wintersec_kit/afterattack(atom/target, mob/user, proximity)
if(!proximity || !ishuman(user) || user.incapacitated())
return
var/mob/living/carbon/human/H = user
if(istype(target, /obj/item/clothing/head/helmet/space/hardsuit/security))
if(used & USED_MOD_HELM)
to_chat(H, "<span class='notice'>The kit's helmet modifier has already been used.</span>")
return
to_chat(H, "<span class='notice'>You modify the appearance of [target].</span>")
used |= USED_MOD_HELM
var/obj/item/clothing/head/helmet/space/hardsuit/security/P = target
P.name = "winterised security hardsuit helmet"
P.desc = "A rare winterised variant of the security hardsuit helmet, used on colder mining worlds for security patrols."
P.icon = 'icons/obj/custom_items.dmi'
P.icon_state = "hardsuit0-secf"
P.item_state = "hardsuit0-secf"
P.sprite_sheets = null
P.item_color = "secf"
user.update_icons()
if(P == H.head)
H.update_inv_head()
return
if(istype(target, /obj/item/clothing/suit/space/hardsuit/security))
if(used & USED_MOD_SUIT)
to_chat(user, "<span class='notice'>The kit's suit modifier has already been used.</span>")
return
to_chat(H, "<span class='notice'>You modify the appearance of [target].</span>")
used |= USED_MOD_SUIT
var/obj/item/clothing/suit/space/hardsuit/security/P = target
P.name = "winterised security hardsuit"
P.desc = "A rare winterised variant of the security hardsuit, used on colder mining worlds for securiry patrols, this one has 'Haliber' written on an ID patch located on the right side of the chest."
P.icon = 'icons/obj/custom_items.dmi'
P.icon_state = "hardsuit-secf"
P.item_state = "hardsuit-secf"
P.sprite_sheets = null
user.update_icons()
if(P == H.wear_suit)
H.update_inv_wear_suit()
return
to_chat(user, "<span class='warning'>You can't modify [target]!</span>")
//////////////////////////////////
//////////// Clothing ////////////
//////////////////////////////////
@@ -945,6 +1000,14 @@
flags_inv = HIDEEARS
//////////// Uniforms ////////////
/obj/item/clothing/under/fluff/benjaminfallout // Benjaminfallout: Pretzel Brassheart
icon = 'icons/obj/custom_items.dmi'
name = "Pretzel's dress"
desc = "A nice looking dress"
icon_state = "fallout_dress"
item_state = "fallout_dress"
item_color = "fallout_dress"
/obj/item/clothing/under/fluff/soviet_casual_uniform // Norstead : Natalya Sokolova
icon = 'icons/obj/custom_items.dmi'
name = "Soviet Casual Uniform"
@@ -1043,6 +1106,15 @@
item_color = "aegisuniform"
displays_id = 0
/obj/item/clothing/under/fluff/elo_turtleneck // vforcebomber: E.L.O.
name = "E.L.O's Turtleneck"
desc = "This TurtleNeck belongs to the IPC E.L.O. And has her name sown into the upper left breast, a very wooly jumper."
icon = 'icons/obj/custom_items.dmi' // for the floor sprite
icon_override = 'icons/obj/custom_items.dmi' // for the mob sprite
icon_state = "eloturtleneckfloor"
item_color = "eloturtleneck"
displays_id = FALSE
//////////// Masks ////////////
/obj/item/clothing/mask/bandana/fluff/dar //sasanek12: Dar'Konr
@@ -1135,6 +1207,15 @@
flags = BLOCKHAIR
flags_inv = HIDEFACE
/obj/item/clothing/shoes/fluff/arachno_boots
name = "Arachno-Man boots"
desc = "These boots were made for crawlin'"
icon = 'icons/obj/custom_items.dmi'
icon_state = "superior_boots"
item_state = "superior_boots"
/obj/item/nullrod/fluff/chronx //chronx100: Hughe O'Splash
fluff_transformations = list(/obj/item/nullrod/fluff/chronx/scythe)
@@ -1219,6 +1300,13 @@
species_fit = null
sprite_sheets = null
/obj/item/storage/backpack/fluff/syndiesatchel //SkeletalElite: Rawkkihiki
name= "Military Satchel"
desc = "A well made satchel for military operations. Totally not made by an enemy corporation"
icon = 'icons/obj/custom_items.dmi'
icon_state = "rawk_satchel"
sprite_sheets = null
/obj/item/storage/backpack/fluff/krich_back //lizardzsi: Krichahka
name = "Voxcaster"
desc = "Battered, Sol-made military radio backpack that had its speakers fried from playing Vox opera. The words 'Swift-Talon' are crudely scratched onto its side."
@@ -1387,3 +1475,12 @@
item_state = "panzermedal"
item_color = "panzermedal"
slot_flags = SLOT_TIE
/obj/item/clothing/accessory/medal/fluff/XannZxiax //Sagrotter: Xann Zxiax
name = "Zxiax Garnet"
desc = "Green Garnet on fancy blue cord, when you look at the Garnet, you feel strangely appeased."
icon = 'icons/obj/custom_items.dmi'
icon_state = "Xann_necklace"
item_state = "Xann_necklace"
item_color = "Xann_necklace"
slot_flags = SLOT_TIE
+1 -1
View File
@@ -80,7 +80,7 @@
if(ismob(loc))
var/mob/M = loc
M.put_in_hands(P)
to_chat(M, "<span class='notice'>Report printed. Log cleared.<span>")
to_chat(M, "<span class='notice'>Report printed. Log cleared.</span>")
// Clear the logs
log = list()
+4 -32
View File
@@ -19,7 +19,7 @@ log transactions
icon = 'icons/obj/terminals.dmi'
icon_state = "atm"
anchored = 1
use_power = 1
use_power = IDLE_POWER_USE
idle_power_usage = 10
var/obj/machinery/computer/account_database/linked_db
var/datum/money_account/authenticated_account
@@ -97,18 +97,9 @@ log transactions
if(!powered())
return
var/obj/item/stack/spacecash/C = I
authenticated_account.money += C.amount
playsound(loc, pick('sound/items/polaroid1.ogg', 'sound/items/polaroid2.ogg'), 50, 1)
//create a transaction log entry
var/datum/transaction/T = new()
T.target_name = authenticated_account.owner_name
T.purpose = "Credit deposit"
T.amount = C.amount
T.source_terminal = machine_id
T.date = current_date_string
T.time = station_time_timestamp()
authenticated_account.transaction_log.Add(T)
authenticated_account.credit(C.amount, "Credit deposit", machine_id, authenticated_account.owner_name)
to_chat(user, "<span class='info'>You insert [C] into [src].</span>")
SSnanoui.update_uis(src)
@@ -175,19 +166,8 @@ log transactions
else if(transfer_amount <= authenticated_account.money)
var/target_account_number = text2num(href_list["target_acc_number"])
var/transfer_purpose = href_list["purpose"]
if(linked_db.charge_to_account(target_account_number, authenticated_account.owner_name, transfer_purpose, machine_id, transfer_amount))
if(linked_db.charge_to_account(target_account_number, authenticated_account, transfer_purpose, machine_id, transfer_amount))
to_chat(usr, "[bicon(src)]<span class='info'>Funds transfer successful.</span>")
authenticated_account.money -= transfer_amount
//create an entry in the account transaction log
var/datum/transaction/T = new()
T.target_name = "Account #[target_account_number]"
T.purpose = transfer_purpose
T.source_terminal = machine_id
T.date = current_date_string
T.time = station_time_timestamp()
T.amount = "([transfer_amount])"
authenticated_account.transaction_log.Add(T)
else
to_chat(usr, "[bicon(src)]<span class='warning'>Funds transfer failed.</span>")
@@ -263,15 +243,7 @@ log transactions
authenticated_account.money -= amount
withdraw_arbitrary_sum(amount)
//create an entry in the account transaction log
var/datum/transaction/T = new()
T.target_name = authenticated_account.owner_name
T.purpose = "Credit withdrawal"
T.amount = "([amount])"
T.source_terminal = machine_id
T.date = current_date_string
T.time = station_time_timestamp()
authenticated_account.transaction_log.Add(T)
authenticated_account.charge(amount, null, "Credit withdrawal", machine_id, authenticated_account.owner_name)
else
to_chat(usr, "[bicon(src)]<span class='warning'>You don't have enough funds to do that!</span>")
if("balance_statement")
+23 -233
View File
@@ -1,4 +1,9 @@
var/global/current_date_string
#define STATION_CREATION_DATE "2 April, 2555"
#define STATION_CREATION_TIME "11:24:30"
#define STATION_START_CASH 75000
#define STATION_SOURCE_TERMINAL "Biesel GalaxyNet Terminal #227"
#define DEPARTMENT_START_CASH 5000
var/global/num_financial_terminals = 1
var/global/datum/money_account/station_account
var/global/list/datum/money_account/department_accounts = list()
@@ -15,19 +20,13 @@ var/global/list/all_money_accounts = list()
station_account.owner_name = "[station_name()] Station Account"
station_account.account_number = rand(111111, 999999)
station_account.remote_access_pin = rand(1111, 111111)
station_account.money = 75000
station_account.money = STATION_START_CASH
//create an entry in the account transaction log for when it was created
var/datum/transaction/T = new()
T.target_name = station_account.owner_name
T.purpose = "Account creation"
T.amount = 75000
T.date = "2nd April, 2555"
T.time = "11:24"
T.source_terminal = "Biesel GalaxyNet Terminal #277"
station_account.makeTransactionLog(STATION_START_CASH, "Account Creation", STATION_SOURCE_TERMINAL, station_account.owner_name, FALSE,
STATION_CREATION_DATE, STATION_CREATION_TIME)
//add the account
station_account.transaction_log.Add(T)
all_money_accounts.Add(station_account)
/proc/create_department_account(department)
@@ -37,19 +36,13 @@ var/global/list/all_money_accounts = list()
department_account.owner_name = "[department] Account"
department_account.account_number = rand(111111, 999999)
department_account.remote_access_pin = rand(1111, 111111)
department_account.money = 5000
department_account.money = DEPARTMENT_START_CASH
//create an entry in the account transaction log for when it was created
var/datum/transaction/T = new()
T.target_name = department_account.owner_name
T.purpose = "Account creation"
T.amount = department_account.money
T.date = "2nd April, 2555"
T.time = "11:24"
T.source_terminal = "Biesel GalaxyNet Terminal #277"
department_account.makeTransactionLog(DEPARTMENT_START_CASH, "Account Creation", STATION_SOURCE_TERMINAL, department_account.owner_name, FALSE,
STATION_CREATION_DATE, STATION_CREATION_TIME)
//add the account
department_account.transaction_log.Add(T)
all_money_accounts.Add(department_account)
department_accounts[department] = department_account
@@ -73,7 +66,7 @@ var/global/list/all_money_accounts = list()
if(!source_db)
//set a random date, time and location some time over the past few decades
T.date = "[num2text(rand(1,31))] [pick(month_names)], [rand(game_year - 20,game_year - 1)]"
T.time = "[rand(0,23)]:[rand(0,59)]"
T.time = "[rand(0,23)]:[rand(0,59)]:[rand(0,59)]"
T.source_terminal = "NTGalaxyNet Terminal #[rand(111,1111)]"
M.account_number = rand(111111, 999999)
@@ -104,7 +97,7 @@ var/global/list/all_money_accounts = list()
<i>Date and time:</i> [station_time_timestamp()], [current_date_string]<br><br>
<i>Creation terminal ID:</i> [source_db.machine_id]<br>
<i>Authorised NT officer overseeing creation:</i> [overseer]<br>"}
// END AUTOFIX
//stamp the paper
var/image/stampoverlay = image('icons/obj/bureaucracy.dmi')
stampoverlay.icon_state = "paper_stamp-cent"
@@ -133,7 +126,6 @@ var/global/list/all_money_accounts = list()
/datum/money_account/New()
..()
//security_level = pick (0,1) //Stealing is now slightly viable
/datum/transaction
var/target_name = ""
@@ -142,222 +134,14 @@ var/global/list/all_money_accounts = list()
var/date = ""
var/time = ""
var/source_terminal = ""
/*
/obj/machinery/account_database
name = "Accounts database"
desc = "Holds transaction logs, account data and all kinds of other financial records."
icon = 'icons/obj/virology.dmi'
icon_state = "analyser"
density = 1
req_one_access = list(access_hop, access_captain)
var/receipt_num
var/machine_id = ""
var/obj/item/card/id/held_card
var/access_level = 0
var/datum/money_account/detailed_account_view
var/creating_new_account = 0
var/activated = 1
/obj/machinery/account_database/New()
..()
if(!station_account)
create_station_account()
if(department_accounts.len == 0)
for(var/department in station_departments)
create_department_account(department)
if(!vendor_account)
create_department_account("Vendor")
vendor_account = department_accounts["Vendor"]
if(!current_date_string)
current_date_string = "[num2text(rand(1,31))] [pick("January","February","March","April","May","June","July","August","September","October","November","December")], 2557"
machine_id = "[station_name()] Acc. DB #[num_financial_terminals++]"
/obj/machinery/account_database/attack_hand(mob/user as mob)
if(ishuman(user) && !user.stat && get_dist(src,user) <= 1)
var/dat = "<b>Accounts Database</b><br>"
// AUTOFIXED BY fix_string_idiocy.py
// C:\Users\Rob\Documents\Projects\vgstation13\code\WorkInProgress\Cael_Aislinn\Economy\Accounts.dm:171: dat += "<i>[machine_id]</i><br>"
dat += {"<i>[machine_id]</i><br>
Confirm identity: <a href='?src=[UID()];choice=insert_card'>[held_card ? held_card : "-----"]</a><br>"}
// END AUTOFIX
if(access_level > 0)
// AUTOFIXED BY fix_string_idiocy.py
// C:\Users\Rob\Documents\Projects\vgstation13\code\WorkInProgress\Cael_Aislinn\Economy\Accounts.dm:175: dat += "<a href='?src=[UID()];toggle_activated=1'>[activated ? "Disable" : "Enable"] remote access</a><br>"
dat += {"<a href='?src=[UID()];toggle_activated=1'>[activated ? "Disable" : "Enable"] remote access</a><br>
You may not edit accounts at this terminal, only create and view them.<br>"}
// END AUTOFIX
if(creating_new_account)
// AUTOFIXED BY fix_string_idiocy.py
// C:\Users\Rob\Documents\Projects\vgstation13\code\WorkInProgress\Cael_Aislinn\Economy\Accounts.dm:178: dat += "<br>"
dat += {"<br>
<a href='?src=[UID()];choice=view_accounts_list;'>Return to accounts list</a>
<form name='create_account' action='?src=[UID()]' method='get'>
<input type='hidden' name='src' value='[UID()]'>
<input type='hidden' name='choice' value='finalise_create_account'>
<b>Holder name:</b> <input type='text' id='holder_name' name='holder_name' style='width:250px; background-color:white;'><br>
<b>Initial funds:</b> <input type='text' id='starting_funds' name='starting_funds' style='width:250px; background-color:white;'> (subtracted from station account)<br>
<i>New accounts are automatically assigned a secret number and pin, which are printed separately in a sealed package.</i><br>
<input type='submit' value='Create'><br>
</form>"}
// END AUTOFIX
else
if(detailed_account_view)
// AUTOFIXED BY fix_string_idiocy.py
// C:\Users\Rob\Documents\Projects\vgstation13\code\WorkInProgress\Cael_Aislinn\Economy\Accounts.dm:190: dat += "<br>"
dat += {"<br>
<a href='?src=[UID()];choice=view_accounts_list;'>Return to accounts list</a><hr>
<b>Account number:</b> #[detailed_account_view.account_number]<br>
<b>Account holder:</b> [detailed_account_view.owner_name]<br>
<b>Account balance:</b> $[detailed_account_view.money]<br>
<table border=1 style='width:100%'>
<tr>
<td><b>Date</b></td>
<td><b>Time</b></td>
<td><b>Target</b></td>
<td><b>Purpose</b></td>
<td><b>Value</b></td>
<td><b>Source terminal ID</b></td>
</tr>"}
// END AUTOFIX
for(var/datum/transaction/T in detailed_account_view.transaction_log)
// AUTOFIXED BY fix_string_idiocy.py
// C:\Users\Rob\Documents\Projects\vgstation13\code\WorkInProgress\Cael_Aislinn\Economy\Accounts.dm:205: dat += "<tr>"
dat += {"<tr>
<td>[T.date]</td>
<td>[T.time]</td>
<td>[T.target_name]</td>
<td>[T.purpose]</td>
<td>$[T.amount]</td>
<td>[T.source_terminal]</td>
</tr>"}
// END AUTOFIX
dat += "</table>"
else
// AUTOFIXED BY fix_string_idiocy.py
// C:\Users\Rob\Documents\Projects\vgstation13\code\WorkInProgress\Cael_Aislinn\Economy\Accounts.dm:215: dat += "<a href='?src=[UID()];choice=create_account;'>Create new account</a><br><br>"
dat += {"<a href='?src=[UID()];choice=create_account;'>Create new account</a><br><br>
<table border=1 style='width:100%'>"}
// END AUTOFIX
for(var/i=1, i<=all_money_accounts.len, i++)
var/datum/money_account/D = all_money_accounts[i]
// AUTOFIXED BY fix_string_idiocy.py
// C:\Users\Rob\Documents\Projects\vgstation13\code\WorkInProgress\Cael_Aislinn\Economy\Accounts.dm:219: dat += "<tr>"
dat += {"<tr>
<td>#[D.account_number]</td>
<td>[D.owner_name]</td>
<td><a href='?src=[UID()];choice=view_account_detail;account_index=[i]'>View in detail</a></td>
</tr>"}
// END AUTOFIX
dat += "</table>"
user << browse(dat,"window=account_db;size=700x650")
else
user << browse(null,"window=account_db")
/obj/machinery/account_database/attackby(O as obj, user as mob)//TODO:SANITY
if(istype(O, /obj/item/card))
var/obj/item/card/id/idcard = O
if(!held_card)
usr.drop_item()
idcard.loc = src
held_card = idcard
if(access_cent_captain in idcard.access)
access_level = 2
else if(access_hop in idcard.access || access_captain in idcard.access)
access_level = 1
else
..()
/obj/machinery/account_database/Topic(var/href, var/href_list)
..()
if(href_list["toggle_activated"])
activated = !activated
if(href_list["choice"])
switch(href_list["choice"])
if("create_account")
creating_new_account = 1
if("finalise_create_account")
var/account_name = href_list["holder_name"]
var/starting_funds = max(text2num(href_list["starting_funds"]), 0)
create_account(account_name, starting_funds, src)
if(starting_funds > 0)
//subtract the money
station_account.money -= starting_funds
//create a transaction log entry
var/datum/transaction/T = new()
T.target_name = account_name
T.purpose = "New account funds initialisation"
T.amount = "([starting_funds])"
T.date = current_date_string
T.time = station_time_timestamp()
T.source_terminal = machine_id
station_account.transaction_log.Add(T)
creating_new_account = 0
if("insert_card")
if(held_card)
held_card.loc = src.loc
if(ishuman(usr) && !usr.get_active_hand())
usr.put_in_hands(held_card)
held_card = null
access_level = 0
else
var/obj/item/I = usr.get_active_hand()
if(istype(I, /obj/item/card/id))
var/obj/item/card/id/C = I
usr.drop_item()
C.loc = src
held_card = C
if(access_cent_captain in C.access)
access_level = 2
else if(access_hop in C.access || access_captain in C.access)
access_level = 1
if("view_account_detail")
var/index = text2num(href_list["account_index"])
if(index && index <= all_money_accounts.len)
detailed_account_view = all_money_accounts[index]
if("view_accounts_list")
detailed_account_view = null
creating_new_account = 0
src.attack_hand(usr)
*/
/obj/machinery/computer/account_database/proc/charge_to_account(var/attempt_account_number, var/source_name, var/purpose, var/terminal_id, var/amount)
/obj/machinery/computer/account_database/proc/charge_to_account(attempt_account_number, datum/money_account/source, purpose, terminal_id, amount)
if(!activated)
return 0
for(var/datum/money_account/D in all_money_accounts)
if(D.account_number == attempt_account_number && !D.suspended)
D.money += amount
//create a transaction log entry
var/datum/transaction/T = new()
T.target_name = source_name
T.purpose = purpose
if(amount < 0)
T.amount = "([amount])"
else
T.amount = "[amount]"
T.date = current_date_string
T.time = station_time_timestamp()
T.source_terminal = terminal_id
D.transaction_log.Add(T)
source.charge(amount, D, purpose, terminal_id, "Account #[D.account_number]", "Transfer from [source.owner_name]",
"[D.owner_name]")
return 1
return 0
@@ -378,3 +162,9 @@ var/global/list/all_money_accounts = list()
for(var/datum/money_account/D in all_money_accounts)
if(D.account_number == attempt_account_number)
return D
#undef STATION_CREATION_DATE
#undef STATION_CREATION_TIME
#undef STATION_START_CASH
#undef STATION_SOURCE_TERMINAL
#undef DEPARTMENT_START_CASH
+23 -59
View File
@@ -1,3 +1,4 @@
var/global/current_date_string
/obj/machinery/computer/account_database
name = "Accounts Uplink Terminal"
@@ -15,34 +16,6 @@
light_color = LIGHT_COLOR_GREEN
/obj/machinery/computer/account_database/proc/get_access_level(var/mob/user)
if(user.can_admin_interact())
return 2
if(!held_card)
return 0
if(access_cent_commander in held_card.access)
return 2
else if(access_hop in held_card.access || access_captain in held_card.access)
return 1
/obj/machinery/computer/account_database/proc/create_transation(target, reason, amount)
var/datum/transaction/T = new()
T.target_name = target
T.purpose = reason
T.amount = amount
T.date = current_date_string
T.time = station_time_timestamp()
T.source_terminal = machine_id
return T
/obj/machinery/computer/account_database/proc/accounting_letterhead(report_name)
return {"
<center><h1><b>[report_name]</b></h1></center>
<center><small><i>[station_name()] Accounting Report</i></small></center>
<hr>
<u>Generated By:</u> [held_card.registered_name], [held_card.assignment]<br>
"}
/obj/machinery/computer/account_database/New()
if(!station_account)
create_station_account()
@@ -55,11 +28,29 @@
vendor_account = department_accounts["Vendor"]
if(!current_date_string)
current_date_string = "[time2text(world.timeofday, "DD MM")], [game_year]"
current_date_string = "[time2text(world.timeofday, "DD Month")], [game_year]"
machine_id = "[station_name()] Acc. DB #[num_financial_terminals++]"
..()
/obj/machinery/computer/account_database/proc/get_access_level(var/mob/user)
if(user.can_admin_interact())
return 2
if(!held_card)
return 0
if(access_cent_commander in held_card.access)
return 2
else if(access_hop in held_card.access || access_captain in held_card.access)
return 1
/obj/machinery/computer/account_database/proc/accounting_letterhead(report_name)
return {"
<center><h1><b>[report_name]</b></h1></center>
<center><small><i>[station_name()] Accounting Report</i></small></center>
<hr>
<u>Generated By:</u> [held_card.registered_name], [held_card.assignment]<br>
"}
/obj/machinery/computer/account_database/attackby(obj/O, mob/user, params)
if(!istype(O, /obj/item/card/id))
return ..()
@@ -160,16 +151,6 @@
if("create_account")
creating_new_account = 1
if("add_funds")
var/amount = input("Enter the amount you wish to add", "Silently add funds") as num
if(detailed_account_view)
detailed_account_view.money += amount
if("remove_funds")
var/amount = input("Enter the amount you wish to remove", "Silently remove funds") as num
if(detailed_account_view)
detailed_account_view.money -= amount
if("toggle_suspension")
if(detailed_account_view)
detailed_account_view.suspended = !detailed_account_view.suspended
@@ -182,14 +163,10 @@
starting_funds = Clamp(starting_funds, 0, station_account.money) // Not authorized to put the station in debt.
starting_funds = min(starting_funds, fund_cap) // Not authorized to give more than the fund cap.
create_account(account_name, starting_funds, src)
var/datum/money_account/M = create_account(account_name, starting_funds, src)
if(starting_funds > 0)
//subtract the money
station_account.money -= starting_funds
//create a transaction log entry
var/trx = create_transation(account_name, "New account activation", "([starting_funds])")
station_account.transaction_log.Add(trx)
station_account.charge(starting_funds, null, "New account activation",
"", "New account activation", M.owner_name)
creating_new_account = 0
ui.close()
@@ -205,19 +182,6 @@
detailed_account_view = null
creating_new_account = 0
if("revoke_payroll")
var/funds = detailed_account_view.money
var/account_trx = create_transation(station_account.owner_name, "Revoke payroll", "([funds])")
var/station_trx = create_transation(detailed_account_view.owner_name, "Revoke payroll", funds)
station_account.money += funds
detailed_account_view.money = 0
detailed_account_view.transaction_log.Add(account_trx)
station_account.transaction_log.Add(station_trx)
callHook("revoke_payroll", list(detailed_account_view))
if("print")
var/text
playsound(loc, 'sound/goonstation/machines/printer_thermal.ogg', 50, 1)
+31 -60
View File
@@ -3,8 +3,7 @@
desc = "Swipe your ID card to make purchases electronically."
icon = 'icons/obj/device.dmi'
icon_state = "eftpos"
var/machine_id = ""
var/eftpos_name = "Default EFTPOS scanner"
var/machine_name = ""
var/transaction_locked = 0
var/transaction_paid = 0
var/transaction_amount = 0
@@ -15,7 +14,7 @@
/obj/item/eftpos/New()
..()
machine_id = "[station_name()] EFTPOS #[num_financial_terminals++]"
machine_name = "[station_name()] EFTPOS #[num_financial_terminals++]"
access_code = rand(1111,111111)
reconnect_database()
spawn(0)
@@ -28,14 +27,10 @@
/obj/item/eftpos/proc/print_reference()
playsound(loc, 'sound/goonstation/machines/printer_thermal.ogg', 50, 1)
var/obj/item/paper/R = new(loc)
R.name = "Reference: [eftpos_name]"
// AUTOFIXED BY fix_string_idiocy.py
// C:\Users\Rob\Documents\Projects\vgstation13\code\WorkInProgress\Cael_Aislinn\Economy\EFTPOS.dm:31: R.info = "<b>[eftpos_name] reference</b><br><br>"
R.info = {"<b>[eftpos_name] reference</b><br><br>
R.name = "Reference: [machine_name]"
R.info = {"<b>[machine_name] reference</b><br><br>
Access code: [access_code]<br><br>
<b>Do not lose or misplace this code.</b><br>"}
// END AUTOFIX
//stamp the paper
var/image/stampoverlay = image('icons/obj/bureaucracy.dmi')
stampoverlay.icon_state = "paper_stamp-cent"
@@ -86,8 +81,7 @@
/obj/item/eftpos/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state)
var/data[0]
data["eftpos_name"] = eftpos_name
data["machine_id"] = machine_id
data["machine_name"] = machine_name
data["transaction_locked"] = transaction_locked
data["transaction_paid"] = transaction_paid
data["transaction_purpose"] = transaction_purpose
@@ -112,15 +106,6 @@
print_reference()
else
to_chat(usr, "[bicon(src)]<span class='warning'>Incorrect code entered.</span>")
if("change_id")
var/attempt_code = text2num(input("Re-enter the current EFTPOS access code", "Confirm EFTPOS code"))
if(attempt_code == access_code)
var/name = input("Enter a new terminal ID for this device", "Enter new EFTPOS ID") as text|null
if(name)
eftpos_name = "[name] EFTPOS scanner"
print_reference()
else
to_chat(usr, "[bicon(src)]<span class='warning'>Incorrect code entered.</span>")
if("link_account")
if(!linked_db)
reconnect_database()
@@ -179,48 +164,34 @@
if(istype(I, /obj/item/card/id))
var/obj/item/card/id/C = I
visible_message("<span class='info'>[user] swipes a card through [src].</span>")
if(transaction_locked && !transaction_paid)
if(linked_account)
var/attempt_pin = input("Enter pin code", "EFTPOS transaction") as num
var/datum/money_account/D = attempt_account_access(C.associated_account_number, attempt_pin, 2)
if(D)
if(transaction_amount <= D.money)
playsound(src, 'sound/machines/chime.ogg', 50, 1)
visible_message("[bicon(src)] The [src] chimes.")
transaction_paid = 1
//transfer the money
D.money -= transaction_amount
linked_account.money += transaction_amount
if(!transaction_locked || transaction_paid)
return
if(!linked_account)
to_chat(user, "[bicon(src)]<span class='warning'>EFTPOS is not connected to an account.</span>")
return
var/confirm = alert("Are you sure you want to pay $[transaction_amount] to Account: [linked_account.owner_name] ", "Confirm transaction", "Yes", "No")
if(confirm == "No")
return
var/attempt_pin = input("Enter pin code", "EFTPOS transaction") as num
var/datum/money_account/D = attempt_account_access(C.associated_account_number, attempt_pin, 2)
if(!D)
to_chat(user, "[bicon(src)]<span class='warning'>Unable to access account. Check security settings and try again.</span>")
if(transaction_amount > D.money)
to_chat(user, "[bicon(src)]<span class='warning'>You don't have that much money!</span>")
return
var/transSuccess = D.charge(transaction_amount, linked_account, transaction_purpose, machine_name, D.owner_name)
if(transSuccess == TRUE)
playsound(src, 'sound/machines/chime.ogg', 50, 1)
visible_message("[bicon(src)] The [src] chimes.")
transaction_paid = 1
//create entries in the two account transaction logs
var/datum/transaction/T = new()
T.target_name = "[linked_account.owner_name] (via [eftpos_name])"
T.purpose = transaction_purpose
if(transaction_amount > 0)
T.amount = "([transaction_amount])"
else
T.amount = "[transaction_amount]"
T.source_terminal = machine_id
T.date = current_date_string
T.time = station_time_timestamp()
D.transaction_log.Add(T)
//
T = new()
T.target_name = D.owner_name
T.purpose = transaction_purpose
T.amount = "[transaction_amount]"
T.source_terminal = machine_id
T.date = current_date_string
T.time = station_time_timestamp()
linked_account.transaction_log.Add(T)
else
to_chat(user, "[bicon(src)]<span class='warning'>You don't have that much money!</span>")
else
to_chat(user, "[bicon(src)]<span class='warning'>Unable to access account. Check security settings and try again.</span>")
else
to_chat(user, "[bicon(src)]<span class='warning'>EFTPOS is not connected to an account.</span>")
else
..()
//emag?
//emag?
+56 -34
View File
@@ -46,47 +46,69 @@
/datum/money_account/proc/fmtBalance()
return "$[num2septext(money)]"
/datum/money_account/proc/charge(var/transaction_amount,var/datum/money_account/dest,var/transaction_purpose, var/terminal_name="", var/terminal_id=0, var/dest_name = "UNKNOWN")
// Seperated from charge so they can reuse the code and also because there's many instances where a log will be made without actually making a transaction
/datum/money_account/proc/makeTransactionLog(transaction_amount = 0, transaction_purpose, terminal_name = "",
dest_name = "UNKNOWN", charging = TRUE, date = current_date_string, time = "")
var/datum/transaction/T = new()
T.target_name = dest_name
T.purpose = transaction_purpose
if(!charging || transaction_amount == 0)
T.amount = "[transaction_amount]"
else
T.amount = "([transaction_amount])"
T.source_terminal = terminal_name
T.date = date
if(time == "")
T.time = station_time_timestamp()
else
T.time = time
transaction_log.Add(T)
// Charge is for transferring money from an account to another. The destination account can possibly not exist (Magical money sink)
/datum/money_account/proc/charge(transaction_amount = 0, datum/money_account/dest, transaction_purpose,
terminal_name = "", dest_name = "UNKNOWN", dest_purpose, dest_target_name)
if(suspended)
to_chat(usr, "<span class='warning'>Unable to access source account: account suspended.</span>")
return 0
if(transaction_amount <= money)
//transfer the money
money -= transaction_amount
makeTransactionLog(transaction_amount, transaction_purpose, terminal_name, dest_name)
if(dest)
dest.money += transaction_amount
dest.makeTransactionLog(transaction_amount,
dest_purpose ? dest_purpose : transaction_purpose, terminal_name, dest_target_name ? dest_target_name : dest_name, FALSE)
return 1
else
to_chat(usr, "<span class='warning'>Insufficient funds in account.</span>")
return 0
// phantom_charge is for when you want to charge an account, without making any corresponding log (e.g. you make it yourself with custom date
// or there won't be any log for some IC reasons (hacking)
/datum/money_account/proc/phantom_charge(transaction_amount = 0, datum/money_account/dest, suspensionbypass = 0)
if(suspended && !suspensionbypass)
return 0
if(transaction_amount <= money)
//transfer the money
money -= transaction_amount
if(dest)
dest.money += transaction_amount
//create entries in the two account transaction logs
var/datum/transaction/T
if(dest)
T = new()
T.target_name = owner_name
if(terminal_name!="")
T.target_name += " (via [terminal_name])"
T.purpose = transaction_purpose
if(transaction_amount > 0)
T.amount = "([transaction_amount])"
else
T.amount = "[transaction_amount]"
if(terminal_id)
T.source_terminal = terminal_id
T.date = current_date_string
T.time = station_time_timestamp()
dest.transaction_log.Add(T)
//
T = new()
T.target_name = (!dest) ? dest_name : dest.owner_name
if(terminal_name!="")
T.target_name += " (via [terminal_name])"
T.purpose = transaction_purpose
T.amount = "[transaction_amount]"
if(terminal_id)
T.source_terminal = terminal_id
T.date = current_date_string
T.time = station_time_timestamp()
transaction_log.Add(T)
return 1
else
to_chat(usr, "<span class='warning'>Insufficient funds in account.</span>")
return 0
return 0
// Credit is for giving money to an account out of thin air. Suspension does not matter.
/datum/money_account/proc/credit(transaction_amount = 0, transaction_purpose,
terminal_name = "", dest_name = "UNKNOWN", date = current_date_string, time = "")
money += transaction_amount
makeTransactionLog(transaction_amount, transaction_purpose, terminal_name, dest_name, FALSE, date, time)
return 1
//phantom_credit is like the above without any log
/datum/money_account/proc/phantom_credit(transaction_amount = 0)
money += transaction_amount
return 1
+15 -17
View File
@@ -1,7 +1,6 @@
/datum/event/blob
announceWhen = 60
endWhen = 120
var/obj/structure/blob/core/Blob
announceWhen = 120
endWhen = 180
/datum/event/blob/announce()
event_announcement.Announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/AI/outbreak5.ogg')
@@ -11,18 +10,17 @@
if(!T)
return kill()
var/list/candidates = pollCandidates("Do you want to play as a blob?", ROLE_BLOB, 1)
var/mob/C
if(candidates.len)
C = pick(candidates)
Blob = new /obj/structure/blob/core(T, new_overmind=C.client)
for(var/i in 1 to 5)
Blob.process()
else
if(!candidates.len)
return kill()
/datum/event/blob/tick()
if(!Blob)
kill()
return
if(IsMultiple(activeFor, 3))
Blob.process()
var/list/vents = list()
for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in all_vent_pumps)
if(is_station_level(temp_vent.loc.z) && !temp_vent.welded)
if(temp_vent.parent.other_atmosmch.len > 50)
vents += temp_vent
var/obj/vent = pick(vents)
var/mob/living/simple_animal/mouse/blobinfected/B = new(vent.loc)
var/mob/M = pick(candidates)
B.key = M.key
to_chat(B, "<span class='userdanger'>You are now a mouse, infected with blob spores. Find somewhere isolated... before you burst and become the blob! Use ventcrawl (alt-click on vents) to move around.</span>")
var/image/alert_overlay = image('icons/mob/blob.dmi', "blank_blob")
notify_ghosts("Infected Mouse has appeared in [get_area(B)].", source = B, alert_overlay = alert_overlay)
+8 -8
View File
@@ -17,12 +17,12 @@
if(announce)
event_announcement.Announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Critical Power Failure", new_sound = 'sound/AI/poweroff.ogg')
var/list/skipped_areas = list(/area/turret_protected/ai, /area/syndicate_depot)
var/list/skipped_areas_apc = list(/area/engine/engineering, /area/syndicate_depot)
var/list/skipped_areas = list(/area/turret_protected/ai)
var/list/skipped_areas_apc = list(/area/engine/engineering)
for(var/obj/machinery/power/smes/S in machines)
var/area/current_area = get_area(S)
if(current_area.type in skipped_areas || !is_station_level(S.z))
if((current_area.type in skipped_areas) || !is_station_level(S.z))
continue
S.last_charge = S.charge
S.last_output_attempt = S.output_attempt
@@ -35,26 +35,26 @@
for(var/obj/machinery/power/apc/C in apcs)
var/area/current_area = get_area(C)
if(current_area.type in skipped_areas_apc || !is_station_level(C.z))
if((current_area.type in skipped_areas_apc) || !is_station_level(C.z))
continue
if(C.cell)
C.cell.charge = 0
/proc/power_restore(var/announce = 1)
var/list/skipped_areas = list(/area/turret_protected/ai, /area/syndicate_depot)
var/list/skipped_areas_apc = list(/area/engine/engineering, /area/syndicate_depot)
var/list/skipped_areas = list(/area/turret_protected/ai)
var/list/skipped_areas_apc = list(/area/engine/engineering)
if(announce)
event_announcement.Announce("Power has been restored to [station_name()]. We apologize for the inconvenience.", "Power Systems Nominal", new_sound = 'sound/AI/poweron.ogg')
for(var/obj/machinery/power/apc/C in apcs)
var/area/current_area = get_area(C)
if(current_area.type in skipped_areas_apc || !is_station_level(C.z))
if((current_area.type in skipped_areas_apc) || !is_station_level(C.z))
continue
if(C.cell)
C.cell.charge = C.cell.maxcharge
for(var/obj/machinery/power/smes/S in machines)
var/area/current_area = get_area(S)
if(current_area.type in skipped_areas || !is_station_level(S.z))
if((current_area.type in skipped_areas) || !is_station_level(S.z))
continue
S.charge = S.last_charge
S.output_attempt = S.last_output_attempt
+21 -15
View File
@@ -1,3 +1,6 @@
#define MINIMUM_PERCENTAGE_LOSS 0.5
#define VARIABLE_LOSS 2 // Invariant: 1 - VARIABLE_LOSS/10 >= MINIMUM_PERCENTAGE_LOSS
/var/global/account_hack_attempted = 0
/datum/event/money_hacker
@@ -16,7 +19,7 @@
/datum/event/money_hacker/announce()
var/message = "A brute force hack has been detected (in progress since [station_time_timestamp()]). The target of the attack is: Financial account #[affected_account.account_number], \
without intervention this attack will succeed in approximately 10 minutes. Required intervention: temporary suspension of affected accounts until the attack has ceased. \
without intervention this attack will succeed in approximately 10 minutes. Required intervention: temporary suspension of affected account until the attack has ceased. \
Notifications will be sent as updates occur.<br>"
var/my_department = "[station_name()] firewall subroutines"
@@ -32,35 +35,38 @@
/datum/event/money_hacker/end()
var/message
if(affected_account && !affected_account)
//hacker wins
if(!isnull(affected_account) && !affected_account.suspended)
message = "The hack attempt has succeeded."
//subtract the money
var/lost = affected_account.money * 0.8 + (rand(2,4) - 2) / 10
affected_account.money -= lost
var/lost = affected_account.money * (MINIMUM_PERCENTAGE_LOSS + rand(0,VARIABLE_LOSS) / 10);
affected_account.phantom_charge(lost)
//create a taunting log entry
var/datum/transaction/T = new()
T.target_name = pick("","yo brotha from anotha motha","el Presidente","chieF smackDowN")
T.purpose = pick("Ne$ ---ount fu%ds init*&lisat@*n","PAY BACK YOUR MUM","Funds withdrawal","pWnAgE","l33t hax","liberationez")
T.amount = pick("","([rand(0,99999)])","alla money","9001$","HOLLA HOLLA GET DOLLA","([lost])")
var/dest_name = pick("","yo brotha from anotha motha","el Presidente","chieF smackDowN")
var/amount = pick("","([rand(0,99999)])","alla money","9001$","HOLLA HOLLA GET DOLLA","([lost])")
var/purpose = pick("Ne$ ---ount fu%ds init*&lisat@*n","PAY BACK YOUR MUM","Funds withdrawal","pWnAgE","l33t hax","liberationez")
var/date1 = "31 December, 1999"
var/date2 = "[num2text(rand(1,31))] [pick("January","February","March","April","May","June","July","August","September","October","November","December")], [rand(1000,3000)]"
T.date = pick("", current_date_string, date1, date2)
var/date = pick("", current_date_string, date1, date2)
var/time1 = rand(0, 99999999)
var/time2 = "[round(time1 / 36000)+12]:[(time1 / 600 % 60) < 10 ? add_zero(time1 / 600 % 60, 1) : time1 / 600 % 60]"
T.time = pick("", station_time_timestamp(), time2)
T.source_terminal = pick("","[pick("Biesel","New Gibson")] GalaxyNet Terminal #[rand(111,999)]","your mums place","nantrasen high CommanD")
var/time = pick("", station_time_timestamp(), time2)
var/source_terminal = pick("","[pick("Biesel","New Gibson")] GalaxyNet Terminal #[rand(111,999)]","your mums place","nantrasen high CommanD")
affected_account.makeTransactionLog(amount, purpose, source_terminal, dest_name, TRUE, date, time)
affected_account.transaction_log.Add(T)
else
//crew wins
message = "The attack has ceased, the affected accounts can now be brought online."
message = "The attack has ceased, the affected account can now be brought online."
var/my_department = "[station_name()] firewall subroutines"
for(var/obj/machinery/message_server/MS in world)
if(!MS.active) continue
MS.send_rc_message("Head of Personnel's Desk", my_department, message, "", "", 2)
#undef MINIMUM_PERCENTAGE_LOSS
#undef VARIABLE_LOSS
+2 -12
View File
@@ -8,19 +8,9 @@
if(all_money_accounts.len)
var/datum/money_account/D = pick(all_money_accounts)
winner_name = D.owner_name
if(!D.suspended)
D.money += winner_sum
var/datum/transaction/T = new()
T.target_name = "Nyx Daily Grand Slam -Stellar- Lottery"
T.purpose = "Winner!"
T.amount = winner_sum
T.date = current_date_string
T.time = worldtime2text()
T.source_terminal = "Biesel TCD Terminal #[rand(111,333)]"
D.transaction_log.Add(T)
deposit_success = 1
D.credit(winner_sum, "Winner!", "Biesel TCD Terminal #[rand(111,333)]", "Nyx Daily Grand Slam -Stellar- Lottery")
deposit_success = 1
/datum/event/money_lotto/announce()
var/datum/feed_message/newMsg = new /datum/feed_message
+1 -1
View File
@@ -43,7 +43,7 @@
nightmare()
if(ishuman(src))
if(prob(10))
emote("writhes in [p_their()] sleep.")
custom_emote(1,"writhes in [p_their()] sleep.")
dir = pick(cardinal)
/mob/living/carbon/proc/experience_dream(dream_image, isNightmare)
+54 -69
View File
@@ -21,7 +21,7 @@ Gunshots/explosions/opening doors/less rare audio (done)
var/image/halbody
var/obj/halitem
var/hal_screwyhud = SCREWYHUD_NONE
var/handling_hal = 0
var/handling_hal = FALSE
/mob/living/carbon/proc/handle_hallucinations()
if(handling_hal)
@@ -34,9 +34,9 @@ Gunshots/explosions/opening doors/less rare audio (done)
//AAAAHg
var/list/major = list("fake"=20,"death"=10,"xeno"=10,"singulo"=10,"borer"=10,"delusion"=20,"koolaid"=10)
handling_hal = 1
handling_hal = TRUE
while(hallucination > 20)
sleep(rand(200, 500) / (hallucination / 25))
sleep(rand(200, 500) / (hallucination * 0.04))
if(prob(20))
continue
var/list/current = list()
@@ -48,10 +48,8 @@ Gunshots/explosions/opening doors/less rare audio (done)
if(86 to 100)
current = major
var/halpick = pickweight(current)
hallucinate(halpick)
handling_hal = 0
hallucinate(pickweight(current))
handling_hal = FALSE
/obj/effect/hallucination
@@ -70,7 +68,7 @@ Gunshots/explosions/opening doors/less rare audio (done)
var/col_mod = null
var/image/current_image = null
var/image_layer = MOB_LAYER
var/active = 1 //qdelery
var/active = TRUE //qdelery
/obj/effect/hallucination/simple/New(loc, mob/living/carbon/T)
..()
@@ -113,7 +111,7 @@ Gunshots/explosions/opening doors/less rare audio (done)
/obj/effect/hallucination/simple/Destroy()
if(target.client)
target.client.images.Remove(current_image)
active = 0
active = FALSE
return ..()
#define FAKE_FLOOD_EXPAND_TIME 20
@@ -198,21 +196,17 @@ Gunshots/explosions/opening doors/less rare audio (done)
pump = U
break
if(!pump)
return 0
return
xeno = new(pump.loc,target)
sleep(10)
if(!xeno)
return
xeno.update_icon("alienh_leap",'icons/mob/alienleap.dmi',-32,-32)
xeno.throw_at(target,7,1, spin = 0, diagonals_first = 1)
sleep(10)
if(!xeno)
return
xeno.update_icon("alienh_leap",'icons/mob/alienleap.dmi',-32,-32)
xeno.throw_at(pump,7,1, spin = 0, diagonals_first = 1)
sleep(10)
if(!xeno)
return
for(var/i in 0 to 2)
xeno.update_icon("alienh_leap",'icons/mob/alienleap.dmi',-32,-32)
xeno.throw_at(target,7,1, spin = 0, diagonals_first = 1)
sleep(10)
if(!xeno)
return
var/xeno_name = xeno.name
to_chat(target, "<span class='notice'>[xeno_name] begins climbing into the ventilation system...</span>")
sleep(10)
@@ -253,7 +247,7 @@ Gunshots/explosions/opening doors/less rare audio (done)
break
if(pump)
borer = new(pump.loc,target)
for(var/i=0, i<11, i++)
for(var/i in 0 to 10)
walk_to(borer, get_step(borer, get_cardinal_dir(borer, T)))
if(borer.Adjacent(T))
to_chat(T, "<span class='userdanger'>You feel a creeping, horrible sense of dread come over you, freezing your limbs and setting your heart racing.</span>")
@@ -331,10 +325,10 @@ Gunshots/explosions/opening doors/less rare audio (done)
target = T
var/turf/start = get_turf(T)
var/screen_border = pick(cardinal)
for(var/i = 0,i<11,i++)
for(var/i in 0 to 10)
start = get_step(start, screen_border)
s = new(start,target)
for(var/i = 0,i<11,i++)
for(var/i in 0 to 10)
sleep(5)
s.loc = get_step(get_turf(s), get_dir(s, target))
s.Show()
@@ -359,10 +353,10 @@ Gunshots/explosions/opening doors/less rare audio (done)
/obj/effect/hallucination/battle/New(loc, mob/living/carbon/T)
target = T
var/hits = rand(3,6)
var/hits = rand(2,5)
switch(rand(1,5))
if(1) //Laser fight
for(var/i=0,i<hits,i++)
for(var/i in 0 to hits)
target.playsound_local(null, 'sound/weapons/Laser.ogg', 25, 1)
if(prob(75))
addtimer(CALLBACK(target, /mob/.proc/playsound_local, null, 'sound/weapons/sear.ogg', 25, 1), rand(10,20))
@@ -372,13 +366,13 @@ Gunshots/explosions/opening doors/less rare audio (done)
target.playsound_local(null, get_sfx("bodyfall"), 25)
if(2) //Esword fight
target.playsound_local(null, 'sound/weapons/saberon.ogg', 15, 1)
for(var/i=0,i<hits,i++)
for(var/i in 0 to hits)
target.playsound_local(null, 'sound/weapons/blade1.ogg', 25, 1)
sleep(rand(CLICK_CD_MELEE, CLICK_CD_MELEE + 8))
target.playsound_local(null, get_sfx("bodyfall"), 25, 1)
target.playsound_local(null, 'sound/weapons/saberoff.ogg', 15, 1)
if(3) //Gun fight
for(var/i=0,i<hits,i++)
for(var/i in 0 to hits)
target.playsound_local(null, get_sfx("gunshot"), 25)
if(prob(75))
addtimer(CALLBACK(target, /mob/.proc/playsound_local, null, 'sound/weapons/pierce.ogg', 25, 1), rand(10,20))
@@ -392,7 +386,7 @@ Gunshots/explosions/opening doors/less rare audio (done)
sleep(20)
target.playsound_local(null, 'sound/weapons/cablecuff.ogg', 15, 1)
if(5) // Tick Tock
for(var/i=0,i<hits,i++)
for(var/i in 0 to hits)
target.playsound_local(null, 'sound/items/timer.ogg', 25, 1)
sleep(15)
qdel(src)
@@ -605,27 +599,25 @@ Gunshots/explosions/opening doors/less rare audio (done)
/obj/effect/fake_attacker/New(loc, mob/living/carbon/T)
..()
my_target = T
spawn(300)
qdel(src)
addtimer(CALLBACK(GLOBAL_PROC, .proc/qdel, src), 300)
step_away(src,my_target,2)
spawn(0)
attack_loop()
INVOKE_ASYNC(src, .proc/attack_loop)
/obj/effect/fake_attacker/proc/updateimage()
// qdel(src.currentimage)
if(dir == NORTH)
qdel(src.currentimage)
currentimage = new /image(up, src)
else if(dir == SOUTH)
qdel(src.currentimage)
currentimage = new /image(down, src)
else if(dir == EAST)
qdel(src.currentimage)
currentimage = new /image(right, src)
else if(dir == WEST)
qdel(src.currentimage)
currentimage = new /image(left, src)
switch(dir)
if(NORTH)
qdel(src.currentimage)
currentimage = new /image(up, src)
if(SOUTH)
qdel(src.currentimage)
currentimage = new /image(down, src)
if(EAST)
qdel(src.currentimage)
currentimage = new /image(right, src)
if(WEST)
qdel(src.currentimage)
currentimage = new /image(left, src)
my_target << currentimage
@@ -672,8 +664,7 @@ Gunshots/explosions/opening doors/less rare audio (done)
O.name = "blood"
var/image/I = image('icons/effects/blood.dmi',O,"floor[rand(1,7)]",O.dir,1)
target << I
spawn(300)
qdel(O)
addtimer(CALLBACK(GLOBAL_PROC, .proc/qdel, O), 300)
return
var/list/non_fakeattack_weapons = list(/obj/item/gun/projectile, /obj/item/ammo_box/a357,\
@@ -815,10 +806,9 @@ var/list/non_fakeattack_weapons = list(/obj/item/gun/projectile, /obj/item/ammo_
playsound_local(null, pick('sound/effects/Glassbr1.ogg','sound/effects/Glassbr2.ogg','sound/effects/Glassbr3.ogg'), 50, 1)
if(5)
playsound_local(null, 'sound/weapons/ring.ogg', 35)
sleep(15)
playsound_local(null, 'sound/weapons/ring.ogg', 35)
sleep(15)
playsound_local(null, 'sound/weapons/ring.ogg', 35)
for(var/i in 0 to 2)
sleep(15)
playsound_local(null, 'sound/weapons/ring.ogg', 35)
if(6)
playsound_local(null, 'sound/magic/Summon_guns.ogg', 50, 1)
if(7)
@@ -828,19 +818,17 @@ var/list/non_fakeattack_weapons = list(/obj/item/gun/projectile, /obj/item/ammo_
if(9)
//To make it more realistic, I added two gunshots (enough to kill)
playsound_local(null, 'sound/weapons/Gunshot.ogg', 25, 1)
spawn(rand(10,30))
playsound_local(null, 'sound/weapons/Gunshot.ogg', 25, 1)
sleep(rand(5,10))
playsound_local(null, sound(get_sfx("bodyfall"), 25), 25, 1)
var/timer_pause = rand(10,30)
addtimer(CALLBACK(GLOBAL_PROC, .proc/playsound_local, null, 'sound/weapons/Gunshot.ogg', 25, 1), timer_pause)
addtimer(CALLBACK(GLOBAL_PROC, .proc/playsound_local, null, sound(get_sfx("bodyfall"), 25), 25, 1), timer_pause+rand(5,10))
if(10)
playsound_local(null, 'sound/effects/pray_chaplain.ogg', 50)
if(11)
//Same as above, but with tasers.
playsound_local(null, 'sound/weapons/Taser.ogg', 25, 1)
spawn(rand(10,30))
playsound_local(null, 'sound/weapons/Taser.ogg', 25, 1)
sleep(rand(5,10))
playsound_local(null, sound(get_sfx("bodyfall"), 25), 25, 1)
var/timer_pause = rand(10,30)
addtimer(CALLBACK(GLOBAL_PROC, .proc/playsound_local, null, 'sound/weapons/Taser.ogg', 25, 1), timer_pause)
addtimer(CALLBACK(GLOBAL_PROC, .proc/playsound_local, null, sound(get_sfx("bodyfall"), 25), 25, 1), timer_pause+rand(5,10))
//Rare audio
if(12)
//These sounds are (mostly) taken from Hidden: Source
@@ -865,7 +853,7 @@ var/list/non_fakeattack_weapons = list(/obj/item/gun/projectile, /obj/item/ammo_
if(16)
playsound_local(null, 'sound/items/Screwdriver.ogg', 15, 1)
sleep(rand(10,30))
for(var/i = rand(1,3), i>0, i--)
for(var/i in 0 to rand(1,3))
playsound_local(null, 'sound/weapons/empty.ogg', 15, 1)
sleep(rand(10,30))
playsound_local(null, 'sound/machines/airlockforced.ogg', 15, 1)
@@ -877,10 +865,9 @@ var/list/non_fakeattack_weapons = list(/obj/item/gun/projectile, /obj/item/ammo_
playsound_local(null, 'sound/AI/outbreak5.ogg')
if(19) //Tesla loose!
playsound_local(null, 'sound/magic/lightningbolt.ogg', 35, 1)
sleep(20)
playsound_local(null, 'sound/magic/lightningbolt.ogg', 65, 1)
sleep(20)
playsound_local(null, 'sound/magic/lightningbolt.ogg', 100, 1)
for(var/i in 0 to 2)
sleep(20)
playsound_local(null, 'sound/magic/lightningbolt.ogg', 65+(35*(i-1)), 1) //65%, then 100% volume.
if(20) //AI is doomsdaying!
to_chat(src, "<h1 class='alert'>Anomaly Alert</h1>")
to_chat(src, "<br><br><span class='alert'>Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.</span><br><br>")
@@ -987,8 +974,7 @@ var/list/non_fakeattack_weapons = list(/obj/item/gun/projectile, /obj/item/ammo_
halitem.icon_state = "flashbang1"
halitem.name = "Flashbang"
if(client) client.screen += halitem
spawn(rand(100,250))
qdel(halitem)
addtimer(CALLBACK(GLOBAL_PROC, .proc/qdel, halitem), rand(100,250))
if("dangerflash")
//Flashes of danger
if(!halimage)
@@ -1007,8 +993,7 @@ var/list/non_fakeattack_weapons = list(/obj/item/gun/projectile, /obj/item/ammo_
halimage = image('icons/turf/floors/Chasms.dmi',target,"smooth",TURF_LAYER)
if(4)
halimage = image('icons/obj/assemblies.dmi',target,"plastic-explosive2",OBJ_LAYER+0.01)
if(client)
client.images += halimage
sleep(rand(40,60)) //Only seen for a brief moment.
@@ -1054,4 +1039,4 @@ var/list/non_fakeattack_weapons = list(/obj/item/gun/projectile, /obj/item/ammo_
spawn(rand(30,50)) //Only seen for a brief moment.
if(client)
client.images -= halbody
halbody = null
halbody = null
@@ -5,7 +5,7 @@
icon = 'icons/obj/cooking_machines.dmi'
icon_state = "candymaker_off"
cook_verbs = list("Wonderizing", "Scrumpdiddlyumptiousification", "Miracle-coating", "Flavorifaction")
recipe_type = /datum/recipe/candy
recipe_type = RECIPE_CANDY
off_icon = "candymaker_off"
on_icon = "candymaker_on"
broken_icon = "candymaker_broke"
@@ -4,7 +4,7 @@
layer = 2.9
density = 1
anchored = 1
use_power = 1
use_power = IDLE_POWER_USE
idle_power_usage = 5
var/on = 0
var/onicon = null
@@ -20,7 +20,7 @@
var/stealthmode = FALSE
var/list/victims = list()
use_power = 1
use_power = IDLE_POWER_USE
idle_power_usage = 2
active_power_usage = 500
@@ -5,7 +5,7 @@
icon = 'icons/obj/cooking_machines.dmi'
icon_state = "grill_off"
cook_verbs = list("Grilling", "Searing", "Frying")
recipe_type = /datum/recipe/grill
recipe_type = RECIPE_GRILL
off_icon = "grill_off"
on_icon = "grill_on"
broken_icon = "grill_broke"
@@ -7,7 +7,7 @@
anchored = 1
icon = 'icons/obj/cooking_machines.dmi'
icon_state = "icecream_vat"
use_power = 1
use_power = IDLE_POWER_USE
idle_power_usage = 20
var/obj/item/reagent_containers/glass/beaker = null
var/useramount = 15 //Last used amount
@@ -6,7 +6,7 @@
layer = 2.9
density = 1
anchored = 0
use_power = 1
use_power = IDLE_POWER_USE
idle_power_usage = 5
active_power_usage = 100
pass_flags = PASSTABLE
@@ -5,7 +5,7 @@
layer = 2.9
density = 1
anchored = 1
use_power = 1
use_power = IDLE_POWER_USE
idle_power_usage = 5
active_power_usage = 100
flags = OPENCONTAINER
@@ -16,10 +16,7 @@
var/list/cook_verbs = list("Cooking")
//Recipe & Item vars
var/recipe_type //Make sure to set this on the machine definition, or else you're gonna runtime on New()
var/list/datum/recipe/available_recipes // List of the recipes you can use
var/list/acceptable_items // List of the items you can put in
var/list/acceptable_reagents // List of the reagents you can put in
var/max_n_of_items = 0
var/max_n_of_items = 25
//Icon states
var/off_icon
var/on_icon
@@ -35,23 +32,28 @@
..()
create_reagents(100)
reagents.set_reacting(FALSE)
if(!available_recipes)
available_recipes = new
acceptable_items = new
acceptable_reagents = new
for(var/type in subtypesof(recipe_type))
init_lists()
/obj/machinery/kitchen_machine/proc/init_lists()
if(!GLOB.cooking_recipes[recipe_type])
GLOB.cooking_recipes[recipe_type] = list()
GLOB.cooking_ingredients[recipe_type] = list()
GLOB.cooking_reagents[recipe_type] = list()
if(!length(GLOB.cooking_recipes[recipe_type]))
for(var/type in subtypesof(GLOB.cooking_recipe_types[recipe_type]))
var/datum/recipe/recipe = new type
if(recipe in GLOB.cooking_recipes[recipe_type])
qdel(recipe)
continue
if(recipe.result) // Ignore recipe subtypes that lack a result
available_recipes += recipe
GLOB.cooking_recipes[recipe_type] += recipe
for(var/item in recipe.items)
acceptable_items |= item
GLOB.cooking_ingredients[recipe_type] |= item
for(var/reagent in recipe.reagents)
acceptable_reagents |= reagent
if(recipe.items)
max_n_of_items = max(max_n_of_items,recipe.count_n_items())
GLOB.cooking_reagents[recipe_type] |= reagent
else
qdel(recipe)
acceptable_items |= /obj/item/reagent_containers/food/snacks/grown
GLOB.cooking_ingredients[recipe_type] |= /obj/item/reagent_containers/food/snacks/grown
/*******************
* Item Adding
@@ -80,26 +82,14 @@
if(broken > 0)
if(broken == 2 && istype(O, /obj/item/screwdriver)) // If it's broken and they're using a screwdriver
user.visible_message( \
"<span class='notice'>[user] starts to fix part of \the [src].</span>", \
"<span class='notice'>You start to fix part of \the [src].</span>" \
)
user.visible_message("<span class='notice'>[user] starts to fix part of [src].</span>", "<span class='notice'>You start to fix part of [src].</span>")
if(do_after(user, 20 * O.toolspeed, target = src))
user.visible_message( \
"<span class='notice'>[user] fixes part of \the [src].</span>", \
"<span class='notice'>You have fixed part of \the [src].</span>" \
)
user.visible_message("<span class='notice'>[user] fixes part of [src].</span>", "<span class='notice'>You have fixed part of \the [src].</span>")
broken = 1 // Fix it a bit
else if(broken == 1 && istype(O, /obj/item/wrench)) // If it's broken and they're doing the wrench
user.visible_message( \
"<span class='notice'>[user] starts to fix part of \the [src].</span>", \
"<span class='notice'>You start to fix part of \the [src].</span>" \
)
user.visible_message("<span class='notice'>[user] starts to fix part of [src].</span>", "<span class='notice'>You start to fix part of [src].</span>")
if(do_after(user, 20 * O.toolspeed, target = src))
user.visible_message( \
"<span class='notice'>[user] fixes \the [src].</span>", \
"<span class='notice'>You have fixed \the [src].</span>" \
)
user.visible_message("<span class='notice'>[user] fixes [src].</span>", "<span class='notice'>You have fixed [src].</span>")
icon_state = off_icon
broken = 0 // Fix it!
dirty = 0 // just to be sure
@@ -109,15 +99,9 @@
return 1
else if(dirty==100) // The machine is all dirty so can't be used!
if(istype(O, /obj/item/reagent_containers/spray/cleaner) || istype(O, /obj/item/soap)) // If they're trying to clean it then let them
user.visible_message( \
"<span class='notice'>[user] starts to clean \the [src].</span>", \
"<span class='notice'>You start to clean \the [src].</span>" \
)
user.visible_message("<span class='notice'>[user] starts to clean [src].</span>", "<span class='notice'>You start to clean [src].</span>")
if(do_after(user, 20 * O.toolspeed, target = src))
user.visible_message( \
"<span class='notice'>[user] has cleaned \the [src].</span>", \
"<span class='notice'>You have cleaned \the [src].</span>" \
)
user.visible_message("<span class='notice'>[user] has cleaned [src].</span>", "<span class='notice'>You have cleaned [src].</span>")
dirty = 0 // It's clean!
broken = 0 // just to be sure
icon_state = off_icon
@@ -125,33 +109,25 @@
else //Otherwise bad luck!!
to_chat(user, "<span class='alert'>It's dirty!</span>")
return 1
else if(is_type_in_list(O,acceptable_items))
else if(is_type_in_list(O, GLOB.cooking_ingredients[recipe_type]) || istype(O, /obj/item/mixing_bowl))
if(contents.len>=max_n_of_items)
to_chat(user, "<span class='alert'>This [src] is full of ingredients, you cannot put more.</span>")
return 1
if(istype(O,/obj/item/stack) && O:amount>1)
new O.type (src)
O:use(1)
user.visible_message( \
"<span class='notice'>[user] has added one of [O] to \the [src].</span>", \
"<span class='notice'>You add one of [O] to \the [src].</span>")
if(istype(O,/obj/item/stack))
var/obj/item/stack/S = O
if(S.amount > 1)
var/obj/item/stack/to_add = S.split(user, 1)
to_add.forceMove(src)
user.visible_message("<span class='notice'>[user] adds one of [S] to [src].</span>", "<span class='notice'>You add one of [S] to [src].</span>")
else
add_item(S, user)
else
if(!user.drop_item())
to_chat(user, "<span class='notice'>\The [O] is stuck to your hand, you cannot put it in \the [src]</span>")
return 0
O.forceMove(src)
user.visible_message( \
"<span class='notice'>[user] has added \the [O] to \the [src].</span>", \
"<span class='notice'>You add \the [O] to \the [src].</span>")
else if(istype(O,/obj/item/reagent_containers/glass) || \
istype(O,/obj/item/reagent_containers/food/drinks) || \
istype(O,/obj/item/reagent_containers/food/condiment) \
)
add_item(O, user)
else if(is_type_in_list(O, list(/obj/item/reagent_containers/glass, /obj/item/reagent_containers/food/drinks, /obj/item/reagent_containers/food/condiment)))
if(!O.reagents)
return 1
for(var/datum/reagent/R in O.reagents.reagent_list)
if(!(R.id in acceptable_reagents))
if(!(R.id in GLOB.cooking_reagents[recipe_type]))
to_chat(user, "<span class='alert'>Your [O] contains components unsuitable for cookery.</span>")
return 1
//G.reagents.trans_to(src,G.amount_per_transfer_from_this)
@@ -162,6 +138,14 @@
return 1
updateUsrDialog()
/obj/machinery/kitchen_machine/proc/add_item(obj/item/I, mob/user)
if(!user.drop_item())
to_chat(user, "<span class='notice'>\The [I] is stuck to your hand, you cannot put it in [src]</span>")
//return 0
else
I.forceMove(src)
user.visible_message("<span class='notice'>[user] adds [I] to [src].</span>", "<span class='notice'>You add [I] to [src].</span>")
/obj/machinery/kitchen_machine/attack_ai(mob/user)
return 0
@@ -182,11 +166,11 @@
return
var/dat = ""
if(broken > 0)
dat = {"<TT>Bzzzzttttt</TT>"}
dat = {"<code>Bzzzzttttt</code>"}
else if(operating)
dat = {"<TT>[pick(cook_verbs)] in progress!<BR>Please wait...!</TT>"}
dat = {"<code>[pick(cook_verbs)] in progress!<BR>Please wait...!</code>"}
else if(dirty==100)
dat = {"<TT>This [src] is dirty!<BR>Please clean it before use!</TT>"}
dat = {"<code>This [src] is dirty!<BR>Please clean it before use!</code>"}
else
var/list/items_counts = new
var/list/items_measures = new
@@ -260,12 +244,13 @@
stop()
return
var/datum/recipe/recipe = select_recipe(available_recipes,src)
var/obj/cooked
var/obj/byproduct
if(!recipe)
var/list/recipes_to_make = choose_recipes()
if(recipes_to_make.len == 1 && recipes_to_make[1][2] == RECIPE_FAIL)
//This only runs if there is a single recipe source to be made and it is a failure (the machine was loaded with only 1 mixing bowl that results in failure OR was directly loaded with ingredients that results in failure).
//If there are multiple sources, this bit gets skipped.
dirty += 1
if(prob(max(10,dirty*5)))
if(prob(max(10,dirty*5))) //chance to get so dirty we require cleaning before next use
if(!wzhzhzh(4))
abort()
return
@@ -274,14 +259,14 @@
muck_finish()
fail()
return
else if(has_extra_item())
else if(has_extra_item()) //if extra items present, break down and require repair before next use
if(!wzhzhzh(4))
abort()
return
broke()
fail()
return
else
else //otherwise just stop without requiring cleaning/repair
if(!wzhzhzh(10))
abort()
return
@@ -289,24 +274,69 @@
fail()
return
else
var/halftime = round(recipe.time/10/2)
if(!wzhzhzh(halftime))
if(!wzhzhzh(5))
abort()
return
if(!wzhzhzh(halftime))
if(!wzhzhzh(5))
abort()
fail()
return
cooked = recipe.make_food(src)
byproduct = recipe.get_byproduct()
stop()
if(cooked)
cooked.forceMove(loc)
for(var/i=1,i<efficiency,i++)
cooked = new cooked.type(loc)
if(byproduct)
new byproduct(loc)
make_recipes(recipes_to_make)
//choose_recipes(): picks out recipes for the machine and any mixing bowls it may contain.
//builds a list of the selected recipes to be made in a later proc by associating the "source" of the ingredients (mixing bowl, machine) with the recipe for that source
/obj/machinery/kitchen_machine/proc/choose_recipes()
var/list/recipes_to_make = list()
for(var/obj/item/mixing_bowl/mb in contents) //if we have mixing bowls present, check each one for possible recipes from its respective contents. Mixing bowls act like a wrapper for recipes and ingredients, isolating them from other ingredients and mixing bowls within a machine.
var/datum/recipe/recipe = select_recipe(GLOB.cooking_recipes[recipe_type], mb)
if(recipe)
recipes_to_make.Add(list(list(mb, recipe)))
else //if the ingredients of the mixing bowl don't make a valid recipe, we return a fail recipe to generate the burned mess
recipes_to_make.Add(list(list(mb, RECIPE_FAIL)))
var/datum/recipe/recipe_src = select_recipe(GLOB.cooking_recipes[recipe_type], src, ignored_items = list(/obj/item/mixing_bowl)) //check the machine's directly-inserted ingredients for possible recipes as well, ignoring the mixing bowls when selecting recipe
if(recipe_src) //if we found a valid recipe for directly-inserted ingredients, add that to our list
recipes_to_make.Add(list(list(src, recipe_src)))
else if(!recipes_to_make.len) //if the machine has no mixing bowls to make recipes from AND also doesn't have a valid recipe of directly-inserted ingredients, return a failure so we can make a burned mess
recipes_to_make.Add(list(list(src, RECIPE_FAIL)))
return recipes_to_make
//make_recipes(recipes_to_make): cycles through the supplied list of recipes and creates each recipe associated with the "source" for that entry
/obj/machinery/kitchen_machine/proc/make_recipes(list/recipes_to_make)
if(!recipes_to_make)
return
var/datum/reagents/temp_reagents = new(500)
for(var/i=1 to recipes_to_make.len) //cycle through each entry on the recipes_to_make list for processing
var/list/L = recipes_to_make[i]
var/obj/source = L[1] //this is the source of the recipe entry (mixing bowl or the machine)
var/datum/recipe/recipe = L[2] //this is the recipe associated with the source (a valid recipe or null)
if(recipe == RECIPE_FAIL) //we have a failure and create a burned mess
//failed recipe
fail()
else //we have a valid recipe to begin making
for(var/obj/O in source.contents) //begin processing the ingredients supplied
if(istype(O, /obj/item/mixing_bowl)) //ignore mixing bowls present among the ingredients in our source (only really applies to machine sourced recipes)
continue
if(O.reagents)
O.reagents.del_reagent("nutriment")
O.reagents.update_total()
O.reagents.trans_to(temp_reagents, O.reagents.total_volume)
qdel(O)
source.reagents.clear_reagents()
for(var/e=1 to efficiency) //upgraded machine? make additional servings and split the ingredient reagents among each serving equally.
var/obj/cooked = new recipe.result()
temp_reagents.trans_to(cooked, temp_reagents.total_volume/efficiency)
cooked.forceMove(loc)
temp_reagents.clear_reagents()
var/obj/byproduct = recipe.get_byproduct() //if the recipe has a byproduct, handle returning that (such as re-usable candy moulds)
if(byproduct)
new byproduct(loc)
if(istype(source, /obj/item/mixing_bowl)) //if the recipe's source was a mixing bowl, make it a little dirtier and return that for re-use.
var/obj/item/mixing_bowl/mb = source
mb.make_dirty(5 * efficiency)
mb.forceMove(loc)
stop()
return
/obj/machinery/kitchen_machine/proc/wzhzhzh(seconds)
for(var/i=1 to seconds)
@@ -318,10 +348,7 @@
/obj/machinery/kitchen_machine/proc/has_extra_item()
for(var/obj/O in contents)
if( \
!istype(O,/obj/item/reagent_containers/food) && \
!istype(O, /obj/item/grown) \
)
if(!is_type_in_list(O, list(/obj/item/reagent_containers/food, /obj/item/grown, /obj/item/mixing_bowl)))
return 1
return 0
@@ -376,19 +403,27 @@
updateUsrDialog()
/obj/machinery/kitchen_machine/proc/fail()
var/obj/item/reagent_containers/food/snacks/badrecipe/ffuu = new(src)
var/amount = 0
for(var/obj/O in contents-ffuu)
for(var/obj/item/mixing_bowl/mb in contents) //fail and remove any mixing bowls present before making the burned mess from the machine itself (to avoid them being destroyed as part of the failure)
mb.fail(src)
mb.forceMove(get_turf(src))
for(var/obj/O in contents)
amount++
if(O.reagents)
if(O.reagents) //this is reagents in inserted objects (like chems in produce)
var/id = O.reagents.get_master_reagent_id()
if(id)
amount+=O.reagents.get_reagent_amount(id)
qdel(O)
if(reagents && reagents.total_volume) //this is directly-added reagents (like water added directly into the machine)
var/id = reagents.get_master_reagent_id()
if(id)
amount += reagents.get_reagent_amount(id)
reagents.clear_reagents()
ffuu.reagents.add_reagent("carbon", amount)
ffuu.reagents.add_reagent("????", amount/10)
ffuu.forceMove(get_turf(src))
if(amount)
var/obj/item/reagent_containers/food/snacks/badrecipe/ffuu = new(src)
ffuu.reagents.add_reagent("carbon", amount)
ffuu.reagents.add_reagent("????", amount/10)
ffuu.forceMove(get_turf(src))
/obj/machinery/kitchen_machine/Topic(href, href_list)
if(..() || panel_open)
@@ -5,7 +5,7 @@
icon = 'icons/obj/kitchen.dmi'
icon_state = "mw"
cook_verbs = list("Microwaving", "Reheating", "Heating")
recipe_type = /datum/recipe/microwave
recipe_type = RECIPE_MICROWAVE
off_icon = "mw"
on_icon = "mw1"
broken_icon = "mwb"
@@ -6,7 +6,7 @@
layer = 2.9
density = 1
anchored = 1
use_power = 1
use_power = IDLE_POWER_USE
idle_power_usage = 5
active_power_usage = 50
var/grinded = 0
@@ -102,4 +102,4 @@
to_chat(user, "<span class='notice'>The machine's display flashes that it has [grinded] monkey\s worth of material left.</span>")
else // I'm not sure if the \s macro works with a word in between; I'll play it safe
to_chat(user, "<span class='warning'>The machine needs at least [required_grind] monkey\s worth of material to compress [cube_production] monkey\s. It only has [grinded].</span>")
return
return
@@ -6,7 +6,7 @@
layer = 2.9
density = 1
anchored = 1
use_power = 1
use_power = IDLE_POWER_USE
var/candy = 0
idle_power_usage = 5
var/on = FALSE //Is it making food already?
@@ -5,7 +5,7 @@
icon = 'icons/obj/cooking_machines.dmi'
icon_state = "oven_off"
cook_verbs = list("Baking", "Roasting", "Broiling")
recipe_type = /datum/recipe/oven
recipe_type = RECIPE_OVEN
off_icon = "oven_off"
on_icon = "oven_on"
broken_icon = "oven_broke"
@@ -9,7 +9,7 @@
var/broken = 0
var/processing = 0
use_power = 1
use_power = IDLE_POWER_USE
idle_power_usage = 5
active_power_usage = 50
var/rating_speed = 1
@@ -7,7 +7,7 @@
layer = 2.9
density = 1
anchored = 1
use_power = 1
use_power = IDLE_POWER_USE
idle_power_usage = 5
active_power_usage = 100
var/max_n_of_items = 1500
@@ -226,7 +226,6 @@
if(load(O, user))
user.visible_message("<span class='notice'>[user] has added \the [O] to \the [src].</span>", "<span class='notice'>You add \the [O] to \the [src].</span>")
SSnanoui.update_uis(src)
else if(istype(O, /obj/item/storage/bag))
@@ -242,7 +241,7 @@
SSnanoui.update_uis(src)
else
else if(!istype(O, /obj/item/card/emag))
to_chat(user, "<span class='notice'>\The [src] smartly refuses [O].</span>")
return 1
@@ -308,11 +307,6 @@
to_chat(user, "<span class='notice'>Some items are refused.</span>")
SSnanoui.update_uis(src)
/obj/machinery/smartfridge/secure/emag_act(mob/user)
emagged = 1
locked = -1
to_chat(user, "You short out the product lock on [src].")
/*******************
* SmartFridge Menu
********************/
@@ -416,7 +410,7 @@
desc = "A wooden contraption, used to dry plant products, food and leather."
icon = 'icons/obj/hydroponics/equipment.dmi'
icon_state = "drying_rack_on"
use_power = 1
use_power = IDLE_POWER_USE
idle_power_usage = 5
active_power_usage = 200
icon_on = "drying_rack_on"
@@ -453,13 +447,13 @@
return 1
if(href_list["dryingOn"])
drying = TRUE
use_power = 2
use_power = ACTIVE_POWER_USE
update_icon()
return 1
if(href_list["dryingOff"])
drying = FALSE
use_power = 1
use_power = IDLE_POWER_USE
update_icon()
return 1
return 0
@@ -503,10 +497,10 @@
/obj/machinery/smartfridge/drying_rack/proc/toggle_drying(forceoff)
if(drying || forceoff)
drying = FALSE
use_power = 1
use_power = IDLE_POWER_USE
else
drying = TRUE
use_power = 2
use_power = ACTIVE_POWER_USE
update_icon()
/obj/machinery/smartfridge/drying_rack/proc/rack_dry()
@@ -539,6 +533,16 @@
/************************
* Secure SmartFridges
*************************/
/obj/machinery/smartfridge/secure/emag_act(mob/user)
emagged = 1
locked = -1
to_chat(user, "You short out the product lock on [src].")
/obj/machinery/smartfridge/secure/emp_act(severity)
if(prob(40/severity) && (!emagged) && (locked != -1))
playsound(loc, 'sound/effects/sparks4.ogg', 60, 1)
emagged = 1
locked = -1
/obj/machinery/smartfridge/secure/Topic(href, href_list)
if(stat & (NOPOWER|BROKEN))
@@ -548,4 +552,4 @@
to_chat(usr, "<span class='warning'>Access denied.</span>")
SSnanoui.update_uis(src)
return 0
return ..()
return ..()
+11 -9
View File
@@ -40,7 +40,7 @@
/obj/item/deck/examine(mob/user)
..()
to_chat(user,"<span class='notice'>It contains [cards.len ? cards.len : "no"] cards</span class>")
to_chat(user,"<span class='notice'>It contains [cards.len ? cards.len : "no"] cards</span>")
/obj/item/deck/attack_hand(mob/user as mob)
draw_card(user)
@@ -221,6 +221,8 @@
return
if(over_object == M)
if(!remove_item_from_storage(M))
M.unEquip(src)
M.put_in_hands(src)
else if(istype(over_object, /obj/screen))
@@ -250,7 +252,7 @@
/obj/item/pack/attack_self(mob/user as mob)
user.visible_message("<span class='notice'>[name] rips open the [src]!</span>", "<span class='notice'>You rips open the [src]!</span>")
var/obj/item/cardhand/H = new()
var/obj/item/cardhand/H = new(get_turf(user))
H.cards += cards
cards.Cut()
@@ -258,7 +260,7 @@
qdel(src)
H.update_icon()
user.put_in_active_hand(H)
user.put_in_hands(H)
/obj/item/cardhand
name = "hand of cards"
@@ -315,9 +317,9 @@
/obj/item/cardhand/examine(mob/user)
..(user)
if((!concealed) && cards.len)
to_chat(user,"<span class='notice'>It contains:</span class>")
to_chat(user,"<span class='notice'>It contains:</span>")
for(var/datum/playingcard/P in cards)
to_chat(user,"<span class='notice'>the [P.name].</span class>")
to_chat(user,"<span class='notice'>the [P.name].</span>")
// Datum action here
@@ -368,16 +370,17 @@
var/datum/playingcard/card = pickablecards[pickedcard]
var/obj/item/cardhand/H = new(get_turf(src))
user.put_in_active_hand(H)
user.put_in_hands(H)
H.cards += card
cards -= card
H.parentdeck = parentdeck
H.concealed = concealed
H.update_icon()
update_icon()
if(!cards.len)
qdel(src)
return
update_icon()
/obj/item/cardhand/verb/discard(var/mob/user as mob)
@@ -410,7 +413,7 @@
if(cards.len)
update_icon()
if(H.cards.len)
usr.visible_message("<span class='notice'>The [user] plays the [discarding].</span>", "<span class='notice'>You play the [discarding].</span>")
usr.visible_message("<span class='notice'>The [usr] plays the [discarding].</span>", "<span class='notice'>You play the [discarding].</span>")
H.loc = get_step(usr,usr.dir)
if(!cards.len)
@@ -419,7 +422,6 @@
/obj/item/cardhand/update_icon(var/direction = 0)
if(!cards.len)
qdel(src)
return
else if(cards.len > 1)
name = "hand of cards"
+1 -1
View File
@@ -5,7 +5,7 @@
icon_state = "biogen-empty"
density = 1
anchored = 1
use_power = 1
use_power = IDLE_POWER_USE
idle_power_usage = 40
var/processing = 0
var/obj/item/reagent_containers/glass/beaker = null
+1 -1
View File
@@ -15,7 +15,7 @@
icon_dead = "soybean-dead"
genes = list(/datum/plant_gene/trait/repeated_harvest)
mutatelist = list(/obj/item/seeds/soya/koi)
reagents_add = list("vitamin" = 0.04, "plantmatter" = 0.05)
reagents_add = list("soybeanoil" = 0.2, "vitamin" = 0.04, "plantmatter" = 0.05)
/obj/item/reagent_containers/food/snacks/grown/soybeans
seed = /obj/item/seeds/soya
+1 -1
View File
@@ -1008,7 +1008,7 @@
icon = 'icons/obj/hydroponics/equipment.dmi'
icon_state = "soil"
density = 0
use_power = 0
use_power = NO_POWER_USE
wrenchable = 0
/obj/machinery/hydroponics/soil/update_icon_hoses()
+9 -5
View File
@@ -315,12 +315,16 @@
/datum/plant_gene/trait/teleport/on_slip(obj/item/reagent_containers/food/snacks/grown/G, mob/living/carbon/C)
var/teleport_radius = max(round(G.seed.potency / 10), 1)
var/turf/T = get_turf(C)
to_chat(C, "<span class='warning'>You slip through spacetime!</span>")
do_teleport(C, T, teleport_radius)
if(prob(50))
do_teleport(G, T, teleport_radius)
if(do_teleport(C, T, teleport_radius))
to_chat(C, "<span class='warning'>You slip through spacetime!</span>")
if(prob(50))
do_teleport(G, T, teleport_radius)
else
new /obj/effect/decal/cleanable/molten_object(T) //Leave a pile of goo behind for dramatic effect...
qdel(G)
else
new /obj/effect/decal/cleanable/molten_object(T) //Leave a pile of goo behind for dramatic effect...
to_chat(C, "<span class='warning'>[src] sparks, and burns up!</span>")
new /obj/effect/decal/cleanable/molten_object(T)
qdel(G)
+63 -72
View File
@@ -1,3 +1,7 @@
/* KARMA
Everything karma related is here.
Part of karma purchase is handled in client_procs.dm */
proc/sql_report_karma(var/mob/spender, var/mob/receiver)
var/sqlspendername = sanitizeSQL(spender.name)
var/sqlspenderkey = spender.ckey
@@ -39,49 +43,49 @@ proc/sql_report_karma(var/mob/spender, var/mob/receiver)
var/err = query.ErrorMsg()
log_game("SQL ERROR during karmatotal logging (adding new key). Error : \[[err]\]\n")
else
karma += 1
karma++
query = dbcon.NewQuery("UPDATE [format_table_name("karmatotals")] SET karma=[karma] WHERE id=[id]")
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during karmatotal logging (updating existing entry). Error : \[[err]\]\n")
var/list/karma_spenders = list()
// Returns 1 if mob can give karma at all; if not, tells them why
// Returns TRUE if mob can give karma at all; if not, tells them why
/mob/proc/can_give_karma()
if(!client)
return 0
to_chat(src, "<span class='warning'>You can't award karma without being connected.</span>")
return FALSE
if(config.disable_karma)
to_chat(src, "<span class='warning'>Karma is disabled.</span>")
return 0
return FALSE
if(!ticker || !player_list.len || (ticker.current_state == GAME_STATE_PREGAME))
to_chat(src, "<span class='warning'>You can't award karma until the game has started.</span>")
return 0
return FALSE
if(client.karma_spent || (ckey in karma_spenders))
to_chat(src, "<span class='warning'>You've already spent your karma for the round.</span>")
return 0
return 1
return FALSE
return TRUE
// Returns 1 if mob can give karma to M; if not, tells them why
// Returns TRUE if mob can give karma to M; if not, tells them why
/mob/proc/can_give_karma_to_mob(mob/M)
if(!can_give_karma())
return 0
return FALSE
if(!istype(M))
to_chat(src, "<span class='warning'>That's not a mob.</span>")
return 0
return FALSE
if(!M.client)
to_chat(src, "<span class='warning'>That mob has no client connected at the moment.</span>")
return 0
if(ckey == M.ckey)
return FALSE
if(M.ckey == ckey)
to_chat(src, "<span class='warning'>You can't spend karma on yourself!</span>")
return 0
return FALSE
if(client.address == M.client.address)
message_admins("<span class='warning'>Illegal karma spending attempt detected from [key] to [M.key]. Using the same IP!</span>")
log_game("Illegal karma spending attempt detected from [key] to [M.key]. Using the same IP!")
to_chat(src, "<span class='warning'>You can't spend karma on someone connected from the same IP.</span>")
return 0
return 1
return FALSE
return TRUE
/mob/verb/spend_karma_list()
@@ -129,9 +133,9 @@ var/list/karma_spenders = list()
if(!can_give_karma_to_mob(M))
return // Check again, just in case things changed while the alert box was up
M.client.karma += 1
M.client.karma++
to_chat(usr, "Good karma spent on [M.name].")
client.karma_spent = 1
client.karma_spent = TRUE
karma_spenders += ckey
var/special_role = "None"
@@ -153,14 +157,14 @@ var/list/karma_spenders = list()
if(config.disable_karma)
to_chat(src, "<span class='warning'>Karma is disabled.</span>")
return 0
return
var/currentkarma=verify_karma()
to_chat(usr, {"<br>You have <b>[currentkarma]</b> available."})
return
var/currentkarma = verify_karma()
if(!isnull(currentkarma))
to_chat(usr, {"<br>You have <b>[currentkarma]</b> available."})
/client/proc/verify_karma()
var/currentkarma=0
var/currentkarma = 0
if(!dbcon.IsConnected())
to_chat(usr, "<span class='warning'>Unable to connect to karma database. Please try again later.<br></span>")
return
@@ -174,24 +178,18 @@ var/list/karma_spenders = list()
totalkarma = query.item[1]
karmaspent = query.item[2]
currentkarma = (text2num(totalkarma) - text2num(karmaspent))
/* if(totalkarma)
to_chat(usr, {"<br>You have <b>[currentkarma]</b> available.<br>)
You've gained <b>[totalkarma]</b> total karma in your time here.<br>"}
else
to_chat(usr, "<b>Your total karma is:</b> 0<br>")*/
return currentkarma
/client/verb/karmashop()
set name = "karmashop"
set desc = "Spend your hard-earned karma here"
set hidden = 1
set hidden = TRUE
if(config.disable_karma)
to_chat(src, "<span class='warning'>Karma is disabled.</span>")
return 0
return
karmashopmenu()
return
/client/proc/karmashopmenu()
var/dat = "<html><body><center>"
@@ -267,7 +265,23 @@ You've gained <b>[totalkarma]</b> total karma in your time here.<br>"}
var/datum/browser/popup = new(usr, "karmashop", "<div align='center'>Karma Shop</div>", 400, 400)
popup.set_content(dat)
popup.open(0)
return
//Checks if can afford, what you're purchasing, then purchases. (used in client_procs.dm)
/client/proc/karma_purchase(var/karma = 0, var/price = 1, var/category, var/name, var/DBname = null)
if(karma < price)
to_chat(usr, "You do not have enough karma!")
return
if(alert("Are you sure you want to unlock [name]?", "Confirmation", "No", "Yes") != "Yes")
return
if(karma < price) //Check one more time. (definitely not repeated code)
to_chat(usr, "You do not have enough karma!")
return
if(!isnull(DBname)) //In case database uses another name for logging. (Machine, Machine People)
name = DBname
if(category == "job")
DB_job_unlock(name,price)
else if(category == "species")
DB_species_unlock(name,price)
/client/proc/DB_job_unlock(var/job,var/cost)
var/DBQuery/query = dbcon.NewQuery("SELECT * FROM [format_table_name("whitelist")] WHERE ckey='[usr.ckey]'")
@@ -281,9 +295,7 @@ You've gained <b>[totalkarma]</b> total karma in your time here.<br>"}
if(!dbckey)
query = dbcon.NewQuery("INSERT INTO [format_table_name("whitelist")] (ckey, job) VALUES ('[usr.ckey]','[job]')")
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during whitelist logging (adding new key). Error: \[[err]\]\n")
message_admins("SQL ERROR during whitelist logging (adding new key). Error: \[[err]\]\n")
queryErrorLog(query.ErrorMsg(),"adding new key")
return
else
to_chat(usr, "You have unlocked [job].")
@@ -297,9 +309,7 @@ You've gained <b>[totalkarma]</b> total karma in your time here.<br>"}
var/newjoblist = jointext(joblist,",")
query = dbcon.NewQuery("UPDATE [format_table_name("whitelist")] SET job='[newjoblist]' WHERE ckey='[dbckey]'")
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during whitelist logging (updating existing entry). Error : \[[err]\]\n")
message_admins("SQL ERROR during whitelist logging (updating existing entry). Error : \[[err]\]\n")
queryErrorLog(query.ErrorMsg(),"updating existing entry")
return
else
to_chat(usr, "You have unlocked [job].")
@@ -321,9 +331,7 @@ You've gained <b>[totalkarma]</b> total karma in your time here.<br>"}
if(!dbckey)
query = dbcon.NewQuery("INSERT INTO [format_table_name("whitelist")] (ckey, species) VALUES ('[usr.ckey]','[species]')")
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during whitelist logging (adding new key). Error : \[[err]\]\n")
message_admins("SQL ERROR during whitelist logging (adding new key). Error : \[[err]\]\n")
queryErrorLog(query.ErrorMsg(),"adding new key")
return
else
to_chat(usr, "You have unlocked [species].")
@@ -337,9 +345,7 @@ You've gained <b>[totalkarma]</b> total karma in your time here.<br>"}
var/newspecieslist = jointext(specieslist,",")
query = dbcon.NewQuery("UPDATE [format_table_name("whitelist")] SET species='[newspecieslist]' WHERE ckey='[dbckey]'")
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during whitelist logging (updating existing entry). Error: \[[err]\]\n")
message_admins("SQL ERROR during whitelist logging (updating existing entry). Error: \[[err]\]\n")
queryErrorLog(query.ErrorMsg(),"updating existing entry")
return
else
to_chat(usr, "You have unlocked [species].")
@@ -349,7 +355,7 @@ You've gained <b>[totalkarma]</b> total karma in your time here.<br>"}
to_chat(usr, "You already have this species unlocked!")
return
/client/proc/karmacharge(var/cost,var/refund = 0)
/client/proc/karmacharge(var/cost,var/refund = FALSE)
var/DBQuery/query = dbcon.NewQuery("SELECT * FROM [format_table_name("karmatotals")] WHERE byondkey='[usr.ckey]'")
query.Execute()
@@ -361,9 +367,7 @@ You've gained <b>[totalkarma]</b> total karma in your time here.<br>"}
spent += cost
query = dbcon.NewQuery("UPDATE [format_table_name("karmatotals")] SET karmaspent=[spent] WHERE byondkey='[usr.ckey]'")
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during karmaspent updating (updating existing entry). Error: \[[err]\]\n")
message_admins("SQL ERROR during karmaspent updating (updating existing entry). Error: \[[err]\]\n")
queryErrorLog(query.ErrorMsg(),"updating existing entry")
return
else
to_chat(usr, "You have been [refund ? "refunded" : "charged"] [cost] karma.")
@@ -372,23 +376,8 @@ You've gained <b>[totalkarma]</b> total karma in your time here.<br>"}
/client/proc/karmarefund(var/type,var/name,var/cost)
switch(name)
if("Tajaran Ambassador")
cost = 30
if("Unathi Ambassador")
cost = 30
if("Skrell Ambassador")
cost = 30
if("Diona Ambassador")
cost = 30
if("Kidan Ambassador")
cost = 30
if("Slime People Ambassador")
cost = 30
if("Grey Ambassador")
cost = 30
if("Vox Ambassador")
cost = 30
if("Customs Officer")
if("Tajaran Ambassador","Unathi Ambassador","Skrell Ambassador","Diona Ambassador","Kidan Ambassador",
"Slime People Ambassador","Grey Ambassador","Vox Ambassador","Customs Officer")
cost = 30
if("Nanotrasen Recruiter")
cost = 10
@@ -422,9 +411,7 @@ You've gained <b>[totalkarma]</b> total karma in your time here.<br>"}
var/newtypelist = jointext(typelist,",")
query = dbcon.NewQuery("UPDATE [format_table_name("whitelist")] SET [type]='[newtypelist]' WHERE ckey='[dbckey]'")
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during whitelist logging (updating existing entry). Error: \[[err]\]\n")
message_admins("SQL ERROR during whitelist logging (updating existing entry). Error: \[[err]\]\n")
queryErrorLog(query.ErrorMsg(),"updating existing entry")
return
else
to_chat(usr, "You have been refunded [cost] karma for [type] [name].")
@@ -436,6 +423,10 @@ You've gained <b>[totalkarma]</b> total karma in your time here.<br>"}
else
to_chat(usr, "<span class='warning'>Your ckey ([dbckey]) was not found.</span>")
/client/proc/queryErrorLog(err = null, errType)
log_game("SQL ERROR during whitelist logging ([errType]]). Error : \[[err]\]\n")
message_admins("SQL ERROR during whitelist logging ([errType]]). Error : \[[err]\]\n")
/client/proc/checkpurchased(var/name = null) // If the first parameter is null, return a full list of purchases
var/DBQuery/query = dbcon.NewQuery("SELECT * FROM [format_table_name("whitelist")] WHERE ckey='[usr.ckey]'")
query.Execute()
@@ -454,10 +445,10 @@ You've gained <b>[totalkarma]</b> total karma in your time here.<br>"}
var/list/combinedlist = joblist + specieslist
if(name)
if(name in combinedlist)
return 1
return TRUE
else
return 0
return FALSE
else
return combinedlist
else
return 0
return FALSE
+1 -1
View File
@@ -77,7 +77,7 @@
health -= O.force * 0.75
else
if(health <= 0)
visible_message("<span class=warning>The bookcase is smashed apart!</span>")
visible_message("<span class='warning'>The bookcase is smashed apart!</span>")
qdel(src)
return ..()
+10
View File
@@ -0,0 +1,10 @@
/datum/map/delta
name = "Delta"
full_name = "NSS Kerberos"
station_name = "NSS Kerberos"
station_short = "Kerberos"
dock_name = "NAS Trurl"
company_name = "Nanotrasen"
company_short = "NT"
starsys_name = "Epsilon Eridani "
+1 -2
View File
@@ -37,8 +37,7 @@
add_to_streak("G",D)
if(check_streak(A,D))
return 1
D.grabbedby(A,1)
var/obj/item/grab/G = A.get_active_hand()
var/obj/item/grab/G = D.grabbedby(A,1)
if(G)
G.state = GRAB_NECK
+1 -2
View File
@@ -53,8 +53,7 @@
A.visible_message("<span class='warning'>[A] tries to grab ahold of [D], but fails!</span>", \
"<span class='warning'>You fail to grab ahold of [D]!</span>")
return 1
D.grabbedby(A,1)
var/obj/item/grab/G = A.get_active_hand()
var/obj/item/grab/G = D.grabbedby(A,1)
if(G)
D.visible_message("<span class='danger'>[A] grabs ahold of [D] drunkenly!</span>", \
"<span class='userdanger'>[A] grabs ahold of [D] drunkenly!</span>")
+1 -2
View File
@@ -108,8 +108,7 @@
add_to_streak("G",D)
if(check_streak(A,D))
return 1
D.grabbedby(A,1)
var/obj/item/grab/G = A.get_active_hand()
var/obj/item/grab/G = D.grabbedby(A,1)
if(G)
G.state = GRAB_AGGRESSIVE //Instant aggressive grab
+3
View File
@@ -664,6 +664,9 @@
var/turf/T = get_turf(H)
T.add_vomit_floor(H)
playsound(H, 'sound/effects/splat.ogg', 50, 1)
else
visible_message("<span class='warning'>[src] flickers and fails, due to bluespace interference!</span>")
qdel(src)
/**********************Resonator**********************/
@@ -16,7 +16,7 @@
/obj/machinery/computer/shuttle/labor/one_way/Topic(href, href_list)
if(href_list["move"])
var/obj/docking_port/mobile/M = shuttle_master.getShuttle("laborcamp")
var/obj/docking_port/mobile/M = SSshuttle.getShuttle("laborcamp")
if(!M)
to_chat(usr, "<span class='warning'>Cannot locate shuttle!</span>")
return 0
@@ -102,7 +102,7 @@
if(!alone_in_area(get_area(src), usr))
to_chat(usr, "<span class='warning'>Prisoners are only allowed to be released while alone.</span>")
else
switch(shuttle_master.moveShuttle("laborcamp","laborcamp_home"))
switch(SSshuttle.moveShuttle("laborcamp","laborcamp_home"))
if(1)
to_chat(usr, "<span class='notice'>Shuttle not found</span>")
if(2)
@@ -116,7 +116,7 @@
if(href_list["choice"] == "release")
if(alone_in_area(get_area(loc), usr))
var/obj/docking_port/stationary/S = shuttle_master.getDock("laborcamp_home")
var/obj/docking_port/stationary/S = SSshuttle.getDock("laborcamp_home")
if(S && S.get_docked())
if(release_door && release_door.density)
release_door.open()
@@ -12,7 +12,7 @@
unacidable = 1
burn_state = LAVA_PROOF | FIRE_PROOF
pixel_y = -4
use_power = 0
use_power = NO_POWER_USE
var/memory_saved = FALSE
var/list/stored_items = list()
var/static/list/blacklist = typecacheof(list(/obj/item/spellbook))
@@ -97,7 +97,7 @@
icon = 'icons/obj/lavaland/artefacts.dmi'
icon_state = "anomaly_crystal"
luminosity = 8
use_power = 0
use_power = NO_POWER_USE
density = 1
burn_state = LAVA_PROOF | FIRE_PROOF
unacidable = 1
+1 -1
View File
@@ -207,7 +207,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
for(var/obj/effect/step_trigger/S in locate(x, y, z)) //<-- this is dumb
S.Crossed(src)
var/area/A = get_area_master(src)
var/area/A = get_area(src)
if(A)
A.Entered(src)
+10 -5
View File
@@ -24,15 +24,20 @@
return target
// All mobs should have custom emote, really..
/mob/proc/custom_emote(var/m_type=1,var/message = null)
/mob/proc/custom_emote(var/m_type=EMOTE_VISUAL,var/message = null)
if(stat || !use_me && usr == src)
if(usr)
to_chat(usr, "You are unable to emote.")
return
var/muzzled = istype(src.wear_mask, /obj/item/clothing/mask/muzzle)
if(m_type == 2 && muzzled) return
var/muzzled = is_muzzled()
if(muzzled)
var/obj/item/clothing/mask/muzzle/M = wear_mask
if(m_type == EMOTE_SOUND && M.mute >= MUZZLE_MUTE_MUFFLE)
return //Not all muzzles block sound
if(m_type == EMOTE_SOUND && !can_speak())
return
var/input
if(!message)
@@ -63,7 +68,7 @@
// Type 1 (Visual) emotes are sent to anyone in view of the item
if(m_type & 1)
if(m_type & EMOTE_VISUAL)
var/list/can_see = get_mobs_in_view(1,src) //Allows silicon & mmi mobs carried around to see the emotes of the person carrying them around.
can_see |= viewers(src,null)
for(var/mob/O in can_see)
@@ -80,7 +85,7 @@
// Type 2 (Audible) emotes are sent to anyone in hear range
// of the *LOCATION* -- this is important for pAIs to be heard
else if(m_type & 2)
else if(m_type & EMOTE_SOUND)
for(var/mob/O in get_mobs_in_view(7,src))
if(O.status_flags & PASSEMOTES)
+4 -4
View File
@@ -1,6 +1,6 @@
// At minimum every mob has a hear_say proc.
/mob/proc/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/alt_name = "", var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol)
/mob/proc/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol)
if(!client)
return 0
@@ -70,12 +70,12 @@
if(speaker == src)
to_chat(src, "<span class='warning'>You cannot hear yourself speak!</span>")
else
to_chat(src, "<span class='name'>[speaker_name]</span>[alt_name] talks but you cannot hear [speaker.p_them()].")
to_chat(src, "<span class='name'>[speaker_name]</span>[speaker.GetAltName()] talks but you cannot hear [speaker.p_them()].")
else
if(language)
to_chat(src, "<span class='game say'><span class='name'>[speaker_name]</span>[alt_name] [track][language.format_message(message, verb)]</span>")
to_chat(src, "<span class='game say'><span class='name'>[speaker_name]</span>[speaker.GetAltName()] [track][language.format_message(message, verb)]</span>")
else
to_chat(src, "<span class='game say'><span class='name'>[speaker_name]</span>[alt_name] [track][verb], <span class='message'><span class='body'>\"[message]\"</span></span></span>")
to_chat(src, "<span class='game say'><span class='name'>[speaker_name]</span>[speaker.GetAltName()] [track][verb], <span class='message'><span class='body'>\"[message]\"</span></span></span>")
if(speech_sound && (get_dist(speaker, src) <= world.view && src.z == speaker.z))
var/turf/source = speaker? get_turf(speaker) : get_turf(src)
src.playsound_local(source, speech_sound, sound_vol, 1)
+2 -2
View File
@@ -83,7 +83,7 @@
//This is probably the main one you need to know :)
//Just puts stuff on the floor for most mobs, since all mobs have hands but putting stuff in the AI/corgi/ghost hand is VERY BAD.
/mob/proc/put_in_hands(obj/item/W)
W.forceMove(get_turf(src))
W.forceMove(drop_location())
W.layer = initial(W.layer)
W.plane = initial(W.plane)
W.dropped()
@@ -137,7 +137,7 @@
if(I)
if(client)
client.screen -= I
I.forceMove(loc)
I.forceMove(drop_location())
I.dropped(src)
if(I)
I.layer = initial(I.layer)
@@ -66,7 +66,7 @@
#define MAX_ALIEN_LEAP_DIST 7
/mob/living/carbon/alien/humanoid/hunter/proc/leap_at(var/atom/A)
if(pounce_cooldown)
if(pounce_cooldown > world.time)
to_chat(src, "<span class='alertalien'>You are too fatigued to pounce right now!</span>")
return
@@ -114,9 +114,7 @@
Weaken(2, 1, 1)
toggle_leap(0)
pounce_cooldown = !pounce_cooldown
spawn(pounce_cooldown_time) //3s by default
pounce_cooldown = !pounce_cooldown
pounce_cooldown = world.time + pounce_cooldown_time
else if(A.density && !A.CanPass(src))
visible_message("<span class ='danger'>[src] smashes into [A]!</span>", "<span class ='alertalien'>[src] smashes into [A]!</span>")
Weaken(2, 1, 1)
@@ -3,3 +3,4 @@
desc = "Enables radio capability on MMIs when either installed directly on the MMI, or through a cyborg's chassis."
icon = 'icons/obj/module.dmi'
icon_state = "cyborg_upgrade1"
origin_tech = "programming=3;biotech=2;engineering=2"
+2 -2
View File
@@ -29,7 +29,7 @@
to_chat(usr, "<span class='warning'>You cannot speak, as your internal speaker is turned off.</span>")
. = FALSE
/mob/living/carbon/brain/handle_message_mode(var/message_mode, var/message, var/verb, var/speaking, var/used_radios, var/alt_name)
/mob/living/carbon/brain/handle_message_mode(var/message_mode, var/message, var/verb, var/speaking, var/used_radios)
switch(message_mode)
if("headset")
var/radio_worked = 0 // If any of the radios our brainmob could use functioned, this is set true so that we don't use any others
@@ -45,6 +45,6 @@
radio_worked = c.radio.talk_into(src, message, message_mode, verb, speaking)
return radio_worked
if("whisper")
whisper_say(message, speaking, alt_name)
whisper_say(message, speaking)
return 1
else return 0
+4
View File
@@ -78,6 +78,10 @@
#undef STOMACH_ATTACK_DELAY
/mob/living/carbon/proc/has_mutated_organs()
return FALSE
/mob/living/carbon/proc/vomit(var/lost_nutrition = 10, var/blood = 0, var/stun = 1, var/distance = 0, var/message = 1)
if(src.is_muzzled())
if(message)
@@ -10,6 +10,10 @@
act = copytext(act, 1, t1)
var/muzzled = is_muzzled()
if(muzzled)
var/obj/item/clothing/mask/muzzle/M = wear_mask
if(M.mute == MUZZLE_MUTE_NONE)
muzzled = 0 //Not all muzzles block sound
if(!can_speak())
muzzled = 1
//var/m_type = 1
@@ -1390,7 +1390,7 @@
dna.species.create_organs(src)
for(var/thing in kept_items)
equip_to_slot_or_del(thing, kept_items[thing])
equip_to_slot_if_possible(thing, kept_items[thing], redraw_mob = 0)
//Handle default hair/head accessories for created mobs.
var/obj/item/organ/external/head/H = get_organ("head")
@@ -1677,6 +1677,12 @@ Eyes need to have significantly high darksight to shine unless the mob has the X
else
return FALSE
/mob/living/carbon/human/has_mutated_organs()
for(var/obj/item/organ/external/E in bodyparts)
if(E.status & ORGAN_MUTATED)
return TRUE
return FALSE
/mob/living/carbon/human/InCritical()
return (health <= config.health_threshold_crit && stat == UNCONSCIOUS)
@@ -88,21 +88,21 @@
return amount
/mob/living/carbon/human/adjustBruteLoss(amount, damage_source)
/mob/living/carbon/human/adjustBruteLoss(amount, damage_source, robotic=0)
if(dna.species)
amount = amount * dna.species.brute_mod
if(amount > 0)
take_overall_damage(amount, 0, used_weapon = damage_source)
else
heal_overall_damage(-amount, 0)
heal_overall_damage(-amount, 0, 0, robotic)
/mob/living/carbon/human/adjustFireLoss(amount, damage_source)
/mob/living/carbon/human/adjustFireLoss(amount, damage_source, robotic=0)
if(dna.species)
amount = amount * dna.species.burn_mod
if(amount > 0)
take_overall_damage(0, amount, used_weapon = damage_source)
else
heal_overall_damage(0, -amount)
heal_overall_damage(0, -amount, 0, robotic)
/mob/living/carbon/human/proc/adjustBruteLossByPart(amount, organ_name, obj/damage_source = null)
if(dna.species)
@@ -178,7 +178,7 @@ emp_act
/mob/living/carbon/human/grabbedby(mob/living/user)
if(w_uniform)
w_uniform.add_fingerprint(user)
..()
return ..()
//Returns 1 if the attack hit, 0 if it missed.
/mob/living/carbon/human/attacked_by(obj/item/I, mob/living/user, def_zone)
@@ -630,7 +630,7 @@
var/obj/item/reagent_containers/food/snacks/newSnack = new chosenType(get_turf(src))
TARGET = newSnack
newSnack.reagents.remove_any((newSnack.reagents.total_volume/2)-1)
newSnack.name = "Synthetic [newSnack.name]"
newSnack.name = "synthetic [newSnack.name]"
custom_emote(2, "[pick("gibbers","drools","slobbers","claps wildly","spits")] as [p_they()] vomit[p_s()] [newSnack] from [p_their()] mouth!")
catch(var/exception/e)
log_runtime(e, src, "Caught in SNPC cooking module")
@@ -581,7 +581,7 @@
saveVoice()
..()
/mob/living/carbon/human/interactive/hear_say(message, verb = "says", datum/language/language = null, alt_name = "", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol)
/mob/living/carbon/human/interactive/hear_say(message, verb = "says", datum/language/language = null, italics = 0, mob/speaker = null, sound/speech_sound, sound_vol)
if(!istype(speaker, /mob/living/carbon/human/interactive))
knownStrings |= html_decode(message)
..()
+6 -6
View File
@@ -1,10 +1,10 @@
/mob/living/carbon/human/say(var/message, var/sanitize = TRUE, var/ignore_speech_problems = FALSE, var/ignore_atmospherics = FALSE)
var/alt_name = ""
..(message, sanitize = sanitize, ignore_speech_problems = ignore_speech_problems, ignore_atmospherics = ignore_atmospherics) //ohgod we should really be passing a datum here.
/mob/living/carbon/human/GetAltName()
if(name != GetVoice())
alt_name = " (as [get_id_name("Unknown")])"
..(message, alt_name = alt_name, sanitize = sanitize, ignore_speech_problems = ignore_speech_problems, ignore_atmospherics = ignore_atmospherics) //ohgod we should really be passing a datum here.
return " (as [get_id_name("Unknown")])"
return ..()
/mob/living/carbon/human/proc/forcesay(list/append)
if(stat == CONSCIOUS)
@@ -160,7 +160,7 @@
returns[3] = speech_problem_flag
return returns
/mob/living/carbon/human/handle_message_mode(var/message_mode, var/message, var/verb, var/speaking, var/used_radios, var/alt_name)
/mob/living/carbon/human/handle_message_mode(var/message_mode, var/message, var/verb, var/speaking, var/used_radios)
switch(message_mode)
if("intercom")
for(var/obj/item/radio/intercom/I in view(1, src))
@@ -203,7 +203,7 @@
R.talk_into(src, message, null, verb, speaking)
if("whisper")
whisper_say(message, speaking, alt_name)
whisper_say(message, speaking)
return 1
else
if(message_mode)

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