Merge branch 'master' of https://github.com/ParadiseSS13/Paradise into turfs

# Conflicts:
#	icons/mob/actions/actions.dmi
#	icons/mob/inhands/items_lefthand.dmi
#	icons/mob/inhands/items_righthand.dmi
#	paradise.dme
This commit is contained in:
Mark van Alphen
2019-05-17 17:37:18 +02:00
69 changed files with 710 additions and 331 deletions
+143
View File
@@ -88,7 +88,9 @@
//get message text, limit it's length.and clean/escape html
if(!msg)
set_typing(C, TRUE)
msg = input(src,"Message:", "Private message to [holder ? key_name(C, FALSE) : key_name_hidden(C, FALSE)]") as text|null
set_typing(C, FALSE)
if(!msg)
return
@@ -130,6 +132,9 @@
var/recieve_message = ""
pm_tracker.add_message(C, src, msg, mob)
C.pm_tracker.add_message(src, src, msg, C.mob)
if(holder && !C.holder)
recieve_message = "<span class='[recieve_span]' size='3'>-- Click the [recieve_pm_type]'s name to reply --</span>\n"
if(C.adminhelped)
@@ -233,3 +238,141 @@
continue
if(check_rights(R_ADMIN|R_MOD|R_MENTOR, 0, X.mob))
to_chat(X, "<B><font color='blue'>PM: [key_name(src, TRUE, 0)]-&gt;IRC-Admins:</B> <span class='notice'>[msg]</span></font>")
/client/verb/open_pms_ui()
set name = "My PMs"
set category = "OOC"
pm_tracker.show_ui(usr)
/client/proc/set_typing(client/target, value)
if(!target)
return
var/datum/pm_convo/convo = target.pm_tracker.pms[key]
if(!convo)
return
convo.typing = value
if(target.pm_tracker.open && target.pm_tracker.current_title == key)
target.pm_tracker.show_ui(target.mob)
/datum/pm_tracker
var/current_title = ""
var/open = FALSE
var/list/pms = list()
var/show_archived = FALSE
var/window_id = "pms_window"
/datum/pm_convo
var/list/messages = list()
var/archived = FALSE
var/client/client
var/read = FALSE
var/typing = FALSE
/datum/pm_convo/New(client/C)
client = C
/datum/pm_convo/proc/add(client/sender, message)
messages.Add("[sender]: [message]")
archived = FALSE
read = FALSE
/datum/pm_tracker/proc/add_message(client/title, client/sender, message, mob/user)
if(!pms[title.key])
pms[title.key] = new /datum/pm_convo(title)
pms[title.key].add(sender, message)
if(!open)
// The next time the window's opened, it'll be open to the most recent message
current_title = title.key
return
// If it's already opened, it'll refresh
show_ui(user)
/datum/pm_tracker/proc/show_ui(mob/user)
var/dat = ""
dat += "<a href='?src=[UID()];refresh=1'>Refresh</a>"
dat += "<a href='?src=[UID()];showarchived=1'>[show_archived ? "Hide" : "Show"] Archived</a>"
dat += "<br>"
for(var/title in pms)
if(pms[title].archived && !show_archived)
continue
var/label = "[title]"
var/class = ""
if(title == current_title)
label = "<b>[label]</b>"
class = "linkOn"
else if(!pms[title].read)
label = "<i>*[label]</i>"
dat += "<a class='[class]' href='?src=[UID()];newtitle=[title]'>[label]</a>"
var/datum/pm_convo/convo = pms[current_title]
if(convo)
convo.read = TRUE
dat += "<h2>[check_rights(R_ADMIN, FALSE, user) ? fancy_title(current_title) : current_title]</h2>"
dat += "<h4>"
dat += "<table style='width:950px; border: 3px solid;'>"
for(var/message in convo.messages)
dat += "<tr><td>[message]</td></tr>"
dat += "</table>"
if(convo.typing)
dat += "<i><span class='typing'>[current_title] is typing</span></i>"
dat += "<br>"
dat += "</h4>"
dat += "<a href='?src=[UID()];reply=[current_title]'>Reply</a>"
dat += "<a href='?src=[UID()];archive=[current_title]'>[convo.archived ? "Unarchive" : "Archive"]</a>"
if(check_rights(R_ADMIN, FALSE, user))
dat += "<a href='?src=[UID()];ping=[current_title]'>Ping</a>"
var/datum/browser/popup = new(user, window_id, "Messages", 1000, 600, src)
popup.set_content(dat)
popup.open()
open = TRUE
/datum/pm_tracker/proc/fancy_title(title)
var/client/C = pms[title].client
if(!C)
return "[title] (Disconnected)"
return "[key_name(C, FALSE)] ([ADMIN_QUE(C.mob,"?")]) ([ADMIN_PP(C.mob,"PP")]) ([ADMIN_VV(C.mob,"VV")]) ([ADMIN_SM(C.mob,"SM")]) ([admin_jump_link(C.mob)]) (<A HREF='?_src_=holder;check_antagonist=1'>CA</A>)"
/datum/pm_tracker/Topic(href, href_list)
if(href_list["archive"])
pms[href_list["archive"]].archived = !pms[href_list["archive"]].archived
show_ui(usr)
return
if(href_list["refresh"])
show_ui(usr)
return
if(href_list["newtitle"])
current_title = href_list["newtitle"]
show_ui(usr)
return
if(href_list["ping"])
var/client/C = pms[href_list["ping"]].client
if(C)
C.pm_tracker.current_title = usr.key
window_flash(C)
C.pm_tracker.show_ui(C.mob)
to_chat(usr, "<span class='notice'>Forced open [C]'s messages window.</span>")
show_ui(usr)
return
if(href_list["reply"])
usr.client.cmd_admin_pm(ckey(href_list["reply"]), null)
show_ui(usr)
return
if(href_list["showarchived"])
show_archived = !show_archived
show_ui(usr)
return
if(href_list["close"])
open = FALSE
return
@@ -177,6 +177,11 @@ client/proc/one_click_antag()
H = pick(candidates)
SSticker.mode.add_cultist(H.mind)
candidates.Remove(H)
if(!summon_spots.len)
while(summon_spots.len < SUMMON_POSSIBILITIES)
var/area/summon = pick(return_sorted_areas() - summon_spots)
if(summon && is_station_level(summon.z) && summon.valid_territory)
summon_spots += summon
return 1
return 0
+1
View File
@@ -7,6 +7,7 @@
var/last_message = "" //contains the last message sent by this client - used to protect against copy-paste spamming.
var/last_message_count = 0 //contains a number of how many times a message identical to last_message was sent.
var/last_message_time = 0 //holds the last time (based on world.time) a message was sent
var/datum/pm_tracker/pm_tracker = new()
/////////
//OTHER//
+2 -2
View File
@@ -688,8 +688,8 @@
message += " (RESTRICTED)"
to_chat(world, "[message]")
/client/proc/colour_transition(var/list/colour_to = null, var/time = 10) //Call this with no parameters to reset to default.
animate(src, color=colour_to, time=time, easing=SINE_EASING)
/client/proc/colour_transition(list/colour_to = null, time = 10) //Call this with no parameters to reset to default.
animate(src, color = colour_to, time = time, easing = SINE_EASING)
/client/proc/on_varedit()
var_edited = TRUE
+4 -4
View File
@@ -256,16 +256,16 @@
desc = "Somehow these seem even more out-of-date than normal sunglasses."
actions_types = list(/datum/action/item_action/noir)
/obj/item/clothing/glasses/sunglasses/noir/attack_self()
toggle_noir()
/obj/item/clothing/glasses/sunglasses/noir/attack_self(mob/user)
toggle_noir(user)
/obj/item/clothing/glasses/sunglasses/noir/item_action_slot_check(slot)
if(slot == slot_glasses)
return 1
/obj/item/clothing/glasses/sunglasses/noir/proc/toggle_noir()
/obj/item/clothing/glasses/sunglasses/noir/proc/toggle_noir(mob/user)
color_view = color_view ? null : MATRIX_GREYSCALE //Toggles between null and grayscale, with null being the default option.
usr.update_client_colour()
user.update_client_colour()
/obj/item/clothing/glasses/sunglasses/yeah
name = "agreeable glasses"
+1
View File
@@ -213,6 +213,7 @@
name = "security gas mask"
desc = "A standard issue Security gas mask with integrated 'Compli-o-nator 3000' device, plays over a dozen pre-recorded compliance phrases designed to get scumbags to stand still whilst you taze them. Do not tamper with the device."
icon_state = "sechailer"
item_state = "sechailer"
var/phrase = 1
var/aggressiveness = 1
var/safety = 1
@@ -409,6 +409,7 @@
for(var/obj/O in contents)
if(O.name == K)
O.forceMove(loc)
adjust_item_drop_location(O)
update_icon()
i--
if(i <= 0)
+15 -8
View File
@@ -207,19 +207,26 @@
/datum/action/innate/minedrone/toggle_meson_vision
name = "Toggle Meson Vision"
button_icon_state = "meson"
var/sight_flags = SEE_TURFS
var/lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
/datum/action/innate/minedrone/toggle_meson_vision/Activate()
var/mob/living/simple_animal/hostile/mining_drone/user = owner
if(user.sight & SEE_TURFS)
user.sight &= ~SEE_TURFS
user.lighting_alpha = initial(user.lighting_alpha)
var/mob/living/user = owner
var/is_active = user.sight & SEE_TURFS
if(is_active)
UnregisterSignal(user, COMSIG_MOB_UPDATE_SIGHT)
user.update_sight()
else
user.sight |= SEE_TURFS
user.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
RegisterSignal(user, COMSIG_MOB_UPDATE_SIGHT, .proc/update_user_sight)
user.update_sight()
user.sync_lighting_plane_alpha()
to_chat(user, "<span class='notice'>You toggle your meson vision [!is_active ? "on" : "off"].</span>")
to_chat(user, "<span class='notice'>You toggle your meson vision [(user.sight & SEE_TURFS) ? "on" : "off"].</span>")
/datum/action/innate/minedrone/toggle_meson_vision/proc/update_user_sight(mob/living/user)
user.sight |= sight_flags
if(!isnull(lighting_alpha))
user.lighting_alpha = min(user.lighting_alpha, lighting_alpha)
/datum/action/innate/minedrone/toggle_mode
name = "Toggle Mode"
@@ -619,12 +619,14 @@
/datum/pai_software/flashlight/toggle(mob/living/silicon/pai/user)
var/atom/movable/actual_location = istype(user.loc, /obj/item/paicard) ? user.loc : user
if(user.flashlight_on)
if(!user.flashlight_on)
actual_location.set_light(2)
user.card.set_light(2)
return
actual_location.set_light(2)
user.card.set_light(0)
else
actual_location.set_light(0)
user.card.set_light(0)
user.flashlight_on = !user.flashlight_on
/datum/pai_software/flashlight/is_active(mob/living/silicon/pai/user)
return user.flashlight_on
@@ -59,9 +59,6 @@
return
target.attack_animal(src)
/obj/item/organ/internal/body_egg/changeling_egg
name = "changeling egg"
desc = "Twitching and disgusting."
@@ -91,7 +88,12 @@
if(origin.changeling.can_absorb_dna(M, owner))
origin.changeling.absorb_dna(owner, M)
origin.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/humanform(null)
var/datum/action/changeling/humanform/HF = new
HF.Grant(M)
for(var/power in origin.changeling.purchasedpowers)
var/datum/action/changeling/S = power
if(istype(S) && S.needs_button)
S.Grant(M)
M.key = origin.key
owner.gib()
-10
View File
@@ -956,9 +956,6 @@ var/list/slot_equipment_priority = list( \
statpanel("Status") // We only want alt-clicked turfs to come before Status
if(mind && mind.changeling)
add_stings_to_statpanel(mind.changeling.purchasedpowers)
if(mob_spell_list && mob_spell_list.len)
for(var/obj/effect/proc_holder/spell/S in mob_spell_list)
add_spell_to_statpanel(S)
@@ -1025,12 +1022,6 @@ var/list/slot_equipment_priority = list( \
statpanel_things += A
statpanel(listed_turf.name, null, statpanel_things)
/mob/proc/add_stings_to_statpanel(var/list/stings)
for(var/obj/effect/proc_holder/changeling/S in stings)
if(S.chemical_cost >=0 && S.can_be_used_by(src))
statpanel("[S.panel]",((S.chemical_cost > 0) ? "[S.chemical_cost]" : ""),S)
/mob/proc/add_spell_to_statpanel(var/obj/effect/proc_holder/spell/S)
switch(S.charge_type)
if("recharge")
@@ -1040,7 +1031,6 @@ var/list/slot_equipment_priority = list( \
if("holdervar")
statpanel(S.panel,"[S.holder_var_type] [S.holder_var_amount]",S)
// facing verbs
/mob/proc/canface()
if(!canmove) return 0
+1 -11
View File
@@ -10,7 +10,6 @@
var/giftwrapped = 0
var/sortTag = 0
/obj/structure/bigDelivery/attack_hand(mob/user as mob)
playsound(src.loc, 'sound/items/poster_ripped.ogg', 50, 1)
if(wrapped)
@@ -24,7 +23,6 @@
qdel(src)
/obj/structure/bigDelivery/attackby(obj/item/W as obj, mob/user as mob, params)
if(istype(W, /obj/item/destTagger))
var/obj/item/destTagger/O = W
@@ -67,17 +65,16 @@
else
to_chat(user, "<span class='notice'>You need more paper.</span>")
/obj/item/smallDelivery
name = "small parcel"
desc = "A small wrapped package."
icon = 'icons/obj/storage.dmi'
icon_state = "deliverycrateSmall"
item_state = "deliverypackage"
var/obj/item/wrapped = null
var/giftwrapped = 0
var/sortTag = 0
/obj/item/smallDelivery/attack_self(mob/user as mob)
if(wrapped && wrapped.loc) //sometimes items can disappear. For example, bombs. --rastaf0
wrapped.loc = user.loc
@@ -88,7 +85,6 @@
playsound(src.loc, 'sound/items/poster_ripped.ogg', 50, 1)
qdel(src)
/obj/item/smallDelivery/attackby(obj/item/W as obj, mob/user as mob, params)
if(istype(W, /obj/item/destTagger))
var/obj/item/destTagger/O = W
@@ -128,8 +124,6 @@
else
to_chat(user, "<span class='notice'>You need more paper.</span>")
/obj/item/stack/packageWrap
name = "package wrapper"
icon = 'icons/obj/items.dmi'
@@ -140,7 +134,6 @@
max_amount = 25
burn_state = FLAMMABLE
/obj/item/stack/packageWrap/afterattack(var/obj/target as obj, mob/user as mob, proximity)
if(!proximity) return
if(!istype(target)) //this really shouldn't be necessary (but it is). -Pete
@@ -153,8 +146,6 @@
if(target in user)
return
if(istype(target, /obj/item) && !(istype(target, /obj/item/storage) && !istype(target,/obj/item/storage/box) && !istype(target, /obj/item/shippingPackage)))
var/obj/item/O = target
if(use(1))
@@ -364,7 +355,6 @@
to_chat(user, "You need more welding fuel to complete this task.")
return
/obj/item/shippingPackage
name = "Shipping package"
desc = "A pre-labeled package for shipping an item to coworkers."
+73 -88
View File
@@ -55,13 +55,9 @@ var/ert_request_answered = FALSE
to_chat(src, "<span class='boldnotice'>Upon using the antagHUD you forfeited the ability to join the round.</span>")
return 0
if(response_team_members.len > 6)
to_chat(src, "<span class='warning'>The emergency response team is already full!</span>")
return 0
return 1
/proc/trigger_armed_response_team(var/datum/response_team/response_team_type, commander_slots, security_slots, medical_slots, engineering_slots, janitor_slots, paranormal_slots, cyborg_slots)
/proc/trigger_armed_response_team(datum/response_team/response_team_type, commander_slots, security_slots, medical_slots, engineering_slots, janitor_slots, paranormal_slots, cyborg_slots)
response_team_members = list()
active_team = response_team_type
active_team.setSlots(commander_slots, security_slots, medical_slots, engineering_slots, janitor_slots, paranormal_slots, cyborg_slots)
@@ -71,7 +67,7 @@ var/ert_request_answered = FALSE
if(!ert_candidates.len)
active_team.cannot_send_team()
send_emergency_team = FALSE
return 0
return
// Respawnable players get first dibs
for(var/mob/dead/observer/M in ert_candidates)
@@ -87,38 +83,58 @@ var/ert_request_answered = FALSE
if(!response_team_members.len)
active_team.cannot_send_team()
send_emergency_team = FALSE
return 0
return
var/index = 1
var/list/ert_gender_prefs = list()
for(var/mob/M in response_team_members)
if(index > emergencyresponseteamspawn.len)
index = 1
ert_gender_prefs.Add(input_async(M, "Please select a gender (10 seconds):", list("Male", "Female")))
addtimer(CALLBACK(GLOBAL_PROC, .proc/get_ert_role_prefs, response_team_members, ert_gender_prefs), 100)
/proc/get_ert_role_prefs(list/response_team_members, list/ert_gender_prefs)
var/list/ert_role_prefs = list()
for(var/datum/async_input/A in ert_gender_prefs)
A.close()
for(var/mob/M in response_team_members)
ert_role_prefs.Add(input_ranked_async(M, "Please order ERT roles from most to least preferred (15 seconds):", active_team.get_slot_list()))
addtimer(CALLBACK(GLOBAL_PROC, .proc/dispatch_response_team, response_team_members, ert_gender_prefs, ert_role_prefs), 150)
/proc/dispatch_response_team(list/response_team_members, list/ert_gender_prefs, list/ert_role_prefs)
var/spawn_index = 1
for(var/i = 1, i <= response_team_members.len, i++)
if(spawn_index > emergencyresponseteamspawn.len)
break
if(!active_team.get_slot_list().len)
break
var/gender_pref = ert_gender_prefs[i].result
var/role_pref = ert_role_prefs[i].close()
var/mob/M = response_team_members[i]
if(!M || !M.client)
continue
log_debug("Spawning as ERT: [M.ckey] ([M])")
var/client/C = M.client
var/mob/living/new_commando = C.create_response_team(emergencyresponseteamspawn[index])
if(!M || !new_commando)
if(!gender_pref || !role_pref)
// Player was afk and did not select
continue
new_commando.mind.key = M.key
new_commando.key = M.key
new_commando.update_icons()
index++
for(var/role in role_pref)
if(active_team.check_slot_available(role))
var/mob/living/new_commando = M.client.create_response_team(gender_pref, role, emergencyresponseteamspawn[spawn_index])
active_team.reduceSlots(role)
spawn_index++
if(!M || !new_commando)
break
new_commando.mind.key = M.key
new_commando.key = M.key
new_commando.update_icons()
break
send_emergency_team = FALSE
active_team.announce_team()
return 1
/client/proc/create_response_team(var/turf/spawn_location)
var/class = 0
while(!class)
class = input(src, "Which loadout would you like to choose?") in active_team.get_slot_list()
if(!active_team.check_slot_available(class)) // Because the prompt does not update automatically when a slot gets filled.
class = 0
if(active_team.count)
active_team.announce_team()
return
// Everyone who said yes was afk
active_team.cannot_send_team()
if(class == "Cyborg")
active_team.reduceCyborgSlots()
/client/proc/create_response_team(new_gender, role, turf/spawn_location)
if(role == "Cyborg")
var/cyborg_unlock = active_team.getCyborgUnlock()
var/mob/living/silicon/robot/ert/R = new /mob/living/silicon/robot/ert(spawn_location, cyborg_unlock)
return R
@@ -126,8 +142,6 @@ var/ert_request_answered = FALSE
var/mob/living/carbon/human/M = new(null)
var/obj/item/organ/external/head/head_organ = M.get_organ("head")
var/new_gender = alert(src, "Please select your gender.", "ERT Character Generation", "Male", "Female")
if(new_gender)
if(new_gender == "Male")
M.change_gender(MALE)
@@ -169,21 +183,24 @@ var/ert_request_answered = FALSE
SSticker.mode.ert += M.mind
M.forceMove(spawn_location)
SSjobs.CreateMoneyAccount(M, class, null)
SSjobs.CreateMoneyAccount(M, role, null)
active_team.equip_officer(class, M)
active_team.equip_officer(role, M)
return M
/datum/response_team
var/command_slots = 1
var/engineer_slots = 3
var/medical_slots = 3
var/security_slots = 3
var/janitor_slots = 0
var/paranormal_slots = 0
var/cyborg_slots = 0
var/list/slots = list(
Commander = 0,
Security = 0,
Engineer = 0,
Medic = 0,
Janitor = 0,
Paranormal = 0,
Cyborg = 0
)
var/count = 0
var/command_outfit
var/engineering_outfit
@@ -193,88 +210,56 @@ var/ert_request_answered = FALSE
var/paranormal_outfit
var/cyborg_unlock = 0
/datum/response_team/proc/setSlots(com, sec, med, eng, jan, par, cyb)
command_slots = com == null ? command_slots : com
security_slots = sec == null ? security_slots : sec
medical_slots = med == null ? medical_slots : med
engineer_slots = eng == null ? engineer_slots : eng
janitor_slots = jan == null ? janitor_slots : jan
paranormal_slots = par == null ? paranormal_slots : par
cyborg_slots = cyb == null ? cyborg_slots : cyb
/datum/response_team/proc/setSlots(com=1, sec=3, med=3, eng=3, jan=0, par=0, cyb=0)
slots["Commander"] = com
slots["Security"] = sec
slots["Medic"] = med
slots["Engineer"] = eng
slots["Janitor"] = jan
slots["Paranormal"] = par
slots["Cyborg"] = cyb
/datum/response_team/proc/reduceCyborgSlots()
cyborg_slots--
/datum/response_team/proc/reduceSlots(role)
slots[role]--
count++
/datum/response_team/proc/getCyborgUnlock()
return cyborg_unlock
/datum/response_team/proc/get_slot_list()
var/list/slots_available = list()
if(command_slots)
slots_available |= "Commander"
if(security_slots)
slots_available |= "Security"
if(engineer_slots)
slots_available |= "Engineer"
if(medical_slots)
slots_available |= "Medic"
if(janitor_slots)
slots_available |= "Janitor"
if(paranormal_slots)
slots_available |= "Paranormal"
if(cyborg_slots)
slots_available |= "Cyborg"
for(var/role in slots)
if(slots[role])
slots_available.Add(role)
return slots_available
/datum/response_team/proc/check_slot_available(var/slot)
switch(slot)
if("Commander")
return command_slots
if("Security")
return security_slots
if("Engineer")
return engineer_slots
if("Medic")
return medical_slots
if("Janitor")
return janitor_slots
if("Paranormal")
return paranormal_slots
if("Cyborg")
return cyborg_slots
return 0
/datum/response_team/proc/check_slot_available(role)
return slots[role]
/datum/response_team/proc/equip_officer(var/officer_type, var/mob/living/carbon/human/M)
switch(officer_type)
if("Engineer")
engineer_slots -= 1
M.equipOutfit(engineering_outfit)
M.job = "ERT Engineering"
if("Security")
security_slots -= 1
M.equipOutfit(security_outfit)
M.job = "ERT Security"
if("Medic")
medical_slots -= 1
M.equipOutfit(medical_outfit)
M.job = "ERT Medical"
if("Janitor")
janitor_slots -= 1
M.equipOutfit(janitor_outfit)
M.job = "ERT Janitor"
if("Paranormal")
paranormal_slots -= 1
M.equipOutfit(paranormal_outfit)
M.job = "ERT Paranormal"
M.mind.isholy = TRUE
if("Commander")
command_slots = 0
// Override name and age for the commander
M.rename_character(null, "[pick("Lieutenant", "Captain", "Major")] [pick(GLOB.last_names)]")
M.age = rand(35,45)