mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2025-12-21 15:42:35 +00:00
Ghost Roles (#6706)
This commit is contained in:
@@ -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"
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
176
code/controllers/subsystems/ghostroles.dm
Normal file
176
code/controllers/subsystems/ghostroles.dm
Normal 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
|
||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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]"
|
|
||||||
146
code/modules/ghostroles/spawner/base.dm
Normal file
146
code/modules/ghostroles/spawner/base.dm
Normal 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
|
||||||
115
code/modules/ghostroles/spawner/human/admin.dm
Normal file
115
code/modules/ghostroles/spawner/human/admin.dm
Normal 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. "
|
||||||
166
code/modules/ghostroles/spawner/human/emergencypod.dm
Normal file
166
code/modules/ghostroles/spawner/human/emergencypod.dm
Normal 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"
|
||||||
113
code/modules/ghostroles/spawner/human/human.dm
Normal file
113
code/modules/ghostroles/spawner/human/human.dm
Normal 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)
|
||||||
|
. = ..()
|
||||||
32
code/modules/ghostroles/spawner/human/merchant.dm
Normal file
32
code/modules/ghostroles/spawner/human/merchant.dm
Normal 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
|
||||||
27
code/modules/ghostroles/spawner/human/visitor.dm
Normal file
27
code/modules/ghostroles/spawner/human/visitor.dm
Normal 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)
|
||||||
41
code/modules/ghostroles/spawner/simplemob/maintdrone.dm
Normal file
41
code/modules/ghostroles/spawner/simplemob/maintdrone.dm
Normal 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
|
||||||
41
code/modules/ghostroles/spawner/simplemob/rat.dm
Normal file
41
code/modules/ghostroles/spawner/simplemob/rat.dm
Normal 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
|
||||||
124
code/modules/ghostroles/spawnpoint/spawnpoint.dm
Normal file
124
code/modules/ghostroles/spawnpoint/spawnpoint.dm
Normal 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
|
||||||
@@ -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)
|
||||||
|
if(random_gender)
|
||||||
gender = pick(MALE, FEMALE)
|
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)
|
||||||
|
|||||||
@@ -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)]°C ([round(environment.temperature,0.1)]K)</span>")
|
to_chat(src, "<span class='notice'>Temperature: [round(environment.temperature-T0C,0.1)]°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)
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -54,4 +54,3 @@
|
|||||||
MOB_STOP_THINKING(src)
|
MOB_STOP_THINKING(src)
|
||||||
|
|
||||||
update_client_color()
|
update_client_color()
|
||||||
testing("mob_login - end")
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
38
code/unit_tests/spawner_tests.dm
Normal file
38
code/unit_tests/spawner_tests.dm
Normal 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
|
||||||
|
// ============================================================================
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
874
vueui/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -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",
|
||||||
|
|||||||
78
vueui/src/components/view/misc/ghostspawner.vue
Normal file
78
vueui/src/components/view/misc/ghostspawner.vue
Normal 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>∞</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>
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
import 'core-js/es/object/values'
|
|
||||||
Reference in New Issue
Block a user