April sync (#360)

* Maps and things no code/icons

* helpers defines globalvars

* Onclick world.dm orphaned_procs

* subsystems

Round vote and shuttle autocall done here too

* datums

* Game folder

* Admin - chatter modules

* clothing - mining

* modular computers - zambies

* client

* mob level 1

* mob stage 2 + simple_animal

* silicons n brains

* mob stage 3 + Alien/Monkey

* human mobs

* icons updated

* some sounds

* emitter y u no commit

* update tgstation.dme

* compile fixes

* travis fixes

Also removes Fast digest mode, because reasons.

* tweaks for travis Mentors are broke again

Also fixes Sizeray guns

* oxygen loss fix for vore code.

* removes unused code

* some code updates

* bulk fixes

* further fixes

* outside things

* whoops.

* Maint bar ported

* GLOBs.
This commit is contained in:
Poojawa
2017-04-13 23:37:00 -05:00
committed by GitHub
parent cdc32c98fa
commit 7e9b96a00f
1322 changed files with 174827 additions and 23888 deletions
-5
View File
@@ -1,5 +0,0 @@
/mob/dead/dust() //ghosts can't be vaporised.
return
/mob/dead/gib() //ghosts can't be gibbed.
return
+6 -6
View File
@@ -6,11 +6,11 @@
..()
if(join_motd)
to_chat(src, "<div class=\"motd\">[join_motd]</div>")
if(GLOB.join_motd)
to_chat(src, "<div class=\"motd\">[GLOB.join_motd]</div>")
if(admin_notice)
to_chat(src, "<span class='notice'><b>Admin Notice:</b>\n \t [admin_notice]</span>")
if(GLOB.admin_notice)
to_chat(src, "<span class='notice'><b>Admin Notice:</b>\n \t [GLOB.admin_notice]</span>")
if(config.soft_popcap && living_player_count() >= config.soft_popcap)
to_chat(src, "<span class='notice'><b>Server Notice:</b>\n \t [config.soft_popcap_message]</span>")
@@ -28,5 +28,5 @@
*/
new_player_panel()
client.playtitlemusic()
if(ticker.current_state < GAME_STATE_SETTING_UP)
to_chat(src, "Please set up your character and select \"Ready\". The game will start in about [round(ticker.GetTimeLeft(), 1)/10] seconds.")
if(SSticker.current_state < GAME_STATE_SETTING_UP)
to_chat(src, "Please set up your character and select \"Ready\". The game will start in about [round(SSticker.GetTimeLeft(), 1)/10] seconds.")
+38 -38
View File
@@ -20,14 +20,14 @@
stack_trace("Warning: [src]([type]) initialized multiple times!")
initialized = TRUE
tag = "mob_[next_mob_id++]"
mob_list += src
GLOB.mob_list += src
if(client && ticker.state == GAME_STATE_STARTUP)
if(client && SSticker.state == GAME_STATE_STARTUP)
var/obj/screen/splash/S = new(client, TRUE, TRUE)
S.Fade(TRUE)
if(length(newplayer_start))
loc = pick(newplayer_start)
if(length(GLOB.newplayer_start))
loc = pick(GLOB.newplayer_start)
else
loc = locate(1,1,1)
@@ -35,7 +35,7 @@
var/output = "<center><p><a href='byond://?src=\ref[src];show_preferences=1'>Setup Character</A></p>"
if(!ticker || ticker.current_state <= GAME_STATE_PREGAME)
if(!SSticker || SSticker.current_state <= GAME_STATE_PREGAME)
if(ready)
output += "<p>\[ <b>Ready</b> | <a href='byond://?src=\ref[src];ready=0'>Not Ready</a> \]</p>"
else
@@ -48,11 +48,11 @@
output += "<p><a href='byond://?src=\ref[src];observe=1'>Observe</A></p>"
if(!IsGuestKey(src.key))
if (dbcon.Connect())
if (GLOB.dbcon.Connect())
var/isadmin = 0
if(src.client && src.client.holder)
isadmin = 1
var/DBQuery/query_get_new_polls = dbcon.NewQuery("SELECT id FROM [format_table_name("poll_question")] WHERE [(isadmin ? "" : "adminonly = false AND")] Now() BETWEEN starttime AND endtime AND id NOT IN (SELECT pollid FROM [format_table_name("poll_vote")] WHERE ckey = \"[ckey]\") AND id NOT IN (SELECT pollid FROM [format_table_name("poll_textreply")] WHERE ckey = \"[ckey]\")")
var/DBQuery/query_get_new_polls = GLOB.dbcon.NewQuery("SELECT id FROM [format_table_name("poll_question")] WHERE [(isadmin ? "" : "adminonly = false AND")] Now() BETWEEN starttime AND endtime AND id NOT IN (SELECT pollid FROM [format_table_name("poll_vote")] WHERE ckey = \"[ckey]\") AND id NOT IN (SELECT pollid FROM [format_table_name("poll_textreply")] WHERE ckey = \"[ckey]\")")
if(!query_get_new_polls.Execute())
return
var/newpoll = 0
@@ -77,18 +77,18 @@
..()
if(statpanel("Lobby"))
stat("Game Mode:", (ticker.hide_mode) ? "Secret" : "[master_mode]")
stat("Game Mode:", (SSticker.hide_mode) ? "Secret" : "[GLOB.master_mode]")
stat("Map:", SSmapping.config.map_name)
if(ticker.current_state == GAME_STATE_PREGAME)
var/time_remaining = ticker.GetTimeLeft()
if(SSticker.current_state == GAME_STATE_PREGAME)
var/time_remaining = SSticker.GetTimeLeft()
if(time_remaining >= 0)
time_remaining /= 10
stat("Time To Start:", (time_remaining >= 0) ? "[round(time_remaining)]s" : "DELAYED")
stat("Players:", "[ticker.totalPlayers]")
stat("Players:", "[SSticker.totalPlayers]")
if(client.holder)
stat("Players Ready:", "[ticker.totalPlayersReady]")
stat("Players Ready:", "[SSticker.totalPlayersReady]")
/mob/dead/new_player/Topic(href, href_list[])
@@ -110,7 +110,7 @@
return 1
if(href_list["ready"])
if(!ticker || ticker.current_state <= GAME_STATE_PREGAME) // Make sure we don't ready up after the round has started
if(!SSticker || SSticker.current_state <= GAME_STATE_PREGAME) // Make sure we don't ready up after the round has started
ready = text2num(href_list["ready"])
if(href_list["refresh"])
@@ -141,14 +141,14 @@
observer.real_name = observer.client.prefs.real_name
observer.name = observer.real_name
observer.update_icon()
observer.stopLobbySound()
observer.stop_sound_channel(CHANNEL_LOBBYMUSIC)
qdel(mind)
qdel(src)
return 1
if(href_list["late_join"])
if(!ticker || ticker.current_state != GAME_STATE_PLAYING)
if(!SSticker || SSticker.current_state != GAME_STATE_PLAYING)
to_chat(usr, "<span class='danger'>The round is either not ready, or has already finished...</span>")
return
@@ -156,17 +156,17 @@
LateChoices()
return
if(ticker.queued_players.len || (relevant_cap && living_player_count() >= relevant_cap && !(ckey(key) in admin_datums)))
if(SSticker.queued_players.len || (relevant_cap && living_player_count() >= relevant_cap && !(ckey(key) in GLOB.admin_datums)))
to_chat(usr, "<span class='danger'>[config.hard_popcap_message]</span>")
var/queue_position = ticker.queued_players.Find(usr)
var/queue_position = SSticker.queued_players.Find(usr)
if(queue_position == 1)
to_chat(usr, "<span class='notice'>You are next in line to join the game. You will be notified when a slot opens up.</span>")
else if(queue_position)
to_chat(usr, "<span class='notice'>There are [queue_position-1] players in front of you in the queue to join the game.</span>")
else
ticker.queued_players += usr
to_chat(usr, "<span class='notice'>You have been added to the queue to join the game. Your position in queue is [ticker.queued_players.len].</span>")
SSticker.queued_players += usr
to_chat(usr, "<span class='notice'>You have been added to the queue to join the game. Your position in queue is [SSticker.queued_players.len].</span>")
return
LateChoices()
@@ -175,12 +175,12 @@
if(href_list["SelectedJob"])
if(!enter_allowed)
if(!GLOB.enter_allowed)
to_chat(usr, "<span class='notice'>There is an administrative lock on entering the game!</span>")
return
if(ticker.queued_players.len && !(ckey(key) in admin_datums))
if((living_player_count() >= relevant_cap) || (src != ticker.queued_players[1]))
if(SSticker.queued_players.len && !(ckey(key) in GLOB.admin_datums))
if((living_player_count() >= relevant_cap) || (src != SSticker.queued_players[1]))
to_chat(usr, "<span class='warning'>Server is full.</span>")
return
@@ -303,7 +303,7 @@
alert(src, "[rank] is not available. Please try another.")
return 0
if(ticker.late_join_disabled)
if(SSticker.late_join_disabled)
alert(src, "An administrator has disabled late join spawning.")
return FALSE
@@ -314,8 +314,8 @@
return FALSE
//Remove the player from the join queue if he was in one and reset the timer
ticker.queued_players -= src
ticker.queue_delay = 4
SSticker.queued_players -= src
SSticker.queue_delay = 4
SSjob.AssignRole(src, rank, 1)
@@ -325,8 +325,8 @@
character = equip
var/D
if(latejoin.len)
D = get_turf(pick(latejoin))
if(GLOB.latejoin.len)
D = get_turf(pick(GLOB.latejoin))
if(!D)
for(var/turf/T in get_area_turfs(/area/shuttle/arrival))
if(!T.density)
@@ -346,46 +346,46 @@
if(chair)
chair.buckle_mob(character)
ticker.minds += character.mind
SSticker.minds += character.mind
var/mob/living/carbon/human/humanc
if(ishuman(character))
humanc = character //Let's retypecast the var to be human,
if(humanc) //These procs all expect humans
data_core.manifest_inject(humanc)
GLOB.data_core.manifest_inject(humanc)
if(SSshuttle.arrivals)
SSshuttle.arrivals.QueueAnnounce(humanc, rank)
else
AnnounceArrival(humanc, rank)
AddEmploymentContract(humanc)
if(highlander)
if(GLOB.highlander)
to_chat(humanc, "<span class='userdanger'><i>THERE CAN BE ONLY ONE!!!</i></span>")
humanc.make_scottish()
joined_player_list += character.ckey
GLOB.joined_player_list += character.ckey
if(config.allow_latejoin_antagonists && humanc) //Borgs aren't allowed to be antags. Will need to be tweaked if we get true latejoin ais.
if(SSshuttle.emergency)
switch(SSshuttle.emergency.mode)
if(SHUTTLE_RECALL, SHUTTLE_IDLE)
ticker.mode.make_antag_chance(humanc)
SSticker.mode.make_antag_chance(humanc)
if(SHUTTLE_CALL)
if(SSshuttle.emergency.timeLeft(1) > initial(SSshuttle.emergencyCallTime)*0.5)
ticker.mode.make_antag_chance(humanc)
SSticker.mode.make_antag_chance(humanc)
qdel(src)
/mob/dead/new_player/proc/AddEmploymentContract(mob/living/carbon/human/employee)
//TODO: figure out a way to exclude wizards/nukeops/demons from this.
sleep(30)
for(var/C in employmentCabinets)
for(var/C in GLOB.employmentCabinets)
var/obj/structure/filingcabinet/employment/employmentCabinet = C
if(!employmentCabinet.virgin)
employmentCabinet.addFile(employee)
/mob/dead/new_player/proc/LateChoices()
var/mills = world.time - round_start_time // 1/10 of a second, not real milliseconds but whatever
var/mills = world.time - SSticker.round_start_time // 1/10 of a second, not real milliseconds but whatever
//var/secs = ((mills % 36000) % 600) / 10 //Not really needed, but I'll leave it here for refrence.. or something
var/mins = (mills % 36000) / 600
var/hours = mills / 36000
@@ -425,7 +425,7 @@
if (job_count > round(available_job_count / 2))
dat += "</div><div class='jobsColumn'>"
var/position_class = "otherPosition"
if (job.title in command_positions)
if (job.title in GLOB.command_positions)
position_class = "commandPosition"
dat += "<a class='[position_class]' href='byond://?src=\ref[src];SelectedJob=[job.title]'>[job.title] ([job.current_positions])</a><br>"
if(!job_count) //if there's nowhere to go, assistant opens up.
@@ -471,12 +471,12 @@
. = new_character
if(.)
new_character.key = key //Manually transfer the key to log them in
new_character.stopLobbySound()
new_character.stop_sound_channel(CHANNEL_LOBBYMUSIC)
/mob/dead/new_player/proc/ViewManifest()
var/dat = "<html><body>"
dat += "<h4>Crew Manifest</h4>"
dat += data_core.get_manifest(OOC = 1)
dat += GLOB.data_core.get_manifest(OOC = 1)
src << browse(dat, "window=manifest;size=387x420;can_close=1")
+32 -32
View File
@@ -3,10 +3,10 @@
var/optiontext
/mob/dead/new_player/proc/handle_player_polling()
if(!dbcon.IsConnected())
if(!GLOB.dbcon.IsConnected())
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
return
var/DBQuery/query_poll_get = dbcon.NewQuery("SELECT id, question FROM [format_table_name("poll_question")] WHERE Now() BETWEEN starttime AND endtime [(client.holder ? "" : "AND adminonly = false")]")
var/DBQuery/query_poll_get = GLOB.dbcon.NewQuery("SELECT id, question FROM [format_table_name("poll_question")] WHERE Now() BETWEEN starttime AND endtime [(client.holder ? "" : "AND adminonly = false")]")
if(!query_poll_get.warn_execute())
return
var/output = "<div align='center'><B>Player polls</B><hr><table>"
@@ -22,10 +22,10 @@
/mob/dead/new_player/proc/poll_player(pollid)
if(!pollid)
return
if (!dbcon.Connect())
if (!GLOB.dbcon.Connect())
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
return
var/DBQuery/query_poll_get_details = dbcon.NewQuery("SELECT starttime, endtime, question, polltype, multiplechoiceoptions FROM [format_table_name("poll_question")] WHERE id = [pollid]")
var/DBQuery/query_poll_get_details = GLOB.dbcon.NewQuery("SELECT starttime, endtime, question, polltype, multiplechoiceoptions FROM [format_table_name("poll_question")] WHERE id = [pollid]")
if(!query_poll_get_details.warn_execute())
return
var/pollstarttime = ""
@@ -41,14 +41,14 @@
multiplechoiceoptions = text2num(query_poll_get_details.item[5])
switch(polltype)
if(POLLTYPE_OPTION)
var/DBQuery/query_option_get_votes = dbcon.NewQuery("SELECT optionid FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'")
var/DBQuery/query_option_get_votes = GLOB.dbcon.NewQuery("SELECT optionid FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'")
if(!query_option_get_votes.warn_execute())
return
var/votedoptionid = 0
if(query_option_get_votes.NextRow())
votedoptionid = text2num(query_option_get_votes.item[1])
var/list/datum/polloption/options = list()
var/DBQuery/query_option_options = dbcon.NewQuery("SELECT id, text FROM [format_table_name("poll_option")] WHERE pollid = [pollid]")
var/DBQuery/query_option_options = GLOB.dbcon.NewQuery("SELECT id, text FROM [format_table_name("poll_option")] WHERE pollid = [pollid]")
if(!query_option_options.warn_execute())
return
while(query_option_options.NextRow())
@@ -82,7 +82,7 @@
src << browse(null ,"window=playerpolllist")
src << browse(output,"window=playerpoll;size=500x250")
if(POLLTYPE_TEXT)
var/DBQuery/query_text_get_votes = dbcon.NewQuery("SELECT replytext FROM [format_table_name("poll_textreply")] WHERE pollid = [pollid] AND ckey = '[ckey]'")
var/DBQuery/query_text_get_votes = GLOB.dbcon.NewQuery("SELECT replytext FROM [format_table_name("poll_textreply")] WHERE pollid = [pollid] AND ckey = '[ckey]'")
if(!query_text_get_votes.warn_execute())
return
var/vote_text = ""
@@ -111,7 +111,7 @@
src << browse(null ,"window=playerpolllist")
src << browse(output,"window=playerpoll;size=500x500")
if(POLLTYPE_RATING)
var/DBQuery/query_rating_get_votes = dbcon.NewQuery("SELECT o.text, v.rating FROM [format_table_name("poll_option")] o, [format_table_name("poll_vote")] v WHERE o.pollid = [pollid] AND v.ckey = '[ckey]' AND o.id = v.optionid")
var/DBQuery/query_rating_get_votes = GLOB.dbcon.NewQuery("SELECT o.text, v.rating FROM [format_table_name("poll_option")] o, [format_table_name("poll_vote")] v WHERE o.pollid = [pollid] AND v.ckey = '[ckey]' AND o.id = v.optionid")
if(!query_rating_get_votes.warn_execute())
return
var/output = "<div align='center'><B>Player poll</B><hr>"
@@ -129,7 +129,7 @@
output += "<input type='hidden' name='votetype' value=[POLLTYPE_RATING]>"
var/minid = 999999
var/maxid = 0
var/DBQuery/query_rating_options = dbcon.NewQuery("SELECT id, text, minval, maxval, descmin, descmid, descmax FROM [format_table_name("poll_option")] WHERE pollid = [pollid]")
var/DBQuery/query_rating_options = GLOB.dbcon.NewQuery("SELECT id, text, minval, maxval, descmin, descmid, descmax FROM [format_table_name("poll_option")] WHERE pollid = [pollid]")
if(!query_rating_options.warn_execute())
return
while(query_rating_options.NextRow())
@@ -163,7 +163,7 @@
src << browse(null ,"window=playerpolllist")
src << browse(output,"window=playerpoll;size=500x500")
if(POLLTYPE_MULTI)
var/DBQuery/query_multi_get_votes = dbcon.NewQuery("SELECT optionid FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'")
var/DBQuery/query_multi_get_votes = GLOB.dbcon.NewQuery("SELECT optionid FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'")
if(!query_multi_get_votes.warn_execute())
return
var/list/votedfor = list()
@@ -172,7 +172,7 @@
var/list/datum/polloption/options = list()
var/maxoptionid = 0
var/minoptionid = 0
var/DBQuery/query_multi_options = dbcon.NewQuery("SELECT id, text FROM [format_table_name("poll_option")] WHERE pollid = [pollid]")
var/DBQuery/query_multi_options = GLOB.dbcon.NewQuery("SELECT id, text FROM [format_table_name("poll_option")] WHERE pollid = [pollid]")
if(!query_multi_options.warn_execute())
return
while(query_multi_options.NextRow())
@@ -214,7 +214,7 @@
var/datum/asset/irv_assets = get_asset_datum(/datum/asset/simple/IRV)
irv_assets.send(src)
var/DBQuery/query_irv_get_votes = dbcon.NewQuery("SELECT optionid FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'")
var/DBQuery/query_irv_get_votes = GLOB.dbcon.NewQuery("SELECT optionid FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'")
if(!query_irv_get_votes.warn_execute())
return
@@ -224,7 +224,7 @@
var/list/datum/polloption/options = list()
var/DBQuery/query_irv_options = dbcon.NewQuery("SELECT id, text FROM [format_table_name("poll_option")] WHERE pollid = [pollid]")
var/DBQuery/query_irv_options = GLOB.dbcon.NewQuery("SELECT id, text FROM [format_table_name("poll_option")] WHERE pollid = [pollid]")
if(!query_irv_options.warn_execute())
return
while(query_irv_options.NextRow())
@@ -327,10 +327,10 @@
var/table = "poll_vote"
if (text)
table = "poll_textreply"
if (!dbcon.Connect())
if (!GLOB.dbcon.Connect())
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
return
var/DBQuery/query_hasvoted = dbcon.NewQuery("SELECT id FROM `[format_table_name(table)]` WHERE pollid = [pollid] AND ckey = '[ckey]'")
var/DBQuery/query_hasvoted = GLOB.dbcon.NewQuery("SELECT id FROM `[format_table_name(table)]` WHERE pollid = [pollid] AND ckey = '[ckey]'")
if(!query_hasvoted.warn_execute())
return
if(query_hasvoted.NextRow())
@@ -355,14 +355,14 @@
return 1
/mob/dead/new_player/proc/vote_valid_check(pollid, holder, type)
if (!dbcon.Connect())
if (!GLOB.dbcon.Connect())
to_chat(src, "<span class='danger'>Failed to establish database connection.</span>")
return 0
pollid = text2num(pollid)
if (!pollid || pollid < 0)
return 0
//validate the poll is actually the right type of poll and its still active
var/DBQuery/query_validate_poll = dbcon.NewQuery("SELECT id FROM [format_table_name("poll_question")] WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime AND polltype = '[type]' [(holder ? "" : "AND adminonly = false")]")
var/DBQuery/query_validate_poll = GLOB.dbcon.NewQuery("SELECT id FROM [format_table_name("poll_question")] WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime AND polltype = '[type]' [(holder ? "" : "AND adminonly = false")]")
if(!query_validate_poll.warn_execute())
return 0
if (!query_validate_poll.NextRow())
@@ -370,7 +370,7 @@
return 1
/mob/dead/new_player/proc/vote_on_irv_poll(pollid, list/votelist)
if (!dbcon.Connect())
if (!GLOB.dbcon.Connect())
to_chat(src, "<span class='danger'>Failed to establish database connection.</span>")
return 0
if (!vote_rig_check())
@@ -395,7 +395,7 @@
return 0
//lets collect the options
var/DBQuery/query_irv_id = dbcon.NewQuery("SELECT id FROM [format_table_name("poll_option")] WHERE pollid = [pollid]")
var/DBQuery/query_irv_id = GLOB.dbcon.NewQuery("SELECT id FROM [format_table_name("poll_option")] WHERE pollid = [pollid]")
if(!query_irv_id.warn_execute())
return 0
var/list/optionlist = list()
@@ -426,12 +426,12 @@
sqlrowlist += "(Now(), [pollid], [vote], '[sanitizeSQL(ckey)]', INET_ATON('[sanitizeSQL(address)]'), '[sanitizeSQL(rank)]')"
//now lets delete their old votes (if any)
var/DBQuery/query_irv_del_old = dbcon.NewQuery("DELETE FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'")
var/DBQuery/query_irv_del_old = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'")
if(!query_irv_del_old.warn_execute())
return 0
//now to add the new ones.
var/DBQuery/query_irv_vote = dbcon.NewQuery("INSERT INTO [format_table_name("poll_vote")] (datetime, pollid, optionid, ckey, ip, adminrank) VALUES [sqlrowlist]")
var/DBQuery/query_irv_vote = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("poll_vote")] (datetime, pollid, optionid, ckey, ip, adminrank) VALUES [sqlrowlist]")
if(!query_irv_vote.warn_execute())
return 0
src << browse(null,"window=playerpoll")
@@ -439,7 +439,7 @@
/mob/dead/new_player/proc/vote_on_poll(pollid, optionid)
if (!dbcon.Connect())
if (!GLOB.dbcon.Connect())
to_chat(src, "<span class='danger'>Failed to establish database connection.</span>")
return 0
if (!vote_rig_check())
@@ -452,14 +452,14 @@
var/adminrank = sanitizeSQL(poll_check_voted(pollid))
if(!adminrank)
return
var/DBQuery/query_option_vote = dbcon.NewQuery("INSERT INTO [format_table_name("poll_vote")] (datetime, pollid, optionid, ckey, ip, adminrank) VALUES (Now(), [pollid], [optionid], '[ckey]', INET_ATON('[client.address]'), '[adminrank]')")
var/DBQuery/query_option_vote = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("poll_vote")] (datetime, pollid, optionid, ckey, ip, adminrank) VALUES (Now(), [pollid], [optionid], '[ckey]', INET_ATON('[client.address]'), '[adminrank]')")
if(!query_option_vote.warn_execute())
return
usr << browse(null,"window=playerpoll")
return 1
/mob/dead/new_player/proc/log_text_poll_reply(pollid, replytext)
if (!dbcon.Connect())
if (!GLOB.dbcon.Connect())
to_chat(src, "<span class='danger'>Failed to establish database connection.</span>")
return 0
if (!vote_rig_check())
@@ -479,14 +479,14 @@
if(!(length(replytext) > 0) || !(length(replytext) <= 8000))
to_chat(usr, "The text you entered was invalid or too long. Please correct the text and submit again.")
return
var/DBQuery/query_text_vote = dbcon.NewQuery("INSERT INTO [format_table_name("poll_textreply")] (datetime ,pollid ,ckey ,ip ,replytext ,adminrank) VALUES (Now(), [pollid], '[ckey]', INET_ATON('[client.address]'), '[replytext]', '[adminrank]')")
var/DBQuery/query_text_vote = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("poll_textreply")] (datetime ,pollid ,ckey ,ip ,replytext ,adminrank) VALUES (Now(), [pollid], '[ckey]', INET_ATON('[client.address]'), '[replytext]', '[adminrank]')")
if(!query_text_vote.warn_execute())
return
usr << browse(null,"window=playerpoll")
return 1
/mob/dead/new_player/proc/vote_on_numval_poll(pollid, optionid, rating)
if (!dbcon.Connect())
if (!GLOB.dbcon.Connect())
to_chat(src, "<span class='danger'>Failed to establish database connection.</span>")
return 0
if (!vote_rig_check())
@@ -496,7 +496,7 @@
//validate the poll
if (!vote_valid_check(pollid, client.holder, POLLTYPE_RATING))
return 0
var/DBQuery/query_numval_hasvoted = dbcon.NewQuery("SELECT id FROM [format_table_name("poll_vote")] WHERE optionid = [optionid] AND ckey = '[ckey]'")
var/DBQuery/query_numval_hasvoted = GLOB.dbcon.NewQuery("SELECT id FROM [format_table_name("poll_vote")] WHERE optionid = [optionid] AND ckey = '[ckey]'")
if(!query_numval_hasvoted.warn_execute())
return
if(query_numval_hasvoted.NextRow())
@@ -506,14 +506,14 @@
if(client.holder)
adminrank = client.holder.rank.name
adminrank = sanitizeSQL(adminrank)
var/DBQuery/query_numval_vote = dbcon.NewQuery("INSERT INTO [format_table_name("poll_vote")] (datetime ,pollid ,optionid ,ckey ,ip ,adminrank, rating) VALUES (Now(), [pollid], [optionid], '[ckey]', INET_ATON('[client.address]'), '[adminrank]', [(isnull(rating)) ? "null" : rating])")
var/DBQuery/query_numval_vote = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("poll_vote")] (datetime ,pollid ,optionid ,ckey ,ip ,adminrank, rating) VALUES (Now(), [pollid], [optionid], '[ckey]', INET_ATON('[client.address]'), '[adminrank]', [(isnull(rating)) ? "null" : rating])")
if(!query_numval_vote.warn_execute())
return
usr << browse(null,"window=playerpoll")
return 1
/mob/dead/new_player/proc/vote_on_multi_poll(pollid, optionid)
if (!dbcon.Connect())
if (!GLOB.dbcon.Connect())
to_chat(src, "<span class='danger'>Failed to establish database connection.</span>")
return 0
if (!vote_rig_check())
@@ -523,13 +523,13 @@
//validate the poll
if (!vote_valid_check(pollid, client.holder, POLLTYPE_MULTI))
return 0
var/DBQuery/query_multi_choicelen = dbcon.NewQuery("SELECT multiplechoiceoptions FROM [format_table_name("poll_question")] WHERE id = [pollid]")
var/DBQuery/query_multi_choicelen = GLOB.dbcon.NewQuery("SELECT multiplechoiceoptions FROM [format_table_name("poll_question")] WHERE id = [pollid]")
if(!query_multi_choicelen.warn_execute())
return 1
var/i
if(query_multi_choicelen.NextRow())
i = text2num(query_multi_choicelen.item[1])
var/DBQuery/query_multi_hasvoted = dbcon.NewQuery("SELECT id FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'")
var/DBQuery/query_multi_hasvoted = GLOB.dbcon.NewQuery("SELECT id FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'")
if(!query_multi_hasvoted.warn_execute())
return 1
while(i)
@@ -543,7 +543,7 @@
if(client.holder)
adminrank = client.holder.rank.name
adminrank = sanitizeSQL(adminrank)
var/DBQuery/query_multi_vote = dbcon.NewQuery("INSERT INTO [format_table_name("poll_vote")] (datetime, pollid, optionid, ckey, ip, adminrank) VALUES (Now(), [pollid], [optionid], '[ckey]', INET_ATON('[client.address]'), '[adminrank]')")
var/DBQuery/query_multi_vote = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("poll_vote")] (datetime, pollid, optionid, ckey, ip, adminrank) VALUES (Now(), [pollid], [optionid], '[ckey]', INET_ATON('[client.address]'), '[adminrank]')")
if(!query_multi_vote.warn_execute())
return 1
usr << browse(null,"window=playerpoll")
@@ -26,7 +26,7 @@
// Silicons only need a very basic preview since there is no customization for them.
if(job_engsec_high)
switch(job_engsec_high)
if(AI)
if(AI_JF)
preview_icon = icon('icons/mob/AI.dmi', "AI", SOUTH)
preview_icon.Scale(64, 64)
return
@@ -812,7 +812,7 @@
gender = FEMALE
/datum/sprite_accessory/undershirt/lover
name = "Lover shirt"
name = "Lover Shirt"
icon_state = "lover"
gender = NEUTER
+2 -1
View File
@@ -1,6 +1,7 @@
/mob/dead/observer/Logout()
if (client)
client.images -= ghost_darkness_images
client.images -= (GLOB.ghost_images_default+GLOB.ghost_images_simple)
if(observetarget)
if(ismob(observetarget))
var/mob/target = observetarget
+71 -88
View File
@@ -1,9 +1,7 @@
var/list/image/ghost_darkness_images = list() //this is a list of images for things ghosts should still be able to see when they toggle darkness, BUT NOT THE GHOSTS THEMSELVES!
var/list/image/ghost_images_full = list() //this is a list of full images of the ghosts themselves
var/list/image/ghost_images_default = list() //this is a list of the default (non-accessorized, non-dir) images of the ghosts themselves
var/list/image/ghost_images_simple = list() //this is a list of all ghost images as the simple white ghost
GLOBAL_LIST_EMPTY(ghost_images_default) //this is a list of the default (non-accessorized, non-dir) images of the ghosts themselves
GLOBAL_LIST_EMPTY(ghost_images_simple) //this is a list of all ghost images as the simple white ghost
var/global/static/observer_default_invisibility = INVISIBILITY_OBSERVER
GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
/mob/dead/observer
name = "ghost"
@@ -19,8 +17,6 @@ var/global/static/observer_default_invisibility = INVISIBILITY_OBSERVER
see_invisible = SEE_INVISIBLE_OBSERVER
see_in_dark = 100
invisibility = INVISIBILITY_OBSERVER
languages_spoken = ALL
languages_understood = ALL
var/can_reenter_corpse
var/datum/hud/living/carbon/hud = null // hud
var/bootime = 0
@@ -29,11 +25,9 @@ var/global/static/observer_default_invisibility = INVISIBILITY_OBSERVER
//Note that this is not a reliable way to determine if admins started as observers, since they change mobs a lot.
var/atom/movable/following = null
var/fun_verbs = 0
var/image/ghostimage = null //this mobs ghost image, for deleting and stuff
var/image/ghostimage_default = null //this mobs ghost image without accessories and dirs
var/image/ghostimage_simple = null //this mob with the simple white ghost sprite
var/ghostvision = 1 //is the ghost able to see things humans can't?
var/seedarkness = 1
var/mob/observetarget = null //The target mob that the ghost is observing. Used as a reference in logout()
var/ghost_hud_enabled = 1 //did this ghost disable the on-screen HUD?
var/data_huds_on = 0 //Are data HUDs currently enabled?
@@ -60,22 +54,24 @@ var/global/static/observer_default_invisibility = INVISIBILITY_OBSERVER
var/deadchat_name
/mob/dead/observer/Initialize()
invisibility = observer_default_invisibility
invisibility = GLOB.observer_default_invisibility
verbs += /mob/dead/observer/proc/dead_tele
if(config.cross_allowed)
verbs += /mob/dead/observer/proc/server_hop
ghostimage = image(src.icon,src,src.icon_state)
if(icon_state in ghost_forms_with_directions_list)
if(icon_state in GLOB.ghost_forms_with_directions_list)
ghostimage_default = image(src.icon,src,src.icon_state + "_nodir")
else
ghostimage_default = image(src.icon,src,src.icon_state)
ghostimage_default.override = TRUE
GLOB.ghost_images_default |= ghostimage_default
ghostimage_simple = image(src.icon,src,"ghost_nodir")
ghost_images_full |= ghostimage
ghost_images_default |= ghostimage_default
ghost_images_simple |= ghostimage_simple
ghostimage_simple.override = TRUE
GLOB.ghost_images_simple |= ghostimage_simple
updateallghostimages()
var/turf/T
@@ -123,6 +119,8 @@ var/global/static/observer_default_invisibility = INVISIBILITY_OBSERVER
verbs -= /mob/dead/observer/verb/possess
animate(src, pixel_y = 2, time = 10, loop = -1)
grant_all_languages()
..()
/mob/dead/observer/narsie_act()
@@ -137,16 +135,11 @@ var/global/static/observer_default_invisibility = INVISIBILITY_OBSERVER
animate(src, color = old_color, time = 10)
addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 10)
/mob/dead/observer/Destroy()
ghost_images_full -= ghostimage
qdel(ghostimage)
ghostimage = null
ghost_images_default -= ghostimage_default
GLOB.ghost_images_default -= ghostimage_default
qdel(ghostimage_default)
ghostimage_default = null
ghost_images_simple -= ghostimage_simple
GLOB.ghost_images_simple -= ghostimage_simple
qdel(ghostimage_simple)
ghostimage_simple = null
@@ -170,49 +163,44 @@ var/global/static/observer_default_invisibility = INVISIBILITY_OBSERVER
if(hair_image)
cut_overlay(hair_image)
ghostimage.add_overlay(hair_image)
hair_image = null
if(facial_hair_image)
cut_overlay(facial_hair_image)
ghostimage.add_overlay(facial_hair_image)
facial_hair_image = null
if(new_form)
icon_state = new_form
ghostimage.icon_state = new_form
if(icon_state in ghost_forms_with_directions_list)
if(icon_state in GLOB.ghost_forms_with_directions_list)
ghostimage_default.icon_state = new_form + "_nodir" //if this icon has dirs, the default ghostimage must use its nodir version or clients with the preference set to default sprites only will see the dirs
else
ghostimage_default.icon_state = new_form
if(ghost_accs >= GHOST_ACCS_DIR && icon_state in ghost_forms_with_directions_list) //if this icon has dirs AND the client wants to show them, we make sure we update the dir on movement
if(ghost_accs >= GHOST_ACCS_DIR && icon_state in GLOB.ghost_forms_with_directions_list) //if this icon has dirs AND the client wants to show them, we make sure we update the dir on movement
updatedir = 1
else
updatedir = 0 //stop updating the dir in case we want to show accessories with dirs on a ghost sprite without dirs
setDir(2 )//reset the dir to its default so the sprites all properly align up
if(ghost_accs == GHOST_ACCS_FULL && icon_state in ghost_forms_with_accessories_list) //check if this form supports accessories and if the client wants to show them
if(ghost_accs == GHOST_ACCS_FULL && icon_state in GLOB.ghost_forms_with_accessories_list) //check if this form supports accessories and if the client wants to show them
var/datum/sprite_accessory/S
if(facial_hair_style)
S = facial_hair_styles_list[facial_hair_style]
S = GLOB.facial_hair_styles_list[facial_hair_style]
if(S)
facial_hair_image = image("icon" = S.icon, "icon_state" = "[S.icon_state]", "layer" = -HAIR_LAYER)
if(facial_hair_color)
facial_hair_image.color = "#" + facial_hair_color
facial_hair_image.alpha = 200
add_overlay(facial_hair_image)
ghostimage.add_overlay(facial_hair_image)
if(hair_style)
S = hair_styles_list[hair_style]
S = GLOB.hair_styles_list[hair_style]
if(S)
hair_image = image("icon" = S.icon, "icon_state" = "[S.icon_state]", "layer" = -HAIR_LAYER)
if(hair_color)
hair_image.color = "#" + hair_color
hair_image.alpha = 200
add_overlay(hair_image)
ghostimage.add_overlay(hair_image)
/*
* Increase the brightness of a color by calculating the average distance between the R, G and B values,
@@ -310,14 +298,14 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/dead/observer/Stat()
..()
if(statpanel("Status"))
if(ticker && ticker.mode)
for(var/datum/gang/G in ticker.mode.gangs)
if(SSticker && SSticker.mode)
for(var/datum/gang/G in SSticker.mode.gangs)
if(G.is_dominating)
stat(null, "[G.name] Gang Takeover: [max(G.domination_time_remaining(), 0)]")
if(istype(ticker.mode, /datum/game_mode/blob))
var/datum/game_mode/blob/B = ticker.mode
if(istype(SSticker.mode, /datum/game_mode/blob))
var/datum/game_mode/blob/B = SSticker.mode
if(B.message_sent)
stat(null, "Blobs to Blob Win: [blobs_legit.len]/[B.blobwincount]")
stat(null, "Blobs to Blob Win: [GLOB.blobs_legit.len]/[B.blobwincount]")
/mob/dead/observer/verb/reenter_corpse()
set category = "Ghost"
@@ -368,7 +356,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
to_chat(usr, "Not when you're not dead!")
return
var/A
A = input("Area to jump to", "BOOYEA", A) as null|anything in sortedAreas
A = input("Area to jump to", "BOOYEA", A) as null|anything in GLOB.sortedAreas
var/area/thearea = A
if(!thearea)
return
@@ -510,35 +498,42 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
set desc = "Toggles your ability to see things only ghosts can see, like other ghosts"
set category = "Ghost"
ghostvision = !(ghostvision)
updateghostsight()
update_sight()
to_chat(usr, "You [(ghostvision?"now":"no longer")] have ghost vision.")
/mob/dead/observer/verb/toggle_darkness()
set name = "Toggle Darkness"
set category = "Ghost"
seedarkness = !(seedarkness)
updateghostsight()
switch(lighting_alpha)
if (LIGHTING_PLANE_ALPHA_VISIBLE)
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
if (LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE)
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
if (LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE)
lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE
else
lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE
/mob/dead/observer/proc/updateghostsight()
update_sight()
/mob/dead/observer/update_sight()
if(client)
ghost_others = client.prefs.ghost_others //A quick update just in case this setting was changed right before calling the proc
if (seedarkness)
see_invisible = SEE_INVISIBLE_OBSERVER
if (!ghostvision || ghost_others <= GHOST_OTHERS_DEFAULT_SPRITE)
see_invisible = SEE_INVISIBLE_LIVING
if (!ghostvision)
see_invisible = SEE_INVISIBLE_LIVING
else
see_invisible = SEE_INVISIBLE_NOLIGHTING
see_invisible = SEE_INVISIBLE_OBSERVER
updateghostimages()
..()
/proc/updateallghostimages()
listclearnulls(ghost_images_full)
listclearnulls(ghost_images_default)
listclearnulls(ghost_images_simple)
listclearnulls(ghost_darkness_images)
listclearnulls(GLOB.ghost_images_default)
listclearnulls(GLOB.ghost_images_simple)
for (var/mob/dead/observer/O in player_list)
for (var/mob/dead/observer/O in GLOB.player_list)
O.updateghostimages()
/mob/dead/observer/proc/updateghostimages()
@@ -547,34 +542,19 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(lastsetting)
switch(lastsetting) //checks the setting we last came from, for a little efficiency so we don't try to delete images from the client that it doesn't have anyway
if(GHOST_OTHERS_THEIR_SETTING)
client.images -= ghost_images_full
if(GHOST_OTHERS_DEFAULT_SPRITE)
client.images -= ghost_images_default
client.images -= GLOB.ghost_images_default
if(GHOST_OTHERS_SIMPLE)
client.images -= ghost_images_simple
if ((seedarkness || !ghostvision) && client.prefs.ghost_others == GHOST_OTHERS_THEIR_SETTING)
client.images -= ghost_darkness_images
lastsetting = null
else if(ghostvision && (!seedarkness || client.prefs.ghost_others <= GHOST_OTHERS_DEFAULT_SPRITE))
//add images for the 60inv things ghosts can normally see when darkness is enabled so they can see them now
if(!lastsetting)
client.images |= ghost_darkness_images
client.images -= GLOB.ghost_images_simple
lastsetting = client.prefs.ghost_others
if(!ghostvision)
return
if(client.prefs.ghost_others != GHOST_OTHERS_THEIR_SETTING)
switch(client.prefs.ghost_others)
if(GHOST_OTHERS_THEIR_SETTING)
client.images |= ghost_images_full
if (ghostimage)
client.images -= ghostimage //remove ourself
if(GHOST_OTHERS_DEFAULT_SPRITE)
client.images |= ghost_images_default
if(ghostimage_default)
client.images -= ghostimage_default
client.images |= (GLOB.ghost_images_default-ghostimage_default)
if(GHOST_OTHERS_SIMPLE)
client.images |= ghost_images_simple
if(ghostimage_simple)
client.images -= ghostimage_simple
lastsetting = client.prefs.ghost_others
client.images |= (GLOB.ghost_images_simple-ghostimage_simple)
/mob/dead/observer/verb/possess()
set category = "Ghost"
@@ -582,8 +562,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
set desc= "Take over the body of a mindless creature!"
var/list/possessible = list()
for(var/mob/living/L in living_mob_list)
if(!(L in player_list) && !L.mind)
for(var/mob/living/L in GLOB.living_mob_list)
if(!(L in GLOB.player_list) && !L.mind)
possessible += L
var/mob/living/target = input("Your new life begins today!", "Possess Mob", null, null) as null|anything in possessible
@@ -595,7 +575,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
to_chat(src, "<span class='warning'>This creature is too powerful for you to possess!</span>")
return 0
if(can_reenter_corpse || (mind && mind.current))
if(can_reenter_corpse && mind && mind.current)
if(alert(src, "Your soul is still tied to your former life as [mind.current.name], if you go forward there is no going back to that life. Are you sure you wish to continue?", "Move On", "Yes", "No") == "No")
return 0
if(target.key)
@@ -631,7 +611,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/proc/show_server_hop_transfer_screen(expected_key)
//only show it to incoming ghosts
for(var/mob/dead/observer/O in player_list)
for(var/mob/dead/observer/O in GLOB.player_list)
if(O.key == expected_key)
if(O.client)
new /obj/screen/splash(O.client, TRUE)
@@ -652,7 +632,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
var/dat
dat += "<h4>Crew Manifest</h4>"
dat += data_core.get_manifest()
dat += GLOB.data_core.get_manifest()
src << browse(dat, "window=manifest;size=387x420;can_close=1")
@@ -692,12 +672,12 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/dead/observer/proc/show_data_huds()
for(var/hudtype in datahuds)
var/datum/atom_hud/H = huds[hudtype]
var/datum/atom_hud/H = GLOB.huds[hudtype]
H.add_hud_to(src)
/mob/dead/observer/proc/remove_data_huds()
for(var/hudtype in datahuds)
var/datum/atom_hud/H = huds[hudtype]
var/datum/atom_hud/H = GLOB.huds[hudtype]
H.remove_hud_from(src)
/mob/dead/observer/verb/toggle_data_huds()
@@ -742,7 +722,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
update_icon()
/mob/dead/observer/canUseTopic()
/mob/dead/observer/canUseTopic(atom/movable/AM,be_close = FALSE)
if(check_rights(R_ADMIN, 0))
return 1
return
@@ -754,11 +734,9 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
. = ..()
switch(var_name)
if("icon")
ghostimage.icon = icon
ghostimage_default.icon = icon
ghostimage_simple.icon = icon
if("icon_state")
ghostimage.icon_state = icon_state
ghostimage_default.icon_state = icon_state
ghostimage_simple.icon_state = icon_state
if("fun_verbs")
@@ -805,7 +783,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(mob_eye.hud_used)
LAZYINITLIST(mob_eye.observers)
mob_eye.observers |= src
mob_eye.hud_used.show_hud(1,src)
mob_eye.hud_used.show_hud(mob_eye.hud_used.hud_version, src)
observetarget = mob_eye
/mob/dead/observer/verb/register_pai_candidate()
@@ -826,9 +804,14 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(isobserver(user) && check_rights(R_SPAWN))
change_mob_type( /mob/living/carbon/human , null, null, TRUE) //always delmob, ghosts shouldn't be left lingering
/mob/dead/observer/examine(mob/user)
..()
if(!invisibility)
to_chat(user, "It seems extremely obvious.")
/proc/set_observer_default_invisibility(amount, message=null)
for(var/mob/dead/observer/G in player_list)
for(var/mob/dead/observer/G in GLOB.player_list)
G.invisibility = amount
if(message)
to_chat(G, message)
observer_default_invisibility = amount
GLOB.observer_default_invisibility = amount
+7 -4
View File
@@ -8,15 +8,18 @@
. = src.say_dead(message)
/mob/dead/observer/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans)
/mob/dead/observer/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
var/atom/movable/to_follow = speaker
if(radio_freq)
var/atom/movable/virtualspeaker/V = speaker
if(isAI(V.source))
var/mob/living/silicon/ai/S = V.source
speaker = S.eyeobj
to_follow = S.eyeobj
else
speaker = V.source
var/link = FOLLOW_LINK(src, speaker)
to_follow = V.source
var/link = FOLLOW_LINK(src, to_follow)
// Recompose the message, because it's scrambled by default
message = compose_message(speaker, message_language, raw_message, radio_freq, spans)
to_chat(src, "[link] [message]")
+10 -4
View File
@@ -280,14 +280,15 @@
//visibly unequips I but it is NOT MOVED AND REMAINS IN SRC
//item MUST BE FORCEMOVE'D OR QDEL'D
/mob/proc/temporarilyRemoveItemFromInventory(obj/item/I, force = FALSE)
return doUnEquip(I, force, null, TRUE)
/mob/proc/temporarilyRemoveItemFromInventory(obj/item/I, force = FALSE, idrop = TRUE)
return doUnEquip(I, force, null, TRUE, idrop)
//DO NOT CALL THIS PROC
//use one of the above 2 helper procs
//you may override it, but do not modify the args
/mob/proc/doUnEquip(obj/item/I, force, newloc, no_move) //Force overrides NODROP for things like wizarditis and admin undress.
/mob/proc/doUnEquip(obj/item/I, force, newloc, no_move, invdrop = TRUE) //Force overrides NODROP for things like wizarditis and admin undress.
//Use no_move if the item is just gonna be immediately moved afterward
//Invdrop is used to prevent stuff in pockets dropping. only set to false if it's going to immediately be replaced
if(!I) //If there's nothing to drop, the drop is automatically succesfull. If(unEquip) should generally be used to check for NODROP.
return TRUE
@@ -346,7 +347,12 @@
items += w_uniform
return items
/mob/living/proc/unequip_everything()
var/list/items = list()
items |= get_equipped_items()
for(var/I in items)
dropItemToGround(I)
drop_all_held_items()
/obj/item/proc/equip_to_best_slot(var/mob/M)
if(src != M.get_active_held_item())
+4 -6
View File
@@ -1,5 +1,3 @@
/obj/item/device/mmi
name = "Man-Machine Interface"
desc = "The Warrior's bland acronym, MMI, obscures the true horror of this monstrosity, that nevertheless has become standard-issue on Nanotrasen stations."
@@ -66,8 +64,8 @@
brainmob.container = src
if(!newbrain.damaged_brain) // the brain organ hasn't been beaten to death.
brainmob.stat = CONSCIOUS //we manually revive the brain mob
dead_mob_list -= brainmob
living_mob_list += brainmob
GLOB.dead_mob_list -= brainmob
GLOB.living_mob_list += brainmob
brainmob.reset_perspective()
brain = newbrain
@@ -99,8 +97,8 @@
brainmob.stat = DEAD
brainmob.emp_damage = 0
brainmob.reset_perspective() //so the brainmob follows the brain organ instead of the mmi. And to update our vision
living_mob_list -= brainmob //Get outta here
dead_mob_list += brainmob
GLOB.living_mob_list -= brainmob //Get outta here
GLOB.dead_mob_list += brainmob
brain.brainmob = brainmob //Set the brain to use the brainmob
brainmob = null //Set mmi brainmob var to null
if(user)
+1 -3
View File
@@ -1,8 +1,6 @@
/mob/living/brain
languages_spoken = HUMAN
languages_understood = HUMAN
var/obj/item/device/mmi/container = null
var/timeofhostdeath = 0
var/emp_damage = 0//Handles a type of MMI damage
@@ -64,4 +62,4 @@
/mob/living/brain/fully_replace_character_name(oldname,newname)
..()
if(stored_dna)
stored_dna.real_name = real_name
stored_dna.real_name = real_name
+1 -1
View File
@@ -20,7 +20,7 @@
/datum/emote/brain/flash
key = "flash"
message = "lights' blink."
message = "blinks their lights."
/datum/emote/brain/notice
key = "notice"
+45 -43
View File
@@ -1,4 +1,4 @@
var/global/posibrain_notif_cooldown = 0
GLOBAL_VAR(posibrain_notify_cooldown)
/obj/item/device/mmi/posibrain
name = "positronic brain"
@@ -7,11 +7,11 @@ var/global/posibrain_notif_cooldown = 0
icon_state = "posibrain"
w_class = WEIGHT_CLASS_NORMAL
origin_tech = "biotech=3;programming=3;plasmatech=2"
var/notified = 0
var/next_ask
var/askDelay = 600 //one minute
var/used = 0 //Prevents split personality virus. May be reset if personality deletion code is added.
var/searching = FALSE
brainmob = null
req_access = list(access_robotics)
req_access = list(GLOB.access_robotics)
mecha = null//This does not appear to be used outside of reference in mecha.dm.
braintype = "Android"
var/autoping = TRUE //if it pings on creation immediately
@@ -25,9 +25,8 @@ var/global/posibrain_notif_cooldown = 0
Remember, the purpose of your existence is to serve the crew and the station. Above all else, do no harm.</b>"
var/new_mob_message = "<span class='notice'>The positronic brain chimes quietly.</span>"
var/dead_message = "<span class='deadsay'>It appears to be completely inactive. The reset light is blinking.</span>"
var/list/fluff_names = list("PBU","HIU","SINA","ARMA","OSI","HBL","MSO","RR","CHRI","CDB","HG","XSI","ORNG","GUN","KOR","MET","FRE","XIS","SLI","PKP","HOG","RZH","GOOF","MRPR","JJR","FIRC","INC","PHL","BGB","ANTR","MIW","WJ","JRD","CHOC","ANCL","JLLO","JNLG","KOS","TKRG","XAL","STLP","CBOS","DUNC","FXMC","DRSD")
var/picked_fluff_name //which fluff name we picked
var/list/possible_names //If you leave this blank, it will use the global posibrain names
var/picked_name
/obj/item/device/mmi/posibrain/Topic(href, href_list)
if(href_list["activate"])
@@ -36,42 +35,42 @@ var/global/posibrain_notif_cooldown = 0
activate(ghost)
/obj/item/device/mmi/posibrain/proc/ping_ghosts(msg, newlymade)
if(newlymade || !posibrain_notif_cooldown)
if(newlymade || GLOB.posibrain_notify_cooldown <= world.time)
notify_ghosts("[name] [msg] in [get_area(src)]!", ghost_sound = !newlymade ? 'sound/effects/ghost2.ogg':null, enter_link = "<a href=?src=\ref[src];activate=1>(Click to enter)</a>", source = src, action = NOTIFY_ATTACK, flashwindow = FALSE)
if(!newlymade)
posibrain_notif_cooldown = 1
addtimer(CALLBACK(src, .proc/reset_posibrain_cooldown), askDelay)
/obj/item/device/mmi/posibrain/proc/reset_posibrain_cooldown()
posibrain_notif_cooldown = 0
GLOB.posibrain_notify_cooldown = world.time + askDelay
/obj/item/device/mmi/posibrain/attack_self(mob/user)
if(brainmob && !brainmob.key && !notified)
//Start the process of requesting a new ghost.
to_chat(user, begin_activation_message)
ping_ghosts("requested", FALSE)
notified = 1
used = 0
update_icon()
spawn(askDelay) //Seperate from the global cooldown.
notified = 0
update_icon()
if(brainmob.client)
visible_message(success_message)
else
visible_message(fail_message)
return //Code for deleting personalities recommended here.
if(!brainmob || brainmob.key)
return
if(next_ask > world.time)
return
//Start the process of requesting a new ghost.
to_chat(user, begin_activation_message)
ping_ghosts("requested", FALSE)
next_ask = world.time + askDelay
searching = TRUE
addtimer(CALLBACK(src, .proc/check_success), askDelay)
/obj/item/device/mmi/posibrain/proc/check_success()
searching = FALSE
update_icon()
if(QDELETED(brainmob))
return
if(brainmob.client)
visible_message(success_message)
else
visible_message(fail_message)
/obj/item/device/mmi/posibrain/attack_ghost(mob/user)
activate(user)
//Two ways to activate a positronic brain. A clickable link in the ghost notif, or simply clicking the object itself.
/obj/item/device/mmi/posibrain/proc/activate(mob/user)
if(used || (brainmob && brainmob.key) || jobban_isbanned(user,"posibrain"))
if(QDELETED(brainmob))
return
if(brainmob.key || jobban_isbanned(user,"posibrain"))
return
var/posi_ask = alert("Become a [name]? (Warning, You can no longer be cloned, and all past lives will be forgotten!)","Are you positive?","Yes","No")
if(posi_ask == "No" || QDELETED(src))
return
@@ -97,10 +96,11 @@ var/global/posibrain_notif_cooldown = 0
update_icon()
/obj/item/device/mmi/posibrain/proc/transfer_personality(mob/candidate)
if(used || (brainmob && brainmob.key)) //Prevents hostile takeover if two ghosts get the prompt or link for the same brain.
if(QDELETED(brainmob))
return
if(brainmob.key) //Prevents hostile takeover if two ghosts get the prompt or link for the same brain.
to_chat(candidate, "This brain has already been taken! Please try your possession again later!")
return FALSE
notified = 0
if(candidate.mind && !isobserver(candidate))
candidate.mind.transfer_to(brainmob)
else
@@ -109,12 +109,11 @@ var/global/posibrain_notif_cooldown = 0
to_chat(brainmob, welcome_message)
brainmob.mind.assigned_role = new_role
brainmob.stat = CONSCIOUS
dead_mob_list -= brainmob
living_mob_list += brainmob
GLOB.dead_mob_list -= brainmob
GLOB.living_mob_list += brainmob
visible_message(new_mob_message)
update_icon()
used = 1
return TRUE
@@ -124,7 +123,7 @@ var/global/posibrain_notif_cooldown = 0
if(brainmob && brainmob.key)
switch(brainmob.stat)
if(CONSCIOUS)
if(!src.brainmob.client)
if(!brainmob.client)
msg = "It appears to be in stand-by mode." //afk
if(DEAD)
msg = "<span class='deadsay'>It appears to be completely inactive.</span>"
@@ -133,24 +132,27 @@ var/global/posibrain_notif_cooldown = 0
to_chat(user, msg)
/obj/item/device/mmi/posibrain/New()
/obj/item/device/mmi/posibrain/Initialize()
..()
brainmob = new(src)
picked_fluff_name = pick(fluff_names)
brainmob.name = "[picked_fluff_name]-[rand(100, 999)]"
var/new_name
if(!LAZYLEN(possible_names))
new_name = pick(GLOB.posibrain_names)
else
new_name = pick(possible_names)
brainmob.name = "[new_name]-[rand(100, 999)]"
brainmob.real_name = brainmob.name
brainmob.loc = src
brainmob.container = src
if(autoping)
ping_ghosts("created", TRUE)
..()
/obj/item/device/mmi/posibrain/attackby(obj/item/O, mob/user)
return
/obj/item/device/mmi/posibrain/update_icon()
if(notified)
if(searching)
icon_state = "[initial(icon_state)]-searching"
return
if(brainmob && brainmob.key)
+13 -4
View File
@@ -1,4 +1,4 @@
/mob/living/brain/say(message)
/mob/living/brain/say(message, language)
if(!(container && istype(container, /obj/item/device/mmi)))
return //No MMI, can't speak, bucko./N
else
@@ -7,16 +7,17 @@
return
else
message = Gibberish(message, (emp_damage*6))//scrambles the message, gets worse when emp_damage is higher
..()
/mob/living/brain/get_spans()
return ..() | SPAN_ROBOT
/mob/living/brain/radio(message, message_mode, list/spans)
/mob/living/brain/radio(message, message_mode, list/spans, language)
if(message_mode && istype(container, /obj/item/device/mmi))
var/obj/item/device/mmi/R = container
if(R.radio)
R.radio.talk_into(src, message, , spans)
R.radio.talk_into(src, message, , get_spans(), language)
return ITALICS | REDUCE_RANGE
/mob/living/brain/lingcheck()
@@ -24,4 +25,12 @@
/mob/living/brain/treat_message(message)
message = capitalize(message)
return message
return message
/mob/living/brain/can_speak_in_language(datum/language/dt)
if(HAS_SECONDARY_FLAG(src, OMNITONGUE))
. = has_language(dt)
else if(istype(container, /obj/item/device/mmi/posibrain/soul_vessel))
. = has_language(dt) && ispath(dt, /datum/language/ratvar)
else
. = ..()
@@ -11,15 +11,13 @@
dna = null
faction = list("alien")
ventcrawler = VENTCRAWLER_ALWAYS
languages_spoken = ALIEN
languages_understood = ALIEN
sight = SEE_MOBS
see_in_dark = 4
verb_say = "hisses"
initial_languages = list(/datum/language/xenocommon)
bubble_icon = "alien"
type_of_meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/xeno
var/nightvision = 1
devourable = 1
var/obj/item/weapon/card/id/wear_id = null // Fix for station bounced radios -- Skie
var/has_fine_manipulation = 0
@@ -111,7 +109,7 @@ Des: Gives the client of the alien an image on each infected mob.
----------------------------------------*/
/mob/living/carbon/alien/proc/AddInfectionImages()
if (client)
for (var/mob/living/C in mob_list)
for (var/mob/living/C in GLOB.mob_list)
if(C.status_flags & XENO_HOST)
var/obj/item/organ/body_egg/alien_embryo/A = C.getorgan(/obj/item/organ/body_egg/alien_embryo)
if(A)
@@ -74,7 +74,8 @@ In all, this is a lot like the monkey code. /N
/mob/living/carbon/alien/attack_animal(mob/living/simple_animal/M)
if(..())
. = ..()
if(.)
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
switch(M.melee_damage_type)
if(BRUTE)
@@ -89,7 +90,6 @@ In all, this is a lot like the monkey code. /N
adjustCloneLoss(damage)
if(STAMINA)
adjustStaminaLoss(damage)
updatehealth()
/mob/living/carbon/alien/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime attack
@@ -1,30 +0,0 @@
/datum/emote/living/alien
mob_type_allowed_typecache = list(/mob/living/carbon/alien)
/datum/emote/living/alien/gnarl
key = "gnarl"
key_third_person = "gnarls"
message = "gnarls and shows its teeth..."
/datum/emote/living/alien/hiss
key = "hiss"
key_third_person = "hisses"
message_alien = "hisses."
message_larva = "hisses softly."
/datum/emote/living/alien/hiss/run_emote(mob/user, params)
. = ..()
if(. && isalienadult(user))
playsound(user.loc, "hiss", 40, 1, 1)
/datum/emote/living/alien/roar
key = "roar"
key_third_person = "roars"
message_alien = "roars"
message_larva = "softly roars"
emote_type = EMOTE_AUDIBLE
/datum/emote/living/alien/roar/run_emote(mob/user, params)
. = ..()
if(. && isalienadult(user))
playsound(user.loc, 'sound/voice/hiss5.ogg', 40, 1, 1)
@@ -87,7 +87,7 @@ Doesn't work on other aliens/AI.*/
log_say("AlienWhisper: [key_name(user)]->[M.key] : [msg]")
to_chat(M, "<span class='noticealien'>You hear a strange, alien voice in your head...</span>[msg]")
to_chat(user, "<span class='noticealien'>You said: \"[msg]\" to [M]</span>")
for(var/ded in dead_mob_list)
for(var/ded in GLOB.dead_mob_list)
if(!isobserver(ded))
continue
var/follow_link_user = FOLLOW_LINK(ded, user)
@@ -13,7 +13,7 @@
if(stat == DEAD)
return
for(var/mob/living/carbon/C in living_mob_list)
for(var/mob/living/carbon/C in GLOB.living_mob_list)
if(C == src) //Make sure not to proc it on ourselves.
continue
var/obj/item/organ/alien/hivenode/node = C.getorgan(/obj/item/organ/alien/hivenode)
@@ -108,7 +108,7 @@
//For alien evolution/promotion/queen finder procs. Checks for an active alien of that type
/proc/get_alien_type(var/alienpath)
for(var/mob/living/carbon/alien/humanoid/A in living_mob_list)
for(var/mob/living/carbon/alien/humanoid/A in GLOB.living_mob_list)
if(!istype(A, alienpath))
continue
if(!A.key || A.stat == DEAD) //Only living aliens with a ckey are valid.
@@ -46,7 +46,7 @@
/mob/living/carbon/alien/humanoid/royal/queen/Initialize()
//there should only be one queen
for(var/mob/living/carbon/alien/humanoid/royal/queen/Q in living_mob_list)
for(var/mob/living/carbon/alien/humanoid/royal/queen/Q in GLOB.living_mob_list)
if(Q == src)
continue
if(Q.stat == DEAD)
+2 -2
View File
@@ -5,10 +5,10 @@
var/message_a = say_quote(message, get_spans())
var/rendered = "<i><span class='alien'>Hivemind, <span class='name'>[shown_name]</span> <span class='message'>[message_a]</span></span></i>"
for(var/mob/S in player_list)
for(var/mob/S in GLOB.player_list)
if(!S.stat && S.hivecheck())
to_chat(S, rendered)
if(S in dead_mob_list)
if(S in GLOB.dead_mob_list)
var/link = FOLLOW_LINK(S, src)
to_chat(S, "[link] [rendered]")
@@ -117,7 +117,7 @@ Proc: AddInfectionImages(C)
Des: Adds the infection image to all aliens for this embryo
----------------------------------------*/
/obj/item/organ/body_egg/alien_embryo/AddInfectionImages()
for(var/mob/living/carbon/alien/alien in player_list)
for(var/mob/living/carbon/alien/alien in GLOB.player_list)
if(alien.client)
var/I = image('icons/mob/alien.dmi', loc = owner, icon_state = "infected[stage]")
alien.client.images += I
@@ -127,7 +127,7 @@ Proc: RemoveInfectionImage(C)
Des: Removes all images from the mob infected by this embryo
----------------------------------------*/
/obj/item/organ/body_egg/alien_embryo/RemoveInfectionImages()
for(var/mob/living/carbon/alien/alien in player_list)
for(var/mob/living/carbon/alien/alien in GLOB.player_list)
if(alien.client)
for(var/image/I in alien.client.images)
if(dd_hasprefix_case(I.icon_state, "infected") && I.loc == owner)
@@ -2,11 +2,11 @@
//TODO: Make these simple_animals
var/const/MIN_IMPREGNATION_TIME = 100 //time it takes to impregnate someone
var/const/MAX_IMPREGNATION_TIME = 150
#define MIN_IMPREGNATION_TIME 100 //time it takes to impregnate someone
#define MAX_IMPREGNATION_TIME 150
var/const/MIN_ACTIVE_TIME = 200 //time between being dropped and going idle
var/const/MAX_ACTIVE_TIME = 400
#define MIN_ACTIVE_TIME 200 //time between being dropped and going idle
#define MAX_ACTIVE_TIME 400
/obj/item/clothing/mask/facehugger
name = "alien"
@@ -152,14 +152,6 @@ var/const/MAX_ACTIVE_TIME = 400
// probiscis-blocker handling
if(iscarbon(M))
var/mob/living/carbon/target = M
if(target.wear_mask)
var/obj/item/clothing/W = target.wear_mask
if(W.flags & NODROP)
return FALSE
if(!istype(W,/obj/item/clothing/mask/facehugger))
target.dropItemToGround(W)
target.visible_message("<span class='danger'>[src] tears [W] off of [target]'s face!</span>", \
"<span class='userdanger'>[src] tears [W] off of [target]'s face!</span>")
if(ishuman(M))
var/mob/living/carbon/human/H = M
@@ -168,6 +160,12 @@ var/const/MAX_ACTIVE_TIME = 400
"<span class='userdanger'>[src] smashes against [H]'s [H.head]!</span>")
Die()
return FALSE
if(target.wear_mask)
var/obj/item/clothing/W = target.wear_mask
if(!istype(W,/obj/item/clothing/mask/facehugger) && target.dropItemToGround(W))
target.visible_message("<span class='danger'>[src] tears [W] off of [target]'s face!</span>", \
"<span class='userdanger'>[src] tears [W] off of [target]'s face!</span>")
forceMove(target)
target.equip_to_slot_if_possible(src, slot_wear_mask, 0, 1, 1)
// early returns and validity checks done: attach.
+7 -1
View File
@@ -522,6 +522,7 @@
return
sight = initial(sight)
lighting_alpha = initial(lighting_alpha)
var/obj/item/organ/eyes/E = getorganslot("eye_sight")
if(!E)
update_tint()
@@ -529,6 +530,8 @@
see_invisible = E.see_invisible
see_in_dark = E.see_in_dark
sight |= E.sight_flags
if(!isnull(E.lighting_alpha))
lighting_alpha = E.lighting_alpha
if(client.eye != src)
var/atom/A = client.eye
@@ -543,6 +546,8 @@
see_invisible = G.invis_override
else
see_invisible = min(G.invis_view, see_invisible)
if(!isnull(G.lighting_alpha))
lighting_alpha = min(lighting_alpha, G.lighting_alpha)
if(dna)
for(var/X in dna.mutations)
var/datum/mutation/M = X
@@ -552,11 +557,12 @@
if(see_override)
see_invisible = see_override
. = ..()
//to recalculate and update the mob's total tint from tinted equipment it's wearing.
/mob/living/carbon/proc/update_tint()
if(!tinted_weldhelh)
if(!GLOB.tinted_weldhelh)
return
tinttotal = get_total_tint()
if(tinttotal >= TINT_BLIND)
@@ -44,4 +44,7 @@
/obj/item/bodypart/r_arm, /obj/item/bodypart/r_leg, /obj/item/bodypart/l_leg)
//Gets filled up in create_bodyparts()
var/list/hand_bodyparts = list() //a collection of arms (or actually whatever the fug /bodyparts you monsters use to wreck my systems)
var/list/hand_bodyparts = list() //a collection of arms (or actually whatever the fug /bodyparts you monsters use to wreck my systems)
var/icon_render_key = ""
var/static/list/limb_icon_cache = list()
@@ -19,12 +19,6 @@
if(legcuffed)
. += legcuffed.slowdown
var/const/NO_SLIP_WHEN_WALKING = 1
var/const/SLIDE = 2
var/const/GALOSHES_DONT_HELP = 4
var/const/SLIDE_ICE = 8
/mob/living/carbon/slip(s_amount, w_amount, obj/O, lube)
if(movement_type & FLYING)
return 0
@@ -147,8 +147,8 @@
parts -= picked
if(updating_health)
updatehealth()
if(update)
update_damage_overlays()
if(update)
update_damage_overlays()
// damage MANY bodyparts, in random order
/mob/living/carbon/take_overall_damage(brute, burn, updating_health = 1)
+5 -5
View File
@@ -9,8 +9,8 @@
emote("deathgasp")
. = ..()
if(ticker && ticker.mode)
ticker.mode.check_win() //Calls the rounds wincheck, mainly for wizard, malf, and changeling now
if(SSticker && SSticker.mode)
SSticker.mode.check_win() //Calls the rounds wincheck, mainly for wizard, malf, and changeling now
/mob/living/carbon/gib(no_brain, no_organs, no_bodyparts)
for(var/mob/M in src)
@@ -35,7 +35,7 @@
if(org_zone == "chest")
O.Remove(src)
O.forceMove(get_turf(src))
O.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5)
O.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5)
else
for(var/X in internal_organs)
var/obj/item/organ/I = X
@@ -44,11 +44,11 @@
continue
I.Remove(src)
I.forceMove(get_turf(src))
I.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5)
I.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5)
/mob/living/carbon/spread_bodyparts()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
BP.drop_limb()
BP.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5)
BP.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5)
@@ -10,8 +10,11 @@
else
new /obj/effect/gibspawner/humanbodypartless(loc, viruses, dna)
/mob/living/carbon/human/spawn_dust()
new /obj/effect/decal/remains/human(loc)
/mob/living/carbon/human/spawn_dust(just_ash = FALSE)
if(just_ash)
new /obj/effect/decal/cleanable/ash(loc)
else
new /obj/effect/decal/remains/human(loc)
/mob/living/carbon/human/death(gibbed)
if(stat == DEAD)
@@ -29,7 +32,7 @@
dna.species.spec_death(gibbed, src)
if(ticker && ticker.mode)
if(SSticker && SSticker.mode)
sql_report_death(src)
if(mind && mind.devilinfo)
INVOKE_ASYNC(mind.devilinfo, /datum/devilinfo.proc/beginResurrectionCheck, src)
@@ -142,7 +142,7 @@
if(!key)
var/foundghost = 0
if(mind)
for(var/mob/dead/observer/G in player_list)
for(var/mob/dead/observer/G in GLOB.player_list)
if(G.mind == mind)
foundghost = 1
if (G.can_reenter_corpse == 0)
@@ -257,9 +257,6 @@
msg += "[t_He] looks like a drunken mess.\n"
if(91.01 to INFINITY)
msg += "[t_He] [t_is] a shitfaced, slobbering wreck.\n"
for (var/I in src.vore_organs)
var/datum/belly/B = vore_organs[I]
msg += B.get_examine_msg()
msg += "</span>"
@@ -292,7 +289,7 @@
if(istype(H.glasses, /obj/item/clothing/glasses/hud) || CIH)
var/perpname = get_face_name(get_id_name(""))
if(perpname)
var/datum/data/record/R = find_record("name", perpname, data_core.general)
var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.general)
if(R)
msg += "<span class='deptradio'>Rank:</span> [R.fields["rank"]]<br>"
msg += "<a href='?src=\ref[src];hud=1;photo_front=1'>\[Front photo\]</a> "
@@ -310,7 +307,7 @@
msg += "<a href='?src=\ref[src];hud=m;p_stat=1'>\[[health_r]\]</a>"
health_r = R.fields["m_stat"]
msg += "<a href='?src=\ref[src];hud=m;m_stat=1'>\[[health_r]\]</a><br>"
R = find_record("name", perpname, data_core.medical)
R = find_record("name", perpname, GLOB.data_core.medical)
if(R)
msg += "<a href='?src=\ref[src];hud=m;evaluation=1'>\[Medical evaluation\]</a><br>"
@@ -320,7 +317,7 @@
//|| !user.canmove || user.restrained()) Fluff: Sechuds have eye-tracking technology and sets 'arrest' to people that the wearer looks and blinks at.
var/criminal = "None"
R = find_record("name", perpname, data_core.security)
R = find_record("name", perpname, GLOB.data_core.security)
if(R)
criminal = R.fields["criminal"]
@@ -1,54 +0,0 @@
/mob/living/carbon/human/proc/examine_nutrition()
var/message = ""
var/nutrition_examine = round(nutrition)
var/t_He = "It" //capitalised for use at the start of each line.
var/t_His = "Its"
var/t_his = "its"
var/t_is = "is"
var/t_has = "has"
switch(gender)
if(MALE)
t_He = "He"
t_his = "his"
t_His = "His"
if(FEMALE)
t_He = "She"
t_his = "her"
t_His = "Her"
if(PLURAL)
t_He = "They"
t_his = "their"
t_His = "Their"
t_is = "are"
t_has = "have"
if(NEUTER)
t_He = "It"
t_his = "its"
t_His = "Its"
switch(nutrition_examine)
if(0 to 49)
message = "<span class='warning'>[t_He] [t_is] starving! You can hear [t_his] stomach snarling from across the room!</span>\n"
if(50 to 99)
message = "<span class='warning'>[t_He] [t_is] extremely hungry. A deep growl occasionally rumbles from [t_his] empty stomach.</span>\n"
if(100 to 499)
return message //Well that's pretty normal, really.
if(500 to 864) // Fat.
message = "[t_He] [t_has] a stuffed belly, bloated fat and round from eating too much.\n"
if(1200 to 1934) // One person fully digested.
message = "<span class='warning'>[t_He] [t_is] sporting a large, round, sagging stomach. It's contains at least their body weight worth of glorping slush.</span>\n"
if(1935 to 3004) // Two people.
message = "<span class='warning'>[t_He] [t_is] engorged with a huge stomach that sags and wobbles as they move. [t_He] must have consumed at least twice their body weight. It looks incredibly soft.</span>\n"
if(3005 to 4074) // Three people.
message = "<span class='warning'>[t_His] stomach is firmly packed with digesting slop. [t_He] must have eaten at least a few times worth their body weight! It looks hard for them to stand, and [t_his] gut jiggles when they move.</span>\n"
if(4075 to 10000) // Four or more people.
message = "<span class='warning'>[t_He] [t_is] so absolutely stuffed that you aren't sure how it's possible to move. [t_He] can't seem to swell any bigger. The surface of [t_his] belly looks sorely strained!</span>\n"
return message
/mob/living/carbon/human/proc/examine_bellies()
var/message = ""
for (var/I in src.vore_organs)
var/datum/belly/B = vore_organs[I]
message += B.get_examine_msg()
return message
+25 -17
View File
@@ -17,6 +17,9 @@
args[1] = FALSE
Initialize(arglist(args))
/mob/living/carbon/human/dummy/Life()
return
/mob/living/carbon/human/Initialize()
verbs += /mob/living/proc/mob_sleep
verbs += /mob/living/proc/lay_down
@@ -39,6 +42,8 @@
handcrafting = new()
grant_language(/datum/language/common) // ME TARZAN, YOU JANEBOT
..()
/mob/living/carbon/human/create_internal_organs()
@@ -298,7 +303,7 @@
var/mob/living/carbon/human/H = usr
var/perpname = get_face_name(get_id_name(""))
if(istype(H.glasses, /obj/item/clothing/glasses/hud) || istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud))
var/datum/data/record/R = find_record("name", perpname, data_core.general)
var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.general)
if(href_list["photo_front"] || href_list["photo_side"])
if(R)
if(!H.canUseHUD())
@@ -388,7 +393,7 @@
if (!G.emagged)
if(H.wear_id)
var/list/access = H.wear_id.GetAccess()
if(access_sec_doors in access)
if(GLOB.access_sec_doors in access)
allowed_access = H.get_authentification_name()
else
allowed_access = "@%&ERROR_%$*"
@@ -399,7 +404,7 @@
return
if(perpname)
R = find_record("name", perpname, data_core.security)
R = find_record("name", perpname, GLOB.data_core.security)
if(R)
if(href_list["status"])
var/setcriminal = input(usr, "Specify a new criminal status for this person.", "Security HUD", R.fields["criminal"]) in list("None", "*Arrest*", "Incarcerated", "Parolled", "Discharged", "Cancel")
@@ -447,8 +452,8 @@
return
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security))
return
var/crime = data_core.createCrimeEntry(t1, t2, allowed_access, worldtime2text())
data_core.addMinorCrime(R.fields["id"], crime)
var/crime = GLOB.data_core.createCrimeEntry(t1, t2, allowed_access, worldtime2text())
GLOB.data_core.addMinorCrime(R.fields["id"], crime)
to_chat(usr, "<span class='notice'>Successfully added a minor crime.</span>")
return
if("Major Crime")
@@ -462,8 +467,8 @@
return
else if (!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security))
return
var/crime = data_core.createCrimeEntry(t1, t2, allowed_access, worldtime2text())
data_core.addMajorCrime(R.fields["id"], crime)
var/crime = GLOB.data_core.createCrimeEntry(t1, t2, allowed_access, worldtime2text())
GLOB.data_core.addMajorCrime(R.fields["id"], crime)
to_chat(usr, "<span class='notice'>Successfully added a major crime.</span>")
return
@@ -494,7 +499,7 @@
var/counter = 1
while(R.fields[text("com_[]", counter)])
counter++
R.fields[text("com_[]", counter)] = text("Made by [] on [] [], []<BR>[]", allowed_access, worldtime2text(), time2text(world.realtime, "MMM DD"), year_integer+540, t1)
R.fields[text("com_[]", counter)] = text("Made by [] on [] [], []<BR>[]", allowed_access, worldtime2text(), time2text(world.realtime, "MMM DD"), GLOB.year_integer+540, t1)
to_chat(usr, "<span class='notice'>Successfully added comment.</span>")
return
to_chat(usr, "<span class='warning'>Unable to locate a data core entry for this person.</span>")
@@ -581,7 +586,7 @@
//Check for weapons
if(judgebot.weaponscheck)
if(!idcard || !(access_weapons in idcard.access))
if(!idcard || !(GLOB.access_weapons in idcard.access))
for(var/obj/item/I in held_items)
if(judgebot.check_for_weapons(I))
threatcount += 4
@@ -591,7 +596,7 @@
//Check for arrest warrant
if(judgebot.check_records)
var/perpname = get_face_name(get_id_name())
var/datum/data/record/R = find_record("name", perpname, data_core.security)
var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.security)
if(R && R.fields["criminal"])
switch(R.fields["criminal"])
if("*Arrest*")
@@ -765,7 +770,7 @@
..()
/mob/living/carbon/human/replace_records_name(oldname,newname) // Only humans have records right now, move this up if changed.
for(var/list/L in list(data_core.general,data_core.medical,data_core.security,data_core.locked))
for(var/list/L in list(GLOB.data_core.general,GLOB.data_core.medical,GLOB.data_core.security,GLOB.data_core.locked))
var/datum/data/record/R = find_record("name", oldname, L)
if(R)
R.fields["name"] = newname
@@ -855,7 +860,7 @@
if(7) // Pride
log_game("[src] was influenced by the sin of pride.")
O = new /datum/objective/sintouched/pride
ticker.mode.sintouched += src.mind
SSticker.mode.sintouched += src.mind
src.mind.objectives += O
src.mind.announce_objectives()
@@ -920,12 +925,15 @@
return
if(buckled) //NO INFINITE STACKING!!
return
if(M.incapacitated(FALSE, TRUE) || incapacitated(FALSE, TRUE))
M.visible_message("<span class='boldwarning'>[M] can't hang onto [src]!</span>")
return
if(iscarbon(M) && (!riding_datum.equip_buckle_inhands(M, 2))) //MAKE SURE THIS IS LAST!!
M.visible_message("<span class='boldwarning'>[M] can't climb onto [src] because [M.p_their()] hands are full!</span>")
if(M.stat != CONSCIOUS)
return
if(iscarbon(M))
if(M.incapacitated(FALSE, TRUE) || incapacitated(FALSE, TRUE))
M.visible_message("<span class='boldwarning'>[M] can't hang onto [src]!</span>")
return
if(!riding_datum.equip_buckle_inhands(M, 2)) //MAKE SURE THIS IS LAST!!
M.visible_message("<span class='boldwarning'>[M] can't climb onto [src] because [M.p_their()] hands are full!</span>")
return
. = ..(M, force, check_loc)
stop_pulling()
@@ -160,8 +160,8 @@
return ..()
/mob/living/carbon/human/grabbedby(mob/living/carbon/user, supress_message = 0)
if(user == src && pulling && !pulling.anchored && grab_state >= GRAB_AGGRESSIVE && isliving(pulling))
vore_attack(user, pulling)
if(user == src && pulling && !pulling.anchored && grab_state >= GRAB_AGGRESSIVE && (disabilities & FAT) && ismonkey(pulling))
devour_mob(pulling)
else
..()
@@ -302,13 +302,14 @@
/mob/living/carbon/human/attack_animal(mob/living/simple_animal/M)
if(..())
. = ..()
if(.)
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
if(check_shields(damage, "the [M.name]", null, MELEE_ATTACK, M.armour_penetration))
return 0
return FALSE
var/dam_zone = dismembering_strike(M, pick("chest", "l_hand", "r_hand", "l_leg", "r_leg"))
if(!dam_zone) //Dismemberment successful
return 1
return TRUE
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
if(!affecting)
affecting = get_bodypart("chest")
@@ -1,7 +1,5 @@
var/global/default_martial_art = new/datum/martial_art
/mob/living/carbon/human
languages_spoken = HUMAN
languages_understood = HUMAN
initial_languages = list(/datum/language/common)
hud_possible = list(HEALTH_HUD,STATUS_HUD,ID_HUD,WANTED_HUD,IMPLOYAL_HUD,IMPCHEM_HUD,IMPTRACK_HUD,ANTAG_HUD)
possible_a_intents = list(INTENT_HELP, INTENT_DISARM, INTENT_GRAB, INTENT_HARM)
pressure_resistance = 25
@@ -43,6 +41,7 @@ var/global/default_martial_art = new/datum/martial_art
var/bleedsuppress = 0 //for stopping bloodloss, eventually this will be limb-based like bleeding
var/datum/martial_art/martial_art = null
var/static/default_martial_art = new/datum/martial_art
var/name_override //For temporary visible name changes
@@ -50,4 +49,4 @@ var/global/default_martial_art = new/datum/martial_art
var/datum/personal_crafting/handcrafting
can_buckle = TRUE
buckle_lying = FALSE
can_ride_typecache = list(/mob/living/carbon/human, /mob/living/simple_animal/slime)
can_ride_typecache = list(/mob/living/carbon/human, /mob/living/simple_animal/slime, /mob/living/simple_animal/parrot)
@@ -67,10 +67,7 @@
//modules
var/list/functions = list("nearbyscan","combat","shitcurity","chatter")
var/restrictedJob = 0
var/shouldUseDynamicProc = 0 // switch to make the AI control it's own proccessing
var/alternateProcessing = 1
var/forceProcess = 0
var/processTime = 8
var/lastProc = 0
var/walkdebug = 0 //causes sparks in our path target. used for debugging
var/debugexamine = 0 //If we show debug info in our examine
@@ -85,6 +82,7 @@
var/traitorScale = 0 // our ability as a traitor
var/traitorType = 0
var/voice_saved = FALSE
/// SNPC voice handling
@@ -96,6 +94,8 @@
knownStrings = list()
/mob/living/carbon/human/interactive/proc/saveVoice()
if(voice_saved)
return
var/savefile/S = new /savefile("data/npc_saves/snpc.sav")
S["knownStrings"] << knownStrings
@@ -145,8 +145,7 @@
retal_target = potentialAssault
..()
/client/proc/resetSNPC(var/mob/A in SSnpc.botPool_l)
/client/proc/resetSNPC(var/mob/A in SSnpcpool.processing)
set name = "Reset SNPC"
set desc = "Reset the SNPC"
set category = "Debug"
@@ -163,24 +162,7 @@
T.retal = 0
T.doing = 0
/client/proc/toggleSNPC(var/mob/A in SSnpc.botPool_l)
set name = "Toggle SNPC Proccessing Mode"
set desc = "Toggle SNPC Proccessing Mode"
set category = "Debug"
if(!holder)
return
if(A)
if(!istype(A,/mob/living/carbon/human/interactive))
return
var/mob/living/carbon/human/interactive/T = A
if(T)
T.alternateProcessing = !T.alternateProcessing
T.forceProcess = 1
to_chat(usr, "[T]'s processing has been switched to [T.alternateProcessing ? "High Profile" : "Low Profile"]")
/client/proc/customiseSNPC(var/mob/A in SSnpc.botPool_l)
/client/proc/customiseSNPC(var/mob/A in SSnpcpool.processing)
set name = "Customize SNPC"
set desc = "Customise the SNPC"
set category = "Debug"
@@ -216,7 +198,7 @@
T.doSetup()
if(prob(25))
var/list/validchoices = list()
for(var/mob/living/carbon/human/M in mob_list)
for(var/mob/living/carbon/human/M in GLOB.mob_list)
validchoices += M
var/mob/living/carbon/human/chosen = pick(validchoices)
var/datum/dna/toDoppel = chosen.dna
@@ -241,7 +223,7 @@
if(shouldDoppel)
if(shouldDoppel == "Yes")
var/list/validchoices = list()
for(var/mob/living/carbon/human/M in mob_list)
for(var/mob/living/carbon/human/M in GLOB.mob_list)
validchoices += M
var/mob/living/carbon/human/chosen = input("Which crewmember?") as null|anything in validchoices
@@ -366,14 +348,14 @@
switch(traitorType)
if(SNPC_BRUTE) // SMASH KILL RAAARGH
traitorTarget = pick(mob_list)
traitorTarget = pick(GLOB.mob_list)
if(SNPC_STEALTH) // Shhh we is sneekies
var/A = pick(typesof(/datum/objective_item/steal) - /datum/objective_item/steal)
var/datum/objective_item/steal/S = new A
traitorTarget = locate(S.targetitem) in world
if(SNPC_MARTYR) // MY LIFE FOR SPESZUL
var/targetType = pick(/obj/machinery/gravity_generator/main/station,/obj/machinery/power/smes/engineering,/obj/machinery/telecomms/hub)
traitorTarget = locate(targetType) in machines
traitorTarget = locate(targetType) in GLOB.machines
if(SNPC_PSYCHO) // YOU'RE LIKE A FLESH BICYLE AND I WANT TO DISMANTLE YOU
traitorTarget = null
@@ -390,7 +372,7 @@
doSetup()
SSnpc.insertBot(src)
START_PROCESSING(SSnpcpool, src)
loadVoice()
@@ -400,8 +382,9 @@
attitude += rand(-10,10)
slyness += rand(-10,10)
doProcess()
/mob/living/carbon/human/interactive/Destroy()
SSnpcpool.stop_processing(src)
return ..()
/mob/living/carbon/human/interactive/proc/retalTarget(var/target)
var/mob/living/carbon/human/M = target
@@ -533,39 +516,22 @@
/mob/living/carbon/human/interactive/proc/targetRange(towhere)
return get_dist(get_turf(towhere), get_turf(src))
/mob/living/carbon/human/interactive/Life()
..()
if(ticker.current_state == GAME_STATE_FINISHED)
/mob/living/carbon/human/interactive/proc/InteractiveProcess()
if(SSticker.current_state == GAME_STATE_FINISHED)
saveVoice()
if(!alternateProcessing || forceProcess || world.time > lastProc + processTime)
doProcess()
doProcess()
/mob/living/carbon/human/interactive/death()
saveVoice()
..()
/mob/living/carbon/human/interactive/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans)
/mob/living/carbon/human/interactive/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans, message_mode)
if(speaker != src)
knownStrings |= html_decode(raw_message)
..()
/mob/living/carbon/human/interactive/proc/doProcess()
set waitfor = 0
forceProcess = 0
lastProc = world.time
if(shouldUseDynamicProc)
var/isSeen = 0
for(var/mob/living/carbon/human/A in orange(12,src))
if(A.client)
isSeen = 1
alternateProcessing = isSeen
if(alternateProcessing)
forceProcess = 1
if(IsDeadOrIncap())
walk(src,0)
return
set waitfor = FALSE
//---------------------------
//---- interest flow control
if(interest < 0 || inactivity_period < 0)
@@ -579,7 +545,7 @@
//VIEW FUNCTIONS
//doorscan is now integrated into life and runs before all other procs
for(var/dir in alldirs)
for(var/dir in GLOB.alldirs)
var/turf/T = get_step(src,dir)
if(T)
for(var/obj/machinery/door/D in T.contents)
@@ -587,10 +553,13 @@
if(istype(D,/obj/machinery/door/airlock))
var/obj/machinery/door/airlock/AL = D
if(!AL.CanAStarPass(RPID)) // only crack open doors we can't get through
inactivity_period = 20
AL.panel_open = 1
AL.update_icon()
AL.shock(src,(100 - smartness)/2)
sleep(5)
if(QDELETED(AL))
return
AL.unbolt()
if(!AL.wires.is_cut(WIRE_BOLTS))
AL.wires.cut(WIRE_BOLTS)
@@ -599,9 +568,15 @@
if(!AL.wires.is_cut(WIRE_POWER2))
AL.wires.cut(WIRE_POWER2)
sleep(5)
if(QDELETED(AL))
return
AL.panel_open = 0
AL.update_icon()
D.open()
D.open(2) //crowbar force
else
D.open()
else
D.open()
if(update_hands)
var/obj/item/l_hand = get_item_for_held_index(1)
@@ -633,7 +608,7 @@
//proc functions
for(var/Proc in functions)
if(!IsDeadOrIncap())
callfunction(Proc)
INVOKE_ASYNC(src, Proc)
//target interaction stays hardcoded
@@ -649,8 +624,8 @@
if(istype(TARGET, /obj/machinery/door))
var/obj/machinery/door/D = TARGET
if(D.check_access(MYID) && !istype(D,/obj/machinery/door/poddoor))
inactivity_period = 10
D.open()
//sleep(15)
var/turf/T = get_step(get_step(D.loc,dir),dir) //recursion yo
tryWalk(T)
//THIEVING SKILLS
@@ -672,15 +647,8 @@
insert_into_backpack()
//---------FASHION
if(istype(TARGET,/obj/item/clothing))
var/obj/item/clothing/C = TARGET
drop_item()
spawn(5)
take_to_slot(C,1)
if(!equip_to_appropriate_slot(C))
var/obj/item/I = get_item_by_slot(C)
dropItemToGround(I)
spawn(5)
equip_to_appropriate_slot(C)
dressup(TARGET)
update_hands = 1
if(MYPDA in src.loc || MYID in src.loc)
if(MYPDA in src.loc)
@@ -738,8 +706,19 @@
TARGET = traitorTarget
tryWalk(TARGET)
LAST_TARGET = TARGET
if(alternateProcessing)
addtimer(CALLBACK(src, .proc/doProcess), processTime)
/mob/living/carbon/human/interactive/proc/dressup(obj/item/clothing/C)
set waitfor = FALSE
inactivity_period = 12
sleep(5)
if(!QDELETED(C) && !QDELETED(src))
take_to_slot(C,1)
if(!equip_to_appropriate_slot(C))
var/obj/item/I = get_item_by_slot(C)
dropItemToGround(I)
sleep(5)
if(!QDELETED(src) && !QDELETED(C))
equip_to_appropriate_slot(C)
/mob/living/carbon/human/interactive/proc/favouredObjIn(var/list/inList)
var/list/outList = list()
@@ -751,11 +730,6 @@
outList = inList
return outList
/mob/living/carbon/human/interactive/proc/callfunction(Proc)
set waitfor = 0
spawn(0)
call(src,Proc)(src)
/mob/living/carbon/human/interactive/proc/tryWalk(turf/inTarget, override = 0)
if(restrictedJob && !override) // we're a job that has to stay in our home
if(!(get_turf(inTarget) in get_area_turfs(job2area(myjob))))
@@ -1133,7 +1107,7 @@
for(var/mob/living/carbon/human/C in nearby)
var/perpname = C.get_face_name(C.get_id_name())
var/datum/data/record/R = find_record("name", perpname, data_core.security)
var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.security)
if(R && R.fields["criminal"])
switch(R.fields["criminal"])
if("*Arrest*")
@@ -1143,7 +1117,8 @@
for(var/obj/item/I in allContents)
if(istype(I,/obj/item/weapon/restraints))
I.attack(TARGET,src) // go go bluespace restraint launcher!
sleep(25)
inactivity_period = 25
break
/mob/living/carbon/human/interactive/proc/clowning(obj)
if(shouldModulePass())
@@ -1225,7 +1200,7 @@
if(get_dist(src,C) <= 2)
src.say("Wait, [C], let me heal you!")
M.attack(C,src)
sleep(25)
inactivity_period = 25
else
tryWalk(get_turf(C))
else if(shouldTryHeal == 2)
@@ -1237,7 +1212,7 @@
if(get_dist(src,C) <= 2)
src.say("Wait, [C], let me heal you!")
HPS.attack(C,src)
sleep(25)
inactivity_period = 25
else
tryWalk(get_turf(C))
@@ -1265,7 +1240,7 @@
tryWalk(TC)
else
S.afterattack(TC,src)
sleep(25)
inactivity_period = 25
/mob/living/carbon/human/interactive/proc/customEmote(var/text)
visible_message("<span class='notice'>[text]</span>")
@@ -1354,7 +1329,7 @@
var/choice = pick(1,2)
if(choice == 1)
tryWalk(get_turf(D))
sleep(get_dist(src,D))
inactivity_period = get_dist(src,D)
D.attackby(RP,src)
else
cookingwithmagic(D)
@@ -1364,7 +1339,7 @@
var/choice = pick(1,2)
if(choice == 1)
tryWalk(get_turf(D))
sleep(get_dist(src,D))
inactivity_period = get_dist(src,D)
FD.attackby(KK,src)
else
cookingwithmagic(FD)
@@ -1374,7 +1349,7 @@
var/choice = pick(1,2)
if(choice == 1)
tryWalk(get_turf(D))
sleep(get_dist(src,D))
inactivity_period = get_dist(src,D)
CB.attackby(RP,src)
else
cookingwithmagic(CB)
@@ -1384,7 +1359,7 @@
var/choice = pick(1,2)
if(choice == 1)
tryWalk(get_turf(D))
sleep(get_dist(src,D))
inactivity_period = get_dist(src,D)
PD.attackby(KK,src)
else
cookingwithmagic(PD)
@@ -1533,6 +1508,7 @@
G.attack_self(src)
if(prob(smartness))
npcDrop(G,1)
inactivity_period = 15
sleep(15)
throw_item(TARGET)
@@ -102,7 +102,7 @@
update_tint()
if(G.vision_correction)
clear_fullscreen("nearsighted")
if(G.vision_flags || G.darkness_view || G.invis_override || G.invis_view)
if(G.vision_flags || G.darkness_view || G.invis_override || G.invis_view || !isnull(G.lighting_alpha))
update_sight()
update_inv_glasses()
if(slot_gloves)
@@ -141,13 +141,13 @@
return not_handled //For future deeper overrides
/mob/living/carbon/human/doUnEquip(obj/item/I, force)
/mob/living/carbon/human/doUnEquip(obj/item/I, force, newloc, no_move, invdrop)
. = ..() //See mob.dm for an explanation on this and some rage about people copypasting instead of calling ..() like they should.
if(!. || !I)
return
if(I == wear_suit)
if(s_store)
if(s_store && invdrop)
dropItemToGround(s_store, TRUE) //It makes no sense for your suit storage to stay on you if you drop your suit.
if(wear_suit.breakouttime) //when unequipping a straightjacket
update_action_buttons_icon() //certain action buttons may be usable again.
@@ -156,17 +156,18 @@
update_inv_w_uniform()
update_inv_wear_suit()
else if(I == w_uniform)
if(r_store)
dropItemToGround(r_store, TRUE) //Again, makes sense for pockets to drop.
if(l_store)
dropItemToGround(l_store, TRUE)
if(wear_id)
dropItemToGround(wear_id)
if(belt)
dropItemToGround(belt)
if(invdrop)
if(r_store)
dropItemToGround(r_store, TRUE) //Again, makes sense for pockets to drop.
if(l_store)
dropItemToGround(l_store, TRUE)
if(wear_id)
dropItemToGround(wear_id)
if(belt)
dropItemToGround(belt)
w_uniform = null
update_suit_sensors()
update_inv_w_uniform()
update_inv_w_uniform(invdrop)
else if(I == gloves)
gloves = null
update_inv_gloves()
@@ -180,7 +181,7 @@
if(G.vision_correction)
if(disabilities & NEARSIGHT)
overlay_fullscreen("nearsighted", /obj/screen/fullscreen/impaired, 1)
if(G.vision_flags || G.darkness_view || G.invis_override || G.invis_view)
if(G.vision_flags || G.darkness_view || G.invis_override || G.invis_view || !isnull(G.lighting_alpha))
update_sight()
update_inv_glasses()
else if(I == ears)
+1 -8
View File
@@ -57,8 +57,6 @@
/mob/living/carbon/human/calculate_affecting_pressure(pressure)
if((wear_suit && (wear_suit.flags & STOPSPRESSUREDMAGE)) && (head && (head.flags & STOPSPRESSUREDMAGE)))
return ONE_ATMOSPHERE
if(ismob(loc))
return ONE_ATMOSPHERE //hopefully won't murderficate people in your guts by going for a spacewalk
else
return pressure
@@ -98,7 +96,7 @@
if(!dna.species.breathe(src))
..()
#define HUMAN_MAX_OXYLOSS 3
#define HUMAN_CRIT_MAX_OXYLOSS (SSmob.wait/30)
#define HUMAN_CRIT_MAX_OXYLOSS (SSmobs.wait/30)
/mob/living/carbon/human/check_breath(datum/gas_mixture/breath)
var/L = getorganslot("lungs")
@@ -141,8 +139,6 @@
/mob/living/carbon/human/proc/get_thermal_protection()
var/thermal_protection = 0 //Simple check to estimate how protected we are against multiple temperatures
if(ismob(loc))
thermal_protection = FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT //because lazy and insulated by being inside someone
if(wear_suit)
if(wear_suit.max_heat_protection_temperature >= FIRE_SUIT_MAX_TEMP_PROTECT)
thermal_protection += (wear_suit.max_heat_protection_temperature*0.7)
@@ -252,9 +248,6 @@
if(dna.check_mutation(COLDRES))
return 1 //Fully protected from the cold.
if(ismob(loc))
return 1 //because lazy and being inside somemone insulates you from space
if(dna && (RESISTCOLD in dna.species.species_traits))
return 1
+7 -9
View File
@@ -1,12 +1,10 @@
/mob/living/carbon/human/say_quote(input, spans)
if(!input)
return "says, \"...\"" //not the best solution, but it will stop a large number of runtimes. The cause is somewhere in the Tcomms code
/mob/living/carbon/human/say_quote(input, spans, message_mode)
verb_say = dna.species.say_mod
. = ..()
if(src.slurring)
input = attach_spans(input, spans)
return "slurs, \"[input]\""
return ..()
/mob/living/carbon/human/treat_message(message)
message = dna.species.handle_speech(message,src)
@@ -75,7 +73,7 @@
if(!istype(dongle)) return 0
if(dongle.translate_binary) return 1
/mob/living/carbon/human/radio(message, message_mode, list/spans)
/mob/living/carbon/human/radio(message, message_mode, list/spans, language)
. = ..()
if(. != 0)
return .
@@ -83,17 +81,17 @@
switch(message_mode)
if(MODE_HEADSET)
if (ears)
ears.talk_into(src, message, , spans)
ears.talk_into(src, message, , spans, language)
return ITALICS | REDUCE_RANGE
if(MODE_DEPARTMENT)
if (ears)
ears.talk_into(src, message, message_mode, spans)
ears.talk_into(src, message, message_mode, spans, language)
return ITALICS | REDUCE_RANGE
if(message_mode in radiochannels)
if(message_mode in GLOB.radiochannels)
if(ears)
ears.talk_into(src, message, message_mode, spans)
ears.talk_into(src, message, message_mode, spans, language)
return ITALICS | REDUCE_RANGE
return 0
+58 -49
View File
@@ -17,6 +17,10 @@
var/default_color = "#FFF" // if alien colors are disabled, this is the color that will be used by that race
var/sexes = 1 // whether or not the race has sexual characteristics. at the moment this is only 0 for skeletons and shadows
var/face_y_offset = 0
var/hair_y_offset = 0
var/hair_color = null // this allows races to have specific hair colors... if null, it uses the H's hair/facial hair colors. if "mutcolor", it uses the H's mutant_color
var/hair_alpha = 255 // the alpha used by the hair. 255 is completely solid, 0 is transparent.
var/use_skintones = 0 // does it use skintones or not? (spoiler alert this is only used by humans)
@@ -69,8 +73,6 @@
var/fixed_mut_color3 = ""
var/whitelisted = 0 //Is this species restricted to certain players?
var/whitelist = list() //List the ckeys that can use this species, if it's whitelisted.: list("John Doe", "poopface666", "SeeALiggerPullTheTrigger") Spaces & capitalization can be included or ignored entirely for each key as it checks for both.
var/lang_spoken = HUMAN
var/lang_understood = HUMAN
///////////
// PROCS //
@@ -90,21 +92,21 @@
var/randname
if(gender == MALE)
randname = pick(first_names_male)
randname = pick(GLOB.first_names_male)
else
randname = pick(first_names_female)
randname = pick(GLOB.first_names_female)
if(lastname)
randname += " [lastname]"
else
randname += " [pick(last_names)]"
randname += " [pick(GLOB.last_names)]"
return randname
//Please override this locally if you want to define when what species qualifies for what rank if human authority is enforced.
/datum/species/proc/qualifies_for_rank(rank, list/features)
if(rank in command_positions)
if(rank in GLOB.command_positions)
return 0
return 1
@@ -205,7 +207,7 @@
facialhair_hidden = TRUE
if(H.facial_hair_style && (FACEHAIR in species_traits) && (!facialhair_hidden || dynamic_fhair_suffix))
S = facial_hair_styles_list[H.facial_hair_style]
S = GLOB.facial_hair_styles_list[H.facial_hair_style]
if(S)
//List of all valid dynamic_fhair_suffixes
@@ -262,7 +264,7 @@
standing += image("icon"='icons/mob/human_face.dmi', "icon_state" = "debrained", "layer" = -HAIR_LAYER)
else if(H.hair_style && (HAIR in species_traits))
S = hair_styles_list[H.hair_style]
S = GLOB.hair_styles_list[H.hair_style]
if(S)
//List of all valid dynamic_hair_suffixes
@@ -295,6 +297,7 @@
img_hair.color = forced_colour
img_hair.alpha = hair_alpha
img_hair.pixel_y += hair_y_offset
standing += img_hair
if(standing.len)
@@ -311,33 +314,36 @@
// eyes
var/has_eyes = (H.getorgan(/obj/item/organ/eyes) && HD)
var/has_eyes = TRUE
if(!has_eyes)
if(!H.getorgan(/obj/item/organ/eyes) && HD)
standing += image("icon"='icons/mob/human_face.dmi', "icon_state" = "eyes_missing", "layer" = -BODY_LAYER)
has_eyes = FALSE
if(!HUSK)
if(!(H.disabilities & HUSK))
// lipstick
if(H.lip_style && (LIPS in species_traits) && HD)
var/image/lips = image("icon"='icons/mob/human_face.dmi', "icon_state"="lips_[H.lip_style]", "layer" = -BODY_LAYER)
lips.color = H.lip_color
lips.pixel_y += face_y_offset
standing += lips
// eyes
if((EYECOLOR in species_traits) && HD && has_eyes)
var/image/img_eyes = image("icon" = 'icons/mob/human_face.dmi', "icon_state" = "eyes", "layer" = -BODY_LAYER)
img_eyes.color = "#" + H.eye_color
img_eyes.pixel_y += face_y_offset
standing += img_eyes
//Underwear, Undershirts & Socks
/*This will be refactored at a later date
if(H.underwear)
var/datum/sprite_accessory/underwear/underwear = underwear_list[H.underwear]
var/datum/sprite_accessory/underwear/underwear = GLOB.underwear_list[H.underwear]
if(underwear)
standing += image("icon"=underwear.icon, "icon_state"="[underwear.icon_state]", "layer"=-BODY_LAYER)
if(H.undershirt)
var/datum/sprite_accessory/undershirt/undershirt = undershirt_list[H.undershirt]
var/datum/sprite_accessory/undershirt/undershirt = GLOB.undershirt_list[H.undershirt]
if(undershirt)
if(H.dna.species.sexes && H.gender == FEMALE)
standing += wear_female_version("[undershirt.icon_state]", undershirt.icon, BODY_LAYER)
@@ -345,7 +351,7 @@
standing += image("icon"=undershirt.icon, "icon_state"="[undershirt.icon_state]", "layer"=-BODY_LAYER)
if(H.socks && H.get_num_legs() >= 2 && !(DIGITIGRADE in species_traits))
var/datum/sprite_accessory/socks/socks = socks_list[H.socks]
var/datum/sprite_accessory/socks/socks = GLOB.socks_list[H.socks]
if(socks)
standing += image("icon"=socks.icon, "icon_state"="[socks.icon_state]", "layer"=-BODY_LAYER)
*/
@@ -495,53 +501,53 @@
var/datum/sprite_accessory/S
switch(bodypart)
if("tail_lizard")
S = tails_list_lizard[H.dna.features["tail_lizard"]]
S = GLOB.tails_list_lizard[H.dna.features["tail_lizard"]]
if("waggingtail_lizard")
S.= animated_tails_list_lizard[H.dna.features["tail_lizard"]]
S.= GLOB.animated_tails_list_lizard[H.dna.features["tail_lizard"]]
if("tail_human")
S = tails_list_human[H.dna.features["tail_human"]]
S = GLOB.tails_list_human[H.dna.features["tail_human"]]
if("waggingtail_human")
S.= animated_tails_list_human[H.dna.features["tail_human"]]
S.= GLOB.animated_tails_list_human[H.dna.features["tail_human"]]
if("spines")
S = spines_list[H.dna.features["spines"]]
S = GLOB.spines_list[H.dna.features["spines"]]
if("waggingspines")
S.= animated_spines_list[H.dna.features["spines"]]
S.= GLOB.animated_spines_list[H.dna.features["spines"]]
if("snout")
S = snouts_list[H.dna.features["snout"]]
S = GLOB.snouts_list[H.dna.features["snout"]]
if("frills")
S = frills_list[H.dna.features["frills"]]
S = GLOB.frills_list[H.dna.features["frills"]]
if("horns")
S = horns_list[H.dna.features["horns"]]
S = GLOB.horns_list[H.dna.features["horns"]]
if("ears")
S = ears_list[H.dna.features["ears"]]
S = GLOB.ears_list[H.dna.features["ears"]]
if("body_markings")
S = body_markings_list[H.dna.features["body_markings"]]
S = GLOB.body_markings_list[H.dna.features["body_markings"]]
if("wings")
S = wings_list[H.dna.features["wings"]]
S = GLOB.wings_list[H.dna.features["wings"]]
if("wingsopen")
S = wings_open_list[H.dna.features["wings"]]
S = GLOB.wings_open_list[H.dna.features["wings"]]
if("legs")
S = legs_list[H.dna.features["legs"]]
S = GLOB.legs_list[H.dna.features["legs"]]
//Mammal Bodyparts (Canid/Felid, others maybe in the future)
if("mam_tail")
S = mam_tails_list[H.dna.features["mam_tail"]]
S = GLOB.mam_tails_list[H.dna.features["mam_tail"]]
if("mam_waggingtail")
S.= mam_tails_animated_list[H.dna.features["mam_tail"]]
S.= GLOB.mam_tails_animated_list[H.dna.features["mam_tail"]]
if("mam_body_markings")
S = mam_body_markings_list[H.dna.features["mam_body_markings"]]
S = GLOB.mam_body_markings_list[H.dna.features["mam_body_markings"]]
if("mam_ears")
S = mam_ears_list[H.dna.features["mam_ears"]]
S = GLOB.mam_ears_list[H.dna.features["mam_ears"]]
if("taur")
S = taur_list[H.dna.features["taur"]]
S = GLOB.taur_list[H.dna.features["taur"]]
//Xeno Bodyparts
if("xenodorsal")
S = xeno_dorsal_list[H.dna.features["xenodorsal"]]
S = GLOB.xeno_dorsal_list[H.dna.features["xenodorsal"]]
if("xenohead")
S = xeno_head_list[H.dna.features["xenohead"]]
S = GLOB.xeno_head_list[H.dna.features["xenohead"]]
if("xenotail")
S = xeno_tail_list[H.dna.features["xenotail"]]
S = GLOB.xeno_tail_list[H.dna.features["xenotail"]]
//Slimecoon Bodyparts
/* if("slimecoontail")
@@ -1035,6 +1041,8 @@
return 1
/datum/species/proc/go_bald(mob/living/carbon/human/H)
if(QDELETED(H)) //may be called from a timer
return
H.facial_hair_style = "Shaved"
H.hair_style = "Bald"
H.update_hair()
@@ -1198,9 +1206,9 @@
target.visible_message("<span class='danger'>[user] has weakened [target]!</span>", \
"<span class='userdanger'>[user] has weakened [target]!</span>")
target.apply_effect(4, WEAKEN, armor_block)
target.forcesay(hit_appends)
target.forcesay(GLOB.hit_appends)
else if(target.lying)
target.forcesay(hit_appends)
target.forcesay(GLOB.hit_appends)
@@ -1223,7 +1231,6 @@
return 1
else
user.do_attack_animation(target, ATTACK_EFFECT_DISARM)
add_logs(user, target, "disarmed")
if(target.w_uniform)
target.w_uniform.add_fingerprint(user)
@@ -1234,24 +1241,26 @@
target.visible_message("<span class='danger'>[user] has pushed [target]!</span>",
"<span class='userdanger'>[user] has pushed [target]!</span>", null, COMBAT_MESSAGE_RANGE)
target.apply_effect(2, WEAKEN, target.run_armor_check(affecting, "melee", "Your armor prevents your fall!", "Your armor softens your fall!"))
target.forcesay(hit_appends)
target.forcesay(GLOB.hit_appends)
add_logs(user, target, "disarmed", " pushing them to the ground")
return
var/talked = 0 // BubbleWrap
if(randn <= 60)
//BubbleWrap: Disarming breaks a pull
var/obj/item/I = null
if(target.pulling)
to_chat(target, "<span class='warning'>[user] has broken [target]'s grip on [target.pulling]!</span>")
talked = 1
target.stop_pulling()
//End BubbleWrap
if(!talked) //BubbleWrap
else
I = target.get_active_held_item()
if(target.drop_item())
target.visible_message("<span class='danger'>[user] has disarmed [target]!</span>", \
"<span class='userdanger'>[user] has disarmed [target]!</span>", null, COMBAT_MESSAGE_RANGE)
else
I = null
playsound(target, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
add_logs(user, target, "disarmed", "[I ? " removing \the [I]" : ""]")
return
@@ -1347,7 +1356,7 @@
H.adjust_blurriness(10)
if(prob(I.force + ((100 - H.health)/2)) && H != user)
ticker.mode.remove_revolutionary(H.mind)
SSticker.mode.remove_revolutionary(H.mind)
if(bloody) //Apply blood
if(H.wear_mask)
@@ -1376,7 +1385,7 @@
H.update_inv_w_uniform()
if(Iforce > 10 || Iforce >= 5 && prob(33))
H.forcesay(hit_appends) //forcesay checks stat already.
H.forcesay(GLOB.hit_appends) //forcesay checks stat already.
return TRUE
/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H)
@@ -1480,7 +1489,7 @@
H.apply_damage(HEAT_DAMAGE_LEVEL_3*heatmod, BURN)
else
H.apply_damage(HEAT_DAMAGE_LEVEL_2*heatmod, BURN)
else if(H.bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT && !(mutations_list[COLDRES] in H.dna.mutations))
else if(H.bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT && !(GLOB.mutations_list[COLDRES] in H.dna.mutations))
switch(H.bodytemperature)
if(200 to 260)
H.throw_alert("temp", /obj/screen/alert/cold, 1)
@@ -14,6 +14,8 @@ datum/species/mammal
if(H)
H.endTailWag()
/datum/species/mammal/qualifies_for_rank(rank, list/features)
return TRUE
//AVIAN//
/datum/species/avian
@@ -32,6 +34,9 @@ datum/species/mammal
if(H)
H.endTailWag()
/datum/species/avian/qualifies_for_rank(rank, list/features)
return TRUE
//AQUATIC//
/datum/species/aquatic
name = "Aquatic"
@@ -48,6 +53,10 @@ datum/species/mammal
/datum/species/aquatic/spec_death(gibbed, mob/living/carbon/human/H)
if(H)
H.endTailWag()
/datum/species/aquatic/qualifies_for_rank(rank, list/features)
return TRUE
//INSECT//
/datum/species/insect
name = "Insect"
@@ -65,6 +74,8 @@ datum/species/mammal
if(H)
H.endTailWag()
/datum/species/insect/qualifies_for_rank(rank, list/features)
return TRUE
//HERBIVOROUS//
//EXOTIC//
@@ -1,7 +1,7 @@
/datum/species/golem
// Animated beings of stone. They have increased defenses, and do not need to breathe. They're also slow as fuuuck.
name = "Golem"
id = "iron"
id = "iron golem"
species_traits = list(NOBREATH,RESISTHOT,RESISTCOLD,RESISTPRESSURE,NOFIRE,NOGUNS,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NODISMEMBER,MUTCOLORS)
speedmod = 2
armor = 55
@@ -12,6 +12,7 @@
no_equip = list(slot_wear_mask, slot_wear_suit, slot_gloves, slot_shoes, slot_w_uniform)
nojumpsuit = 1
sexes = 1
damage_overlay_type = ""
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/golem
// To prevent golem subtypes from overwhelming the odds when random species
// changes, only the Random Golem type can be chosen
@@ -21,6 +22,21 @@
fixed_mut_color = "aaa"
var/info_text = "As an <span class='danger'>Iron Golem</span>, you don't have any special traits."
var/prefix = "Iron"
var/list/special_names
/datum/species/golem/random_name(gender,unique,lastname)
var/golem_surname = pick(GLOB.golem_names)
// 3% chance that our golem has a human surname, because
// cultural contamination
if(prob(3))
golem_surname = pick(GLOB.last_names)
else if(special_names && prob(5))
golem_surname = pick(special_names)
var/golem_name = "[prefix] [golem_surname]"
return golem_name
/datum/species/golem/random
name = "Random Golem"
blacklisted = FALSE
@@ -36,21 +52,24 @@
/datum/species/golem/adamantine
name = "Adamantine Golem"
id = "adamantine"
id = "adamantine golem"
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/golem/adamantine
fixed_mut_color = "4ed"
info_text = "As an <span class='danger'>Adamantine Golem</span>, you don't have any special traits."
prefix = "Adamantine"
//Explodes on death
/datum/species/golem/plasma
name = "Plasma Golem"
id = "plasma"
id = "plasma golem"
fixed_mut_color = "a3d"
meat = /obj/item/weapon/ore/plasma
//Can burn and takes damage from heat
species_traits = list(NOBREATH,RESISTCOLD,RESISTPRESSURE,NOGUNS,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NODISMEMBER,MUTCOLORS)
info_text = "As a <span class='danger'>Plasma Golem</span>, you explode on death!"
burnmod = 1.5
prefix = "Plasma"
special_names = list("Flood","Fire","Bar","Man")
/datum/species/golem/plasma/spec_death(gibbed, mob/living/carbon/human/H)
explosion(get_turf(H),0,1,2,flame_range = 5)
@@ -60,35 +79,40 @@
//Harder to hurt
/datum/species/golem/diamond
name = "Diamond Golem"
id = "diamond"
id = "diamond golem"
fixed_mut_color = "0ff"
armor = 70 //up from 55
meat = /obj/item/weapon/ore/diamond
info_text = "As a <span class='danger'>Diamond Golem</span>, you are more resistant than the average golem."
prefix = "Diamond"
special_names = list("Back")
//Faster but softer and less armoured
/datum/species/golem/gold
name = "Gold Golem"
id = "gold"
id = "gold golem"
fixed_mut_color = "cc0"
speedmod = 1
armor = 25 //down from 55
meat = /obj/item/weapon/ore/gold
info_text = "As a <span class='danger'>Gold Golem</span>, you are faster but less resistant than the average golem."
prefix = "Golden"
//Heavier, thus higher chance of stunning when punching
/datum/species/golem/silver
name = "Silver Golem"
id = "silver"
id = "silver golem"
fixed_mut_color = "ddd"
punchstunthreshold = 9 //60% chance, from 40%
meat = /obj/item/weapon/ore/silver
info_text = "As a <span class='danger'>Silver Golem</span>, your attacks are heavier and have a higher chance of stunning."
prefix = "Silver"
special_names = list("Surfer", "Chariot", "Lining")
//Harder to stun, deals more damage, but it's even slower
/datum/species/golem/plasteel
name = "Plasteel Golem"
id = "plasteel"
id = "plasteel golem"
fixed_mut_color = "bbb"
stunmod = 0.40
punchdamagelow = 12
@@ -99,15 +123,17 @@
info_text = "As a <span class='danger'>Plasteel Golem</span>, you are slower, but harder to stun, and hit very hard when punching."
attack_verb = "smash"
attack_sound = 'sound/effects/meteorimpact.ogg' //hits pretty hard
prefix = "Plasteel"
//Immune to ash storms
/datum/species/golem/titanium
name = "Titanium Golem"
id = "titanium"
id = "titanium golem"
fixed_mut_color = "fff"
meat = /obj/item/weapon/ore/titanium
info_text = "As a <span class='danger'>Titanium Golem</span>, you are immune to ash storms, and slightly more resistant to burn damage."
burnmod = 0.9
prefix = "Titanium"
/datum/species/golem/titanium/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
@@ -120,11 +146,12 @@
//Immune to ash storms and lava
/datum/species/golem/plastitanium
name = "Plastitanium Golem"
id = "plastitanium"
id = "plastitanium golem"
fixed_mut_color = "888"
meat = /obj/item/weapon/ore/titanium
info_text = "As a <span class='danger'>Plastitanium Golem</span>, you are immune to both ash storms and lava, and slightly more resistant to burn damage."
burnmod = 0.8
prefix = "Plastitanium"
/datum/species/golem/plastitanium/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
@@ -139,12 +166,14 @@
//Fast and regenerates... but can only speak like an abductor
/datum/species/golem/alloy
name = "Alien Alloy Golem"
id = "alloy"
id = "alloy golem"
fixed_mut_color = "333"
meat = /obj/item/stack/sheet/mineral/abductor
mutant_organs = list(/obj/item/organ/tongue/abductor) //abductor tongue
speedmod = 1 //faster
info_text = "As an <span class='danger'>Alloy Golem</span>, you are made of advanced alien materials: you are faster and regenerate over time. You are, however, only able to be heard by other alloy golems."
prefix = "Alien"
special_names = list("Outsider", "Technology", "Watcher", "Stranger") //ominous and unknown
//Regenerates because self-repairing super-advanced alien tech
/datum/species/golem/alloy/spec_life(mob/living/carbon/human/H)
@@ -157,7 +186,7 @@
//Since this will usually be created from a collaboration between podpeople and free golems, wood golems are a mix between the two races
/datum/species/golem/wood
name = "Wood Golem"
id = "wood"
id = "wood golem"
fixed_mut_color = "49311c"
meat = /obj/item/stack/sheet/mineral/wood
//Can burn and take damage from heat
@@ -166,6 +195,13 @@
burnmod = 1.25
heatmod = 1.5
info_text = "As a <span class='danger'>Wooden Golem</span>, you have plant-like traits: you take damage from extreme temperatures, can be set on fire, and have lower armor than a normal golem. You regenerate when in the light and wither in the darkness."
prefix = "Wooden"
/datum/species/golem/wood/random_name(gender,unique,lastname)
var/plant_name = pick("Tomato", "Potato", "Broccoli", "Carrot", "Ambrosia", "Pumpkin", "Ivy", "Kudzu", "Banana", "Moss", "Flower", "Bloom", "Root", "Bark", "Glowshroom", "Petal", "Leaf", \
"Venus", "Sprout","Cocoa", "Strawberry", "Citrus", "Oak", "Cactus", "Pepper", "Juniper")
var/golem_name = "[prefix] [plant_name]"
return golem_name
/datum/species/golem/wood/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
@@ -204,13 +240,14 @@
//Radioactive
/datum/species/golem/uranium
name = "Uranium Golem"
id = "uranium"
id = "uranium golem"
fixed_mut_color = "7f0"
meat = /obj/item/weapon/ore/uranium
info_text = "As an <span class='danger'>Uranium Golem</span>, you emit radiation pulses every once in a while. It won't harm fellow golems, but organic lifeforms will be affected."
var/last_event = 0
var/active = null
prefix = "Uranium"
/datum/species/golem/uranium/spec_life(mob/living/carbon/human/H)
if(!active)
@@ -224,7 +261,7 @@
//Immune to physical bullets and resistant to brute, but very vulnerable to burn damage. Dusts on death.
/datum/species/golem/sand
name = "Sand Golem"
id = "sand"
id = "sand golem"
fixed_mut_color = "ffdc8f"
meat = /obj/item/weapon/ore/glass //this is sand
armor = 0
@@ -232,6 +269,7 @@
brutemod = 0.25
info_text = "As a <span class='danger'>Sand Golem</span>, you are immune to physical bullets and take very little brute damage, but are extremely vulnerable to burn damage. You will also turn to sand when dying, preventing any form of recovery."
attack_sound = 'sound/effects/shovel_dig.ogg'
prefix = "Sand"
/datum/species/golem/sand/spec_death(gibbed, mob/living/carbon/human/H)
H.visible_message("<span class='danger'>[H] turns into a pile of sand!</span>")
@@ -253,7 +291,7 @@
//Reflects lasers and resistant to burn damage, but very vulnerable to brute damage. Shatters on death.
/datum/species/golem/glass
name = "Glass Golem"
id = "glass"
id = "glass golem"
fixed_mut_color = "5a96b4aa" //transparent body
meat = /obj/item/weapon/shard
armor = 0
@@ -261,6 +299,7 @@
burnmod = 0.25
info_text = "As a <span class='danger'>Glass Golem</span>, you reflect lasers and energy weapons, and are very resistant to burn damage, but you are extremely vulnerable to brute damage. On death, you'll shatter beyond any hope of recovery."
attack_sound = 'sound/effects/Glassbr2.ogg'
prefix = "Glass"
/datum/species/golem/glass/spec_death(gibbed, mob/living/carbon/human/H)
playsound(H, "shatter", 70, 1)
@@ -295,12 +334,14 @@
//Teleports when hit or when it wants to
/datum/species/golem/bluespace
name = "Bluespace Golem"
id = "bluespace"
id = "bluespace golem"
fixed_mut_color = "33f"
meat = /obj/item/weapon/ore/bluespace_crystal
info_text = "As a <span class='danger'>Bluespace Golem</span>, are spatially unstable: you will teleport when hit, and you can teleport manually at a long distance."
attack_verb = "bluespace punch"
attack_sound = 'sound/effects/phasein.ogg'
prefix = "Bluespace"
special_names = list("Crystal", "Polycrystal")
var/datum/action/innate/unstable_teleport/unstable_teleport
var/teleport_cooldown = 100
@@ -384,7 +425,7 @@
//honk
/datum/species/golem/bananium
name = "Bananium Golem"
id = "bananium"
id = "bananium golem"
fixed_mut_color = "ff0"
say_mod = "honks"
punchdamagelow = 0
@@ -394,6 +435,7 @@
info_text = "As a <span class='danger'>Bananium Golem</span>, you are made for pranking. Your body emits natural honks, and you cannot hurt people when punching them. Your skin also emits bananas when damaged."
attack_verb = "honk"
attack_sound = 'sound/items/AirHorn2.ogg'
prefix = "Bananium"
var/last_honk = 0
var/honkooldown = 0
@@ -401,6 +443,11 @@
var/banana_cooldown = 100
var/active = null
/datum/species/golem/bananium/random_name(gender,unique,lastname)
var/clown_name = pick(GLOB.clown_names)
var/golem_name = "[uppertext(clown_name)]"
return golem_name
/datum/species/golem/bananium/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style = M.martial_art)
..()
if(world.time > last_banana + banana_cooldown && M != H && M.a_intent != INTENT_HELP)
@@ -449,7 +496,7 @@
/datum/species/golem/runic
name = "Runic Golem"
id = "runic"
id = "runic golem"
limbs_id = "cultgolem"
sexes = FALSE
info_text = "As a <span class='danger'>Runic Golem</span>, you possess eldritch powers granted by the Elder God Nar'Sie."
@@ -459,6 +506,12 @@
var/obj/effect/proc_holder/spell/targeted/abyssal_gaze/abyssal_gaze
var/obj/effect/proc_holder/spell/targeted/dominate/dominate
/datum/species/golem/runic/random_name(gender,unique,lastname)
var/edgy_first_name = pick("Razor","Blood","Dark","Evil","Cold","Pale","Black","Silent","Chaos","Deadly")
var/edgy_last_name = pick("Edge","Night","Death","Razor","Blade","Steel","Calamity","Twilight","Shadow","Nightmare") //dammit Razor Razor
var/golem_name = "[edgy_first_name] [edgy_last_name]"
return golem_name
/datum/species/golem/runic/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
C.faction |= "cult"
@@ -489,3 +542,100 @@
H.adjustFireLoss(-4)
H.reagents.remove_reagent(chem.id, REAGENTS_METABOLISM)
/datum/species/golem/cloth
name = "Cloth Golem"
id = "cloth golem"
limbs_id = "clothgolem"
sexes = FALSE
info_text = "As a <span class='danger'>Cloth Golem</span>, you are able to reform yourself after death, provided your remains aren't burned or destroyed. You are, of course, very flammable."
species_traits = list(NOBREATH,RESISTCOLD,RESISTPRESSURE,NOGUNS,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NODISMEMBER) //no mutcolors, and can burn
armor = 15 //feels no pain, but not too resistant
burnmod = 2 // don't get burned
speedmod = 1 // not as heavy as stone
punchdamagelow = 4
punchstunthreshold = 7
punchdamagehigh = 8 // not as heavy as stone
prefix = "Cloth"
/datum/species/golem/cloth/random_name(gender,unique,lastname)
var/pharaoh_name = pick("Neferkare", "Hudjefa", "Khufu", "Mentuhotep", "Ahmose", "Amenhotep", "Thutmose", "Hatshepsut", "Tutankhamun", "Ramses", "Seti", \
"Merenptah", "Djer", "Semerkhet", "Nynetjer", "Khafre", "Pepi", "Intef", "Ay") //yes, Ay was an actual pharaoh
var/golem_name = "[pharaoh_name] \Roman[rand(1,99)]"
return golem_name
/datum/species/golem/cloth/spec_life(mob/living/carbon/human/H)
if(H.fire_stacks < 1)
H.adjust_fire_stacks(1) //always prone to burning
..()
/datum/species/golem/cloth/spec_death(gibbed, mob/living/carbon/human/H)
if(gibbed)
return
if(H.on_fire)
H.visible_message("<span class='danger'>[H] burns into ash!</span>")
H.dust(just_ash = TRUE)
return
H.visible_message("<span class='danger'>[H] falls apart into a pile of bandages!</span>")
new /obj/structure/cloth_pile(get_turf(H), H)
..()
/obj/structure/cloth_pile
name = "pile of bandages"
desc = "It emits a strange aura, as if there was still life within it..."
obj_integrity = 50
max_integrity = 50
armor = list(melee = 90, bullet = 90, laser = 25, energy = 80, bomb = 50, bio = 100, fire = -50, acid = -50)
icon = 'icons/obj/items.dmi'
icon_state = "pile_bandages"
resistance_flags = FLAMMABLE
var/revive_time = 900
var/mob/living/carbon/human/cloth_golem
/obj/structure/cloth_pile/Initialize(mapload, mob/living/carbon/human/H)
if(!QDELETED(H) && is_species(H, /datum/species/golem/cloth))
H.unequip_everything()
H.forceMove(src)
cloth_golem = H
to_chat(cloth_golem, "<span class='notice'>You start gathering your life energy, preparing to rise again...</span>")
addtimer(CALLBACK(src, .proc/revive), revive_time)
else
qdel(src)
/obj/structure/cloth_pile/Destroy()
if(cloth_golem)
QDEL_NULL(cloth_golem)
return ..()
/obj/structure/cloth_pile/burn()
visible_message("<span class='danger'>[src] burns into ash!</span>")
new /obj/effect/decal/cleanable/ash(get_turf(src))
..()
/obj/structure/cloth_pile/proc/revive()
if(QDELETED(src) || QDELETED(cloth_golem)) //QDELETED also checks for null, so if no cloth golem is set this won't runtime
return
if(cloth_golem.suiciding || cloth_golem.disabilities & NOCLONE)
QDEL_NULL(cloth_golem)
return
invisibility = INVISIBILITY_MAXIMUM //disappear before the animation
new /obj/effect/overlay/temp/mummy_animation(get_turf(src))
if(cloth_golem.revive(full_heal = TRUE, admin_revive = TRUE))
cloth_golem.grab_ghost() //won't pull if it's a suicide
sleep(20)
cloth_golem.forceMove(get_turf(src))
cloth_golem.visible_message("<span class='danger'>[src] rises and reforms into [cloth_golem]!</span>","<span class='userdanger'>You reform into yourself!</span>")
cloth_golem = null
qdel(src)
/obj/structure/cloth_pile/attackby(obj/item/weapon/P, mob/living/carbon/human/user, params)
. = ..()
if(resistance_flags & ON_FIRE)
return
if(P.is_hot())
visible_message("<span class='danger'>[src] bursts into flames!</span>")
fire_act()
@@ -10,9 +10,7 @@
/datum/species/human/qualifies_for_rank(rank, list/features)
if((!features["tail_human"] || features["tail_human"] == "None") && (!features["ears"] || features["ears"] == "None"))
return TRUE //Pure humans are always allowed in all roles.
return ..()
return TRUE
//Curiosity killed the cat's wagging tail.
/datum/species/human/spec_death(gibbed, mob/living/carbon/human/H)
@@ -7,6 +7,7 @@
species_traits = list(MUTCOLORS,EYECOLOR,NOBLOOD,VIRUSIMMUNE,TOXINLOVER)
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/slime
exotic_blood = "slimejelly"
damage_overlay_type = ""
var/datum/action/innate/regenerate_limbs/regenerate_limbs
/datum/species/jelly/on_species_loss(mob/living/carbon/C)
@@ -226,7 +227,7 @@
else
ui_interact(owner)
/datum/action/innate/swap_body/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = conscious_state)
/datum/action/innate/swap_body/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.conscious_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
@@ -7,6 +7,8 @@
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAIR,FACEHAIR)
mutant_bodyparts = list("tail_lizard", "snout", "spines", "horns", "frills", "body_markings", "legs", "taur")
mutant_organs = list(/obj/item/organ/tongue/lizard)
coldmod = 1.5
heatmod = 0.67
default_features = list("mcolor" = "0F0","mcolor2" = "0F0","mcolor3" = "0F0", "tail" = "Smooth", "snout" = "Round", "horns" = "None", "frills" = "None", "spines" = "None", "body_markings" = "None", "legs" = "Normal Legs", "taur" = "None")
attack_verb = "slash"
attack_sound = 'sound/weapons/slash.ogg'
@@ -26,6 +28,9 @@
return randname
/datum/species/lizard/qualifies_for_rank(rank, list/features)
return TRUE
//I wag in death
/datum/species/lizard/spec_death(gibbed, mob/living/carbon/human/H)
if(H)
@@ -38,4 +43,4 @@
name = "Ash Walker"
id = "ashlizard"
limbs_id = "lizard"
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,NOBREATH,NOGUNS,DIGITIGRADE)
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,NOBREATH,NOGUNS,DIGITIGRADE)
@@ -1,5 +1,3 @@
var/global/image/plasmaman_on_fire = image("icon"='icons/mob/OnFire.dmi', "icon_state"="plasmaman")
/datum/species/plasmaman
name = "Plasmaman"
id = "plasmaman"
@@ -52,7 +50,7 @@ var/global/image/plasmaman_on_fire = image("icon"='icons/mob/OnFire.dmi', "icon_
return 0
/datum/species/plasmaman/qualifies_for_rank(rank, list/features)
if(rank in security_positions)
if(rank in GLOB.security_positions)
return 0
if(rank == "Clown" || rank == "Mime")//No funny bussiness
return 0
@@ -99,7 +99,7 @@ There are several things that need to be remembered:
/* --------------------------------------- */
//vvvvvv UPDATE_INV PROCS vvvvvv
/mob/living/carbon/human/update_inv_w_uniform()
/mob/living/carbon/human/update_inv_w_uniform(invdrop = TRUE)
remove_overlay(UNIFORM_LAYER)
if(client && hud_used)
@@ -138,7 +138,7 @@ There are several things that need to be remembered:
overlays_standing[UNIFORM_LAYER] = standing
else if(!(dna && dna.species.nojumpsuit))
else if(!(dna && dna.species.nojumpsuit) && invdrop)
// Automatically drop anything in store / id / belt if you're not wearing a uniform. //CHECK IF NECESARRY
for(var/obj/item/thing in list(r_store, l_store, wear_id, belt)) //
dropItemToGround(thing)
@@ -274,7 +274,7 @@ There are several things that need to be remembered:
client.screen += shoes //add it to client's screen
update_observer_view(shoes,1)
var/image/standing = shoes.build_worn_icon(state = shoes.icon_state, default_layer = SHOES_LAYER, default_icon_file = 'icons/mob/feet.dmi')
overlays_standing[SHOES_LAYER] = standing
overlays_standing[SHOES_LAYER] = standing
apply_overlay(SHOES_LAYER)
@@ -392,10 +392,10 @@ There are several things that need to be remembered:
/proc/wear_female_version(t_color, icon, layer, type)
var/index = t_color
var/icon/female_clothing_icon = female_clothing_icons[index]
var/icon/female_clothing_icon = GLOB.female_clothing_icons[index]
if(!female_clothing_icon) //Create standing/laying icons if they don't exist
generate_female_clothing(index,t_color,icon,type)
var/standing = image("icon"=female_clothing_icons["[t_color]"], "layer"=-layer)
var/standing = image("icon"=GLOB.female_clothing_icons["[t_color]"], "layer"=-layer)
return(standing)
/mob/living/carbon/human/proc/get_overlays_copy(list/unwantedLayers)
@@ -1,10 +1,15 @@
/mob/living/carbon/human/whisper(message as text)
/mob/living/carbon/human/whisper_verb(message as text)
whisper(message)
/mob/living/carbon/human/whisper(message, datum/language/language=null)
if(!IsVocal())
return
if(!message)
return
if(!language)
language = get_default_language()
if(say_disabled) //This is here to try to identify lag problems
if(GLOB.say_disabled) //This is here to try to identify lag problems
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
@@ -44,9 +49,11 @@
message = Ellipsis(message, 10, 1)
message = treat_message(message)
if(!message)
return
var/list/listening_dead = list()
for(var/mob/M in player_list)
for(var/mob/M in GLOB.player_list)
if(M.stat == DEAD && M.client && ((M.client.prefs.chat_toggles & CHAT_GHOSTWHISPER) || (get_dist(M, src) <= 7)))
listening_dead |= M
@@ -71,14 +78,14 @@
for(var/atom/movable/AM in listening)
if(istype(AM,/obj/item/device/radio))
continue
AM.Hear(rendered, src, languages_spoken, message, , spans)
AM.Hear(rendered, src, language, message, , spans)
message = stars(message)
rendered = "<span class='game say'><span class='name'>[GetVoice()]</span>[alt_name] [whispers], <span class='message'>\"[attach_spans(message, spans)]\"</span></span>"
for(var/atom/movable/AM in eavesdropping)
if(istype(AM,/obj/item/device/radio))
continue
AM.Hear(rendered, src, languages_spoken, message, , spans)
AM.Hear(rendered, src, language, message, , spans)
if(critical) //Dying words.
succumb(1)
+4 -6
View File
@@ -29,7 +29,7 @@
//Start of a breath chain, calls breathe()
/mob/living/carbon/handle_breathing()
if(SSmob.times_fired%4==2 || failed_last_breath)
if(SSmobs.times_fired%4==2 || failed_last_breath)
breathe() //Breathe per 4 ticks, unless suffocating
else
if(istype(loc, /obj/))
@@ -47,8 +47,6 @@
if(loc)
environment = loc.return_air()
if(ismob(loc)) return
var/datum/gas_mixture/breath
if(health <= HEALTH_THRESHOLD_CRIT || (pulledby && pulledby.grab_state >= GRAB_KILL && !getorganslot("breathing_tube")))
@@ -132,7 +130,7 @@
if(prob(20))
emote("gasp")
if(O2_partialpressure > 0)
var/ratio = safe_oxy_min/O2_partialpressure
var/ratio = 1 - O2_partialpressure/safe_oxy_min
adjustOxyLoss(min(5*ratio, 3))
failed_last_breath = 1
oxygen_used = breath_gases["o2"][MOLES]*ratio
@@ -255,7 +253,7 @@
dna.previous.Remove("blood_type")
dna.temporary_mutations.Remove(mut)
continue
HM = mutations_list[mut]
HM = GLOB.mutations_list[mut]
HM.force_lose(src)
dna.temporary_mutations.Remove(mut)
@@ -294,7 +292,7 @@
stomach_contents.Remove(M)
qdel(M)
continue
if(SSmob.times_fired%3==1)
if(SSmobs.times_fired%3==1)
if(!(M.status_flags & GODMODE))
M.adjustBruteLoss(5)
nutrition += 10
@@ -16,6 +16,8 @@
var/pickpocketing = FALSE
var/disposing_body = FALSE
var/obj/machinery/disposal/bodyDisposal = null
var/next_battle_screech = 0
var/battle_screech_cooldown = 50
/mob/living/carbon/monkey/proc/IsStandingStill()
return resisting || pickpocketing || disposing_body
@@ -59,6 +61,12 @@
return 1
return 0
/mob/living/carbon/monkey/proc/battle_screech()
if(next_battle_screech < world.time)
emote(pick("roar","screech"))
for(var/mob/living/carbon/monkey/M in view(7,src))
M.next_battle_screech = world.time + battle_screech_cooldown
/mob/living/carbon/monkey/proc/equip_item(var/obj/item/I)
if(I.loc == src)
@@ -197,7 +205,7 @@
for(var/mob/living/L in around)
if( should_target(L) )
if(L.stat == CONSCIOUS)
emote(pick("roar","screech"))
battle_screech()
retaliate(L)
return TRUE
else if(bodyDisposal)
@@ -241,7 +249,7 @@
var/list/around = view(src, MONKEY_ENEMY_VISION)
for(var/mob/living/carbon/monkey/M in around)
if(M.mode == MONKEY_IDLE && prob(MONKEY_RECRUIT_PROB))
M.emote(pick("roar","screech"))
M.battle_screech()
M.target = target
M.mode = MONKEY_HUNT
@@ -406,7 +414,7 @@
enemies[L] += MONKEY_HATRED_AMOUNT
if(a_intent != INTENT_HARM)
emote(pick("roar","screech"))
battle_screech()
a_intent = INTENT_HARM
/mob/living/carbon/monkey/attack_hand(mob/living/L)
@@ -16,7 +16,7 @@
if(stat == CONSCIOUS)
if(!handle_combat())
if(prob(33) && canmove && isturf(loc) && !pulledby)
step(src, pick(cardinal))
step(src, pick(GLOB.cardinal))
if(prob(1))
emote(pick("scratch","jump","roll","tail"))
else
@@ -2,18 +2,16 @@
name = "monkey"
voice_name = "monkey"
verb_say = "chimpers"
initial_languages = list(/datum/language/monkey)
icon = 'icons/mob/monkey.dmi'
icon_state = ""
gender = NEUTER
pass_flags = PASSTABLE
languages_spoken = MONKEY
languages_understood = MONKEY
ventcrawler = VENTCRAWLER_NUDE
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/monkey = 5, /obj/item/stack/sheet/animalhide/monkey = 1)
type_of_meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/monkey
gib_type = /obj/effect/decal/cleanable/blood/gibs
unique_name = 1
devourable = 1
bodyparts = list(/obj/item/bodypart/chest/monkey, /obj/item/bodypart/head/monkey, /obj/item/bodypart/l_arm/monkey,
/obj/item/bodypart/r_arm/monkey, /obj/item/bodypart/r_leg/monkey, /obj/item/bodypart/l_leg/monkey)
@@ -160,4 +158,4 @@
if(prob(10))
var/obj/item/clothing/head/helmet/justice/escape/helmet = new(src)
equip_to_slot_or_del(helmet,slot_head)
helmet.attack_self(src) // todo encapsulate toggle
helmet.attack_self(src) // todo encapsulate toggle
@@ -117,26 +117,33 @@
playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to lunge at [name]!</span>", \
"<span class='userdanger'>[M] has attempted to lunge at [name]!</span>", null, COMBAT_MESSAGE_RANGE)
if (M.a_intent == INTENT_DISARM)
var/obj/item/I = null
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
if(prob(95))
Weaken(10)
visible_message("<span class='danger'>[M] has tackled down [name]!</span>", \
"<span class='userdanger'>[M] has tackled down [name]!</span>", null, COMBAT_MESSAGE_RANGE)
else
I = get_active_held_item()
if(drop_item())
visible_message("<span class='danger'>[M] has disarmed [name]!</span>", \
"<span class='userdanger'>[M] has disarmed [name]!</span>", null, COMBAT_MESSAGE_RANGE)
add_logs(M, src, "disarmed")
else
I = null//did not manage to actually disarm the item, gross but no time to refactor
add_logs(M, src, "disarmed", "[I ? " removing \the [I]" : ""]")
updatehealth()
/mob/living/carbon/monkey/attack_animal(mob/living/simple_animal/M)
if(..())
. = ..()
if(.)
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
var/dam_zone = dismembering_strike(M, pick("chest", "l_hand", "r_hand", "l_leg", "r_leg"))
if(!dam_zone) //Dismemberment successful
return 1
return TRUE
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
if(!affecting)
affecting = get_bodypart("chest")
@@ -32,7 +32,7 @@
equip_to_slot_or_del(new relic_mask, slot_wear_mask)
/mob/living/carbon/monkey/punpun/Life()
if(ticker.current_state == GAME_STATE_FINISHED && !memory_saved)
if(SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
Write_Memory(0)
..()
@@ -68,7 +68,7 @@
//update whether our neck item appears on our hud.
/mob/living/carbon/monkey/update_hud_neck(obj/item/I)
if(client && hud_used && hud_used.hud_shown)
I.screen_loc = ui_monkey_mask
I.screen_loc = ui_monkey_neck
client.screen += I
//update whether our back item appears on our hud.
+12
View File
@@ -28,3 +28,15 @@
var/obj/item/I = get_active_held_item()
if(I)
. |= I.get_held_item_speechspans(src)
/mob/living/carbon/can_speak_in_language(datum/language/dt)
if(HAS_SECONDARY_FLAG(src, OMNITONGUE))
. = has_language(dt)
else if(has_language(dt))
var/obj/item/organ/tongue/T = getorganslot("tongue")
if(T)
. = T.can_speak_in_language(dt)
else
. = initial(dt.flags) & TONGUELESS_SPEECH
else
. = FALSE
@@ -276,12 +276,6 @@
See RemieRichards on irc.rizon.net #coderbus
*/
var/global/list/limb_icon_cache = list()
/mob/living/carbon
var/icon_render_key = ""
//produces a key based on the mob's limbs
/mob/living/carbon/proc/generate_icon_render_key()
+5 -5
View File
@@ -26,20 +26,20 @@
/mob/living/proc/spread_bodyparts()
return
/mob/living/dust()
/mob/living/dust(just_ash = FALSE)
death(1)
if(buckled)
buckled.unbuckle_mob(src,force=1)
dust_animation()
spawn_dust()
spawn_dust(just_ash)
qdel(src)
/mob/living/proc/dust_animation()
return
/mob/living/proc/spawn_dust()
/mob/living/proc/spawn_dust(just_ash = FALSE)
new /obj/effect/decal/cleanable/ash(loc)
@@ -55,9 +55,9 @@
deadchat_broadcast(rendered, follow_target = src, turf_target = T, message_type=DEADCHAT_DEATHRATTLE)
if(mind)
mind.store_memory("Time of death: [tod]", 0)
living_mob_list -= src
GLOB.living_mob_list -= src
if(!gibbed)
dead_mob_list += src
GLOB.dead_mob_list += src
paralysis = 0
stunned = 0
weakened = 0
+5 -2
View File
@@ -7,7 +7,8 @@
param = copytext(act, custom_param + 1, length(act) + 1)
act = copytext(act, 1, custom_param)
var/datum/emote/E = emote_list[act]
var/datum/emote/E
E = E.emote_list[act]
if(!E)
to_chat(src, "<span class='notice'>Unusable emote '[act]'. Say *help for a list.</span>")
return
@@ -426,10 +427,12 @@
var/list/keys = list()
var/list/message = list("Available emotes, you can use them with say \"*emote\": ")
var/datum/emote/E
var/list/emote_list = E.emote_list
for(var/e in emote_list)
if(e in keys)
continue
var/datum/emote/E = emote_list[e]
E = emote_list[e]
if(E.can_run_emote(user, TRUE))
keys += E.key
+2 -5
View File
@@ -9,7 +9,7 @@
return
if(!loc)
if(client)
for(var/obj/effect/landmark/error/E in landmarks_list)
for(var/obj/effect/landmark/error/E in GLOB.landmarks_list)
loc = E.loc
break
message_admins("[key_name_admin(src)] was found to have no .loc with an attached client, if the cause is unknown it would be wise to ask how this was accomplished.")
@@ -40,9 +40,6 @@
//stuff in the stomach
handle_stomach()
// Vore code for belly processes
handle_internal_contents()
update_gravity(mob_has_gravity())
if(machine)
@@ -70,7 +67,7 @@
if(!digitaldisguise)
src.digitaldisguise = image(loc = src)
src.digitaldisguise.override = 1
for(var/mob/living/silicon/ai/AI in player_list)
for(var/mob/living/silicon/ai/AI in GLOB.player_list)
AI.client.images |= src.digitaldisguise
+26 -26
View File
@@ -2,7 +2,7 @@
. = ..()
generateStaticOverlay()
if(staticOverlays.len)
for(var/mob/living/simple_animal/drone/D in player_list)
for(var/mob/living/simple_animal/drone/D in GLOB.player_list)
if(D && D.seeStatic)
if(D.staticChoice in staticOverlays)
D.staticOverlays |= staticOverlays[D.staticChoice]
@@ -13,10 +13,12 @@
if(unique_name)
name = "[name] ([rand(1, 1000)])"
real_name = name
var/datum/atom_hud/data/human/medical/advanced/medhud = huds[DATA_HUD_MEDICAL_ADVANCED]
var/datum/atom_hud/data/human/medical/advanced/medhud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
medhud.add_to_hud(src)
faction += "\ref[src]"
language_menu = new(src)
/mob/living/prepare_huds()
..()
@@ -33,7 +35,7 @@
buckled.unbuckle_mob(src,force=1)
QDEL_NULL(riding_datum)
for(var/mob/living/simple_animal/drone/D in player_list)
for(var/mob/living/simple_animal/drone/D in GLOB.player_list)
for(var/image/I in staticOverlays)
D.staticOverlays.Remove(I)
D.client.images.Remove(I)
@@ -41,6 +43,8 @@
staticOverlays.len = 0
remove_from_all_data_huds()
QDEL_NULL(language_menu)
return ..()
/mob/living/ghostize(can_reenter_corpse = 1)
@@ -342,8 +346,8 @@
if(full_heal)
fully_heal(admin_revive)
if(stat == DEAD && can_be_revived()) //in some cases you can't revive (e.g. no brain)
dead_mob_list -= src
living_mob_list += src
GLOB.dead_mob_list -= src
GLOB.living_mob_list += src
suiciding = 0
stat = UNCONSCIOUS //the mob starts unconscious,
blind_eyes(1)
@@ -480,7 +484,7 @@
newdir = NORTH
else if(newdir == 12) //E + W
newdir = EAST
if((newdir in cardinal) && (prob(50)))
if((newdir in GLOB.cardinal) && (prob(50)))
newdir = turn(get_dir(T, src.loc), 180)
if(!blood_exists)
new /obj/effect/decal/cleanable/trail_holder(src.loc)
@@ -546,9 +550,6 @@
if(buckled && last_special <= world.time)
resist_buckle()
// climbing out of a gut
if(attempt_vr(src,"vore_process_resist",args)) return TRUE
//Breaking out of a container (Locker, sleeper, cryo...)
else if(isobj(loc))
var/obj/C = loc
@@ -598,7 +599,7 @@
return name
/mob/living/update_gravity(has_gravity,override = 0)
if(!ticker || !ticker.mode)
if(!SSticker || !SSticker.mode)
return
if(has_gravity)
clear_alert("weightless")
@@ -668,7 +669,8 @@
if(what && Adjacent(who) && what.mob_can_equip(who, src, final_where, TRUE))
if(temporarilyRemoveItemFromInventory(what))
if(where_list)
who.put_in_hand(what, where_list[2])
if(!who.put_in_hand(what, where_list[2]))
what.forceMove(get_turf(who))
else
who.equip_to_slot(what, where, TRUE)
@@ -725,14 +727,14 @@
..()
if(statpanel("Status"))
if(ticker && ticker.mode)
for(var/datum/gang/G in ticker.mode.gangs)
if(SSticker && SSticker.mode)
for(var/datum/gang/G in SSticker.mode.gangs)
if(G.is_dominating)
stat(null, "[G.name] Gang Takeover: [max(G.domination_time_remaining(), 0)]")
if(istype(ticker.mode, /datum/game_mode/blob))
var/datum/game_mode/blob/B = ticker.mode
if(istype(SSticker.mode, /datum/game_mode/blob))
var/datum/game_mode/blob/B = SSticker.mode
if(B.message_sent)
stat(null, "Blobs to Blob Win: [blobs_legit.len]/[B.blobwincount]")
stat(null, "Blobs to Blob Win: [GLOB.blobs_legit.len]/[B.blobwincount]")
/mob/living/cancel_camera()
..()
@@ -802,9 +804,6 @@
setStaminaLoss(health - 2)
update_health_hud()
/mob/proc/update_sight()
return
/mob/living/proc/owns_soul()
if(mind)
return mind.soulOwner == mind
@@ -910,13 +909,14 @@
// used by secbot and monkeys Crossed
/mob/living/proc/knockOver(var/mob/living/carbon/C)
C.visible_message("<span class='warning'>[pick( \
"[C] dives out of [src]'s way!", \
"[C] stumbles over [src]!", \
"[C] jumps out of [src]'s path!", \
"[C] trips over [src] and falls!", \
"[C] topples over [src]!", \
"[C] leaps out of [src]'s way!")]</span>")
if(C.key) //save us from monkey hordes
C.visible_message("<span class='warning'>[pick( \
"[C] dives out of [src]'s way!", \
"[C] stumbles over [src]!", \
"[C] jumps out of [src]'s path!", \
"[C] trips over [src] and falls!", \
"[C] topples over [src]!", \
"[C] leaps out of [src]'s way!")]</span>")
C.Weaken(2)
/mob/living/post_buckle_mob(mob/living/M)
+2 -6
View File
@@ -122,7 +122,7 @@
IgniteMob()
/mob/living/proc/grabbedby(mob/living/carbon/user, supress_message = 0)
if(user == src || anchored)
if(user == src || anchored || !isturf(user.loc))
return 0
if(!user.pulling || user.pulling != src)
user.start_pulling(src, supress_message)
@@ -172,7 +172,7 @@
/mob/living/attack_slime(mob/living/simple_animal/slime/M)
if(!ticker || !ticker.mode)
if(!SSticker || !SSticker.mode)
to_chat(M, "You cannot attack people before the game has started.")
return
@@ -244,10 +244,6 @@
return 0
/mob/living/attack_alien(mob/living/carbon/alien/humanoid/M)
if(isturf(loc) && istype(loc.loc, /area/start))
to_chat(M, "No attacking people at spawn, you jackass.")
return 0
switch(M.a_intent)
if ("help")
visible_message("<span class='notice'>[M] caresses [src] with its scythe like arm.</span>")
+4 -3
View File
@@ -1,7 +1,5 @@
/mob/living
see_invisible = SEE_INVISIBLE_LIVING
languages_spoken = HUMAN
languages_understood = HUMAN
sight = 0
see_in_dark = 2
hud_possible = list(HEALTH_HUD,STATUS_HUD,ANTAG_HUD)
@@ -74,4 +72,7 @@
var/list/implants = null
var/tesla_ignore = FALSE
var/datum/riding/riding_datum
var/datum/riding/riding_datum
var/datum/language/selected_default_language
var/datum/language_menu/language_menu
+2 -2
View File
@@ -5,8 +5,8 @@
mind.show_memory(src, 0)
//Round specific stuff
if(ticker && ticker.mode)
switch(ticker.mode.name)
if(SSticker && SSticker.mode)
switch(SSticker.mode.name)
if("sandbox")
CanBuild()
+198 -100
View File
@@ -1,70 +1,69 @@
var/list/department_radio_keys = list(
":r" = "right hand", "#r" = "right hand", ".r" = "right hand",
":l" = "left hand", "#l" = "left hand", ".l" = "left hand",
":i" = "intercom", "#i" = "intercom", ".i" = "intercom",
":h" = "department", "#h" = "department", ".h" = "department",
":c" = "Command", "#c" = "Command", ".c" = "Command",
":n" = "Science", "#n" = "Science", ".n" = "Science",
":m" = "Medical", "#m" = "Medical", ".m" = "Medical",
":e" = "Engineering", "#e" = "Engineering", ".e" = "Engineering",
":s" = "Security", "#s" = "Security", ".s" = "Security",
":w" = "whisper", "#w" = "whisper", ".w" = "whisper",
":b" = "binary", "#b" = "binary", ".b" = "binary",
":a" = "alientalk", "#a" = "alientalk", ".a" = "alientalk",
":t" = "Syndicate", "#t" = "Syndicate", ".t" = "Syndicate",
":u" = "Supply", "#u" = "Supply", ".u" = "Supply",
":v" = "Service", "#v" = "Service", ".v" = "Service",
":o" = "AI Private", "#o" = "AI Private", ".o" = "AI Private",
":g" = "changeling", "#g" = "changeling", ".g" = "changeling",
":y" = "Centcom", "#y" = "Centcom", ".y" = "Centcom",
":x" = "cords", "#x" = "cords", ".x" = "cords",
":p" = "admin", "#p" = "admin", ".p" = "admin",
":d" = "deadmin", "#d" = "deadmin", ".d" = "deadmin",
GLOBAL_LIST_INIT(department_radio_keys, list(
":r" = "right hand", ".r" = "right hand",
":l" = "left hand", ".l" = "left hand",
":i" = "intercom", ".i" = "intercom",
":h" = "department", ".h" = "department",
":c" = "Command", ".c" = "Command",
":n" = "Science", ".n" = "Science",
":m" = "Medical", ".m" = "Medical",
":e" = "Engineering", ".e" = "Engineering",
":s" = "Security", ".s" = "Security",
":b" = "binary", ".b" = "binary",
":a" = "alientalk", ".a" = "alientalk",
":t" = "Syndicate", ".t" = "Syndicate",
":u" = "Supply", ".u" = "Supply",
":v" = "Service", ".v" = "Service",
":o" = "AI Private", ".o" = "AI Private",
":g" = "changeling", ".g" = "changeling",
":y" = "Centcom", ".y" = "Centcom",
":x" = "cords", ".x" = "cords",
":p" = "admin", ".p" = "admin",
":d" = "deadmin", ".d" = "deadmin",
":R" = "right hand", "#R" = "right hand", ".R" = "right hand",
":L" = "left hand", "#L" = "left hand", ".L" = "left hand",
":I" = "intercom", "#I" = "intercom", ".I" = "intercom",
":H" = "department", "#H" = "department", ".H" = "department",
":C" = "Command", "#C" = "Command", ".C" = "Command",
":N" = "Science", "#N" = "Science", ".N" = "Science",
":M" = "Medical", "#M" = "Medical", ".M" = "Medical",
":E" = "Engineering", "#E" = "Engineering", ".E" = "Engineering",
":S" = "Security", "#S" = "Security", ".S" = "Security",
":W" = "whisper", "#W" = "whisper", ".W" = "whisper",
":B" = "binary", "#B" = "binary", ".B" = "binary",
":A" = "alientalk", "#A" = "alientalk", ".A" = "alientalk",
":T" = "Syndicate", "#T" = "Syndicate", ".T" = "Syndicate",
":U" = "Supply", "#U" = "Supply", ".U" = "Supply",
":V" = "Service", "#V" = "Service", ".V" = "Service",
":O" = "AI Private", "#O" = "AI Private", ".O" = "AI Private",
":G" = "changeling", "#G" = "changeling", ".G" = "changeling",
":Y" = "Centcom", "#Y" = "Centcom", ".Y" = "Centcom",
":X" = "cords", "#X" = "cords", ".X" = "cords",
":P" = "admin", "#P" = "admin", ".P" = "admin",
":D" = "deadmin", "#D" = "deadmin", ".D" = "deadmin",
":R" = "right hand", ".R" = "right hand",
":L" = "left hand", ".L" = "left hand",
":I" = "intercom", ".I" = "intercom",
":H" = "department", ".H" = "department",
":C" = "Command", ".C" = "Command",
":N" = "Science", ".N" = "Science",
":M" = "Medical", ".M" = "Medical",
":E" = "Engineering", ".E" = "Engineering",
":S" = "Security", ".S" = "Security",
":B" = "binary", ".B" = "binary",
":A" = "alientalk", ".A" = "alientalk",
":T" = "Syndicate", ".T" = "Syndicate",
":U" = "Supply", ".U" = "Supply",
":V" = "Service", ".V" = "Service",
":O" = "AI Private", ".O" = "AI Private",
":G" = "changeling", ".G" = "changeling",
":Y" = "Centcom", ".Y" = "Centcom",
":X" = "cords", ".X" = "cords",
":P" = "admin", ".P" = "admin",
":D" = "deadmin", ".D" = "deadmin",
//kinda localization -- rastaf0
//same keys as above, but on russian keyboard layout. This file uses cp1251 as encoding.
":ê" = "right hand", "#ê" = "right hand", ".ê" = "right hand",
":ä" = "left hand", "#ä" = "left hand", ".ä" = "left hand",
":ø" = "intercom", "#ø" = "intercom", ".ø" = "intercom",
":ð" = "department", "#ð" = "department", ".ð" = "department",
":ñ" = "Command", "#ñ" = "Command", ".ñ" = "Command",
":ò" = "Science", "#ò" = "Science", ".ò" = "Science",
":ü" = "Medical", "#ü" = "Medical", ".ü" = "Medical",
":ó" = "Engineering", "#ó" = "Engineering", ".ó" = "Engineering",
":û" = "Security", "#û" = "Security", ".û" = "Security",
":ö" = "whisper", "#ö" = "whisper", ".ö" = "whisper",
":è" = "binary", "#è" = "binary", ".è" = "binary",
":ô" = "alientalk", "#ô" = "alientalk", ".ô" = "alientalk",
":å" = "Syndicate", "#å" = "Syndicate", ".å" = "Syndicate",
":é" = "Supply", "#é" = "Supply", ".é" = "Supply",
":ï" = "changeling", "#ï" = "changeling", ".ï" = "changeling"
)
":ê" = "right hand", ".ê" = "right hand",
":ä" = "left hand", ".ä" = "left hand",
":ø" = "intercom", ".ø" = "intercom",
":ð" = "department", ".ð" = "department",
":ñ" = "Command", ".ñ" = "Command",
":ò" = "Science", ".ò" = "Science",
":ü" = "Medical", ".ü" = "Medical",
":ó" = "Engineering", ".ó" = "Engineering",
":û" = "Security", ".û" = "Security",
":è" = "binary", ".è" = "binary",
":ô" = "alientalk", ".ô" = "alientalk",
":å" = "Syndicate", ".å" = "Syndicate",
":é" = "Supply", ".é" = "Supply",
":ï" = "changeling", ".ï" = "changeling"))
var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
/mob/living/say(message, bubble_type,var/list/spans = list(), sanitize = TRUE, datum/language/language = null)
var/static/list/crit_allowed_modes = list(MODE_WHISPER = TRUE, MODE_CHANGELING = TRUE, MODE_ALIEN = TRUE)
var/static/list/unconscious_allowed_modes = list(MODE_CHANGELING = TRUE, MODE_ALIEN = TRUE)
var/static/list/one_character_prefix = list(MODE_HEADSET = TRUE, MODE_ROBOT = TRUE, MODE_WHISPER = TRUE)
/mob/living/say(message, bubble_type,var/list/spans = list(), sanitize = TRUE)
if(sanitize)
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
if(!message || message == "")
@@ -72,8 +71,9 @@ var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
var/message_mode = get_message_mode(message)
var/original_message = message
var/in_critical = InCritical()
if(message_mode == MODE_HEADSET || message_mode == MODE_ROBOT)
if(one_character_prefix[message_mode])
message = copytext(message, 2)
else if(message_mode)
message = copytext(message, 3)
@@ -94,34 +94,79 @@ var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
say_dead(original_message)
return
if(check_emote(original_message))
if(check_emote(original_message) || !can_speak_basic(original_message))
return
if(!can_speak_basic(original_message)) //Stat is seperate so I can handle whispers properly.
return
if(in_critical)
if(!(crit_allowed_modes[message_mode]))
return
else if(stat == UNCONSCIOUS)
if(!(unconscious_allowed_modes[message_mode]))
return
if(stat && !(message_mode in crit_allowed_modes))
return
// language comma detection.
var/datum/language/message_language = get_message_language(message)
if(message_language)
// No, you cannot speak in xenocommon just because you know the key
if(can_speak_in_language(message_language))
language = message_language
message = copytext(message, 3)
if(handle_inherent_channels(message, message_mode)) //Hiveminds, binary chat & holopad.
// Trim the space if they said ",0 I LOVE LANGUAGES"
if(findtext(message, " ", 1, 2))
message = copytext(message, 2)
if(!language)
language = get_default_language()
// Detection of language needs to be before inherent channels, because
// AIs use inherent channels for the holopad. Most inherent channels
// ignore the language argument however.
if(handle_inherent_channels(message, message_mode, language)) //Hiveminds, binary chat & holopad.
return
if(!can_speak_vocal(message))
to_chat(src, "<span class='warning'>You find yourself unable to speak!</span>")
return
if(message_mode != MODE_WHISPER) //whisper() calls treat_message(); double process results in "hisspering"
message = treat_message(message)
var/message_range = 7
var/succumbed = FALSE
if(message_mode == MODE_WHISPER)
message_range = 1
spans |= SPAN_ITALICS
log_whisper("[src.name]/[src.key] : [message]")
if(in_critical)
var/health_diff = round(-HEALTH_THRESHOLD_DEAD + health)
// If we cut our message short, abruptly end it with a-..
var/message_len = length(message)
message = copytext(message, 1, health_diff) + "[message_len > health_diff ? "-.." : "..."]"
message = Ellipsis(message, 10, 1)
message_mode = MODE_WHISPER_CRIT
succumbed = TRUE
else
log_say("[name]/[key] : [message]")
message = treat_message(message)
if(!message)
return
spans += get_spans()
if(language)
var/datum/language/L = GLOB.language_datums[language]
if(!istype(L))
L = new language
GLOB.language_datums[language] = L
spans |= L.spans
//Log what we've said with an associated timestamp, using the list's len for safety/to prevent overwriting messages
log_message(message, INDIVIDUAL_SAY_LOG)
var/message_range = 7
var/radio_return = radio(message, message_mode, spans)
if(radio_return & NOPASS) //There's a whisper() message_mode, no need to continue the proc if that is called
return
if(radio_return & ITALICS)
spans |= SPAN_ITALICS
if(radio_return & REDUCE_RANGE)
@@ -137,12 +182,15 @@ var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
if(pressure < ONE_ATMOSPHERE*0.4) //Thin air, let's italicise the message
spans |= SPAN_ITALICS
send_speech(message, message_range, src, bubble_type, spans)
send_speech(message, message_range, src, bubble_type, spans, language, message_mode)
if(succumbed)
succumb(1)
to_chat(src, compose_message(src, language, message, , spans, message_mode))
log_say("[name]/[key] : [message]")
return 1
/mob/living/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans)
/mob/living/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
if(!client)
return
var/deaf_message
@@ -154,20 +202,38 @@ var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
else
deaf_message = "<span class='notice'>You can't hear yourself!</span>"
deaf_type = 2 // Since you should be able to hear yourself without looking
if(!(message_langs & languages_understood) || force_compose) //force_compose is so AIs don't end up without their hrefs.
message = compose_message(speaker, message_langs, raw_message, radio_freq, spans)
// Recompose message for AI hrefs, language incomprehension.
message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode)
show_message(message, 2, deaf_message, deaf_type)
return message
/mob/living/send_speech(message, message_range = 7, obj/source = src, bubble_type = bubble_icon, list/spans)
var/list/listening = get_hearers_in_view(message_range, source)
for(var/mob/M in player_list)
/mob/living/send_speech(message, message_range = 6, obj/source = src, bubble_type = bubble_icon, list/spans, datum/language/message_language=null, message_mode)
var/static/list/eavesdropping_modes = list(MODE_WHISPER = TRUE, MODE_WHISPER_CRIT = TRUE)
var/eavesdrop_range = 0
if(eavesdropping_modes[message_mode])
eavesdrop_range = EAVESDROP_EXTRA_RANGE
var/list/listening = get_hearers_in_view(message_range+eavesdrop_range, source)
var/list/the_dead = list()
for(var/_M in GLOB.player_list)
var/mob/M = _M
if(M.stat == DEAD && M.client && ((M.client.prefs.chat_toggles & CHAT_GHOSTEARS) || (get_dist(M, src) <= 7 && M.z == z)) && client) // client is so that ghosts don't have to listen to mice
listening |= M
the_dead[M] = TRUE
var/rendered = compose_message(src, languages_spoken, message, , spans)
for(var/atom/movable/AM in listening)
AM.Hear(rendered, src, languages_spoken, message, , spans)
var/eavesdropping
var/eavesrendered
if(eavesdrop_range)
eavesdropping = stars(message)
eavesrendered = compose_message(src, message_language, eavesdropping, , spans, message_mode)
var/rendered = compose_message(src, message_language, message, , spans, message_mode)
for(var/_AM in listening)
var/atom/movable/AM = _AM
if(eavesdrop_range && get_dist(source, AM) > message_range && !(the_dead[AM]))
AM.Hear(eavesrendered, src, message_language, eavesdropping, , spans, message_mode)
else
AM.Hear(rendered, src, message_language, message, , spans, message_mode)
//speech bubble
var/list/speech_bubble_recipients = list()
@@ -176,8 +242,7 @@ var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
speech_bubble_recipients.Add(M.client)
var/image/I = image('icons/mob/talk.dmi', src, "[bubble_type][say_test(message)]", FLY_LAYER)
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
spawn(0)
flick_overlay(I, speech_bubble_recipients, 30)
INVOKE_ASYNC(GLOBAL_PROC, /.proc/flick_overlay, I, speech_bubble_recipients, 30)
/mob/proc/binarycheck()
return 0
@@ -216,16 +281,32 @@ var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
/mob/living/proc/get_message_mode(message)
if(copytext(message, 1, 2) == ";")
return MODE_HEADSET
else if(copytext(message, 1, 2) == "#")
return MODE_WHISPER
else if(length(message) > 2)
return department_radio_keys[copytext(message, 1, 3)]
return GLOB.department_radio_keys[copytext(message, 1, 3)]
/mob/living/proc/get_message_language(message)
var/static/list/langlist
if(!langlist)
langlist = subtypesof(/datum/language)
if(copytext(message, 1, 2) == ",")
var/key = copytext(message, 2, 3)
for(var/ld in langlist)
var/datum/language/LD = ld
if(initial(LD.key) == key)
return LD
return null
/mob/living/proc/handle_inherent_channels(message, message_mode)
if(message_mode == MODE_CHANGELING)
switch(lingcheck())
if(3)
var/msg = "<i><font color=#800040><b>[src.mind]:</b> [message]</font></i>"
for(var/mob/M in mob_list)
if(M in dead_mob_list)
for(var/_M in GLOB.mob_list)
var/mob/M = _M
if(M in GLOB.dead_mob_list)
var/link = FOLLOW_LINK(M, src)
to_chat(M, "[link] [msg]")
else
@@ -240,8 +321,9 @@ var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
if(2)
var/msg = "<i><font color=#800080><b>[mind.changeling.changelingID]:</b> [message]</font></i>"
log_say("[mind.changeling.changelingID]/[src.key] : [message]")
for(var/mob/M in mob_list)
if(M in dead_mob_list)
for(var/_M in GLOB.mob_list)
var/mob/M = _M
if(M in GLOB.dead_mob_list)
var/link = FOLLOW_LINK(M, src)
to_chat(M, "[link] [msg]")
else
@@ -287,32 +369,28 @@ var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
return message
/mob/living/proc/radio(message, message_mode, list/spans)
/mob/living/proc/radio(message, message_mode, list/spans, language)
switch(message_mode)
if(MODE_R_HAND)
for(var/obj/item/r_hand in get_held_items_for_side("r", all = TRUE))
if (r_hand)
return r_hand.talk_into(src, message, , spans)
return r_hand.talk_into(src, message, , spans, language)
return ITALICS | REDUCE_RANGE
if(MODE_L_HAND)
for(var/obj/item/l_hand in get_held_items_for_side("l", all = TRUE))
if (l_hand)
return l_hand.talk_into(src, message, , spans)
return l_hand.talk_into(src, message, , spans, language)
return ITALICS | REDUCE_RANGE
if(MODE_INTERCOM)
for (var/obj/item/device/radio/intercom/I in view(1, null))
I.talk_into(src, message, , spans)
I.talk_into(src, message, , spans, language)
return ITALICS | REDUCE_RANGE
if(MODE_BINARY)
if(binarycheck())
robot_talk(message)
return ITALICS | REDUCE_RANGE //Does not return 0 since this is only reached by humans, not borgs or AIs.
if(MODE_WHISPER)
whisper(message)
return NOPASS
return 0
/mob/living/lingcheck() //1 is ling w/ no hivemind. 2 is ling w/hivemind. 3 is ling victim being linked into hivemind.
@@ -324,10 +402,30 @@ var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
return 3
return 0
/mob/living/say_quote(input, list/spans)
/mob/living/say_quote(input, list/spans, message_mode)
var/tempinput = attach_spans(input, spans)
if(message_mode == MODE_WHISPER)
return "[verb_whisper], \"[tempinput]\""
if(message_mode == MODE_WHISPER_CRIT)
return "[verb_whisper] in [p_their()] last breath, \"[tempinput]\""
if (stuttering)
return "stammers, \"[tempinput]\""
if (getBrainLoss() >= 60)
return "gibbers, \"[tempinput]\""
return ..()
/mob/living/get_default_language()
if(selected_default_language)
if(has_language(selected_default_language))
return selected_default_language
else
selected_default_language = null
. = ..()
/mob/living/proc/open_language_menu(mob/user)
language_menu.ui_interact(user)
/mob/living/whisper(message as text)
say("#[message]")
+98 -27
View File
@@ -1,11 +1,10 @@
#define CALL_BOT_COOLDOWN 900
var/list/ai_list = list()
//Not sure why this is necessary...
/proc/AutoUpdateAI(obj/subject)
var/is_in_use = 0
if (subject!=null)
for(var/A in ai_list)
for(var/A in GLOB.ai_list)
var/mob/living/silicon/ai/M = A
if ((M.client && M.machine == subject))
is_in_use = 1
@@ -22,7 +21,6 @@ var/list/ai_list = list()
canmove = 0
status_flags = CANSTUN|CANPUSH
a_intent = INTENT_HARM //so we always get pushed instead of trying to swap
force_compose = 1 //This ensures that the AI always composes it's own hear message. Needed for hrefs and job display.
sight = SEE_TURFS | SEE_MOBS | SEE_OBJS
see_in_dark = 8
med_hud = DATA_HUD_MEDICAL_BASIC
@@ -84,6 +82,10 @@ var/list/ai_list = list()
var/obj/machinery/camera/portable/builtInCamera
var/obj/structure/AIcore/deactivated/linked_core //For exosuit control
var/mob/living/silicon/robot/deployed_shell = null //For shell control
var/datum/action/innate/deploy_shell/deploy_action = new
var/datum/action/innate/deploy_last_shell/redeploy_action = new
var/chnotify = 0
/mob/living/silicon/ai/Initialize(mapload, datum/ai_laws/L, mob/target_ai)
..()
@@ -138,22 +140,24 @@ var/list/ai_list = list()
radio = new /obj/item/device/radio/headset/ai(src)
aicamera = new/obj/item/device/camera/siliconcam/ai_camera(src)
deploy_action.Grant(src)
if(isturf(loc))
verbs.Add(/mob/living/silicon/ai/proc/ai_network_change, \
/mob/living/silicon/ai/proc/ai_statuschange, /mob/living/silicon/ai/proc/ai_hologram_change, \
/mob/living/silicon/ai/proc/toggle_camera_light, /mob/living/silicon/ai/proc/botcall,\
/mob/living/silicon/ai/proc/control_integrated_radio, /mob/living/silicon/ai/proc/set_automatic_say_channel)
ai_list += src
shuttle_caller_list += src
GLOB.ai_list += src
GLOB.shuttle_caller_list += src
builtInCamera = new /obj/machinery/camera/portable(src)
builtInCamera.network = list("SS13")
/mob/living/silicon/ai/Destroy()
ai_list -= src
shuttle_caller_list -= src
GLOB.ai_list -= src
GLOB.shuttle_caller_list -= src
SSshuttle.autoEvac()
qdel(eyeobj) // No AI, no Eye
malfhack = null
@@ -247,13 +251,16 @@ var/list/ai_list = list()
for(var/mob/living/silicon/robot/R in connected_robots)
borg_area = get_area(R)
var/robot_status = "Nominal"
if(R.stat || !R.client)
if(R.shell)
robot_status = "AI SHELL"
else if(R.stat || !R.client)
robot_status = "OFFLINE"
else if(!R.cell || R.cell.charge <= 0)
robot_status = "DEPOWERED"
//Name, Health, Battery, Module, Area, and Status! Everything an AI wants to know about its borgies!
stat(null, text("[R.name] | S.Integrity: [R.health]% | Cell: [R.cell ? "[R.cell.charge]/[R.cell.maxcharge]" : "Empty"] | \
Module: [R.designation] | Loc: [borg_area.name] | Status: [robot_status]"))
Module: [R.designation] | Loc: [borg_area.name] | Status: [robot_status]"))
stat(null, text("AI shell beacons detected: [LAZYLEN(GLOB.available_ai_shells)]")) //Count of total AI shells
else
stat(null, text("Systems nonfunctional"))
@@ -293,7 +300,7 @@ var/list/ai_list = list()
/mob/living/silicon/ai/proc/ai_roster()
var/dat = "<html><head><title>Crew Roster</title></head><body><b>Crew Roster:</b><br><br>"
dat += data_core.get_manifest()
dat += GLOB.data_core.get_manifest()
dat += "</body></html>"
src << browse(dat, "window=airoster")
@@ -315,7 +322,7 @@ var/list/ai_list = list()
// hack to display shuttle timer
if(!EMERGENCY_IDLE_OR_RECALLED)
var/obj/machinery/computer/communications/C = locate() in machines
var/obj/machinery/computer/communications/C = locate() in GLOB.machines
if(C)
C.post_status("shuttle")
@@ -363,7 +370,7 @@ var/list/ai_list = list()
unset_machine()
src << browse(null, t1)
if (href_list["switchcamera"])
switchCamera(locate(href_list["switchcamera"])) in cameranet.cameras
switchCamera(locate(href_list["switchcamera"])) in GLOB.cameranet.cameras
if (href_list["showalerts"])
ai_alerts()
#ifdef AI_VOX
@@ -403,14 +410,14 @@ var/list/ai_list = list()
if(call_bot_cooldown > world.time)
to_chat(src, "<span class='danger'>Error: Your last call bot command is still processing, please wait for the bot to finish calculating a route.</span>")
return
Bot = locate(href_list["callbot"]) in living_mob_list
Bot = locate(href_list["callbot"]) in GLOB.living_mob_list
if(!Bot || Bot.remote_disabled || src.control_disabled)
return //True if there is no bot found, the bot is manually emagged, or the AI is carded with wireless off.
waypoint_mode = 1
to_chat(src, "<span class='notice'>Set your waypoint by clicking on a valid location free of obstructions.</span>")
return
if(href_list["interface"]) //Remotely connect to a bot!
Bot = locate(href_list["interface"]) in living_mob_list
Bot = locate(href_list["interface"]) in GLOB.living_mob_list
if(!Bot || Bot.remote_disabled || src.control_disabled)
return
Bot.attack_ai(src)
@@ -423,7 +430,7 @@ var/list/ai_list = list()
if(controlled_mech)
to_chat(src, "<span class='warning'>You are already loaded into an onboard computer!</span>")
return
if(!cameranet.checkCameraVis(M))
if(!GLOB.cameranet.checkCameraVis(M))
to_chat(src, "<span class='warning'>Exosuit is no longer near active cameras.</span>")
return
if(lacks_power())
@@ -470,7 +477,7 @@ var/list/ai_list = list()
d += "<A HREF=?src=\ref[src];botrefresh=1>Query network status</A><br>"
d += "<table width='100%'><tr><td width='40%'><h3>Name</h3></td><td width='30%'><h3>Status</h3></td><td width='30%'><h3>Location</h3></td><td width='10%'><h3>Control</h3></td></tr>"
for (Bot in living_mob_list)
for (Bot in GLOB.living_mob_list)
if(Bot.z == ai_Zlevel && !Bot.remote_disabled) //Only non-emagged bots on the same Z-level are detected!
bot_area = get_area(Bot)
var/bot_mode = Bot.get_mode()
@@ -492,7 +499,7 @@ var/list/ai_list = list()
//The target must be in view of a camera or near the core.
if(turf_check in range(get_turf(src)))
call_bot(turf_check)
else if(cameranet && cameranet.checkTurfVis(turf_check))
else if(GLOB.cameranet && GLOB.cameranet.checkTurfVis(turf_check))
call_bot(turf_check)
else
to_chat(src, "<span class='danger'>Selected location is not visible.</span>")
@@ -582,7 +589,7 @@ var/list/ai_list = list()
var/mob/living/silicon/ai/U = usr
for (var/obj/machinery/camera/C in cameranet.cameras)
for (var/obj/machinery/camera/C in GLOB.cameranet.cameras)
if(!C.can_use())
continue
@@ -601,7 +608,7 @@ var/list/ai_list = list()
if(isnull(network))
network = old_network // If nothing is selected
else
for(var/obj/machinery/camera/C in cameranet.cameras)
for(var/obj/machinery/camera/C in GLOB.cameranet.cameras)
if(!C.can_use())
continue
if(network in C.network)
@@ -625,7 +632,7 @@ var/list/ai_list = list()
return //won't work if dead
var/list/ai_emotions = list("Very Happy", "Happy", "Neutral", "Unsure", "Confused", "Sad", "BSOD", "Blank", "Problems?", "Awesome", "Facepalm", "Friend Computer", "Dorfy", "Blue Glow", "Red Glow")
var/emote = input("Please, select a status!", "AI Status", null, null) in ai_emotions
for (var/obj/machinery/M in machines) //change status
for (var/obj/machinery/M in GLOB.machines) //change status
if(istype(M, /obj/machinery/ai_status_display))
var/obj/machinery/ai_status_display/AISD = M
AISD.emotion = emote
@@ -652,7 +659,7 @@ var/list/ai_list = list()
if("Crew Member")
var/list/personnel_list = list()
for(var/datum/data/record/t in data_core.locked)//Look in data core locked.
for(var/datum/data/record/t in GLOB.data_core.locked)//Look in data core locked.
personnel_list["[t.fields["name"]]: [t.fields["rank"]]"] = t.fields["image"]//Pull names, rank, and image.
if(personnel_list.len)
@@ -791,12 +798,13 @@ var/list/ai_list = list()
if(!..())
return
if(interaction == AI_TRANS_TO_CARD)//The only possible interaction. Upload AI mob to a card.
if(!mind)
to_chat(user, "<span class='warning'>No intelligence patterns detected.</span>" )
return
if(!can_be_carded)
to_chat(user, "<span class='boldwarning'>Transfer failed.</span>")
return
disconnect_shell() //If the AI is controlling a borg, force the player back to core!
if(!mind)
to_chat(user, "<span class='warning'>No intelligence patterns detected.</span>" )
return
ShutOffDoomsdayDevice()
new /obj/structure/AIcore/deactivated(loc)//Spawns a deactivated terminal at AI location.
ai_restore_power()//So the AI initially has power.
@@ -818,12 +826,12 @@ var/list/ai_list = list()
//stop AIs from leaving windows open and using then after they lose vision
//apc_override is needed here because AIs use their own APC when powerless
//get_turf_pixel() is because APCs in maint aren't actually in view of the inner camera
if(M && cameranet && !cameranet.checkTurfVis(get_turf_pixel(M)) && !apc_override)
if(M && GLOB.cameranet && !GLOB.cameranet.checkTurfVis(get_turf_pixel(M)) && !apc_override)
return
return 1
/mob/living/silicon/ai/proc/relay_speech(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans)
raw_message = lang_treat(speaker, message_langs, raw_message, spans)
/mob/living/silicon/ai/proc/relay_speech(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
raw_message = lang_treat(speaker, message_language, raw_message, spans, message_mode)
var/name_used = speaker.GetVoice()
var/rendered = "<i><span class='game say'>Relayed Speech: <span class='name'>[name_used]</span> <span class='message'>[raw_message]</span></span></i>"
show_message(rendered, 2)
@@ -907,6 +915,69 @@ var/list/ai_list = list()
to_chat(src, "Hack complete. \The [apc] is now under your exclusive control.")
apc.update_icon()
/mob/living/silicon/ai/verb/deploy_to_shell(var/mob/living/silicon/robot/target)
set category = "AI Commands"
set name = "Deploy to Shell"
if(stat || lacks_power() || control_disabled)
to_chat(src, "<span class='danger'>Wireless networking module is offline.</span>")
return
var/list/possible = list()
for(var/borgie in GLOB.available_ai_shells)
var/mob/living/silicon/robot/R = borgie
if(R.shell && !R.deployed && (R.stat != DEAD) && (!R.connected_ai ||(R.connected_ai == src)))
possible += R
if(!LAZYLEN(possible))
to_chat(src, "No usable AI shell beacons detected.")
if(!target || !(target in possible)) //If the AI is looking for a new shell, or its pre-selected shell is no longer valid
target = input(src, "Which body to control?") as null|anything in possible
if (!target || target.stat == DEAD || target.deployed || !(!target.connected_ai ||(target.connected_ai == src)))
return
else if(mind)
soullink(/datum/soullink/sharedbody, src, target)
deployed_shell = target
target.deploy_init(src)
mind.transfer_to(target)
diag_hud_set_deployed()
/datum/action/innate/deploy_shell
name = "Deploy to AI Shell"
desc = "Wirelessly control a specialized cyborg shell."
button_icon_state = "ai_shell"
/datum/action/innate/deploy_shell/Trigger()
var/mob/living/silicon/ai/AI = owner
if(!AI)
return
AI.deploy_to_shell()
/datum/action/innate/deploy_last_shell
name = "Reconnect to shell"
desc = "Reconnect to the most recently used AI shell."
button_icon_state = "ai_last_shell"
var/mob/living/silicon/robot/last_used_shell
/datum/action/innate/deploy_last_shell/Trigger()
if(!owner)
return
if(last_used_shell)
var/mob/living/silicon/ai/AI = owner
AI.deploy_to_shell(last_used_shell)
else
Remove(owner) //If the last shell is blown, destroy it.
/mob/living/silicon/ai/proc/disconnect_shell()
if(deployed_shell) //Forcibly call back AI in event of things such as damage, EMP or power loss.
to_chat(src, "<span class='danger'>Your remote connection has been reset!</span>")
deployed_shell.undeploy()
diag_hud_set_deployed()
/mob/living/silicon/ai/resist()
return
@@ -6,7 +6,7 @@
/mob/living/silicon/ai/attack_alien(mob/living/carbon/alien/humanoid/M)
if(!ticker || !ticker.mode)
if(!SSticker || !SSticker.mode)
to_chat(M, "You cannot attack people before the game has started.")
return
..()
@@ -22,6 +22,7 @@
return 0
/mob/living/silicon/ai/emp_act(severity)
disconnect_shell()
if (prob(30))
switch(pick(1,2))
if(1)
+2 -2
View File
@@ -16,7 +16,7 @@
if(eyeobj)
eyeobj.setLoc(get_turf(src))
shuttle_caller_list -= src
GLOB.shuttle_caller_list -= src
SSshuttle.autoEvac()
ShutOffDoomsdayDevice()
@@ -35,7 +35,7 @@
if(nuking)
set_security_level("red")
nuking = FALSE
for(var/obj/item/weapon/pinpointer/P in pinpointer_list)
for(var/obj/item/weapon/pinpointer/P in GLOB.pinpointer_list)
P.switch_mode_to(TRACK_NUKE_DISK) //Party's over, back to work, everyone
P.nuke_warning = FALSE
@@ -1,21 +1,23 @@
/mob/living/silicon/ai/examine(mob/user)
var/msg = "<span class='info'>*---------*\nThis is \icon[src] <EM>[src]</EM>!\n"
if (src.stat == DEAD)
if (stat == DEAD)
msg += "<span class='deadsay'>It appears to be powered-down.</span>\n"
else
msg += "<span class='warning'>"
if (src.getBruteLoss())
if (src.getBruteLoss() < 30)
if (getBruteLoss())
if (getBruteLoss() < 30)
msg += "It looks slightly dented.\n"
else
msg += "<B>It looks severely dented!</B>\n"
if (src.getFireLoss())
if (src.getFireLoss() < 30)
if (getFireLoss())
if (getFireLoss() < 30)
msg += "It looks slightly charred.\n"
else
msg += "<B>Its casing is melted and heat-warped!</B>\n"
msg += "</span>"
if (shunted == 0 && !src.client)
if(deployed_shell)
msg += "The wireless networking light is blinking.\n"
else if (!shunted && !client)
msg += "[src]Core.exe has stopped responding! NTOS is searching for a solution to the problem...\n"
msg += "*---------*</span>"
@@ -2,9 +2,9 @@
//
// The datum containing all the chunks.
var/const/CHUNK_SIZE = 16 // Only chunk sizes that are to the power of 2. E.g: 2, 4, 8, 16, etc..
#define CHUNK_SIZE 16 // Only chunk sizes that are to the power of 2. E.g: 2, 4, 8, 16, etc..
var/datum/cameranet/cameranet = new()
GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
/datum/cameranet
var/name = "Camera Net" // Name to show for VV and stat()
@@ -66,7 +66,7 @@ var/datum/cameranet/cameranet = new()
/datum/cameranet/proc/updateVisibility(atom/A, opacity_check = 1)
if(!ticker || (opacity_check && !A.opacity))
if(!SSticker || (opacity_check && !A.opacity))
return
majorChunkChange(A, 2)
@@ -151,7 +151,7 @@ var/datum/cameranet/cameranet = new()
if(!statclick)
statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
stat(name, statclick.update("Cameras: [cameranet.cameras.len] | Chunks: [cameranet.chunks.len]"))
stat(name, statclick.update("Cameras: [GLOB.cameranet.cameras.len] | Chunks: [GLOB.cameranet.chunks.len]"))
// Debug verb for VVing the chunk that the turf is in.
/*
@@ -173,4 +173,5 @@
t.obscured.plane = LIGHTING_PLANE+1
obscured += t.obscured
#undef UPDATE_BUFFER
#undef UPDATE_BUFFER
#undef CHUNK_SIZE
@@ -21,7 +21,7 @@
return
T = get_turf(T)
loc = T
cameranet.visibility(src)
GLOB.cameranet.visibility(src)
if(ai.client)
ai.client.eye = src
update_parallax_contents()
@@ -104,6 +104,6 @@
acceleration = !acceleration
to_chat(usr, "Camera acceleration has been toggled [acceleration ? "on" : "off"].")
/mob/camera/aiEye/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans)
/mob/camera/aiEye/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
if(relay_speech && speaker && ai && !radio_freq && speaker != ai && near_camera(speaker))
ai.relay_speech(message, speaker, message_langs, raw_message, radio_freq, spans)
ai.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans)
+4 -1
View File
@@ -65,6 +65,7 @@
health = maxHealth - getOxyLoss() - getToxLoss() - getBruteLoss() - getFireLoss()
update_stat()
diag_hud_set_health()
disconnect_shell()
/mob/living/silicon/ai/update_stat()
if(status_flags & GODMODE)
@@ -90,6 +91,7 @@
if(see_override)
see_invisible = see_override
sync_lighting_plane_alpha()
/mob/living/silicon/ai/proc/start_RestorePowerRoutine()
@@ -146,7 +148,7 @@
to_chat(src, "Receiving control information from APC.")
sleep(2)
apc_override = 1
theAPC.ui_interact(src, state = conscious_state)
theAPC.ui_interact(src, state = GLOB.conscious_state)
apc_override = 0
aiRestorePowerRoutine = POWER_RESTORATION_APC_FOUND
sleep(50)
@@ -163,6 +165,7 @@
update_sight()
/mob/living/silicon/ai/proc/ai_lose_power()
disconnect_shell()
aiRestorePowerRoutine = POWER_RESTORATION_START
blind_eyes(1)
update_sight()
+1 -1
View File
@@ -6,7 +6,7 @@
client.images += blood
if(stat != DEAD)
for(var/obj/machinery/ai_status_display/O in machines) //change status
for(var/obj/machinery/ai_status_display/O in GLOB.machines) //change status
O.mode = 1
O.emotion = "Neutral"
view_core()
+25 -20
View File
@@ -1,6 +1,6 @@
/mob/living/silicon/ai/say(message)
/mob/living/silicon/ai/say(message, language)
if(parent && istype(parent) && parent.stat != 2) //If there is a defined "parent" AI, it is actually an AI, and it is alive, anything the AI tries to say is said by the parent instead.
parent.say(message)
parent.say(message, language)
return
..(message)
@@ -17,7 +17,7 @@
/mob/living/silicon/ai/IsVocal()
return !config.silent_ai
/mob/living/silicon/ai/radio(message, message_mode, list/spans)
/mob/living/silicon/ai/radio(message, message_mode, list/spans, language)
if(!radio_enabled || aiRestorePowerRoutine || stat) //AI cannot speak if radio is disabled (via intellicard) or depowered.
to_chat(src, "<span class='danger'>Your radio transmitter is offline!</span>")
return 0
@@ -29,17 +29,17 @@
else
return ..()
/mob/living/silicon/ai/handle_inherent_channels(message, message_mode)
/mob/living/silicon/ai/handle_inherent_channels(message, message_mode, language)
. = ..()
if(.)
return .
if(message_mode == MODE_HOLOPAD)
holopad_talk(message)
holopad_talk(message, language)
return 1
//For holopads only. Usable by AI.
/mob/living/silicon/ai/proc/holopad_talk(message)
/mob/living/silicon/ai/proc/holopad_talk(message, language)
log_say("[key_name(src)] : [message]")
message = trim(message)
@@ -49,20 +49,15 @@
var/obj/machinery/holopad/T = current
if(istype(T) && T.masters[src])//If there is a hologram and its master is the user.
send_speech(message, 7, T, "robot", get_spans())
send_speech(message, 7, T, "robot", get_spans(), language)
to_chat(src, "<i><span class='game say'>Holopad transmitted, <span class='name'>[real_name]</span> <span class='message robot'>\"[message]\"</span></span></i>")
else
to_chat(src, "No holopad connected.")
return
// Make sure that the code compiles with AI_VOX undefined
#ifdef AI_VOX
var/announcing_vox = 0 // Stores the time of the last announcement
var/const/VOX_CHANNEL = 200
var/const/VOX_DELAY = 600
#define VOX_DELAY 600
/mob/living/silicon/ai/verb/announcement_help()
set name = "Announcement Help"
@@ -79,10 +74,10 @@ var/const/VOX_DELAY = 600
<font class='bad'>WARNING:</font><BR>Misuse of the announcement system will get you job banned.<HR>"
var/index = 0
for(var/word in vox_sounds)
for(var/word in GLOB.vox_sounds)
index++
dat += "<A href='?src=\ref[src];say_word=[word]'>[capitalize(word)]</A>"
if(index != vox_sounds.len)
if(index != GLOB.vox_sounds.len)
dat += " / "
var/datum/browser/popup = new(src, "announce_help", "Announcement Help", 500, 400)
@@ -91,6 +86,7 @@ var/const/VOX_DELAY = 600
/mob/living/silicon/ai/proc/announcement()
var/static/announcing_vox = 0 // Stores the time of the last announcement
if(announcing_vox > world.time)
to_chat(src, "<span class='notice'>Please wait [round((announcing_vox - world.time) / 10)] seconds.</span>")
return
@@ -120,7 +116,7 @@ var/const/VOX_DELAY = 600
if(!word)
words -= word
continue
if(!vox_sounds[word])
if(!GLOB.vox_sounds[word])
incorrect_words += word
if(incorrect_words.len)
@@ -147,16 +143,16 @@ var/const/VOX_DELAY = 600
word = lowertext(word)
if(vox_sounds[word])
if(GLOB.vox_sounds[word])
var/sound_file = vox_sounds[word]
var/sound/voice = sound(sound_file, wait = 1, channel = VOX_CHANNEL)
var/sound_file = GLOB.vox_sounds[word]
var/sound/voice = sound(sound_file, wait = 1, channel = CHANNEL_VOX)
voice.status = SOUND_STREAM
// If there is no single listener, broadcast to everyone in the same z level
if(!only_listener)
// Play voice for all mobs in the z level
for(var/mob/M in player_list)
for(var/mob/M in GLOB.player_list)
if(M.client && !M.ear_deaf && (M.client.prefs.toggles & SOUND_ANNOUNCEMENTS))
var/turf/T = get_turf(M)
if(T.z == z_level)
@@ -167,3 +163,12 @@ var/const/VOX_DELAY = 600
return 0
#endif
/mob/living/silicon/ai/can_speak_in_language(datum/language/dt)
if(HAS_SECONDARY_FLAG(src, OMNITONGUE))
. = has_language(dt)
else if(is_servant_of_ratvar(src))
// Ratvarian AIs can only speak Ratvarian
. = ispath(dt, /datum/language/ratvar) && has_language(dt)
else
. = ..()
@@ -2,7 +2,7 @@
// Dynamically loading it has bad results with sounds overtaking each other, even with the wait variable.
#ifdef AI_VOX
var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg',
GLOBAL_LIST_INIT(vox_sounds, list("," = 'sound/vox_fem/,.ogg',
"." = 'sound/vox_fem/..ogg',
"a" = 'sound/vox_fem/a.ogg',
"abortions" = 'sound/vox_fem/abortions.ogg',
@@ -713,6 +713,5 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg',
"z" = 'sound/vox_fem/z.ogg',
"zero" = 'sound/vox_fem/zero.ogg',
"zone" = 'sound/vox_fem/zone.ogg',
"zulu" = 'sound/vox_fem/zulu.ogg',
)
"zulu" = 'sound/vox_fem/zulu.ogg'))
#endif
+4 -4
View File
@@ -1,6 +1,6 @@
/mob/living/silicon/Login()
if(mind && ticker && ticker.mode)
ticker.mode.remove_cultist(mind, 0, 0)
ticker.mode.remove_revolutionary(mind, 0)
ticker.mode.remove_gangster(mind, remove_bosses=1)
if(mind && SSticker && SSticker.mode)
SSticker.mode.remove_cultist(mind, 0, 0)
SSticker.mode.remove_revolutionary(mind, 0)
SSticker.mode.remove_gangster(mind, remove_bosses=1)
..()
+3 -1
View File
@@ -4,10 +4,12 @@
stat = DEAD
canmove = 0
card.removePersonality()
if(holoform)
card.forceMove(loc)
update_sight()
clear_fullscreens()
//New pAI's get a brand new mind to prevent meta stuff from their previous life. This new mind causes problems down the line if it's not deleted here.
living_mob_list -= src
GLOB.living_mob_list -= src
ghostize()
qdel(src)
+5 -2
View File
@@ -78,13 +78,13 @@
. += slowdown
/mob/living/silicon/pai/Destroy()
pai_list -= src
GLOB.pai_list -= src
..()
/mob/living/silicon/pai/Initialize()
var/obj/item/device/paicard/P = loc
START_PROCESSING(SSfastprocess, src)
pai_list += src
GLOB.pai_list += src
make_laws()
canmove = 0
if(!istype(P)) //when manually spawning a pai, we create a card to put it into.
@@ -110,10 +110,13 @@
var/datum/action/innate/pai/chassis/AC = new /datum/action/innate/pai/chassis
var/datum/action/innate/pai/rest/AR = new /datum/action/innate/pai/rest
var/datum/action/innate/pai/light/AL = new /datum/action/innate/pai/light
var/datum/action/language_menu/ALM = new
AS.Grant(src)
AC.Grant(src)
AR.Grant(src)
AL.Grant(src)
ALM.Grant(src)
emittersemicd = TRUE
addtimer(CALLBACK(src, .proc/emittercool), 600)
@@ -102,4 +102,4 @@
/mob/living/silicon/pai/movement_delay()
. = ..()
. += 1 //A bit slower than humans, so they're easier to smash
. += 1 //A bit slower than humans, so they're easier to smash
+26 -26
View File
@@ -33,7 +33,7 @@
if(temp)
left_part = temp
else if(src.stat == 2) // Show some flavor text if the pAI is dead
left_part = "<b><font color=red>ÈRrÖR Ða†Ä ÇÖRrÚþ†Ìoñ</font></b>"
left_part = "<b><font color=red>RrR a Rro</font></b>"
right_part = "<pre>Program index hash not found</pre>"
else
@@ -220,18 +220,18 @@
// Accessing medical records
if("medicalrecord")
if(subscreen == 1)
medicalActive1 = find_record("id", href_list["med_rec"], data_core.general)
medicalActive1 = find_record("id", href_list["med_rec"], GLOB.data_core.general)
if(medicalActive1)
medicalActive2 = find_record("id", href_list["med_rec"], data_core.medical)
medicalActive2 = find_record("id", href_list["med_rec"], GLOB.data_core.medical)
if(!medicalActive2)
medicalActive1 = null
temp = "Unable to locate requested security record. Record may have been deleted, or never have existed."
if("securityrecord")
if(subscreen == 1)
securityActive1 = find_record("id", href_list["sec_rec"], data_core.general)
securityActive1 = find_record("id", href_list["sec_rec"], GLOB.data_core.general)
if(securityActive1)
securityActive2 = find_record("id", href_list["sec_rec"], data_core.security)
securityActive2 = find_record("id", href_list["sec_rec"], GLOB.data_core.security)
if(!securityActive2)
securityActive1 = null
temp = "Unable to locate requested security record. Record may have been deleted, or never have existed."
@@ -241,7 +241,7 @@
if(secHUD)
add_sec_hud()
else
var/datum/atom_hud/sec = huds[sec_hud]
var/datum/atom_hud/sec = GLOB.huds[sec_hud]
sec.remove_hud_from(src)
if("medicalhud")
if(href_list["toggle"])
@@ -249,13 +249,13 @@
if(medHUD)
add_med_hud()
else
var/datum/atom_hud/med = huds[med_hud]
var/datum/atom_hud/med = GLOB.huds[med_hud]
med.remove_hud_from(src)
if("translator")
if(href_list["toggle"])
var/on_already = ((languages_understood == ALL) && (languages_spoken == ALL))
languages_spoken = on_already ? (HUMAN | ROBOT) : ALL
languages_understood = on_already ? (HUMAN | ROBOT) : ALL
if(!HAS_SECONDARY_FLAG(src, OMNITONGUE))
grant_all_languages(TRUE)
// this is PERMAMENT.
if("doorjack")
if(href_list["jack"])
if(src.cable && src.cable.machine)
@@ -313,7 +313,8 @@
if(s == "medical HUD")
dat += "<a href='byond://?src=\ref[src];software=medicalhud;sub=0'>Medical Analysis Suite</a>[(src.medHUD) ? "<font color=#55FF55> On</font>" : "<font color=#FF5555> Off</font>"] <br>"
if(s == "universal translator")
dat += "<a href='byond://?src=\ref[src];software=translator;sub=0'>Universal Translator</a>[((languages_spoken == ALL) && (languages_understood == ALL)) ? "<font color=#55FF55> On</font>" : "<font color=#FF5555> Off</font>"] <br>"
var/translator_on = HAS_SECONDARY_FLAG(src, OMNITONGUE)
dat += "<a href='byond://?src=\ref[src];software=translator;sub=0'>Universal Translator</a>[translator_on ? "<font color=#55FF55> On</font>" : "<font color=#FF5555> Off</font>"] <br>"
if(s == "projection array")
dat += "<a href='byond://?src=\ref[src];software=projectionarray;sub=0'>Projection Array</a> <br>"
if(s == "camera jack")
@@ -413,8 +414,8 @@
// Crew Manifest
/mob/living/silicon/pai/proc/softwareManifest()
. += "<h2>Crew Manifest</h2><br><br>"
if(data_core.general)
for(var/datum/data/record/t in sortRecord(data_core.general))
if(GLOB.data_core.general)
for(var/datum/data/record/t in sortRecord(GLOB.data_core.general))
. += "[t.fields["name"]] - [t.fields["rank"]]<BR>"
. += "</body></html>"
return .
@@ -424,16 +425,16 @@
switch(subscreen)
if(0)
. += "<h3>Medical Records</h3><HR>"
if(data_core.general)
for(var/datum/data/record/R in sortRecord(data_core.general))
if(GLOB.data_core.general)
for(var/datum/data/record/R in sortRecord(GLOB.data_core.general))
. += "<A href='?src=\ref[src];med_rec=[R.fields["id"]];software=medicalrecord;sub=1'>[R.fields["id"]]: [R.fields["name"]]<BR>"
if(1)
. += "<CENTER><B>Medical Record</B></CENTER><BR>"
if(medicalActive1 in data_core.general)
if(medicalActive1 in GLOB.data_core.general)
. += "Name: [medicalActive1.fields["name"]] ID: [medicalActive1.fields["id"]]<BR>\nSex: [medicalActive1.fields["sex"]]<BR>\nAge: [medicalActive1.fields["age"]]<BR>\nFingerprint: [medicalActive1.fields["fingerprint"]]<BR>\nPhysical Status: [medicalActive1.fields["p_stat"]]<BR>\nMental Status: [medicalActive1.fields["m_stat"]]<BR>"
else
. += "<pre>Requested medical record not found.</pre><BR>"
if(medicalActive2 in data_core.medical)
if(medicalActive2 in GLOB.data_core.medical)
. += "<BR>\n<CENTER><B>Medical Data</B></CENTER><BR>\nBlood Type: <A href='?src=\ref[src];field=blood_type'>[medicalActive2.fields["blood_type"]]</A><BR>\nDNA: <A href='?src=\ref[src];field=b_dna'>[medicalActive2.fields["b_dna"]]</A><BR>\n<BR>\nMinor Disabilities: <A href='?src=\ref[src];field=mi_dis'>[medicalActive2.fields["mi_dis"]]</A><BR>\nDetails: <A href='?src=\ref[src];field=mi_dis_d'>[medicalActive2.fields["mi_dis_d"]]</A><BR>\n<BR>\nMajor Disabilities: <A href='?src=\ref[src];field=ma_dis'>[medicalActive2.fields["ma_dis"]]</A><BR>\nDetails: <A href='?src=\ref[src];field=ma_dis_d'>[medicalActive2.fields["ma_dis_d"]]</A><BR>\n<BR>\nAllergies: <A href='?src=\ref[src];field=alg'>[medicalActive2.fields["alg"]]</A><BR>\nDetails: <A href='?src=\ref[src];field=alg_d'>[medicalActive2.fields["alg_d"]]</A><BR>\n<BR>\nCurrent Diseases: <A href='?src=\ref[src];field=cdi'>[medicalActive2.fields["cdi"]]</A> (per disease info placed in log/comment section)<BR>\nDetails: <A href='?src=\ref[src];field=cdi_d'>[medicalActive2.fields["cdi_d"]]</A><BR>\n<BR>\nImportant Notes:<BR>\n\t<A href='?src=\ref[src];field=notes'>[medicalActive2.fields["notes"]]</A><BR>\n<BR>\n<CENTER><B>Comments/Log</B></CENTER><BR>"
else
. += "<pre>Requested medical record not found.</pre><BR>"
@@ -446,16 +447,16 @@
switch(subscreen)
if(0)
. += "<h3>Security Records</h3><HR>"
if(data_core.general)
for(var/datum/data/record/R in sortRecord(data_core.general))
if(GLOB.data_core.general)
for(var/datum/data/record/R in sortRecord(GLOB.data_core.general))
. += "<A href='?src=\ref[src];sec_rec=[R.fields["id"]];software=securityrecord;sub=1'>[R.fields["id"]]: [R.fields["name"]]<BR>"
if(1)
. += "<h3>Security Record</h3>"
if(securityActive1 in data_core.general)
if(securityActive1 in GLOB.data_core.general)
. += "Name: <A href='?src=\ref[src];field=name'>[securityActive1.fields["name"]]</A> ID: <A href='?src=\ref[src];field=id'>[securityActive1.fields["id"]]</A><BR>\nSex: <A href='?src=\ref[src];field=sex'>[securityActive1.fields["sex"]]</A><BR>\nAge: <A href='?src=\ref[src];field=age'>[securityActive1.fields["age"]]</A><BR>\nRank: <A href='?src=\ref[src];field=rank'>[securityActive1.fields["rank"]]</A><BR>\nFingerprint: <A href='?src=\ref[src];field=fingerprint'>[securityActive1.fields["fingerprint"]]</A><BR>\nPhysical Status: [securityActive1.fields["p_stat"]]<BR>\nMental Status: [securityActive1.fields["m_stat"]]<BR>"
else
. += "<pre>Requested security record not found,</pre><BR>"
if(securityActive2 in data_core.security)
if(securityActive2 in GLOB.data_core.security)
. += "<BR>\nSecurity Data<BR>\nCriminal Status: [securityActive2.fields["criminal"]]<BR>\n<BR>\nMinor Crimes: <A href='?src=\ref[src];field=mi_crim'>[securityActive2.fields["mi_crim"]]</A><BR>\nDetails: <A href='?src=\ref[src];field=mi_crim_d'>[securityActive2.fields["mi_crim_d"]]</A><BR>\n<BR>\nMajor Crimes: <A href='?src=\ref[src];field=ma_crim'>[securityActive2.fields["ma_crim"]]</A><BR>\nDetails: <A href='?src=\ref[src];field=ma_crim_d'>[securityActive2.fields["ma_crim_d"]]</A><BR>\n<BR>\nImportant Notes:<BR>\n\t<A href='?src=\ref[src];field=notes'>[securityActive2.fields["notes"]]</A><BR>\n<BR>\n<CENTER><B>Comments/Log</B></CENTER><BR>"
else
. += "<pre>Requested security record not found,</pre><BR>"
@@ -464,11 +465,10 @@
// Universal Translator
/mob/living/silicon/pai/proc/softwareTranslator()
var/translator_on = HAS_SECONDARY_FLAG(src, OMNITONGUE)
. = {"<h3>Universal Translator</h3><br>
When enabled, this device will automatically convert all spoken and written language into a format that any known recipient can understand.<br><br>
The device is currently [ ((languages_spoken == ALL) && (languages_understood == ALL)) ? "<font color=#55FF55>en" : "<font color=#FF5555>dis" ]abled.</font><br>
<a href='byond://?src=\ref[src];software=translator;sub=0;toggle=1'>Toggle Device</a><br>
"}
When enabled, this device will permamently be able to speak and understand all known forms of communication.<br><br>
The device is currently [translator_on ? "<font color=#55FF55>en" : "<font color=#FF5555>dis" ]abled.</font><br>[translator_on ? "" : "<a href='byond://?src=\ref[src];software=translator;sub=0;toggle=1'>Activate Translation Module</a><br>"]"}
return .
// Security HUD
@@ -599,7 +599,7 @@
// Door Jack - supporting proc
/mob/living/silicon/pai/proc/hackloop()
var/turf/T = get_turf(src.loc)
for(var/mob/living/silicon/ai/AI in player_list)
for(var/mob/living/silicon/ai/AI in GLOB.player_list)
if(T.loc)
to_chat(AI, "<font color = red><b>Network Alert: Brute-force encryption crack in progress in [T.loc].</b></font>")
else
@@ -36,9 +36,11 @@
if(is_servant_of_ratvar(src) && user.Adjacent(src) && !stat) //To counter pseudo-stealth by using headlamps
msg += "<span class='warning'>Its eyes are glowing a blazing yellow!</span>\n"
switch(src.stat)
switch(stat)
if(CONSCIOUS)
if(!src.client)
if(shell)
msg += "It appears to be an [deployed ? "active" : "empty"] AI shell.\n"
else if(!client)
msg += "It appears to be in stand-by mode.\n" //afk
if(UNCONSCIOUS)
msg += "<span class='warning'>It doesn't seem to be responding.</span>\n"
@@ -32,7 +32,9 @@
to_chat(who, "<b>Obey these laws:</b>")
laws.show_laws(who)
if (is_special_character(src) && connected_ai)
if (shell) //AI shell
to_chat(who, "<b>Remember, you are an AI remotely controlling your shell, other AIs can be ignored.</b>")
else if (is_special_character(src) && connected_ai)
to_chat(who, "<b>Remember, [connected_ai.name] is technically your master, but your objective comes first.</b>")
else if (connected_ai)
to_chat(who, "<b>Remember, [connected_ai.name] is your master, other AIs can be ignored.</b>")
@@ -37,8 +37,8 @@
update_cell_hud_icon()
if(syndicate)
if(ticker.mode.name == "traitor")
for(var/datum/mind/tra in ticker.mode.traitors)
if(SSticker.mode.name == "traitor")
for(var/datum/mind/tra in SSticker.mode.traitors)
if(tra.current)
var/I = image('icons/mob/mob.dmi', loc = tra.current, icon_state = "traitor") //no traitor sprite in that dmi!
src.client.images += I
@@ -48,7 +48,7 @@
if(mind)
if(!mind.special_role)
mind.special_role = "traitor"
ticker.mode.traitors += mind
SSticker.mode.traitors += mind
/mob/living/silicon/robot/update_health_hud()
@@ -4,5 +4,5 @@
regenerate_icons()
show_laws(0)
if(mind)
ticker.mode.remove_revolutionary(mind)
ticker.mode.remove_gangster(mind,1,remove_bosses=1)
SSticker.mode.remove_revolutionary(mind)
SSticker.mode.remove_gangster(mind,1,remove_bosses=1)
+136 -45
View File
@@ -16,6 +16,10 @@
var/obj/item/robot_suit/robot_suit = null //Used for deconstruction to remember what the borg was constructed out of..
var/obj/item/device/mmi/mmi = null
var/shell = FALSE
var/deployed = FALSE
var/mob/living/silicon/ai/mainframe = null
var/datum/action/innate/undeployment/undeployment_action = new
//Hud stuff
@@ -47,7 +51,7 @@
var/ident = 0
var/locked = 1
var/list/req_access = list(access_robotics)
var/list/req_access = list(GLOB.access_robotics)
var/alarms = list("Motion"=list(), "Fire"=list(), "Atmosphere"=list(), "Power"=list(), "Camera"=list(), "Burglar"=list())
@@ -73,7 +77,7 @@
var/sight_mode = 0
var/updating = 0 //portable camera camerachunk update
hud_possible = list(ANTAG_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_BATT_HUD)
hud_possible = list(ANTAG_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_BATT_HUD, DIAG_TRACK_HUD)
var/list/upgrades = list()
@@ -129,8 +133,12 @@
update_icons()
..()
//If this body is meant to be a borg controlled by the AI player
if(shell)
make_shell()
//MMI stuff. Held togheter by magic. ~Miauw
if(!mmi || !mmi.brainmob)
else if(!mmi || !mmi.brainmob)
mmi = new (src)
mmi.brain = new /obj/item/organ/brain(mmi)
mmi.brain.name = "[real_name]'s brain"
@@ -159,8 +167,8 @@
if(mmi.brainmob)
if(mmi.brainmob.stat == DEAD)
mmi.brainmob.stat = CONSCIOUS
dead_mob_list -= mmi.brainmob
living_mob_list += mmi.brainmob
GLOB.dead_mob_list -= mmi.brainmob
GLOB.living_mob_list += mmi.brainmob
mind.transfer_to(mmi.brainmob)
mmi.update_icon()
else
@@ -170,6 +178,8 @@
mmi = null
if(connected_ai)
connected_ai.connected_robots -= src
if(shell)
GLOB.available_ai_shells -= src
qdel(wires)
qdel(module)
qdel(eye_lights)
@@ -204,6 +214,8 @@
/mob/living/silicon/robot/proc/updatename()
if(shell)
return
var/changed_name = ""
if(custom_name)
changed_name = custom_name
@@ -424,7 +436,9 @@
update_icons()
else if(istype(W, /obj/item/weapon/screwdriver) && opened && cell) // radio
if(radio)
if(shell)
to_chat(user, "You cannot seem to open the radio compartment") //Prevent AI radio key theft
else if(radio)
radio.attackby(W,user)//Push it to the radio to let it handle everything
else
to_chat(user, "<span class='warning'>Unable to locate a radio!</span>")
@@ -453,6 +467,9 @@
if(!cell)
to_chat(user, "<span class='warning'>You need to install a power cell to do that!</span>")
return
if(shell) //AI shells always have the laws of the AI
to_chat(user, "<span class='warning'>[src] is controlled remotely! You cannot upload new laws this way!</span>")
return
if(emagged || (connected_ai && lawupdate)) //Can't be sure which, metagamers
emote("buzz-[user.name]")
return
@@ -594,7 +611,7 @@
/mob/living/silicon/robot/proc/do_camera_update(oldLoc)
if(oldLoc != src.loc)
cameranet.updatePortableCamera(src.camera)
GLOB.cameranet.updatePortableCamera(src.camera)
updating = 0
/mob/living/silicon/robot/Move(a, b, flag)
@@ -606,36 +623,6 @@
updating = 1
addtimer(CALLBACK(src, .proc/do_camera_update, oldLoc), BORG_CAMERA_BUFFER)
if(module)
if(istype(module, /obj/item/weapon/robot_module/janitor))
var/turf/tile = loc
if(isturf(tile))
tile.clean_blood()
for(var/A in tile)
if(is_cleanable(A))
qdel(A)
else if(istype(A, /obj/item))
var/obj/item/cleaned_item = A
cleaned_item.clean_blood()
else if(ishuman(A))
var/mob/living/carbon/human/cleaned_human = A
if(cleaned_human.lying)
if(cleaned_human.head)
cleaned_human.head.clean_blood()
cleaned_human.update_inv_head()
if(cleaned_human.wear_suit)
cleaned_human.wear_suit.clean_blood()
cleaned_human.update_inv_wear_suit()
else if(cleaned_human.w_uniform)
cleaned_human.w_uniform.clean_blood()
cleaned_human.update_inv_w_uniform()
if(cleaned_human.shoes)
cleaned_human.shoes.clean_blood()
cleaned_human.update_inv_shoes()
cleaned_human.clean_blood()
cleaned_human.wash_cream()
to_chat(cleaned_human, "<span class='danger'>[src] cleans your face!</span>")
return
if(istype(module, /obj/item/weapon/robot_module/miner))
if(istype(loc, /turf/open/floor/plating/asteroid))
for(var/obj/item/I in held_items)
@@ -806,7 +793,7 @@
icon_state = "syndie_bloodhound"
faction = list("syndicate")
bubble_icon = "syndibot"
req_access = list(access_syndicate)
req_access = list(GLOB.access_syndicate)
lawupdate = FALSE
scrambledcodes = TRUE // These are rogue borgs.
ionpulse = TRUE
@@ -829,6 +816,9 @@
if(playstyle_string)
to_chat(src, playstyle_string)
/mob/living/silicon/robot/syndicate/ResetModule()
return
/mob/living/silicon/robot/syndicate/medical
icon_state = "syndi-medi"
playstyle_string = "<span class='userdanger'>You are a Syndicate medical cyborg!</span><br>\
@@ -843,12 +833,14 @@
if(!connected_ai)
return
switch(notifytype)
if(1) //New Cyborg
if(NEW_BORG) //New Cyborg
to_chat(connected_ai, "<br><br><span class='notice'>NOTICE - New cyborg connection detected: <a href='?src=\ref[connected_ai];track=[html_encode(name)]'>[name]</a></span><br>")
if(2) //New Module
if(NEW_MODULE) //New Module
to_chat(connected_ai, "<br><br><span class='notice'>NOTICE - Cyborg module change detected: [name] has loaded the [designation] module.</span><br>")
if(3) //New Name
if(RENAME) //New Name
to_chat(connected_ai, "<br><br><span class='notice'>NOTICE - Cyborg reclassification detected: [oldname] is now designated as [newname].</span><br>")
if(AI_SHELL) //New Shell
to_chat(connected_ai, "<br><br><span class='notice'>NOTICE - New cyborg shell detected: <a href='?src=\ref[connected_ai];track=[html_encode(name)]'>[name]</a></span><br>")
/mob/living/silicon/robot/canUseTopic(atom/movable/M, be_close = 0)
if(stat || lockcharge || low_power_mode)
@@ -889,12 +881,12 @@
if(sight_mode & BORGMESON)
sight |= SEE_TURFS
see_invisible = min(see_invisible, SEE_INVISIBLE_MINIMUM)
lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE
see_in_dark = 1
if(sight_mode & BORGMATERIAL)
sight |= SEE_OBJS
see_invisible = min(see_invisible, SEE_INVISIBLE_MINIMUM)
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
see_in_dark = 1
if(sight_mode & BORGXRAY)
@@ -909,6 +901,7 @@
if(see_override)
see_invisible = see_override
sync_lighting_plane_alpha()
/mob/living/silicon/robot/update_stat()
if(status_flags & GODMODE)
@@ -931,6 +924,7 @@
update_headlamp()
diag_hud_set_status()
diag_hud_set_health()
diag_hud_set_aishell()
update_health_hud()
/mob/living/silicon/robot/revive(full_heal = 0, admin_revive = 0)
@@ -940,13 +934,13 @@
update_headlamp()
if(admin_revive)
locked = 1
notify_ai(1)
notify_ai(NEW_BORG)
. = 1
/mob/living/silicon/robot/fully_replace_character_name(oldname, newname)
..()
if(oldname != real_name)
notify_ai(3, oldname, newname)
notify_ai(RENAME, oldname, newname)
if(camera)
camera.c_tag = real_name
custom_name = newname
@@ -967,6 +961,7 @@
speed = 0
ionpulse = FALSE
revert_shell()
return 1
@@ -985,6 +980,11 @@
else
status_flags &= ~CANPUSH
if(module.clean_on_move)
flags |= CLEAN_ON_MOVE
else
flags &= ~CLEAN_ON_MOVE
hat_offset = module.hat_offset
magpulse = module.magpulsing
@@ -998,6 +998,97 @@
new_hat.forceMove(src)
update_icons()
/mob/living/silicon/robot/proc/make_shell(var/obj/item/borg/upgrade/ai/board)
if(!board)
upgrades |= new /obj/item/borg/upgrade/ai(src)
shell = TRUE
braintype = "AI Shell"
name = "[designation] AI Shell [rand(100,999)]"
real_name = name
GLOB.available_ai_shells |= src
if(camera)
camera.c_tag = real_name //update the camera name too
diag_hud_set_aishell()
notify_ai(AI_SHELL)
/mob/living/silicon/robot/proc/revert_shell()
if(!shell)
return
undeploy()
for(var/obj/item/borg/upgrade/ai/boris in src)
//A player forced reset of a borg would drop the module before this is called, so this is for catching edge cases
qdel(boris)
shell = FALSE
GLOB.available_ai_shells -= src
name = "Unformatted Cyborg [rand(100,999)]"
real_name = name
if(camera)
camera.c_tag = real_name
diag_hud_set_aishell()
/mob/living/silicon/robot/proc/deploy_init(var/mob/living/silicon/ai/AI)
real_name = "[AI.real_name] shell [rand(100, 999)] - [designation]" //Randomizing the name so it shows up seperately in the shells list
name = real_name
if(camera)
camera.c_tag = real_name //update the camera name too
mainframe = AI
deployed = TRUE
connected_ai = mainframe
mainframe.connected_robots |= src
lawupdate = TRUE
lawsync()
if(radio && AI.radio) //AI keeps all channels, including Syndie if it is a Traitor
if(AI.radio.syndie)
radio.make_syndie()
radio.subspace_transmission = TRUE
radio.channels = AI.radio.channels
for(var/chan in radio.channels)
radio.secure_radio_connections[chan] = add_radio(radio, GLOB.radiochannels[chan])
diag_hud_set_aishell()
undeployment_action.Grant(src)
/datum/action/innate/undeployment
name = "Disconnect from shell"
desc = "Stop controlling your shell and resume normal core operations."
button_icon_state = "ai_core"
/datum/action/innate/undeployment/Trigger()
if(!..())
return FALSE
var/mob/living/silicon/robot/R = owner
R.undeploy()
return TRUE
/mob/living/silicon/robot/proc/undeploy()
if(!deployed || !mind || !mainframe)
return
mainframe.redeploy_action.Grant(mainframe)
mainframe.redeploy_action.last_used_shell = src
mind.transfer_to(mainframe)
deployed = FALSE
mainframe.deployed_shell = null
undeployment_action.Remove(src)
if(radio) //Return radio to normal
radio.recalculateChannels()
if(camera)
camera.c_tag = real_name //update the camera name too
diag_hud_set_aishell()
mainframe.diag_hud_set_deployed()
mainframe.show_laws() //Always remind the AI when switching
mainframe = null
/mob/living/silicon/robot/attack_ai(mob/user)
if(shell && (!connected_ai || connected_ai == user))
var/mob/living/silicon/ai/AI = user
AI.deploy_to_shell(src)
/mob/living/silicon/robot/shell
shell = TRUE
/mob/living/silicon/robot/MouseDrop_T(mob/living/M, mob/living/user)
. = ..()
if(!(M in buckled_mobs) && isliving(M))
@@ -16,11 +16,12 @@
if (M.a_intent == INTENT_DISARM)
if(!(lying))
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
if(get_active_held_item())
var/obj/item/I = get_active_held_item()
if(I)
uneq_active()
visible_message("<span class='danger'>[M] disarmed [src]!</span>", \
"<span class='userdanger'>[M] has disabled [src]'s active module!</span>", null, COMBAT_MESSAGE_RANGE)
add_logs(M, src, "disarmed")
add_logs(M, src, "disarmed", "[I ? " removing \the [I]" : ""]")
else
Stun(2)
step(src,get_dir(M,src))
@@ -92,6 +93,8 @@
if(locked)
to_chat(user, "<span class='notice'>You emag the cover lock.</span>")
locked = 0
if(shell) //A warning to Traitors who may not know that emagging AI shells does not slave them.
to_chat(user, "<span class='boldwarning'>[src] seems to be controlled remotely! Emagging the interface may not work as expected.</span>")
else
to_chat(user, "<span class='warning'>The cover is already unlocked!</span>")
return
@@ -125,6 +128,12 @@
log_game("[key_name(user)] attempted to emag cyborg [key_name(src)], but they were slaved to traitor AI [connected_ai].")
return
if(shell) //AI shells cannot be emagged, so we try to make it look like a standard reset. Smart players may see through this, however.
to_chat(user, "<span class='danger'>[src] is remotely controlled! Your emag attempt has triggered a system reset instead!</span>")
log_game("[key_name(user)] attempted to emag an AI shell belonging to [key_name(src) ? key_name(src) : connected_ai]. The shell has been reset as a result.")
ResetModule()
return
SetEmagged(1)
SetStunned(3) //Borgs were getting into trouble because they would attack the emagger before the new laws were shown
lawupdate = 0
@@ -132,7 +141,7 @@
message_admins("[key_name_admin(user)] emagged cyborg [key_name_admin(src)]. Laws overridden.")
log_game("[key_name(user)] emagged cyborg [key_name(src)]. Laws overridden.")
var/time = time2text(world.realtime,"hh:mm:ss")
lawchanges.Add("[time] <B>:</B> [user.name]([user.key]) emagged [name]([key])")
GLOB.lawchanges.Add("[time] <B>:</B> [user.name]([user.key]) emagged [name]([key])")
to_chat(src, "<span class='danger'>ALERT: Foreign software detected.</span>")
sleep(5)
to_chat(src, "<span class='danger'>Initiating diagnostics...</span>")
@@ -20,6 +20,7 @@
var/can_be_pushed = TRUE
var/magpulsing = FALSE
var/clean_on_move = FALSE
var/did_feedback = FALSE
var/feedback_key
@@ -217,7 +218,7 @@
R.SetLockdown(0)
R.anchored = FALSE
R.notransform = FALSE
R.notify_ai(2)
R.notify_ai(NEW_MODULE)
if(R.hud_used)
R.hud_used.update_robot_modules_display()
if(feedback_key && !did_feedback)
@@ -228,8 +229,17 @@
basic_modules = list(
/obj/item/device/assembly/flash/cyborg,
/obj/item/weapon/reagent_containers/borghypo/epi,
/obj/item/device/healthanalyzer,
/obj/item/weapon/weldingtool/largetank/cyborg,
/obj/item/weapon/wrench/cyborg,
/obj/item/weapon/crowbar/cyborg,
/obj/item/stack/sheet/metal/cyborg,
/obj/item/stack/rods/cyborg,
/obj/item/stack/tile/plasteel/cyborg,
/obj/item/weapon/extinguisher,
/obj/item/weapon/pickaxe,
/obj/item/device/t_scanner/adv_mining_scanner,
/obj/item/weapon/restraints/handcuffs/cable/zipties/cyborg,
/obj/item/weapon/soap/nanotrasen,
/obj/item/borg/cyborghug)
emag_modules = list(/obj/item/weapon/melee/energy/sword/cyborg)
@@ -382,6 +392,7 @@
moduleselect_icon = "janitor"
feedback_key = "cyborg_janitor"
hat_offset = -5
clean_on_move = TRUE
/obj/item/weapon/reagent_containers/spray/cyborg_drying
name = "drying agent spray"
+5 -5
View File
@@ -10,7 +10,7 @@
desig = trim_left(S.designation + " " + S.job)
var/message_a = say_quote(message, get_spans())
var/rendered = "<i><span class='game say'>Robotic Talk, <span class='name'>[name]</span> <span class='message'>[message_a]</span></span></i>"
for(var/mob/M in player_list)
for(var/mob/M in GLOB.player_list)
if(M.binarycheck())
if(isAI(M))
var/renderedAI = "<i><span class='game say'>Robotic Talk, <a href='?src=\ref[M];track=[html_encode(name)]'><span class='name'>[name] ([desig])</span></a> <span class='message'>[message_a]</span></span></i>"
@@ -33,19 +33,19 @@
/mob/living/silicon/lingcheck()
return 0 //Borged or AI'd lings can't speak on the ling channel.
/mob/living/silicon/radio(message, message_mode, list/spans)
/mob/living/silicon/radio(message, message_mode, list/spans, language)
. = ..()
if(. != 0)
return .
if(message_mode == "robot")
if (radio)
radio.talk_into(src, message, , spans)
radio.talk_into(src, message, , spans, language)
return REDUCE_RANGE
else if(message_mode in radiochannels)
else if(message_mode in GLOB.radiochannels)
if(radio)
radio.talk_into(src, message, message_mode, spans)
radio.talk_into(src, message, message_mode, spans, language)
return ITALICS | REDUCE_RANGE
return 0
+13 -15
View File
@@ -1,13 +1,12 @@
/mob/living/silicon
gender = NEUTER
voice_name = "synthesized voice"
languages_spoken = ROBOT | HUMAN
languages_understood = ROBOT | HUMAN
has_unlimited_silicon_privilege = 1
verb_say = "states"
verb_ask = "queries"
verb_exclaim = "declares"
verb_yell = "alarms"
initial_languages = list(/datum/language/common, /datum/language/machine)
see_in_dark = 8
bubble_icon = "machine"
weather_immunities = list("ash")
@@ -21,8 +20,7 @@
var/designation = ""
var/radiomod = "" //Radio character used before state laws/arrivals announce to allow department transmissions, default, or none at all.
var/obj/item/device/camera/siliconcam/aicamera = null //photography
//hud_possible = list(DIAG_STAT_HUD, DIAG_HUD, ANTAG_HUD)
hud_possible = list(ANTAG_HUD, DIAG_STAT_HUD, DIAG_HUD)
hud_possible = list(ANTAG_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_TRACK_HUD)
var/obj/item/device/radio/borg/radio = null //AIs dont use this but this is at the silicon level to advoid copypasta in say()
@@ -41,8 +39,8 @@
/mob/living/silicon/Initialize()
..()
silicon_mobs += src
var/datum/atom_hud/data/diagnostic/diag_hud = huds[DATA_HUD_DIAGNOSTIC]
GLOB.silicon_mobs += src
var/datum/atom_hud/data/diagnostic/diag_hud = GLOB.huds[DATA_HUD_DIAGNOSTIC]
diag_hud.add_to_hud(src)
diag_hud_set_status()
diag_hud_set_health()
@@ -56,7 +54,7 @@
/mob/living/silicon/Destroy()
radio = null
aicamera = null
silicon_mobs -= src
GLOB.silicon_mobs -= src
return ..()
/mob/living/silicon/contents_explosion(severity, target)
@@ -307,8 +305,8 @@
else if(Autochan == "None") //Prevents use of the radio for automatic annoucements.
radiomod = ""
else //For department channels, if any, given by the internal radio.
for(var/key in department_radio_keys)
if(department_radio_keys[key] == Autochan)
for(var/key in GLOB.department_radio_keys)
if(GLOB.department_radio_keys[key] == Autochan)
radiomod = key
break
@@ -327,23 +325,23 @@
return -10
/mob/living/silicon/proc/remove_med_sec_hud()
var/datum/atom_hud/secsensor = huds[sec_hud]
var/datum/atom_hud/medsensor = huds[med_hud]
var/datum/atom_hud/diagsensor = huds[d_hud]
var/datum/atom_hud/secsensor = GLOB.huds[sec_hud]
var/datum/atom_hud/medsensor = GLOB.huds[med_hud]
var/datum/atom_hud/diagsensor = GLOB.huds[d_hud]
secsensor.remove_hud_from(src)
medsensor.remove_hud_from(src)
diagsensor.remove_hud_from(src)
/mob/living/silicon/proc/add_sec_hud()
var/datum/atom_hud/secsensor = huds[sec_hud]
var/datum/atom_hud/secsensor = GLOB.huds[sec_hud]
secsensor.add_hud_to(src)
/mob/living/silicon/proc/add_med_hud()
var/datum/atom_hud/medsensor = huds[med_hud]
var/datum/atom_hud/medsensor = GLOB.huds[med_hud]
medsensor.add_hud_to(src)
/mob/living/silicon/proc/add_diag_hud()
var/datum/atom_hud/diagsensor = huds[d_hud]
var/datum/atom_hud/diagsensor = GLOB.huds[d_hud]
diagsensor.add_hud_to(src)
/mob/living/silicon/proc/sensor_mode()
@@ -24,7 +24,8 @@
"<span class='userdanger'>[M] took a swipe at [src]!</span>")
/mob/living/silicon/attack_animal(mob/living/simple_animal/M)
if(..())
. = ..()
if(.)
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
if(prob(damage))
for(var/mob/living/N in buckled_mobs)
@@ -44,7 +45,6 @@
adjustCloneLoss(damage)
if(STAMINA)
adjustStaminaLoss(damage)
updatehealth()
/mob/living/silicon/attack_paw(mob/living/user)
return attack_hand(user)
@@ -10,10 +10,7 @@
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
if("grab")
if(grab_state >= GRAB_AGGRESSIVE && isliving(pulling))
vore_attack(M, pulling)
else
grabbedby(M)
grabbedby(M)
if("harm", "disarm")
M.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
@@ -63,25 +60,25 @@
return 1
/mob/living/simple_animal/attack_larva(mob/living/carbon/alien/larva/L)
if(..() && stat != DEAD) //successful larva bite
. = ..()
if(. && stat != DEAD) //successful larva bite
var/damage = rand(5, 10)
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
attack_threshold_check(damage)
return 1
. = attack_threshold_check(damage)
if(.)
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
/mob/living/simple_animal/attack_animal(mob/living/simple_animal/M)
if(..())
. = ..()
if(.)
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
attack_threshold_check(damage, M.melee_damage_type)
return 1
return attack_threshold_check(damage, M.melee_damage_type)
/mob/living/simple_animal/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime attack
var/damage = rand(15, 25)
if(M.is_adult)
damage = rand(20, 35)
attack_threshold_check(damage)
return 1
return attack_threshold_check(damage)
/mob/living/simple_animal/proc/attack_threshold_check(damage, damagetype = BRUTE, armorcheck = "melee")
var/temp_damage = damage
@@ -92,8 +89,10 @@
if(temp_damage >= 0 && temp_damage <= force_threshold)
visible_message("<span class='warning'>[src] looks unharmed.</span>")
return FALSE
else
apply_damage(damage, damagetype, null, getarmor(null, armorcheck))
return TRUE
/mob/living/simple_animal/bullet_act(obj/item/projectile/Proj)
if(!Proj)
@@ -136,4 +135,4 @@
visual_effect_icon = ATTACK_EFFECT_PUNCH
else
visual_effect_icon = ATTACK_EFFECT_SMASH
..()
..()
@@ -20,6 +20,7 @@
verb_ask = "queries"
verb_exclaim = "declares"
verb_yell = "alarms"
initial_languages = list(/datum/language/common, /datum/language/machine)
bubble_icon = "machine"
faction = list("neutral", "silicon" , "turret")
@@ -118,7 +119,7 @@
..()
access_card = new /obj/item/weapon/card/id(src)
//This access is so bots can be immediately set to patrol and leave Robotics, instead of having to be let out first.
access_card.access += access_robotics
access_card.access += GLOB.access_robotics
set_custom_texts()
Radio = new/obj/item/device/radio(src)
if(radio_key)
@@ -131,7 +132,7 @@
//Adds bot to the diagnostic HUD system
prepare_huds()
var/datum/atom_hud/data/diagnostic/diag_hud = huds[DATA_HUD_DIAGNOSTIC]
var/datum/atom_hud/data/diagnostic/diag_hud = GLOB.huds[DATA_HUD_DIAGNOSTIC]
diag_hud.add_to_hud(src)
diag_hud_set_bothealth()
diag_hud_set_botstat()
@@ -140,6 +141,9 @@
//Gives a HUD view to player bots that use a HUD.
activate_data_hud()
grant_language(/datum/language/common)
grant_language(/datum/language/machine)
/mob/living/simple_animal/bot/update_canmove()
. = ..()
@@ -323,30 +327,29 @@
if((!on) || (!message))
return
if(channel && Radio.channels[channel])// Use radio if we have channel key
Radio.talk_into(src, message, channel, get_spans())
Radio.talk_into(src, message, channel, get_spans(), get_default_language())
else
say(message)
return
/mob/living/simple_animal/bot/get_spans()
return ..() | SPAN_ROBOT
/mob/living/simple_animal/bot/radio(message, message_mode, list/spans)
/mob/living/simple_animal/bot/radio(message, message_mode, list/spans, language)
. = ..()
if(. != 0)
return .
switch(message_mode)
if(MODE_HEADSET)
Radio.talk_into(src, message, , spans)
Radio.talk_into(src, message, , spans, language)
return REDUCE_RANGE
if(MODE_DEPARTMENT)
Radio.talk_into(src, message, message_mode, spans)
Radio.talk_into(src, message, message_mode, spans, language)
return REDUCE_RANGE
if(message_mode in radiochannels)
Radio.talk_into(src, message, message_mode, spans)
if(message_mode in GLOB.radiochannels)
Radio.talk_into(src, message, message_mode, spans, language)
return REDUCE_RANGE
return 0
@@ -607,7 +610,7 @@ Pass a positive integer as an argument to override a bot's default speed.
/mob/living/simple_animal/bot/proc/get_next_patrol_target()
// search the beacon list for the next target in the list.
for(var/obj/machinery/navbeacon/NB in navbeacons["[z]"])
for(var/obj/machinery/navbeacon/NB in GLOB.navbeacons["[z]"])
if(NB.location == next_destination) //Does the Beacon location text match the destination?
destination = new_destination //We now know the name of where we want to go.
patrol_target = NB.loc //Get its location and set it as the target.
@@ -615,7 +618,7 @@ Pass a positive integer as an argument to override a bot's default speed.
return 1
/mob/living/simple_animal/bot/proc/find_nearest_beacon()
for(var/obj/machinery/navbeacon/NB in navbeacons["[z]"])
for(var/obj/machinery/navbeacon/NB in GLOB.navbeacons["[z]"])
var/dist = get_dist(src, NB)
if(nearest_beacon) //Loop though the beacon net to find the true closest beacon.
//Ignore the beacon if were are located on it.
@@ -922,5 +925,5 @@ Pass a positive integer as an argument to override a bot's default speed.
//If a bot has its own HUD (for player bots), provide it.
if(!data_hud_type)
return
var/datum/atom_hud/datahud = huds[data_hud_type]
var/datum/atom_hud/datahud = GLOB.huds[data_hud_type]
datahud.add_hud_to(src)
@@ -265,7 +265,7 @@
..()
/obj/machinery/bot_core/cleanbot
req_one_access = list(access_janitor, access_robotics)
req_one_access = list(GLOB.access_janitor, GLOB.access_robotics)
/mob/living/simple_animal/bot/cleanbot/get_controls(mob/user)
@@ -419,8 +419,7 @@
return
build_step++
to_chat(user, "<span class='notice'>You complete the Securitron! Beep boop.</span>")
var/mob/living/simple_animal/bot/secbot/S = new /mob/living/simple_animal/bot/secbot
S.loc = get_turf(src)
var/mob/living/simple_animal/bot/secbot/S = new /mob/living/simple_animal/bot/secbot(get_turf(src))
S.name = created_name
S.baton_type = I.type
qdel(I)
@@ -59,7 +59,7 @@
shot_delay = 6//Longer shot delay because JESUS CHRIST
check_records = 0//Don't actively target people set to arrest
arrest_type = 1//Don't even try to cuff
bot_core.req_access = list(access_maint_tunnels, access_theatre)
bot_core.req_access = list(GLOB.access_maint_tunnels, GLOB.access_theatre)
arrest_type = 1
if((lasercolor == "b") && (name == "\improper ED-209 Security Robot"))//Picks a name if there isn't already a custome one
name = pick("BLUE BALLER","SANIC","BLUE KILLDEATH MURDERBOT")
@@ -67,7 +67,7 @@
name = pick("RED RAMPAGE","RED ROVER","RED KILLDEATH MURDERBOT")
//SECHUD
var/datum/atom_hud/secsensor = huds[DATA_HUD_SECURITY_ADVANCED]
var/datum/atom_hud/secsensor = GLOB.huds[DATA_HUD_SECURITY_ADVANCED]
secsensor.add_hud_to(src)
/mob/living/simple_animal/bot/ed209/turn_on()
@@ -387,7 +387,7 @@
..()
/obj/machinery/bot_core/floorbot
req_one_access = list(access_construction, access_robotics)
req_one_access = list(GLOB.access_construction, GLOB.access_robotics)
/mob/living/simple_animal/bot/floorbot/UnarmedAttack(atom/A)
if(isturf(A))
@@ -338,7 +338,7 @@
/mob/living/simple_animal/bot/medbot/proc/assess_patient(mob/living/carbon/C)
//Time to see if they need medical help!
if(C.stat == 2)
if(C.stat == DEAD || (C.status_flags & FAKEDEATH))
return 0 //welp too late for them!
if(C.suiciding)
@@ -404,7 +404,7 @@
soft_reset()
return
if(C.stat == 2)
if(C.stat == DEAD || (C.status_flags & FAKEDEATH))
var/list/messagevoice = list("No! Stay with me!" = 'sound/voice/mno.ogg',"Live, damnit! LIVE!" = 'sound/voice/mlive.ogg',"I...I've never lost a patient before. Not today, I mean." = 'sound/voice/mlost.ogg')
var/message = pick(messagevoice)
speak(message)
@@ -496,7 +496,7 @@
return
/mob/living/simple_animal/bot/medbot/proc/check_overdose(mob/living/carbon/patient,reagent_id,injection_amount)
var/datum/reagent/R = chemical_reagents_list[reagent_id]
var/datum/reagent/R = GLOB.chemical_reagents_list[reagent_id]
if(!R.overdose_threshold) //Some chems do not have an OD threshold
return 0
var/current_volume = patient.reagents.get_reagent_amount(reagent_id)
@@ -545,4 +545,4 @@
declare_cooldown = 0
/obj/machinery/bot_core/medbot
req_one_access =list(access_medical, access_robotics)
req_one_access =list(GLOB.access_medical, GLOB.access_robotics)
@@ -4,8 +4,6 @@
// Navigates via floor navbeacons
// Remote Controlled from QM's PDA
var/global/mulebot_count = 0
#define SIGH 0
#define ANNOYED 1
#define DELIGHT 2
@@ -58,10 +56,10 @@ var/global/mulebot_count = 0
cell.charge = 2000
cell.maxcharge = 2000
spawn(10) // must wait for map loading to finish
mulebot_count += 1
if(!suffix)
set_suffix("#[mulebot_count]")
var/static/mulebot_count = 0
mulebot_count += 1
if(!suffix)
set_suffix("#[mulebot_count]")
/mob/living/simple_animal/bot/mulebot/Destroy()
unload(0)
@@ -165,7 +163,7 @@ var/global/mulebot_count = 0
ui_interact(user)
/mob/living/simple_animal/bot/mulebot/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, \
datum/tgui/master_ui = null, datum/ui_state/state = default_state)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "mulebot", name, 600, 375, master_ui, state)
@@ -231,7 +229,7 @@ var/global/mulebot_count = 0
if(mode == BOT_IDLE || mode == BOT_DELIVER)
start_home()
if("destination")
var/new_dest = input(user, "Enter Destination:", name, destination) as null|anything in deliverybeacontags
var/new_dest = input(user, "Enter Destination:", name, destination) as null|anything in GLOB.deliverybeacontags
if(new_dest)
set_destination(new_dest)
if("setid")
@@ -239,7 +237,7 @@ var/global/mulebot_count = 0
if(new_id)
set_suffix(new_id)
if("sethome")
var/new_home = input(user, "Enter Home:", name, home_destination) as null|anything in deliverybeacontags
var/new_home = input(user, "Enter Home:", name, home_destination) as null|anything in GLOB.deliverybeacontags
if(new_home)
home_destination = new_home
if("unload")
@@ -686,7 +684,7 @@ var/global/mulebot_count = 0
if(!on || wires.is_cut(WIRE_BEACON))
return
for(var/obj/machinery/navbeacon/NB in deliverybeacons)
for(var/obj/machinery/navbeacon/NB in GLOB.deliverybeacons)
if(NB.location == new_destination) // if the beacon location matches the set destination
// the we will navigate there
destination = new_destination
@@ -754,4 +752,4 @@ var/global/mulebot_count = 0
#undef DELIGHT
/obj/machinery/bot_core/mulebot
req_access = list(access_cargo)
req_access = list(GLOB.access_cargo)

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