mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-12 23:53:47 +01:00
Merge branch 'master' into stationgoals
This commit is contained in:
@@ -167,7 +167,7 @@ var/list/admin_verbs_debug = list(
|
||||
/client/proc/admin_serialize,
|
||||
/client/proc/admin_deserialize,
|
||||
/client/proc/jump_to_ruin,
|
||||
/client/proc/toggle_medal_disable
|
||||
/client/proc/toggle_medal_disable
|
||||
)
|
||||
var/list/admin_verbs_possess = list(
|
||||
/proc/possess,
|
||||
@@ -214,6 +214,10 @@ var/list/admin_verbs_snpc = list(
|
||||
/client/proc/hide_snpc_verbs
|
||||
)
|
||||
|
||||
/client/proc/on_holder_add()
|
||||
if(chatOutput && chatOutput.loaded)
|
||||
chatOutput.loadAdmin()
|
||||
|
||||
/client/proc/add_admin_verbs()
|
||||
if(holder)
|
||||
verbs += admin_verbs_default
|
||||
|
||||
@@ -32,6 +32,7 @@ var/list/admin_datums = list()
|
||||
if(istype(C))
|
||||
owner = C
|
||||
owner.holder = src
|
||||
owner.on_holder_add()
|
||||
owner.add_admin_verbs() //TODO
|
||||
owner.verbs -= /client/proc/readmin
|
||||
admins |= C
|
||||
|
||||
@@ -531,6 +531,16 @@
|
||||
if(ticker.mode.greyshirts.len)
|
||||
dat += check_role_table("Greyshirts", ticker.mode.greyshirts)
|
||||
|
||||
if(ts_spiderlist.len)
|
||||
var/list/spider_minds = list()
|
||||
for(var/mob/living/simple_animal/hostile/poison/terror_spider/S in ts_spiderlist)
|
||||
if(S.ckey)
|
||||
spider_minds += S.mind
|
||||
dat += check_role_table("Terror Spiders", spider_minds)
|
||||
|
||||
if(ticker.mode.ert.len)
|
||||
dat += check_role_table("ERT", ticker.mode.ert)
|
||||
|
||||
dat += "</body></html>"
|
||||
usr << browse(dat, "window=roundstatus;size=400x500")
|
||||
else
|
||||
|
||||
@@ -1710,6 +1710,103 @@
|
||||
to_chat(src.owner, "You sent a [eviltype] fax to [H]")
|
||||
log_admin("[key_name(src.owner)] sent [key_name(H)] a [eviltype] fax")
|
||||
message_admins("[key_name_admin(src.owner)] replied to [key_name_admin(H)] with a [eviltype] fax")
|
||||
else if(href_list["Bless"])
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
var/mob/living/M = locateUID(href_list["Bless"])
|
||||
if(!istype(M))
|
||||
to_chat(usr, "This can only be used on instances of type /mob/living")
|
||||
return
|
||||
var/btypes = list("To Arrivals", "Moderate Heal")
|
||||
var/mob/living/carbon/human/H
|
||||
if(ishuman(M))
|
||||
H = M
|
||||
btypes += "Heal Over Time"
|
||||
btypes += "Permanent Regeneration"
|
||||
btypes += "Super Powers"
|
||||
var/blessing = input(src.owner, "How would you like to bless [M]?", "Its good to be good...", "") as null|anything in btypes
|
||||
if(!(blessing in btypes))
|
||||
return
|
||||
switch(blessing)
|
||||
if("To Arrivals")
|
||||
M.forceMove(pick(latejoin))
|
||||
to_chat(M, "<span class='userdanger'>You are abruptly pulled through space!</span>")
|
||||
if("Moderate Heal")
|
||||
M.adjustBruteLoss(-25)
|
||||
M.adjustFireLoss(-25)
|
||||
M.adjustToxLoss(-25)
|
||||
M.adjustOxyLoss(-25)
|
||||
to_chat(M,"<span class='userdanger'>You feel invigorated!</span>")
|
||||
if("Heal Over Time")
|
||||
H.reagents.add_reagent("salglu_solution", 30)
|
||||
H.reagents.add_reagent("salbutamol", 20)
|
||||
H.reagents.add_reagent("spaceacillin", 20)
|
||||
if("Permanent Regeneration")
|
||||
H.dna.SetSEState(REGENERATEBLOCK, 1)
|
||||
genemutcheck(H, REGENERATEBLOCK, null, MUTCHK_FORCED)
|
||||
H.update_mutations()
|
||||
if("Super Powers")
|
||||
var/list/default_genes = list(REGENERATEBLOCK, NOBREATHBLOCK, COLDBLOCK)
|
||||
for(var/gene in default_genes)
|
||||
H.dna.SetSEState(gene, 1)
|
||||
genemutcheck(H, gene, null, MUTCHK_FORCED)
|
||||
H.update_mutations()
|
||||
else if(href_list["Smite"])
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
var/mob/living/M = locateUID(href_list["Smite"])
|
||||
var/mob/living/carbon/human/H
|
||||
if(!istype(M))
|
||||
to_chat(usr, "This can only be used on instances of type /mob/living")
|
||||
return
|
||||
var/ptypes = list("Lightning bolt", "Fire Death", "Gib")
|
||||
if(ishuman(M))
|
||||
H = M
|
||||
ptypes += "Brain Damage"
|
||||
ptypes += "Honk Tumor"
|
||||
ptypes += "Cluwne"
|
||||
ptypes += "Mutagen Cookie"
|
||||
ptypes += "Hellwater Cookie"
|
||||
var/punishment = input(src.owner, "How would you like to smite [M]?", "Its good to be baaaad...", "") as null|anything in ptypes
|
||||
if(!(punishment in ptypes))
|
||||
return
|
||||
switch(punishment)
|
||||
if("Lightning bolt")
|
||||
M.electrocute_act(5, "Lightning Bolt", safety=1)
|
||||
playsound(get_turf(M), 'sound/magic/LightningShock.ogg', 50, 1, -1)
|
||||
M.adjustFireLoss(75)
|
||||
M.Weaken(5)
|
||||
to_chat(M, "<span class='userdanger'>The gods have punished you for your sins!</span>")
|
||||
if("Brain Damage")
|
||||
H.adjustBrainLoss(75)
|
||||
if("Fire Death")
|
||||
to_chat(M,"<span class='userdanger'>You feel hotter than usual. Maybe you should lowe-wait, is that your hand melting?</span>")
|
||||
var/turf/simulated/T = get_turf(M)
|
||||
new /obj/effect/hotspot(T)
|
||||
M.adjustFireLoss(150)
|
||||
if("Honk Tumor")
|
||||
if(!H.get_int_organ(/obj/item/organ/internal/honktumor))
|
||||
var/obj/item/organ/internal/organ = new /obj/item/organ/internal/honktumor
|
||||
to_chat(H, "<span class='userdanger'>Life seems funnier, somehow.</span>")
|
||||
organ.insert(H)
|
||||
if("Cluwne")
|
||||
H.makeCluwne()
|
||||
if("Mutagen Cookie")
|
||||
var/obj/item/weapon/reagent_containers/food/snacks/cookie/evilcookie = new /obj/item/weapon/reagent_containers/food/snacks/cookie
|
||||
evilcookie.reagents.add_reagent("mutagen", 10)
|
||||
evilcookie.desc = "It has a faint green glow."
|
||||
evilcookie.bitesize = 100
|
||||
H.drop_l_hand()
|
||||
H.equip_to_slot_or_del(evilcookie, slot_l_hand)
|
||||
if("Hellwater Cookie")
|
||||
var/obj/item/weapon/reagent_containers/food/snacks/cookie/evilcookie = new /obj/item/weapon/reagent_containers/food/snacks/cookie
|
||||
evilcookie.reagents.add_reagent("hell_water", 25)
|
||||
evilcookie.desc = "Sulphur-flavored."
|
||||
evilcookie.bitesize = 100
|
||||
H.drop_l_hand()
|
||||
H.equip_to_slot_or_del(evilcookie, slot_l_hand)
|
||||
if("Gib")
|
||||
M.gib(FALSE)
|
||||
else if(href_list["FaxReplyTemplate"])
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
return
|
||||
|
||||
var/image/cross = image('icons/obj/storage.dmi',"bible")
|
||||
msg = "\blue [bicon(cross)] <b><font color=purple>PRAY: </font>[key_name(src, 1)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[src]'>?</A>) (<A HREF='?_src_=holder;adminplayeropts=\ref[src]'>PP</A>) (<A HREF='?_src_=vars;Vars=[UID()]'>VV</A>) (<A HREF='?_src_=holder;subtlemessage=\ref[src]'>SM</A>) ([admin_jump_link(src)]) (<A HREF='?_src_=holder;secretsadmin=check_antagonist'>CA</A>) (<A HREF='?_src_=holder;adminspawncookie=\ref[src]'>SC</a>):</b> [msg]"
|
||||
msg = "\blue [bicon(cross)] <b><font color=purple>PRAY: </font>[key_name(src, 1)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[src]'>?</A>) (<A HREF='?_src_=holder;adminplayeropts=\ref[src]'>PP</A>) (<A HREF='?_src_=vars;Vars=[UID()]'>VV</A>) (<A HREF='?_src_=holder;subtlemessage=\ref[src]'>SM</A>) ([admin_jump_link(src)]) (<A HREF='?_src_=holder;secretsadmin=check_antagonist'>CA</A>) (<A HREF='?_src_=holder;adminspawncookie=\ref[src]'>SC</a>) (<A HREF='?_src_=holder;Bless=[UID()]'>BLESS</A>) (<A HREF='?_src_=holder;Smite=[UID()]'>SMITE</A>):</b> [msg]"
|
||||
|
||||
for(var/client/X in admins)
|
||||
if(check_rights(R_EVENT,0,X.mob))
|
||||
|
||||
@@ -92,4 +92,6 @@
|
||||
var/datum/chatOutput/chatOutput
|
||||
|
||||
// Donator stuff.
|
||||
var/donator_level = DONATOR_LEVEL_NONE
|
||||
var/donator_level = DONATOR_LEVEL_NONE
|
||||
|
||||
var/var_edited = FALSE
|
||||
|
||||
@@ -232,7 +232,7 @@
|
||||
to_chat(src, "Become a BYOND member to access member-perks and features, as well as support the engine that makes this game possible. <a href='http://www.byond.com/membership'>Click here to find out more</a>.")
|
||||
return 0
|
||||
return 1
|
||||
|
||||
|
||||
//Like for /atoms, but clients are their own snowflake FUCK
|
||||
/client/proc/setDir(newdir)
|
||||
dir = newdir
|
||||
@@ -335,6 +335,7 @@
|
||||
world.update_status()
|
||||
|
||||
if(holder)
|
||||
on_holder_add()
|
||||
add_admin_verbs()
|
||||
admin_memo_output("Show", 0, 1)
|
||||
|
||||
@@ -408,10 +409,12 @@
|
||||
if(IsGuestKey(key))
|
||||
return
|
||||
|
||||
|
||||
establish_db_connection()
|
||||
if(!dbcon.IsConnected())
|
||||
return
|
||||
|
||||
|
||||
var/DBQuery/query = dbcon.NewQuery("SELECT id, datediff(Now(),firstseen) as age FROM [format_table_name("player")] WHERE ckey = '[ckey]'")
|
||||
query.Execute()
|
||||
var/sql_id = 0
|
||||
@@ -421,6 +424,7 @@
|
||||
player_age = text2num(query.item[2])
|
||||
break
|
||||
|
||||
|
||||
var/DBQuery/query_ip = dbcon.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ip = '[address]'")
|
||||
query_ip.Execute()
|
||||
related_accounts_ip = list()
|
||||
@@ -428,6 +432,7 @@
|
||||
if(ckey != query_ip.item[1])
|
||||
related_accounts_ip.Add("[query_ip.item[1]]")
|
||||
|
||||
|
||||
var/DBQuery/query_cid = dbcon.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE computerid = '[computer_id]'")
|
||||
query_cid.Execute()
|
||||
related_accounts_cid = list()
|
||||
@@ -435,6 +440,7 @@
|
||||
if(ckey != query_cid.item[1])
|
||||
related_accounts_cid.Add("[query_cid.item[1]]")
|
||||
|
||||
|
||||
var/admin_rank = "Player"
|
||||
if(holder)
|
||||
admin_rank = holder.rank
|
||||
@@ -443,15 +449,18 @@
|
||||
if(check_randomizer(connectiontopic))
|
||||
return
|
||||
|
||||
|
||||
//Log all the alts
|
||||
if(related_accounts_cid.len)
|
||||
log_access("Alts: [key_name(src)]:[jointext(related_accounts_cid, " - ")]")
|
||||
|
||||
|
||||
var/watchreason = check_watchlist(ckey)
|
||||
if(watchreason)
|
||||
message_admins("<font color='red'><B>Notice: </B></font><font color='blue'>[key_name_admin(src)] is on the watchlist and has just connected - Reason: [watchreason]</font>")
|
||||
send2irc(config.admin_notify_irc, "Watchlist - [key_name(src)] is on the watchlist and has just connected - Reason: [watchreason]")
|
||||
|
||||
|
||||
//Just the standard check to see if it's actually a number
|
||||
if(sql_id)
|
||||
if(istext(sql_id))
|
||||
@@ -467,17 +476,24 @@
|
||||
if(sql_id)
|
||||
//Player already identified previously, we need to just update the 'lastseen', 'ip' and 'computer_id' variables
|
||||
var/DBQuery/query_update = dbcon.NewQuery("UPDATE [format_table_name("player")] SET lastseen = Now(), ip = '[sql_ip]', computerid = '[sql_computerid]', lastadminrank = '[sql_admin_rank]' WHERE id = [sql_id]")
|
||||
query_update.Execute()
|
||||
if(!query_update.Execute())
|
||||
var/err = query_update.ErrorMsg()
|
||||
log_game("SQL ERROR during log_client_to_db (update). Error : \[[err]\]\n")
|
||||
message_admins("SQL ERROR during log_client_to_db (update). Error : \[[err]\]\n")
|
||||
else
|
||||
//New player!! Need to insert all the stuff
|
||||
var/DBQuery/query_insert = dbcon.NewQuery("INSERT INTO [format_table_name("player")] (id, ckey, firstseen, lastseen, ip, computerid, lastadminrank) VALUES (null, '[ckey]', Now(), Now(), '[sql_ip]', '[sql_computerid]', '[sql_admin_rank]')")
|
||||
query_insert.Execute()
|
||||
if(!query_insert.Execute())
|
||||
var/err = query_insert.ErrorMsg()
|
||||
log_game("SQL ERROR during log_client_to_db (insert). Error : \[[err]\]\n")
|
||||
message_admins("SQL ERROR during log_client_to_db (insert). Error : \[[err]\]\n")
|
||||
|
||||
//Logging player access
|
||||
var/serverip = "[world.internet_address]:[world.port]"
|
||||
var/DBQuery/query_accesslog = dbcon.NewQuery("INSERT INTO `[format_table_name("connection_log")]`(`id`,`datetime`,`serverip`,`ckey`,`ip`,`computerid`) VALUES(null,Now(),'[serverip]','[ckey]','[sql_ip]','[sql_computerid]');")
|
||||
query_accesslog.Execute()
|
||||
|
||||
|
||||
#undef TOPIC_SPAM_DELAY
|
||||
#undef UPLOAD_LIMIT
|
||||
#undef MIN_CLIENT_VERSION
|
||||
@@ -628,3 +644,6 @@
|
||||
|
||||
/client/proc/colour_transition(var/list/colour_to = null, var/time = 10) //Call this with no parameters to reset to default.
|
||||
animate(src, color=colour_to, time=time, easing=SINE_EASING)
|
||||
|
||||
/client/proc/on_varedit()
|
||||
var_edited = TRUE
|
||||
|
||||
@@ -95,6 +95,8 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
|
||||
var/UI_style_alpha = 255
|
||||
var/windowflashing = TRUE
|
||||
|
||||
//ghostly preferences
|
||||
var/ghost_anonsay = 0
|
||||
|
||||
//character preferences
|
||||
var/real_name //our character's name
|
||||
@@ -283,6 +285,8 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
|
||||
dat += "<b>Species:</b> <a href='?_src_=prefs;preference=species;task=input'>[species]</a><br>"
|
||||
if(species == "Vox")
|
||||
dat += "<b>N2 Tank:</b> <a href='?_src_=prefs;preference=speciesprefs;task=input'>[speciesprefs ? "Large N2 Tank" : "Specialized N2 Tank"]</a><br>"
|
||||
if(species == "Grey")
|
||||
dat += "<b>Voice:</b> <a href ='?_src_=prefs;preference=speciesprefs;task=input'>[speciesprefs ? "Wingdings" : "Normal"]</a><BR>"
|
||||
dat += "<b>Secondary Language:</b> <a href='?_src_=prefs;preference=language;task=input'>[language]</a><br>"
|
||||
dat += "<b>Blood Type:</b> <a href='?_src_=prefs;preference=b_type;task=input'>[b_type]</a><br>"
|
||||
if(species in list("Human", "Drask", "Vox"))
|
||||
@@ -444,6 +448,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
|
||||
dat += "<b>Ghost ears:</b> <a href='?_src_=prefs;preference=ghost_ears'><b>[(toggles & CHAT_GHOSTEARS) ? "Nearest Creatures" : "All Speech"]</b></a><br>"
|
||||
dat += "<b>Ghost sight:</b> <a href='?_src_=prefs;preference=ghost_sight'><b>[(toggles & CHAT_GHOSTSIGHT) ? "Nearest Creatures" : "All Emotes"]</b></a><br>"
|
||||
dat += "<b>Ghost radio:</b> <a href='?_src_=prefs;preference=ghost_radio'><b>[(toggles & CHAT_GHOSTRADIO) ? "Nearest Speakers" : "All Chatter"]</b></a><br>"
|
||||
dat += "<b>Deadchat anonymity:</b> <a href='?_src_=prefs;preference=ghost_anonsay'><b>[ghost_anonsay ? "Anonymous" : "Not Anonymous"]</b></a><br>"
|
||||
|
||||
dat += "</td><td width='300px' height='300px' valign='top'>"
|
||||
dat += "<h2>Special Role Settings</h2>"
|
||||
@@ -1334,6 +1339,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
|
||||
b_skin = 0
|
||||
|
||||
alt_head = "None" //No alt heads on species that don't have them.
|
||||
speciesprefs = 0 //My Vox tank shouldn't change how my future Grey talks.
|
||||
|
||||
body_accessory = null //no vulptail on humans damnit
|
||||
|
||||
@@ -1994,6 +2000,9 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
|
||||
if("ghost_radio")
|
||||
toggles ^= CHAT_GHOSTRADIO
|
||||
|
||||
if("ghost_anonsay")
|
||||
ghost_anonsay = !ghost_anonsay
|
||||
|
||||
if("save")
|
||||
save_preferences(user)
|
||||
save_character(user)
|
||||
@@ -2040,6 +2049,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
|
||||
|
||||
character.add_language(language)
|
||||
|
||||
|
||||
character.real_name = real_name
|
||||
character.dna.real_name = real_name
|
||||
character.name = character.real_name
|
||||
|
||||
@@ -14,8 +14,9 @@
|
||||
nanoui_fancy,
|
||||
show_ghostitem_attack,
|
||||
lastchangelog,
|
||||
exp,
|
||||
windowflashing
|
||||
windowflashing,
|
||||
ghost_anonsay,
|
||||
exp
|
||||
FROM [format_table_name("player")]
|
||||
WHERE ckey='[C.ckey]'"}
|
||||
)
|
||||
@@ -42,8 +43,9 @@
|
||||
nanoui_fancy = text2num(query.item[11])
|
||||
show_ghostitem_attack = text2num(query.item[12])
|
||||
lastchangelog = query.item[13]
|
||||
exp = query.item[14]
|
||||
windowflashing = text2num(query.item[15])
|
||||
windowflashing = text2num(query.item[14])
|
||||
ghost_anonsay = text2num(query.item[15])
|
||||
exp = query.item[16]
|
||||
|
||||
//Sanitize
|
||||
ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor))
|
||||
@@ -58,8 +60,9 @@
|
||||
nanoui_fancy = sanitize_integer(nanoui_fancy, 0, 1, initial(nanoui_fancy))
|
||||
show_ghostitem_attack = sanitize_integer(show_ghostitem_attack, 0, 1, initial(show_ghostitem_attack))
|
||||
lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog))
|
||||
exp = sanitize_text(exp, initial(exp))
|
||||
windowflashing = sanitize_integer(windowflashing, 0, 1, initial(windowflashing))
|
||||
ghost_anonsay = sanitize_integer(ghost_anonsay, 0, 1, initial(ghost_anonsay))
|
||||
exp = sanitize_text(exp, initial(exp))
|
||||
return 1
|
||||
|
||||
/datum/preferences/proc/save_preferences(client/C)
|
||||
@@ -84,7 +87,9 @@
|
||||
volume='[volume]',
|
||||
nanoui_fancy='[nanoui_fancy]',
|
||||
show_ghostitem_attack='[show_ghostitem_attack]',
|
||||
lastchangelog='[lastchangelog]'
|
||||
lastchangelog='[lastchangelog]',
|
||||
windowflashing='[windowflashing]',
|
||||
ghost_anonsay='[ghost_anonsay]'
|
||||
WHERE ckey='[C.ckey]'"}
|
||||
)
|
||||
|
||||
|
||||
@@ -327,8 +327,8 @@
|
||||
flash_protect = 0
|
||||
tint = 0
|
||||
var/mob/living/carbon/user = usr
|
||||
user.update_inv_glasses()
|
||||
user.update_tint()
|
||||
user.update_inv_glasses()
|
||||
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
@@ -492,4 +492,4 @@
|
||||
else
|
||||
to_chat(user, "<span class='notice'>The eye winks at you and vanishes into the abyss, you feel really unlucky.</span>")
|
||||
qdel(src)
|
||||
..()
|
||||
..()
|
||||
@@ -383,7 +383,7 @@
|
||||
|
||||
/obj/item/clothing/head/griffin/proc/caw()
|
||||
if(cooldown < world.time - 20) // A cooldown, to stop people being jerks
|
||||
playsound(src.loc, "sound/misc/caw.ogg", 50, 1)
|
||||
playsound(src.loc, 'sound/misc/caw.ogg', 50, 1)
|
||||
cooldown = world.time
|
||||
|
||||
|
||||
|
||||
@@ -67,9 +67,9 @@
|
||||
to_chat(usr, "You push the [src] up out of your face.")
|
||||
flash_protect = 0
|
||||
tint = 0
|
||||
var/mob/living/carbon/C = usr
|
||||
C.update_tint()
|
||||
usr.update_inv_head() //so our mob-overlays update
|
||||
var/mob/living/carbon/user = usr
|
||||
user.update_tint()
|
||||
user.update_inv_head() //so our mob-overlays update
|
||||
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
|
||||
@@ -52,7 +52,9 @@
|
||||
to_chat(usr, "You push the [src] up out of your face.")
|
||||
flash_protect = 0
|
||||
tint = 0
|
||||
usr.update_inv_wear_mask() //so our mob-overlays update
|
||||
var/mob/living/carbon/user = usr
|
||||
user.update_tint()
|
||||
user.update_inv_wear_mask() //so our mob-overlays update
|
||||
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
@@ -182,7 +184,7 @@
|
||||
|
||||
/obj/item/clothing/mask/gas/owl_mask/proc/hoot()
|
||||
if(cooldown < world.time - 35) // A cooldown, to stop people being jerks
|
||||
playsound(src.loc, "sound/misc/hoot.ogg", 50, 1)
|
||||
playsound(src.loc, 'sound/misc/hoot.ogg', 50, 1)
|
||||
cooldown = world.time
|
||||
|
||||
// ********************************************************************
|
||||
|
||||
@@ -40,8 +40,7 @@
|
||||
if(!isturf(I.loc)) //If it isn't on the floor. Do some checks to see if it's in our hands or a box. Otherwise give up.
|
||||
if(istype(I.loc,/obj/item/weapon/storage)) //in a container.
|
||||
var/obj/item/weapon/storage/U = I.loc
|
||||
user.client.screen -= I
|
||||
U.contents.Remove(I)
|
||||
U.remove_from_storage(I, src)
|
||||
else if(user.l_hand == I) //in a hand
|
||||
user.drop_l_hand()
|
||||
else if(user.r_hand == I) //in a hand
|
||||
@@ -59,6 +58,7 @@
|
||||
I.pixel_x = 0 //then remove it so it'll stay within the evidence bag
|
||||
I.pixel_y = 0
|
||||
var/image/img = image("icon"=I, "layer"=FLOAT_LAYER) //take a snapshot. (necessary to stop the underlays appearing under our inventory-HUD slots ~Carn
|
||||
img.plane = FLOAT_PLANE
|
||||
I.pixel_x = xx //and then return it
|
||||
I.pixel_y = yy
|
||||
overlays += img
|
||||
@@ -69,7 +69,7 @@
|
||||
w_class = I.w_class
|
||||
return 1
|
||||
|
||||
/obj/item/weapon/evidencebag/attack_self(mob/user as mob)
|
||||
/obj/item/weapon/evidencebag/attack_self(mob/user)
|
||||
if(contents.len)
|
||||
var/obj/item/I = contents[1]
|
||||
user.visible_message("<span class='notice'>[user] takes [I] out of [src].</span>", "<span class='notice'>You take [I] out of [src].</span>",\
|
||||
@@ -83,17 +83,16 @@
|
||||
else
|
||||
to_chat(user, "[src] is empty.")
|
||||
icon_state = "evidenceobj"
|
||||
return
|
||||
|
||||
/obj/item/weapon/storage/box/evidence
|
||||
name = "evidence bag box"
|
||||
desc = "A box claiming to contain evidence bags."
|
||||
New()
|
||||
new /obj/item/weapon/evidencebag(src)
|
||||
new /obj/item/weapon/evidencebag(src)
|
||||
new /obj/item/weapon/evidencebag(src)
|
||||
new /obj/item/weapon/evidencebag(src)
|
||||
new /obj/item/weapon/evidencebag(src)
|
||||
new /obj/item/weapon/evidencebag(src)
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/storage/box/evidence/New()
|
||||
new /obj/item/weapon/evidencebag(src)
|
||||
new /obj/item/weapon/evidencebag(src)
|
||||
new /obj/item/weapon/evidencebag(src)
|
||||
new /obj/item/weapon/evidencebag(src)
|
||||
new /obj/item/weapon/evidencebag(src)
|
||||
new /obj/item/weapon/evidencebag(src)
|
||||
..()
|
||||
@@ -66,7 +66,7 @@
|
||||
if(log.len && !scanning)
|
||||
scanning = 1
|
||||
to_chat(usr, "<span class='notice'>Printing report, please wait...</span>")
|
||||
playsound(loc, "sound/goonstation/machines/printer_thermal.ogg", 50, 1)
|
||||
playsound(loc, 'sound/goonstation/machines/printer_thermal.ogg', 50, 1)
|
||||
spawn(100)
|
||||
|
||||
// Create our paper
|
||||
|
||||
@@ -335,7 +335,7 @@ log transactions
|
||||
to_chat(usr, "<span class='notice'>The [src.name] flashes an error on its display.</span>")
|
||||
return
|
||||
lastprint = world.timeofday
|
||||
playsound(loc, "sound/goonstation/machines/printer_thermal.ogg", 50, 1)
|
||||
playsound(loc, 'sound/goonstation/machines/printer_thermal.ogg', 50, 1)
|
||||
var/obj/item/weapon/paper/R = new(src.loc)
|
||||
R.name = "Account balance: [authenticated_account.owner_name]"
|
||||
R.info = {"<b>NT Automated Teller Account Statement</b><br><br>
|
||||
|
||||
@@ -89,7 +89,7 @@ var/global/list/all_money_accounts = list()
|
||||
var/obj/item/smallDelivery/P = new /obj/item/smallDelivery(source_db.loc)
|
||||
|
||||
var/obj/item/weapon/paper/R = new /obj/item/weapon/paper(P)
|
||||
playsound(source_db.loc, "sound/goonstation/machines/printer_thermal.ogg", 50, 1)
|
||||
playsound(source_db.loc, 'sound/goonstation/machines/printer_thermal.ogg', 50, 1)
|
||||
P.wrapped = R
|
||||
R.name = "Account information: [M.owner_name]"
|
||||
|
||||
|
||||
@@ -220,7 +220,7 @@
|
||||
|
||||
if("print")
|
||||
var/text
|
||||
playsound(loc, "sound/goonstation/machines/printer_thermal.ogg", 50, 1)
|
||||
playsound(loc, 'sound/goonstation/machines/printer_thermal.ogg', 50, 1)
|
||||
var/obj/item/weapon/paper/P = new(loc)
|
||||
if(detailed_account_view)
|
||||
P.name = "account #[detailed_account_view.account_number] details"
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
linked_account = station_account
|
||||
|
||||
/obj/item/device/eftpos/proc/print_reference()
|
||||
playsound(loc, "sound/goonstation/machines/printer_thermal.ogg", 50, 1)
|
||||
playsound(loc, 'sound/goonstation/machines/printer_thermal.ogg', 50, 1)
|
||||
var/obj/item/weapon/paper/R = new(src.loc)
|
||||
R.name = "Reference: [eftpos_name]"
|
||||
|
||||
|
||||
@@ -201,7 +201,7 @@ var/const/POS_HEADER = {"<html>
|
||||
</tr>"}
|
||||
receipt += "</table></body></html>"
|
||||
|
||||
playsound(loc, "sound/goonstation/machines/printer_thermal.ogg", 50, 1)
|
||||
playsound(loc, 'sound/goonstation/machines/printer_thermal.ogg', 50, 1)
|
||||
var/obj/item/weapon/paper/P = new(loc)
|
||||
P.name="Receipt #[id]-[++sales]"
|
||||
P.info=receipt
|
||||
|
||||
@@ -191,7 +191,8 @@ var/list/event_last_fired = list()
|
||||
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Abductor Visit", /datum/event/abductor, 80, is_one_shot = 1),
|
||||
new /datum/event_meta/alien(EVENT_LEVEL_MAJOR, "Alien Infestation", /datum/event/alien_infestation, 0, list(ASSIGNMENT_SECURITY = 30), 1),
|
||||
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Traders", /datum/event/traders, 0, is_one_shot = 1),
|
||||
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Slaughter Demon", /datum/event/spawn_slaughter, 15, is_one_shot = 1),
|
||||
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Terror Spiders", /datum/event/spider_terror, 0, is_one_shot = 1),
|
||||
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Slaughter Demon", /datum/event/spawn_slaughter, 15, is_one_shot = 1)
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -29,14 +29,16 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
|
||||
anchored = 1
|
||||
var/z_original = 0
|
||||
var/destination
|
||||
var/notify = TRUE
|
||||
|
||||
/obj/effect/immovablerod/New(atom/start, atom/end)
|
||||
loc = start
|
||||
z_original = z
|
||||
destination = end
|
||||
notify_ghosts("\A [src] is inbound!",
|
||||
enter_link="<a href=?src=[UID()];follow=1>(Click to follow)</a>",
|
||||
source=src, action=NOTIFY_FOLLOW)
|
||||
if(notify)
|
||||
notify_ghosts("\A [src] is inbound!",
|
||||
enter_link="<a href=?src=[UID()];follow=1>(Click to follow)</a>",
|
||||
source=src, action=NOTIFY_FOLLOW)
|
||||
poi_list |= src
|
||||
if(end && end.z==z_original)
|
||||
walk_towards(src, destination, 1)
|
||||
|
||||
@@ -15,5 +15,5 @@
|
||||
|
||||
|
||||
|
||||
/datum/event/meteor_wave/goreops/end()
|
||||
/datum/event/meteor_wave/goreop/end()
|
||||
event_announcement.Announce("All MeteorOps are dead. Major Station Victory.", "MeteorOps")
|
||||
@@ -428,8 +428,8 @@
|
||||
if(potency != null)
|
||||
mutativeness = potency / 10
|
||||
if(production != null)
|
||||
spread_cap *= production / 5
|
||||
spread_multiplier /= production / 5
|
||||
spread_cap /= production / 5
|
||||
spread_multiplier *= production / 5
|
||||
..()
|
||||
|
||||
|
||||
@@ -567,4 +567,4 @@
|
||||
if(isliving(A))
|
||||
var/mob/living/M = A
|
||||
if(("vines" in M.faction) || ("plants" in M.faction))
|
||||
. = TRUE
|
||||
. = TRUE
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
|
||||
/datum/event/spider_terror
|
||||
announceWhen = 400
|
||||
var/spawncount = 1
|
||||
|
||||
/datum/event/spider_terror/setup()
|
||||
announceWhen = rand(announceWhen, announceWhen + 50)
|
||||
spawncount = 1
|
||||
|
||||
/datum/event/spider_infestation/announce()
|
||||
command_announcement.Announce("Confirmed outbreak of level 3 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/effects/siren.ogg')
|
||||
|
||||
/datum/event/spider_terror/start()
|
||||
|
||||
var/list/vents = list()
|
||||
for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in all_vent_pumps)
|
||||
if(is_station_level(temp_vent.loc.z) && !temp_vent.welded)
|
||||
if(temp_vent.parent.other_atmosmch.len > 50)
|
||||
vents += temp_vent
|
||||
|
||||
var/spider_type
|
||||
var/infestation_type = pick(1, 2, 3, 4)
|
||||
switch(infestation_type)
|
||||
if(1)
|
||||
spider_type = /mob/living/simple_animal/hostile/poison/terror_spider/green
|
||||
spawncount = pick(2,3)
|
||||
if(2)
|
||||
spider_type = /mob/living/simple_animal/hostile/poison/terror_spider/white
|
||||
spawncount = 1
|
||||
if(3)
|
||||
spider_type = /mob/living/simple_animal/hostile/poison/terror_spider/prince
|
||||
spawncount = 1
|
||||
if(4)
|
||||
spider_type = /mob/living/simple_animal/hostile/poison/terror_spider/queen
|
||||
spawncount = 1
|
||||
|
||||
while(spawncount >= 1 && vents.len)
|
||||
var/obj/vent = pick(vents)
|
||||
var/obj/effect/spider/spiderling/terror_spiderling/S = new(vent.loc)
|
||||
S.name = "evil-looking spiderling"
|
||||
S.grow_as = spider_type
|
||||
S.amount_grown = 75
|
||||
vents -= vent
|
||||
spawncount--
|
||||
@@ -1218,13 +1218,6 @@
|
||||
user.drop_item()
|
||||
forceMove(get_turf(O))
|
||||
return Expand()
|
||||
if(istype(O, /obj/machinery/computer/camera_advanced/xenobio))
|
||||
var/obj/machinery/computer/camera_advanced/xenobio/X = O
|
||||
X.monkeys++
|
||||
to_chat(user, "<span class='notice'>You feed [src] to the [X]. It now has [X.monkeys] monkey cubes stored.</span>")
|
||||
user.drop_item()
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/monkeycube/water_act(volume, temperature)
|
||||
|
||||
@@ -59,21 +59,14 @@ var/list/all_lighting_overlays = list() // Global list of lighting overlays.
|
||||
|
||||
var/max = max(cr.cache_mx, cg.cache_mx, cb.cache_mx, ca.cache_mx)
|
||||
|
||||
var/list/new_matrix = list(
|
||||
color = list(
|
||||
cr.cache_r, cr.cache_g, cr.cache_b, 0,
|
||||
cg.cache_r, cg.cache_g, cg.cache_b, 0,
|
||||
cb.cache_r, cb.cache_g, cb.cache_b, 0,
|
||||
ca.cache_r, ca.cache_g, ca.cache_b, 0,
|
||||
0, 0, 0, 1
|
||||
)
|
||||
var/lum = max > LIGHTING_SOFT_THRESHOLD
|
||||
|
||||
if(lum)
|
||||
luminosity = 1
|
||||
animate(src, color = new_matrix, time = 5)
|
||||
else
|
||||
animate(src, color = new_matrix, time = 5)
|
||||
animate(luminosity = 0, time = 0)
|
||||
)
|
||||
luminosity = max > LIGHTING_SOFT_THRESHOLD
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/var/list/datum/light_source/all_lighting_sources = list()
|
||||
// This is where the fun begins.
|
||||
// These are the main datums that emit light.
|
||||
|
||||
@@ -31,6 +32,7 @@
|
||||
var/force_update
|
||||
|
||||
/datum/light_source/New(var/atom/owner, var/atom/top)
|
||||
all_lighting_sources += src
|
||||
source_atom = owner // Set our new owner.
|
||||
if(!source_atom.light_sources)
|
||||
source_atom.light_sources = list()
|
||||
@@ -55,10 +57,12 @@
|
||||
|
||||
update()
|
||||
|
||||
|
||||
return ..()
|
||||
|
||||
// Kill ourselves.
|
||||
/datum/light_source/proc/destroy()
|
||||
all_lighting_sources -= src
|
||||
destroyed = TRUE
|
||||
force_update()
|
||||
if(source_atom)
|
||||
|
||||
@@ -701,310 +701,6 @@
|
||||
new /mob/living/simple_animal/hostile/mining_drone(get_turf(src))
|
||||
qdel(src)
|
||||
|
||||
/**********************Mining drone**********************/
|
||||
#define MINEDRONE_COLLECT 1
|
||||
#define MINEDRONE_ATTACK 2
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone
|
||||
name = "nanotrasen minebot"
|
||||
desc = "The instructions printed on the side read: This is a small robot used to support miners, can be set to search and collect loose ore, or to help fend off wildlife. A mining scanner can instruct it to drop loose ore. Field repairs can be done with a welder."
|
||||
icon = 'icons/obj/aibots.dmi'
|
||||
icon_state = "mining_drone"
|
||||
icon_living = "mining_drone"
|
||||
status_flags = CANSTUN|CANWEAKEN|CANPUSH
|
||||
mouse_opacity = 1
|
||||
faction = list("neutral")
|
||||
a_intent = I_HARM
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
minbodytemp = 0
|
||||
wander = 0
|
||||
idle_vision_range = 5
|
||||
move_to_delay = 10
|
||||
retreat_distance = 1
|
||||
minimum_distance = 2
|
||||
health = 125
|
||||
maxHealth = 125
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 15
|
||||
environment_smash = 0
|
||||
check_friendly_fire = 1
|
||||
stop_automated_movement_when_pulled = 1
|
||||
attacktext = "drills"
|
||||
attack_sound = 'sound/weapons/circsawhit.ogg'
|
||||
ranged = 1
|
||||
sentience_type = SENTIENCE_MINEBOT
|
||||
ranged_message = "shoots"
|
||||
ranged_cooldown_time = 30
|
||||
projectiletype = /obj/item/projectile/kinetic
|
||||
projectilesound = 'sound/weapons/Gunshot4.ogg'
|
||||
speak_emote = list("states")
|
||||
wanted_objects = list(/obj/item/weapon/ore/diamond, /obj/item/weapon/ore/gold, /obj/item/weapon/ore/silver,
|
||||
/obj/item/weapon/ore/plasma, /obj/item/weapon/ore/uranium, /obj/item/weapon/ore/iron,
|
||||
/obj/item/weapon/ore/bananium, /obj/item/weapon/ore/tranquillite, /obj/item/weapon/ore/glass)
|
||||
healable = 0
|
||||
var/mode = MINEDRONE_COLLECT
|
||||
var/light_on = 0
|
||||
var/mesons_active
|
||||
|
||||
var/datum/action/innate/minedrone/toggle_light/toggle_light_action
|
||||
var/datum/action/innate/minedrone/toggle_meson_vision/toggle_meson_vision_action
|
||||
var/datum/action/innate/minedrone/toggle_mode/toggle_mode_action
|
||||
var/datum/action/innate/minedrone/dump_ore/dump_ore_action
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/New()
|
||||
..()
|
||||
toggle_light_action = new()
|
||||
toggle_light_action.Grant(src)
|
||||
toggle_meson_vision_action = new()
|
||||
toggle_meson_vision_action.Grant(src)
|
||||
toggle_mode_action = new()
|
||||
toggle_mode_action.Grant(src)
|
||||
dump_ore_action = new()
|
||||
dump_ore_action.Grant(src)
|
||||
|
||||
SetCollectBehavior()
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/sentience_act()
|
||||
AIStatus = AI_OFF
|
||||
check_friendly_fire = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/weapon/weldingtool))
|
||||
var/obj/item/weapon/weldingtool/W = I
|
||||
if(W.welding && !stat)
|
||||
if(AIStatus != AI_OFF && AIStatus != AI_IDLE)
|
||||
to_chat(user, "<span class='info'>[src] is moving around too much to repair!</span>")
|
||||
return
|
||||
if(maxHealth == health)
|
||||
to_chat(user, "<span class='info'>[src] is at full integrity.</span>")
|
||||
else
|
||||
adjustBruteLoss(-10)
|
||||
to_chat(user, "<span class='info'>You repair some of the armor on [src].</span>")
|
||||
return
|
||||
if(istype(I, /obj/item/device/mining_scanner) || istype(I, /obj/item/device/t_scanner/adv_mining_scanner))
|
||||
to_chat(user, "<span class='info'>You instruct [src] to drop any collected ore.</span>")
|
||||
DropOre()
|
||||
return
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/death()
|
||||
..()
|
||||
visible_message("<span class='danger'>[src] is destroyed!</span>")
|
||||
new /obj/effect/decal/cleanable/blood/gibs/robot(src.loc)
|
||||
DropOre(0)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/attack_hand(mob/living/carbon/human/M)
|
||||
if(M.a_intent == I_HELP)
|
||||
toggle_mode()
|
||||
switch(mode)
|
||||
if(MINEDRONE_COLLECT)
|
||||
to_chat(M, "<span class='info'>[src] has been set to search and store loose ore.</span>")
|
||||
if(MINEDRONE_ATTACK)
|
||||
to_chat(M, "<span class='info'>[src] has been set to attack hostile wildlife.</span>")
|
||||
return
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/proc/SetCollectBehavior()
|
||||
mode = MINEDRONE_COLLECT
|
||||
idle_vision_range = 9
|
||||
search_objects = 2
|
||||
wander = 1
|
||||
ranged = 0
|
||||
minimum_distance = 1
|
||||
retreat_distance = null
|
||||
icon_state = "mining_drone"
|
||||
to_chat(src, "<span class='info'>You are set to collect mode. You can now collect loose ore.</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/proc/SetOffenseBehavior()
|
||||
mode = MINEDRONE_ATTACK
|
||||
idle_vision_range = 7
|
||||
search_objects = 0
|
||||
wander = 0
|
||||
ranged = 1
|
||||
retreat_distance = 1
|
||||
minimum_distance = 2
|
||||
icon_state = "mining_drone_offense"
|
||||
to_chat(src, "<span class='info'>You are set to attack mode. You can now attack from range.</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/AttackingTarget()
|
||||
if(istype(target, /obj/item/weapon/ore) && mode == MINEDRONE_COLLECT)
|
||||
CollectOre()
|
||||
return
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/proc/CollectOre()
|
||||
var/obj/item/weapon/ore/O
|
||||
for(O in src.loc)
|
||||
O.forceMove(src)
|
||||
for(var/dir in alldirs)
|
||||
var/turf/T = get_step(src,dir)
|
||||
for(O in T)
|
||||
O.forceMove(src)
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/proc/DropOre(message = 1)
|
||||
if(!contents.len)
|
||||
if(message)
|
||||
to_chat(src, "<span class='notice'>You attempt to dump your stored ore, but you have none.</span>")
|
||||
return
|
||||
if(message)
|
||||
to_chat(src, "<span class='notice'>You dump your stored ore.</span>")
|
||||
for(var/obj/item/weapon/ore/O in contents)
|
||||
contents -= O
|
||||
O.forceMove(loc)
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/adjustHealth(amount)
|
||||
if(mode != MINEDRONE_ATTACK && amount > 0)
|
||||
SetOffenseBehavior()
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/proc/toggle_mode()
|
||||
switch(mode)
|
||||
if(MINEDRONE_COLLECT)
|
||||
SetOffenseBehavior()
|
||||
if(MINEDRONE_ATTACK)
|
||||
SetCollectBehavior()
|
||||
else //This should never happen.
|
||||
mode = MINEDRONE_COLLECT
|
||||
SetCollectBehavior()
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/update_sight()
|
||||
if(!client)
|
||||
return
|
||||
if(stat == DEAD)
|
||||
grant_death_vision()
|
||||
return
|
||||
|
||||
if(mesons_active)
|
||||
sight |= SEE_TURFS
|
||||
see_invisible = SEE_INVISIBLE_MINIMUM
|
||||
else
|
||||
sight &= ~SEE_TURFS
|
||||
see_invisible = SEE_INVISIBLE_LIVING
|
||||
|
||||
see_in_dark = initial(see_in_dark)
|
||||
|
||||
if(client.eye != src)
|
||||
var/atom/A = client.eye
|
||||
if(A.update_remote_sight(src)) //returns 1 if we override all other sight updates.
|
||||
return
|
||||
|
||||
//Actions for sentient minebots
|
||||
|
||||
/datum/action/innate/minedrone
|
||||
check_flags = AB_CHECK_CONSCIOUS
|
||||
background_icon_state = "bg_default"
|
||||
|
||||
/datum/action/innate/minedrone/toggle_light
|
||||
name = "Toggle Light"
|
||||
button_icon_state = "mech_lights_off"
|
||||
|
||||
/datum/action/innate/minedrone/toggle_light/Activate()
|
||||
var/mob/living/simple_animal/hostile/mining_drone/user = owner
|
||||
|
||||
if(user.light_on)
|
||||
user.set_light(0)
|
||||
else
|
||||
user.set_light(6)
|
||||
user.light_on = !user.light_on
|
||||
to_chat(user, "<span class='notice'>You toggle your light [user.light_on ? "on" : "off"].</span>")
|
||||
|
||||
/datum/action/innate/minedrone/toggle_meson_vision
|
||||
name = "Toggle Meson Vision"
|
||||
button_icon_state = "meson"
|
||||
|
||||
/datum/action/innate/minedrone/toggle_meson_vision/Activate()
|
||||
var/mob/living/simple_animal/hostile/mining_drone/user = owner
|
||||
user.mesons_active = !user.mesons_active
|
||||
user.update_sight()
|
||||
|
||||
to_chat(user, "<span class='notice'>You toggle your meson vision [(user.mesons_active) ? "on" : "off"].</span>")
|
||||
|
||||
/datum/action/innate/minedrone/toggle_mode
|
||||
name = "Toggle Mode"
|
||||
button_icon_state = "mech_cycle_equip_off"
|
||||
|
||||
/datum/action/innate/minedrone/toggle_mode/Activate()
|
||||
var/mob/living/simple_animal/hostile/mining_drone/user = owner
|
||||
user.toggle_mode()
|
||||
|
||||
/datum/action/innate/minedrone/dump_ore
|
||||
name = "Dump Ore"
|
||||
button_icon_state = "mech_eject"
|
||||
|
||||
/datum/action/innate/minedrone/dump_ore/Activate()
|
||||
var/mob/living/simple_animal/hostile/mining_drone/user = owner
|
||||
user.DropOre()
|
||||
|
||||
|
||||
/**********************Minebot Upgrades**********************/
|
||||
|
||||
//Melee
|
||||
|
||||
/obj/item/device/mine_bot_upgrade
|
||||
name = "minebot melee upgrade"
|
||||
desc = "A minebot upgrade."
|
||||
icon_state = "door_electronics"
|
||||
icon = 'icons/obj/doors/door_assembly.dmi'
|
||||
|
||||
/obj/item/device/mine_bot_upgrade/afterattack(mob/living/simple_animal/hostile/mining_drone/M, mob/user, proximity)
|
||||
if(!istype(M) || !proximity)
|
||||
return
|
||||
upgrade_bot(M, user)
|
||||
|
||||
/obj/item/device/mine_bot_upgrade/proc/upgrade_bot(mob/living/simple_animal/hostile/mining_drone/M, mob/user)
|
||||
if(M.melee_damage_upper != initial(M.melee_damage_upper))
|
||||
to_chat(user, "[M] already has a combat upgrade installed!")
|
||||
return
|
||||
M.melee_damage_lower = 22
|
||||
M.melee_damage_upper = 22
|
||||
to_chat(user, "You upgrade [M]'s combat module.")
|
||||
qdel(src)
|
||||
|
||||
//Health
|
||||
|
||||
/obj/item/device/mine_bot_upgrade/health
|
||||
name = "minebot chassis upgrade"
|
||||
|
||||
/obj/item/device/mine_bot_upgrade/health/upgrade_bot(mob/living/simple_animal/hostile/mining_drone/M, mob/user)
|
||||
if(M.maxHealth != initial(M.maxHealth))
|
||||
to_chat(user, "[M] already has a reinforced chassis!")
|
||||
return
|
||||
M.maxHealth = 170
|
||||
to_chat(user, "You reinforce [M]'s chassis.")
|
||||
qdel(src)
|
||||
|
||||
|
||||
//Cooldown
|
||||
|
||||
/obj/item/device/mine_bot_upgrade/cooldown
|
||||
name = "minebot cooldown upgrade"
|
||||
|
||||
/obj/item/device/mine_bot_upgrade/cooldown/upgrade_bot(mob/living/simple_animal/hostile/mining_drone/M, mob/user)
|
||||
if(M.ranged_cooldown_time != initial(M.ranged_cooldown_time))
|
||||
to_chat(user, "[M] already has a decreased weapon cooldown!")
|
||||
return
|
||||
M.ranged_cooldown_time = 10
|
||||
to_chat(user, "You upgrade [M]'s ranged weaponry, reducing its cooldown.")
|
||||
qdel(src)
|
||||
|
||||
|
||||
//AI
|
||||
/obj/item/slimepotion/sentience/mining
|
||||
name = "minebot AI upgrade"
|
||||
desc = "Can be used to grant sentience to minebots."
|
||||
icon_state = "door_electronics"
|
||||
icon = 'icons/obj/doors/door_assembly.dmi'
|
||||
sentience_type = SENTIENCE_MINEBOT
|
||||
origin_tech = "programming=6"
|
||||
|
||||
#undef MINEDRONE_COLLECT
|
||||
#undef MINEDRONE_ATTACK
|
||||
|
||||
/**********************Mining drone kit**********************/
|
||||
|
||||
/obj/item/weapon/storage/box/drone_kit
|
||||
|
||||
@@ -200,7 +200,6 @@
|
||||
/obj/structure/closet/crate/miningcar
|
||||
desc = "A mining car. This one doesn't work on rails, but has to be dragged."
|
||||
name = "mining car (not for rails)"
|
||||
icon = 'icons/obj/storage.dmi'
|
||||
icon_state = "miningcar"
|
||||
density = 1
|
||||
icon_opened = "miningcaropen"
|
||||
|
||||
@@ -0,0 +1,303 @@
|
||||
/**********************Mining drone**********************/
|
||||
#define MINEDRONE_COLLECT 1
|
||||
#define MINEDRONE_ATTACK 2
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone
|
||||
name = "nanotrasen minebot"
|
||||
desc = "The instructions printed on the side read: This is a small robot used to support miners, can be set to search and collect loose ore, or to help fend off wildlife. A mining scanner can instruct it to drop loose ore. Field repairs can be done with a welder."
|
||||
icon = 'icons/obj/aibots.dmi'
|
||||
icon_state = "mining_drone"
|
||||
icon_living = "mining_drone"
|
||||
status_flags = CANSTUN|CANWEAKEN|CANPUSH
|
||||
mouse_opacity = 1
|
||||
faction = list("neutral")
|
||||
a_intent = I_HARM
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
minbodytemp = 0
|
||||
wander = 0
|
||||
idle_vision_range = 5
|
||||
move_to_delay = 10
|
||||
retreat_distance = 1
|
||||
minimum_distance = 2
|
||||
health = 125
|
||||
maxHealth = 125
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 15
|
||||
environment_smash = 0
|
||||
check_friendly_fire = 1
|
||||
stop_automated_movement_when_pulled = 1
|
||||
attacktext = "drills"
|
||||
attack_sound = 'sound/weapons/circsawhit.ogg'
|
||||
ranged = 1
|
||||
sentience_type = SENTIENCE_MINEBOT
|
||||
ranged_message = "shoots"
|
||||
ranged_cooldown_time = 30
|
||||
projectiletype = /obj/item/projectile/kinetic
|
||||
projectilesound = 'sound/weapons/Gunshot4.ogg'
|
||||
speak_emote = list("states")
|
||||
wanted_objects = list(/obj/item/weapon/ore/diamond, /obj/item/weapon/ore/gold, /obj/item/weapon/ore/silver,
|
||||
/obj/item/weapon/ore/plasma, /obj/item/weapon/ore/uranium, /obj/item/weapon/ore/iron,
|
||||
/obj/item/weapon/ore/bananium, /obj/item/weapon/ore/tranquillite, /obj/item/weapon/ore/glass)
|
||||
healable = 0
|
||||
var/mode = MINEDRONE_COLLECT
|
||||
var/light_on = 0
|
||||
var/mesons_active
|
||||
|
||||
var/datum/action/innate/minedrone/toggle_light/toggle_light_action
|
||||
var/datum/action/innate/minedrone/toggle_meson_vision/toggle_meson_vision_action
|
||||
var/datum/action/innate/minedrone/toggle_mode/toggle_mode_action
|
||||
var/datum/action/innate/minedrone/dump_ore/dump_ore_action
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/New()
|
||||
..()
|
||||
toggle_light_action = new()
|
||||
toggle_light_action.Grant(src)
|
||||
toggle_meson_vision_action = new()
|
||||
toggle_meson_vision_action.Grant(src)
|
||||
toggle_mode_action = new()
|
||||
toggle_mode_action.Grant(src)
|
||||
dump_ore_action = new()
|
||||
dump_ore_action.Grant(src)
|
||||
|
||||
SetCollectBehavior()
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/sentience_act()
|
||||
AIStatus = AI_OFF
|
||||
check_friendly_fire = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/weapon/weldingtool))
|
||||
var/obj/item/weapon/weldingtool/W = I
|
||||
if(W.welding && !stat)
|
||||
if(AIStatus != AI_OFF && AIStatus != AI_IDLE)
|
||||
to_chat(user, "<span class='info'>[src] is moving around too much to repair!</span>")
|
||||
return
|
||||
if(maxHealth == health)
|
||||
to_chat(user, "<span class='info'>[src] is at full integrity.</span>")
|
||||
else
|
||||
adjustBruteLoss(-10)
|
||||
to_chat(user, "<span class='info'>You repair some of the armor on [src].</span>")
|
||||
return
|
||||
if(istype(I, /obj/item/device/mining_scanner) || istype(I, /obj/item/device/t_scanner/adv_mining_scanner))
|
||||
to_chat(user, "<span class='info'>You instruct [src] to drop any collected ore.</span>")
|
||||
DropOre()
|
||||
return
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/death()
|
||||
..()
|
||||
visible_message("<span class='danger'>[src] is destroyed!</span>")
|
||||
new /obj/effect/decal/cleanable/blood/gibs/robot(src.loc)
|
||||
DropOre(0)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/attack_hand(mob/living/carbon/human/M)
|
||||
if(M.a_intent == I_HELP)
|
||||
toggle_mode()
|
||||
switch(mode)
|
||||
if(MINEDRONE_COLLECT)
|
||||
to_chat(M, "<span class='info'>[src] has been set to search and store loose ore.</span>")
|
||||
if(MINEDRONE_ATTACK)
|
||||
to_chat(M, "<span class='info'>[src] has been set to attack hostile wildlife.</span>")
|
||||
return
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/proc/SetCollectBehavior()
|
||||
mode = MINEDRONE_COLLECT
|
||||
idle_vision_range = 9
|
||||
search_objects = 2
|
||||
wander = 1
|
||||
ranged = 0
|
||||
minimum_distance = 1
|
||||
retreat_distance = null
|
||||
icon_state = "mining_drone"
|
||||
to_chat(src, "<span class='info'>You are set to collect mode. You can now collect loose ore.</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/proc/SetOffenseBehavior()
|
||||
mode = MINEDRONE_ATTACK
|
||||
idle_vision_range = 7
|
||||
search_objects = 0
|
||||
wander = 0
|
||||
ranged = 1
|
||||
retreat_distance = 1
|
||||
minimum_distance = 2
|
||||
icon_state = "mining_drone_offense"
|
||||
to_chat(src, "<span class='info'>You are set to attack mode. You can now attack from range.</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/AttackingTarget()
|
||||
if(istype(target, /obj/item/weapon/ore) && mode == MINEDRONE_COLLECT)
|
||||
CollectOre()
|
||||
return
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/proc/CollectOre()
|
||||
var/obj/item/weapon/ore/O
|
||||
for(O in src.loc)
|
||||
O.forceMove(src)
|
||||
for(var/dir in alldirs)
|
||||
var/turf/T = get_step(src,dir)
|
||||
for(O in T)
|
||||
O.forceMove(src)
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/proc/DropOre(message = 1)
|
||||
if(!contents.len)
|
||||
if(message)
|
||||
to_chat(src, "<span class='notice'>You attempt to dump your stored ore, but you have none.</span>")
|
||||
return
|
||||
if(message)
|
||||
to_chat(src, "<span class='notice'>You dump your stored ore.</span>")
|
||||
for(var/obj/item/weapon/ore/O in contents)
|
||||
contents -= O
|
||||
O.forceMove(loc)
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/adjustHealth(amount)
|
||||
if(mode != MINEDRONE_ATTACK && amount > 0)
|
||||
SetOffenseBehavior()
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/proc/toggle_mode()
|
||||
switch(mode)
|
||||
if(MINEDRONE_COLLECT)
|
||||
SetOffenseBehavior()
|
||||
if(MINEDRONE_ATTACK)
|
||||
SetCollectBehavior()
|
||||
else //This should never happen.
|
||||
mode = MINEDRONE_COLLECT
|
||||
SetCollectBehavior()
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/mining_drone/update_sight()
|
||||
if(!client)
|
||||
return
|
||||
if(stat == DEAD)
|
||||
grant_death_vision()
|
||||
return
|
||||
|
||||
if(mesons_active)
|
||||
sight |= SEE_TURFS
|
||||
see_invisible = SEE_INVISIBLE_MINIMUM
|
||||
else
|
||||
sight &= ~SEE_TURFS
|
||||
see_invisible = SEE_INVISIBLE_LIVING
|
||||
|
||||
see_in_dark = initial(see_in_dark)
|
||||
|
||||
if(client.eye != src)
|
||||
var/atom/A = client.eye
|
||||
if(A.update_remote_sight(src)) //returns 1 if we override all other sight updates.
|
||||
return
|
||||
|
||||
//Actions for sentient minebots
|
||||
|
||||
/datum/action/innate/minedrone
|
||||
check_flags = AB_CHECK_CONSCIOUS
|
||||
background_icon_state = "bg_default"
|
||||
|
||||
/datum/action/innate/minedrone/toggle_light
|
||||
name = "Toggle Light"
|
||||
button_icon_state = "mech_lights_off"
|
||||
|
||||
/datum/action/innate/minedrone/toggle_light/Activate()
|
||||
var/mob/living/simple_animal/hostile/mining_drone/user = owner
|
||||
|
||||
if(user.light_on)
|
||||
user.set_light(0)
|
||||
else
|
||||
user.set_light(6)
|
||||
user.light_on = !user.light_on
|
||||
to_chat(user, "<span class='notice'>You toggle your light [user.light_on ? "on" : "off"].</span>")
|
||||
|
||||
/datum/action/innate/minedrone/toggle_meson_vision
|
||||
name = "Toggle Meson Vision"
|
||||
button_icon_state = "meson"
|
||||
|
||||
/datum/action/innate/minedrone/toggle_meson_vision/Activate()
|
||||
var/mob/living/simple_animal/hostile/mining_drone/user = owner
|
||||
user.mesons_active = !user.mesons_active
|
||||
user.update_sight()
|
||||
|
||||
to_chat(user, "<span class='notice'>You toggle your meson vision [(user.mesons_active) ? "on" : "off"].</span>")
|
||||
|
||||
/datum/action/innate/minedrone/toggle_mode
|
||||
name = "Toggle Mode"
|
||||
button_icon_state = "mech_cycle_equip_off"
|
||||
|
||||
/datum/action/innate/minedrone/toggle_mode/Activate()
|
||||
var/mob/living/simple_animal/hostile/mining_drone/user = owner
|
||||
user.toggle_mode()
|
||||
|
||||
/datum/action/innate/minedrone/dump_ore
|
||||
name = "Dump Ore"
|
||||
button_icon_state = "mech_eject"
|
||||
|
||||
/datum/action/innate/minedrone/dump_ore/Activate()
|
||||
var/mob/living/simple_animal/hostile/mining_drone/user = owner
|
||||
user.DropOre()
|
||||
|
||||
|
||||
/**********************Minebot Upgrades**********************/
|
||||
|
||||
//Melee
|
||||
|
||||
/obj/item/device/mine_bot_upgrade
|
||||
name = "minebot melee upgrade"
|
||||
desc = "A minebot upgrade."
|
||||
icon_state = "door_electronics"
|
||||
icon = 'icons/obj/doors/door_assembly.dmi'
|
||||
|
||||
/obj/item/device/mine_bot_upgrade/afterattack(mob/living/simple_animal/hostile/mining_drone/M, mob/user, proximity)
|
||||
if(!istype(M) || !proximity)
|
||||
return
|
||||
upgrade_bot(M, user)
|
||||
|
||||
/obj/item/device/mine_bot_upgrade/proc/upgrade_bot(mob/living/simple_animal/hostile/mining_drone/M, mob/user)
|
||||
if(M.melee_damage_upper != initial(M.melee_damage_upper))
|
||||
to_chat(user, "[M] already has a combat upgrade installed!")
|
||||
return
|
||||
M.melee_damage_lower = 22
|
||||
M.melee_damage_upper = 22
|
||||
to_chat(user, "You upgrade [M]'s combat module.")
|
||||
qdel(src)
|
||||
|
||||
//Health
|
||||
|
||||
/obj/item/device/mine_bot_upgrade/health
|
||||
name = "minebot chassis upgrade"
|
||||
|
||||
/obj/item/device/mine_bot_upgrade/health/upgrade_bot(mob/living/simple_animal/hostile/mining_drone/M, mob/user)
|
||||
if(M.maxHealth != initial(M.maxHealth))
|
||||
to_chat(user, "[M] already has a reinforced chassis!")
|
||||
return
|
||||
M.maxHealth = 170
|
||||
to_chat(user, "You reinforce [M]'s chassis.")
|
||||
qdel(src)
|
||||
|
||||
|
||||
//Cooldown
|
||||
|
||||
/obj/item/device/mine_bot_upgrade/cooldown
|
||||
name = "minebot cooldown upgrade"
|
||||
|
||||
/obj/item/device/mine_bot_upgrade/cooldown/upgrade_bot(mob/living/simple_animal/hostile/mining_drone/M, mob/user)
|
||||
if(M.ranged_cooldown_time != initial(M.ranged_cooldown_time))
|
||||
to_chat(user, "[M] already has a decreased weapon cooldown!")
|
||||
return
|
||||
M.ranged_cooldown_time = 10
|
||||
to_chat(user, "You upgrade [M]'s ranged weaponry, reducing its cooldown.")
|
||||
qdel(src)
|
||||
|
||||
|
||||
//AI
|
||||
/obj/item/slimepotion/sentience/mining
|
||||
name = "minebot AI upgrade"
|
||||
desc = "Can be used to grant sentience to minebots."
|
||||
icon_state = "door_electronics"
|
||||
icon = 'icons/obj/doors/door_assembly.dmi'
|
||||
sentience_type = SENTIENCE_MINEBOT
|
||||
origin_tech = "programming=6"
|
||||
|
||||
#undef MINEDRONE_COLLECT
|
||||
#undef MINEDRONE_ATTACK
|
||||
@@ -22,7 +22,6 @@ var/list/image/ghost_darkness_images = list() //this is a list of images for thi
|
||||
//Note that this is not a reliable way to determine if admins started as observers, since they change mobs a lot.
|
||||
universal_speak = 1
|
||||
var/atom/movable/following = null
|
||||
var/anonsay = 0
|
||||
var/image/ghostimage = null //this mobs ghost image, for deleting and stuff
|
||||
var/ghostvision = 1 //is the ghost able to see things humans can't?
|
||||
var/seedarkness = 1
|
||||
@@ -596,15 +595,12 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
//END TELEPORT HREF CODE
|
||||
|
||||
/mob/dead/observer/verb/toggle_anonsay()
|
||||
set name = "Toggle Anonymous Dead-chat"
|
||||
set category = "Ghost"
|
||||
set name = "Toggle Anonymous Chat"
|
||||
set desc = "Toggles showing your key in dead chat."
|
||||
|
||||
src.anonsay = !src.anonsay
|
||||
if(anonsay)
|
||||
to_chat(src, "<span class='info'>Your key won't be shown when you speak in dead chat.</span>")
|
||||
else
|
||||
to_chat(src, "<span class='info'>Your key will be publicly visible again.</span>")
|
||||
client.prefs.ghost_anonsay = !client.prefs.ghost_anonsay
|
||||
to_chat(src, "As a ghost, your key will [(client.prefs.ghost_anonsay) ? "no longer" : "now"] be shown when you speak in dead chat.</span>")
|
||||
client.prefs.save_preferences(src)
|
||||
|
||||
/mob/dead/observer/verb/toggle_ghostsee()
|
||||
set name = "Toggle Ghost Vision"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/obj/item/device/mmi/posibrain
|
||||
name = "positronic brain"
|
||||
desc = "A cube of shining metal, four inches to a side and covered in shallow grooves. The speaker switch is set to 'on'."
|
||||
desc = "A cube of shining metal, four inches to a side and covered in shallow grooves."
|
||||
icon = 'icons/obj/assemblies.dmi'
|
||||
icon_state = "posibrain"
|
||||
w_class = 3
|
||||
@@ -15,11 +15,14 @@
|
||||
var/silenced = 0 //if set to 1, they can't talk.
|
||||
var/next_ping_at = 0
|
||||
|
||||
/obj/item/device/mmi/posibrain/examine(mob/user)
|
||||
if(..(user, 1))
|
||||
to_chat(user, "Its speaker is turned [silenced ? "off" : "on"].")
|
||||
|
||||
/obj/item/device/mmi/posibrain/attack_self(mob/user as mob)
|
||||
/obj/item/device/mmi/posibrain/attack_self(mob/user)
|
||||
if(brainmob && !brainmob.key && searching == 0)
|
||||
//Start the process of searching for a new user.
|
||||
to_chat(user, "\blue You carefully locate the manual activation switch and start the positronic brain's boot process.")
|
||||
to_chat(user, "<span class='notice'>You carefully locate the manual activation switch and start the positronic brain's boot process.</span>")
|
||||
icon_state = "posibrain-searching"
|
||||
ghost_volunteers.Cut()
|
||||
src.searching = 1
|
||||
@@ -31,18 +34,10 @@
|
||||
transfer_personality(O)
|
||||
reset_search()
|
||||
else
|
||||
if(silenced)
|
||||
silenced = 0
|
||||
to_chat(user, "<span class='notice'>You toggle the speaker to 'on', on the [src].</span>")
|
||||
desc = "A cube of shining metal, four inches to a side and covered in shallow grooves. The speaker switch is set to 'on'."
|
||||
if(brainmob && brainmob.key)
|
||||
to_chat(brainmob, "<span class='warning'>Your internal speaker has been toggled to 'on'.</span>")
|
||||
else
|
||||
silenced = 1
|
||||
to_chat(user, "<span class='notice'>You toggle the speaker to 'off', on the [src].</span>")
|
||||
desc = "A cube of shining metal, four inches to a side and covered in shallow grooves. The speaker switch is set to 'off'."
|
||||
if(brainmob && brainmob.key)
|
||||
to_chat(brainmob, "<span class='warning'>Your internal speaker has been toggled to 'off'.</span>")
|
||||
silenced = !silenced
|
||||
to_chat(user, "<span class='notice'>You toggle the speaker [silenced ? "off" : "on"].</span>")
|
||||
if(brainmob && brainmob.key)
|
||||
to_chat(brainmob, "<span class='warning'>Your internal speaker has been toggled [silenced ? "off" : "on"].</span>")
|
||||
|
||||
/obj/item/device/mmi/posibrain/proc/request_player()
|
||||
for(var/mob/dead/observer/O in player_list)
|
||||
|
||||
@@ -1,23 +1,33 @@
|
||||
//TODO: Convert this over for languages.
|
||||
/mob/living/carbon/brain/say(var/message, var/datum/language/speaking = null)
|
||||
if(silent)
|
||||
if(!can_speak(warning = TRUE))
|
||||
return
|
||||
|
||||
if(prob(emp_damage * 4))
|
||||
if(prob(10)) //10% chance to drop the message entirely
|
||||
return
|
||||
else
|
||||
message = Gibberish(message, (emp_damage*6))//scrambles the message, gets worse when emp_damage is higher
|
||||
|
||||
..(message)
|
||||
|
||||
/mob/living/carbon/brain/whisper(message as text)
|
||||
if(!can_speak(warning = TRUE))
|
||||
return
|
||||
|
||||
if(!(container && istype(container, /obj/item/device/mmi)))
|
||||
return //No MMI, can't speak, bucko./N
|
||||
else
|
||||
if(container && istype(container, /obj/item/device/mmi/posibrain))
|
||||
var/obj/item/device/mmi/posibrain/P = container
|
||||
if(P && P.silenced)
|
||||
to_chat(usr, "<span class='warning'>You cannot speak, as your internal speaker has been toggled to 'off'.</span>")
|
||||
return
|
||||
if(prob(emp_damage*4))
|
||||
if(prob(10))//10% chane to drop the message entirely
|
||||
return
|
||||
else
|
||||
message = Gibberish(message, (emp_damage*6))//scrambles the message, gets worse when emp_damage is higher
|
||||
..()
|
||||
|
||||
/mob/living/carbon/brain/can_speak(var/warning = FALSE)
|
||||
. = ..()
|
||||
|
||||
..(message)
|
||||
if(!istype(container, /obj/item/device/mmi))
|
||||
. = FALSE
|
||||
else if(istype(container, /obj/item/device/mmi/posibrain))
|
||||
var/obj/item/device/mmi/posibrain/P = container
|
||||
if(P && P.silenced)
|
||||
if(warning)
|
||||
to_chat(usr, "<span class='warning'>You cannot speak, as your internal speaker is turned off.</span>")
|
||||
. = FALSE
|
||||
|
||||
/mob/living/carbon/brain/handle_message_mode(var/message_mode, var/message, var/verb, var/speaking, var/used_radios, var/alt_name)
|
||||
switch(message_mode)
|
||||
|
||||
@@ -174,7 +174,7 @@
|
||||
"<span class='userdanger'>The [source] arc flashes and electrocutes you!</span>", \
|
||||
"<span class='italics'>You hear a lightning-like crack!</span>" \
|
||||
)
|
||||
playsound(loc, "sound/effects/eleczap.ogg", 50, 1, -1)
|
||||
playsound(loc, 'sound/effects/eleczap.ogg', 50, 1, -1)
|
||||
explosion(src.loc,-1,0,2,2)
|
||||
if(override)
|
||||
return override
|
||||
|
||||
@@ -57,6 +57,10 @@
|
||||
on_CD = handle_emote_CD(50) //longer cooldown
|
||||
if("fart", "farts", "flip", "flips", "snap", "snaps")
|
||||
on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm
|
||||
if("cough", "coughs")
|
||||
on_CD = handle_emote_CD()
|
||||
if("sneeze", "sneezes")
|
||||
on_CD = handle_emote_CD()
|
||||
//Everything else, including typos of the above emotes
|
||||
else
|
||||
on_CD = 0 //If it doesn't induce the cooldown, we won't check for the cooldown
|
||||
@@ -399,6 +403,12 @@
|
||||
if(!muzzled)
|
||||
message = "<B>[src]</B> coughs!"
|
||||
m_type = 2
|
||||
if(gender == FEMALE)
|
||||
if(species.female_cough_sounds)
|
||||
playsound(src, pick(species.female_cough_sounds), 120)
|
||||
else
|
||||
if(species.male_cough_sounds)
|
||||
playsound(src, pick(species.male_cough_sounds), 120)
|
||||
else
|
||||
message = "<B>[src]</B> makes a strong noise."
|
||||
m_type = 2
|
||||
@@ -654,6 +664,10 @@
|
||||
else
|
||||
if(!muzzled)
|
||||
message = "<B>[src]</B> sneezes."
|
||||
if(gender == FEMALE)
|
||||
playsound(src, species.female_sneeze_sound, 70)
|
||||
else
|
||||
playsound(src, species.male_sneeze_sound, 70)
|
||||
m_type = 2
|
||||
else
|
||||
message = "<B>[src]</B> makes a strange noise."
|
||||
|
||||
@@ -1246,7 +1246,6 @@
|
||||
return 0
|
||||
return 1
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/get_visible_gender()
|
||||
if(wear_suit && wear_suit.flags_inv & HIDEJUMPSUIT && ((head && head.flags_inv & HIDEMASK) || wear_mask))
|
||||
return NEUTER
|
||||
@@ -1515,6 +1514,8 @@
|
||||
if(oldspecies.default_genes.len)
|
||||
oldspecies.handle_dna(src,1) // Remove any genes that belong to the old species
|
||||
|
||||
tail = species.tail
|
||||
|
||||
if(vessel)
|
||||
vessel = null
|
||||
make_blood()
|
||||
@@ -2051,6 +2052,10 @@
|
||||
|
||||
return .
|
||||
|
||||
/mob/living/carbon/human/proc/change_icobase(var/new_icobase, var/new_deform, var/owner_sensitive)
|
||||
for(var/obj/item/organ/external/O in organs)
|
||||
O.change_organ_icobase(new_icobase, new_deform, owner_sensitive) //Change the icobase/deform of all our organs. If owner_sensitive is set, that means the proc won't mess with frankenstein limbs.
|
||||
|
||||
/mob/living/carbon/human/serialize()
|
||||
// Currently: Limbs/organs only
|
||||
var/list/data = ..()
|
||||
|
||||
@@ -57,7 +57,7 @@ emp_act
|
||||
organ.add_autopsy_data(P.name, P.damage) // Add the bullet's name to the autopsy data
|
||||
|
||||
return (..(P , def_zone))
|
||||
|
||||
|
||||
/mob/living/carbon/human/check_projectile_dismemberment(obj/item/projectile/P, def_zone)
|
||||
var/obj/item/organ/external/affecting = get_organ(check_zone(def_zone))
|
||||
if(affecting && !affecting.cannot_amputate && affecting.get_damage() >= (affecting.max_damage - P.dismemberment))
|
||||
@@ -67,7 +67,7 @@ emp_act
|
||||
damtype = DROPLIMB_BLUNT
|
||||
if(BURN)
|
||||
damtype = DROPLIMB_BURN
|
||||
|
||||
|
||||
affecting.droplimb(FALSE, damtype)
|
||||
|
||||
/mob/living/carbon/human/getarmor(var/def_zone, var/type)
|
||||
@@ -228,9 +228,9 @@ emp_act
|
||||
|
||||
if(! I.discrete)
|
||||
if(I.attack_verb.len)
|
||||
visible_message("<span class='danger'>[src] has been [pick(I.attack_verb)] in the [hit_area] with [I.name] by [user]!</span>")
|
||||
visible_message("<span class='combat danger'>[src] has been [pick(I.attack_verb)] in the [hit_area] with [I.name] by [user]!</span>")
|
||||
else
|
||||
visible_message("<span class='danger'>[src] has been attacked in the [hit_area] with [I.name] by [user]!</span>")
|
||||
visible_message("<span class='combat danger'>[src] has been attacked in the [hit_area] with [I.name] by [user]!</span>")
|
||||
|
||||
var/armor = run_armor_check(affecting, "melee", "Your armor has protected your [hit_area].", "Your armor has softened hit to your [hit_area].", armour_penetration = I.armour_penetration)
|
||||
var/weapon_sharp = is_sharp(I)
|
||||
@@ -266,8 +266,8 @@ emp_act
|
||||
if("head")//Harder to score a stun but if you do it lasts a bit longer
|
||||
if(stat == CONSCIOUS && armor < 50)
|
||||
if(prob(I.force))
|
||||
visible_message("<span class='danger'>[src] has been knocked down!</span>", \
|
||||
"<span class='userdanger'>[src] has been knocked down!</span>")
|
||||
visible_message("<span class='combat danger'>[src] has been knocked down!</span>", \
|
||||
"<span class='combat userdanger'>[src] has been knocked down!</span>")
|
||||
apply_effect(5, WEAKEN, armor)
|
||||
AdjustConfused(15)
|
||||
if(prob(I.force + ((100 - health)/2)) && src != user && I.damtype == BRUTE)
|
||||
@@ -286,8 +286,8 @@ emp_act
|
||||
|
||||
if("upper body")//Easier to score a stun but lasts less time
|
||||
if(stat == CONSCIOUS && I.force && prob(I.force + 10))
|
||||
visible_message("<span class='danger'>[src] has been knocked down!</span>", \
|
||||
"<span class='userdanger'>[src] has been knocked down!</span>")
|
||||
visible_message("<span class='combat danger'>[src] has been knocked down!</span>", \
|
||||
"<span class='combat userdanger'>[src] has been knocked down!</span>")
|
||||
apply_effect(5, WEAKEN, armor)
|
||||
|
||||
if(bloody)
|
||||
|
||||
@@ -72,3 +72,4 @@ var/global/default_martial_art = new/datum/martial_art
|
||||
var/fire_sprite = "Standing"
|
||||
|
||||
var/datum/body_accessory/body_accessory = null
|
||||
var/tail // Name of tail image in species effects icon file.
|
||||
|
||||
@@ -105,6 +105,7 @@
|
||||
/mob/living/carbon/human/handle_speech_problems(var/message, var/verb)
|
||||
var/list/returns[3]
|
||||
var/speech_problem_flag = 0
|
||||
var/span = mind.speech_span
|
||||
|
||||
if(silent || (disabilities & MUTE))
|
||||
message = ""
|
||||
@@ -143,8 +144,10 @@
|
||||
verb = "yells loudly"
|
||||
|
||||
if((COMIC in mutations) || (locate(/obj/item/organ/internal/cyberimp/brain/clown_voice) in internal_organs))
|
||||
message = "<span class='sans'>[message]</span>"
|
||||
span = "sans"
|
||||
|
||||
if(span)
|
||||
message = "<span class='[span]'>[message]</span>"
|
||||
returns[1] = message
|
||||
returns[2] = verb
|
||||
returns[3] = speech_problem_flag
|
||||
|
||||
@@ -128,6 +128,10 @@
|
||||
var/scream_verb = "screams"
|
||||
var/male_scream_sound = 'sound/goonstation/voice/male_scream.ogg'
|
||||
var/female_scream_sound = 'sound/goonstation/voice/female_scream.ogg'
|
||||
var/male_cough_sounds = list('sound/effects/mob_effects/m_cougha.ogg','sound/effects/mob_effects/m_coughb.ogg', 'sound/effects/mob_effects/m_coughc.ogg')
|
||||
var/female_cough_sounds = list('sound/effects/mob_effects/f_cougha.ogg','sound/effects/mob_effects/f_coughb.ogg')
|
||||
var/male_sneeze_sound = 'sound/effects/mob_effects/sneeze.ogg'
|
||||
var/female_sneeze_sound = 'sound/effects/mob_effects/f_sneeze.ogg'
|
||||
|
||||
//Default hair/headacc style vars.
|
||||
var/default_hair //Default hair style for newly created humans unless otherwise set.
|
||||
@@ -676,4 +680,4 @@ It'll return null if the organ doesn't correspond, so include null checks when u
|
||||
H.see_invisible = SEE_INVISIBLE_MINIMUM
|
||||
|
||||
if(H.see_override) //Override all
|
||||
H.see_invisible = H.see_override
|
||||
H.see_invisible = H.see_override
|
||||
|
||||
@@ -360,34 +360,35 @@
|
||||
//H.verbs += /mob/living/carbon/human/proc/leap
|
||||
..()
|
||||
|
||||
/datum/species/vox/updatespeciescolor(var/mob/living/carbon/human/H) //Handling species-specific skin-tones for the Vox race.
|
||||
/datum/species/vox/updatespeciescolor(var/mob/living/carbon/human/H, var/owner_sensitive = 1) //Handling species-specific skin-tones for the Vox race.
|
||||
if(H.species.name == "Vox") //Making sure we don't break Armalis.
|
||||
var/new_icobase = 'icons/mob/human_races/vox/r_vox.dmi' //Default Green Vox.
|
||||
var/new_deform = 'icons/mob/human_races/vox/r_def_vox.dmi' //Default Green Vox.
|
||||
switch(H.s_tone)
|
||||
if(6) //Azure Vox.
|
||||
icobase = 'icons/mob/human_races/vox/r_voxazu.dmi'
|
||||
deform = 'icons/mob/human_races/vox/r_def_voxazu.dmi'
|
||||
tail = "voxtail_azu"
|
||||
new_icobase = 'icons/mob/human_races/vox/r_voxazu.dmi'
|
||||
new_deform = 'icons/mob/human_races/vox/r_def_voxazu.dmi'
|
||||
H.tail = "voxtail_azu"
|
||||
if(5) //Emerald Vox.
|
||||
icobase = 'icons/mob/human_races/vox/r_voxemrl.dmi'
|
||||
deform = 'icons/mob/human_races/vox/r_def_voxemrl.dmi'
|
||||
tail = "voxtail_emrl"
|
||||
new_icobase = 'icons/mob/human_races/vox/r_voxemrl.dmi'
|
||||
new_deform = 'icons/mob/human_races/vox/r_def_voxemrl.dmi'
|
||||
H.tail = "voxtail_emrl"
|
||||
if(4) //Grey Vox.
|
||||
icobase = 'icons/mob/human_races/vox/r_voxgry.dmi'
|
||||
deform = 'icons/mob/human_races/vox/r_def_voxgry.dmi'
|
||||
tail = "voxtail_gry"
|
||||
new_icobase = 'icons/mob/human_races/vox/r_voxgry.dmi'
|
||||
new_deform = 'icons/mob/human_races/vox/r_def_voxgry.dmi'
|
||||
H.tail = "voxtail_gry"
|
||||
if(3) //Brown Vox.
|
||||
icobase = 'icons/mob/human_races/vox/r_voxbrn.dmi'
|
||||
deform = 'icons/mob/human_races/vox/r_def_voxbrn.dmi'
|
||||
tail = "voxtail_brn"
|
||||
new_icobase = 'icons/mob/human_races/vox/r_voxbrn.dmi'
|
||||
new_deform = 'icons/mob/human_races/vox/r_def_voxbrn.dmi'
|
||||
H.tail = "voxtail_brn"
|
||||
if(2) //Dark Green Vox.
|
||||
icobase = 'icons/mob/human_races/vox/r_voxdgrn.dmi'
|
||||
deform = 'icons/mob/human_races/vox/r_def_voxdgrn.dmi'
|
||||
tail = "voxtail_dgrn"
|
||||
new_icobase = 'icons/mob/human_races/vox/r_voxdgrn.dmi'
|
||||
new_deform = 'icons/mob/human_races/vox/r_def_voxdgrn.dmi'
|
||||
H.tail = "voxtail_dgrn"
|
||||
else //Default Green Vox.
|
||||
icobase = 'icons/mob/human_races/vox/r_vox.dmi'
|
||||
deform = 'icons/mob/human_races/vox/r_def_vox.dmi'
|
||||
tail = "voxtail" //Ensures they get an appropriately coloured tail depending on the skin-tone.
|
||||
H.tail = "voxtail" //Ensures they get an appropriately coloured tail depending on the skin-tone.
|
||||
|
||||
H.change_icobase(new_icobase, new_deform, owner_sensitive) //Update the icobase/deform of all our organs, but make sure we don't mess with frankenstein limbs in doing so.
|
||||
H.update_dna()
|
||||
|
||||
/datum/species/vox/armalis/handle_post_spawn(var/mob/living/carbon/human/H)
|
||||
@@ -509,6 +510,9 @@
|
||||
oxy_mod = 0
|
||||
brain_mod = 2.5
|
||||
|
||||
male_cough_sounds = list('sound/effects/slime_squish.ogg')
|
||||
female_cough_sounds = list('sound/effects/slime_squish.ogg')
|
||||
|
||||
flags = IS_WHITELISTED | NO_BREATHE | HAS_LIPS | NO_INTORGANS | NO_SCAN
|
||||
clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS
|
||||
bodyflags = HAS_SKIN_COLOR | NO_EYES
|
||||
@@ -720,6 +724,11 @@
|
||||
genemutcheck(C,REMOTETALKBLOCK,null,MUTCHK_FORCED)
|
||||
..()
|
||||
|
||||
/datum/species/grey/equip(var/mob/living/carbon/human/H)
|
||||
var/speech_pref = H.client.prefs.speciesprefs
|
||||
if(speech_pref)
|
||||
H.mind.speech_span = "wingdings"
|
||||
|
||||
/datum/species/diona
|
||||
name = "Diona"
|
||||
name_plural = "Dionaea"
|
||||
@@ -733,6 +742,7 @@
|
||||
slowdown = 5
|
||||
remains_type = /obj/effect/decal/cleanable/ash
|
||||
|
||||
|
||||
warning_low_pressure = 50
|
||||
hazard_low_pressure = -1
|
||||
|
||||
@@ -822,7 +832,7 @@
|
||||
|
||||
if(H.nutrition > NUTRITION_LEVEL_WELL_FED)
|
||||
H.nutrition = NUTRITION_LEVEL_WELL_FED
|
||||
|
||||
|
||||
if(light_amount > 0)
|
||||
H.clear_alert("nolight")
|
||||
else
|
||||
@@ -876,6 +886,10 @@
|
||||
reagent_tag = PROCESS_SYN
|
||||
male_scream_sound = 'sound/goonstation/voice/robot_scream.ogg'
|
||||
female_scream_sound = 'sound/goonstation/voice/robot_scream.ogg'
|
||||
male_cough_sounds = list('sound/effects/mob_effects/m_machine_cougha.ogg','sound/effects/mob_effects/m_machine_coughb.ogg', 'sound/effects/mob_effects/m_machine_coughc.ogg')
|
||||
female_cough_sounds = list('sound/effects/mob_effects/f_machine_cougha.ogg','sound/effects/mob_effects/f_machine_coughb.ogg')
|
||||
male_sneeze_sound = 'sound/effects/mob_effects/machine_sneeze.ogg'
|
||||
female_sneeze_sound = 'sound/effects/mob_effects/f_machine_sneeze.ogg'
|
||||
butt_sprite = "machine"
|
||||
|
||||
has_organ = list(
|
||||
@@ -935,6 +949,10 @@
|
||||
speech_chance = 20
|
||||
male_scream_sound = 'sound/voice/DraskTalk2.ogg'
|
||||
female_scream_sound = 'sound/voice/DraskTalk2.ogg'
|
||||
male_cough_sounds = null //whale cough when
|
||||
female_cough_sounds = null
|
||||
male_sneeze_sound = null
|
||||
female_sneeze_sound = null
|
||||
|
||||
burn_mod = 2
|
||||
//exotic_blood = "cryoxadone"
|
||||
@@ -1017,4 +1035,4 @@
|
||||
H.apply_damage(hot_env_multiplier*HEAT_GAS_DAMAGE_LEVEL_2, BURN, "head", used_weapon = "Excessive Heat")
|
||||
|
||||
if(heat_level_3_breathe to INFINITY)
|
||||
H.apply_damage(hot_env_multiplier*HEAT_GAS_DAMAGE_LEVEL_3, BURN, "head", used_weapon = "Excessive Heat")
|
||||
H.apply_damage(hot_env_multiplier*HEAT_GAS_DAMAGE_LEVEL_3, BURN, "head", used_weapon = "Excessive Heat")
|
||||
|
||||
@@ -298,9 +298,9 @@ var/global/list/damage_icon_parts = list()
|
||||
base_icon.MapColors(rgb(tone[1],0,0),rgb(0,tone[2],0),rgb(0,0,tone[3]))
|
||||
|
||||
//Handle husk overlay.
|
||||
if(husk && ("overlay_husk" in icon_states(species.icobase)))
|
||||
if(husk && ("overlay_husk" in icon_states(chest.icobase)))
|
||||
var/icon/mask = new(base_icon)
|
||||
var/icon/husk_over = new(species.icobase,"overlay_husk")
|
||||
var/icon/husk_over = new(chest.icobase,"overlay_husk")
|
||||
mask.MapColors(0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,0)
|
||||
husk_over.Blend(mask, ICON_ADD)
|
||||
base_icon.Blend(husk_over, ICON_OVERLAY)
|
||||
@@ -1197,9 +1197,9 @@ var/global/list/damage_icon_parts = list()
|
||||
else // Otherwise, since the user's tail isn't overlapped by limbs, go ahead and use default icon generation.
|
||||
overlays_standing[TAIL_LAYER] = image(accessory_s, "pixel_x" = body_accessory.pixel_x_offset, "pixel_y" = body_accessory.pixel_y_offset)
|
||||
|
||||
else if(species.tail && species.bodyflags & HAS_TAIL) //no tailless tajaran
|
||||
else if(tail && species.bodyflags & HAS_TAIL) //no tailless tajaran
|
||||
if(!wear_suit || !(wear_suit.flags_inv & HIDETAIL) && !istype(wear_suit, /obj/item/clothing/suit/space))
|
||||
var/icon/tail_s = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.tail]_s")
|
||||
var/icon/tail_s = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[tail]_s")
|
||||
if(species.bodyflags & HAS_SKIN_COLOR)
|
||||
tail_s.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD)
|
||||
if(tail_marking_icon)
|
||||
@@ -1266,8 +1266,8 @@ var/global/list/damage_icon_parts = list()
|
||||
else // Otherwise, since the user's tail isn't overlapped by limbs, go ahead and use default icon generation.
|
||||
overlays_standing[TAIL_LAYER] = image(accessory_s, "pixel_x" = body_accessory.pixel_x_offset, "pixel_y" = body_accessory.pixel_y_offset)
|
||||
|
||||
else if(species.tail && species.bodyflags & HAS_TAIL)
|
||||
var/icon/tailw_s = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[species.tail]w_s")
|
||||
else if(tail && species.bodyflags & HAS_TAIL)
|
||||
var/icon/tailw_s = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[tail]w_s")
|
||||
if(species.bodyflags & HAS_SKIN_COLOR)
|
||||
tailw_s.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD)
|
||||
if(tail_marking_icon)
|
||||
|
||||
@@ -83,12 +83,14 @@
|
||||
var/current_pda_messaging = null
|
||||
|
||||
/mob/living/silicon/pai/New(var/obj/item/device/paicard)
|
||||
src.loc = paicard
|
||||
loc = paicard
|
||||
card = paicard
|
||||
if(card)
|
||||
faction = card.faction.Copy()
|
||||
sradio = new(src)
|
||||
if(card)
|
||||
if(!card.radio)
|
||||
card.radio = new /obj/item/device/radio(src.card)
|
||||
card.radio = new /obj/item/device/radio(card)
|
||||
radio = card.radio
|
||||
|
||||
//Default languages without universal translator software
|
||||
@@ -122,7 +124,7 @@
|
||||
|
||||
// this function shows the information about being silenced as a pAI in the Status panel
|
||||
/mob/living/silicon/pai/proc/show_silenced()
|
||||
if(src.silence_time)
|
||||
if(silence_time)
|
||||
var/timeleft = round((silence_time - world.timeofday)/10 ,1)
|
||||
stat(null, "Communications system reboot in -[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]")
|
||||
|
||||
@@ -130,7 +132,7 @@
|
||||
/mob/living/silicon/pai/Stat()
|
||||
..()
|
||||
statpanel("Status")
|
||||
if(src.client.statpanel == "Status")
|
||||
if(client.statpanel == "Status")
|
||||
show_silenced()
|
||||
|
||||
if(proc_holder_list.len)//Generic list for proc_holder objects.
|
||||
@@ -138,20 +140,20 @@
|
||||
statpanel("[P.panel]","",P)
|
||||
|
||||
/mob/living/silicon/pai/check_eye(var/mob/user as mob)
|
||||
if(!src.current)
|
||||
if(!current)
|
||||
return null
|
||||
user.reset_perspective(src.current)
|
||||
user.reset_perspective(current)
|
||||
return 1
|
||||
|
||||
/mob/living/silicon/pai/blob_act()
|
||||
if(src.stat != 2)
|
||||
src.adjustBruteLoss(60)
|
||||
src.updatehealth()
|
||||
if(stat != 2)
|
||||
adjustBruteLoss(60)
|
||||
updatehealth()
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/mob/living/silicon/pai/restrained()
|
||||
if(istype(src.loc,/obj/item/device/paicard))
|
||||
if(istype(loc,/obj/item/device/paicard))
|
||||
return 0
|
||||
..()
|
||||
|
||||
@@ -165,18 +167,18 @@
|
||||
// 33% chance to change prime directive (based on severity)
|
||||
// 33% chance of no additional effect
|
||||
|
||||
src.silence_time = world.timeofday + 120 * 10 // Silence for 2 minutes
|
||||
silence_time = world.timeofday + 120 * 10 // Silence for 2 minutes
|
||||
to_chat(src, "<font color=green><b>Communication circuit overload. Shutting down and reloading communication circuits - speech and messaging functionality will be unavailable until the reboot is complete.</b></font>")
|
||||
if(prob(20))
|
||||
var/turf/T = get_turf_or_move(src.loc)
|
||||
var/turf/T = get_turf_or_move(loc)
|
||||
for(var/mob/M in viewers(T))
|
||||
M.show_message("\red A shower of sparks spray from [src]'s inner workings.", 3, "\red You hear and smell the ozone hiss of electrical sparks being expelled violently.", 2)
|
||||
return src.death(0)
|
||||
return death(0)
|
||||
|
||||
switch(pick(1,2,3))
|
||||
if(1)
|
||||
src.master = null
|
||||
src.master_dna = null
|
||||
master = null
|
||||
master_dna = null
|
||||
to_chat(src, "<font color=green>You feel unbound.</font>")
|
||||
if(2)
|
||||
var/command
|
||||
@@ -184,7 +186,7 @@
|
||||
command = pick("Serve", "Love", "Fool", "Entice", "Observe", "Judge", "Respect", "Educate", "Amuse", "Entertain", "Glorify", "Memorialize", "Analyze")
|
||||
else
|
||||
command = pick("Serve", "Kill", "Love", "Hate", "Disobey", "Devour", "Fool", "Enrage", "Entice", "Observe", "Judge", "Respect", "Disrespect", "Consume", "Educate", "Destroy", "Disgrace", "Amuse", "Entertain", "Ignite", "Glorify", "Memorialize", "Analyze")
|
||||
src.pai_law0 = "[command] your master."
|
||||
pai_law0 = "[command] your master."
|
||||
to_chat(src, "<font color=green>Pr1m3 d1r3c71v3 uPd473D.</font>")
|
||||
if(3)
|
||||
to_chat(src, "<font color=green>You feel an electric surge run through your circuitry and become acutely aware at how lucky you are that you can still feel at all.</font>")
|
||||
@@ -194,15 +196,15 @@
|
||||
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
if(src.stat != 2)
|
||||
if(stat != 2)
|
||||
adjustBruteLoss(100)
|
||||
adjustFireLoss(100)
|
||||
if(2.0)
|
||||
if(src.stat != 2)
|
||||
if(stat != 2)
|
||||
adjustBruteLoss(60)
|
||||
adjustFireLoss(60)
|
||||
if(3.0)
|
||||
if(src.stat != 2)
|
||||
if(stat != 2)
|
||||
adjustBruteLoss(30)
|
||||
|
||||
return
|
||||
@@ -219,8 +221,8 @@
|
||||
playsound(loc, M.attack_sound, 50, 1, 1)
|
||||
for(var/mob/O in viewers(src, null))
|
||||
O.show_message("<span class='danger'>[M]</span> [M.attacktext] [src]!", 1)
|
||||
M.create_attack_log("<font color='red'>attacked [src.name] ([src.ckey])</font>")
|
||||
src.create_attack_log("<font color='orange'>was attacked by [M.name] ([M.ckey])</font>")
|
||||
M.create_attack_log("<font color='red'>attacked [name] ([ckey])</font>")
|
||||
create_attack_log("<font color='orange'>was attacked by [M.name] ([M.ckey])</font>")
|
||||
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
|
||||
adjustBruteLoss(damage)
|
||||
updatehealth()
|
||||
@@ -230,7 +232,7 @@
|
||||
to_chat(M, "You cannot attack people before the game has started.")
|
||||
return
|
||||
|
||||
if(istype(src.loc, /turf) && istype(src.loc.loc, /area/start))
|
||||
if(istype(loc, /turf) && istype(loc.loc, /area/start))
|
||||
to_chat(M, "You cannot attack someone in the spawn area.")
|
||||
return
|
||||
|
||||
@@ -245,16 +247,16 @@
|
||||
M.do_attack_animation(src)
|
||||
var/damage = rand(10, 20)
|
||||
if(prob(90))
|
||||
playsound(src.loc, 'sound/weapons/slash.ogg', 25, 1, -1)
|
||||
playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1)
|
||||
for(var/mob/O in viewers(src, null))
|
||||
if((O.client && !( O.blinded )))
|
||||
O.show_message(text("<span class='danger'>[] has slashed at []!</span>", M, src), 1)
|
||||
if(prob(8))
|
||||
flash_eyes(affect_silicon = 1)
|
||||
src.adjustBruteLoss(damage)
|
||||
src.updatehealth()
|
||||
adjustBruteLoss(damage)
|
||||
updatehealth()
|
||||
else
|
||||
playsound(src.loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1)
|
||||
playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1)
|
||||
for(var/mob/O in viewers(src, null))
|
||||
if((O.client && !( O.blinded )))
|
||||
O.show_message(text("<span class='danger'>[] took a swipe at []!</span>", M, src), 1)
|
||||
@@ -263,16 +265,16 @@
|
||||
/mob/living/silicon/pai/proc/switchCamera(var/obj/machinery/camera/C)
|
||||
usr:cameraFollow = null
|
||||
if(!C)
|
||||
src.unset_machine()
|
||||
src.reset_perspective(null)
|
||||
unset_machine()
|
||||
reset_perspective(null)
|
||||
return 0
|
||||
if(stat == 2 || !C.status || !(src.network in C.network)) return 0
|
||||
if(stat == 2 || !C.status || !(network in C.network)) return 0
|
||||
|
||||
// ok, we're alive, camera is good and in our network...
|
||||
|
||||
src.set_machine(src)
|
||||
set_machine(src)
|
||||
src:current = C
|
||||
src.reset_perspective(C)
|
||||
reset_perspective(C)
|
||||
return 1
|
||||
|
||||
/mob/living/silicon/pai/verb/reset_record_view()
|
||||
@@ -291,8 +293,8 @@
|
||||
/mob/living/silicon/pai/cancel_camera()
|
||||
set category = "pAI Commands"
|
||||
set name = "Cancel Camera View"
|
||||
src.reset_perspective(null)
|
||||
src.unset_machine()
|
||||
reset_perspective(null)
|
||||
unset_machine()
|
||||
src:cameraFollow = null
|
||||
|
||||
//Addition by Mord_Sith to define AI's network change ability
|
||||
@@ -300,8 +302,8 @@
|
||||
/mob/living/silicon/pai/proc/pai_network_change()
|
||||
set category = "pAI Commands"
|
||||
set name = "Change Camera Network"
|
||||
src.reset_perspective(null)
|
||||
src.unset_machine()
|
||||
reset_perspective(null)
|
||||
unset_machine()
|
||||
src:cameraFollow = null
|
||||
var/cameralist[0]
|
||||
|
||||
@@ -316,8 +318,8 @@
|
||||
if(C.network != "CREED" && C.network != "thunder" && C.network != "RD" && C.network != "toxins" && C.network != "Prison") COMPILE ERROR! This will have to be updated as camera.network is no longer a string, but a list instead
|
||||
cameralist[C.network] = C.network
|
||||
|
||||
src.network = input(usr, "Which network would you like to view?") as null|anything in cameralist
|
||||
to_chat(src, "\blue Switched to [src.network] camera network.")
|
||||
network = input(usr, "Which network would you like to view?") as null|anything in cameralist
|
||||
to_chat(src, "\blue Switched to [network] camera network.")
|
||||
//End of code by Mord_Sith
|
||||
*/
|
||||
|
||||
@@ -327,7 +329,7 @@
|
||||
/mob/verb/makePAI(var/turf/t in view())
|
||||
var/obj/item/device/paicard/card = new(t)
|
||||
var/mob/living/silicon/pai/pai = new(card)
|
||||
pai.key = src.key
|
||||
pai.key = key
|
||||
card.setPersonality(pai)
|
||||
|
||||
*/
|
||||
@@ -394,7 +396,7 @@
|
||||
|
||||
var/choice
|
||||
var/finalized = "No"
|
||||
while(finalized == "No" && src.client)
|
||||
while(finalized == "No" && client)
|
||||
|
||||
choice = input(usr,"What would you like to use for your mobile chassis icon? This decision can only be made once.") as null|anything in possible_chassis
|
||||
if(!choice) return
|
||||
@@ -425,9 +427,9 @@
|
||||
set category = "IC"
|
||||
|
||||
// Pass lying down or getting up to our pet human, if we're in a rig.
|
||||
if(stat == CONSCIOUS && istype(src.loc,/obj/item/device/paicard))
|
||||
if(stat == CONSCIOUS && istype(loc,/obj/item/device/paicard))
|
||||
resting = 0
|
||||
var/obj/item/weapon/rig/rig = src.get_rig()
|
||||
var/obj/item/weapon/rig/rig = get_rig()
|
||||
if(istype(rig))
|
||||
rig.force_rest(src)
|
||||
else
|
||||
@@ -449,15 +451,15 @@
|
||||
updatehealth()
|
||||
N.use(1)
|
||||
user.visible_message("<span class='notice'>[user.name] applied some [W] at [src]'s damaged areas.</span>",\
|
||||
"<span class='notice'>You apply some [W] at [src.name]'s damaged areas.</span>")
|
||||
"<span class='notice'>You apply some [W] at [name]'s damaged areas.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>All [src.name]'s systems are nominal.</span>")
|
||||
to_chat(user, "<span class='notice'>All [name]'s systems are nominal.</span>")
|
||||
|
||||
return
|
||||
else if(W.force)
|
||||
visible_message("<span class='danger'>[user.name] attacks [src] with [W]!</span>")
|
||||
src.adjustBruteLoss(W.force)
|
||||
src.updatehealth()
|
||||
adjustBruteLoss(W.force)
|
||||
updatehealth()
|
||||
else
|
||||
visible_message("<span class='warning'>[user.name] bonks [src] harmlessly with [W].</span>")
|
||||
spawn(1)
|
||||
@@ -529,9 +531,9 @@
|
||||
|
||||
var/msg = "<span class='info'>"
|
||||
|
||||
switch(src.stat)
|
||||
switch(stat)
|
||||
if(CONSCIOUS)
|
||||
if(!src.client) msg += "\nIt appears to be in stand-by mode." //afk
|
||||
if(!client) msg += "\nIt appears to be in stand-by mode." //afk
|
||||
if(UNCONSCIOUS) msg += "\n<span class='warning'>It doesn't seem to be responding.</span>"
|
||||
if(DEAD) msg += "\n<span class='deadsay'>It looks completely unsalvageable.</span>"
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/mob/living/simple_animal/hostile/mimic
|
||||
name = "crate"
|
||||
desc = "A rectangular steel crate."
|
||||
icon = 'icons/obj/storage.dmi'
|
||||
icon = 'icons/obj/crates.dmi'
|
||||
icon_state = "crate"
|
||||
icon_living = "crate"
|
||||
|
||||
|
||||
@@ -4,8 +4,18 @@
|
||||
#define MOVING_TO_TARGET 3
|
||||
#define SPINNING_COCOON 4
|
||||
|
||||
#define TS_DESC_RED "Red - Assault"
|
||||
#define TS_DESC_GRAY "Gray - Ambush"
|
||||
#define TS_DESC_GREEN "Green - Nurse"
|
||||
#define TS_DESC_WHITE "White - Infect"
|
||||
#define TS_DESC_BLACK "Black - Poison"
|
||||
#define TS_DESC_PURPLE "Purple - Guard"
|
||||
#define TS_DESC_PRINCE "Prince - WAR"
|
||||
#define TS_DESC_MOTHER "Mother - HORROR"
|
||||
#define TS_DESC_QUEEN "Queen - LEADER"
|
||||
|
||||
#define TS_TIER_1 1
|
||||
#define TS_TIER_2 2
|
||||
#define TS_TIER_3 3
|
||||
#define TS_TIER_4 4
|
||||
#define TS_TIER_5 5
|
||||
#define TS_TIER_5 5
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
// ---------- ACTIONS FOR ALL SPIDERS
|
||||
|
||||
/datum/action/innate/terrorspider/web
|
||||
name = "Web"
|
||||
@@ -19,17 +19,83 @@
|
||||
user.FindWrapTarget()
|
||||
user.DoWrap()
|
||||
|
||||
// ---------- GREEN ACTIONS
|
||||
|
||||
/datum/action/innate/terrorspider/greeneggs
|
||||
name = "Lay Green Eggs"
|
||||
icon_icon = 'icons/effects/effects.dmi'
|
||||
button_icon_state = "eggs"
|
||||
|
||||
/datum/action/innate/terrorspider/greeneggs/Activate()
|
||||
var/mob/living/simple_animal/hostile/poison/terror_spider/green/user = owner
|
||||
user.DoLayGreenEggs()
|
||||
|
||||
// ---------- PRINCE ACTIONS
|
||||
|
||||
/datum/action/innate/terrorspider/princesmash
|
||||
name = "Smash Welded Vent"
|
||||
icon_icon = 'icons/atmos/vent_pump.dmi'
|
||||
button_icon_state = "map_vent"
|
||||
|
||||
/datum/action/innate/terrorspider/princesmash/Activate()
|
||||
var/mob/living/simple_animal/hostile/poison/terror_spider/prince/user = owner
|
||||
user.DoPrinceSmash()
|
||||
|
||||
// ---------- QUEEN ACTIONS
|
||||
|
||||
/datum/action/innate/terrorspider/queen/queennest
|
||||
name = "Nest"
|
||||
icon_icon = 'icons/mob/terrorspider.dmi'
|
||||
button_icon_state = "terror_queen"
|
||||
|
||||
/datum/action/innate/terrorspider/queen/queennest/Activate()
|
||||
var/mob/living/simple_animal/hostile/poison/terror_spider/queen/user = owner
|
||||
user.NestMode()
|
||||
|
||||
/datum/action/innate/terrorspider/queen/queensense
|
||||
name = "Hive Sense"
|
||||
icon_icon = 'icons/mob/actions.dmi'
|
||||
button_icon_state = "mindswap"
|
||||
|
||||
/datum/action/innate/terrorspider/queen/queensense/Activate()
|
||||
var/mob/living/simple_animal/hostile/poison/terror_spider/queen/user = owner
|
||||
user.DoHiveSense()
|
||||
|
||||
/datum/action/innate/terrorspider/queen/queeneggs
|
||||
name = "Lay Queen Eggs"
|
||||
icon_icon = 'icons/effects/effects.dmi'
|
||||
button_icon_state = "eggs"
|
||||
|
||||
/datum/action/innate/terrorspider/queen/queeneggs/Activate()
|
||||
var/mob/living/simple_animal/hostile/poison/terror_spider/queen/user = owner
|
||||
user.LayQueenEggs()
|
||||
|
||||
/datum/action/innate/terrorspider/queen/queenfakelings
|
||||
name = "Fake Spiderlings"
|
||||
icon_icon = 'icons/effects/effects.dmi'
|
||||
button_icon_state = "spiderling"
|
||||
|
||||
/datum/action/innate/terrorspider/queen/queenfakelings/Activate()
|
||||
var/mob/living/simple_animal/hostile/poison/terror_spider/queen/user = owner
|
||||
user.QueenFakeLings()
|
||||
|
||||
// ---------- WEB
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/Web()
|
||||
var/turf/mylocation = loc
|
||||
visible_message("<span class='notice'>[src] begins to secrete a sticky substance.</span>")
|
||||
if(do_after(src, 40, target = loc))
|
||||
var/obj/effect/spider/terrorweb/T = locate() in get_turf(src)
|
||||
if(T)
|
||||
to_chat(src, "<span class='danger'>There is already a web here.</span>")
|
||||
if(loc != mylocation)
|
||||
return
|
||||
else if(istype(loc, /turf/space))
|
||||
to_chat(src, "<span class='danger'>Webs cannot be spun in space.</span>")
|
||||
else
|
||||
new /obj/effect/spider/terrorweb(loc)
|
||||
var/obj/effect/spider/terrorweb/T = locate() in get_turf(src)
|
||||
if(T)
|
||||
to_chat(src, "<span class='danger'>There is already a web here.</span>")
|
||||
else
|
||||
var/obj/effect/spider/terrorweb/W = new /obj/effect/spider/terrorweb(loc)
|
||||
W.creator_ckey = ckey
|
||||
|
||||
/obj/effect/spider/terrorweb
|
||||
name = "terror web"
|
||||
@@ -39,23 +105,27 @@
|
||||
density = 0 // prevents it blocking all movement
|
||||
health = 20 // two welders, or one laser shot (15 for the normal spider webs)
|
||||
icon_state = "stickyweb1"
|
||||
|
||||
var/creator_ckey = null
|
||||
|
||||
/obj/effect/spider/terrorweb/New()
|
||||
..()
|
||||
if(prob(50))
|
||||
icon_state = "stickyweb2"
|
||||
|
||||
|
||||
/obj/effect/spider/terrorweb/CanPass(atom/movable/mover, turf/target)
|
||||
if(istype(mover, /mob/living/simple_animal/hostile/poison/terror_spider))
|
||||
return 1
|
||||
if(istype(mover, /obj/item/projectile/terrorqueenspit))
|
||||
return 1
|
||||
if(isliving(mover))
|
||||
if(prob(80))
|
||||
to_chat(mover, "<span class='danger'>You get stuck in [src] for a moment.</span>")
|
||||
var/mob/living/M = mover
|
||||
M.Stun(4) // 8 seconds.
|
||||
M.Weaken(4) // 8 seconds.
|
||||
if(iscarbon(mover))
|
||||
spawn(70)
|
||||
qdel(src)
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
@@ -63,22 +133,25 @@
|
||||
return prob(20)
|
||||
return ..()
|
||||
|
||||
|
||||
|
||||
/obj/effect/spider/terrorweb/bullet_act(obj/item/projectile/Proj)
|
||||
if(Proj.damage_type != BRUTE && Proj.damage_type != BURN)
|
||||
visible_message("<span class='danger'>[src] is undamaged by [Proj]!</span>")
|
||||
// Webs don't care about disablers, tasers, etc. Or toxin damage. They're organic, but not alive.
|
||||
return
|
||||
..()
|
||||
|
||||
// ---------- WRAP
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/FindWrapTarget()
|
||||
if(!cocoon_target)
|
||||
var/list/choices = list()
|
||||
for(var/mob/living/L in oview(1,src))
|
||||
if(Adjacent(L))
|
||||
if(Adjacent(L) && !L.anchored)
|
||||
if(L.stat == DEAD)
|
||||
choices += L
|
||||
for(var/obj/O in oview(1,src))
|
||||
if(Adjacent(O) && !O.anchored)
|
||||
if(!istype(O, /obj/effect/spider/terrorweb) && !istype(O, /obj/effect/spider/cocoon))
|
||||
if(!istype(O, /obj/effect/spider/terrorweb) && !istype(O, /obj/effect/spider/cocoon) && !istype(O, /obj/effect/spider/spiderling/terror_spiderling))
|
||||
choices += O
|
||||
if(choices.len)
|
||||
cocoon_target = input(src,"What do you wish to cocoon?") in null|choices
|
||||
@@ -87,6 +160,9 @@
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/DoWrap()
|
||||
if(cocoon_target && busy != SPINNING_COCOON)
|
||||
if(cocoon_target.anchored)
|
||||
cocoon_target = null
|
||||
return
|
||||
busy = SPINNING_COCOON
|
||||
visible_message("<span class='notice'>[src] begins to secrete a sticky substance around [cocoon_target].</span>")
|
||||
stop_automated_movement = 1
|
||||
@@ -125,3 +201,17 @@
|
||||
busy = 0
|
||||
stop_automated_movement = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/prince/proc/DoPrinceSmash()
|
||||
for(var/obj/machinery/atmospherics/unary/vent_pump/P in view(1,src))
|
||||
if(P.welded)
|
||||
P.welded = 0
|
||||
P.update_icon()
|
||||
visible_message("<span class='danger'>[src] smashes the welded cover off [P]!</span>")
|
||||
return
|
||||
for(var/obj/machinery/atmospherics/unary/vent_scrubber/C in view(1,src))
|
||||
if(C.welded)
|
||||
C.welded = 0
|
||||
C.update_icon()
|
||||
visible_message("<span class='danger'>[src] smashes the welded cover off [C]!</span>")
|
||||
return
|
||||
to_chat(src, "<span class='danger'>There is no unwelded vent close enough to do this.</span>")
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/black
|
||||
name = "Black Terror spider"
|
||||
desc = "An ominous-looking spider, black as the darkest night, and with merciless eyes and a blood-red hourglass pattern on its back."
|
||||
desc = "An ominous-looking spider, black as the darkest night. It has merciless eyes, and a blood-red hourglass pattern on its back."
|
||||
spider_role_summary = "Hit-and-run attacker with extremely venomous bite."
|
||||
|
||||
icon_state = "terror_widow"
|
||||
@@ -24,14 +24,15 @@
|
||||
stat_attack = 1 // ensures they will target people in crit, too!
|
||||
spider_tier = TS_TIER_2
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/black/spider_specialattack(mob/living/carbon/human/L, poisonable)
|
||||
if(!poisonable)
|
||||
return ..()
|
||||
if(L.reagents.has_reagent("terror_black_toxin", 50))
|
||||
if(L.reagents.has_reagent("terror_black_toxin", 100))
|
||||
return ..()
|
||||
var/inject_target = pick("chest", "head")
|
||||
if(L.stunned || L.can_inject(null, 0, inject_target, 0))
|
||||
L.reagents.add_reagent("terror_black_toxin", 15) // inject our special poison
|
||||
L.reagents.add_reagent("terror_black_toxin", 30) // inject our special poison
|
||||
visible_message("<span class='danger'>[src] buries its long fangs deep into the [inject_target] of [target]!</span>")
|
||||
else
|
||||
visible_message("<span class='danger'>[src] bites [target], but cannot inject venom into their [inject_target]!</span>")
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
// Terror Spider, Black, Deadly Venom
|
||||
|
||||
/datum/reagent/terror_black_toxin
|
||||
@@ -8,26 +9,38 @@
|
||||
metabolization_rate = 0.1
|
||||
|
||||
/datum/reagent/terror_black_toxin/on_mob_life(mob/living/M)
|
||||
if(volume < 15)
|
||||
// bitten once, die slowly. Easy to survive a single bite - just go to medbay.
|
||||
// total damage: 2/tick, human health 150 until crit, = 75 ticks, = 150 seconds = 2.5 minutes to get to medbay.
|
||||
M.adjustToxLoss(2) // same damage/tick as tabun cycle 0 to 60
|
||||
else if(volume < 30)
|
||||
// bitten twice, die more quickly, muscle cramps make movement difficult. Call medics immediately.
|
||||
// total damage: 4, human health 150 until crit, = 37.5 ticks, = 75s = 1m15s until death
|
||||
M.adjustToxLoss(4)
|
||||
M.Confused(3)
|
||||
if(volume < 30)
|
||||
// bitten once, die very slowly. Easy to survive a single bite - just go to medbay.
|
||||
// total damage: 1/tick, human health 150 until crit, = 150 ticks, = 300 seconds = 5 minutes to get to medbay.
|
||||
M.adjustToxLoss(1)
|
||||
else if(volume < 60)
|
||||
// bitten twice, die slowly. Get to medbay.
|
||||
// total damage: 2/tick, human health 150 until crit, = 75 ticks, = 150 seconds = 2.5 minutes to get some medical treatment.
|
||||
M.adjustToxLoss(2)
|
||||
M.EyeBlurry(3)
|
||||
else if(volume < 45)
|
||||
// bitten thrice, die very quickly, severe muscle cramps make movement very difficult. Even calling for help probably won't save you.
|
||||
// total damage: 8, human health 150 until crit, = 18.75 ticks, = 37s until death
|
||||
M.adjustToxLoss(8) // a bit worse than coiine
|
||||
else if(volume < 90)
|
||||
// bitten thrice, die quickly, severe muscle cramps make movement very difficult. Even calling for help probably won't save you.
|
||||
// total damage: 4, human health 150 until crit, = 37.5 ticks, = 75s = 1m15s until death
|
||||
M.adjustToxLoss(4) // a bit worse than coiine
|
||||
M.Confused(6)
|
||||
M.EyeBlurry(6)
|
||||
else
|
||||
// bitten 4 or more times, whole body goes into shock/death
|
||||
// total damage: 12, human health 150 until crit, = 12.5 ticks, = 25s until death
|
||||
M.adjustToxLoss(12)
|
||||
// total damage: 8, human health 150 until crit, = 18.75 ticks, = 37s until death
|
||||
M.adjustToxLoss(8)
|
||||
M.EyeBlurry(6)
|
||||
M.Paralyse(5)
|
||||
..()
|
||||
|
||||
// Terror Spider, Queen Toxin
|
||||
|
||||
/datum/reagent/terror_queen_toxin
|
||||
name = "Terror Queen venom"
|
||||
id = "terror_queen_toxin"
|
||||
description = "A royally potent venom."
|
||||
color = "#CF3600"
|
||||
metabolization_rate = 2
|
||||
|
||||
/datum/reagent/terror_queen_toxin/on_mob_life(mob/living/M)
|
||||
// make them hallucinate a lot, like a changeling sting
|
||||
M.AdjustHallucinate(50, bound_upper = 400)
|
||||
@@ -13,15 +13,15 @@
|
||||
return
|
||||
var/error_on_humanize = ""
|
||||
var/humanize_prompt = "Take direct control of [src]?"
|
||||
humanize_prompt += "Role: [spider_role_summary]"
|
||||
humanize_prompt += " Role: [spider_role_summary]"
|
||||
if(user.ckey in ts_ckey_blacklist)
|
||||
error_on_humanize = "You are not able to control any terror spider this round."
|
||||
else if(!ai_playercontrol_allowingeneral)
|
||||
error_on_humanize = "Terror spiders cannot currently be player-controlled."
|
||||
else if(spider_awaymission)
|
||||
error_on_humanize = "Terror spiders that are part of an away mission cannot be controlled by ghosts."
|
||||
else if(!ai_playercontrol_allowtype)
|
||||
error_on_humanize = "This specific type of terror spider is not player-controllable."
|
||||
else if(degenerate)
|
||||
error_on_humanize = "Dying spiders are not player-controllable."
|
||||
else if(stat == DEAD)
|
||||
error_on_humanize = "Dead spiders are not player-controllable."
|
||||
if(jobban_isbanned(user, "Syndicate") || jobban_isbanned(user, "alien"))
|
||||
@@ -39,5 +39,4 @@
|
||||
return
|
||||
key = user.key
|
||||
for(var/mob/dead/observer/G in player_list)
|
||||
G.show_message("<i>A ghost has taken control of <b>[src]</b>. ([ghost_follow_link(src, ghost=G)]).</i>")
|
||||
|
||||
G.show_message("<i>A ghost has taken control of <b>[src]</b>. ([ghost_follow_link(src, ghost=G)]).</i>")
|
||||
@@ -18,10 +18,8 @@
|
||||
health = 120
|
||||
melee_damage_lower = 10
|
||||
melee_damage_upper = 20
|
||||
ventcrawler = 1
|
||||
move_to_delay = 5 // normal speed
|
||||
stat_attack = 1 // ensures they will target people in crit, too!
|
||||
environment_smash = 1
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/gray/spider_specialattack(mob/living/carbon/human/L, poisonable)
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// ----------------- TERROR SPIDERS: T1 GREEN TERROR ------------------------------
|
||||
// --------------------------------------------------------------------------------
|
||||
// -------------: ROLE: reproduction
|
||||
// -------------: SPECIAL: can also create webs, web normal objects, etc
|
||||
// -------------: TO FIGHT IT: kill it however you like - just don't die to it!
|
||||
// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/green
|
||||
name = "Green Terror spider"
|
||||
desc = "An ominous-looking green spider. It has a small egg-sac attached to it, and dried blood stains on its carapace."
|
||||
spider_role_summary = "Average melee spider that webs its victims and lays more spider eggs"
|
||||
|
||||
icon_state = "terror_green"
|
||||
icon_living = "terror_green"
|
||||
icon_dead = "terror_green_dead"
|
||||
maxHealth = 120
|
||||
health = 120
|
||||
melee_damage_lower = 10
|
||||
melee_damage_upper = 20
|
||||
var/feedings_to_lay = 2
|
||||
|
||||
var/datum/action/innate/terrorspider/greeneggs/greeneggs_action
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/green/New()
|
||||
..()
|
||||
greeneggs_action = new()
|
||||
greeneggs_action.Grant(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/green/proc/DoLayGreenEggs()
|
||||
var/obj/effect/spider/eggcluster/E = locate() in get_turf(src)
|
||||
if(E)
|
||||
to_chat(src, "<span class='notice'>There is already a cluster of eggs here!</span>")
|
||||
else if(fed < feedings_to_lay)
|
||||
to_chat(src, "<span class='warning'>You must wrap more prey before you can do this!</span>")
|
||||
else
|
||||
visible_message("<span class='notice'>[src] begins to lay a cluster of eggs.</span>")
|
||||
if(prob(33))
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/red, 1, 1)
|
||||
else if(prob(50))
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/gray, 1, 1)
|
||||
else
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/green, 1, 1)
|
||||
fed -= feedings_to_lay
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/green/spider_specialattack(mob/living/carbon/human/L, poisonable)
|
||||
if(!poisonable)
|
||||
..()
|
||||
return
|
||||
var/inject_target = pick("chest","head")
|
||||
if(L.stunned || L.can_inject(null,0,inject_target,0))
|
||||
if(L.eye_blurry < 60)
|
||||
L.AdjustEyeBlurry(10)
|
||||
// instead of having a venom that only lasts seconds, we just add the eyeblur directly.
|
||||
visible_message("<span class='danger'>[src] buries its fangs deep into the [inject_target] of [target]!</span>")
|
||||
else
|
||||
visible_message("<span class='danger'>[src] bites [target], but cannot inject venom into their [inject_target]!</span>")
|
||||
L.attack_animal(src)
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
// All terror spider code that relates to queen ruling over a hive
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/DoHiveSense()
|
||||
var/hsline = ""
|
||||
to_chat(src, "Your Brood: ")
|
||||
for(var/mob/living/simple_animal/hostile/poison/terror_spider/T in ts_spiderlist)
|
||||
if(T.spider_awaymission != spider_awaymission)
|
||||
continue
|
||||
hsline = "* [T] in [get_area(T)], "
|
||||
if(T.stat == DEAD)
|
||||
hsline += "DEAD"
|
||||
else
|
||||
hsline += "health [T.health] / [T.maxHealth], "
|
||||
if(T.ckey)
|
||||
hsline += " *Player Controlled* "
|
||||
else
|
||||
hsline += " AI "
|
||||
to_chat(src,hsline)
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/CountSpiders()
|
||||
var/numspiders = 0
|
||||
for(var/mob/living/simple_animal/hostile/poison/terror_spider/T in ts_spiderlist)
|
||||
if(T.stat != DEAD && !T.spider_placed && spider_awaymission == T.spider_awaymission)
|
||||
numspiders += 1
|
||||
return numspiders
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/CountSpidersType(specific_type)
|
||||
var/numspiders = 0
|
||||
for(var/mob/living/simple_animal/hostile/poison/terror_spider/T in ts_spiderlist)
|
||||
if(T.stat != DEAD && !T.spider_placed && spider_awaymission == T.spider_awaymission)
|
||||
if(T.type == specific_type)
|
||||
numspiders += 1
|
||||
for(var/obj/effect/spider/eggcluster/terror_eggcluster/E in ts_egg_list)
|
||||
if(E.spiderling_type == specific_type && E.z == z)
|
||||
numspiders += E.spiderling_number
|
||||
for(var/obj/effect/spider/spiderling/terror_spiderling/L in ts_spiderling_list)
|
||||
if(!L.stillborn && L.grow_as == specific_type && L.z == z)
|
||||
numspiders += 1
|
||||
return numspiders
|
||||
@@ -0,0 +1,46 @@
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// ----------------- TERROR SPIDERS: T3 MOTHER OF TERROR --------------------------
|
||||
// --------------------------------------------------------------------------------
|
||||
// -------------: ROLE: living schmuck bait
|
||||
// -------------: SPECIAL: spawns an ungodly number of spiderlings when killed
|
||||
// -------------: TO FIGHT IT: don't! Just leave it alone! It is harmless by itself... but god help you if you aggro it.
|
||||
// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/mother
|
||||
name = "Mother of Terror spider"
|
||||
desc = "An enormous spider. Hundreds of tiny spiderlings are crawling all over it. Their beady little eyes all stare at you. The horror!"
|
||||
spider_role_summary = "Schmuck bait. Extremely weak in combat, but spawns many spiderlings when it dies."
|
||||
|
||||
icon_state = "terror_gray2"
|
||||
icon_living = "terror_gray2"
|
||||
icon_dead = "terror_gray2_dead"
|
||||
maxHealth = 50
|
||||
health = 50
|
||||
melee_damage_lower = 10
|
||||
melee_damage_upper = 20
|
||||
move_to_delay = 5
|
||||
|
||||
spider_tier = TS_TIER_3
|
||||
spider_opens_doors = 2
|
||||
|
||||
var/canspawn = 1
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/mother/death(gibbed)
|
||||
if(canspawn)
|
||||
canspawn = 0
|
||||
for(var/i in 0 to 30)
|
||||
var/obj/effect/spider/spiderling/terror_spiderling/S = new /obj/effect/spider/spiderling/terror_spiderling(get_turf(src))
|
||||
S.grow_as = pick(/mob/living/simple_animal/hostile/poison/terror_spider/red, /mob/living/simple_animal/hostile/poison/terror_spider/gray)
|
||||
if(prob(66))
|
||||
S.stillborn = 1
|
||||
else if(prob(10))
|
||||
S.grow_as = pick(/mob/living/simple_animal/hostile/poison/terror_spider/black, /mob/living/simple_animal/hostile/poison/terror_spider/green)
|
||||
visible_message("<span class='userdanger'>[src] breaks apart, the many spiders on its back scurrying everywhere!</span>")
|
||||
degenerate = 1
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/mother/Destroy()
|
||||
canspawn = 0
|
||||
return ..()
|
||||
@@ -11,20 +11,34 @@
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/prince
|
||||
name = "Prince of Terror spider"
|
||||
desc = "An enormous, terrifying spider. It looks like it is judging everything it sees. Its hide seems armored, and it bears the scars of many battles."
|
||||
spider_role_summary = "Boss-level terror spider. Lightning bruiser. Capable of taking on a squad by itself."
|
||||
spider_role_summary = "Miniboss terror spider. Lightning bruiser."
|
||||
|
||||
icon_state = "terror_allblack"
|
||||
icon_living = "terror_allblack"
|
||||
icon_dead = "terror_allblack_dead"
|
||||
maxHealth = 400 // 20 laser shots.
|
||||
health = 400
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 25
|
||||
move_to_delay = 5
|
||||
ventcrawler = 1
|
||||
|
||||
maxHealth = 600 // 30 laser shots
|
||||
health = 600
|
||||
regen_points_per_hp = 6 // double the normal - IE halved regen speed
|
||||
|
||||
melee_damage_lower = 20
|
||||
melee_damage_upper = 30
|
||||
move_to_delay = 4 // faster than normal
|
||||
|
||||
ventcrawler = 0
|
||||
environment_smash = 3
|
||||
|
||||
loot = list(/obj/item/clothing/accessory/medal)
|
||||
spider_tier = TS_TIER_3
|
||||
spider_opens_doors = 2
|
||||
|
||||
var/datum/action/innate/terrorspider/princesmash/princesmash_action
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/prince/New()
|
||||
..()
|
||||
princesmash_action = new()
|
||||
princesmash_action.Grant(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/prince/spider_specialattack(mob/living/carbon/human/L)
|
||||
if(prob(15))
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// ----------------- TERROR SPIDERS: T2 PURPLE TERROR -----------------------------
|
||||
// --------------------------------------------------------------------------------
|
||||
// -------------: ROLE: guarding queen nests
|
||||
// -------------: SPECIAL: chance to stun on hit
|
||||
// -------------: TO FIGHT IT: shoot it from range, bring friends!
|
||||
// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/purple
|
||||
name = "Purple Terror spider"
|
||||
desc = "An ominous-looking purple spider. It looks about warily, as if waiting for something."
|
||||
spider_role_summary = "Guards the nest of the Queen of Terror."
|
||||
|
||||
icon_state = "terror_purple"
|
||||
icon_living = "terror_purple"
|
||||
icon_dead = "terror_purple_dead"
|
||||
maxHealth = 200
|
||||
health = 200
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 25
|
||||
move_to_delay = 6
|
||||
|
||||
spider_tier = TS_TIER_2
|
||||
spider_opens_doors = 2
|
||||
|
||||
ventcrawler = 0
|
||||
environment_smash = 3
|
||||
|
||||
var/dcheck_counter = 0
|
||||
var/queen_visible = 1
|
||||
var/cycles_noqueen = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/purple/spider_specialattack(mob/living/carbon/human/L, poisonable)
|
||||
if(cycles_noqueen < 6 && prob(10))
|
||||
visible_message("<span class='danger'>[src] rams into [L], knocking them to the floor!</span>")
|
||||
L.Weaken(5)
|
||||
L.Stun(5)
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/purple/Life()
|
||||
. = ..()
|
||||
if(.) // if mob is NOT dead
|
||||
if(!degenerate && spider_myqueen)
|
||||
if(dcheck_counter >= 10)
|
||||
dcheck_counter = 0
|
||||
purple_distance_check()
|
||||
else
|
||||
dcheck_counter++
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/purple/proc/purple_distance_check()
|
||||
if(spider_myqueen)
|
||||
var/mob/living/simple_animal/hostile/poison/terror_spider/queen/Q = spider_myqueen
|
||||
if(Q)
|
||||
if(Q.stat == DEAD)
|
||||
spider_myqueen = null
|
||||
degenerate = 1
|
||||
to_chat(src,"<span class='userdanger'>Your Queen has died! Her power no longer sustains you!</span>")
|
||||
return
|
||||
queen_visible = 0
|
||||
for(var/mob/living/M in view(src, vision_range))
|
||||
if(M == Q)
|
||||
queen_visible = 1
|
||||
break
|
||||
if(queen_visible)
|
||||
cycles_noqueen = 0
|
||||
if(spider_debug)
|
||||
to_chat(src,"<span class='notice'>Queen visible.</span>")
|
||||
else
|
||||
cycles_noqueen++
|
||||
if(spider_debug)
|
||||
to_chat(src,"<span class='danger'>Queen NOT visible. Cycles: [cycles_noqueen].</span>")
|
||||
if(cycles_noqueen == 3)
|
||||
// one minute without queen sighted
|
||||
to_chat(src,"<span class='notice'>You wonder where your Queen is.</span>")
|
||||
else if(cycles_noqueen == 6)
|
||||
// two minutes without queen sighted
|
||||
to_chat(src,"<span class='danger'>Without your Queen in sight, you feel yourself getting weaker...</span>")
|
||||
else if(cycles_noqueen >= 9)
|
||||
// three minutes without queen sighted, kill them.
|
||||
degenerate = 1
|
||||
to_chat(src,"<span class='userdanger'>Your link to your Queen has been broken! Your life force starts to drain away!</span>")
|
||||
melee_damage_lower = 5
|
||||
melee_damage_upper = 10
|
||||
@@ -0,0 +1,214 @@
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// ----------------- TERROR SPIDERS: T4 QUEEN OF TERROR ---------------------------
|
||||
// --------------------------------------------------------------------------------
|
||||
// -------------: ROLE: gamma-level threat to the whole station, like a blob
|
||||
// -------------: SPECIAL: spins webs, breaks lights, breaks cameras, webs objects, lays eggs, commands other spiders...
|
||||
// -------------: TO FIGHT IT: bring an army, and take no prisoners. Mechs and/or decloner guns are a very good idea.
|
||||
// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/queen
|
||||
name = "Queen of Terror spider"
|
||||
desc = "An enormous, terrifying spider. Its egg sac is almost as big as its body, and teeming with spider eggs!"
|
||||
spider_role_summary = "Commander of the spider forces. Lays eggs, directs the brood."
|
||||
|
||||
icon_state = "terror_queen"
|
||||
icon_living = "terror_queen"
|
||||
icon_dead = "terror_queen_dead"
|
||||
maxHealth = 200
|
||||
health = 200
|
||||
melee_damage_lower = 10
|
||||
melee_damage_upper = 20
|
||||
move_to_delay = 15 // yeah, this is very slow, but
|
||||
ventcrawler = 1
|
||||
var/spider_spawnfrequency = 1200 // 120 seconds
|
||||
var/spider_spawnfrequency_stable = 1200 // 120 seconds. Spawnfrequency is set to this on ai spiders once nest setup is complete.
|
||||
var/spider_lastspawn = 0
|
||||
var/nestfrequency = 150 // 15 seconds
|
||||
var/lastnestsetup = 0
|
||||
var/neststep = 0
|
||||
var/hasnested = 0
|
||||
var/spider_max_per_nest = 20 // above this, queen stops spawning more, and declares war.
|
||||
|
||||
var/canlay = 0 // main counter for egg-laying ability! # = num uses, incremented at intervals
|
||||
var/spider_can_fakelings = 3 // spawns defective spiderlings that don't grow up, used to freak out crew, atmosphere
|
||||
|
||||
force_threshold = 18 // outright immune to anything of force under 18, this means welders can't hurt it, only guns can
|
||||
|
||||
ranged = 1
|
||||
retreat_distance = 5
|
||||
minimum_distance = 5
|
||||
projectilesound = 'sound/weapons/pierce.ogg'
|
||||
projectiletype = /obj/item/projectile/terrorqueenspit
|
||||
|
||||
spider_tier = TS_TIER_4
|
||||
spider_opens_doors = 2
|
||||
loot = list(/obj/item/clothing/accessory/medal)
|
||||
|
||||
var/datum/action/innate/terrorspider/queen/queennest/queennest_action
|
||||
var/datum/action/innate/terrorspider/queen/queensense/queensense_action
|
||||
var/datum/action/innate/terrorspider/queen/queeneggs/queeneggs_action
|
||||
var/datum/action/innate/terrorspider/queen/queenfakelings/queenfakelings_action
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/queen/New()
|
||||
..()
|
||||
queennest_action = new()
|
||||
queennest_action.Grant(src)
|
||||
spider_myqueen = src
|
||||
if(spider_awaymission)
|
||||
spider_growinstantly = 1
|
||||
spider_spawnfrequency = 150
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/queen/Life()
|
||||
. = ..()
|
||||
if(.) // if mob is NOT dead
|
||||
if(ckey && canlay < 12 && hasnested) // max 12 eggs worth stored at any one time, realistically that's tons.
|
||||
if(world.time > (spider_lastspawn + spider_spawnfrequency))
|
||||
canlay++
|
||||
spider_lastspawn = world.time
|
||||
if(canlay == 1)
|
||||
to_chat(src, "<span class='notice'>You are able to lay eggs again.</span>")
|
||||
else if(canlay == 12)
|
||||
to_chat(src, "<span class='notice'>You have [canlay] eggs available to lay. You won't grow any more eggs until you lay some of your existing ones.</span>")
|
||||
else
|
||||
to_chat(src, "<span class='notice'>You have [canlay] eggs available to lay.</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/queen/death(gibbed)
|
||||
if(!hasdied)
|
||||
// When a queen dies, so do her player-controlled purple-type guardians. Intended as a motivator for purples to ensure they guard her.
|
||||
for(var/mob/living/simple_animal/hostile/poison/terror_spider/purple/P in ts_spiderlist)
|
||||
if(ckey)
|
||||
P.visible_message("<span class='danger'>\The [src] writhes in pain!</span>")
|
||||
to_chat(P,"<span class='userdanger'>\The [src] has died. Without her hivemind link, purple terrors like yourself cannot survive more than a few minutes!</span>")
|
||||
P.degenerate = 1
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/queen/proc/NestMode()
|
||||
queeneggs_action = new()
|
||||
queeneggs_action.Grant(src)
|
||||
queenfakelings_action = new()
|
||||
queenfakelings_action.Grant(src)
|
||||
queensense_action = new()
|
||||
queensense_action.Grant(src)
|
||||
queennest_action.Remove(src)
|
||||
hasnested = 1
|
||||
ventcrawler = 0
|
||||
environment_smash = 3
|
||||
DoQueenScreech(8, 100, 8, 100)
|
||||
MassFlicker()
|
||||
to_chat(src, "<span class='notice'>You have matured to your egglaying stage. You can now smash through walls, and lay eggs, but can no longer ventcrawl.</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/queen/proc/MassFlicker()
|
||||
var/list/target_lights = list()
|
||||
for(var/mob/living/carbon/human/H in player_list)
|
||||
if(H.z != z)
|
||||
continue
|
||||
if(H.stat == DEAD)
|
||||
continue
|
||||
for(var/obj/machinery/light/L in orange(7, H))
|
||||
if(L.on && prob(25))
|
||||
target_lights += L
|
||||
for(var/obj/machinery/light/I in target_lights)
|
||||
I.flicker()
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/queen/proc/LayQueenEggs()
|
||||
if(!hasnested)
|
||||
to_chat(src, "<span class='danger'>You must nest before doing this.</span>")
|
||||
return
|
||||
if(canlay < 1)
|
||||
var/remainingtime = round(((spider_lastspawn + spider_spawnfrequency) - world.time) / 10, 1)
|
||||
if(remainingtime > 0)
|
||||
to_chat(src, "<span class='danger'>Too soon to attempt that again. Wait another [num2text(remainingtime)] seconds.</span>")
|
||||
else
|
||||
to_chat(src, "<span class='danger'>Too soon to attempt that again. Wait just a few more seconds...</span>")
|
||||
return
|
||||
var/list/eggtypes = list(TS_DESC_RED, TS_DESC_GRAY, TS_DESC_GREEN, TS_DESC_BLACK, TS_DESC_PURPLE)
|
||||
if(canlay >= 12)
|
||||
eggtypes |= TS_DESC_MOTHER
|
||||
eggtypes |= TS_DESC_PRINCE
|
||||
var num_purples = CountSpidersType(/mob/living/simple_animal/hostile/poison/terror_spider/purple)
|
||||
if(num_purples >= 2)
|
||||
eggtypes -= TS_DESC_PURPLE
|
||||
var num_blacks = CountSpidersType(/mob/living/simple_animal/hostile/poison/terror_spider/black)
|
||||
if(num_blacks >= 2)
|
||||
eggtypes -= TS_DESC_BLACK
|
||||
var/eggtype = input("What kind of eggs?") as null|anything in eggtypes
|
||||
if(!(eggtype in eggtypes))
|
||||
to_chat(src, "<span class='danger'>Unrecognized egg type.</span>")
|
||||
return 0
|
||||
if(eggtype == TS_DESC_MOTHER || eggtype == TS_DESC_PRINCE)
|
||||
if(canlay < 12)
|
||||
to_chat(src, "<span class='danger'>Insufficient strength. It takes as much effort to lay one of those as it does to lay 12 normal eggs.</span>")
|
||||
else
|
||||
if(eggtype == TS_DESC_MOTHER)
|
||||
canlay -= 12
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/mother, 1, 0)
|
||||
else if(eggtype == TS_DESC_PRINCE)
|
||||
canlay -= 12
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/prince, 1, 0)
|
||||
return
|
||||
var/numlings = 1
|
||||
if(eggtype != TS_DESC_PURPLE)
|
||||
if(canlay >= 5)
|
||||
numlings = input("How many in the batch?") as null|anything in list(1, 2, 3, 4, 5)
|
||||
else if(canlay >= 3)
|
||||
numlings = input("How many in the batch?") as null|anything in list(1, 2, 3)
|
||||
else if(canlay == 2)
|
||||
numlings = input("How many in the batch?") as null|anything in list(1, 2)
|
||||
if(eggtype == null || numlings == null)
|
||||
to_chat(src, "<span class='danger'>Cancelled.</span>")
|
||||
return
|
||||
//spider_lastspawn = world.time // don't think we actually need this, if queen is laying manually canlay controls her rate.
|
||||
canlay -= numlings
|
||||
if(eggtype == TS_DESC_RED)
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/red, numlings, 1)
|
||||
else if(eggtype == TS_DESC_GRAY)
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/gray, numlings, 1)
|
||||
else if(eggtype == TS_DESC_GREEN)
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/green, numlings, 1)
|
||||
else if(eggtype == TS_DESC_BLACK)
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/black, numlings, 1)
|
||||
else if(eggtype == TS_DESC_PURPLE)
|
||||
DoLayTerrorEggs(/mob/living/simple_animal/hostile/poison/terror_spider/purple, numlings, 0)
|
||||
else
|
||||
to_chat(src, "<span class='danger'>Unrecognized egg type.</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/queen/proc/DoQueenScreech(light_range, light_chance, camera_range, camera_chance)
|
||||
visible_message("<span class='userdanger'>\The [src] emits a bone-chilling shriek!</span>")
|
||||
for(var/obj/machinery/light/L in orange(light_range, src))
|
||||
if(L.on && prob(light_chance))
|
||||
L.broken()
|
||||
for(var/obj/machinery/camera/C in orange(camera_range, src))
|
||||
if(C.status && prob(camera_chance))
|
||||
C.toggle_cam(src, 0)
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/queen/proc/QueenFakeLings()
|
||||
if(spider_can_fakelings)
|
||||
spider_can_fakelings--
|
||||
var/numlings = 15
|
||||
for(var/i in 1 to numlings)
|
||||
var/obj/effect/spider/spiderling/terror_spiderling/S = new /obj/effect/spider/spiderling/terror_spiderling(get_turf(src))
|
||||
S.grow_as = /mob/living/simple_animal/hostile/poison/terror_spider/red
|
||||
S.stillborn = 1
|
||||
S.name = "Evil-Looking Spiderling"
|
||||
S.desc = "It moves very quickly, hisses loudly for its size... and has disproportionately large fangs. Hopefully it does not grow up..."
|
||||
if(!spider_can_fakelings)
|
||||
queenfakelings_action.Remove(src)
|
||||
else
|
||||
to_chat(src, "<span class='danger'>You have run out of uses of this ability.</span>")
|
||||
|
||||
/obj/item/projectile/terrorqueenspit
|
||||
name = "poisonous spit"
|
||||
damage = 0
|
||||
icon_state = "toxin"
|
||||
damage_type = TOX
|
||||
|
||||
/obj/item/projectile/terrorqueenspit/on_hit(mob/living/carbon/target)
|
||||
if(ismob(target))
|
||||
var/mob/living/L = target
|
||||
if(L.reagents)
|
||||
if(L.can_inject(null, 0, "chest", 0))
|
||||
L.reagents.add_reagent("terror_queen_toxin", 15)
|
||||
if(!istype(L, /mob/living/simple_animal/hostile/poison/terror_spider))
|
||||
L.adjustToxLoss(30)
|
||||
@@ -57,4 +57,4 @@
|
||||
visible_message("<span class='notice'>[src] retracts its fangs a little.</span>")
|
||||
melee_damage_lower = melee_damage_lower_rage0
|
||||
melee_damage_upper = melee_damage_upper_rage0
|
||||
..()
|
||||
..()
|
||||
@@ -0,0 +1,172 @@
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// ----------------- TERROR SPIDERS: SPIDERLINGS (USED BY GREEN, WHITE, QUEEN AND MOTHER TYPES)
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
/obj/effect/spider/spiderling/terror_spiderling
|
||||
name = "spiderling"
|
||||
desc = "A fast-moving tiny spider, prone to making aggressive hissing sounds. Hope it doesn't grow up."
|
||||
icon_state = "spiderling"
|
||||
anchored = 0
|
||||
layer = 2.75
|
||||
health = 3
|
||||
var/stillborn = 0
|
||||
faction = list("terrorspiders")
|
||||
var/spider_myqueen = null
|
||||
var/use_vents = 1
|
||||
|
||||
/obj/effect/spider/spiderling/terror_spiderling/New()
|
||||
..()
|
||||
ts_spiderling_list += src
|
||||
|
||||
/obj/effect/spider/spiderling/terror_spiderling/Destroy()
|
||||
ts_spiderling_list -= src
|
||||
return ..()
|
||||
|
||||
/obj/effect/spider/spiderling/terror_spiderling/Bump(atom/A)
|
||||
if(istype(A, /obj/structure/table))
|
||||
forceMove(A.loc)
|
||||
else if(istype(A, /obj/machinery/recharge_station))
|
||||
qdel(src)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/effect/spider/spiderling/terror_spiderling/process()
|
||||
if(travelling_in_vent)
|
||||
if(isturf(loc))
|
||||
travelling_in_vent = 0
|
||||
entry_vent = null
|
||||
else if(entry_vent)
|
||||
if(get_dist(src, entry_vent) <= 1)
|
||||
var/list/vents = list()
|
||||
for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in entry_vent.parent.other_atmosmch)
|
||||
vents.Add(temp_vent)
|
||||
if(!vents.len)
|
||||
entry_vent = null
|
||||
return
|
||||
var/obj/machinery/atmospherics/unary/vent_pump/exit_vent = pick(vents)
|
||||
if(prob(50))
|
||||
visible_message("<B>[src] scrambles into the ventillation ducts!</B>", "<span class='notice'>You hear something squeezing through the ventilation ducts.</span>")
|
||||
var/original_location = loc
|
||||
spawn(rand(20,60))
|
||||
forceMove(exit_vent)
|
||||
var/travel_time = round(get_dist(loc, exit_vent.loc) / 2)
|
||||
spawn(travel_time)
|
||||
if(!exit_vent || exit_vent.welded)
|
||||
forceMove(original_location)
|
||||
entry_vent = null
|
||||
return
|
||||
if(prob(50))
|
||||
audible_message("<span class='notice'>You hear something squeezing through the ventilation ducts.</span>")
|
||||
spawn(travel_time)
|
||||
if(!exit_vent || exit_vent.welded)
|
||||
forceMove(original_location)
|
||||
entry_vent = null
|
||||
return
|
||||
forceMove(exit_vent.loc)
|
||||
entry_vent = null
|
||||
var/area/new_area = get_area(loc)
|
||||
if(new_area)
|
||||
new_area.Entered(src)
|
||||
else if(prob(33))
|
||||
var/list/nearby = oview(10, src)
|
||||
if(nearby.len)
|
||||
var/target_atom = pick(nearby)
|
||||
walk_to(src, target_atom)
|
||||
else if(prob(10) && use_vents)
|
||||
for(var/obj/machinery/atmospherics/unary/vent_pump/v in view(7,src))
|
||||
if(!v.welded)
|
||||
entry_vent = v
|
||||
walk_to(src, entry_vent, 1)
|
||||
break
|
||||
if(isturf(loc))
|
||||
amount_grown += rand(0,2)
|
||||
if(amount_grown >= 100)
|
||||
if(stillborn)
|
||||
die()
|
||||
else
|
||||
if(!grow_as)
|
||||
grow_as = pick(/mob/living/simple_animal/hostile/poison/terror_spider/red, /mob/living/simple_animal/hostile/poison/terror_spider/gray, /mob/living/simple_animal/hostile/poison/terror_spider/green)
|
||||
var/mob/living/simple_animal/hostile/poison/terror_spider/S = new grow_as(loc)
|
||||
S.faction = faction
|
||||
S.spider_myqueen = spider_myqueen
|
||||
S.master_commander = master_commander
|
||||
qdel(src)
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// ----------------- TERROR SPIDERS: EGGS (USED BY NURSE AND QUEEN TYPES) ---------
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/DoLayTerrorEggs(lay_type, lay_number, lay_crawl)
|
||||
stop_automated_movement = 1
|
||||
var/obj/effect/spider/eggcluster/terror_eggcluster/C = new /obj/effect/spider/eggcluster/terror_eggcluster(get_turf(src))
|
||||
C.spiderling_type = lay_type
|
||||
C.spiderling_number = lay_number
|
||||
C.spiderling_ventcrawl = lay_crawl
|
||||
C.faction = faction
|
||||
C.spider_myqueen = spider_myqueen
|
||||
C.master_commander = master_commander
|
||||
if(spider_growinstantly)
|
||||
C.amount_grown = 250
|
||||
C.spider_growinstantly = 1
|
||||
spawn(10)
|
||||
stop_automated_movement = 0
|
||||
|
||||
/obj/effect/spider/eggcluster/terror_eggcluster
|
||||
name = "terror egg cluster"
|
||||
desc = "A cluster of tiny spider eggs. They pulse with a strong inner life, and appear to have sharp thorns on the sides."
|
||||
icon_state = "eggs"
|
||||
var/spider_growinstantly = 0
|
||||
faction = list("terrorspiders")
|
||||
var/spider_myqueen = null
|
||||
var/spiderling_type = null
|
||||
var/spiderling_number = 1
|
||||
var/spiderling_ventcrawl = 1
|
||||
|
||||
/obj/effect/spider/eggcluster/terror_eggcluster/New()
|
||||
..()
|
||||
ts_egg_list += src
|
||||
spawn(50)
|
||||
if(spiderling_type == /mob/living/simple_animal/hostile/poison/terror_spider/red)
|
||||
name = "red terror eggs"
|
||||
else if(spiderling_type == /mob/living/simple_animal/hostile/poison/terror_spider/gray)
|
||||
name = "gray terror eggs"
|
||||
else if(spiderling_type == /mob/living/simple_animal/hostile/poison/terror_spider/green)
|
||||
name = "green terror eggs"
|
||||
else if(spiderling_type == /mob/living/simple_animal/hostile/poison/terror_spider/black)
|
||||
name = "black terror eggs"
|
||||
else if(spiderling_type == /mob/living/simple_animal/hostile/poison/terror_spider/purple)
|
||||
name = "purple terror eggs"
|
||||
else if(spiderling_type == /mob/living/simple_animal/hostile/poison/terror_spider/white)
|
||||
name = "white terror eggs"
|
||||
else if(spiderling_type == /mob/living/simple_animal/hostile/poison/terror_spider/mother)
|
||||
name = "mother of terror eggs"
|
||||
else if(spiderling_type == /mob/living/simple_animal/hostile/poison/terror_spider/prince)
|
||||
name = "prince of terror eggs"
|
||||
else if(spiderling_type == /mob/living/simple_animal/hostile/poison/terror_spider/queen)
|
||||
name = "queen of terror eggs"
|
||||
|
||||
/obj/effect/spider/eggcluster/terror_eggcluster/Destroy()
|
||||
ts_egg_list -= src
|
||||
return ..()
|
||||
|
||||
/obj/effect/spider/eggcluster/terror_eggcluster/process()
|
||||
amount_grown += rand(0,2)
|
||||
if(amount_grown >= 100)
|
||||
var/num = spiderling_number
|
||||
for(var/i=0, i<num, i++)
|
||||
var/obj/effect/spider/spiderling/terror_spiderling/S = new /obj/effect/spider/spiderling/terror_spiderling(get_turf(src))
|
||||
if(spiderling_type)
|
||||
S.grow_as = spiderling_type
|
||||
S.use_vents = spiderling_ventcrawl
|
||||
S.faction = faction
|
||||
S.spider_myqueen = spider_myqueen
|
||||
S.master_commander = master_commander
|
||||
if(spider_growinstantly)
|
||||
S.amount_grown = 250
|
||||
var/rnum = 5 - spiderling_number
|
||||
for(var/i=0, i<rnum, i++)
|
||||
var/obj/effect/spider/spiderling/terror_spiderling/S = new /obj/effect/spider/spiderling/terror_spiderling(get_turf(src))
|
||||
S.stillborn = 1
|
||||
// every set of eggs always spawn 5 spiderlings, but most are decoys
|
||||
qdel(src)
|
||||
@@ -6,6 +6,8 @@ var/global/ts_count_alive_station = 0
|
||||
var/global/ts_death_last = 0
|
||||
var/global/ts_death_window = 9000 // 15 minutes
|
||||
var/global/list/ts_spiderlist = list()
|
||||
var/global/list/ts_egg_list = list()
|
||||
var/global/list/ts_spiderling_list = list()
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// --------------------- TERROR SPIDERS: DEFAULTS ---------------------------------
|
||||
@@ -62,6 +64,8 @@ var/global/list/ts_spiderlist = list()
|
||||
// desired: 20hp/minute unmolested, 40hp/min on food boost, assuming one tick every 2 seconds
|
||||
// 90/kill means bonus 30hp/kill regenerated over the next 1-2 minutes
|
||||
|
||||
var/degenerate = 0 // if 1, they slowly degen until they all die off. Used by high-level abilities only.
|
||||
|
||||
// Vision
|
||||
idle_vision_range = 10
|
||||
aggro_vision_range = 10
|
||||
@@ -70,8 +74,7 @@ var/global/list/ts_spiderlist = list()
|
||||
vision_type = new /datum/vision_override/nightvision/thermals/ling_augmented_eyesight
|
||||
see_invisible = 5
|
||||
|
||||
// player control by ghosts
|
||||
var/ai_playercontrol_allowingeneral = 1 // if 0, no spiders are player controllable. Default set in code, can be changed by queens.
|
||||
// AI player control by ghosts
|
||||
var/ai_playercontrol_allowtype = 1 // if 0, this specific class of spider is not player-controllable. Default set in code for each class, cannot be changed.
|
||||
|
||||
var/spider_opens_doors = 1 // all spiders can open firedoors (they have no security). 1 = can open depowered doors. 2 = can open powered doors
|
||||
@@ -81,47 +84,46 @@ var/global/list/ts_spiderlist = list()
|
||||
var/spider_placed = 0
|
||||
|
||||
// AI variables designed for use in procs
|
||||
var/atom/cocoon_target // for queen and nurse
|
||||
var/atom/movable/cocoon_target // for queen and nurse
|
||||
var/obj/machinery/atmospherics/unary/vent_pump/entry_vent // nearby vent they are going to try to get to, and enter
|
||||
var/obj/machinery/atmospherics/unary/vent_pump/exit_vent // remote vent they intend to come out of
|
||||
var/obj/machinery/atmospherics/unary/vent_pump/nest_vent // home vent, usually used by queens
|
||||
var/fed = 0
|
||||
var/travelling_in_vent = 0
|
||||
var/killcount = 0
|
||||
var/busy = 0 // leave this alone!
|
||||
var/spider_tier = TS_TIER_1 // 1 for red,gray,green. 2 for purple,black,white, 3 for prince, mother. 4 for queen, 5 for empress.
|
||||
var/spider_tier = TS_TIER_1 // 1 for red,gray,green. 2 for purple,black,white, 3 for prince, mother. 4 for queen
|
||||
var/hasdied = 0
|
||||
var/attackstep = 0
|
||||
var/attackcycles = 0
|
||||
var/spider_myqueen = null
|
||||
var/mylocation = null
|
||||
var/chasecycles = 0
|
||||
var/last_cocoon_object = 0 // leave this, changed by procs.
|
||||
var/killcount = 0
|
||||
|
||||
// Breathing, Pressure & Fire
|
||||
// - No breathing / cannot be suffocated (spiders can hold their breath, look it up)
|
||||
// - No pressure damage either - they have effectively exoskeletons
|
||||
// - HOWEVER they can be burned to death!
|
||||
// - Normal SPACE spiders should probably be immune to SPACE too, but meh, we try to leave the base spiders alone.
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
minbodytemp = 0
|
||||
maxbodytemp = 1500
|
||||
heat_damage_per_tick = 5 //amount of damage applied if animal's body temperature is higher than maxbodytemp
|
||||
|
||||
// DEBUG OPTIONS & COMMANDS
|
||||
var/spider_debug = 0
|
||||
|
||||
var/datum/action/innate/terrorspider/web/web_action
|
||||
var/datum/action/innate/terrorspider/wrap/wrap_action
|
||||
|
||||
// Breathing - require some oxygen, and no toxins, but take little damage from this requirement not being met (they can hold their breath)
|
||||
atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 1, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
unsuitable_atmos_damage = 1
|
||||
|
||||
// Temperature - can freeze in space and cook in plasma, but it takes extreme temperatures to do this.
|
||||
minbodytemp = 100
|
||||
maxbodytemp = 500
|
||||
heat_damage_per_tick = 3
|
||||
|
||||
// DEBUG OPTIONS & COMMANDS
|
||||
var/spider_growinstantly = 0 // DEBUG OPTION, DO NOT ENABLE THIS ON LIVE. IT IS USED TO TEST NEST GROWTH/SETUP AI.
|
||||
var/spider_debug = 0
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// --------------------- TERROR SPIDERS: SHARED ATTACK CODE -----------------------
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/AttackingTarget()
|
||||
if(istype(target, /mob/living/simple_animal/hostile/poison/terror_spider))
|
||||
if(isterrorspider(target))
|
||||
var/mob/living/simple_animal/hostile/poison/terror_spider/T = target
|
||||
if(T.spider_tier > spider_tier)
|
||||
visible_message("<span class='notice'>[src] bows in respect for the terrifying presence of [target].</span>")
|
||||
@@ -163,22 +165,21 @@ var/global/list/ts_spiderlist = list()
|
||||
spider_specialattack(G,can_poison)
|
||||
else
|
||||
G.attack_animal(src)
|
||||
else if(istype(target, /obj/structure/alien/resin))
|
||||
var/obj/structure/alien/resin/E = target
|
||||
do_attack_animation(E)
|
||||
E.health -= rand(melee_damage_lower, melee_damage_upper)
|
||||
E.healthcheck()
|
||||
else
|
||||
target.attack_animal(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/spider_specialattack(mob/living/carbon/human/L, var/poisonable)
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/spider_specialattack(mob/living/carbon/human/L, poisonable)
|
||||
L.attack_animal(src)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// --------------------- TERROR SPIDERS: PROC OVERRIDES ---------------------------
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/examine(mob/user)
|
||||
..()
|
||||
var/list/msgs = list()
|
||||
@@ -195,18 +196,20 @@ var/global/list/ts_spiderlist = list()
|
||||
msgs += "<span class='warning'>It has many injuries.</span>"
|
||||
else if(health > (maxHealth*0.25))
|
||||
msgs += "<span class='warning'>It is barely clinging on to life!</span>"
|
||||
if(degenerate)
|
||||
msgs += "<span class='warning'>It appears to be dying.</span>"
|
||||
else if(health < maxHealth && regen_points > regen_points_per_kill)
|
||||
msgs += "<span class='notice'>It appears to be regenerating quickly.</span>"
|
||||
if(killcount >= 1)
|
||||
msgs += "<span class='warning'>It has blood dribbling from its mouth.</span>"
|
||||
to_chat(usr,msgs.Join("<BR>"))
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/New()
|
||||
..()
|
||||
ts_spiderlist += src
|
||||
add_language("Spider Hivemind")
|
||||
add_language("Galactic Common")
|
||||
if(spider_tier >= TS_TIER_2)
|
||||
add_language("Galactic Common")
|
||||
default_language = all_languages["Spider Hivemind"]
|
||||
|
||||
web_action = new()
|
||||
@@ -215,6 +218,7 @@ var/global/list/ts_spiderlist = list()
|
||||
wrap_action.Grant(src)
|
||||
|
||||
name += " ([rand(1, 1000)])"
|
||||
real_name = name
|
||||
msg_terrorspiders("[src] has grown in [get_area(src)].")
|
||||
if(is_away_level(z))
|
||||
spider_awaymission = 1
|
||||
@@ -233,7 +237,7 @@ var/global/list/ts_spiderlist = list()
|
||||
if(ckey)
|
||||
var/image/alert_overlay = image('icons/mob/terrorspider.dmi', icon_state)
|
||||
notify_ghosts("[src] has appeared in [get_area(src)]. (already player-controlled)", source = src, alert_overlay = alert_overlay)
|
||||
else if(ai_playercontrol_allowingeneral && ai_playercontrol_allowtype)
|
||||
else if(ai_playercontrol_allowtype)
|
||||
var/image/alert_overlay = image('icons/mob/terrorspider.dmi', icon_state)
|
||||
notify_ghosts("[src] has appeared in [get_area(src)].", enter_link = "<a href=?src=[UID()];activate=1>(Click to control)</a>", source = src, alert_overlay = alert_overlay, action = NOTIFY_ATTACK)
|
||||
|
||||
@@ -243,13 +247,15 @@ var/global/list/ts_spiderlist = list()
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/Life()
|
||||
..()
|
||||
if(stat == DEAD)
|
||||
. = ..()
|
||||
if(!.) // if mob is dead
|
||||
if(prob(2))
|
||||
// 2% chance every cycle to decompose
|
||||
visible_message("<span class='notice'>\The dead body of the [src] decomposes!</span>")
|
||||
gib()
|
||||
else
|
||||
if(degenerate > 0)
|
||||
adjustToxLoss(rand(1,10))
|
||||
if(regen_points < regen_points_max)
|
||||
regen_points += regen_points_per_tick
|
||||
if((bruteloss > 0) || (fireloss > 0))
|
||||
@@ -263,9 +269,6 @@ var/global/list/ts_spiderlist = list()
|
||||
if(prob(5))
|
||||
CheckFaction()
|
||||
|
||||
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/handle_dying()
|
||||
if(!hasdied)
|
||||
hasdied = 1
|
||||
@@ -282,7 +285,6 @@ var/global/list/ts_spiderlist = list()
|
||||
handle_dying()
|
||||
..()
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/spider_special_action()
|
||||
return
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// ----------------- TERROR SPIDERS: T2 WHITE TERROR ------------------------------
|
||||
// --------------------------------------------------------------------------------
|
||||
// -------------: ROLE: stealthy reproduction
|
||||
// -------------: AI: injects a venom that makes you grow spiders in your body, then retreats
|
||||
// -------------: SPECIAL: stuns you on first attack - vulnerable to groups while it does this
|
||||
// -------------: TO FIGHT IT: blast it before it can get away
|
||||
// -------------: SPRITES FROM: FoS, http://nanotrasen.se/phpBB3/memberlist.php?mode=viewprofile&u=386
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/white
|
||||
name = "White Terror spider"
|
||||
desc = "An ominous-looking white spider, its ghostly eyes and vicious-looking fangs are the stuff of nightmares."
|
||||
spider_role_summary = "Rare, bite-and-run spider that infects hosts with spiderlings"
|
||||
|
||||
icon_state = "terror_white"
|
||||
icon_living = "terror_white"
|
||||
icon_dead = "terror_white_dead"
|
||||
maxHealth = 100
|
||||
health = 100
|
||||
melee_damage_lower = 5
|
||||
melee_damage_upper = 15
|
||||
move_to_delay = 4
|
||||
spider_tier = TS_TIER_2
|
||||
loot = list(/obj/item/clothing/accessory/medal)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/white/spider_specialattack(mob/living/carbon/human/L, poisonable)
|
||||
if(!poisonable)
|
||||
..()
|
||||
return
|
||||
var/inject_target = pick("chest","head")
|
||||
L.attack_animal(src)
|
||||
if(L.stunned || L.paralysis || L.can_inject(null,0,inject_target,0))
|
||||
if(!IsInfected(L))
|
||||
visible_message("<span class='danger'>[src] buries its long fangs deep into the [inject_target] of [L]!</span>")
|
||||
new /obj/item/organ/internal/body_egg/terror_eggs(L)
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/proc/IsInfected(mob/living/carbon/C) // Terror AI requires this
|
||||
if(C.get_int_organ(/obj/item/organ/internal/body_egg))
|
||||
return 1
|
||||
return 0
|
||||
@@ -196,3 +196,5 @@
|
||||
var/list/permanent_huds = list()
|
||||
|
||||
var/list/actions = list()
|
||||
|
||||
var/list/progressbars = null //for stacking do_after bars
|
||||
|
||||
@@ -442,9 +442,9 @@ var/list/intents = list(I_HELP,I_DISARM,I_GRAB,I_HARM)
|
||||
if(istype(subject, /mob/dead/observer))
|
||||
DM = subject
|
||||
if(check_rights(R_ADMIN|R_MOD,0,M)) // What admins see
|
||||
lname = "[keyname][(DM && DM.anonsay) ? "*" : (DM ? "" : "^")] ([name])"
|
||||
lname = "[keyname][(DM && DM.client && DM.client.prefs.ghost_anonsay) ? "*" : (DM ? "" : "^")] ([name])"
|
||||
else
|
||||
if(DM && DM.anonsay) // If the person is actually observer they have the option to be anonymous
|
||||
if(DM && DM.client && DM.client.prefs.ghost_anonsay) // If the person is actually observer they have the option to be anonymous
|
||||
lname = "Ghost of [name]"
|
||||
else if(DM) // Non-anons
|
||||
lname = "[keyname] ([name])"
|
||||
@@ -617,3 +617,6 @@ var/list/intents = list(I_HELP,I_DISARM,I_GRAB,I_HARM)
|
||||
return FALSE
|
||||
// Cast to 1/0
|
||||
return !!(client.prefs.toggles & toggleflag)
|
||||
|
||||
|
||||
#define isterrorspider(A) (istype((A), /mob/living/simple_animal/hostile/poison/terror_spider))
|
||||
@@ -241,11 +241,12 @@
|
||||
var/mob/living/carbon/human/H = new
|
||||
H.species = current_species
|
||||
H.s_tone = s_tone
|
||||
H.species.updatespeciescolor(H)
|
||||
|
||||
icobase = H.species.icobase
|
||||
H.species.updatespeciescolor(H, 0) //The mob's species wasn't set, so it's almost certainly different than the character's species at the moment. Thus, we need to be owner-insensitive.
|
||||
var/obj/item/organ/external/chest/C = H.get_organ("chest")
|
||||
icobase = C.icobase ? C.icobase : C.species.icobase
|
||||
if(H.species.bodyflags & HAS_TAIL)
|
||||
coloured_tail = H.species.tail
|
||||
coloured_tail = H.tail ? H.tail : H.species.tail
|
||||
|
||||
qdel(H)
|
||||
else
|
||||
icobase = current_species.icobase
|
||||
|
||||
@@ -130,12 +130,12 @@ var/list/alldepartments = list()
|
||||
if(href_list["dept"])
|
||||
if(authenticated)
|
||||
var/lastdestination = destination
|
||||
var/list/combineddepartments = alldepartments
|
||||
var/list/combineddepartments = alldepartments.Copy()
|
||||
if(long_range_enabled)
|
||||
combineddepartments += admin_departments
|
||||
combineddepartments += admin_departments.Copy()
|
||||
|
||||
if(emagged)
|
||||
combineddepartments += hidden_admin_departments
|
||||
combineddepartments += hidden_admin_departments.Copy()
|
||||
|
||||
destination = input(usr, "To which department?", "Choose a department", "") as null|anything in combineddepartments
|
||||
if(!destination)
|
||||
@@ -221,7 +221,7 @@ var/list/alldepartments = list()
|
||||
|
||||
flick("faxreceive", src)
|
||||
|
||||
playsound(loc, "sound/goonstation/machines/printer_dotmatrix.ogg", 50, 1)
|
||||
playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, 1)
|
||||
|
||||
// give the sprite some time to flick
|
||||
sleep(20)
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
|
||||
playsound(loc, "sound/goonstation/machines/printer_dotmatrix.ogg", 50, 1)
|
||||
playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, 1)
|
||||
for(var/i = 0, i < copies, i++)
|
||||
if(toner <= 0)
|
||||
break
|
||||
@@ -111,7 +111,7 @@
|
||||
if(!selection)
|
||||
return
|
||||
|
||||
playsound(loc, "sound/goonstation/machines/printer_dotmatrix.ogg", 50, 1)
|
||||
playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, 1)
|
||||
var/obj/item/weapon/photo/p = new /obj/item/weapon/photo (src.loc)
|
||||
p.construct(selection)
|
||||
if(p.desc == "")
|
||||
|
||||
@@ -319,7 +319,7 @@ field_generator power level display
|
||||
if(O.last_warning && temp)
|
||||
if((world.time - O.last_warning) > 50) //to stop message-spam
|
||||
temp = 0
|
||||
message_admins("A singulo exists and a containment field has failed.",1)
|
||||
message_admins("A singulo exists and a containment field has failed. Location: [get_area(src)] (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</A>)",1)
|
||||
investigate_log("has <font color='red'>failed</font> whilst a singulo exists.","singulo")
|
||||
O.last_warning = world.time
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
projectile_type = /obj/item/projectile/beam/disabler
|
||||
select_name = "disable"
|
||||
e_cost = 500
|
||||
fire_sound = "sound/weapons/taser2.ogg"
|
||||
fire_sound = 'sound/weapons/taser2.ogg'
|
||||
|
||||
/obj/item/ammo_casing/energy/plasma
|
||||
projectile_type = /obj/item/projectile/plasma
|
||||
@@ -139,7 +139,7 @@
|
||||
/obj/item/ammo_casing/energy/wormhole
|
||||
projectile_type = /obj/item/projectile/beam/wormhole
|
||||
e_cost = 0
|
||||
fire_sound = "sound/weapons/pulse3.ogg"
|
||||
fire_sound = 'sound/weapons/pulse3.ogg'
|
||||
var/obj/item/weapon/gun/energy/wormhole_projector/gun = null
|
||||
select_name = "blue"
|
||||
|
||||
@@ -193,7 +193,7 @@
|
||||
|
||||
/obj/item/ammo_casing/energy/toxplasma
|
||||
projectile_type = /obj/item/projectile/energy/toxplasma
|
||||
fire_sound = "sound/weapons/taser2.ogg"
|
||||
fire_sound = 'sound/weapons/taser2.ogg'
|
||||
select_name = "plasma dart"
|
||||
|
||||
/obj/item/ammo_casing/energy/clown
|
||||
|
||||
@@ -153,15 +153,15 @@
|
||||
var/obj/item/weapon/gun/energy/kinetic_accelerator/KA = loc
|
||||
KA.modify_projectile(BB)
|
||||
|
||||
var/turf/proj_turf = get_turf(BB)
|
||||
if(!isturf(proj_turf))
|
||||
return
|
||||
var/datum/gas_mixture/environment = proj_turf.return_air()
|
||||
var/pressure = environment.return_pressure()
|
||||
if(pressure > 50)
|
||||
BB.name = "weakened [BB.name]"
|
||||
var/obj/item/projectile/kinetic/K = BB
|
||||
K.damage *= K.pressure_decrease
|
||||
var/turf/proj_turf = get_turf(BB)
|
||||
if(!isturf(proj_turf))
|
||||
return
|
||||
var/datum/gas_mixture/environment = proj_turf.return_air()
|
||||
var/pressure = environment.return_pressure()
|
||||
if(pressure > 50)
|
||||
BB.name = "weakened [BB.name]"
|
||||
var/obj/item/projectile/kinetic/K = BB
|
||||
K.damage *= K.pressure_decrease
|
||||
|
||||
|
||||
//Projectiles
|
||||
@@ -176,7 +176,7 @@
|
||||
|
||||
var/pressure_decrease = 0.25
|
||||
var/turf_aoe = FALSE
|
||||
var/mob_aoe = 0
|
||||
var/mob_aoe = FALSE
|
||||
var/list/hit_overlays = list()
|
||||
|
||||
/obj/item/projectile/kinetic/on_range()
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
ammo_type = /obj/item/ammo_casing/magic/change
|
||||
icon_state = "staffofchange"
|
||||
item_state = "staffofchange"
|
||||
fire_sound = "sound/magic/Staff_Change.ogg"
|
||||
fire_sound = 'sound/magic/Staff_Change.ogg'
|
||||
|
||||
/obj/item/weapon/gun/magic/staff/animate
|
||||
name = "staff of animation"
|
||||
@@ -16,7 +16,7 @@
|
||||
ammo_type = /obj/item/ammo_casing/magic/animate
|
||||
icon_state = "staffofanimation"
|
||||
item_state = "staffofanimation"
|
||||
fire_sound = "sound/magic/Staff_animation.ogg"
|
||||
fire_sound = 'sound/magic/Staff_animation.ogg'
|
||||
|
||||
/obj/item/weapon/gun/magic/staff/healing
|
||||
name = "staff of healing"
|
||||
@@ -24,7 +24,7 @@
|
||||
ammo_type = /obj/item/ammo_casing/magic/heal
|
||||
icon_state = "staffofhealing"
|
||||
item_state = "staffofhealing"
|
||||
fire_sound = "sound/magic/Staff_Healing.ogg"
|
||||
fire_sound = 'sound/magic/Staff_Healing.ogg'
|
||||
|
||||
/obj/item/weapon/gun/magic/staff/healing/handle_suicide() //Stops people trying to commit suicide to heal themselves
|
||||
return
|
||||
@@ -38,7 +38,7 @@
|
||||
max_charges = 10
|
||||
recharge_rate = 2
|
||||
no_den_usage = 1
|
||||
fire_sound = "sound/magic/Staff_Chaos.ogg"
|
||||
fire_sound = 'sound/magic/Staff_Chaos.ogg'
|
||||
|
||||
/obj/item/weapon/gun/magic/staff/door
|
||||
name = "staff of door creation"
|
||||
@@ -49,7 +49,7 @@
|
||||
max_charges = 10
|
||||
recharge_rate = 2
|
||||
no_den_usage = 1
|
||||
fire_sound = "sound/magic/Staff_Door.ogg"
|
||||
fire_sound = 'sound/magic/Staff_Door.ogg'
|
||||
|
||||
/obj/item/weapon/gun/magic/staff/honk
|
||||
name = "staff of the honkmother"
|
||||
@@ -59,7 +59,7 @@
|
||||
item_state = "honker"
|
||||
max_charges = 4
|
||||
recharge_rate = 8
|
||||
fire_sound = "sound/items/airhorn.ogg"
|
||||
fire_sound = 'sound/items/airhorn.ogg'
|
||||
|
||||
/obj/item/weapon/gun/magic/staff/focus
|
||||
name = "mental focus"
|
||||
@@ -72,7 +72,7 @@
|
||||
/obj/item/weapon/gun/magic/staff/spellblade
|
||||
name = "spellblade"
|
||||
desc = "A deadly combination of laziness and boodlust, this blade allows the user to dismember their enemies without all the hard work of actually swinging the sword."
|
||||
fire_sound = "sound/magic/Fireball.ogg"
|
||||
fire_sound = 'sound/magic/Fireball.ogg'
|
||||
ammo_type = /obj/item/ammo_casing/magic/spellblade
|
||||
icon_state = "spellblade"
|
||||
item_state = "spellblade"
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
/obj/item/weapon/gun/magic/wand/death
|
||||
name = "wand of death"
|
||||
desc = "This deadly wand overwhelms the victim's body with pure energy, slaying them without fail."
|
||||
fire_sound = "sound/magic/WandoDeath.ogg"
|
||||
fire_sound = 'sound/magic/WandoDeath.ogg'
|
||||
ammo_type = /obj/item/ammo_casing/magic/death
|
||||
icon_state = "deathwand"
|
||||
max_charges = 3 //3, 2, 2, 1
|
||||
@@ -80,7 +80,7 @@
|
||||
name = "wand of resurrection"
|
||||
desc = "This wand uses healing magics to heal and revive. They are rarely utilized within the Wizard Federation for some reason."
|
||||
ammo_type = /obj/item/ammo_casing/magic/heal
|
||||
fire_sound = "sound/magic/Staff_Healing.ogg"
|
||||
fire_sound = 'sound/magic/Staff_Healing.ogg'
|
||||
icon_state = "revivewand"
|
||||
max_charges = 3 //3, 2, 2, 1
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
name = "wand of polymorph"
|
||||
desc = "This wand is attuned to chaos and will radically alter the victim's form."
|
||||
ammo_type = /obj/item/ammo_casing/magic/change
|
||||
fire_sound = "sound/magic/Staff_Change.ogg"
|
||||
fire_sound = 'sound/magic/Staff_Change.ogg'
|
||||
icon_state = "polywand"
|
||||
max_charges = 10 //10, 5, 5, 4
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
icon_state = "telewand"
|
||||
max_charges = 10 //10, 5, 5, 4
|
||||
no_den_usage = 1
|
||||
fire_sound = "sound/magic/Wand_Teleport.ogg"
|
||||
fire_sound = 'sound/magic/Wand_Teleport.ogg'
|
||||
|
||||
/obj/item/weapon/gun/magic/wand/teleport/zap_self(mob/living/user)
|
||||
do_teleport(user, user, 10)
|
||||
@@ -136,7 +136,7 @@
|
||||
name = "wand of door creation"
|
||||
desc = "This particular wand can create doors in any wall for the unscrupulous wizard who shuns teleportation magics."
|
||||
ammo_type = /obj/item/ammo_casing/magic/door
|
||||
fire_sound = "sound/magic/Staff_Door.ogg"
|
||||
fire_sound = 'sound/magic/Staff_Door.ogg'
|
||||
icon_state = "doorwand"
|
||||
max_charges = 20 //20, 10, 10, 7
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
/obj/item/weapon/gun/magic/wand/fireball
|
||||
name = "wand of fireball"
|
||||
desc = "This wand shoots scorching balls of fire that explode into destructive flames."
|
||||
fire_sound = "sound/magic/Fireball.ogg"
|
||||
fire_sound = 'sound/magic/Fireball.ogg'
|
||||
ammo_type = /obj/item/ammo_casing/magic/fireball
|
||||
icon_state = "firewand"
|
||||
max_charges = 8 //8, 4, 4, 3
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
if(!(printing))
|
||||
printing = 1
|
||||
visible_message("<span class='notice'>[src] rattles and prints out a sheet of paper.</span>")
|
||||
playsound(loc, "sound/goonstation/machines/printer_dotmatrix.ogg", 50, 1)
|
||||
playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, 1)
|
||||
var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(loc)
|
||||
P.info = "<CENTER><B>Chemical Analysis</B></CENTER><BR>"
|
||||
P.info += "<b>Time of analysis:</b> [worldtime2text(world.time)]<br><br>"
|
||||
|
||||
@@ -417,15 +417,15 @@
|
||||
var/newsize = current_size
|
||||
switch(volume)
|
||||
if(0 to 19)
|
||||
newsize = 1.25
|
||||
newsize = 1.1
|
||||
if(20 to 49)
|
||||
newsize = 1.5
|
||||
newsize = 1.2
|
||||
if(50 to 99)
|
||||
newsize = 2
|
||||
newsize = 1.25
|
||||
if(100 to 199)
|
||||
newsize = 2.5
|
||||
newsize = 1.3
|
||||
if(200 to INFINITY)
|
||||
newsize = 3.5
|
||||
newsize = 1.5
|
||||
|
||||
H.resize = newsize/current_size
|
||||
current_size = newsize
|
||||
|
||||
@@ -178,6 +178,7 @@
|
||||
..()
|
||||
|
||||
/datum/reagent/phlogiston/reaction_mob(mob/living/M, method=TOUCH, volume)
|
||||
M.adjust_fire_stacks(1)
|
||||
M.IgniteMob()
|
||||
..()
|
||||
|
||||
@@ -299,4 +300,4 @@
|
||||
if(method == TOUCH)
|
||||
M.adjust_fire_stacks(volume / 5)
|
||||
return
|
||||
..()
|
||||
..()
|
||||
|
||||
@@ -402,4 +402,4 @@ datum/chemical_reaction/flash_powder
|
||||
id = "thermite"
|
||||
result = "thermite"
|
||||
required_reagents = list("aluminum" = 1, "iron" = 1, "oxygen" = 1)
|
||||
result_amount = 3
|
||||
result_amount = 3
|
||||
|
||||
@@ -152,8 +152,8 @@
|
||||
build_path = /obj/item/ammo_box/magazine/wt550m9/wtic
|
||||
|
||||
/datum/design/mag_oldsmg/tx_mag
|
||||
name = "WT-550 Auto Gun Urnaium Magazine (4.6x30mm TX)"
|
||||
desc = "A 20 round urnaium tipped magazine for the out of date security WT-550 Auto Rifle"
|
||||
name = "WT-550 Auto Gun Uranium Magazine (4.6x30mm TX)"
|
||||
desc = "A 20 round uranium tipped magazine for the out of date security WT-550 Auto Rifle"
|
||||
id = "mag_oldsmg_tx"
|
||||
materials = list(MAT_METAL = 6000, MAT_SILVER = 600, MAT_URANIUM = 2000)
|
||||
build_path = /obj/item/ammo_box/magazine/wt550m9/wttx
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
results = get_scan_info(scanned_object)
|
||||
|
||||
src.visible_message("<b>[name]</b> states, \"Scanning complete.\"")
|
||||
playsound(loc, "sound/goonstation/machines/printer_dotmatrix.ogg", 50, 1)
|
||||
playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, 1)
|
||||
var/obj/item/weapon/paper/P = new(src.loc)
|
||||
P.name = "[src] report #[++report_num]"
|
||||
P.info = "<b>[src] analysis report #[report_num]</b><br>"
|
||||
|
||||
@@ -257,7 +257,7 @@
|
||||
|
||||
if(scanned_item)
|
||||
//create report
|
||||
playsound(loc, "sound/goonstation/machines/printer_dotmatrix.ogg", 50, 1)
|
||||
playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, 1)
|
||||
var/obj/item/weapon/paper/P = new(src)
|
||||
P.name = "[src] report #[++report_num]: [scanned_item.name]"
|
||||
P.stamped = list(/obj/item/weapon/stamp)
|
||||
|
||||
@@ -67,6 +67,26 @@
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/camera_advanced/xenobio/attackby(obj/item/O, mob/user, params)
|
||||
if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/monkeycube))
|
||||
monkeys++
|
||||
to_chat(user, "<span class='notice'>You feed [O] to [src]. It now has [monkeys] monkey cubes stored.</span>")
|
||||
user.drop_item()
|
||||
qdel(O)
|
||||
return
|
||||
else if(istype(O, /obj/item/weapon/storage/bag))
|
||||
var/obj/item/weapon/storage/P = O
|
||||
var/loaded = 0
|
||||
for(var/obj/G in P.contents)
|
||||
if(istype(G, /obj/item/weapon/reagent_containers/food/snacks/monkeycube))
|
||||
loaded = 1
|
||||
monkeys++
|
||||
qdel(G)
|
||||
if(loaded)
|
||||
to_chat(user, "<span class='notice'>You fill [src] with the monkey cubes stored in [O]. [src] now has [monkeys] monkey cubes stored.</span>")
|
||||
return
|
||||
..()
|
||||
|
||||
/datum/action/innate/camera_off/xenobio/Activate()
|
||||
if(!target || !ishuman(target))
|
||||
return
|
||||
@@ -82,9 +102,8 @@
|
||||
origin.monkey_recycle_action.Remove(C)
|
||||
//All of this stuff below could probably be a proc for all advanced cameras, only the action removal needs to be camera specific
|
||||
remote_eye.eye_user = null
|
||||
C.reset_perspective(null)
|
||||
if(C.client)
|
||||
C.client.perspective = MOB_PERSPECTIVE
|
||||
C.client.eye = src
|
||||
C.client.images -= remote_eye.user_image
|
||||
for(var/datum/camerachunk/chunk in remote_eye.visibleCameraChunks)
|
||||
C.client.images -= chunk.obscured
|
||||
@@ -109,6 +128,8 @@
|
||||
S.forceMove(remote_eye.loc)
|
||||
S.visible_message("[S] warps in!")
|
||||
X.stored_slimes -= S
|
||||
else
|
||||
to_chat(owner, "<span class='notice'>Target is not near a camera. Cannot proceed.</span>")
|
||||
|
||||
/datum/action/innate/slime_pick_up
|
||||
name = "Pick up Slime"
|
||||
@@ -132,7 +153,8 @@
|
||||
S.visible_message("[S] vanishes in a flash of light!")
|
||||
S.forceMove(X)
|
||||
X.stored_slimes += S
|
||||
|
||||
else
|
||||
to_chat(owner, "<span class='notice'>Target is not near a camera. Cannot proceed.</span>")
|
||||
|
||||
/datum/action/innate/feed_slime
|
||||
name = "Feed Slimes"
|
||||
@@ -151,7 +173,8 @@
|
||||
food.LAssailant = C
|
||||
X.monkeys --
|
||||
to_chat(owner, "[X] now has [X.monkeys] monkeys left.")
|
||||
|
||||
else
|
||||
to_chat(owner, "<span class='notice'>Target is not near a camera. Cannot proceed.</span>")
|
||||
|
||||
/datum/action/innate/monkey_recycle
|
||||
name = "Recycle Monkeys"
|
||||
@@ -168,5 +191,7 @@
|
||||
for(var/mob/living/carbon/human/M in remote_eye.loc)
|
||||
if(issmall(M) && M.stat)
|
||||
M.visible_message("[M] vanishes as they are reclaimed for recycling!")
|
||||
X.monkeys += 0.2
|
||||
X.monkeys = round(X.monkeys + 0.2,0.1)
|
||||
qdel(M)
|
||||
else
|
||||
to_chat(owner, "<span class='notice'>Target is not near a camera. Cannot proceed.</span>")
|
||||
@@ -295,7 +295,7 @@
|
||||
return
|
||||
|
||||
var/obj/item/weapon/paper/reqform = new /obj/item/weapon/paper(_loc)
|
||||
playsound(_loc, "sound/goonstation/machines/printer_thermal.ogg", 50, 1)
|
||||
playsound(_loc, 'sound/goonstation/machines/printer_thermal.ogg', 50, 1)
|
||||
reqform.name = "Requisition Form - [crates] '[object.name]' for [orderedby]"
|
||||
reqform.info += "<h3>[station_name] Supply Requisition Form</h3><hr>"
|
||||
reqform.info += "INDEX: #[shuttle_master.ordernum]<br>"
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
shuttleId = "syndicate"
|
||||
possible_destinations = "syndicate_away;syndicate_z5;syndicate_z3;syndicate_ne;syndicate_nw;syndicate_n;syndicate_se;syndicate_sw;syndicate_s"
|
||||
var/challenge = FALSE
|
||||
var/moved = FALSE
|
||||
|
||||
/obj/machinery/computer/shuttle/syndicate/recall
|
||||
name = "syndicate shuttle recall terminal"
|
||||
@@ -18,6 +19,7 @@
|
||||
if(challenge && world.time < SYNDICATE_CHALLENGE_TIMER)
|
||||
to_chat(usr, "<span class='warning'>You've issued a combat challenge to the station! You've got to give them at least [round(((SYNDICATE_CHALLENGE_TIMER - world.time) / 10) / 60)] more minutes to allow them to prepare.</span>")
|
||||
return 0
|
||||
moved = TRUE
|
||||
..()
|
||||
|
||||
/obj/machinery/computer/shuttle/syndicate/drop_pod
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
icon_state = "weapon_taser"
|
||||
projectile_type = "/obj/item/projectile/beam/disabler"
|
||||
shot_cost = 400
|
||||
fire_sound = "sound/weapons/Taser.ogg"
|
||||
fire_sound = 'sound/weapons/Taser.ogg'
|
||||
|
||||
/obj/item/device/spacepod_equipment/weaponry/burst_taser
|
||||
name = "burst taser system"
|
||||
@@ -100,7 +100,7 @@
|
||||
projectile_type = "/obj/item/projectile/beam/disabler"
|
||||
shot_cost = 1200
|
||||
shots_per = 3
|
||||
fire_sound = "sound/weapons/Taser.ogg"
|
||||
fire_sound = 'sound/weapons/Taser.ogg'
|
||||
fire_delay = 30
|
||||
|
||||
/obj/item/device/spacepod_equipment/weaponry/laser
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
var/model
|
||||
var/force_icon
|
||||
|
||||
var/icobase = 'icons/mob/human_races/r_human.dmi' // Normal icon set.
|
||||
var/deform = 'icons/mob/human_races/r_def_human.dmi' // Mutated icon set.
|
||||
|
||||
var/damage_state = "00"
|
||||
var/brute_dam = 0
|
||||
var/burn_dam = 0
|
||||
@@ -127,9 +130,12 @@
|
||||
|
||||
/obj/item/organ/external/New(var/mob/living/carbon/holder)
|
||||
..()
|
||||
if(istype(holder, /mob/living/carbon/human))
|
||||
replaced(holder)
|
||||
sync_colour_to_human(holder)
|
||||
var/mob/living/carbon/human/H = holder
|
||||
icobase = species.icobase
|
||||
deform = species.deform
|
||||
if(istype(H))
|
||||
replaced(H)
|
||||
sync_colour_to_human(H)
|
||||
spawn(1)
|
||||
get_icon()
|
||||
|
||||
|
||||
@@ -14,6 +14,16 @@ var/global/list/limb_icon_cache = list()
|
||||
overlays += organ.mob_icon
|
||||
child_icons += organ.mob_icon
|
||||
|
||||
/obj/item/organ/external/proc/change_organ_icobase(var/new_icobase, var/new_deform, var/owner_sensitive) //Change the icobase/deform of this organ. If owner_sensitive is set, that means the proc won't mess with frankenstein limbs.
|
||||
if(owner_sensitive) //This and the below statements mean that the icobase/deform will only get updated if the limb is the same species as and is owned by the mob it's attached to.
|
||||
if(species && owner.species && species.name != owner.species.name)
|
||||
return
|
||||
if(dna.unique_enzymes != owner.dna.unique_enzymes) // This isn't MY arm
|
||||
return
|
||||
|
||||
icobase = new_icobase ? new_icobase : icobase
|
||||
deform = new_deform ? new_deform : deform
|
||||
|
||||
/obj/item/organ/external/proc/sync_colour_to_human(var/mob/living/carbon/human/H)
|
||||
if(status & ORGAN_ROBOT && !(species && species.name == "Machine")) //machine people get skin color
|
||||
return
|
||||
@@ -29,6 +39,9 @@ var/global/list/limb_icon_cache = list()
|
||||
if(H.species.bodyflags & HAS_SKIN_COLOR)
|
||||
s_tone = null
|
||||
s_col = list(H.r_skin, H.g_skin, H.b_skin)
|
||||
if(H.species.bodyflags & HAS_ICON_SKIN_TONE)
|
||||
var/obj/item/organ/external/chest/C = H.get_organ("chest")
|
||||
change_organ_icobase(C.icobase, C.deform)
|
||||
|
||||
/obj/item/organ/external/proc/sync_colour_to_dna()
|
||||
if(status & ORGAN_ROBOT)
|
||||
@@ -171,10 +184,10 @@ var/global/list/limb_icon_cache = list()
|
||||
icon_file = 'icons/mob/human_races/robotic.dmi'
|
||||
else
|
||||
if(status & ORGAN_MUTATED)
|
||||
icon_file = species.deform
|
||||
icon_file = deform
|
||||
else
|
||||
// Congratulations, you are normal
|
||||
icon_file = species.icobase
|
||||
icon_file = icobase
|
||||
return list(icon_file, new_icon_state)
|
||||
|
||||
/obj/item/organ/external/chest/get_icon_state(skeletal)
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
|
||||
// Traitor-only space spider eggs
|
||||
|
||||
/obj/item/organ/internal/body_egg/spider_eggs
|
||||
name = "spider eggs"
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
@@ -34,3 +37,82 @@
|
||||
M.reagents.del_reagent("spidereggs") //purge all remaining spider eggs reagent if caught, in time.
|
||||
qdel(src) //We don't want people re-implanting these for near instant gibbings.
|
||||
return null
|
||||
|
||||
|
||||
|
||||
// Terror Spiders - white spider infection
|
||||
|
||||
/obj/item/organ/internal/body_egg/terror_eggs
|
||||
name = "terror eggs"
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "eggs"
|
||||
var/current_cycle = 0
|
||||
var/awaymission_infection = 0
|
||||
var/alternate_ending = 0
|
||||
|
||||
/obj/item/organ/internal/body_egg/terror_eggs/on_life()
|
||||
current_cycle += 1
|
||||
if(owner.health < -25)
|
||||
to_chat(owner,"<span class='notice'>You feel a strange, blissful senstation.</span>")
|
||||
owner.adjustBruteLoss(-5)
|
||||
owner.adjustFireLoss(-5)
|
||||
owner.adjustToxLoss(-5)
|
||||
// the spider eggs secrete stimulants to keep their host alive until they hatch
|
||||
switch(current_cycle)
|
||||
if(1) // immediately
|
||||
to_chat(owner,"<span class='danger'>Your spider bite wound hurts horribly! </span>")
|
||||
if(istype(get_area(owner), /area/awaycontent) || istype(get_area(owner), /area/awaymission))
|
||||
awaymission_infection = 1
|
||||
if(15) // 30 seconds... enough time for the nerve agent to kick in, the pain to be blocked, and healing to begin
|
||||
to_chat(owner,"<span class='notice'>The pain has faded, and stopped bleeding, though the skin around it has turned black.</span>")
|
||||
owner.adjustBruteLoss(-10)
|
||||
if(60) // 2 minutes... the point where the venom uses and accellerates the healing process, to feed the eggs
|
||||
to_chat(owner,"<span class='notice'>Your bite wound has completely sealed up, though the skin is still black. You feel significantly better.</span>")
|
||||
owner.adjustBruteLoss(-20)
|
||||
if(120) // 4 minutes... where the eggs are developing, and the wound is turning into a hatching site, but invisibly
|
||||
to_chat(owner,"<span class='notice'>The black flesh around your old spider bite wound has started to peel off.</span>")
|
||||
if(150) // 5 minutes... where the victim realizes something is wrong - this is not a normal wound
|
||||
to_chat(owner,"<span class='danger'>The black flesh around your spider bite wound has cracked, and started to split open!</span>")
|
||||
if(165) // 5m 30s
|
||||
to_chat(owner,"<span class='danger'>The black flesh splits open completely, revealing a cluster of small black oval shapes inside you, shapes that seem to be moving!</span>")
|
||||
if(180) // 6m
|
||||
if(awaymission_infection && is_away_level(owner.z))
|
||||
// we started in the awaymission, we ended on the station.
|
||||
// To prevent someone bringing an infection back, we're going to trigger an alternate, equally-bad result here.
|
||||
// Actually, let's make it slightly worse... just to discourage people from bringing back infections.
|
||||
alternate_ending = 1
|
||||
to_chat(owner,"<span class='danger'>The shapes extend tendrils out of your wound... no... those are legs! SPIDER LEGS! You have spiderlings growing inside you! You scratch at the wound, but it just aggrivates them - they swarm out of the wound, biting you all over!</span>")
|
||||
owner.visible_message("<span class='danger'>[owner] flails around on the floor as spiderlings erupt from their skin and swarm all over them! </span>")
|
||||
owner.Stun(20)
|
||||
owner.Weaken(20)
|
||||
// yes, this is a long stun - that's intentional. Gotta give the spiderlings time to escape.
|
||||
var/obj/effect/spider/spiderling/terror_spiderling/S1 = new(get_turf(owner))
|
||||
S1.grow_as = /mob/living/simple_animal/hostile/poison/terror_spider/red
|
||||
S1.name = "red spiderling"
|
||||
if(prob(50))
|
||||
S1.stillborn = 1
|
||||
var/obj/effect/spider/spiderling/terror_spiderling/S2 = new(get_turf(owner))
|
||||
S2.grow_as = /mob/living/simple_animal/hostile/poison/terror_spider/gray
|
||||
S2.name = "gray spiderling"
|
||||
if(prob(50))
|
||||
S2.stillborn = 1
|
||||
var/obj/effect/spider/spiderling/terror_spiderling/S3 = new(get_turf(owner))
|
||||
S3.grow_as = /mob/living/simple_animal/hostile/poison/terror_spider/green
|
||||
S3.name = "green spiderling"
|
||||
if(prob(50))
|
||||
S3.stillborn = 1
|
||||
if(alternate_ending)
|
||||
S1.stillborn = 1
|
||||
S2.stillborn = 1
|
||||
S3.stillborn = 1
|
||||
owner.gib()
|
||||
else
|
||||
owner.adjustToxLoss(rand(100,180)) // normal case, range: 100-180, average 140, almost crit (150).
|
||||
if(190) // 6m 30s
|
||||
to_chat(owner,"<span class='danger'>The spiderlings are gone. Your wound, though, looks worse than ever. Remnants of tiny spider eggs, and dead spiders, inside your flesh. Disgusting.</span>")
|
||||
qdel(src)
|
||||
|
||||
/obj/item/organ/internal/body_egg/terror_eggs/remove(var/mob/living/carbon/M, var/special = 0)
|
||||
..()
|
||||
qdel(src) // prevent people re-implanting them into others
|
||||
return null
|
||||
|
||||
@@ -433,7 +433,7 @@ var/static/regex/multispin_words = regex("like a record baby")
|
||||
//HONK
|
||||
else if((findtext(message, honk_words)))
|
||||
spawn(25)
|
||||
playsound(get_turf(owner), "sound/items/bikehorn.ogg", 300, 1)
|
||||
playsound(get_turf(owner), 'sound/items/bikehorn.ogg', 300, 1)
|
||||
if(owner.mind && owner.mind.assigned_role == "Clown")
|
||||
for(var/mob/living/carbon/C in listeners)
|
||||
C.slip(0,7 * power_multiplier)
|
||||
|
||||
Reference in New Issue
Block a user