Tg 2 11 sync (#215)
* first series of updates * datums * games folder * admin and atmosia stuffs * moar * mob updates borg riding * sprites and stuff * fixes for various things * oops. some missed fixes
This commit is contained in:
@@ -100,44 +100,6 @@
|
||||
qdel(src)
|
||||
|
||||
|
||||
//Luxury Shuttle Blockers
|
||||
|
||||
/obj/effect/forcefield/luxury_shuttle
|
||||
var/threshhold = 500
|
||||
var/list/approved_passengers = list()
|
||||
|
||||
/obj/effect/forcefield/luxury_shuttle/CanPass(atom/movable/mover, turf/target, height=0)
|
||||
if(mover in approved_passengers)
|
||||
return 1
|
||||
|
||||
if(!isliving(mover)) //No stowaways
|
||||
return 0
|
||||
|
||||
var/total_cash = 0
|
||||
var/list/counted_money = list()
|
||||
|
||||
for(var/obj/item/weapon/coin/C in mover)
|
||||
total_cash += C.value
|
||||
counted_money += C
|
||||
if(total_cash >= threshhold)
|
||||
break
|
||||
for(var/obj/item/stack/spacecash/S in mover)
|
||||
total_cash += S.value * S.amount
|
||||
counted_money += S
|
||||
if(total_cash >= threshhold)
|
||||
break
|
||||
|
||||
if(total_cash >= threshhold)
|
||||
for(var/obj/I in counted_money)
|
||||
qdel(I)
|
||||
|
||||
mover << "Thank you for your payment! Please enjoy your flight."
|
||||
approved_passengers += mover
|
||||
return 1
|
||||
else
|
||||
mover << "You don't have enough money to enter the main shuttle. You'll have to fly coach."
|
||||
return 0
|
||||
|
||||
//Shuttle Build
|
||||
|
||||
/obj/effect/shuttle_build
|
||||
@@ -149,4 +111,69 @@
|
||||
|
||||
/obj/effect/shuttle_build/New()
|
||||
SSshuttle.emergency.dock(SSshuttle.getDock("emergency_home"))
|
||||
qdel(src)
|
||||
qdel(src)
|
||||
|
||||
//Arena
|
||||
|
||||
/obj/effect/forcefield/arena_shuttle
|
||||
name = "portal"
|
||||
var/list/warp_points = list()
|
||||
|
||||
|
||||
/obj/effect/forcefield/arena_shuttle/Bumped(mob/M as mob|obj)
|
||||
if(!warp_points.len)
|
||||
warp_points = get_area_turfs(/area/shuttle/escape)
|
||||
for(var/turf/T in warp_points)
|
||||
for(var/atom/movable/AM in T)
|
||||
if(AM.density && AM.anchored)
|
||||
warp_points -= T
|
||||
break
|
||||
if(!isliving(M))
|
||||
return
|
||||
else
|
||||
var/mob/living/L = M
|
||||
if(L.pulling && istype(L.pulling, /obj/item/bodypart/head))
|
||||
L << "Your offering is accepted. You may pass."
|
||||
qdel(L.pulling)
|
||||
var/turf/LA = pick(warp_points)
|
||||
L.forceMove(LA)
|
||||
L.hallucination = 0
|
||||
L << "<span class='reallybig redtext'>The battle is won. Your bloodlust subsides.</span>"
|
||||
for(var/obj/item/weapon/twohanded/required/chainsaw/doomslayer/chainsaw in L)
|
||||
qdel(chainsaw)
|
||||
else
|
||||
L << "You are not yet worthy of passing. Drag a severed head to the barrier to be allowed entry to the hall of champions."
|
||||
|
||||
/obj/effect/landmark/shuttle_arena_safe
|
||||
name = "hall of champions"
|
||||
desc = "For the winners."
|
||||
|
||||
/obj/effect/landmark/shuttle_arena_entrance
|
||||
name = "the arena"
|
||||
desc = "A lava filled battlefield."
|
||||
|
||||
|
||||
/obj/effect/forcefield/arena_shuttle_entrance
|
||||
name = "portal"
|
||||
var/list/warp_points = list()
|
||||
|
||||
/obj/effect/forcefield/arena_shuttle_entrance/Bumped(mob/M as mob|obj)
|
||||
if(!warp_points.len)
|
||||
for(var/obj/effect/landmark/shuttle_arena_entrance/S in landmarks_list)
|
||||
warp_points |= S
|
||||
if(!isliving(M))
|
||||
return
|
||||
|
||||
var/obj/effect/landmark/LA = pick(warp_points)
|
||||
|
||||
M.forceMove(get_turf(LA))
|
||||
M << "<span class='reallybig redtext'>You're trapped in a deadly arena! To escape, you'll need to drag a severed head to the escape portals.</span>"
|
||||
spawn()
|
||||
var/obj/effect/mine/pickup/bloodbath/B = new(M)
|
||||
B.mineEffect(M)
|
||||
|
||||
|
||||
/area/shuttle_arena
|
||||
name = "arena"
|
||||
has_gravity = 1
|
||||
requires_power = 0
|
||||
|
||||
@@ -337,10 +337,40 @@
|
||||
dat += "Time limit: <a href='?_src_=holder;alter_midround_time_limit=1'>[config.midround_antag_time_check] minutes into round</a><BR>"
|
||||
dat += "Living crew limit: <a href='?_src_=holder;alter_midround_life_limit=1'>[config.midround_antag_life_check * 100]% of crew alive</a><BR>"
|
||||
dat += "If limits past: <a href='?_src_=holder;toggle_noncontinuous_behavior=1'>[ticker.mode.round_ends_with_antag_death ? "End The Round" : "Continue As Extended"]</a><BR>"
|
||||
|
||||
dat += "<BR>"
|
||||
dat += "<a href='?_src_=holder;end_round=\ref[usr]'>End Round Now</a><br>"
|
||||
dat += "<a href='?_src_=holder;delay_round_end=1'>[ticker.delay_end ? "End Round Normally" : "Delay Round End"]</a><br>"
|
||||
dat += "<a href='?_src_=holder;delay_round_end=1'>[ticker.delay_end ? "End Round Normally" : "Delay Round End"]</a>"
|
||||
var/connected_players = clients.len
|
||||
var/lobby_players = 0
|
||||
var/observers = 0
|
||||
var/observers_connected = 0
|
||||
var/living_players = 0
|
||||
var/living_players_connected = 0
|
||||
var/living_players_antagonist = 0
|
||||
var/other_players = 0
|
||||
for(var/mob/M in mob_list)
|
||||
if(M.ckey)
|
||||
if(isnewplayer(M))
|
||||
lobby_players++
|
||||
continue
|
||||
else if(M.stat != DEAD && M.mind && !isbrain(M))
|
||||
living_players++
|
||||
if(M.mind.special_role)
|
||||
living_players_antagonist++
|
||||
if(M.client)
|
||||
living_players_connected++
|
||||
else if((M.stat == DEAD )||(isobserver(M)))
|
||||
observers++
|
||||
if(M.client)
|
||||
observers_connected++
|
||||
else
|
||||
other_players++
|
||||
dat += "<BR><b><font color='blue' size='3'>Players:|[connected_players - lobby_players] ingame|[connected_players] connected|[lobby_players] lobby|</font></b>"
|
||||
dat += "<BR><b><font color='green'>Living Players:|[living_players_connected] active|[living_players - living_players_connected] disconnected|[living_players_antagonist] antagonists|</font></b>"
|
||||
dat += "<BR><b><font color='red'>Dead/Observing players:|[observers_connected] active|[observers - observers_connected] disconnected|</font></b>"
|
||||
if(other_players)
|
||||
dat += "<BR><span class='userdanger'>[other_players] players in invalid state or the statistics code is bugged!</span>"
|
||||
dat += "<BR>"
|
||||
|
||||
if(ticker.mode.syndicates.len)
|
||||
dat += "<br><table cellspacing=5><tr><td><B>Syndicates</B></td><td></td></tr>"
|
||||
for(var/datum/mind/N in ticker.mode.syndicates)
|
||||
|
||||
@@ -35,8 +35,8 @@
|
||||
if(!timestamp)
|
||||
timestamp = SQLtime()
|
||||
if(!server)
|
||||
if (config && config.server_name)
|
||||
server = config.server_name
|
||||
if (config && config.server_sql_name)
|
||||
server = config.server_sql_name
|
||||
server = sanitizeSQL(server)
|
||||
if(isnull(secret))
|
||||
switch(alert("Hide note from being viewed by players?", "Secret note?","Yes","No","Cancel"))
|
||||
@@ -332,7 +332,7 @@ proc/get_message_output(type, target_ckey)
|
||||
return
|
||||
if("watchlist entry")
|
||||
message_admins("<font color='red'><B>Notice: </B></font><font color='blue'>[key_name_admin(target_ckey)] is on the watchlist and has just connected - Reason: [text]</font>")
|
||||
// send2irc_adminless_only("Watchlist", "[key_name(target_ckey)] is on the watchlist and has just connected - Reason: [text]")
|
||||
send2irc_adminless_only("Watchlist", "[key_name(target_ckey)] is on the watchlist and has just connected - Reason: [text]")
|
||||
if("memo")
|
||||
output += "<span class='memo'>Memo by <span class='prefix'>[admin_ckey]</span> on [timestamp]"
|
||||
if(editor_ckey)
|
||||
@@ -352,8 +352,8 @@ proc/get_message_output(type, target_ckey)
|
||||
var/notetext
|
||||
notesfile >> notetext
|
||||
var/server
|
||||
if(config && config.server_name)
|
||||
server = config.server_name
|
||||
if(config && config.server_sql_name)
|
||||
server = config.server_sql_name
|
||||
var/regex/note = new("^(\\d{2}-\\w{3}-\\d{4}) \\| (.+) ~(\\w+)$", "i")
|
||||
note.Find(notetext)
|
||||
var/timestamp = note.group[1]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/proc/keywords_lookup(msg)
|
||||
/proc/keywords_lookup(msg,irc)
|
||||
|
||||
//This is a list of words which are ignored by the parser when comparing message contents for names. MUST BE IN LOWER CASE!
|
||||
var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","alien","as", "i")
|
||||
@@ -10,9 +10,11 @@
|
||||
var/list/surnames = list()
|
||||
var/list/forenames = list()
|
||||
var/list/ckeys = list()
|
||||
var/founds = ""
|
||||
for(var/mob/M in mob_list)
|
||||
var/list/indexing = list(M.real_name, M.name)
|
||||
if(M.mind) indexing += M.mind.name
|
||||
if(M.mind)
|
||||
indexing += M.mind.name
|
||||
|
||||
for(var/string in indexing)
|
||||
var/list/L = splittext(string, " ")
|
||||
@@ -52,9 +54,19 @@
|
||||
mobs_found += found
|
||||
if(!ai_found && isAI(found))
|
||||
ai_found = 1
|
||||
msg += "[original_word]<font size='1' color='black'>(<A HREF='?_src_=holder;adminmoreinfo=\ref[found]'>?</A>|<A HREF='?_src_=holder;adminplayerobservefollow=\ref[found]'>F</A>)</font> "
|
||||
var/is_antag = 0
|
||||
if(found.mind && found.mind.special_role)
|
||||
is_antag = 1
|
||||
founds += "Name: [found.name]([found.real_name]) Ckey: [found.ckey] [is_antag ? "(Antag)" : null] "
|
||||
msg += "[original_word]<font size='1' color='[is_antag ? "red" : "black"]'>(<A HREF='?_src_=holder;adminmoreinfo=\ref[found]'>?</A>|<A HREF='?_src_=holder;adminplayerobservefollow=\ref[found]'>F</A>)</font> "
|
||||
continue
|
||||
msg += "[original_word] "
|
||||
if(irc)
|
||||
if(founds == "")
|
||||
return "Search Failed"
|
||||
else
|
||||
return founds
|
||||
|
||||
return msg
|
||||
|
||||
|
||||
@@ -78,7 +90,20 @@
|
||||
return
|
||||
if(src.handle_spam_prevention(msg,MUTE_ADMINHELP))
|
||||
return
|
||||
var/ref_mob = "\ref[mob]"
|
||||
|
||||
|
||||
//clean the input msg
|
||||
if(!msg)
|
||||
return
|
||||
msg = sanitize(copytext(msg,1,MAX_MESSAGE_LEN))
|
||||
if(!msg) return
|
||||
var/original_msg = msg
|
||||
|
||||
msg = keywords_lookup(msg)
|
||||
|
||||
if(!mob)
|
||||
return //this doesn't happen
|
||||
|
||||
var/ref_client = "\ref[src]"
|
||||
for(var/datum/adminticket/T in admintickets)
|
||||
if(T.permckey == src.ckey && T.resolved == "No")
|
||||
@@ -87,7 +112,7 @@
|
||||
if(T.admin == "N/A")
|
||||
usr << "<b>Due to the fact your Adminhelp had no assigned admin, admins have been pinged.</b>"
|
||||
message_admins("[src.ckey] has bumped their adminhelp #[T.ID], still no assigned admin!")
|
||||
msg = "<span class='adminnotice'><b><font color=red>HELP: </font><A HREF='?priv_msg=[ckey];ahelp_reply=1'>[key_name(src)]</A> [ADMIN_QUE(mob)] [ADMIN_PP(mob)] [ADMIN_VV(mob)] [ADMIN_SM(mob)] [ADMIN_FLW(mob)] [ADMIN_TP(mob)] (<A HREF='?_src_=holder;rejectadminhelp=[ref_client]'>REJT</A>) (<A HREF='?_src_=holder;icissue=[ref_client]'>IC</A>) (<A HREF='?_src_=holder;resolve=[T.ID]'>R</a>):</b> [msg]</span>"
|
||||
msg = "<span class='adminnotice'><b><font color=red>HELP: </font><A HREF='?priv_msg=[ckey];ahelp_reply=1'>[key_name(src)]</A> [ADMIN_QUE(mob)] [ADMIN_PP(mob)] [ADMIN_VV(mob)] [ADMIN_SM(mob)] [ADMIN_FLW(mob)] [ADMIN_TP(mob)] (<A HREF='?_src_=holder;rejectadminhelp=[ref_client]'>REJT</A>) (<A HREF='?_src_=holder;icissue=[ref_client]'>IC</A>) (<A HREF='?_src_=ticket;resolve=[T.ID]'>R</a>):</b> [msg]</span>"
|
||||
for(var/client/X in admins)
|
||||
if(X.prefs.toggles & SOUND_ADMINHELP)
|
||||
X << 'sound/effects/adminhelp.ogg'
|
||||
@@ -104,27 +129,10 @@
|
||||
src.verbs -= /client/verb/adminhelp
|
||||
adminhelptimerid = addtimer(CALLBACK(src, .proc/giveadminhelpverb), 1200, TIMER_STOPPABLE)
|
||||
|
||||
//clean the input msg
|
||||
if(!msg) return
|
||||
msg = sanitize(copytext(msg,1,MAX_MESSAGE_LEN))
|
||||
if(!msg) return
|
||||
var/original_msg = msg
|
||||
|
||||
msg = keywords_lookup(msg)
|
||||
|
||||
if(!mob) return //this doesn't happen
|
||||
for(var/datum/adminticket/T in admintickets)
|
||||
msg = "<span class='adminnotice'><b><font color=red>HELP: </font><A HREF='?priv_msg=[ckey];ahelp_reply=1'>[key_name(src)]</A> [ADMIN_QUE(mob)] [ADMIN_PP(mob)] [ADMIN_VV(mob)] [ADMIN_SM(mob)] [ADMIN_FLW(mob)] [ADMIN_TP(mob)] (<A HREF='?_src_=holder;rejectadminhelp=[ref_client]'>REJT</A>) (<A HREF='?_src_=holder;icissue=[ref_client]'>IC</A>) (<A HREF='?_src_=ticket;resolve=[T.ID]'>R</a>):</b> [msg]</span>"
|
||||
|
||||
createticket(src, msg, src.ckey, mob)
|
||||
|
||||
var/datum/adminticket/ticket
|
||||
|
||||
for(var/datum/adminticket/T in admintickets)
|
||||
if(T.permckey == src.ckey)
|
||||
ticket = T
|
||||
|
||||
msg = "<span class='adminnotice'><b><font color=red>ADMINHELP: </font><A HREF='?priv_msg=[ckey];ahelp_reply=1'>[key_name(src)]</A> (<A HREF='?_src_=holder;adminmoreinfo=[ref_mob]'>?</A>) (<A HREF='?_src_=holder;adminplayeropts=[ref_mob]'>PP</A>) (<A HREF='?_src_=vars;Vars=[ref_mob]'>VV</A>) (<A HREF='?_src_=holder;subtlemessage=[ref_mob]'>SM</A>) (<A HREF='?_src_=holder;traitor=[ref_mob]'>TP</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=[ref_mob]'>FLW</A>) (<a href='?src=\ref[ticket];resolve=\ref[ticket]'>R</a>):</b> [msg]</span>"
|
||||
|
||||
|
||||
//send this msg to all admins
|
||||
|
||||
for(var/client/X in admins)
|
||||
@@ -138,88 +146,72 @@
|
||||
src << "<span class='adminnotice'>PM to-<b>Admins</b>: [original_msg]</span>"
|
||||
|
||||
//send it to irc if nobody is on and tell us how many were on
|
||||
var/admin_number_present = send2irc_admin_notice_handler("adminhelp", ckey, original_msg)
|
||||
log_admin("ADMINHELP: [key_name(src)]: [original_msg] - heard by [admin_number_present] non-AFK admins who have +BAN.")
|
||||
var/admin_number_present = send2admindiscord(ckey,original_msg)
|
||||
log_admin("HELP: [key_name(src)]: [original_msg] - heard by [admin_number_present] non-AFK admins who have +BAN.")
|
||||
if(admin_number_present <= 0)
|
||||
src << "<span class='notice'>No active admins are online, your adminhelp was sent to the admin irc.</span>"
|
||||
feedback_add_details("admin_verb","AH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
return
|
||||
|
||||
/proc/calculate_admins(type, requiredflags = R_BAN)
|
||||
var/admin_number_total = 0 //Total number of admins
|
||||
var/admin_number_afk = 0 //Holds the number of admins who are afk
|
||||
var/admin_number_ignored = 0 //Holds the number of admins without +BAN (so admins who are not really admins)
|
||||
var/admin_number_decrease = 0 //Holds the number of admins with are afk, ignored or both
|
||||
/proc/get_admin_counts(requiredflags = R_BAN)
|
||||
. = list("total" = list(), "noflags" = list(), "afk" = list(), "stealth" = list(), "present" = list())
|
||||
for(var/client/X in admins)
|
||||
admin_number_total++;
|
||||
var/invalid = 0
|
||||
.["total"] += X
|
||||
if(requiredflags != 0 && !check_rights_for(X, requiredflags))
|
||||
admin_number_ignored++
|
||||
invalid = 1
|
||||
if(X.is_afk())
|
||||
admin_number_afk++
|
||||
invalid = 1
|
||||
if(X.holder.fakekey)
|
||||
admin_number_ignored++
|
||||
invalid = 1
|
||||
if(invalid)
|
||||
admin_number_decrease++
|
||||
switch(type)
|
||||
if("ignored")
|
||||
return admin_number_ignored
|
||||
if("total")
|
||||
return admin_number_total
|
||||
if("away")
|
||||
return admin_number_afk
|
||||
if("present")
|
||||
return admin_number_total - admin_number_decrease
|
||||
return 0
|
||||
.["noflags"] += X
|
||||
else if(X.is_afk())
|
||||
.["afk"] += X
|
||||
else if(X.holder.fakekey)
|
||||
.["stealth"] += X
|
||||
else
|
||||
.["present"] += X
|
||||
|
||||
/proc/send2irc_adminless_only(source, msg, requiredflags = R_BAN)
|
||||
var/list/adm = get_admin_counts(requiredflags)
|
||||
var/list/activemins = adm["present"]
|
||||
. = activemins.len
|
||||
if(. <= 0)
|
||||
var/final = ""
|
||||
var/list/afkmins = adm["afk"]
|
||||
var/list/stealthmins = adm["stealth"]
|
||||
var/list/powerlessmins = adm["noflags"]
|
||||
var/list/allmins = adm["total"]
|
||||
if(!afkmins.len && !stealthmins.len && !powerlessmins.len)
|
||||
final = "[msg] - No admins online"
|
||||
else
|
||||
final = "[msg] - All admins stealthed\[[english_list(stealthmins)]\], AFK\[[english_list(afkmins)]\], or lacks +BAN\[[english_list(powerlessmins)]\]! Total: [allmins.len] "
|
||||
send2irc(source,final)
|
||||
send2admindiscord(source,final)
|
||||
|
||||
/proc/send2irc_admin_notice_handler(type, source, msg)
|
||||
var/afk_admins = calculate_admins("away")
|
||||
var/total_admins = calculate_admins("total")
|
||||
var/ignored_admins = calculate_admins("ignored")
|
||||
var/admin_number_present = calculate_admins("present") //Number of admins who are neither afk nor invalid
|
||||
var/irc_message_afk = "[msg] - All admins AFK ([afk_admins]/[total_admins]) or skipped ([ignored_admins]/[total_admins])"
|
||||
var/irc_message_normal = "[msg] - heard by [admin_number_present] non-AFK admins who have +BAN."
|
||||
var/irc_message_adminless = "[msg] - No admins online"
|
||||
|
||||
switch(type)
|
||||
if("adminhelp")
|
||||
if(config.announce_adminhelps)
|
||||
send2irc(source, irc_message_normal)
|
||||
else
|
||||
if(admin_number_present <= 0)
|
||||
if(!afk_admins && !ignored_admins)
|
||||
send2admindiscord(source, irc_message_adminless)
|
||||
else if(afk_admins >= 1)
|
||||
send2admindiscord(source, irc_message_afk)
|
||||
else
|
||||
send2admindiscord(source, irc_message_normal)
|
||||
if("watchlist")
|
||||
if(config.announce_watchlist)
|
||||
send2irc(source, irc_message_normal)
|
||||
else
|
||||
if(admin_number_present <= 0)
|
||||
if(!afk_admins && !ignored_admins)
|
||||
send2admindiscord(source, irc_message_adminless)
|
||||
else if(afk_admins >= 1)
|
||||
send2admindiscord(source, irc_message_afk)
|
||||
else
|
||||
send2admindiscord(source, irc_message_normal)
|
||||
if("new_player")
|
||||
if(config.irc_first_connection_alert)
|
||||
send2irc(source, irc_message_normal)
|
||||
else
|
||||
if(admin_number_present <= 0)
|
||||
if(!afk_admins && !ignored_admins)
|
||||
send2admindiscord(source, irc_message_adminless)
|
||||
else if(afk_admins >= 1)
|
||||
send2admindiscord(source, irc_message_afk)
|
||||
else
|
||||
send2admindiscord(source, irc_message_normal)
|
||||
return admin_number_present
|
||||
|
||||
/proc/send2irc(msg,msg2)
|
||||
if(config.useircbot)
|
||||
shell("python nudge.py [msg] \"[msg2]\"")
|
||||
return
|
||||
shell("python nudge.py [msg] [msg2]")
|
||||
return
|
||||
|
||||
/proc/send2otherserver(source,msg,type = "Ahelp")
|
||||
if(global.cross_allowed)
|
||||
var/list/message = list()
|
||||
message["message_sender"] = source
|
||||
message["message"] = msg
|
||||
message["source"] = "([config.cross_name])"
|
||||
message["key"] = global.comms_key
|
||||
message["crossmessage"] = type
|
||||
|
||||
world.Export("[global.cross_address]?[list2params(message)]")
|
||||
|
||||
|
||||
/proc/ircadminwho()
|
||||
var/list/message = list("Admins: ")
|
||||
var/list/admin_keys = list()
|
||||
for(var/adm in admins)
|
||||
var/client/C = adm
|
||||
admin_keys += "[C][C.holder.fakekey ? "(Stealth)" : ""][C.is_afk() ? "(AFK)" : ""]"
|
||||
|
||||
for(var/admin in admin_keys)
|
||||
if(LAZYLEN(admin_keys) > 1)
|
||||
message += ", [admin]"
|
||||
else
|
||||
message += "[admin]"
|
||||
|
||||
return jointext(message, "")
|
||||
@@ -1,3 +1,5 @@
|
||||
#define IRCREPLYCOUNT 2
|
||||
|
||||
//allows right clicking mobs to send an admin PM to their client, forwards the selected mob's client to cmd_admin_pm
|
||||
/client/proc/cmd_admin_pm_context(mob/M in mob_list)
|
||||
set category = null
|
||||
@@ -5,7 +7,8 @@
|
||||
if(!holder)
|
||||
src << "<font color='red'>Error: Admin-PM-Context: Only administrators may use this command.</font>"
|
||||
return
|
||||
if( !ismob(M) || !M.client ) return
|
||||
if( !ismob(M) || !M.client )
|
||||
return
|
||||
cmd_admin_pm(M.client,null)
|
||||
feedback_add_details("admin_verb","APMM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
@@ -19,16 +22,15 @@
|
||||
var/list/client/targets[0]
|
||||
for(var/client/T)
|
||||
if(T.mob)
|
||||
if(istype(T.mob, /mob/new_player))
|
||||
if(isnewplayer(T.mob))
|
||||
targets["(New Player) - [T]"] = T
|
||||
else if(istype(T.mob, /mob/dead/observer))
|
||||
else if(isobserver(T.mob))
|
||||
targets["[T.mob.name](Ghost) - [T]"] = T
|
||||
else
|
||||
targets["[T.mob.real_name](as [T.mob.name]) - [T]"] = T
|
||||
else
|
||||
targets["(No Mob) - [T]"] = T
|
||||
var/list/sorted = sortList(targets)
|
||||
var/target = input(src,"To whom shall we send a message?","Admin PM",null) in sorted|null
|
||||
var/target = input(src,"To whom shall we send a message?","Admin PM",null) as null|anything in sortList(targets)
|
||||
cmd_admin_pm(targets[target],null)
|
||||
feedback_add_details("admin_verb","APM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
@@ -44,7 +46,8 @@
|
||||
else if(istype(whom,/client))
|
||||
C = whom
|
||||
if(!C)
|
||||
if(holder) src << "<font color='red'>Error: Admin-PM: Client not found.</font>"
|
||||
if(holder)
|
||||
src << "<font color='red'>Error: Admin-PM: Client not found.</font>"
|
||||
return
|
||||
|
||||
var/datum/adminticket/ticket
|
||||
@@ -205,4 +208,51 @@
|
||||
//we don't use message_admins here because the sender/receiver might get it too
|
||||
for(var/client/X in admins)
|
||||
if(X.key!=key && X.key!=C.key) //check client/X is an admin and isn't the sender or recipient
|
||||
X << "<B><font color='blue'>PM: [key_name(src, X, 0)]->[key_name(C, X, 0)]:</B> \blue [keywordparsedmsg]</font>" //inform X
|
||||
X << "<B><font color='blue'>PM: [key_name(src, X, 0)]->[key_name(C, X, 0)]:</B> \blue [keywordparsedmsg]</font>" //inform X
|
||||
|
||||
/proc/IrcPm(target,msg,sender)
|
||||
|
||||
var/client/C = directory[target]
|
||||
|
||||
var/static/stealthkey
|
||||
var/adminname = config.showircname ? "[sender](IRC)" : "Administrator"
|
||||
|
||||
if(!C)
|
||||
return "No client"
|
||||
|
||||
if(!stealthkey)
|
||||
stealthkey = GenIrcStealthKey()
|
||||
|
||||
msg = sanitize(copytext(msg,1,MAX_MESSAGE_LEN))
|
||||
if(!msg)
|
||||
return "No message"
|
||||
|
||||
message_admins("IRC message from [sender] to [key_name_admin(C)] : [msg]")
|
||||
log_admin("IRC PM: [sender] -> [key_name(C)] : [msg]")
|
||||
msg = emoji_parse(msg)
|
||||
|
||||
C << "<font color='red' size='4'><b>-- Administrator private message --</b></font>"
|
||||
C << "<font color='red'>Admin PM from-<b><a href='?priv_msg=[stealthkey]'>[adminname]</A></b>: [msg]</font>"
|
||||
C << "<font color='red'><i>Click on the administrator's name to reply.</i></font>"
|
||||
window_flash(C)
|
||||
//always play non-admin recipients the adminhelp sound
|
||||
C << 'sound/effects/adminhelp.ogg'
|
||||
|
||||
C.ircreplyamount = IRCREPLYCOUNT
|
||||
|
||||
return "Message Successful"
|
||||
|
||||
/proc/GenIrcStealthKey()
|
||||
var/num = (rand(0,1000))
|
||||
var/i = 0
|
||||
while(i == 0)
|
||||
i = 1
|
||||
for(var/P in stealthminID)
|
||||
if(num == stealthminID[P])
|
||||
num++
|
||||
i = 0
|
||||
var/stealth = "@[num2text(num)]"
|
||||
stealthminID["IRCKEY"] = stealth
|
||||
return stealth
|
||||
|
||||
#undef IRCREPLYCOUNT
|
||||
@@ -118,16 +118,19 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
|
||||
if(isnull(argnum))
|
||||
return
|
||||
|
||||
var/list/lst = list()
|
||||
|
||||
. = list()
|
||||
var/list/named_args = list()
|
||||
while(argnum--)
|
||||
var/named_arg = input("Leave blank for positional argument. Positional arguments will be considered as if they were added first.", "Named argument") as text|null
|
||||
var/value = vv_get_value(restricted_classes = list(VV_RESTORE_DEFAULT))
|
||||
if (!value["class"])
|
||||
return
|
||||
lst += value["value"]
|
||||
|
||||
return lst
|
||||
|
||||
if(named_arg)
|
||||
named_args[named_arg] = value["value"]
|
||||
else
|
||||
. += value["value"]
|
||||
if(LAZYLEN(named_args))
|
||||
. += named_args
|
||||
|
||||
/client/proc/get_callproc_returnval(returnval,procname)
|
||||
. = ""
|
||||
|
||||
@@ -35,11 +35,11 @@
|
||||
|
||||
var/list/atmos_overlay_types //gas IDs of current active gas overlays
|
||||
|
||||
/turf/open/New()
|
||||
..()
|
||||
/turf/open/Initialize()
|
||||
if(!blocks_air)
|
||||
air = new
|
||||
air.copy_from_turf(src)
|
||||
..()
|
||||
|
||||
/turf/open/Destroy()
|
||||
if(active_hotspot)
|
||||
@@ -113,11 +113,12 @@
|
||||
|
||||
/turf/open/proc/tile_graphic()
|
||||
. = new /list
|
||||
var/list/gases = air.gases
|
||||
for(var/id in gases)
|
||||
var/gas = gases[id]
|
||||
if(gas[GAS_META][META_GAS_OVERLAY] && gas[MOLES] > gas[GAS_META][META_GAS_MOLES_VISIBLE])
|
||||
. += gas[GAS_META][META_GAS_OVERLAY]
|
||||
if(air)
|
||||
var/list/gases = air.gases
|
||||
for(var/id in gases)
|
||||
var/gas = gases[id]
|
||||
if(gas[GAS_META][META_GAS_OVERLAY] && gas[MOLES] > gas[GAS_META][META_GAS_MOLES_VISIBLE])
|
||||
. += gas[GAS_META][META_GAS_OVERLAY]
|
||||
|
||||
/////////////////////////////SIMULATION///////////////////////////////////
|
||||
|
||||
|
||||
@@ -99,26 +99,28 @@
|
||||
flags_cover = MASKCOVERSEYES
|
||||
resistance_flags = FLAMMABLE
|
||||
actions_types = list(/datum/action/item_action/adjust)
|
||||
|
||||
|
||||
/obj/item/clothing/mask/gas/mime/attack_self(mob/user)
|
||||
cycle_mask(user)
|
||||
/obj/item/clothing/mask/gas/mime/ui_action_click(mob/user)
|
||||
if(!istype(user) || user.incapacitated())
|
||||
return
|
||||
|
||||
/obj/item/clothing/mask/gas/mime/proc/cycle_mask(mob/user)
|
||||
switch(icon_state)
|
||||
if("mime")
|
||||
icon_state = "sadmime"
|
||||
if("sadmime")
|
||||
icon_state = "scaredmime"
|
||||
if("scaredmime")
|
||||
icon_state = "sexymime"
|
||||
if("sexymime")
|
||||
icon_state = "mime"
|
||||
user.update_inv_wear_mask()
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon()
|
||||
user << "<span class='notice'>You adjust your mask to portray a different emotion.</span>"
|
||||
return 1
|
||||
var/list/options = list()
|
||||
options["Blanc"] = "mime"
|
||||
options["Triste"] = "sadmime"
|
||||
options["Effrayé"] = "scaredmime"
|
||||
options["Excité"] ="sexymime"
|
||||
|
||||
var/choice = input(user,"To what form do you wish to Morph this mask?","Morph Mask") in options
|
||||
|
||||
if(src && choice && !user.incapacitated() && in_range(user,src))
|
||||
icon_state = options[choice]
|
||||
user.update_inv_wear_mask()
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon()
|
||||
user << "<span class='notice'>Your Mime Mask has now morphed into [choice]!</span>"
|
||||
return 1
|
||||
|
||||
/obj/item/clothing/mask/gas/monkeymask
|
||||
name = "monkey mask"
|
||||
@@ -170,6 +172,7 @@
|
||||
resistance_flags = FLAMMABLE
|
||||
obj_integrity = 100
|
||||
max_integrity = 100
|
||||
actions_types = list(/datum/action/item_action/adjust)
|
||||
dog_fashion = null
|
||||
|
||||
|
||||
@@ -186,7 +189,6 @@ obj/item/clothing/mask/gas/tiki_mask/ui_action_click(mob/user)
|
||||
|
||||
if(src && choice && !M.stat && in_range(M,src))
|
||||
icon_state = options[choice]
|
||||
item_state = options[choice]
|
||||
user.update_inv_wear_mask()
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
|
||||
@@ -268,6 +268,11 @@
|
||||
/obj/item/clothing/suit/armor/reactive/tesla
|
||||
name = "reactive tesla armor"
|
||||
desc = "An experimental suit of armor with sensitive detectors hooked up to a huge capacitor grid, with emitters strutting out of it. Zap."
|
||||
siemens_coefficient = -1
|
||||
var/tesla_power = 25000
|
||||
var/tesla_range = 20
|
||||
var/tesla_boom = FALSE
|
||||
var/tesla_stun = FALSE
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/tesla/hit_reaction(mob/living/carbon/human/owner, attack_text)
|
||||
if(!active)
|
||||
@@ -277,15 +282,10 @@
|
||||
var/datum/effect_system/spark_spread/sparks = new /datum/effect_system/spark_spread
|
||||
sparks.set_up(1, 1, src)
|
||||
sparks.start()
|
||||
owner.visible_message("<span class='danger'>The tesla capacitors on [owner]'s reactive telsa armor are still recharging! The armor merely emits some sparks.</spawn>")
|
||||
owner.visible_message("<span class='danger'>The tesla capacitors on [owner]'s reactive tesla armor are still recharging! The armor merely emits some sparks.</spawn>")
|
||||
return
|
||||
owner.visible_message("<span class='danger'>The [src] blocks the [attack_text], sending out arcs of lightning!</span>")
|
||||
for(var/mob/living/M in view(6, owner))
|
||||
if(M == owner)
|
||||
continue
|
||||
owner.Beam(M,icon_state="lightning[rand(1, 12)]",time=5)
|
||||
M.adjustFireLoss(25)
|
||||
playsound(M, 'sound/machines/defib_zap.ogg', 50, 1, -1)
|
||||
tesla_zap(owner,tesla_range,tesla_power,tesla_boom, tesla_stun)
|
||||
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
|
||||
return 1
|
||||
|
||||
|
||||
@@ -3,9 +3,12 @@
|
||||
typepath = /datum/round_event/ghost_role/sentience
|
||||
weight = 10
|
||||
|
||||
|
||||
/datum/round_event/ghost_role/sentience
|
||||
minimum_required = 1
|
||||
role_name = "random animal"
|
||||
var/animals = 1
|
||||
var/one = "one"
|
||||
|
||||
/datum/round_event/ghost_role/sentience/start()
|
||||
var/sentience_report = "<font size=3><b>[command_name()] Medium-Priority Update</b></font>"
|
||||
@@ -14,7 +17,7 @@
|
||||
var/pets = pick("animals/bots", "bots/animals", "pets", "simple animals", "lesser lifeforms", "\[REDACTED\]")
|
||||
var/strength = pick("human", "moderate", "lizard", "security", "command", "clown", "low", "very low", "\[REDACTED\]")
|
||||
|
||||
sentience_report += "<br><br>Based on [data], we believe that one of the station's [pets] has developed [strength] level intelligence, and the ability to communicate."
|
||||
sentience_report += "<br><br>Based on [data], we believe that [one] of the station's [pets] has developed [strength] level intelligence, and the ability to communicate."
|
||||
|
||||
print_command_report(sentience_report, "Classified [command_name()] Update")
|
||||
priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/AI/commandreport.ogg')
|
||||
@@ -36,25 +39,40 @@
|
||||
|
||||
if(!potential.len)
|
||||
return WAITING_FOR_SOMETHING
|
||||
var/mob/living/simple_animal/SA = pick(potential)
|
||||
if(!candidates.len)
|
||||
return NOT_ENOUGH_PLAYERS
|
||||
var/mob/dead/observer/SG = pick(candidates)
|
||||
|
||||
SA.key = SG.key
|
||||
SA.languages_spoken |= HUMAN
|
||||
SA.languages_understood |= HUMAN
|
||||
SA.sentience_act()
|
||||
var/spawned_animals = 0
|
||||
while(spawned_animals < animals && candidates.len && potential.len)
|
||||
var/mob/living/simple_animal/SA = pick_n_take(potential)
|
||||
var/mob/dead/observer/SG = pick_n_take(candidates)
|
||||
|
||||
SA.maxHealth = max(SA.maxHealth, 200)
|
||||
SA.health = SA.maxHealth
|
||||
SA.del_on_death = FALSE
|
||||
spawned_animals++
|
||||
|
||||
spawned_mobs += SA
|
||||
SA.key = SG.key
|
||||
SA.languages_spoken |= HUMAN
|
||||
SA.languages_understood |= HUMAN
|
||||
SA.sentience_act()
|
||||
|
||||
SA << "<span class='userdanger'>Hello world!</span>"
|
||||
SA << "<span class='warning'>Due to freak radiation and/or chemicals \
|
||||
and/or lucky chance, you have gained human level intelligence \
|
||||
and the ability to speak and understand human language!</span>"
|
||||
SA.maxHealth = max(SA.maxHealth, 200)
|
||||
SA.health = SA.maxHealth
|
||||
SA.del_on_death = FALSE
|
||||
|
||||
spawned_mobs += SA
|
||||
|
||||
SA << "<span class='userdanger'>Hello world!</span>"
|
||||
SA << "<span class='warning'>Due to freak radiation and/or chemicals \
|
||||
and/or lucky chance, you have gained human level intelligence \
|
||||
and the ability to speak and understand human language!</span>"
|
||||
|
||||
return SUCCESSFUL_SPAWN
|
||||
|
||||
/datum/round_event_control/sentience/all
|
||||
name = "Station-wide Human-level Intelligence"
|
||||
typepath = /datum/round_event/ghost_role/sentience/all
|
||||
weight = 0
|
||||
|
||||
/datum/round_event/ghost_role/sentience/all
|
||||
one = "all"
|
||||
animals = INFINITY // as many as there are ghosts and animals
|
||||
// cockroach pride, station wide
|
||||
|
||||
@@ -124,6 +124,12 @@
|
||||
list_reagents = list("sodiumchloride" = 20)
|
||||
possible_states = list()
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/condiment/saltshaker/on_reagent_change()
|
||||
if(reagents.reagent_list.len == 0)
|
||||
icon_state = "emptyshaker"
|
||||
else
|
||||
icon_state = "saltshakersmall"
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/condiment/saltshaker/suicide_act(mob/user)
|
||||
user.visible_message("<span class='suicide'>[user] begins to swap forms with the salt shaker! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
var/newname = "[name]"
|
||||
@@ -156,6 +162,12 @@
|
||||
list_reagents = list("blackpepper" = 20)
|
||||
possible_states = list()
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/condiment/peppermill/on_reagent_change()
|
||||
if(reagents.reagent_list.len == 0)
|
||||
icon_state = "emptyshaker"
|
||||
else
|
||||
icon_state = "peppermillsmall"
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/condiment/milk
|
||||
name = "space milk"
|
||||
desc = "It's milk. White and nutritious goodness!"
|
||||
|
||||
@@ -18,6 +18,15 @@ insert ascii eagle on american flag background here
|
||||
container_type = OPENCONTAINER
|
||||
var/obj/item/frying = null //What's being fried RIGHT NOW?
|
||||
var/cook_time = 0
|
||||
var/static/list/blacklisted_items = typecacheof(list(
|
||||
/obj/item/weapon/screwdriver,
|
||||
/obj/item/weapon/crowbar,
|
||||
/obj/item/weapon/wrench,
|
||||
/obj/item/weapon/wirecutters,
|
||||
/obj/item/device/multitool,
|
||||
/obj/item/weapon/weldingtool,
|
||||
/obj/item/weapon/reagent_containers/glass,
|
||||
/obj/item/weapon/storage/part_replacer))
|
||||
|
||||
/obj/item/weapon/circuitboard/machine/deep_fryer
|
||||
name = "circuit board (Deep Fryer)"
|
||||
@@ -46,8 +55,16 @@ insert ascii eagle on american flag background here
|
||||
if(istype(I, /obj/item/weapon/reagent_containers/food/snacks/deepfryholder))
|
||||
user << "<span class='userdanger'>Your cooking skills are not up to the legendary Doublefry technique.</span>"
|
||||
return
|
||||
if(default_unfasten_wrench(user, I))
|
||||
return
|
||||
else if(exchange_parts(user, I))
|
||||
return
|
||||
else if(default_deconstruction_screwdriver(user, "fryer_off", "fryer_off" ,I)) //where's the open maint panel icon?!
|
||||
return
|
||||
else
|
||||
if(user.drop_item() && !frying)
|
||||
if(is_type_in_typecache(I, blacklisted_items))
|
||||
. = ..()
|
||||
else if(user.drop_item() && !frying)
|
||||
user << "<span class='notice'>You put [I] into [src].</span>"
|
||||
frying = I
|
||||
frying.forceMove(src)
|
||||
@@ -78,6 +95,7 @@ insert ascii eagle on american flag background here
|
||||
S.overlays = frying.overlays
|
||||
S.icon_state = frying.icon_state
|
||||
S.desc = frying.desc
|
||||
S.w_class = frying.w_class
|
||||
reagents.trans_to(S, 2*(cook_time/15))
|
||||
switch(cook_time)
|
||||
if(0 to 15)
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
if(V == "air")
|
||||
var/turf/open/O1 = B
|
||||
var/turf/open/O2 = T
|
||||
O1.air.copy_from(O2.air)
|
||||
O1.air.copy_from(O2.return_air())
|
||||
continue
|
||||
B.vars[V] = T.vars[V]
|
||||
toupdate += B
|
||||
|
||||
@@ -64,25 +64,25 @@
|
||||
..()
|
||||
|
||||
/obj/machinery/computer/holodeck/Initialize(mapload)
|
||||
..()
|
||||
if(!mapload && ticker.current_state < GAME_STATE_PLAYING)
|
||||
return
|
||||
program_cache = list()
|
||||
emag_programs = list()
|
||||
for(var/typekey in subtypesof(program_type))
|
||||
var/area/holodeck/A = locate(typekey)
|
||||
if(!A || A == offline_program) continue
|
||||
if(A.contents.len == 0) continue // not loaded
|
||||
if(A.restricted)
|
||||
emag_programs += A
|
||||
else
|
||||
program_cache += A
|
||||
if(typekey == init_program)
|
||||
load_program(A,force=1)
|
||||
if(random_program && program_cache.len && init_program == null)
|
||||
load_program(pick(program_cache),force=1)
|
||||
else if(!program)
|
||||
load_program(offline_program)
|
||||
. = mapload //late-initialize, area_copy need turfs to have air
|
||||
if(!mapload)
|
||||
..()
|
||||
program_cache = list()
|
||||
emag_programs = list()
|
||||
for(var/typekey in subtypesof(program_type))
|
||||
var/area/holodeck/A = locate(typekey)
|
||||
if(!A || A == offline_program) continue
|
||||
if(A.contents.len == 0) continue // not loaded
|
||||
if(A.restricted)
|
||||
emag_programs += A
|
||||
else
|
||||
program_cache += A
|
||||
if(typekey == init_program)
|
||||
load_program(A,force=1)
|
||||
if(random_program && program_cache.len && init_program == null)
|
||||
load_program(pick(program_cache),force=1)
|
||||
else if(!program)
|
||||
load_program(offline_program)
|
||||
|
||||
/obj/machinery/computer/holodeck/power_change()
|
||||
..()
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
name = "asteroid"
|
||||
icon_state = "asteroid0"
|
||||
|
||||
/turf/open/floor/holofloor/asteroid/New()
|
||||
/turf/open/floor/holofloor/asteroid/Initialize()
|
||||
icon_state = "asteroid[pick(0,1,2,3,4,5,6,7,8,9,10,11,12)]"
|
||||
..()
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
name = "basalt"
|
||||
icon_state = "basalt0"
|
||||
|
||||
/turf/open/floor/holofloor/basalt/New()
|
||||
/turf/open/floor/holofloor/basalt/Initialize()
|
||||
icon_state = "basalt[pick(0,1,2,3,4,5,6,7,8,9,10,11,12)]"
|
||||
..()
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
icon = 'icons/turf/space.dmi'
|
||||
icon_state = "0"
|
||||
|
||||
/turf/open/floor/holofloor/space/New()
|
||||
/turf/open/floor/holofloor/space/Initialize()
|
||||
icon_state = SPACE_ICON_STATE // so realistic
|
||||
..()
|
||||
|
||||
@@ -68,11 +68,11 @@
|
||||
icon = 'icons/turf/space.dmi'
|
||||
icon_state = "speedspace_ns_1"
|
||||
|
||||
/turf/open/floor/holofloor/hyperspace/New()
|
||||
/turf/open/floor/holofloor/hyperspace/Initialize()
|
||||
icon_state = "speedspace_ns_[(x + 5*y + (y%2+1)*7)%15+1]"
|
||||
..()
|
||||
|
||||
/turf/open/floor/holofloor/hyperspace/ns/New()
|
||||
/turf/open/floor/holofloor/hyperspace/ns/Initialize()
|
||||
..()
|
||||
icon_state = "speedspace_ns_[(x + 5*y + (y%2+1)*7)%15+1]"
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
smooth = SMOOTH_TRUE
|
||||
canSmoothWith = null
|
||||
|
||||
/turf/open/floor/holofloor/carpet/New()
|
||||
/turf/open/floor/holofloor/carpet/Initialize()
|
||||
..()
|
||||
addtimer(CALLBACK(src, .proc/update_icon), 1)
|
||||
|
||||
|
||||
@@ -1,40 +1,22 @@
|
||||
#define SOAPSTONE_PREFIX_FILE "strings/soapstone_prefixes.txt"
|
||||
#define SOAPSTONE_SUFFIX_FILE "soapstone_suffixes.json"
|
||||
//Vocabulary lists; soapstones use a prefix and a suffix. Optionally, they can have a prefix and suffix, then a conjunction that links another set.
|
||||
var/global/list/soapstone_prefixes = list() //Read from "strings/soapstone_prefixes.txt"; if you're adding your own, put **** where the subject should be!
|
||||
var/global/list/soapstone_suffixes = list() //Read from "strings/soapstone_suffixes.json"
|
||||
/obj/item/soapstone
|
||||
name = "chisel"
|
||||
desc = "Leave \"informative\" messages for the crew, including the crew of future shifts!\n\
|
||||
(Not suitable for engraving on shuttles, off station or on cats. Side effects may include beatings, bannings and orbital bombardment.)"
|
||||
desc = "Leave informative messages for the crew, including the crew of future shifts!\nEven if out of uses, it can still be used to remove messages.\n(Not suitable for engraving on shuttles, off station or on cats. Side effects may include beatings, bannings and orbital bombardment.)"
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "soapstone"
|
||||
throw_speed = 3
|
||||
throw_range = 5
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
var/tool_speed = 50
|
||||
var/remaining_uses = 3
|
||||
|
||||
var/non_dull_name
|
||||
var/w_engrave = "engrave"
|
||||
var/w_engraving = "engraving"
|
||||
var/w_chipping = "chipping"
|
||||
var/w_dull = "dull"
|
||||
|
||||
/obj/item/soapstone/New()
|
||||
. = ..()
|
||||
if(!soapstone_prefixes.len)
|
||||
soapstone_prefixes = file2list(SOAPSTONE_PREFIX_FILE, "\n")
|
||||
if(!soapstone_suffixes.len)
|
||||
soapstone_suffixes = list(\
|
||||
"Characters" = strings(SOAPSTONE_SUFFIX_FILE, "Characters"), \
|
||||
"Careers" = strings(SOAPSTONE_SUFFIX_FILE, "Careers"), \
|
||||
"Antagonists" = strings(SOAPSTONE_SUFFIX_FILE, "Antagonists"), \
|
||||
"Objects" = strings(SOAPSTONE_SUFFIX_FILE, "Objects"), \
|
||||
"Techniques" = strings(SOAPSTONE_SUFFIX_FILE, "Techniques"), \
|
||||
"Actions" = strings(SOAPSTONE_SUFFIX_FILE, "Actions"), \
|
||||
"Geography" = strings(SOAPSTONE_SUFFIX_FILE, "Geography"), \
|
||||
"Orientation" = strings(SOAPSTONE_SUFFIX_FILE, "Orientation"), \
|
||||
"Body parts" = strings(SOAPSTONE_SUFFIX_FILE, "Body parts"), \
|
||||
"Concepts" = strings(SOAPSTONE_SUFFIX_FILE, "Concepts"), \
|
||||
"Musings" = strings(SOAPSTONE_SUFFIX_FILE, "Musings"), \
|
||||
)
|
||||
random_name()
|
||||
check_name() // could start empty
|
||||
|
||||
@@ -43,6 +25,9 @@ var/global/list/soapstone_suffixes = list() //Read from "strings/soapstone_suffi
|
||||
non_dull_name = name
|
||||
if(name == "chalk" || name == "magic marker")
|
||||
desc = replacetext(desc, "engraving", "scribbling")
|
||||
w_engrave = "scribble"
|
||||
w_engraving = "scribbling"
|
||||
w_chipping = "sketching"
|
||||
if(name == "chalk")
|
||||
w_dull = "used"
|
||||
if(name == "magic marker")
|
||||
@@ -50,6 +35,9 @@ var/global/list/soapstone_suffixes = list() //Read from "strings/soapstone_suffi
|
||||
|
||||
if(name == "soapstone" || name == "chisel")
|
||||
desc = replacetext(desc, "scribbling", "engraving")
|
||||
w_engrave = initial(w_engrave)
|
||||
w_engraving = initial(w_engraving)
|
||||
w_chipping = initial(w_chipping)
|
||||
w_dull = "dull"
|
||||
|
||||
/obj/item/soapstone/examine(mob/user)
|
||||
@@ -60,48 +48,59 @@ var/global/list/soapstone_suffixes = list() //Read from "strings/soapstone_suffi
|
||||
user << "It looks like it can be used an unlimited number of times."
|
||||
|
||||
/obj/item/soapstone/afterattack(atom/target, mob/user, proximity)
|
||||
if(!remaining_uses)
|
||||
user << "<span class='warning'>[src] is [w_dull] and can't be used anymore!</span>"
|
||||
return
|
||||
var/turf/T = get_turf(target)
|
||||
if(!proximity)
|
||||
return
|
||||
var/obj/structure/chisel_message/msg = locate() in T
|
||||
if(msg)
|
||||
if(msg.creator_key != user.ckey)
|
||||
user << "<span class='warning'>There's already a message there!</span>"
|
||||
return
|
||||
else
|
||||
if(alert(user, "Erase this message?", name, "Yes", "No") == "Yes")
|
||||
user.visible_message("<span class='notice'>[user] erases [msg].</span>", "<span class='notice'>You permanently erase [msg].</span>")
|
||||
playsound(T, 'sound/items/gavel.ogg', 50, 1)
|
||||
refund_use()
|
||||
msg.persists = 0
|
||||
qdel(msg)
|
||||
return
|
||||
return
|
||||
|
||||
|
||||
var/obj/structure/chisel_message/already_message = locate(/obj/structure/chisel_message) in T
|
||||
|
||||
var/our_message = FALSE
|
||||
if(already_message)
|
||||
our_message = already_message.creator_key == user.ckey
|
||||
|
||||
if(!remaining_uses && !already_message)
|
||||
// The dull chisel is dull.
|
||||
user << "<span class='warning'>[src] is [w_dull].</span>"
|
||||
return
|
||||
|
||||
if(!good_chisel_message_location(T))
|
||||
user << "<span class='warning'>You can't write there!</span>"
|
||||
user << "<span class='warning'>It's not appropriate to [w_engrave] on [T].</span>"
|
||||
return
|
||||
var/prefix = input(user, "Choose a prefix for your message.", name) as null|anything in soapstone_prefixes
|
||||
if(!prefix)
|
||||
|
||||
if(already_message)
|
||||
user.visible_message("<span class='notice'>[user] starts erasing [already_message].</span>", "<span class='notice'>You start erasing [already_message].</span>", "<span class='italics'>You hear a [w_chipping] sound.</span>")
|
||||
playsound(loc, 'sound/items/gavel.ogg', 50, 1, -1)
|
||||
|
||||
// Removing our own messages refunds a charge
|
||||
|
||||
if(do_after(user, tool_speed, target=target))
|
||||
user.visible_message("<span class='notice'>[user] has erased [already_message].</span>", "<span class='notice'>You erased [already_message].</span>")
|
||||
already_message.persists = FALSE
|
||||
qdel(already_message)
|
||||
playsound(loc, 'sound/items/gavel.ogg', 50, 1, -1)
|
||||
if(our_message)
|
||||
refund_use()
|
||||
return
|
||||
var/suffix_category_string = input(user, "Choose a suffix category.", "[prefix]...") as null|anything in soapstone_suffixes
|
||||
var/list/suffix_category = soapstone_suffixes[suffix_category_string]
|
||||
if(!suffix_category || !suffix_category.len)
|
||||
|
||||
var/message = stripped_input(user, "What would you like to [w_engrave]?", "[name] Message")
|
||||
if(!message)
|
||||
user << "You decide not to [w_engrave] anything."
|
||||
return
|
||||
var/suffix = input(user, "Choose a suffix.", "[prefix]...") as null|anything in suffix_category
|
||||
if(!suffix)
|
||||
|
||||
if(!target.Adjacent(user) && locate(/obj/structure/chisel_message) in T)
|
||||
user << "You decide not to [w_engrave] anything."
|
||||
return
|
||||
var/processed_message = replacetext(prefix, "****", suffix)
|
||||
if(!user.Adjacent(T) || !good_chisel_message_location(T) || locate(/obj/structure/chisel_message) in T)
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] writes a message onto [T]!</span>", "<span class='notice'>You write a message onto [T].</span>")
|
||||
playsound(T, 'sound/items/gavel.ogg', 50, 1)
|
||||
var/obj/structure/chisel_message/M = new(T)
|
||||
M.register(user, processed_message)
|
||||
remove_use()
|
||||
return 1
|
||||
|
||||
playsound(loc, 'sound/items/gavel.ogg', 50, 1, -1)
|
||||
user.visible_message("<span class='notice'>[user] starts [w_engraving] a message into [T].</span>", "You start [w_engraving] a message into [T].", "<span class='italics'>You hear a [w_chipping] sound.</span>")
|
||||
if(can_use() && do_after(user, tool_speed, target=T) && can_use())
|
||||
if(!locate(/obj/structure/chisel_message in T))
|
||||
user << "You [w_engrave] a message into [T]."
|
||||
playsound(loc, 'sound/items/gavel.ogg', 50, 1, -1)
|
||||
var/obj/structure/chisel_message/M = new(T)
|
||||
M.register(user, message)
|
||||
remove_use()
|
||||
|
||||
/obj/item/soapstone/proc/can_use()
|
||||
if(remaining_uses == -1 || remaining_uses >= 0)
|
||||
@@ -172,34 +171,6 @@ var/global/list/soapstone_suffixes = list() //Read from "strings/soapstone_suffi
|
||||
var/map
|
||||
var/persists = TRUE
|
||||
|
||||
var/positive_ratings = 0
|
||||
var/negative_ratings = 0
|
||||
|
||||
var/list/raters = list() //Ckeys who have rated this message
|
||||
|
||||
/obj/structure/chisel_message/attack_hand(mob/user)
|
||||
if(user.ckey == creator_key)
|
||||
user << "<span class='warning'>You can't rate your own messages!</span>"
|
||||
return
|
||||
if(raters[user.ckey])
|
||||
user << "<span class='warning'>You've already rated this message!</span>"
|
||||
return
|
||||
switch(alert(user, "How would you like to rate this message?", "Message Rating", "Positive", "Negative", "Cancel"))
|
||||
if("Positive")
|
||||
for(var/client/C in clients)
|
||||
if(C.ckey == creator_key)
|
||||
C.mob << "<span class='notice'>One of your messages was rated as positive!</span>"
|
||||
user << "<span class='noticealien'>You rated this message as positive.</span>"
|
||||
positive_ratings++
|
||||
raters[user.ckey] = "positive"
|
||||
if("Negative")
|
||||
for(var/client/C in clients)
|
||||
if(C.ckey == creator_key)
|
||||
C.mob << "<span class='danger'>One of your messages was rated as negative!</span>"
|
||||
user << "<span class='danger'>You rated this message as negative.</span>"
|
||||
negative_ratings++
|
||||
raters[user.ckey] = "negative"
|
||||
|
||||
/obj/structure/chisel_message/New(newloc)
|
||||
..()
|
||||
SSpersistence.chisel_messages += src
|
||||
@@ -219,6 +190,12 @@ var/global/list/soapstone_suffixes = list() //Read from "strings/soapstone_suffi
|
||||
map = MAP_NAME
|
||||
update_icon()
|
||||
|
||||
/obj/structure/chisel_message/update_icon()
|
||||
..()
|
||||
var/hash = md5(hidden_message)
|
||||
var/newcolor = copytext(hash, 1, 7)
|
||||
add_atom_colour("#[newcolor]", FIXED_COLOUR_PRIORITY)
|
||||
|
||||
/obj/structure/chisel_message/proc/pack()
|
||||
var/list/data = list()
|
||||
data["hidden_message"] = hidden_message
|
||||
@@ -229,9 +206,6 @@ var/global/list/soapstone_suffixes = list() //Read from "strings/soapstone_suffi
|
||||
var/turf/T = get_turf(src)
|
||||
data["x"] = T.x
|
||||
data["y"] = T.y
|
||||
data["pos_ratings"] = positive_ratings
|
||||
data["neg_ratings"] = positive_ratings
|
||||
data["raters"] = raters
|
||||
return data
|
||||
|
||||
/obj/structure/chisel_message/proc/unpack(list/data)
|
||||
@@ -239,9 +213,6 @@ var/global/list/soapstone_suffixes = list() //Read from "strings/soapstone_suffi
|
||||
creator_name = data["creator_name"]
|
||||
creator_key = data["creator_key"]
|
||||
realdate = data["realdate"]
|
||||
positive_ratings = data["pos_ratings"]
|
||||
negative_ratings = data["neg_ratings"]
|
||||
raters = data["raters"]
|
||||
|
||||
var/x = data["x"]
|
||||
var/y = data["y"]
|
||||
@@ -251,10 +222,7 @@ var/global/list/soapstone_suffixes = list() //Read from "strings/soapstone_suffi
|
||||
|
||||
/obj/structure/chisel_message/examine(mob/user)
|
||||
..()
|
||||
user << "<span class='notice'>[hidden_message]</span>"
|
||||
user << "Ratings: <span class='noticealien'>[positive_ratings]</span> <span class='danger'>[negative_ratings]</span>"
|
||||
if(raters[user.ckey])
|
||||
user << "<i>You rated this message as [raters[user.ckey]].</i>"
|
||||
user << "<span class='warning'>[hidden_message]</span>"
|
||||
|
||||
/obj/structure/chisel_message/Destroy()
|
||||
if(persists)
|
||||
|
||||
@@ -91,20 +91,29 @@
|
||||
return 1
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/throw_impact(atom/hit_atom)
|
||||
/mob/living/carbon/throw_impact(atom/hit_atom, throwingdatum)
|
||||
. = ..()
|
||||
var/hurt = TRUE
|
||||
if(istype(throwingdatum, /datum/thrownthing))
|
||||
var/datum/thrownthing/D = throwingdatum
|
||||
if(iscyborg(D.thrower))
|
||||
var/mob/living/silicon/robot/R = D.thrower
|
||||
if(!R.emagged)
|
||||
hurt = FALSE
|
||||
if(hit_atom.density && isturf(hit_atom))
|
||||
Weaken(1)
|
||||
take_bodypart_damage(10)
|
||||
if(hurt)
|
||||
Weaken(1)
|
||||
take_bodypart_damage(10)
|
||||
if(iscarbon(hit_atom) && hit_atom != src)
|
||||
var/mob/living/carbon/victim = hit_atom
|
||||
if(victim.movement_type & FLYING)
|
||||
return
|
||||
victim.Weaken(1)
|
||||
Weaken(1)
|
||||
victim.take_bodypart_damage(10)
|
||||
take_bodypart_damage(10)
|
||||
visible_message("<span class='danger'>[src] crashes into [victim], knocking them both over!</span>", "<span class='userdanger'>You violently crash into [victim]!</span>")
|
||||
if(hurt)
|
||||
victim.take_bodypart_damage(10)
|
||||
take_bodypart_damage(10)
|
||||
victim.Weaken(1)
|
||||
Weaken(1)
|
||||
visible_message("<span class='danger'>[src] crashes into [victim], knocking them both over!</span>", "<span class='userdanger'>You violently crash into [victim]!</span>")
|
||||
playsound(src,'sound/weapons/punch1.ogg',50,1)
|
||||
|
||||
|
||||
@@ -231,23 +240,6 @@
|
||||
/mob/living/carbon/is_muzzled()
|
||||
return(istype(src.wear_mask, /obj/item/clothing/mask/muzzle))
|
||||
|
||||
/mob/living/carbon/proc/spin(spintime, speed)
|
||||
set waitfor = 0
|
||||
var/D = dir
|
||||
while(spintime >= speed)
|
||||
sleep(speed)
|
||||
switch(D)
|
||||
if(NORTH)
|
||||
D = EAST
|
||||
if(SOUTH)
|
||||
D = WEST
|
||||
if(EAST)
|
||||
D = SOUTH
|
||||
if(WEST)
|
||||
D = NORTH
|
||||
setDir(D)
|
||||
spintime -= speed
|
||||
|
||||
/mob/living/carbon/resist_buckle()
|
||||
if(restrained())
|
||||
changeNext_move(CLICK_CD_BREAKOUT)
|
||||
|
||||
@@ -168,7 +168,7 @@
|
||||
O.emp_act(severity)
|
||||
..()
|
||||
|
||||
/mob/living/carbon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, override = 0, tesla_shock = 0, illusion = 0)
|
||||
/mob/living/carbon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, override = 0, tesla_shock = 0, illusion = 0, stun = TRUE)
|
||||
if(tesla_shock && tesla_ignore)
|
||||
return FALSE
|
||||
shock_damage *= siemens_coeff
|
||||
@@ -190,11 +190,11 @@
|
||||
jitteriness += 1000 //High numbers for violent convulsions
|
||||
do_jitter_animation(jitteriness)
|
||||
stuttering += 2
|
||||
if(!tesla_shock || (tesla_shock && siemens_coeff > 0.5))
|
||||
if((!tesla_shock || (tesla_shock && siemens_coeff > 0.5)) && stun)
|
||||
Stun(2)
|
||||
spawn(20)
|
||||
jitteriness = max(jitteriness - 990, 10) //Still jittery, but vastly less
|
||||
if(!tesla_shock || (tesla_shock && siemens_coeff > 0.5))
|
||||
if((!tesla_shock || (tesla_shock && siemens_coeff > 0.5)) && stun)
|
||||
Stun(3)
|
||||
Weaken(3)
|
||||
if(override)
|
||||
|
||||
@@ -436,7 +436,7 @@
|
||||
|
||||
|
||||
//Added a safety check in case you want to shock a human mob directly through electrocute_act.
|
||||
/mob/living/carbon/human/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, override = 0, tesla_shock = 0, illusion = 0)
|
||||
/mob/living/carbon/human/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, override = 0, tesla_shock = 0, illusion = 0, stun = TRUE)
|
||||
if(tesla_shock)
|
||||
var/total_coeff = 1
|
||||
if(gloves)
|
||||
@@ -447,6 +447,8 @@
|
||||
var/obj/item/clothing/suit/S = wear_suit
|
||||
if(S.siemens_coefficient <= 0)
|
||||
total_coeff -= 0.95
|
||||
else if(S.siemens_coefficient == (-1))
|
||||
total_coeff -= 1
|
||||
siemens_coeff = total_coeff
|
||||
if(tesla_ignore)
|
||||
siemens_coeff = 0
|
||||
@@ -461,7 +463,7 @@
|
||||
heart_attack = 0
|
||||
if(stat == CONSCIOUS)
|
||||
src << "<span class='notice'>You feel your heart beating again!</span>"
|
||||
. = ..(shock_damage,source,siemens_coeff,safety,override,tesla_shock, illusion)
|
||||
. = ..(shock_damage,source,siemens_coeff,safety,override,tesla_shock, illusion, stun)
|
||||
if(.)
|
||||
electrocution_animation(40)
|
||||
|
||||
@@ -754,4 +756,4 @@
|
||||
torn_items += leg_clothes
|
||||
|
||||
for(var/obj/item/I in torn_items)
|
||||
I.take_damage(damage_amount, damage_type, damage_flag, 0)
|
||||
I.take_damage(damage_amount, damage_type, damage_flag, 0)
|
||||
|
||||
@@ -1015,7 +1015,7 @@
|
||||
var/obj/item/organ/cyberimp/chest/thrusters/T = H.getorganslot("thrusters")
|
||||
if(!istype(J) && istype(C))
|
||||
J = C.jetpack
|
||||
if(istype(J) && J.allow_thrust(0.01, H)) //Prevents stacking
|
||||
if(istype(J) && J.full_speed && J.allow_thrust(0.01, H)) //Prevents stacking
|
||||
. -= 2
|
||||
else if(istype(T) && T.allow_thrust(0.01, H))
|
||||
. -= 2
|
||||
|
||||
@@ -150,4 +150,14 @@
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/monkey/can_use_guns(var/obj/item/weapon/gun/G)
|
||||
return 1
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/monkey/angry
|
||||
aggressive = TRUE
|
||||
|
||||
/mob/living/carbon/monkey/angry/Initialize()
|
||||
..()
|
||||
if(prob(10))
|
||||
var/obj/item/clothing/head/helmet/justice/escape/helmet = new(src)
|
||||
equip_to_slot_or_del(helmet,slot_head)
|
||||
helmet.attack_self(src) // todo encapsulate toggle
|
||||
@@ -93,6 +93,7 @@
|
||||
if(istype(S) && S.deathmessage)
|
||||
message_simple = S.deathmessage
|
||||
. = ..()
|
||||
message_simple = initial(message_simple)
|
||||
if(. && isalienadult(user))
|
||||
playsound(user.loc, 'sound/voice/hiss6.ogg', 80, 1, 1)
|
||||
|
||||
@@ -451,3 +452,15 @@
|
||||
message = "beeps."
|
||||
message_param = "beeps at %t."
|
||||
sound = 'sound/machines/twobeep.ogg'
|
||||
|
||||
/datum/emote/living/spin
|
||||
key = "spin"
|
||||
key_third_person = "spins"
|
||||
message = "spins around dizzily!"
|
||||
|
||||
/datum/emote/living/spin/run_emote(mob/user)
|
||||
user.spin(20, 1)
|
||||
if(istype(user, /mob/living/silicon/robot))
|
||||
var/mob/living/silicon/robot/R = user
|
||||
R.riding_datum.force_dismount()
|
||||
..()
|
||||
@@ -274,8 +274,7 @@
|
||||
take_bodypart_damage(acidpwr * min(1, acid_volume * 0.1))
|
||||
return 1
|
||||
|
||||
|
||||
/mob/living/proc/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0, illusion = 0)
|
||||
/mob/living/proc/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0, illusion = 0, stun = TRUE)
|
||||
if(tesla_shock && tesla_ignore)
|
||||
return FALSE
|
||||
if(shock_damage > 0)
|
||||
@@ -325,13 +324,16 @@
|
||||
|
||||
|
||||
/mob/living/ratvar_act()
|
||||
if(stat != DEAD && !is_servant_of_ratvar(src) && !add_servant_of_ratvar(src))
|
||||
src << "<span class='userdanger'>A blinding light boils you alive! <i>Run!</i></span>"
|
||||
adjustFireLoss(35)
|
||||
if(src)
|
||||
adjust_fire_stacks(1)
|
||||
IgniteMob()
|
||||
return FALSE
|
||||
if(stat != DEAD && !is_servant_of_ratvar(src))
|
||||
for(var/obj/item/weapon/implant/mindshield/M in implants)
|
||||
qdel(M)
|
||||
if(!add_servant_of_ratvar(src))
|
||||
src << "<span class='userdanger'>A blinding light boils you alive! <i>Run!</i></span>"
|
||||
adjustFireLoss(35)
|
||||
if(src)
|
||||
adjust_fire_stacks(1)
|
||||
IgniteMob()
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
|
||||
|
||||
@@ -57,11 +57,11 @@
|
||||
var/chassis = "repairbot"
|
||||
var/list/possible_chassis = list("cat", "mouse", "monkey", "corgi", "fox", "repairbot", "rabbit")
|
||||
|
||||
var/emitterhealth = 50
|
||||
var/emittermaxhealth = 50
|
||||
var/emitterregen = 0.5
|
||||
var/emittercd = 20
|
||||
var/emitteroverloadcd = 50
|
||||
var/emitterhealth = 20
|
||||
var/emittermaxhealth = 20
|
||||
var/emitterregen = 0.25
|
||||
var/emittercd = 50
|
||||
var/emitteroverloadcd = 100
|
||||
var/emittersemicd = FALSE
|
||||
|
||||
var/overload_ventcrawl = 0
|
||||
@@ -235,4 +235,4 @@
|
||||
|
||||
/mob/living/silicon/pai/process()
|
||||
emitterhealth = Clamp((emitterhealth + emitterregen), -50, emittermaxhealth)
|
||||
hit_slowdown = Clamp((hit_slowdown - 1), 0, 100)
|
||||
hit_slowdown = Clamp((hit_slowdown - 1), 0, 100)
|
||||
@@ -30,4 +30,6 @@
|
||||
|
||||
update_icons()
|
||||
|
||||
sql_report_death(src)
|
||||
unbuckle_all_mobs(TRUE)
|
||||
|
||||
sql_report_death(src)
|
||||
|
||||
@@ -69,4 +69,4 @@
|
||||
"You announce you are operating in low power mode.")
|
||||
playsound(loc, 'sound/machines/buzz-two.ogg', 50, 0)
|
||||
else
|
||||
src << "<span class='warning'>You can only use this emote when you're out of charge.</span>"
|
||||
src << "<span class='warning'>You can only use this emote when you're out of charge.</span>"
|
||||
|
||||
@@ -89,7 +89,9 @@
|
||||
/obj/item/clothing/head/sombrero,
|
||||
/obj/item/clothing/head/witchunter_hat)
|
||||
|
||||
|
||||
can_buckle = TRUE
|
||||
buckle_lying = FALSE
|
||||
var/datum/riding/cyborg/riding_datum = null
|
||||
|
||||
/mob/living/silicon/robot/New(loc)
|
||||
spark_system = new /datum/effect_system/spark_spread()
|
||||
@@ -995,3 +997,90 @@
|
||||
hat = new_hat
|
||||
new_hat.forceMove(src)
|
||||
update_icons()
|
||||
|
||||
/mob/living/silicon/robot/MouseDrop_T(mob/living/M, mob/living/user)
|
||||
. = ..()
|
||||
if(!(M in buckled_mobs))
|
||||
buckle_mob(M)
|
||||
|
||||
/mob/living/silicon/robot/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE)
|
||||
if(!riding_datum)
|
||||
riding_datum = new /datum/riding/cyborg
|
||||
riding_datum.ridden = src
|
||||
if(buckled_mobs)
|
||||
if(buckled_mobs.len >= max_buckled_mobs)
|
||||
return
|
||||
if(M in buckled_mobs)
|
||||
return
|
||||
if(stat)
|
||||
return
|
||||
if(incapacitated())
|
||||
return
|
||||
if(M.restrained())
|
||||
return
|
||||
if(iscyborg(M))
|
||||
M.visible_message("<span class='warning'>[M] really can't seem to mount the [src]...</span>")
|
||||
return
|
||||
if(isbot(M))
|
||||
M.visible_message("<span class='boldwarning'>No. Just... no.</span>")
|
||||
return
|
||||
if(module)
|
||||
if(!module.allow_riding)
|
||||
M.visible_message("<span class='boldwarning'>Unfortunately, [M] just can't seem to hold onto [src]!</span>")
|
||||
return
|
||||
if(iscarbon(M))
|
||||
if(!equip_buckle_inhands(M)) //MAKE SURE THIS IS LAST!
|
||||
M.visible_message("<span class='boldwarning'>[M] can't climb onto [src] because his hands are full!</span>")
|
||||
return
|
||||
. = ..(M, force, check_loc)
|
||||
riding_datum.handle_vehicle_offsets()
|
||||
|
||||
/mob/living/silicon/robot/unbuckle_mob(mob/user)
|
||||
if(iscarbon(user))
|
||||
unequip_buckle_inhands(user)
|
||||
. = ..(user)
|
||||
riding_datum.restore_position(user)
|
||||
|
||||
/mob/living/silicon/robot/proc/unequip_buckle_inhands(mob/living/carbon/user)
|
||||
for(var/obj/item/cyborgride_offhand/O in user.contents)
|
||||
if(O.ridden != src)
|
||||
CRASH("RIDING OFFHAND ON WRONG MOB")
|
||||
continue
|
||||
if(O.selfdeleting)
|
||||
continue
|
||||
else
|
||||
qdel(O)
|
||||
return TRUE
|
||||
|
||||
/mob/living/silicon/robot/proc/equip_buckle_inhands(mob/living/carbon/user)
|
||||
var/obj/item/cyborgride_offhand/inhand = new /obj/item/cyborgride_offhand(user)
|
||||
inhand.rider = user
|
||||
inhand.ridden = src
|
||||
return user.put_in_hands(inhand, TRUE)
|
||||
|
||||
/obj/item/cyborgride_offhand
|
||||
name = "offhand"
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "offhand"
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
flags = ABSTRACT | DROPDEL | NOBLUDGEON
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
var/mob/living/carbon/rider
|
||||
var/mob/living/silicon/robot/ridden
|
||||
var/selfdeleting = FALSE
|
||||
|
||||
/obj/item/cyborgride_offhand/dropped()
|
||||
selfdeleting = TRUE
|
||||
. = ..()
|
||||
|
||||
/obj/item/cyborgride_offhand/equipped()
|
||||
if(loc != rider)
|
||||
selfdeleting = TRUE
|
||||
qdel(src)
|
||||
. = ..()
|
||||
|
||||
/obj/item/cyborgride_offhand/Destroy()
|
||||
if(selfdeleting)
|
||||
if(rider in ridden.buckled_mobs)
|
||||
ridden.unbuckle_mob(rider)
|
||||
. = ..()
|
||||
|
||||
@@ -26,6 +26,11 @@
|
||||
|
||||
var/hat_offset = -3
|
||||
|
||||
var/list/ride_offset_x = list("north" = 0, "south" = 0, "east" = -6, "west" = 6)
|
||||
var/list/ride_offset_y = list("north" = 4, "south" = 4, "east" = 3, "west" = 3)
|
||||
var/ride_allow_incapacitated = FALSE
|
||||
var/allow_riding = TRUE
|
||||
|
||||
/obj/item/weapon/robot_module/New()
|
||||
..()
|
||||
for(var/i in basic_modules)
|
||||
|
||||
@@ -17,3 +17,8 @@
|
||||
/mob/living/silicon/robot/experience_pressure_difference(pressure_difference, direction)
|
||||
if(!magpulse)
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/robot/Moved()
|
||||
. = ..()
|
||||
if(riding_datum)
|
||||
riding_datum.on_vehicle_move()
|
||||
@@ -26,6 +26,11 @@
|
||||
/mob/living/silicon/attack_animal(mob/living/simple_animal/M)
|
||||
if(..())
|
||||
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
|
||||
if(prob(damage))
|
||||
for(var/mob/living/N in buckled_mobs)
|
||||
N.Weaken(1)
|
||||
unbuckle_mob(N)
|
||||
N.visible_message("<span class='boldwarning'>[N] is knocked off of [src] by [M]!</span>")
|
||||
switch(M.melee_damage_type)
|
||||
if(BRUTE)
|
||||
adjustBruteLoss(damage)
|
||||
@@ -73,6 +78,10 @@
|
||||
return 0
|
||||
|
||||
/mob/living/silicon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0, illusion = 0)
|
||||
if(buckled_mobs)
|
||||
for(var/mob/living/M in buckled_mobs)
|
||||
unbuckle_mob(M)
|
||||
M.electrocute_act(shock_damage/100, source, siemens_coeff, safety, tesla_shock, illusion) //Hard metal shell conducts!
|
||||
return 0 //So borgs they don't die trying to fix wiring
|
||||
|
||||
/mob/living/silicon/emp_act(severity)
|
||||
@@ -83,12 +92,26 @@
|
||||
src.take_bodypart_damage(10)
|
||||
src << "<span class='userdanger'>*BZZZT*</span>"
|
||||
src << "<span class='danger'>Warning: Electromagnetic pulse detected.</span>"
|
||||
for(var/mob/living/M in buckled_mobs)
|
||||
if(prob(severity*50))
|
||||
unbuckle_mob(M)
|
||||
M.Weaken(2)
|
||||
M.visible_message("<span class='boldwarning'>[M] is thrown off of [src]!</span>")
|
||||
flash_act(affect_silicon = 1)
|
||||
..()
|
||||
|
||||
/mob/living/silicon/bullet_act(obj/item/projectile/Proj)
|
||||
if((Proj.damage_type == BRUTE || Proj.damage_type == BURN))
|
||||
adjustBruteLoss(Proj.damage)
|
||||
if(prob(Proj.damage*1.5))
|
||||
for(var/mob/living/M in buckled_mobs)
|
||||
M.visible_message("<span class='boldwarning'>[M] is knocked off of [src]!</span>")
|
||||
unbuckle_mob(M)
|
||||
M.Weaken(2)
|
||||
if(Proj.stun || Proj.weaken)
|
||||
for(var/mob/living/M in buckled_mobs)
|
||||
unbuckle_mob(M)
|
||||
M.visible_message("<span class='boldwarning'>[M] is knocked off of [src] by the [Proj]!</span>")
|
||||
Proj.on_hit(src)
|
||||
return 2
|
||||
|
||||
|
||||
@@ -145,8 +145,9 @@ Auto Patrol: []"},
|
||||
mode = BOT_HUNT
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/attack_hand(mob/living/carbon/human/H)
|
||||
if(H.a_intent == INTENT_HARM)
|
||||
if((H.a_intent == INTENT_HARM) || (H.a_intent == INTENT_DISARM))
|
||||
retaliate(H)
|
||||
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/attackby(obj/item/weapon/W, mob/user, params)
|
||||
@@ -409,4 +410,4 @@ Auto Patrol: []"},
|
||||
..()
|
||||
|
||||
/obj/machinery/bot_core/secbot
|
||||
req_access = list(access_security)
|
||||
req_access = list(access_security)
|
||||
@@ -98,7 +98,7 @@ Difficulty: Hard
|
||||
INVOKE_ASYNC(src, .proc/charge)
|
||||
else
|
||||
if(prob(70) || warped)
|
||||
INVOKE_ASYNC(src, .proc/triple_charge)
|
||||
INVOKE_ASYNC(src, .proc/charge, 2)
|
||||
else
|
||||
INVOKE_ASYNC(src, .proc/warp_charge)
|
||||
|
||||
@@ -141,12 +141,7 @@ Difficulty: Hard
|
||||
blood_warp()
|
||||
charge()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/triple_charge()
|
||||
charge()
|
||||
charge()
|
||||
charge()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/charge()
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/charge(bonus_charges)
|
||||
var/turf/T = get_turf(target)
|
||||
if(!T || T == loc)
|
||||
return
|
||||
@@ -156,14 +151,18 @@ Difficulty: Hard
|
||||
walk(src, 0)
|
||||
setDir(get_dir(src, T))
|
||||
var/obj/effect/overlay/temp/decoy/D = new /obj/effect/overlay/temp/decoy(loc,src)
|
||||
animate(D, alpha = 0, color = "#FF0000", transform = matrix()*2, time = 5)
|
||||
sleep(5)
|
||||
throw_at(T, get_dist(src, T), 1, src, 0, callback = CALLBACK(src, .charge_end))
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/charge_end()
|
||||
animate(D, alpha = 0, color = "#FF0000", transform = matrix()*2, time = 3)
|
||||
sleep(3)
|
||||
throw_at(T, get_dist(src, T), 0.5, src, 0, callback = CALLBACK(src, .charge_end, bonus_charges))
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/charge_end(bonus_charges)
|
||||
charging = 0
|
||||
try_bloodattack()
|
||||
if(target)
|
||||
Goto(target, move_to_delay, minimum_distance)
|
||||
if(bonus_charges)
|
||||
charge(bonus_charges--)
|
||||
else
|
||||
Goto(target, move_to_delay, minimum_distance)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/Bump(atom/A)
|
||||
@@ -312,8 +311,8 @@ Difficulty: Hard
|
||||
DA.color = "#FF0000"
|
||||
var/oldtransform = DA.transform
|
||||
DA.transform = matrix()*2
|
||||
animate(DA, alpha = 255, color = initial(DA.color), transform = oldtransform, time = 5)
|
||||
sleep(5)
|
||||
animate(DA, alpha = 255, color = initial(DA.color), transform = oldtransform, time = 3)
|
||||
sleep(3)
|
||||
qdel(DA)
|
||||
|
||||
var/obj/effect/decal/cleanable/blood/found_bloodpool
|
||||
|
||||
@@ -299,21 +299,20 @@
|
||||
if(!gibbed)
|
||||
if(death_sound)
|
||||
playsound(get_turf(src),death_sound, 200, 1)
|
||||
if(deathmessage && !del_on_death)
|
||||
if(deathmessage || !del_on_death)
|
||||
emote("deathgasp")
|
||||
if(del_on_death)
|
||||
ghostize()
|
||||
..()
|
||||
//Prevent infinite loops if the mob Destroy() is overriden in such
|
||||
//a manner as to cause a call to death() again
|
||||
del_on_death = FALSE
|
||||
qdel(src)
|
||||
return
|
||||
else
|
||||
health = 0
|
||||
icon_state = icon_dead
|
||||
density = 0
|
||||
lying = 1
|
||||
..()
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/proc/CanAttack(atom/the_target)
|
||||
if(see_invisible < the_target.invisibility)
|
||||
@@ -551,4 +550,4 @@
|
||||
|
||||
/mob/living/simple_animal/buckle_mob(mob/living/buckled_mob, force = 0, check_loc = 1)
|
||||
. = ..()
|
||||
riding_datum = new/datum/riding/animal
|
||||
riding_datum = new/datum/riding/animal
|
||||
+19
-40
@@ -1,6 +1,5 @@
|
||||
/mob/Destroy()//This makes sure that mobs with clients/keys are not just deleted from the game.
|
||||
mob_list -= src
|
||||
SSmob.currentrun -= src
|
||||
dead_mob_list -= src
|
||||
living_mob_list -= src
|
||||
all_clockwork_mobs -= src
|
||||
@@ -28,8 +27,8 @@ var/next_mob_id = 0
|
||||
dead_mob_list += src
|
||||
else
|
||||
living_mob_list += src
|
||||
prepare_huds()
|
||||
hook_vr("mob_new",list(src))
|
||||
prepare_huds()
|
||||
..()
|
||||
|
||||
/atom/proc/prepare_huds()
|
||||
@@ -112,7 +111,7 @@ var/next_mob_id = 0
|
||||
if(self_message)
|
||||
msg = self_message
|
||||
else
|
||||
if(M.see_invisible<invisibility)//if src is invisible to us
|
||||
if(M.see_invisible<invisibility)//if src is invisible to us,
|
||||
if(blind_message) // then people see blind message if there is one, otherwise nothing.
|
||||
msg = blind_message
|
||||
else
|
||||
@@ -125,18 +124,6 @@ var/next_mob_id = 0
|
||||
continue
|
||||
M.show_message(msg,1,blind_message,2)
|
||||
|
||||
/mob/proc/get_top_level_mob()
|
||||
if(istype(src.loc,/mob)&&src.loc!=src)
|
||||
var/mob/M=src.loc
|
||||
return M.get_top_level_mob()
|
||||
return src
|
||||
|
||||
proc/get_top_level_mob(var/mob/S)
|
||||
if(istype(S.loc,/mob)&&S.loc!=S)
|
||||
var/mob/M=S.loc
|
||||
return M.get_top_level_mob()
|
||||
return S
|
||||
|
||||
// Show a message to all mobs in earshot of this one
|
||||
// This would be for audible actions by the src mob
|
||||
// message is the message output to anyone who can hear.
|
||||
@@ -352,6 +339,23 @@ proc/get_top_level_mob(var/mob/S)
|
||||
else
|
||||
M.LAssailant = usr
|
||||
|
||||
/mob/proc/spin(spintime, speed)
|
||||
set waitfor = 0
|
||||
var/D = dir
|
||||
while(spintime >= speed)
|
||||
sleep(speed)
|
||||
switch(D)
|
||||
if(NORTH)
|
||||
D = EAST
|
||||
if(SOUTH)
|
||||
D = WEST
|
||||
if(EAST)
|
||||
D = SOUTH
|
||||
if(WEST)
|
||||
D = NORTH
|
||||
setDir(D)
|
||||
spintime -= speed
|
||||
|
||||
/mob/verb/stop_pulling()
|
||||
set name = "Stop Pulling"
|
||||
set category = "IC"
|
||||
@@ -452,30 +456,7 @@ proc/get_top_level_mob(var/mob/S)
|
||||
// M.Login() //wat
|
||||
return
|
||||
|
||||
/mob/proc/update_flavor_text()
|
||||
set src in usr
|
||||
if(usr != src)
|
||||
usr << "No."
|
||||
var/msg = input(usr,"Set the flavor text in your 'examine' verb. Can also be used for OOC notes about your character.","Flavor Text",html_decode(flavor_text)) as message|null
|
||||
|
||||
if(msg != null)
|
||||
msg = copytext(msg, 1, MAX_MESSAGE_LEN)
|
||||
msg = html_encode(msg)
|
||||
|
||||
flavor_text = msg
|
||||
|
||||
/mob/proc/warn_flavor_changed()
|
||||
if(flavor_text && flavor_text != "") // don't spam people that don't use it!
|
||||
src << "<h2 class='alert'>OOC Warning:</h2>"
|
||||
src << "<span class='alert'>Your flavor text is likely out of date! <a href='byond://?src=\ref[src];flavor_change=1'>Change</a></span>"
|
||||
|
||||
/mob/proc/print_flavor_text()
|
||||
if(flavor_text && flavor_text != "")
|
||||
var/msg = replacetext(flavor_text, "\n", " ")
|
||||
if(lentext(msg) <= 40)
|
||||
return "\blue [msg]"
|
||||
else
|
||||
return "\blue [copytext(msg, 1, 37)]... <a href='byond://?src=\ref[src];flavor_more=1'>More...</a>"
|
||||
|
||||
/mob/verb/cancel_camera()
|
||||
set name = "Cancel Camera View"
|
||||
@@ -571,7 +552,6 @@ proc/get_top_level_mob(var/mob/S)
|
||||
stat(null, "Next Map: [nextmap.friendlyname]")
|
||||
stat(null, "Server Time: [time2text(world.realtime, "YYYY-MM-DD hh:mm")]")
|
||||
if(SSshuttle.emergency)
|
||||
stat(null, "Current Shuttle: [SSshuttle.emergency.name]")
|
||||
var/ETA = SSshuttle.emergency.getModeStr()
|
||||
if(ETA)
|
||||
stat(null, "[ETA] [SSshuttle.emergency.getTimerStr()]")
|
||||
@@ -967,5 +947,4 @@ proc/get_top_level_mob(var/mob/S)
|
||||
switch(var_name)
|
||||
if ("attack_log")
|
||||
return debug_variable(var_name, attack_log, 0, src, FALSE)
|
||||
|
||||
. = ..()
|
||||
@@ -175,7 +175,8 @@
|
||||
|
||||
moving = 0
|
||||
if(mob && .)
|
||||
mob.throwing = 0
|
||||
if(mob.throwing)
|
||||
mob.throwing.finalize(FALSE)
|
||||
|
||||
for(var/obj/O in mob)
|
||||
O.on_mob_move(direct, src)
|
||||
@@ -424,7 +425,7 @@
|
||||
/client/verb/toggle_walk_run()
|
||||
set name = "toggle-walk-run"
|
||||
set hidden = TRUE
|
||||
set instant = TRUE
|
||||
set instant = TRUE
|
||||
if(mob)
|
||||
mob.toggle_move_intent()
|
||||
|
||||
|
||||
@@ -69,4 +69,41 @@
|
||||
|
||||
/mob/proc/emote_vr(var/act, var/type, var/message) //This would normally go in say.dm
|
||||
if(act == "me")
|
||||
return custom_emote_vr(type, message)
|
||||
return custom_emote_vr(type, message)
|
||||
|
||||
/mob/proc/update_flavor_text()
|
||||
set src in usr
|
||||
if(usr != src)
|
||||
usr << "No."
|
||||
var/msg = input(usr,"Set the flavor text in your 'examine' verb. Can also be used for OOC notes about your character.","Flavor Text",html_decode(flavor_text)) as message|null
|
||||
|
||||
if(msg != null)
|
||||
msg = copytext(msg, 1, MAX_MESSAGE_LEN)
|
||||
msg = html_encode(msg)
|
||||
|
||||
flavor_text = msg
|
||||
|
||||
/mob/proc/warn_flavor_changed()
|
||||
if(flavor_text && flavor_text != "") // don't spam people that don't use it!
|
||||
src << "<h2 class='alert'>OOC Warning:</h2>"
|
||||
src << "<span class='alert'>Your flavor text is likely out of date! <a href='byond://?src=\ref[src];flavor_change=1'>Change</a></span>"
|
||||
|
||||
/mob/proc/print_flavor_text()
|
||||
if(flavor_text && flavor_text != "")
|
||||
var/msg = replacetext(flavor_text, "\n", " ")
|
||||
if(lentext(msg) <= 40)
|
||||
return "\blue [msg]"
|
||||
else
|
||||
return "\blue [copytext(msg, 1, 37)]... <a href='byond://?src=\ref[src];flavor_more=1'>More...</a>"
|
||||
|
||||
/mob/proc/get_top_level_mob()
|
||||
if(istype(src.loc,/mob)&&src.loc!=src)
|
||||
var/mob/M=src.loc
|
||||
return M.get_top_level_mob()
|
||||
return src
|
||||
|
||||
proc/get_top_level_mob(var/mob/S)
|
||||
if(istype(S.loc,/mob)&&S.loc!=S)
|
||||
var/mob/M=S.loc
|
||||
return M.get_top_level_mob()
|
||||
return S
|
||||
@@ -29,6 +29,18 @@
|
||||
var/list/stamped
|
||||
var/rigged = 0
|
||||
var/spam_flag = 0
|
||||
var/contact_poison // Reagent ID to transfer on contact
|
||||
var/contact_poison_volume = 0
|
||||
|
||||
|
||||
/obj/item/weapon/paper/pickup(user)
|
||||
if(contact_poison && ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
var/obj/item/clothing/gloves/G = H.gloves
|
||||
if(!istype(G) || G.transfer_prints)
|
||||
H.reagents.add_reagent(contact_poison,contact_poison_volume)
|
||||
contact_poison = null
|
||||
..()
|
||||
|
||||
|
||||
/obj/item/weapon/paper/New()
|
||||
@@ -166,7 +178,7 @@
|
||||
/obj/item/weapon/paper/proc/clearpaper()
|
||||
info = null
|
||||
stamps = null
|
||||
stamped = list()
|
||||
LAZYCLEARLIST(stamped)
|
||||
cut_overlays()
|
||||
updateinfolinks()
|
||||
update_icon()
|
||||
@@ -289,7 +301,7 @@
|
||||
else
|
||||
info += t // Oh, he wants to edit to the end of the file, let him.
|
||||
updateinfolinks()
|
||||
|
||||
i.on_write(src,usr)
|
||||
usr << browse("<HTML><HEAD><TITLE>[name]</TITLE></HEAD><BODY>[info_links]<HR>[stamps]</BODY></HTML>", "window=[name]") // Update the window
|
||||
update_icon()
|
||||
|
||||
@@ -326,9 +338,7 @@
|
||||
|
||||
stampoverlay.icon_state = "paper_[P.icon_state]"
|
||||
|
||||
if(!stamped)
|
||||
stamped = new
|
||||
stamped += P.icon_state
|
||||
LAZYADD(stamped, P.icon_state)
|
||||
add_overlay(stampoverlay)
|
||||
|
||||
user << "<span class='notice'>You stamp the paper with your rubber stamp.</span>"
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
max_integrity = 50
|
||||
|
||||
var/obj/item/weapon/paper/internalPaper
|
||||
var/list/stamped = list()
|
||||
|
||||
/obj/item/weapon/paperplane/New(loc, obj/item/weapon/paper/newPaper)
|
||||
..()
|
||||
@@ -20,13 +19,18 @@
|
||||
pixel_x = rand(-9, 9)
|
||||
if(newPaper)
|
||||
internalPaper = newPaper
|
||||
src.flags = newPaper.flags
|
||||
stamped = internalPaper.stamped
|
||||
flags = newPaper.flags
|
||||
newPaper.forceMove(src)
|
||||
else
|
||||
internalPaper = new /obj/item/weapon/paper(src)
|
||||
update_icon()
|
||||
|
||||
/obj/item/weapon/paperplane/Destroy()
|
||||
if(internalPaper)
|
||||
qdel(internalPaper)
|
||||
internalPaper = null
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/paperplane/suicide_act(mob/user)
|
||||
user.Stun(10)
|
||||
user.visible_message("<span class='suicide'>[user] jams the [src] in [user.p_their()] nose. It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
@@ -37,18 +41,18 @@
|
||||
|
||||
/obj/item/weapon/paperplane/update_icon()
|
||||
cut_overlays()
|
||||
if(!stamped)
|
||||
stamped = new
|
||||
else if(stamped)
|
||||
var/list/stamped = internalPaper.stamped
|
||||
if(stamped)
|
||||
for(var/S in stamped)
|
||||
var/obj/item/weapon/stamp/stamp = S
|
||||
var/image/stampoverlay = image('icons/obj/bureaucracy.dmi', "paperplane_[initial(stamp.icon_state)]")
|
||||
var/image/stampoverlay = image('icons/obj/bureaucracy.dmi', "paperplane_[stamped]")
|
||||
add_overlay(stampoverlay)
|
||||
|
||||
/obj/item/weapon/paperplane/attack_self(mob/user)
|
||||
user << "<span class='notice'>You unfold [src].</span>"
|
||||
var/internal_paper_tmp = internalPaper
|
||||
internalPaper = null
|
||||
qdel(src)
|
||||
user.put_in_hands(internalPaper)
|
||||
user.put_in_hands(internal_paper_tmp)
|
||||
|
||||
/obj/item/weapon/paperplane/attackby(obj/item/weapon/P, mob/living/carbon/human/user, params)
|
||||
..()
|
||||
@@ -57,15 +61,7 @@
|
||||
return
|
||||
|
||||
else if(istype(P, /obj/item/weapon/stamp)) //we don't randomize stamps on a paperplane
|
||||
|
||||
if (!stamped)
|
||||
stamped = new
|
||||
|
||||
stamped += P.type
|
||||
internalPaper.stamps += "<img src=large_[P.icon_state].png>" //stamps the paper inside!
|
||||
internalPaper.stamped = stamped
|
||||
internalPaper.attackby(P) //spoofed attack to update internal paper.
|
||||
user << "<span class='notice'>You stamp [src] with your rubber stamp.</span>"
|
||||
internalPaper.attackby(P, user) //spoofed attack to update internal paper.
|
||||
update_icon()
|
||||
|
||||
else if(P.is_hot())
|
||||
@@ -108,7 +104,7 @@
|
||||
return
|
||||
user << "<span class='notice'>You fold [src] into the shape of a plane!</span>"
|
||||
user.temporarilyRemoveItemFromInventory(src)
|
||||
I = new /obj/item/weapon/paperplane(loc, src)
|
||||
I = new /obj/item/weapon/paperplane(user, src)
|
||||
user.put_in_hands(I)
|
||||
else
|
||||
user << "<span class='notice'> You lack the dexterity to fold \the [src]. </span>"
|
||||
|
||||
@@ -162,3 +162,12 @@
|
||||
else
|
||||
icon_state = initial(icon_state) //looks like a normal pen when off.
|
||||
item_state = initial(item_state)
|
||||
|
||||
//Crayons path disambiguity sigh.
|
||||
/obj/item/proc/on_write(obj/item/weapon/paper/P, mob/user)
|
||||
return
|
||||
|
||||
/obj/item/weapon/pen/poison/on_write(obj/item/weapon/paper/P, mob/user)
|
||||
P.contact_poison = "delayed_toxin"
|
||||
P.contact_poison_volume = 10
|
||||
add_logs(user,P,"used poison pen on")
|
||||
@@ -53,9 +53,10 @@ var/global/list/rad_collectors = list()
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/machinery/power/rad_collector/can_be_unfasten_wrench(mob/user)
|
||||
/obj/machinery/power/rad_collector/can_be_unfasten_wrench(mob/user, silent)
|
||||
if(loaded_tank)
|
||||
user << "<span class='warning'>Remove the plasma tank first!</span>"
|
||||
if(!silent)
|
||||
user << "<span class='warning'>Remove the plasma tank first!</span>"
|
||||
return FAILED_UNFASTEN
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@
|
||||
return 1
|
||||
|
||||
/obj/machinery/power/emitter/attack_animal(mob/living/simple_animal/M)
|
||||
if(ismegafauna(M))
|
||||
if(ismegafauna(M) && anchored)
|
||||
state = 0
|
||||
anchored = FALSE
|
||||
M.visible_message("<span class='warning'>[M] rips [src] free from its moorings!</span>")
|
||||
@@ -217,9 +217,10 @@
|
||||
A.starting = loc
|
||||
A.fire()
|
||||
|
||||
/obj/machinery/power/emitter/can_be_unfasten_wrench(mob/user)
|
||||
/obj/machinery/power/emitter/can_be_unfasten_wrench(mob/user, silent)
|
||||
if(state == EM_WELDED)
|
||||
user << "<span class='warning'>[src] is welded to the floor!</span>"
|
||||
if(!silent)
|
||||
user << "<span class='warning'>[src] is welded to the floor!</span>"
|
||||
return FAILED_UNFASTEN
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -77,9 +77,10 @@ field_generator power level display
|
||||
else
|
||||
user << "<span class='warning'>The [src] needs to be firmly secured to the floor first!</span>"
|
||||
|
||||
/obj/machinery/field/generator/can_be_unfasten_wrench(mob/user)
|
||||
/obj/machinery/field/generator/can_be_unfasten_wrench(mob/user, silent)
|
||||
if(state == FG_WELDED)
|
||||
user << "<span class='warning'>[src] is welded to the floor!</span>"
|
||||
if(!silent)
|
||||
user << "<span class='warning'>[src] is welded to the floor!</span>"
|
||||
return FAILED_UNFASTEN
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@ var/list/blacklisted_tesla_types = typecacheof(list(/obj/machinery/atmospherics,
|
||||
var/mob/living/carbon/C = A
|
||||
C.dust()
|
||||
|
||||
/proc/tesla_zap(atom/source, zap_range = 3, power, explosive = FALSE)
|
||||
/proc/tesla_zap(atom/source, zap_range = 3, power, explosive = FALSE, stun_mobs = TRUE)
|
||||
. = source.dir
|
||||
if(power < 1000)
|
||||
return
|
||||
@@ -251,26 +251,27 @@ var/list/blacklisted_tesla_types = typecacheof(list(/obj/machinery/atmospherics,
|
||||
|
||||
//per type stuff:
|
||||
if(closest_tesla_coil)
|
||||
closest_tesla_coil.tesla_act(power, explosive)
|
||||
closest_tesla_coil.tesla_act(power, explosive, stun_mobs)
|
||||
|
||||
else if(closest_grounding_rod)
|
||||
closest_grounding_rod.tesla_act(power, explosive)
|
||||
closest_grounding_rod.tesla_act(power, explosive, stun_mobs)
|
||||
|
||||
else if(closest_mob)
|
||||
var/shock_damage = Clamp(round(power/400), 10, 90) + rand(-5, 5)
|
||||
closest_mob.electrocute_act(shock_damage, source, 1, tesla_shock = 1)
|
||||
closest_mob.electrocute_act(shock_damage, source, 1, tesla_shock = 1, stun = stun_mobs)
|
||||
if(issilicon(closest_mob))
|
||||
var/mob/living/silicon/S = closest_mob
|
||||
S.emp_act(2)
|
||||
tesla_zap(S, 7, power / 1.5) // metallic folks bounce it further
|
||||
if(stun_mobs)
|
||||
S.emp_act(2)
|
||||
tesla_zap(S, 7, power / 1.5, stun_mobs) // metallic folks bounce it further
|
||||
else
|
||||
tesla_zap(closest_mob, 5, power / 1.5)
|
||||
tesla_zap(closest_mob, 5, power / 1.5, stun_mobs)
|
||||
|
||||
else if(closest_machine)
|
||||
closest_machine.tesla_act(power, explosive)
|
||||
closest_machine.tesla_act(power, explosive, stun_mobs)
|
||||
|
||||
else if(closest_blob)
|
||||
closest_blob.tesla_act(power, explosive)
|
||||
closest_blob.tesla_act(power, explosive, stun_mobs)
|
||||
|
||||
else if(closest_structure)
|
||||
closest_structure.tesla_act(power, explosive)
|
||||
closest_structure.tesla_act(power, explosive, stun_mobs)
|
||||
|
||||
@@ -355,4 +355,3 @@
|
||||
user.emote("scream")
|
||||
user.drop_item()
|
||||
user.Weaken(4)
|
||||
return
|
||||
|
||||
@@ -165,6 +165,9 @@
|
||||
/obj/item/weapon/gun/ballistic/shotgun/boltaction/enchanted/arcane_barrage/discard_gun(mob/user)
|
||||
return
|
||||
|
||||
/obj/item/weapon/gun/ballistic/shotgun/boltaction/enchanted/attack_self()
|
||||
return
|
||||
|
||||
/obj/item/weapon/gun/ballistic/shotgun/boltaction/enchanted/shoot_live_shot(mob/living/user as mob|obj, pointblank = 0, mob/pbtarget = null, message = 1)
|
||||
..()
|
||||
if(guns_left)
|
||||
|
||||
@@ -376,28 +376,32 @@
|
||||
/obj/item/borg/upgrade/modkit/chassis_mod
|
||||
name = "super chassis"
|
||||
desc = "Makes your KA yellow. All the fun of having a more powerful KA without actually having a more powerful KA."
|
||||
cost = 10
|
||||
cost = 0
|
||||
denied_type = /obj/item/borg/upgrade/modkit/chassis_mod
|
||||
var/chassis_icon = "kineticgun_u"
|
||||
var/chassis_name = "super-kinetic accelerator"
|
||||
|
||||
/obj/item/borg/upgrade/modkit/chassis_mod/install(obj/item/weapon/gun/energy/kinetic_accelerator/KA, mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
KA.icon_state = chassis_icon
|
||||
KA.name = chassis_name
|
||||
|
||||
/obj/item/borg/upgrade/modkit/chassis_mod/uninstall(obj/item/weapon/gun/energy/kinetic_accelerator/KA)
|
||||
KA.icon_state = initial(KA.icon_state)
|
||||
KA.name = initial(KA.name)
|
||||
..()
|
||||
|
||||
/obj/item/borg/upgrade/modkit/chassis_mod/orange
|
||||
name = "hyper chassis"
|
||||
desc = "Makes your KA orange. All the fun of having explosive blasts without actually having explosive blasts."
|
||||
chassis_icon = "kineticgun_h"
|
||||
chassis_name = "hyper-kinetic accelerator"
|
||||
|
||||
/obj/item/borg/upgrade/modkit/tracer
|
||||
name = "white tracer bolts"
|
||||
desc = "Causes kinetic accelerator bolts to have a white tracer trail and explosion."
|
||||
cost = 4
|
||||
cost = 0
|
||||
denied_type = /obj/item/borg/upgrade/modkit/tracer
|
||||
var/bolt_color = "#FFFFFF"
|
||||
|
||||
|
||||
@@ -814,3 +814,23 @@
|
||||
if(prob(30))
|
||||
M << "You should sit down and take a rest..."
|
||||
..()
|
||||
|
||||
/datum/reagent/toxin/delayed
|
||||
name = "Toxin Microcapsules"
|
||||
id = "delayed_toxin"
|
||||
description = "Causes heavy toxin damage after a brief time of inactivity."
|
||||
reagent_state = LIQUID
|
||||
metabolization_rate = 0 //stays in the system until active.
|
||||
var/actual_metaboliztion_rate = REAGENTS_METABOLISM
|
||||
toxpwr = 0
|
||||
var/actual_toxpwr = 5
|
||||
var/delay = 30
|
||||
|
||||
/datum/reagent/toxin/delayed/on_mob_life(mob/living/M)
|
||||
if(current_cycle > delay)
|
||||
holder.remove_reagent(id, actual_metaboliztion_rate * M.metabolism_efficiency)
|
||||
M.adjustToxLoss(actual_toxpwr*REM, 0)
|
||||
if(prob(10))
|
||||
M.Weaken(1, 0)
|
||||
. = 1
|
||||
..()
|
||||
@@ -62,16 +62,17 @@
|
||||
deconstruct()
|
||||
|
||||
/obj/machinery/disposal/Initialize(mapload)
|
||||
..()
|
||||
if(!mapload)
|
||||
return
|
||||
//this will get a copy of the air turf and take a SEND PRESSURE amount of air from it
|
||||
var/atom/L = loc
|
||||
var/datum/gas_mixture/env = new
|
||||
env.copy_from(L.return_air())
|
||||
var/datum/gas_mixture/removed = env.remove(SEND_PRESSURE + 1)
|
||||
air_contents.merge(removed)
|
||||
trunk_check()
|
||||
. = mapload //late-initialize, we need turfs to have air
|
||||
if(initialized) //will only be run on late mapload initialization
|
||||
//this will get a copy of the air turf and take a SEND PRESSURE amount of air from it
|
||||
var/atom/L = loc
|
||||
var/datum/gas_mixture/env = new
|
||||
env.copy_from(L.return_air())
|
||||
var/datum/gas_mixture/removed = env.remove(SEND_PRESSURE + 1)
|
||||
air_contents.merge(removed)
|
||||
trunk_check()
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/machinery/disposal/attackby(obj/item/I, mob/user, params)
|
||||
add_fingerprint(user)
|
||||
|
||||
@@ -389,7 +389,9 @@
|
||||
launch_status = UNLAUNCHED
|
||||
|
||||
/obj/docking_port/mobile/pod/request()
|
||||
if(security_level == SEC_LEVEL_RED || security_level == SEC_LEVEL_DELTA)
|
||||
var/obj/machinery/computer/shuttle/S = getControlConsole()
|
||||
|
||||
if(security_level == SEC_LEVEL_RED || security_level == SEC_LEVEL_DELTA || (S && S.emagged))
|
||||
if(launch_status == UNLAUNCHED)
|
||||
launch_status = EARLY_LAUNCHED
|
||||
return ..()
|
||||
@@ -418,6 +420,11 @@
|
||||
/obj/machinery/computer/shuttle/pod/update_icon()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/shuttle/pod/emag_act(mob/user)
|
||||
if(!emagged)
|
||||
emagged = TRUE
|
||||
user << "<span class='warning'>You fry the pod's alert level checking system.</span>"
|
||||
|
||||
/obj/docking_port/stationary/random
|
||||
name = "escape pod"
|
||||
id = "pod"
|
||||
@@ -469,6 +476,7 @@
|
||||
density = 0
|
||||
icon = 'icons/obj/storage.dmi'
|
||||
icon_state = "safe"
|
||||
var/unlocked = FALSE
|
||||
|
||||
/obj/item/weapon/storage/pod/New()
|
||||
..()
|
||||
@@ -488,13 +496,18 @@
|
||||
return
|
||||
|
||||
/obj/item/weapon/storage/pod/MouseDrop(over_object, src_location, over_location)
|
||||
if(security_level == SEC_LEVEL_RED || security_level == SEC_LEVEL_DELTA)
|
||||
if(security_level == SEC_LEVEL_RED || security_level == SEC_LEVEL_DELTA || unlocked)
|
||||
. = ..()
|
||||
else
|
||||
usr << "The storage unit will only unlock during a Red or Delta security alert."
|
||||
|
||||
/obj/item/weapon/storage/pod/attack_hand(mob/user)
|
||||
return
|
||||
return MouseDrop(user)
|
||||
|
||||
/obj/item/weapon/storage/pod/onShuttleMove()
|
||||
unlocked = TRUE
|
||||
// If the pod was launched, the storage will always open.
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/docking_port/mobile/emergency/backup
|
||||
|
||||
@@ -699,4 +699,13 @@
|
||||
else
|
||||
dst = destination
|
||||
. += " towards [dst ? dst.name : "unknown location"] ([timeLeft(600)] minutes)"
|
||||
|
||||
|
||||
// attempts to locate /obj/machinery/computer/shuttle with matching ID inside the shuttle
|
||||
/obj/docking_port/mobile/proc/getControlConsole()
|
||||
for(var/obj/machinery/computer/shuttle/S in areaInstance)
|
||||
if(S.shuttleId == id)
|
||||
return S
|
||||
return null
|
||||
|
||||
#undef DOCKING_PORT_HIGHLIGHT
|
||||
|
||||
@@ -216,3 +216,42 @@
|
||||
var/obj/item/weapon/card/id/ID = user.get_idcard()
|
||||
if(ID && (access_cent_bar in ID.access))
|
||||
return TRUE
|
||||
|
||||
//Luxury Shuttle Blockers
|
||||
|
||||
/obj/effect/forcefield/luxury_shuttle
|
||||
var/threshhold = 500
|
||||
var/static/list/approved_passengers = list()
|
||||
|
||||
/obj/effect/forcefield/luxury_shuttle/CanPass(atom/movable/mover, turf/target, height=0)
|
||||
if(mover in approved_passengers)
|
||||
return 1
|
||||
|
||||
if(!isliving(mover)) //No stowaways
|
||||
return 0
|
||||
|
||||
var/total_cash = 0
|
||||
var/list/counted_money = list()
|
||||
|
||||
for(var/obj/item/weapon/coin/C in mover.GetAllContents())
|
||||
total_cash += C.value
|
||||
counted_money += C
|
||||
if(total_cash >= threshhold)
|
||||
break
|
||||
for(var/obj/item/stack/spacecash/S in mover.GetAllContents())
|
||||
total_cash += S.value * S.amount
|
||||
counted_money += S
|
||||
if(total_cash >= threshhold)
|
||||
break
|
||||
|
||||
if(total_cash >= threshhold)
|
||||
for(var/obj/I in counted_money)
|
||||
qdel(I)
|
||||
|
||||
mover << "Thank you for your payment! Please enjoy your flight."
|
||||
approved_passengers += mover
|
||||
return 1
|
||||
else
|
||||
mover << "You don't have enough money to enter the main shuttle. You'll have to fly coach."
|
||||
return 0
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
var/active_msg = "You charge your projectile!"
|
||||
var/base_icon_state = "projectile"
|
||||
var/active_icon_state = "projectile"
|
||||
var/projectile_damage_override = -1
|
||||
|
||||
/obj/effect/proc_holder/spell/aimed/Click()
|
||||
var/mob/living/user = usr
|
||||
@@ -54,6 +55,11 @@
|
||||
var/obj/item/projectile/P = new projectile_type(user.loc)
|
||||
P.current = get_turf(user)
|
||||
P.preparePixelProjectile(target, get_turf(target), user)
|
||||
if(projectile_damage_override != -1)
|
||||
P.damage = projectile_damage_override
|
||||
P.nodamage = TRUE
|
||||
if(P.damage)
|
||||
P.nodamage = FALSE
|
||||
P.fire()
|
||||
return TRUE
|
||||
|
||||
@@ -80,6 +86,11 @@
|
||||
var/obj/item/projectile/magic/aoe/lightning/P = new /obj/item/projectile/magic/aoe/lightning(user.loc)
|
||||
P.current = get_turf(user)
|
||||
P.preparePixelProjectile(target, get_turf(target), user)
|
||||
if(projectile_damage_override != -1)
|
||||
P.damage = projectile_damage_override
|
||||
P.nodamage = TRUE
|
||||
if(P.damage)
|
||||
P.nodamage = FALSE
|
||||
P.tesla_power = tesla_power
|
||||
P.tesla_range = tesla_range
|
||||
P.tesla_boom = tesla_boom
|
||||
|
||||
@@ -618,6 +618,13 @@ var/list/uplink_items = list() // Global list so we only initialize this once.
|
||||
cost = 4
|
||||
exclude_modes = list(/datum/game_mode/nuclear,/datum/game_mode/gang)
|
||||
|
||||
/datum/uplink_item/stealthy_weapons/poison_pen
|
||||
name = "Poison Pen"
|
||||
desc = "Cutting edge of deadly writing implements technology, this gadget will infuse any piece of paper with delayed contact poison."
|
||||
item = /obj/item/weapon/pen/poison
|
||||
cost = 2
|
||||
exclude_modes = list(/datum/game_mode/nuclear)
|
||||
|
||||
/datum/uplink_item/stealthy_weapons/soap
|
||||
name = "Syndicate Soap"
|
||||
desc = "A sinister-looking surfactant used to clean blood stains to hide murders and prevent DNA analysis. \
|
||||
@@ -1166,13 +1173,14 @@ var/list/uplink_items = list() // Global list so we only initialize this once.
|
||||
/datum/uplink_item/role_restricted
|
||||
category = "Role-Restricted"
|
||||
exclude_modes = list(/datum/game_mode/nuclear)
|
||||
surplus = 0
|
||||
|
||||
/datum/uplink_item/role_restricted/reverse_revolver
|
||||
name = "Reverse Revolver"
|
||||
desc = "A revolver that always fires at its user. \"Accidentally\" drop your weapon, then watch as the greedy corporate pigs blow their own brains all over the wall. \
|
||||
The revolver itself is actually real. Only clumsy people, and clowns, can fire it normally. Honk."
|
||||
The revolver itself is actually real. Only clumsy people, and clowns, can fire it normally. Comes in a box of hugs. Honk."
|
||||
cost = 14
|
||||
item = /obj/item/weapon/gun/ballistic/revolver/reverse
|
||||
item = /obj/item/weapon/storage/box/hug/reverse_revolver
|
||||
restricted_roles = list("Clown")
|
||||
|
||||
/datum/uplink_item/role_restricted/ez_clean_bundle
|
||||
|
||||
Reference in New Issue
Block a user