Ghost Roles (#6706)

This commit is contained in:
Werner
2019-08-10 23:57:49 +02:00
committed by GitHub
parent 15fcefb923
commit a8e4e7f88c
36 changed files with 1865 additions and 683 deletions

View File

@@ -169,6 +169,7 @@
#include "code\controllers\subsystems\falling.dm" #include "code\controllers\subsystems\falling.dm"
#include "code\controllers\subsystems\garbage-debug.dm" #include "code\controllers\subsystems\garbage-debug.dm"
#include "code\controllers\subsystems\garbage.dm" #include "code\controllers\subsystems\garbage.dm"
#include "code\controllers\subsystems\ghostroles.dm"
#include "code\controllers\subsystems\global_listener.dm" #include "code\controllers\subsystems\global_listener.dm"
#include "code\controllers\subsystems\icon_cache.dm" #include "code\controllers\subsystems\icon_cache.dm"
#include "code\controllers\subsystems\icon_smooth.dm" #include "code\controllers\subsystems\icon_smooth.dm"
@@ -1231,7 +1232,6 @@
#include "code\modules\cargo\random_stock\~undefs.dm" #include "code\modules\cargo\random_stock\~undefs.dm"
#include "code\modules\cciaa\cciaa.dm" #include "code\modules\cciaa\cciaa.dm"
#include "code\modules\cciaa\cciaa_items.dm" #include "code\modules\cciaa\cciaa_items.dm"
#include "code\modules\cciaa\ert_cmd.dm"
#include "code\modules\client\asset_cache.dm" #include "code\modules\client\asset_cache.dm"
#include "code\modules\client\client defines.dm" #include "code\modules\client\client defines.dm"
#include "code\modules\client\client procs.dm" #include "code\modules\client\client procs.dm"
@@ -1473,6 +1473,15 @@
#include "code\modules\games\spaceball_cards.dm" #include "code\modules\games\spaceball_cards.dm"
#include "code\modules\games\tarot.dm" #include "code\modules\games\tarot.dm"
#include "code\modules\genetics\side_effects.dm" #include "code\modules\genetics\side_effects.dm"
#include "code\modules\ghostroles\spawner\base.dm"
#include "code\modules\ghostroles\spawner\human\admin.dm"
#include "code\modules\ghostroles\spawner\human\emergencypod.dm"
#include "code\modules\ghostroles\spawner\human\human.dm"
#include "code\modules\ghostroles\spawner\human\merchant.dm"
#include "code\modules\ghostroles\spawner\human\visitor.dm"
#include "code\modules\ghostroles\spawner\simplemob\maintdrone.dm"
#include "code\modules\ghostroles\spawner\simplemob\rat.dm"
#include "code\modules\ghostroles\spawnpoint\spawnpoint.dm"
#include "code\modules\ghosttrap\trap.dm" #include "code\modules\ghosttrap\trap.dm"
#include "code\modules\global_listener\devices.dm" #include "code\modules\global_listener\devices.dm"
#include "code\modules\global_listener\interfaces.dm" #include "code\modules\global_listener\interfaces.dm"
@@ -2477,6 +2486,7 @@
#include "code\unit_tests\mob_tests.dm" #include "code\unit_tests\mob_tests.dm"
#include "code\unit_tests\object_tests.dm" #include "code\unit_tests\object_tests.dm"
#include "code\unit_tests\observation_tests.dm" #include "code\unit_tests\observation_tests.dm"
#include "code\unit_tests\spawner_tests.dm"
#include "code\unit_tests\sql_tests.dm" #include "code\unit_tests\sql_tests.dm"
#include "code\unit_tests\ss_test.dm" #include "code\unit_tests\ss_test.dm"
#include "code\unit_tests\unit_test.dm" #include "code\unit_tests\unit_test.dm"

View File

@@ -91,6 +91,7 @@
#define slot_r_ear 20 #define slot_r_ear 20
#define slot_legs 21 #define slot_legs 21
#define slot_tie 22 #define slot_tie 22
#define slot_in_belt 23
// Inventory slot strings. // Inventory slot strings.
// since numbers cannot be used as associative list keys. // since numbers cannot be used as associative list keys.

View File

@@ -0,0 +1,176 @@
/var/datum/controller/subsystem/ghostroles/SSghostroles
/datum/controller/subsystem/ghostroles
name = "Ghost Roles"
flags = SS_NO_FIRE
var/list/spawnpoints = list() //List of the available spawnpoints by spawnpoint type
// -> type 1 -> spawnpoint 1
// -> spawnpoint 2
var/list/spawners = list() //List of the available spawner datums
/datum/controller/subsystem/ghostroles/Recover()
src.spawnpoints = SSghostroles.spawnpoints
src.spawners = SSghostroles.spawners
/datum/controller/subsystem/ghostroles/New()
NEW_SS_GLOBAL(SSghostroles)
/datum/controller/subsystem/ghostroles/Initialize(start_timeofday)
. = ..()
for(var/spawner in subtypesof(/datum/ghostspawner))
CHECK_TICK
var/datum/ghostspawner/G = new spawner
//Check if we have name, short_name and desc set
if(!G.short_name || !G.name || !G.desc)
log_ss("ghostroles","Spawner [G.type] got removed from selection because of missing data")
continue
//Check if we have a spawnpoint on the current map
if(!G.select_spawnpoint(FALSE))
log_debug("ghostroles","Spawner [G.type] got removed from selection because of missing spawnpoint")
continue
spawners[G.short_name] = G
for (var/identifier in spawnpoints)
CHECK_TICK
update_spawnpoint_status_by_identifier(identifier)
//Adds a spawnpoint to the spawnpoint list
/datum/controller/subsystem/ghostroles/proc/add_spawnpoints(var/obj/effect/ghostspawpoint/P)
if(!P.identifier) //If the spawnpoint has no identifier -> Abort
log_ss("ghostroles","Spawner [P] at [P.x],[P.y],[P.z] has no identifier set")
qdel(P)
return
if(!spawnpoints[P.identifier])
spawnpoints[P.identifier] = list()
spawnpoints[P.identifier].Add(P)
//Only update the status if the round is started. During initialization that´s taken care of at the end of init.
if(ROUND_IS_STARTED)
update_spawnpoint_status(P)
/datum/controller/subsystem/ghostroles/proc/update_spawnpoint_status(var/obj/effect/ghostspawpoint/P)
if(!P || !istype(P))
return null
//If any of the spawners uses that spawnpoint and is active set the status to available
for(var/s in spawners)
var/datum/ghostspawner/G = spawners[s]
if(!G.is_enabled())
continue
if(!(P.identifier in G.spawnpoints))
continue
P.set_available()
return TRUE
P.set_unavailable()
return FALSE
/datum/controller/subsystem/ghostroles/proc/update_spawnpoint_status_by_identifier(var/identifier)
if(!identifier) //If no identifier ist set, return false
return null
if(!length(spawnpoints[identifier])) //If we have no spawnpoints for that identifier, return false
return null
for (var/spawnpoint in spawnpoints[identifier])
CHECK_TICK
var/obj/effect/ghostspawpoint/P = spawnpoint
update_spawnpoint_status(P)
/datum/controller/subsystem/ghostroles/proc/remove_spawnpoints(var/obj/effect/ghostspawpoint/G)
spawnpoints[G.identifier].Remove(G)
return
//Returns the turf where the spawnpoint is located and updates the spawner to be used
/datum/controller/subsystem/ghostroles/proc/get_spawnpoint(var/identifier, var/use = TRUE)
if(!identifier) //If no identifier ist set, return false
return null
if(!length(spawnpoints[identifier])) //If we have no spawnpoints for that identifier, return false
return null
for (var/spawnpoint in spawnpoints[identifier])
var/obj/effect/ghostspawpoint/P = spawnpoint
if(P.is_available())
if(use)
P.set_spawned()
return get_turf(P)
/datum/controller/subsystem/ghostroles/proc/vui_interact(mob/user,var/spawnpoint=null)
var/datum/vueui/ui = SSvueui.get_open_ui(user,src)
if(!ui)
ui = new(user,src,"misc-ghostspawner",950,700,"Ghost Role Spawner", nstate = interactive_state)
ui.data = vueui_data_change(list("spawnpoint"=spawnpoint,"current_tag"="All"),user,ui)
ui.open()
/datum/controller/subsystem/ghostroles/vueui_data_change(var/list/data, var/mob/user, var/datum/vueui/ui)
if(!data)
. = data = list("current_tag"="All")
LAZYINITLIST(data["spawners"])
for(var/s in spawners)
var/datum/ghostspawner/G = spawners[s]
if(G.cant_see(user))
//if we have this spawner in our data list, then remove it
if(data["spawners"][G.short_name])
data["spawners"] -= G.short_name
continue
LAZYINITLIST(data["spawners"][G.short_name])
VUEUI_SET_CHECK(data["spawners"][G.short_name]["name"], G.name, ., data)
VUEUI_SET_CHECK(data["spawners"][G.short_name]["desc"], G.desc, ., data)
VUEUI_SET_CHECK(data["spawners"][G.short_name]["cant_spawn"], G.cant_spawn(user), ., data)
VUEUI_SET_CHECK(data["spawners"][G.short_name]["can_edit"], G.can_edit(user), ., data)
VUEUI_SET_CHECK(data["spawners"][G.short_name]["enabled"], G.enabled, ., data)
VUEUI_SET_CHECK(data["spawners"][G.short_name]["count"], G.count, ., data)
VUEUI_SET_CHECK(data["spawners"][G.short_name]["max_count"], G.max_count, ., data)
VUEUI_SET_CHECK(data["spawners"][G.short_name]["tags"], G.tags, ., data)
VUEUI_SET_CHECK(data["spawners"][G.short_name]["spawnpoints"], G.spawnpoints, ., data)
/datum/controller/subsystem/ghostroles/Topic(href, href_list)
var/datum/vueui/ui = href_list["vueui"]
if(!istype(ui))
return
if(href_list["spawn"])
var/spawner = href_list["spawn"]
var/datum/ghostspawner/S = spawners[spawner]
if(!S)
return
var/cant_spawn = S.cant_spawn(usr)
if(cant_spawn)
to_chat(usr, "Unable to spawn: [cant_spawn]")
return
if(!S.pre_spawn(usr))
to_chat(usr, "Unable to spawn: pre_spawn failed. Report this on GitHub")
return
var/mob/M = S.spawn_mob(usr)
if(!M)
to_chat(usr, "Unable to spawn: spawn_mob failed. Report this on GitHub")
return
if(!S.post_spawn(M))
to_chat(usr, "Unable to spawn: post_spawn failed. Report this on GitHub")
return
log_and_message_admins("joined as GhostRole: [S.name]", M)
SSvueui.check_uis_for_change(src) //Make sure to update all the UIs so the count is updated
if(href_list["enable"])
var/datum/ghostspawner/S = spawners[href_list["enable"]]
if(!S)
return
if(!S.can_edit(usr))
return
if(!S.enabled)
S.enable()
to_chat(usr, "Ghost spawner enabled: [S.name]")
SSvueui.check_uis_for_change(src) //Update all the UIs to update the status of the spawner
for(var/i in S.spawnpoints)
update_spawnpoint_status_by_identifier(i)
if(href_list["disable"])
var/datum/ghostspawner/S = spawners[href_list["disable"]]
if(!S)
return
if(!S.can_edit(usr))
return
if(S.enabled)
S.disable()
to_chat(usr, "Ghost spawner disabled: [S.name]")
SSvueui.check_uis_for_change(src) //Update all the UIs to update the status of the spawner
for(var/i in S.spawnpoints)
update_spawnpoint_status_by_identifier(i)
return

View File

@@ -29,7 +29,7 @@
var/internals_slot = null //ID of slot containing a gas tank var/internals_slot = null //ID of slot containing a gas tank
var/list/backpack_contents = list() //In the list(path=count,otherpath=count) format var/list/backpack_contents = list() //In the list(path=count,otherpath=count) format
var/list/accessory_contents = list() var/list/accessory_contents = list()
var/list/belt_contents = list() var/list/belt_contents = list() //In the list(path=count,otherpath=count) format
var/list/implants = null //A list of implants that should be implanted var/list/implants = null //A list of implants that should be implanted
/datum/outfit/proc/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE) /datum/outfit/proc/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
@@ -158,6 +158,10 @@
var/number = backpack_contents[path] var/number = backpack_contents[path]
for(var/i in 1 to number) for(var/i in 1 to number)
H.equip_or_collect(new path(H), slot_in_backpack) H.equip_or_collect(new path(H), slot_in_backpack)
for(var/path in belt_contents)
var/number = belt_contents[path]
for(var/i in 1 to number)
H.equip_or_collect(new path(H), slot_in_belt)
post_equip(H, visualsOnly) post_equip(H, visualsOnly)

View File

@@ -313,8 +313,8 @@
uniform = /obj/item/clothing/under/rank/centcom_commander uniform = /obj/item/clothing/under/rank/centcom_commander
suit = /obj/item/clothing/suit/storage/vest/heavy/ert/commander suit = /obj/item/clothing/suit/storage/vest/heavy/ert/commander
shoes = /obj/item/clothing/shoes/swat shoes = /obj/item/clothing/shoes/jackboots
gloves = /obj/item/clothing/gloves/swat gloves = /obj/item/clothing/gloves/white
l_ear = /obj/item/device/radio/headset/ert l_ear = /obj/item/device/radio/headset/ert
glasses = /obj/item/clothing/glasses/sunglasses/sechud glasses = /obj/item/clothing/glasses/sunglasses/sechud
head = /obj/item/clothing/head/beret/centcom/commander head = /obj/item/clothing/head/beret/centcom/commander
@@ -329,6 +329,42 @@
/obj/item/weapon/implant/loyalty /obj/item/weapon/implant/loyalty
) )
/datum/outfit/admin/nt/tcfl_commander
name = "TCFL Commander"
uniform = /obj/item/clothing/under/legion
shoes = /obj/item/clothing/shoes/jackboots
l_ear = /obj/item/device/radio/headset/legion
head = /obj/item/clothing/head/legion_beret
belt = /obj/item/weapon/storage/belt/security/tactical
backpack_contents = list(
/obj/item/weapon/gun/projectile/revolver = 1,
/obj/item/clothing/accessory/holster/hip = 1,
/obj/item/clothing/accessory/legion = 1,
/obj/item/weapon/storage/box/flashbangs = 1
)
belt_contents = list(
/obj/item/weapon/melee/baton/loaded = 1,
/obj/item/weapon/handcuffs = 2,
/obj/item/ammo_magazine/a357 = 2,
/obj/item/device/flash = 1
)
/datum/outfit/admin/nt/cciaa
name = "CCIA Agent"
uniform = /obj/item/clothing/under/rank/centcom_officer
suit = /obj/item/clothing/suit/storage/toggle/internalaffairs/cciaa
shoes = /obj/item/clothing/shoes/laceup
gloves = /obj/item/clothing/gloves/white
l_ear = /obj/item/device/radio/headset/ert/ccia
glasses = /obj/item/clothing/glasses/sunglasses/sechud
head = /obj/item/clothing/head/beret/centcom/officer
l_pocket = /obj/item/weapon/reagent_containers/spray/pepper
r_pocket = /obj/item/device/taperecorder/cciaa
l_hand = /obj/item/weapon/storage/lockbox/cciaa
/datum/outfit/admin/nt/odinsec /datum/outfit/admin/nt/odinsec
name = "NTCC Odin Security Specialist" name = "NTCC Odin Security Specialist"
@@ -349,6 +385,14 @@
backpack_contents = null backpack_contents = null
belt_contents = list(
/obj/item/weapon/reagent_containers/spray/pepper = 1,
/obj/item/weapon/melee/baton/loaded = 1,
/obj/item/weapon/grenade/chem_grenade/gas = 1,
/obj/item/device/flash = 1,
/obj/item/ammo_magazine/c45x = 2
)
implants = list( implants = list(
/obj/item/weapon/implant/loyalty /obj/item/weapon/implant/loyalty
) )
@@ -364,22 +408,6 @@
var/obj/item/clothing/under/rank/U = H.w_uniform var/obj/item/clothing/under/rank/U = H.w_uniform
U.attach_accessory(null, holster) U.attach_accessory(null, holster)
if(H && H.belt)
var/obj/item/weapon/reagent_containers/spray/pepper/pepperspray = new(H)
var/obj/item/weapon/melee/baton/loaded/baton = new(H)
var/obj/item/weapon/grenade/chem_grenade/gas/gasgrenade = new(H)
var/obj/item/device/flash/flash = new(H)
var/obj/item/ammo_magazine/c45x/mag1 = new(H)
var/obj/item/ammo_magazine/c45x/mag2 = new(H)
H.belt.contents += mag1
H.belt.contents += mag2
H.belt.contents += gasgrenade
H.belt.contents += pepperspray
H.belt.contents += flash
H.belt.contents += baton
/datum/outfit/admin/nt/specops /datum/outfit/admin/nt/specops
name = "Special Operations Officer" name = "Special Operations Officer"

View File

@@ -21,6 +21,15 @@
outfit = /datum/outfit/job/merchant outfit = /datum/outfit/job/merchant
/datum/job/merchant/announce(mob/living/carbon/human/H)
to_chat(H,"You are a merchant heading to the [station_name()] to make profit, your main objective is to sell and trade with the crew.")
/datum/job/merchant/New()
..()
if(prob(config.merchant_chance))
spawn_positions = 1
total_positions = 1
/datum/outfit/job/merchant /datum/outfit/job/merchant
name = "Merchant" name = "Merchant"
jobtype = /datum/job/merchant jobtype = /datum/job/merchant
@@ -31,11 +40,8 @@
pda = /obj/item/device/pda/merchant pda = /obj/item/device/pda/merchant
r_pocket = /obj/item/device/price_scanner r_pocket = /obj/item/device/price_scanner
/datum/job/merchant/announce(mob/living/carbon/human/H) /datum/outfit/job/merchant/assistant
to_chat(H,"You are a merchant heading to the [station_name()] to make profit, your main objective is to sell and trade with the crew.") name = "Merchant's Assistant"
/datum/job/merchant/New() /datum/outfit/job/merchant/assistant/get_id_rank(mob/living/carbon/human/H)
..() return "Merchant's Assistant"
if(prob(config.merchant_chance))
spawn_positions = 1
total_positions = 1

View File

@@ -385,6 +385,14 @@ var/list/global/slot_flags_enumeration = list(
allow = 1 allow = 1
if(!allow) if(!allow)
return 0 return 0
if(slot_in_belt)
var/allow = 0
if(istype(H.belt, /obj/item/weapon/storage/belt))
var/obj/item/weapon/storage/belt/B = H.belt
if(B.can_be_inserted(src,1))
allow = 1
if(!allow)
return 0
if(slot_tie) if(slot_tie)
if(!H.w_uniform && (slot_w_uniform in mob_equip)) if(!H.w_uniform && (slot_w_uniform in mob_equip))
if(!disable_warning) if(!disable_warning)

View File

@@ -381,15 +381,13 @@ var/list/admin_verbs_dev = list( //will need to be altered - Ryan784
) )
var/list/admin_verbs_cciaa = list( var/list/admin_verbs_cciaa = list(
/client/proc/cmd_admin_pm_panel, /*admin-pm list*/ /client/proc/cmd_admin_pm_panel, /*admin-pm list*/
/client/proc/spawn_duty_officer,
/client/proc/cmd_admin_create_centcom_report, /client/proc/cmd_admin_create_centcom_report,
/client/proc/cmd_cciaa_say, /client/proc/cmd_cciaa_say,
/client/proc/returntobody, /client/proc/returntobody,
/datum/admins/proc/create_admin_fax, /datum/admins/proc/create_admin_fax,
/client/proc/check_fax_history, /client/proc/check_fax_history,
/client/proc/aooc, /client/proc/aooc,
/client/proc/check_antagonists, /client/proc/check_antagonists
/client/proc/spawn_ert_commander
) )
/client/proc/add_admin_verbs() /client/proc/add_admin_verbs()

View File

@@ -1,127 +1,3 @@
/client/proc/spawn_duty_officer()
set category = "Special Verbs"
set name = "Spawn CCIA Agent"
set desc = "Spawns a CCIA Agent to agent around."
if(!check_rights(R_CCIAA)) return
if(!holder)
return //how did they get here?
if(!ROUND_IS_STARTED)
to_chat(src,"<span class='warning'>The game hasn't started yet!</span>")
return
if(istype(mob, /mob/abstract/new_player))
to_chat(src,"<span class='warning'>You can't be in the lobby to join as a duty officer.</span>")
return
if (alert(usr, "Do you want to cancel or proceed?", "Are you sure?", "Proceed", "Cancel") == "Cancel")
to_chat(src,"<span class='notice'>Cancelled.</span>")
return
if(mob.mind && mob.mind.special_role == "CCIA Agent")
to_chat(src,"<span class='warning'>You are already a CCIA Agent.</span>")
verbs += /client/proc/returntobody
return
var/wasLiving = 0
if(istype(mob, /mob/living))
holder.original_mob = mob
wasLiving = 1
var/obj/effect/landmark/L
for (var/obj/effect/landmark/landmark in landmarks_list)
if(landmark.name == "CCIAAgent")
L = landmark
break
if (!L)
return
var/new_name = input(usr, "Pick a name","Name") as text
var/mob/living/carbon/human/M = new(null)
M.check_dna(M)
M.real_name = new_name
M.name = new_name
M.age = input("Enter your characters age:","Num") as num
if(!M.age)
M.age = rand(35,50)
if(M.age < 33 || M.age > 60)
to_chat(src,"<span class='warning'>The age you selected was not in a valid range for a Duty Officer.</span>")
if(M.age < 33)
M.age = 33
else
M.age = 60
to_chat(src,"<span class='warning'>Your age has been set to [M.age].</span>")
M.dna.ready_dna(M)
M.mind = new
M.mind.current = M
M.mind.original = M
if(wasLiving)
M.mind.admin_mob_placeholder = mob
M.mind.assigned_role = "Central Command Internal Affairs Agent"
M.mind.special_role = "CCIA Agent"
M.forceMove(L.loc)
M.key = key
M.change_appearance(APPEARANCE_ALL, M.loc, check_species_whitelist = 1)
if(wasLiving)
clear_cciaa_job(holder.original_mob)
addtimer(CALLBACK(holder.original_mob, /mob/.proc/invalidate_key_tmr), 1)
M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/centcom_officer(M), slot_w_uniform)
M.equip_to_slot_or_del(new /obj/item/clothing/shoes/laceup(M), slot_shoes)
M.equip_to_slot_or_del(new /obj/item/clothing/gloves/white(M), slot_gloves)
M.equip_to_slot_or_del(new /obj/item/device/radio/headset/ert/ccia(M), slot_l_ear)
M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/sechud(M), slot_glasses)
M.equip_to_slot_or_del(new /obj/item/clothing/head/beret/centcom/officer(M), slot_head)
M.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/spray/pepper(M), slot_l_store)
M.equip_to_slot_or_del(new /obj/item/device/taperecorder/cciaa(M), slot_r_store)
var/obj/item/clothing/suit/storage/toggle/liaison/suit = new(M)
suit.name = "central command internal affairs jacket"
M.equip_to_slot_or_del(suit, slot_wear_suit)
var/obj/item/weapon/storage/backpack/satchel/bag = new(M)
bag.name = "officer's leather satchel"
bag.desc = "A well cared for leather satchel for Nanotrasen officers."
M.equip_to_slot_or_del(bag, slot_back)
if(M.backbag == 1)
M.equip_to_slot_or_del(new /obj/item/weapon/stamp/centcomm(M), slot_in_backpack)
var /obj/item/weapon/storage/lockbox/lockbox = new(M)
lockbox.req_access = list(access_cent_captain)
lockbox.name = "CCIA agent briefcase"
lockbox.desc = "A smart looking briefcase with a NT logo on the side"
lockbox.storage_slots = 8
lockbox.max_storage_space = 16
M.equip_to_slot_or_del(lockbox, slot_l_hand)
var/obj/item/device/pda/central/pda = new(M)
pda.owner = M.real_name
pda.ownjob = "Central Command Internal Affairs Agent"
pda.name = "PDA-[M.real_name] ([pda.ownjob])"
M.equip_to_slot_or_del(pda, slot_belt)
M.implant_loyalty(M, 1)
var/obj/item/weapon/card/id/centcom/W = new(M)
W.name = "[M.real_name]'s ID Card"
W.item_state = "id_inv"
W.access = get_all_accesses() | get_centcom_access("CCIA Agent")
W.assignment = "Central Command Internal Affairs Agent"
W.registered_name = M.real_name
M.equip_to_slot_or_del(W, slot_wear_id)
verbs += /client/proc/returntobody
/client/proc/returntobody() /client/proc/returntobody()
set name = "Return to mob" set name = "Return to mob"
set desc = "The Agent's work is done, return to your original mob" set desc = "The Agent's work is done, return to your original mob"

View File

@@ -266,3 +266,14 @@
/obj/item/device/encryptionkey/ccia /obj/item/device/encryptionkey/ccia
name = "\improper CCIA radio encryption key" name = "\improper CCIA radio encryption key"
channels = list("Response Team" = 1, "Science" = 0, "Command" = 1, "Medical" = 0, "Engineering" = 0, "Security" = 0, "Supply" = 0, "Service" = 0) channels = list("Response Team" = 1, "Science" = 0, "Command" = 1, "Medical" = 0, "Engineering" = 0, "Security" = 0, "Supply" = 0, "Service" = 0)
/obj/item/clothing/suit/storage/toggle/internalaffairs/cciaa
name = "central command internal affairs jacket"
/obj/item/weapon/storage/lockbox/cciaa
req_access = list(access_cent_captain)
name = "CCIA agent briefcase"
desc = "A smart looking briefcase with a NT logo on the side"
storage_slots = 8
max_storage_space = 16

View File

@@ -1,109 +0,0 @@
/client/proc/spawn_ert_commander()
set category = "Special Verbs"
set name = "Spawn ERT Commander"
set desc = "Spawns an ERT Commander."
if(!check_rights(R_CCIAA)) return
if(!holder)
return //how did they get here?
if(!ROUND_IS_STARTED)
to_chat(src,"<span class='warning'>The game hasn't started yet!</span>")
return
if(istype(mob, /mob/abstract/new_player))
to_chat(src,"<span class='warning'>You can't be in the lobby to join as a commander.</span>")
return
if (alert(usr, "Do you want to cancel or proceed?", "Are you sure?", "Proceed", "Cancel") == "Cancel")
to_chat(src,"<span class='notice'>Cancelled.</span>")
return
if(mob.mind && mob.mind.special_role == "ERT Commander")
to_chat(src,"<span class='warning'>You are already an ERT Commander.</span>")
verbs += /client/proc/returntobody
return
var/wasLiving = 0
if(istype(mob, /mob/living))
holder.original_mob = mob
wasLiving = 1
var/obj/effect/landmark/L
for (var/obj/effect/landmark/landmark in landmarks_list)
if(landmark.name == "ERTCommander")
L = landmark
break
if (!L)
return
var/new_name = input(usr, "Pick a name","Name") as text
var/mob/living/carbon/human/M = new(null)
M.check_dna(M)
M.real_name = new_name
M.name = new_name
M.age = input("Enter your characters age:","Num") as num
if(!M.age)
M.age = rand(35,50)
if(M.age < 33 || M.age > 60)
to_chat(src,"<span class='warning'>The age you selected was not in a valid range for a Commander.</span>")
if(M.age < 33)
M.age = 33
else
M.age = 60
to_chat(src,"<span class='warning'>Your age has been set to [M.age].</span>")
M.dna.ready_dna(M)
M.mind = new
M.mind.current = M
M.mind.original = M
if(wasLiving)
M.mind.admin_mob_placeholder = mob
M.mind.assigned_role = "Emergency Response Team Commander"
M.mind.special_role = "ERT Commander"
M.forceMove(L.loc)
M.key = key
M.change_appearance(APPEARANCE_ALL, M.loc, check_species_whitelist = 1)
if(wasLiving)
clear_cciaa_job(holder.original_mob)
addtimer(CALLBACK(holder.original_mob, /mob/.proc/invalidate_key_tmr), 1)
M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/centcom_commander(M), slot_w_uniform)
M.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(M), slot_shoes)
M.equip_to_slot_or_del(new /obj/item/clothing/gloves/white(M), slot_gloves)
M.equip_to_slot_or_del(new /obj/item/device/radio/headset/ert(M), slot_l_ear)
M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/sechud(M), slot_glasses)
M.equip_to_slot_or_del(new /obj/item/clothing/head/beret/centcom/commander(M), slot_head)
M.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/vest/heavy/ert/commander(M), slot_wear_suit)
M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel, slot_back)
var/obj/item/device/pda/central/pda = new(M)
pda.owner = M.real_name
pda.ownjob = "Emergency Response Team Commander"
pda.name = "PDA-[M.real_name] ([pda.ownjob])"
M.equip_to_slot_or_del(pda, slot_belt)
M.implant_loyalty(M, 1)
var/obj/item/weapon/card/id/centcom/W = new(M)
W.name = "[M.real_name]'s ID Card"
W.item_state = "id_inv"
W.access = get_all_accesses() | get_centcom_access("BlackOps Commander")
W.assignment = "Emergency Response Team Commander"
W.registered_name = M.real_name
M.equip_to_slot_or_del(W, slot_wear_id)
verbs += /client/proc/returntobody
/mob/proc/invalidate_key_tmr()
key = "@[key]"

View File

@@ -0,0 +1,146 @@
/datum/ghostspawner
var/short_name = null
var/name = null
var/desc = null
var/welcome_message = null
var/list/tags = list() //Tags associated with that spawner
//Vars regarding the spawnpoints and conditions of the spawner
var/list/spawnpoints = null //List of the applicable spawnpoints (by name)
var/landmark_name = null //Alternatively you can specify a landmark name
var/max_count = 0 //How often can this spawner be used
var/count = 0 //How ofen has this spawner been used
var/req_perms = null //What permission flags are required to use this spawner
var/req_perms_edit = R_ADMIN
var/req_head_whitelist = FALSE //If a head of staff whitelist is required
var/req_species_whitelist = null //Name/Datum of the species whitelist that is required, or null
var/enabled = TRUE //If the spawnpoint is enabled
var/enable_chance = null //If set to a value other than null, has the set chance to become enabled
var/enable_dmessage = TRUE //The message to send to deadchat if the ghostspawner is enabled or TRUE for a default message
var/respawn_flag = null //Flag to check for when trying to spawn someone of that type (CREW, ANIMAL, MINISYNTH)
var/jobban_job = null //If this is set, then it will check if the user is jobbanned from a specific job. Otherwise it will check for the name of the spawner
//Vars regarding the mob to use
var/mob/spawn_mob = null //The mob that should be spawned
var/list/variables = list() //Variables of that mob
var/mob_name = FALSE //The name of that mob; If null prompts for it
var/mob_name_prefix = null //The prefix that should be applied to the mob (i.e. CCIAA, Tpr., Cmdr.)
var/mob_name_suffix = null //The suffix that should be applied to the mob name
/datum/ghostspawner/New()
. = ..()
if(!jobban_job)
jobban_job = name
if(!isnull(enable_chance))
enabled = prob(enable_chance)
//Return a error message if the user CANT see the ghost spawner. Otherwise FALSE
/datum/ghostspawner/proc/cant_see(mob/user) //If the user can see the spawner in the menu
if(req_perms) //Only those with the correct flags can see restricted roles
if(check_rights(req_perms, show_msg=FALSE, user=user))
return FALSE //Return early and dont perform whitelist checks if staff flags are met
else
return "Missing Permissions"
if(req_head_whitelist && !check_whitelist(user))
return "Missing Head of Staff Whitelist"
if(req_species_whitelist && !is_alien_whitelisted(user, req_species_whitelist))
return "Missing Species Whitelist"
if(jobban_job && jobban_isbanned(user,jobban_job))
return "Job Banned"
if(!enabled && !can_edit(user)) //If its not enabled and the user cant edit it, dont show it
return "Currently Disabled"
return FALSE
//Return a error message if the user CANT spawn. Otherwise FALSE
/datum/ghostspawner/proc/cant_spawn(mob/user) //If the user can spawn using the spawner
if(!ROUND_IS_STARTED)
return "The round is not started yet."
var/cant_see = cant_see()
if(cant_see) //If we cant see it, we cant spawn it
return cant_see
if(!istype(user, /mob/abstract/observer))
return "You are not a ghost."
if(!enabled) //If the spawner id disabled, we cant spawn in
return "This spawner is not enabled."
if(respawn_flag && !user.MayRespawn(0,respawn_flag))
return "You can not respawn at this time."
if(!config.enter_allowed)
return "There is an administrative lock on entering the game."
if(SSticker.mode?.explosion_in_progress)
return "The station is currently exploding."
if(max_count && count > max_count)
return "No more slots are available."
//Check if a spawnpoint is available
var/T = select_spawnpoint(FALSE)
if(!T)
return "No spawnpoint available."
return FALSE
//Proc executed before someone is spawned in
/datum/ghostspawner/proc/pre_spawn(mob/user)
count++ //Increment the spawned in mob count
if(count >= max_count)
disable()
return TRUE
//This proc selects the spawnpoint to use.
/datum/ghostspawner/proc/select_spawnpoint(var/use=TRUE)
if(!isnull(spawnpoints))
for(var/spawnpoint in spawnpoints) //Loop through the applicable spawnpoints
var/turf/T = SSghostroles.get_spawnpoint(spawnpoint, use) //Gets the first matching spawnpoint or null if none are available
if(T) //If we have a spawnpoint, return it
return T
if(!isnull(landmark_name))
var/obj/effect/landmark/L
for(var/obj/effect/landmark/landmark in landmarks_list)
if(landmark.name == landmark_name)
L = landmark
return get_turf(L)
log_debug("Ghostspawner: Spawner [short_name] has neither spawnpoints nor landmarks or a matching spawnpoint/landmark could not be found")
return null //If we dont have anything return null
//The proc to actually spawn in the user
/datum/ghostspawner/proc/spawn_mob(mob/user)
//OVERWRITE THIS IN THE CHILD IMPLEMENTATIONS to return the spawned in mob !!!
return null
//Proc executed after someone is spawned in
/datum/ghostspawner/proc/post_spawn(mob/user)
if(welcome_message)
to_chat(user, welcome_message)
return TRUE
//Proc to check if a specific user can edit this spawner (open/close/...)
/datum/ghostspawner/proc/can_edit(mob/user)
if(check_rights(req_perms_edit, show_msg=FALSE, user=user))
return TRUE
return FALSE
/datum/ghostspawner/proc/is_enabled()
if(max_count)
return enabled && count < max_count
return enabled
//Proc to enable the ghostspawner
/datum/ghostspawner/proc/enable()
enabled = TRUE
if(enable_dmessage)
for(var/mob/abstract/observer/O in player_list)
if(O.client && !cant_see(O))
if(enable_dmessage == TRUE)
to_chat(O, "<span class='deadsay'><b>A ghostspawner for a \"[src.name]\" has been enabled.</b></span>")
else
to_chat(O, "<span class='deadsay'><b>[enable_dmessage]</b></span>")
return TRUE
//Proc to disable the ghostspawner
/datum/ghostspawner/proc/disable()
enabled = FALSE
return TRUE

View File

@@ -0,0 +1,115 @@
/datum/ghostspawner/human/admin
tags = list("Admin")
/datum/ghostspawner/human/admin/ert_commander
short_name = "ertcommander"
name = "ERT Commander"
desc = "Command the response team from Central Command"
landmark_name = "ERTCommander"
req_perms = R_CCIAA
//Vars related to human mobs
outfit = /datum/outfit/admin/nt/ert_commander
possible_species = list("Human")
possible_genders = list(MALE,FEMALE)
allow_appearance_change = TRUE
assigned_role = "Emergency Response Team Commander"
special_role = "ERT Commander"
respawn_flag = null
mob_name = null
mob_name_prefix = "Cmdr. "
/datum/ghostspawner/human/admin/legion_commander
short_name = "legioncommander"
name = "TCFL Commander"
desc = "Command the TCFL, a walking and talking joke, whos members regularly die before they even arrive at their target."
landmark_name = "TCFLCommander"
req_perms = R_CCIAA
//Vars related to human mobs
outfit = /datum/outfit/admin/nt/tcfl_commander
possible_species = list("Human")
possible_genders = list(MALE,FEMALE)
allow_appearance_change = TRUE
assigned_role = "Tau Ceti Foreign Legion Commander"
special_role = "TCFL Commander"
respawn_flag = null
mob_name = null
mob_name_prefix = "Cmdr. "
/datum/ghostspawner/human/admin/cciaagent
short_name = "cciaagent"
name = "CCIA Agent"
desc = "Board the Aurora, annoy crew with your interviews and get squashed by your own shuttle."
landmark_name = "CCIAAgent"
req_perms = R_CCIAA
//Vars related to human mobs
outfit = /datum/outfit/admin/nt/cciaa
possible_species = list("Human")
possible_genders = list(MALE,FEMALE)
allow_appearance_change = TRUE
assigned_role = "Emergency Response Team Commander"
special_role = "ERT Commander"
respawn_flag = null
mob_name = null
mob_name_prefix = "CCIAA "
/datum/ghostspawner/human/admin/cciaescort
short_name = "cciaescort"
name = "CCIA Escort"
desc = "Escort a CCIA Agent to the station, watch them annoy the crew and prevent them from throwing themselvs under their own shuttle."
enabled = FALSE
landmark_name = "CCIAEscort"
req_perms = null
req_perms_edit = R_CCIAA
max_count = 1
//Vars related to human mobs
outfit = /datum/outfit/admin/nt/protection_detail
possible_species = list("Human")
possible_genders = list(MALE,FEMALE)
allow_appearance_change = TRUE
assigned_role = "Civil Protection Officer"
special_role = "Civil Protection Officer"
respawn_flag = null
mob_name = null
mob_name_prefix = "Ofc. "
/datum/ghostspawner/human/admin/checkpointsec
short_name = "checkpointsec"
name = "Odin Checkpoint Security"
desc = "Secure the Odin checkpoint. Verify the identity of everyone passing through, perform random searches on \"suspicious\" crew."
enabled = FALSE
spawnpoints = list("OdinCheckpoint")
req_perms = null
req_perms_edit = R_CCIAA
max_count = 4
//Vars related to human mobs
outfit = /datum/outfit/admin/nt/protection_detail
possible_species = list("Human","Skrell","Tajara","Unathi")
possible_genders = list(MALE,FEMALE)
allow_appearance_change = TRUE
assigned_role = "Odin Security Officer"
special_role = "Odin Security Officer"
respawn_flag = null
mob_name = null
mob_name_prefix = "Spec. "

View File

@@ -0,0 +1,166 @@
/datum/ghostspawner/human/rescuepodsurv
short_name = "rescuepodsurv"
name = "Rescue Pod Survivor"
desc = "You managed to get into a rescue pod and landed somewhere on a asteroid."
tags = list("External")
enabled = FALSE
req_perms = null
max_count = 1
//Vars related to human mobs
outfit = /datum/outfit/admin/random/visitor
possible_species = list("Human","Skrell","Tajara","Unathi")
possible_genders = list(MALE,FEMALE)
allow_appearance_change = TRUE
assigned_role = "Pod Survivor"
special_role = "Pod Survivor"
respawn_flag = CREW
mob_name = FALSE
enable_chance = 10
/datum/ghostspawner/human/rescuepodsurv/New()
. = ..()
var/t = pick(list("star","priest","rep","smuggler"))
if(t == "star")
welcome_message = "You are a stranded starlet!<br>You were relaxing comfortably in your cryo pod as tragedy struck - the pilot of your luxury yacht fell asleep under some mysterious circumstances. You were unceremoniously stuffed into an escape pod, and left to wander in space. What a despicable, low-quality plot to get rid of you. Should've chosen murder instead - you certainly know you'll convince someone nice to lend you a shuttle."
outfit = /datum/outfit/admin/pod/star
possible_genders = list(FEMALE)
possible_species = list("Human","Skrell","Tajara")
else if(t == "priest")
welcome_message = "You are a stranded Trinary Perfection priest!<br>You were traveling around space on your small shuttle, preaching peacefully of the future divinity of the synthetics, and the grand purpose of mankind as the ones to help them achieve that goal. Unfortunately, Dominians don't seem to be as peaceful in disagreeing with your views - and had to evacuate your shot-down ship. Have your prayers to the Divines helped you now?"
outfit = /datum/outfit/admin/pod/priest
possible_species = list("Human")
else if(t == "rep")
welcome_message = "You are a stranded Idris Incorporated representative!<br>You were traveling back from your business in Sol to the Mendell City HQ. Unfortunately, after a very unusual set of circumstances, the engine broke down just almost as you got back. You're stranded somewhere nearby - perhaps your excellent customer service and negotiation skills might get you a ride back to Mendell?"
outfit = /datum/outfit/admin/pod/rep
possible_species = list("Human")
else
welcome_message = "You are a stranded drugs smuggler!<br>You shouldn't have had the fucking Tajara pilot your ship. <i>Of course</i> we crashed into a rock. Good thing you've got some of the stuff with you while evacuating - maybe you'll crash somewhere you could sell it for a ticket back?"
outfit = /datum/outfit/admin/pod/smuggler
possible_species = list("Human","Skrell","Unathi")
/datum/ghostspawner/human/rescuepodsurv/select_spawnpoint(var/use=TRUE)
//Randomly select a Turf on the asteroid.
var/turf/T = pick_area_turf(/area/mine/unexplored)
if(!use) //If we are just checking if we can get one, return the turf we found
return T
if(!T) //If we didnt find a turn, return now
return null
//Otherwise spawn a droppod at that location
var/x = T.x
var/y = T.y
var/z = T.z
new /datum/random_map/droppod(null,x,y,z,supplied_drop="custom",do_not_announce=TRUE,automated=FALSE)
return get_turf(locate(x+1,y+1,z)) //Get the turf again, so we end up inside of the pod - There is probs a better way to do this
//Base equipment for the pod (softsuit + emergency oxygen)
/datum/outfit/admin/pod
head = /obj/item/clothing/head/helmet/space/emergency
mask = /obj/item/clothing/mask/breath
suit = /obj/item/clothing/suit/space/emergency
suit_store = /obj/item/weapon/tank/emergency_oxygen/double
l_ear = /obj/item/device/radio/headset
back = /obj/item/weapon/storage/backpack
/datum/outfit/admin/pod/post_equip(mob/living/carbon/human/H, visualsOnly)
. = ..()
//Turn on the oxygen tank
H.internal = H.s_store
if(istype(H.internal,/obj/item/weapon/tank) && H.internals)
H.internals.icon_state = "internal1"
/datum/outfit/admin/pod/star
name = "RescuePod - Star"
uniform = "dress selection"
shoes = "flats selection"
id = /obj/item/weapon/card/id
backpack_contents = list(
/obj/item/weapon/lipstick/random = 2,
/obj/item/weapon/haircomb/random = 1,
/obj/item/weapon/spacecash/c1000 = 2,
/obj/item/device/oxycandle = 1,
/obj/item/airbubble = 1
)
/datum/outfit/admin/pod/star/get_id_assignment()
return "Visitor"
/datum/outfit/admin/pod/star/get_id_rank()
return "Visitor"
/datum/outfit/admin/pod/priest
name = "RescuePod - Priest"
uniform = /obj/item/clothing/under/rank/chaplain
shoes = /obj/item/clothing/shoes/black
id = /obj/item/weapon/card/id
pda = /obj/item/device/pda/chaplain
backpack_contents = list(
/obj/item/weapon/storage/bible/fluff/oscar_bible = 1,
/obj/item/device/oxycandle = 1,
/obj/item/airbubble = 1
)
/datum/outfit/admin/pod/priest/get_id_assignment()
return "Priest"
/datum/outfit/admin/pod/priest/get_id_rank()
return "Priest"
/datum/outfit/admin/pod/rep
name = "RescuePod - IdrisRep"
uniform = /obj/item/clothing/under/rank/idris
id = /obj/item/weapon/card/id/idris
pda = /obj/item/device/pda/lawyer
shoes = /obj/item/clothing/shoes/laceup
glasses = /obj/item/clothing/glasses/sunglasses/big
l_hand = /obj/item/weapon/storage/briefcase
backpack_contents = list(
/obj/item/clothing/head/beret/liaison = 1,
/obj/item/device/camera = 1,
/obj/item/weapon/gun/energy/pistol = 1,
/obj/item/device/oxycandle = 1,
/obj/item/airbubble = 1
)
/datum/outfit/admin/pod/rep/get_id_assignment()
return "Corporate Liaison (Idris)"
/datum/outfit/admin/pod/rep/get_id_rank()
return "Corporate Liaison"
/datum/outfit/admin/pod/smuggler
name = "RescuePod - Smuggler"
shoes = "shoe selection"
uniform = "pants selection"
backpack_contents = list(
/obj/item/weapon/reagent_containers/inhaler/space_drugs = 3,
/obj/item/weapon/reagent_containers/inhaler/hyperzine = 2,
/obj/item/weapon/reagent_containers/inhaler/soporific = 1,
/obj/item/weapon/gun/projectile/leyon = 1,
/obj/item/device/oxycandle = 1,
/obj/item/airbubble = 1
)
/datum/outfit/admin/pod/smuggler/get_id_assignment()
return "Merchant"
/datum/outfit/admin/pod/smuggler/get_id_rank()
return "Merchant"

View File

@@ -0,0 +1,113 @@
/datum/ghostspawner/human
short_name = null
name = null
desc = null
respawn_flag = CREW //Flag to check for when trying to spawn someone of that type (CREW, ANIMAL, MINISYNTH)
//Vars regarding the mob to use
spawn_mob = /mob/living/carbon/human //The mob that should be spawned
variables = list() //Variables of that mob
//Vars related to human mobs
var/datum/outfit/outfit = null //Outfit to equip
var/possible_species = list("Human")
var/possible_genders = list(MALE,FEMALE)
var/allow_appearance_change = FALSE
var/assigned_role = null
var/special_role = null
var/faction = null
mob_name = null
//Proc executed before someone is spawned in
/datum/ghostspawner/human/pre_spawn(mob/user)
. = ..()
/datum/ghostspawner/human/proc/get_mob_name(mob/user)
var/mname = mob_name
if(isnull(mname))
var/pick_message = "Pick a name."
if(mob_name_prefix)
pick_message = "[pick_message] Automatic Prefix: \"[mob_name_prefix]\" "
if(mob_name_suffix)
pick_message = "[pick_message] Automatic Suffix: \"[mob_name_suffix]\" "
mname = sanitizeSafe(input(user, pick_message, "Name (without prefix/suffix"))
if(mob_name_prefix)
mname = "[mob_name_prefix][mname]"
if(mob_name_suffix)
mname = "[mname][mob_name_suffix]"
return mname
//The proc to actually spawn in the user
/datum/ghostspawner/human/spawn_mob(mob/user)
//Select a spawnpoint (if available)
var/turf/T = select_spawnpoint()
if(!T)
log_debug("GhostSpawner: Unable to select spawnpoint for [short_name]")
return FALSE
//Get the name / age from them first
var/mname = get_mob_name(user)
var/age = input(user, "Enter your characters age:","Num") as num
//Spawn in the mob
var/mob/living/carbon/human/M = new spawn_mob(null)
M.change_gender(pick(possible_genders))
M.set_species(pick(possible_species))
//Prepare the mob
M.check_dna(M)
M.dna.ready_dna(M)
//Move the mob inside and initialize the mind
M.key = user.ckey //!! After that USER is invalid, so we have to use M
M.mind_initialize()
if(assigned_role)
M.mind.assigned_role = assigned_role
if(special_role)
M.mind.special_role = special_role
if(faction)
M.faction = faction
//Move the mob
M.forceMove(T)
M.lastarea = get_area(M.loc) //So gravity doesnt fuck them.
M.megavend = TRUE //So the autodrobe ignores them
//Setup the appearance
if(allow_appearance_change)
M.change_appearance(APPEARANCE_ALL, M.loc, check_species_whitelist = 1)
else //otherwise randomize
M.client.prefs.randomize_appearance_for(M, FALSE)
//Setup the mob age and name
if(!mname)
mname = random_name(M.gender, M.species.name)
M.fully_replace_character_name(M.real_name, mname)
if(!age)
age = rand(35, 50)
M.age = Clamp(age, 21, 65)
//Setup the outfit
if(outfit)
M.preEquipOutfit(outfit, FALSE)
M.equipOutfit(outfit, FALSE)
M.force_update_limbs()
M.update_eyes()
M.regenerate_icons()
return M
//Proc executed after someone is spawned in
/datum/ghostspawner/human/post_spawn(mob/user)
. = ..()

View File

@@ -0,0 +1,32 @@
/datum/ghostspawner/human/merchantass
short_name = "merchantass"
name = "Merchants Assistant"
desc = "Assist the Merchant with their duties."
tags = list("External")
enabled = FALSE
spawnpoints = list("MerchantAss")
req_perms = null
max_count = 1
//Vars related to human mobs
outfit = /datum/outfit/job/merchant/assistant
possible_species = list("Human","Skrell","Tajara","Unathi")
possible_genders = list(MALE,FEMALE)
allow_appearance_change = TRUE
assigned_role = "Merchants Assistant"
special_role = "Merchants Assistant"
respawn_flag = null
mob_name = null
/datum/ghostspawner/human/merchantass/can_edit(mob/user)
. = ..()
var/is_merchant = FALSE
if(ishuman(user))
var/mob/living/carbon/human/H = user
is_merchant = (H.job == "Merchant")
return . || is_merchant

View File

@@ -0,0 +1,27 @@
/datum/ghostspawner/human/visitorerror
short_name = "visitorerror"
name = "Visitor"
desc = "You are a Visitor, but noone told them."
tags = list("External")
enabled = FALSE
landmark_name = "JoinLate"
req_perms = null
max_count = 1
//Vars related to human mobs
outfit = /datum/outfit/admin/random/visitor
possible_species = list("Human","Skrell","Tajara","Unathi")
possible_genders = list(MALE,FEMALE)
allow_appearance_change = TRUE
assigned_role = "Visitor"
special_role = "Visitor"
respawn_flag = CREW
mob_name = null
enable_chance = 10
/datum/ghostspawner/human/visitorerror/select_spawnpoint(var/use=TRUE)
return pick(latejoin)

View File

@@ -0,0 +1,41 @@
/datum/ghostspawner/simplemob/maintdrone
short_name = "maintdrone"
name = "Maintenence Drone"
desc = "Maintain and Improve the Systems on the Aurora"
tags = list("Simple Mobs")
respawn_flag = MINISYNTH //Flag to check for when trying to spawn someone of that type (CREW, ANIMAL, MINISYNTH)
jobban_job = "Cyborg"
//Vars regarding the mob to use
spawn_mob = /mob/living/simple_animal/rat //The mob that should be spawned
/datum/ghostspawner/simplemob/maintdrone/cant_see()
if(!config.allow_drone_spawn)
return "Spawning as drone is disabled"
return ..()
/datum/ghostspawner/simplemob/maintdrone/select_spawnpoint(var/use)
return TRUE //We just fake it here, since the spawnpoint is selected if someone is spawned in.
//The proc to actually spawn in the user
/datum/ghostspawner/simplemob/maintdrone/spawn_mob(mob/user)
var/obj/machinery/drone_fabricator/fabricator
var/list/all_fabricators = list()
for(var/obj/machinery/drone_fabricator/DF in SSmachinery.all_machines)
if((DF.stat & NOPOWER) || !DF.produce_drones || DF.drone_progress < 100)
continue
all_fabricators[DF.fabricator_tag] = DF
if(!all_fabricators.len)
to_chat(user, "<span class='danger'>There are no available drone spawn points, sorry.</span>")
return FALSE
var/choice = input(user, "Which fabricator do you wish to use?") as null|anything in all_fabricators
if(!choice || !all_fabricators[choice])
return FALSE
fabricator = all_fabricators[choice]
if(user && fabricator && !((fabricator.stat & NOPOWER) || !fabricator.produce_drones || fabricator.drone_progress < 100))
return fabricator.create_drone(user.client)
return FALSE

View File

@@ -0,0 +1,41 @@
/datum/ghostspawner/simplemob/rat
short_name = "rat"
name = "Rat"
desc = "Join as a Rat on the aurora, a common nuciance to the crew."
welcome_message = "You are now a rat. Though you may interact with players, do not give any hints away that you are more than a simple rodent. Find food, avoid cats, and try to survive!"
tags = list("Simple Mobs")
respawn_flag = ANIMAL //Flag to check for when trying to spawn someone of that type (CREW, ANIMAL, MINISYNTH)
//Vars regarding the mob to use
spawn_mob = /mob/living/simple_animal/rat //The mob that should be spawned
//This proc selects the spawnpoint to use.
/datum/ghostspawner/simplemob/rat/select_spawnpoint()
//find a viable mouse candidate
var/obj/machinery/atmospherics/unary/vent_pump/spawnpoint = find_mouse_spawnpoint(pick(current_map.station_levels))
return get_turf(spawnpoint)
/datum/ghostspawner/simplemob/rat/cant_see()
if(config.disable_player_rats)
return "Spawning as Rat is disabled"
return ..()
//The proc to actually spawn in the user
/datum/ghostspawner/simplemob/rat/spawn_mob(mob/user)
//Select a spawnpoint (if available)
var/turf/T = select_spawnpoint()
var/mob/living/simple_animal/S
if (T)
S = new spawn_mob(T)
else
to_chat(user, "<span class='warning'>Unable to find any safe, unwelded vents to spawn rats at. The station must be quite a mess! Trying again might work, if you think there's still a safe place. </span>")
if(S)
if(config.uneducated_rats)
S.universal_understand = 0
announce_ghost_joinleave(user, 0, "They are now a [name].")
S.ckey = user.ckey
return S

View File

@@ -0,0 +1,124 @@
#define STATE_UNAVAILABLE 1
#define STATE_AVAILABLE 2
#define STATE_RECHARGING 3
#define STATE_USED 4
/obj/effect/ghostspawpoint
name = "invisible ghost spawner - single"
desc = "A Invisible ghost spawner"
icon = 'icons/mob/screen/generic.dmi'
icon_state = "x2"
anchored = 1
unacidable = 1
simulated = 0
invisibility = 101
var/identifier = null //identifier of this spawnpoint
var/recharge_time = 0 //Time it takes until the ghostspawner can be used again
var/unavailable_time = null //Time when the ghost spawner became unavailable
var/icon_unavailable = "x2"
var/icon_available = "x2" //Icon to use when available
var/icon_recharging = "x2" //Icon to use when recharging
var/icon_used = "x2" //Icon to use when spwanpoint has been used
var/state = STATE_AVAILABLE
/obj/effect/ghostspawpoint/Initialize(mapload)
. = ..()
SSghostroles.add_spawnpoints(src)
/obj/effect/ghostspawpoint/update_icon()
if(state == STATE_UNAVAILABLE)
icon_state = icon_unavailable
else if(state == STATE_AVAILABLE)
icon_state = icon_available
else if (state == STATE_RECHARGING)
icon_state = icon_recharging
else if (state == STATE_USED)
icon_state = icon_used
else
icon_state = initial(icon_state)
/obj/effect/ghostspawpoint/process()
if(recharge_time && (recharge_time * 10) > (world.time - unavailable_time))
STOP_PROCESSING(SSprocessing, src)
state = STATE_AVAILABLE
update_icon()
/obj/effect/ghostspawpoint/attack_ghost(mob/user)
if(!ROUND_IS_STARTED)
to_chat(usr, "<span class='danger'>The round hasn't started yet!</span>")
return
SSghostroles.vui_interact(user,identifier)
/obj/effect/ghostspawpoint/attack_hand(mob/user)
if(!ROUND_IS_STARTED)
to_chat(usr, "<span class='danger'>The round hasn't started yet!</span>")
return
SSghostroles.vui_interact(user,identifier)
/obj/effect/ghostspawpoint/proc/is_available()
return state == STATE_AVAILABLE
/obj/effect/ghostspawpoint/proc/set_spawned()
if(recharge_time) //If we are available again after a certain time -> being processing
state = STATE_RECHARGING
unavailable_time = world.time
START_PROCESSING(SSprocessing, src)
else
state = STATE_USED
update_icon()
/obj/effect/ghostspawpoint/proc/set_available()
if(state == STATE_USED)
return //if its a one-use spawner and it got used already, dont reset it
state = STATE_AVAILABLE
update_icon()
/obj/effect/ghostspawpoint/proc/set_unavailable()
if(state == STATE_USED)
return //if its a one-use spawner and it got used already, dont reset it
else if(state == STATE_RECHARGING)
STOP_PROCESSING(SSprocessing, src)
state = STATE_UNAVAILABLE
update_icon()
#undef STATE_UNAVAILABLE
#undef STATE_AVAILABLE
#undef STATE_RECHARGING
#undef STATE_USED
/obj/effect/ghostspawpoint/repeat
name = "invisible ghost spawner - repeat"
desc = "A Invisible ghost spawner"
icon = 'icons/mob/screen/generic.dmi'
icon_state = "x3"
icon_unavailable = "x3" //Icon to use when unavailable
icon_available = "x3" //Icon to use when available
icon_recharging = "x3" //Icon to use when recharging
icon_used = "x3" //Icon to use when spwanpoint has been used
recharge_time = 1
/obj/effect/ghostspawpoint/cryo
name = "cryogenic storage pod"
desc = "A pod used to store individual in suspended animation"
icon = 'icons/obj/sleeper.dmi'
icon_state = "sleeper-closed"
identifier = null //identifier of this spawnpoint
icon_unavailable = "sleeper-closed" //Icon to use when unavailable
icon_available = "sleeper-closed" //Icon to use when available
icon_recharging = "sleeper" //Icon to use when recharging
icon_used = "sleeper" //Icon to use when spwanpoint has been used
anchored = 1
unacidable = 1
simulated = 1
invisibility = 0

View File

@@ -1,7 +1,10 @@
datum/preferences datum/preferences
//The mob should have a gender you want before running this proc. Will run fine without H //The mob should have a gender you want before running this proc. Will run fine without H
proc/randomize_appearance_for(var/mob/living/carbon/human/H) proc/randomize_appearance_for(var/mob/living/carbon/human/H,var/random_gender=TRUE)
gender = pick(MALE, FEMALE) if(random_gender)
gender = pick(MALE, FEMALE)
else
gender = H.gender
var/datum/species/current_species = all_species[species] var/datum/species/current_species = all_species[species]
if(current_species) if(current_species)

View File

@@ -487,46 +487,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
to_chat(src, "<span class='notice'>Temperature: [round(environment.temperature-T0C,0.1)]&deg;C ([round(environment.temperature,0.1)]K)</span>") to_chat(src, "<span class='notice'>Temperature: [round(environment.temperature-T0C,0.1)]&deg;C ([round(environment.temperature,0.1)]K)</span>")
to_chat(src, "<span class='notice'>Heat Capacity: [round(environment.heat_capacity(),0.1)]</span>") to_chat(src, "<span class='notice'>Heat Capacity: [round(environment.heat_capacity(),0.1)]</span>")
/mob/abstract/observer/verb/become_mouse()
set name = "Become Rat"
set category = "Ghost"
if(config.disable_player_rats)
to_chat(src, "<span class='warning'>Spawning as a rat is currently disabled.</span>")
return
if(!ROUND_IS_STARTED)
to_chat(src, "<span class='warning'>You can not spawn as a rat before round start!</span>")
return
if(!MayRespawn(1, ANIMAL))
return
var/turf/T = get_turf(src)
if(!T || (T.z in current_map.admin_levels))
to_chat(src, "<span class='warning'>You may not spawn as a rat on this Z-level.</span>")
return
var/response = alert(src, "Are you -sure- you want to become a rat?","Are you sure you want to squeek?","Squeek!","Nope!")
if(response != "Squeek!") return //Hit the wrong key...again.
//find a viable mouse candidate
var/mob/living/simple_animal/rat/host
var/obj/machinery/atmospherics/unary/vent_pump/spawnpoint = find_mouse_spawnpoint(T.z)
if (spawnpoint)
host = new /mob/living/simple_animal/rat(spawnpoint.loc)
else
to_chat(src, "<span class='warning'>Unable to find any safe, unwelded vents to spawn rats at. The station must be quite a mess! Trying again might work, if you think there's still a safe place. </span>")
if(host)
if(config.uneducated_rats)
host.universal_understand = 0
announce_ghost_joinleave(src, 0, "They are now a rat.")
host.ckey = src.ckey
to_chat(host, "<span class='info'>You are now a rat. Though you may interact with players, do not give any hints away that you are more than a simple rodent. Find food, avoid cats, and try to survive!</span>")
/proc/find_mouse_spawnpoint(var/ZLevel) /proc/find_mouse_spawnpoint(var/ZLevel)
//This function will attempt to find a good spawnpoint for rats, and prevent them from spawning in closed vent systems with no escape //This function will attempt to find a good spawnpoint for rats, and prevent them from spawning in closed vent systems with no escape
//It does this by bruteforce: Picks a random vent, tests if it has enough connections, if not, repeat //It does this by bruteforce: Picks a random vent, tests if it has enough connections, if not, repeat
@@ -643,7 +603,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(usr == src && try_possession(M)) if(usr == src && try_possession(M))
return return
if(istype(over, /obj/machinery/drone_fabricator)) if(istype(over, /obj/machinery/drone_fabricator))
if(try_drone_spawn(src, over)) var/obj/machinery/drone_fabricator/fab = over
if(fab.create_drone(src))
return return
return ..() return ..()
@@ -658,7 +619,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
//Used for drawing on walls with blood puddles as a spooky ghost. //Used for drawing on walls with blood puddles as a spooky ghost.
/mob/abstract/observer/verb/bloody_doodle() /mob/abstract/observer/verb/bloody_doodle()
set category = "Ghost" set category = "Ghost"
set name = "Write in blood" set name = "Write in blood"
set desc = "If the round is sufficiently spooky, write a short message in blood on the floor or a wall. Remember, no IC in OOC or OOC in IC." set desc = "If the round is sufficiently spooky, write a short message in blood on the floor or a wall. Remember, no IC in OOC or OOC in IC."
@@ -959,3 +919,15 @@ mob/abstract/observer/MayRespawn(var/feedback = 0, var/respawn_type = null)
if((!target) || (!ghost)) return if((!target) || (!ghost)) return
. = "<a href='byond://?src=\ref[ghost];track=\ref[target]'>\[F\]</a>" . = "<a href='byond://?src=\ref[ghost];track=\ref[target]'>\[F\]</a>"
. += target.extra_ghost_link(ghost) . += target.extra_ghost_link(ghost)
//Opens the Ghost Spawner Menu
/mob/abstract/observer/verb/ghost_spawner()
set category = "Ghost"
set name = "Ghost Spawner"
if(!ROUND_IS_STARTED)
to_chat(usr, "<span class='danger'>The round hasn't started yet!</span>")
return
SSghostroles.vui_interact(src)

View File

@@ -80,6 +80,8 @@ This saves us from having to call add_fingerprint() any time something is put in
return 1 return 1
if(slot_tie) if(slot_tie)
return 1 return 1
if(slot_in_belt)
return 1
/mob/living/carbon/human/u_equip(obj/W as obj) /mob/living/carbon/human/u_equip(obj/W as obj)
if(!W) return 0 if(!W) return 0
@@ -291,6 +293,10 @@ This saves us from having to call add_fingerprint() any time something is put in
if(src.get_active_hand() == W) if(src.get_active_hand() == W)
src.remove_from_mob(W) src.remove_from_mob(W)
W.forceMove(src.back) W.forceMove(src.back)
if(slot_in_belt)
if(src.get_active_hand() == W)
src.remove_from_mob(W)
W.forceMove(src.belt)
if(slot_tie) if(slot_tie)
var/obj/item/clothing/under/uniform = src.w_uniform var/obj/item/clothing/under/uniform = src.w_uniform
uniform.attackby(W,src) uniform.attackby(W,src)

View File

@@ -52,6 +52,10 @@
if(slot_w_uniform in equip_slots) if(slot_w_uniform in equip_slots)
equip_slots |= slot_tie equip_slots |= slot_tie
if(slot_belt in equip_slots)
equip_slots |= slot_in_belt
equip_slots |= slot_legcuffed equip_slots |= slot_legcuffed
/datum/hud_data/diona /datum/hud_data/diona

View File

@@ -57,7 +57,7 @@
/obj/machinery/drone_fabricator/examine(mob/user) /obj/machinery/drone_fabricator/examine(mob/user)
..(user) ..(user)
if(produce_drones && drone_progress >= 100 && istype(user,/mob/abstract) && config.allow_drone_spawn && count_drones() < config.max_maint_drones) if(produce_drones && drone_progress >= 100 && istype(user,/mob/abstract) && config.allow_drone_spawn && count_drones() < config.max_maint_drones)
to_chat(user, "<BR><B>A drone is prepared. Select 'Join As Drone' from the Ghost tab to spawn as a maintenance drone.</B>") to_chat(user, "<BR><B>A drone is prepared. use 'Ghost Roles' from the Ghost tab to spawn as a maintenance drone.</B>")
/obj/machinery/drone_fabricator/proc/create_drone(var/client/player) /obj/machinery/drone_fabricator/proc/create_drone(var/client/player)
@@ -84,47 +84,4 @@
drone_progress = 0 drone_progress = 0
/mob/abstract/observer/verb/join_as_drone() return new_drone
set category = "Ghost"
set name = "Join As Drone"
set desc = "If there is a powered, enabled fabricator in the game world with a prepared chassis, join as a maintenance drone."
try_drone_spawn(src)
/proc/try_drone_spawn(var/mob/user, var/obj/machinery/drone_fabricator/fabricator)
if(!ROUND_IS_STARTED)
to_chat(user, "<span class='danger'>The game hasn't started yet!</span>")
return
if(!(config.allow_drone_spawn))
to_chat(user, "<span class='danger'>That verb is not currently permitted.</span>")
return
if(jobban_isbanned(user,"Cyborg"))
to_chat(user, "<span class='danger'>You are banned from playing synthetics and cannot spawn as a drone.</span>")
return
if(!user.MayRespawn(1, MINISYNTH))
return
if(!fabricator)
var/list/all_fabricators = list()
for(var/obj/machinery/drone_fabricator/DF in SSmachinery.all_machines)
if((DF.stat & NOPOWER) || !DF.produce_drones || DF.drone_progress < 100)
continue
all_fabricators[DF.fabricator_tag] = DF
if(!all_fabricators.len)
to_chat(user, "<span class='danger'>There are no available drone spawn points, sorry.</span>")
return
var/choice = input(user,"Which fabricator do you wish to use?") as null|anything in all_fabricators
if(!choice || !all_fabricators[choice])
return
fabricator = all_fabricators[choice]
if(user && fabricator && !((fabricator.stat & NOPOWER) || !fabricator.produce_drones || fabricator.drone_progress < 100))
fabricator.create_drone(user.client)
return 1
return

View File

@@ -54,4 +54,3 @@
MOB_STOP_THINKING(src) MOB_STOP_THINKING(src)
update_client_color() update_client_color()
testing("mob_login - end")

View File

@@ -13,6 +13,7 @@
wall_type = /turf/simulated/wall/titanium wall_type = /turf/simulated/wall/titanium
floor_type = /turf/simulated/floor/reinforced floor_type = /turf/simulated/floor/reinforced
spawn_roof = TRUE
var/list/supplied_drop_types = list() var/list/supplied_drop_types = list()
var/door_type = /obj/structure/droppod_door var/door_type = /obj/structure/droppod_door
var/drop_type = /mob/living/simple_animal/parrot var/drop_type = /mob/living/simple_animal/parrot

View File

@@ -23,6 +23,7 @@ var/global/list/map_count = list()
var/wall_type = /turf/simulated/wall var/wall_type = /turf/simulated/wall
var/floor_type = /turf/simulated/floor var/floor_type = /turf/simulated/floor
var/target_turf_type var/target_turf_type
var/spawn_roof = FALSE //Set to TRUE if a roof should be spawned based.
// Storage for the final iteration of the map. // Storage for the final iteration of the map.
var/list/map = list() // Actual map. var/list/map = list() // Actual map.
@@ -179,6 +180,8 @@ var/global/list/map_count = list()
var/newpath = get_appropriate_path(map[tmp_cell]) var/newpath = get_appropriate_path(map[tmp_cell])
if(newpath) if(newpath)
T.ChangeTurf(newpath) T.ChangeTurf(newpath)
if(spawn_roof)
T.spawn_roof()
get_additional_spawns(map[tmp_cell],T,get_spawn_dir(x, y)) get_additional_spawns(map[tmp_cell],T,get_spawn_dir(x, y))
return T return T

View File

@@ -0,0 +1,38 @@
/*
*
* Unit Test Template
* This file is not used.
*
*/
datum/unit_test/template
name = "Ghost Spawner Tests" // If it's a template leave the word "template" in it's name so it's not ran.
datum/unit_test/template/start_test()
var/list/ignore_spawners = list(
/datum/ghostspawner/human,
/datum/ghostspawner/human/admin,
/datum/ghostspawner/simplemob
)
var/failed_checks = 0
var/checks = 0
for(var/spawner in subtypesof(/datum/ghostspawner))
checks++
var/datum/ghostspawner/G = new spawner
if(instances_of_type_in_list(G,ignore_spawners, strict = TRUE))
continue
//Check if we hae name, short_name and desc set
if(!G.short_name || !G.name || !G.desc)
log_unit_test("[ascii_red]--------------- Invalid Spawner: Type:[G.type], Short-Name:[G.short_name], Name:[G.name]")
failed_checks++
if(failed_checks)
fail("\[[failed_checks] / [checks]\] Ghost Spawners are invalid")
else
pass("All Ghost Spawners are valid.")
return 1
// ============================================================================

View File

@@ -6507,15 +6507,6 @@
}, },
/turf/simulated/floor/tiled, /turf/simulated/floor/tiled,
/area/merchant_station) /area/merchant_station)
"apk" = (
/obj/machinery/computer/cryopod{
pixel_y = 32
},
/obj/machinery/light{
dir = 1
},
/turf/simulated/floor/tiled,
/area/merchant_station)
"apl" = ( "apl" = (
/obj/machinery/sleeper{ /obj/machinery/sleeper{
icon_state = "sleeper_0"; icon_state = "sleeper_0";
@@ -6608,8 +6599,6 @@
/area/merchant_station) /area/merchant_station)
"apy" = ( "apy" = (
/obj/structure/table/reinforced, /obj/structure/table/reinforced,
/obj/item/weapon/storage/firstaid/fire,
/obj/item/weapon/storage/firstaid/o2,
/obj/item/weapon/storage/firstaid/toxin, /obj/item/weapon/storage/firstaid/toxin,
/obj/item/weapon/storage/firstaid/regular, /obj/item/weapon/storage/firstaid/regular,
/turf/simulated/floor/tiled, /turf/simulated/floor/tiled,
@@ -23760,7 +23749,9 @@
/turf/simulated/floor/tiled/dark, /turf/simulated/floor/tiled/dark,
/area/centcom/legion) /area/centcom/legion)
"bbm" = ( "bbm" = (
/obj/structure/bed/chair/comfy/black, /obj/effect/landmark{
name = "TCFLCommander"
},
/turf/simulated/floor/carpet/blue, /turf/simulated/floor/carpet/blue,
/area/centcom/legion) /area/centcom/legion)
"bbn" = ( "bbn" = (
@@ -24430,6 +24421,12 @@
icon_state = "floor" icon_state = "floor"
}, },
/area/centcom/ferry) /area/centcom/ferry)
"gVd" = (
/obj/structure/table/reinforced,
/obj/item/weapon/storage/firstaid/fire,
/obj/item/weapon/storage/firstaid/o2,
/turf/simulated/floor/tiled,
/area/merchant_station)
"haj" = ( "haj" = (
/obj/machinery/chem_master, /obj/machinery/chem_master,
/turf/simulated/floor/tiled/dark, /turf/simulated/floor/tiled/dark,
@@ -24438,6 +24435,10 @@
/obj/structure/bed/chair/office/dark{ /obj/structure/bed/chair/office/dark{
dir = 1 dir = 1
}, },
/obj/effect/ghostspawpoint{
identifier = "OdinCheckpoint";
name = "igs - OdinCheckpoint"
},
/turf/unsimulated/floor{ /turf/unsimulated/floor{
icon_state = "floor" icon_state = "floor"
}, },
@@ -24811,6 +24812,13 @@
/obj/effect/wingrille_spawn/reinforced/crescent, /obj/effect/wingrille_spawn/reinforced/crescent,
/turf/template_noop, /turf/template_noop,
/area/centcom/evac) /area/centcom/evac)
"mrx" = (
/obj/effect/ghostspawpoint/cryo{
dir = 4;
identifier = "MerchantAss"
},
/turf/simulated/floor/tiled,
/area/merchant_station)
"mQj" = ( "mQj" = (
/turf/unsimulated/floor{ /turf/unsimulated/floor{
dir = 10; dir = 10;
@@ -25101,6 +25109,10 @@
/area/centcom/living) /area/centcom/living)
"sQk" = ( "sQk" = (
/obj/structure/bed/chair/office/dark, /obj/structure/bed/chair/office/dark,
/obj/effect/ghostspawpoint{
identifier = "OdinCheckpoint";
name = "igs - OdinCheckpoint"
},
/turf/unsimulated/floor{ /turf/unsimulated/floor{
icon_state = "floor" icon_state = "floor"
}, },
@@ -25151,6 +25163,15 @@
dir = 4 dir = 4
}, },
/area/centcom/living) /area/centcom/living)
"tou" = (
/obj/effect/landmark{
name = "CCIAEscort"
},
/turf/unsimulated/floor{
icon_state = "vault";
dir = 5
},
/area/centcom/ferry)
"tAQ" = ( "tAQ" = (
/obj/machinery/door/blast/odin{ /obj/machinery/door/blast/odin{
density = 0; density = 0;
@@ -25181,6 +25202,15 @@
icon_state = "floor" icon_state = "floor"
}, },
/area/centcom/checkpoint/fore) /area/centcom/checkpoint/fore)
"uQh" = (
/obj/machinery/light{
dir = 1
},
/obj/machinery/computer/cryopod{
pixel_y = 32
},
/turf/simulated/floor/tiled,
/area/merchant_station)
"vdZ" = ( "vdZ" = (
/obj/effect/decal/warning_stripes, /obj/effect/decal/warning_stripes,
/obj/machinery/porta_turret/crescent, /obj/machinery/porta_turret/crescent,
@@ -29863,7 +29893,7 @@ ahM
ahM ahM
aaP aaP
ahV ahV
ahV aoY
aoY aoY
aoY aoY
aoY aoY
@@ -30120,10 +30150,10 @@ ahM
aaP aaP
aaP aaP
ahV ahV
ahV
aoY aoY
api api
api api
api
aoY aoY
apN apN
aXW aXW
@@ -30377,8 +30407,8 @@ ahM
aaP aaP
ahV ahV
ahV ahV
ahV
aoY aoY
mrx
apj apj
apj apj
aoY aoY
@@ -30634,9 +30664,9 @@ ahM
aaP aaP
ahV ahV
ahV ahV
ahV
aoY aoY
apk uQh
apt
apt apt
apK apK
apt apt
@@ -30891,8 +30921,8 @@ ahM
aaP aaP
ahV ahV
ahV ahV
ahV
aoY aoY
gVd
apl apl
apy apy
aoY aoY
@@ -31148,7 +31178,7 @@ ahM
aaP aaP
ahV ahV
ahV ahV
ahV aoY
aoY aoY
aoY aoY
aoY aoY
@@ -60765,7 +60795,7 @@ aDm
aDm aDm
aDM aDM
aDY aDY
aDY tou
aDY aDY
aDM aDM
aEN aEN

View File

@@ -1,5 +1,13 @@
module.exports = { module.exports = {
presets: [ presets: [
['@vue/app', { useBuiltIns: 'entry' }] ['@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: 3,
targets: {
ie: 9
}
}
]
] ]
} }

874
vueui/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -9,17 +9,18 @@
"dev": "vue-cli-service build --watch" "dev": "vue-cli-service build --watch"
}, },
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-free": "^5.9.0", "@fortawesome/fontawesome-free": "^5.10.1",
"core-js": "^3.1.4", "core-js": "^3.1.4",
"core-js-compat": "^3.1.4", "core-js-compat": "^3.1.4",
"fuse.js": "^3.4.5", "fuse.js": "^3.4.5",
"vue": "^2.6.10", "vue": "^2.6.10",
"webpack": "^4.35.3" "webpack": "^4.39.1"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "^3.9.2", "@babel/preset-env": "^7.5.5",
"@vue/cli-plugin-eslint": "^3.9.2", "@vue/cli-plugin-babel": "^3.10.0",
"@vue/cli-service": "^3.9.2", "@vue/cli-plugin-eslint": "^3.10.0",
"@vue/cli-service": "^3.10.0",
"node-sass": "^4.12.0", "node-sass": "^4.12.0",
"sass-loader": "^7.1.0", "sass-loader": "^7.1.0",
"vue-template-compiler": "^2.6.10", "vue-template-compiler": "^2.6.10",

View File

@@ -0,0 +1,78 @@
<template>
<div>
<div class="tagselector" v-show="!spawnpoint">
<vui-button v-for="(amount,tag) in tags" :key="tag" v-on:click="current_tag = tag" v-bind:class="{ selected: current_tag == tag}">{{tag}} ({{amount}})</vui-button>
</div>
<hr v-show="!spawnpoint">
<table>
<tr>
<th>Name</th>
<th>Description</th>
<th>Available Slots</th>
<th class="action">Actions</th>
</tr>
<tr v-for="(data,index) in spawners" :key="index" v-show="showEntry(data)">
<td>{{data.name}}</td>
<td>{{data.desc}}</td>
<td v-if="data.max_count > 0">{{data.max_count - data.count}} / {{data.max_count}}</td>
<td v-else>&infin;</td>
<td class="action">
<vui-button :disabled="(data.cant_spawn !== 0)" :params="{spawn: index, spawnpoint: spawnpoint}" icon="star">Spawn</vui-button>
<vui-button v-if="data.can_edit == 1" :disabled="(data.enabled == 1)" :params="{enable: index}">Enable</vui-button>
<vui-button v-if="data.can_edit == 1" :disabled="(data.enabled == 0)" :params="{disable: index}">Disable</vui-button>
</td>
</tr>
</table>
</div>
</template>
<script>
export default {
data() {
return this.$root.$data.state;
},
computed: {
tags: function() {
let st = Object.values(this.spawners).flatMap(s => s.tags)
let tags = {All: Object.values(this.spawners).length}
st.filter((v, i, a) => a.indexOf(v) === i).forEach(tag => {
tags[tag] = st.filter(t => t == tag).length
})
return tags
}
}, methods:{
showEntry: function(data) {
if(!this.spawnpoint){
//if we dont have a spawnpoint-filter set, then look at the tag filter
return !data.tags.indexOf(this.current_tag) || this.current_tag == 'All'
} else {
//if we have a spawnpoint filter set, filter by spawnpoints
if(!data.hasOwnProperty('spawnpoints'))
return false
return !data.spawnpoints.indexOf(this.spawnpoint)
}
}
}
}
</script>
<style lang="scss" scoped>
table {
width: 100%;
th, td {
text-align: center;
width: auto;
&.action {
width: 1%;
white-space: nowrap;
}
}
th {
font-weight: bold;
}
}
.tagselector {
display: flex;
}
</style>

View File

@@ -8,7 +8,6 @@ import camelCase from 'lodash/camelCase'
import Store from './store.js' import Store from './store.js'
import './assets/global.scss' import './assets/global.scss'
import './polyfills.js'
const requireComponent = require.context( const requireComponent = require.context(
'./components', // The relative path of the components folder './components', // The relative path of the components folder

View File

@@ -1 +0,0 @@
import 'core-js/es/object/values'