Ghostspawner Conversion 2 (#10970)

This commit is contained in:
Geeves
2021-01-16 12:41:24 +01:00
committed by GitHub
parent 74982a3222
commit e2abfd7e23
17 changed files with 118 additions and 555 deletions
@@ -720,7 +720,6 @@
SearchVar(event_last_fired)
SearchVar(dreams)
SearchVar(non_fakeattack_weapons)
SearchVar(ghost_traps)
SearchVar(current_map.holodeck_programs)
SearchVar(fruit_icon_cache)
SearchVar(plant_seed_sprites)
+2 -7
View File
@@ -10,7 +10,6 @@
/datum/brain_trauma/special/imaginary_friend/on_gain()
..()
make_friend()
get_ghost()
/datum/brain_trauma/special/imaginary_friend/on_life()
if(get_dist(owner, friend) > 9)
@@ -24,12 +23,7 @@
/datum/brain_trauma/special/imaginary_friend/proc/make_friend()
friend = new(get_turf(src), src)
/datum/brain_trauma/special/imaginary_friend/proc/get_ghost()
set waitfor = FALSE
var/datum/ghosttrap/G = get_ghost_trap("friend")
G.request_player(friend, "Would you like to play as [owner]'s imaginary friend?", 60 SECONDS)
addtimer(CALLBACK(src, .proc/reset_search), 60 SECONDS)
SSghostroles.add_spawn_atom("imaginary_friend", friend)
/datum/brain_trauma/special/imaginary_friend/proc/reset_search()
if(src.friend && src.friend.key)
@@ -91,6 +85,7 @@
owner.client.images.Remove(human_image)
if(client)
client.images.Remove(human_image)
SSghostroles.remove_spawn_atom("imaginary_friend", src)
return ..()
/mob/abstract/mental/friend/proc/yank()
+6 -21
View File
@@ -16,24 +16,12 @@
/datum/brain_trauma/severe/split_personality/on_gain()
..()
make_backseats()
get_ghost()
/datum/brain_trauma/severe/split_personality/proc/make_backseats()
stranger_backseat = new(owner, src)
SSghostroles.add_spawn_atom("split_personality", stranger_backseat)
owner_backseat = new(owner, src)
/datum/brain_trauma/severe/split_personality/proc/get_ghost()
set waitfor = FALSE
var/datum/ghosttrap/G = get_ghost_trap("split personality")
G.request_player(stranger_backseat, "Would you like to play as [owner]'s split personality?", 60 SECONDS)
addtimer(CALLBACK(src, .proc/reset_search), 60 SECONDS)
/datum/brain_trauma/severe/split_personality/proc/reset_search()
if(src.stranger_backseat && src.stranger_backseat.key)
return
else
qdel(src)
/datum/brain_trauma/severe/split_personality/on_life()
if(owner.stat == DEAD)
if(current_controller != OWNER)
@@ -63,7 +51,7 @@
current_backseat = owner_backseat
free_backseat = stranger_backseat
log_game("[current_backseat]/([current_backseat.ckey]) assumed control of [owner]/([owner.ckey] due to [src]. (Original owner: [current_controller == OWNER ? owner.ckey : current_backseat.ckey])")
log_game("[current_backseat]/([current_backseat.ckey]) assumed control of [owner]/([owner.ckey]) due to [src]. (Original owner: [current_controller == OWNER ? owner.ckey : current_backseat.ckey])")
to_chat(owner, "<span class='danger'>You feel your control being taken away... your other personality is in charge now!</span>")
to_chat(current_backseat, "<span class='danger'>You manage to take control of your body!</span>")
@@ -146,6 +134,10 @@
/mob/living/mental/split_personality/emote(message)
return
/mob/living/mental/split_personality/Destroy()
SSghostroles.remove_spawn_atom("split_personality", src)
return ..()
///////////////BRAINWASHING////////////////////
/datum/brain_trauma/severe/split_personality/brainwashing
@@ -180,13 +172,6 @@
stranger_backseat = new /mob/living/mental/split_personality/traitor(owner, src, codeword, objective)
owner_backseat = new(owner, src)
/datum/brain_trauma/severe/split_personality/brainwashing/get_ghost()
set waitfor = FALSE
var/datum/ghosttrap/G = get_ghost_trap("split personality")
G.request_player(stranger_backseat, "Would you like to play as [owner]'s split personality?", 60 SECONDS)
addtimer(CALLBACK(src, .proc/reset_search), 60 SECONDS)
/datum/brain_trauma/severe/split_personality/brainwashing/on_life()
return //no random switching
@@ -1,25 +0,0 @@
/datum/admin_secret_item/admin_secret/replace_player_with_ghost
name = "Replace player with ghost"
/datum/admin_secret_item/admin_secret/replace_player_with_ghost/can_execute(var/mob/user)
if(!ROUND_IS_STARTED) return 0
return ..()
/datum/admin_secret_item/admin_secret/replace_player_with_ghost/execute(var/mob/user)
. = ..()
if(!.)
return
var/list/targets = list()
targets += getmobs()
var/mob/T = input(user, "Which player do you want to replace?") as null|anything in targets
if (!T)
return
var/mob/player_to_replace = targets[T]
var/datum/ghosttrap/G = get_ghost_trap("[player_to_replace.mind.special_role]")
if(player_to_replace.client)
player_to_replace.ghostize(0)
if(G)
G.request_player(player_to_replace, "Would you like to play as a [player_to_replace.mind.special_role]?", 60 SECONDS)
else
G = ghost_traps["Special"]
G.request_player(player_to_replace, "Would you like to play as [player_to_replace.name]?", 60 SECONDS)
@@ -57,42 +57,10 @@
else
dat += "<a href='?src=\ref[src];add_special=[antag.role_type]'>Yes</a> / <b>No</b></br>"
dat += "</td></tr>"
var/list/ghost_traps = get_ghost_traps()
for(var/ghost_trap_key in ghost_traps)
var/datum/ghosttrap/ghost_trap = ghost_traps[ghost_trap_key]
if(!ghost_trap.list_as_special_role)
continue
dat += "<tr><td>[(ghost_trap.ghost_trap_role)]: </td><td>"
var/ban_state = banned_from_ghost_role(preference_mob(), ghost_trap)
if(ban_state == AGEBAN)
var/age_to_beat = 0
for (var/A in ghost_trap.ban_checks)
age_to_beat = player_old_enough_for_role(preference_mob(), A)
if (age_to_beat)
break
dat += "<span class='danger'>\[IN [age_to_beat] DAYS\]</span><br>"
else if (ban_state == RANBAN)
dat += "<span class='danger'>\[<a href='?src=\ref[user.client];view_jobban=[ghost_trap];'>BANNED</a>\]</span><br>"
else if(ghost_trap.pref_check in pref.be_special_role)
dat += "<b>Yes</b> / <a href='?src=\ref[src];del_special=[ghost_trap.pref_check]'>No</a></br>"
else
dat += "<a href='?src=\ref[src];add_special=[ghost_trap.pref_check]'>Yes</a> / <b>No</b></br>"
dat += "</td></tr>"
dat += "</table>"
. = dat.Join()
/datum/category_item/player_setup_item/proc/banned_from_ghost_role(var/mob, var/datum/ghosttrap/ghost_trap)
for(var/ban_type in ghost_trap.ban_checks)
. = jobban_isbanned(mob, ban_type)
if(. == "AGE WHITELISTED")
return AGEBAN
else if (.)
return RANBAN
return NOBAN
/datum/category_item/player_setup_item/antagonism/candidacy/OnTopic(var/href,var/list/href_list, var/mob/user)
if(href_list["add_special"])
if(!(href_list["add_special"] in valid_special_roles()))
@@ -112,13 +80,6 @@
var/datum/antagonist/antag = all_antag_types[antag_type]
private_valid_special_roles += antag.role_type
var/list/ghost_traps = get_ghost_traps()
for(var/ghost_trap_key in ghost_traps)
var/datum/ghosttrap/ghost_trap = ghost_traps[ghost_trap_key]
if(!ghost_trap.list_as_special_role)
continue
private_valid_special_roles += ghost_trap.pref_check
return private_valid_special_roles
#undef AGEBAN
@@ -0,0 +1,10 @@
/datum/ghostspawner/diona_nymph
short_name = "diona_nymph"
name = "Diona Nymph"
desc = "Join in as a Diona Nymph. Suck blood, act cuter than you really are."
tags = list("Simple Mobs")
loc_type = GS_LOC_ATOM
atom_add_message = "A Diona Nymph has sprung up somewhere on the station!"
spawn_mob = /mob/living/carbon/alien/diona
@@ -0,0 +1,10 @@
/datum/ghostspawner/imaginary_friend
short_name = "imaginary_friend"
name = "Imaginary Friend"
desc = "Join in as a Imaginary Friend, help them find their way throughout the round."
tags = list("Mental Trauma")
loc_type = GS_LOC_ATOM
atom_add_message = "Someone has conjured up an imaginary friend!"
spawn_mob = /mob/abstract/mental/friend
@@ -0,0 +1,10 @@
/datum/ghostspawner/living_plant
short_name = "living_plant"
name = "Living Plant"
desc = "Join in as a Living Plant. What do plants do?"
tags = list("Simple Mobs")
loc_type = GS_LOC_ATOM
atom_add_message = "A Living Plant has sprung up somewhere on the station!"
spawn_mob = /mob/living
@@ -0,0 +1,10 @@
/datum/ghostspawner/split_personality
short_name = "split_personality"
name = "Split Personality"
desc = "Join in as a Split Personality, play the alter ego of one poor crewmember."
tags = list("Mental Trauma")
loc_type = GS_LOC_ATOM
atom_add_message = "Someone has developed a split personality!"
spawn_mob = /mob/living/mental/split_personality
@@ -0,0 +1,10 @@
/datum/ghostspawner/rebooted_maint_drone
short_name = "rebooted_maint_drone"
name = "Rebooted Maint Drone"
desc = "Join in as a Rebooted Maintenance Drone. Do dronelike things."
tags = list("Simple Mobs")
loc_type = GS_LOC_ATOM
atom_add_message = "A maintenance drone has started its rebooting procedure!"
spawn_mob = /mob/living/silicon/robot/drone
-433
View File
@@ -1,433 +0,0 @@
// This system is used to grab a ghost from observers with the required preferences and
// lack of bans set. See posibrain.dm for an example of how they are called/used. ~Z
var/list/ghost_traps
/proc/get_ghost_trap(var/trap_key)
if(!ghost_traps)
populate_ghost_traps()
return ghost_traps[trap_key]
/proc/get_ghost_traps()
if(!ghost_traps)
populate_ghost_traps()
return ghost_traps
/proc/populate_ghost_traps()
ghost_traps = list()
for(var/traptype in typesof(/datum/ghosttrap))
var/datum/ghosttrap/G = new traptype
ghost_traps[G.object] = G
/datum/ghosttrap
var/object = "positronic brain"
var/respawn_check = 0//Which respawning test we check against
var/list/ban_checks = list("AI","Cyborg")
var/pref_check = BE_SYNTH
var/ghost_trap_message = "They are occupying a positronic brain now."
var/ghost_trap_role = "Positronic Brain"
var/can_set_own_name = TRUE
var/list_as_special_role = TRUE // If true, this entry will be listed as a special role in the character setup
var/list/request_timeouts
/datum/ghosttrap/New()
request_timeouts = list()
..()
// Check for bans, proper atom types, etc.
/datum/ghosttrap/proc/assess_candidate(var/mob/abstract/observer/candidate, var/mob/target)
if(!candidate.MayRespawn(1, respawn_check))
return 0
if(islist(ban_checks))
for(var/bantype in ban_checks)
if(jobban_isbanned(candidate, "[bantype]"))
to_chat(candidate, "You are banned from one or more required roles and hence cannot enter play as \a [object].")
return 0
return 1
// Print a message to all ghosts with the right prefs/lack of bans.
/datum/ghosttrap/proc/request_player(var/mob/target, var/request_string, var/request_timeout)
if(request_timeout)
request_timeouts[target] = world.time + request_timeout
destroyed_event.register(target, src, /datum/ghosttrap/proc/target_destroyed)
else
request_timeouts -= target
for(var/mob/abstract/observer/O in player_list)
if(!O.MayRespawn())
continue
if(islist(ban_checks))
for(var/bantype in ban_checks)
if(jobban_isbanned(O, "[bantype]"))
continue
if(pref_check && !(pref_check in O.client.prefs.be_special_role))
continue
if(O.client)
to_chat(O, "[ghost_follow_link(target, O)] <span class='deadsay'><font size=3><b>[request_string] <a href='?src=\ref[src];candidate=\ref[O];target=\ref[target]'>(Occupy)</a></b></font></span>")
/datum/ghosttrap/proc/target_destroyed(var/destroyed_target)
request_timeouts -= destroyed_target
// Handles a response to request_player().
/datum/ghosttrap/Topic(href, href_list)
if(..())
return 1
if(href_list["candidate"] && href_list["target"])
var/mob/abstract/observer/candidate = locate(href_list["candidate"]) // BYOND magic.
var/mob/target = locate(href_list["target"]) // So much BYOND magic.
if(!target || !candidate)
return
if(candidate != usr)
return
if(request_timeouts[target] && world.time > request_timeouts[target])
to_chat(candidate, "This occupation request is no longer valid.")
return
if(target.key)
to_chat(candidate, "The target is already occupied.")
return
if(assess_candidate(candidate, target))
transfer_personality(candidate,target)
return 1
// Shunts the ckey/mind into the target mob.
/datum/ghosttrap/proc/transfer_personality(var/mob/candidate, var/mob/target)
if(!assess_candidate(candidate))
return 0
target.ckey = candidate.ckey
if(target.mind)
target.mind.assigned_role = "[ghost_trap_role]"
announce_ghost_joinleave(candidate, 0, "[ghost_trap_message]")
welcome_candidate(target)
set_new_name(target)
return 1
// Fluff!
/datum/ghosttrap/proc/welcome_candidate(var/mob/target)
to_chat(target, "<b>You are a positronic brain, brought into existence on [station_name()].</b>")
to_chat(target, "<b>As a synthetic intelligence, you answer to all crewmembers, as well as the AI.</b>")
to_chat(target, "<b>Remember, the purpose of your existence is to serve the crew and the station. Above all else, do no harm.</b>")
to_chat(target, "<b>Use say [target.get_language_prefix()]b to speak to other artificial intelligences.</b>")
var/turf/T = get_turf(target)
T.visible_message("<span class='notice'>\The [target] chimes quietly.</span>")
var/obj/item/device/mmi/digital/posibrain/P = target.loc
if(!istype(P)) //wat
return
P.searching = 0
P.name = "positronic brain ([P.brainmob.name])"
P.icon_state = "posibrain-occupied"
// Allows people to set their own name. May or may not need to be removed for posibrains if people are dumbasses.
/datum/ghosttrap/proc/set_new_name(var/mob/target)
if(!can_set_own_name)
return
var/newname = sanitizeSafe(input(target,"Enter a name, or leave blank for the default name.", "Name change","") as text, MAX_NAME_LEN)
if (newname != "")
target.real_name = newname
target.name = target.real_name
/***********************************
* Diona pods and walking mushrooms *
***********************************/
/datum/ghosttrap/plant
object = "living plant"
ban_checks = list("Dionaea")
pref_check = BE_PLANT
ghost_trap_message = "They are occupying a living plant now."
ghost_trap_role = "Plant"
/datum/ghosttrap/plant/welcome_candidate(var/mob/target)
to_chat(target, "<span class='alium'><B>You awaken slowly, stirring into sluggish motion as the air caresses you.</B></span>")
// This is a hack, replace with some kind of species blurb proc.
if(istype(target,/mob/living/carbon/alien/diona))
to_chat(target, "<B>You are \a [target], one of a race of drifting interstellar plantlike creatures that sometimes share their seeds with human traders.</B>")
to_chat(target, "<B>Too much darkness will send you into shock and starve you, but light will help you heal.</B>")
/*****************
* Cortical Borer *
*****************/
/datum/ghosttrap/borer
object = "cortical borer"
ban_checks = list("Borer")
pref_check = MODE_BORER
ghost_trap_message = "They are occupying a borer now."
ghost_trap_role = "Cortical Borer"
can_set_own_name = FALSE
list_as_special_role = FALSE
/datum/ghosttrap/borer/welcome_candidate(var/mob/target)
to_chat(target, "<span class='notice'>You are a cortical borer!</span> You are a brain slug that worms its way into the head of its victim. Use stealth, persuasion and your powers of mind control to keep you, your host and your eventual spawn safe and warm.")
to_chat(target, "You can speak to your victim with <b>say</b>, to other borers with <b>say [target.get_language_prefix()]x</b>, and use your Abilities tab to access powers.")
/********************
* Maintenance Drone *
*********************/
/datum/ghosttrap/drone
object = "maintenance drone"
pref_check = BE_PAI
ghost_trap_message = "They are occupying a maintenance drone now."
ghost_trap_role = "Maintenance Drone"
can_set_own_name = FALSE
list_as_special_role = FALSE
/datum/ghosttrap/drone/New()
respawn_check = MINISYNTH
..()
datum/ghosttrap/drone/assess_candidate(var/mob/abstract/observer/candidate, var/mob/target)
. = ..()
if(. && !target.can_be_possessed_by(candidate))
return 0
datum/ghosttrap/drone/transfer_personality(var/mob/candidate, var/mob/living/silicon/robot/drone/drone)
if(!assess_candidate(candidate))
return 0
drone.transfer_personality(candidate.client)
/********************
* Mining Drone *
*********************/
/datum/ghosttrap/mdrone
object = "mining drone"
pref_check = BE_PAI
ghost_trap_message = "They are occupying a mining drone now."
ghost_trap_role = "Mining Drone"
can_set_own_name = FALSE
list_as_special_role = FALSE
/datum/ghosttrap/mdrone/New()
respawn_check = MINISYNTH
..()
/datum/ghosttrap/mdrone/assess_candidate(var/mob/abstract/observer/candidate, var/mob/target)
. = ..()
if(. && !target.can_be_possessed_by(candidate))
return 0
datum/ghosttrap/drone/transfer_personality(var/mob/candidate, var/mob/living/silicon/robot/drone/drone)
if(!assess_candidate(candidate))
return 0
drone.transfer_personality(candidate.client)
var/tmp_health = drone.health
drone.revive()
drone.health = tmp_health
drone.updatehealth()
/***********************************
* Syndicate Cyborg *
***********************************/
/datum/ghosttrap/syndicateborg
object = "syndicate cyborg"
ban_checks = list("Antagonist","AI","Cyborg")
pref_check = BE_SYNTH
ghost_trap_message = "They are occupying a syndicate cyborg now."
ghost_trap_role = "Syndicate Cyborg"
can_set_own_name = TRUE
list_as_special_role = FALSE
/datum/ghosttrap/syndicateborg/welcome_candidate(var/mob/target)
to_chat(target, "<span class='notice'><B>You are a syndicate cyborg, bound to help and follow the orders of the mercenaries that are deploying you. Remember to speak to the other mercenaries to know more about their plans</B></span>")
mercs.add_antagonist_mind(target.mind,1)
/**************
* pAI *
**************/
/datum/ghosttrap/pai
object = "pAI"
pref_check = BE_PAI
ghost_trap_message = "They are occupying a pAI now."
ghost_trap_role = "pAI"
datum/ghosttrap/pai/assess_candidate(var/mob/candidate, var/mob/target)
return 0
datum/ghosttrap/pai/transfer_personality(var/mob/candidate, var/mob/living/silicon/robot/drone/drone)
return 0
/**************
* Wizard Familiar *
**************/
/datum/ghosttrap/familiar
object = "wizard familiar"
pref_check = MODE_WIZARD
ghost_trap_message = "They are occupying a familiar now."
ghost_trap_role = "Wizard Familiar"
ban_checks = list(MODE_WIZARD)
list_as_special_role = FALSE
/datum/ghosttrap/familiar/welcome_candidate(var/mob/target)
return 0
/**************
* Skeleton minion *
**************/
/datum/ghosttrap/skeleton
object = "skeleton minion"
pref_check = MODE_WIZARD
ghost_trap_message = "They are occupying a skeleton minion."
ghost_trap_role = "Skeleton Minion"
ban_checks = list(MODE_WIZARD)
can_set_own_name = FALSE
list_as_special_role = FALSE
/datum/ghosttrap/skeleton/welcome_candidate(var/mob/target)
return 0
//Gamemodes
/datum/ghosttrap/merc
object = "Mercenary"
pref_check = MODE_MERCENARY
ghost_trap_message = "They are occupying a mercenary."
ghost_trap_role = "Mercenary"
ban_checks = list(MODE_MERCENARY)
can_set_own_name = FALSE
list_as_special_role = FALSE
/datum/ghosttrap/merc/welcome_candidate(var/mob/target)
return 0
/datum/ghosttrap/raider
object = "Raider"
pref_check = MODE_RAIDER
ghost_trap_message = "They are occupying a raider."
ghost_trap_role = "Raider"
ban_checks = list(MODE_RAIDER)
can_set_own_name = FALSE
list_as_special_role = FALSE
/datum/ghosttrap/raider/welcome_candidate(var/mob/target)
return 0
/datum/ghosttrap/ninja
object = "Ninja"
pref_check = MODE_NINJA
ghost_trap_message = "They are occupying a ninja."
ghost_trap_role = "Ninja"
ban_checks = list(MODE_NINJA)
can_set_own_name = FALSE
list_as_special_role = FALSE
/datum/ghosttrap/ninja/welcome_candidate(var/mob/target)
return 0
/datum/ghosttrap/wizard
object = "Wizard"
pref_check = MODE_WIZARD
ghost_trap_message = "They are occupying a wizard."
ghost_trap_role = "Wizard"
ban_checks = list(MODE_WIZARD)
can_set_own_name = FALSE
list_as_special_role = FALSE
/datum/ghosttrap/wizard/welcome_candidate(var/mob/target)
return 0
/datum/ghosttrap/malf
object = "AI Malfunction"
pref_check = MODE_MALFUNCTION
ghost_trap_message = "They are occupying a malfunctioning AI."
ghost_trap_role = "Malfuntioning AI"
ban_checks = list(MODE_MALFUNCTION)
can_set_own_name = FALSE
list_as_special_role = FALSE
/datum/ghosttrap/malf/welcome_candidate(var/mob/target)
return 0
/datum/ghosttrap/ert
object = "Emergency Responder"
pref_check = MODE_ERT
ghost_trap_message = "They are occupying an ERT member."
ghost_trap_role = "ERT member"
ban_checks = list(MODE_ERT)
can_set_own_name = FALSE
list_as_special_role = FALSE
/datum/ghosttrap/ert/welcome_candidate(var/mob/target)
return 0
/datum/ghosttrap/changeling
object = "Changeling"
pref_check = MODE_CHANGELING
ghost_trap_message = "They are occupying a changeling."
ghost_trap_role = "Changeling"
ban_checks = list(MODE_CHANGELING)
can_set_own_name = FALSE
list_as_special_role = FALSE
/datum/ghosttrap/changeling/welcome_candidate(var/mob/target)
return 0
/datum/ghosttrap/cultist
object = "Cult"
pref_check = MODE_CULTIST
ghost_trap_message = "They are occupying a cultist."
ghost_trap_role = "Cultist"
ban_checks = list(MODE_CULTIST)
can_set_own_name = FALSE
list_as_special_role = FALSE
/datum/ghosttrap/cultist/welcome_candidate(var/mob/target)
return 0
/datum/ghosttrap/traitor
object = "Traitor"
pref_check = MODE_TRAITOR
ghost_trap_message = "They are occupying a traitor."
ghost_trap_role = "Traitor"
ban_checks = list(MODE_TRAITOR)
can_set_own_name = FALSE
list_as_special_role = FALSE
/datum/ghosttrap/traitor/welcome_candidate(var/mob/target)
to_chat(target, "<span class ='notice'> Check your notes for your uplink code!</span>")
return 1
/datum/ghosttrap/vampire
object = "Vampire"
pref_check = MODE_VAMPIRE
ghost_trap_message = "They are occupying a vampire."
ghost_trap_role = "Vampire"
ban_checks = list(MODE_VAMPIRE)
can_set_own_name = FALSE
list_as_special_role = FALSE
/datum/ghosttrap/vampire/welcome_candidate(var/mob/target)
return 0
/datum/ghosttrap/special
object = "Special"
pref_check = null
ghost_trap_message = "They are occupying a person."
ghost_trap_role = "person"
ban_checks = list()
can_set_own_name = FALSE
list_as_special_role = FALSE
/datum/ghosttrap/special/welcome_candidate(var/mob/target)
return 0
/datum/ghosttrap/brainwashed
object = "split personality"
ghost_trap_message = "They are a split personality now."
ghost_trap_role = "Split personality"
can_set_own_name = TRUE
list_as_special_role = TRUE
/datum/ghosttrap/brainwashed/welcome_candidate(var/mob/target)
return 0
/datum/ghosttrap/friend
object = "friend"
ghost_trap_message = "They are an imaginary friend now."
ghost_trap_role = "Imaginary friend"
can_set_own_name = TRUE
list_as_special_role = TRUE
/datum/ghosttrap/friend/welcome_candidate(var/mob/target)
return 0
+19 -13
View File
@@ -1,19 +1,25 @@
// The following procs are used to grab players for mobs produced by a seed (mostly for dionaea).
/datum/seed/proc/handle_living_product(var/mob/living/host)
if(!host || !istype(host))
return
if(!host || !istype(host)) return
var/host_spawner_type = "living_plant"
if(istype(host, /mob/living/carbon/alien/diona))
host_spawner_type = "diona_nymph"
var/datum/ghosttrap/plant/P = get_ghost_trap("living plant")
P.request_player(host, "Someone is harvesting \a [display_name].")
SSghostroles.add_spawn_atom(host_spawner_type, host)
addtimer(CALLBACK(src, .proc/kill_living_product, WEAKREF(host), host_spawner_type), 3 MINUTES)
spawn(75)
if(!host.ckey && !host.client)
host.death() // This seems redundant, but a lot of mobs don't
host.stat = DEAD // handle death() properly. Better safe than etc.
host.visible_message("<span class='danger'>[host] is malformed and unable to survive. It expires pitifully, leaving behind some seeds.</span>")
/datum/seed/proc/kill_living_product(var/datum/weakref/host_ref, var/product_spawner_type = "living_plant")
var/mob/living/host = host_ref.resolve()
if(host && !host.ckey && !host.client)
SSghostroles.remove_spawn_atom(product_spawner_type, host)
host.death() // This seems redundant, but a lot of mobs don't
host.stat = DEAD // handle death() properly. Better safe than etc.
host.visible_message("<span class='danger'>[host] is malformed and unable to survive. It expires pitifully, leaving behind some seeds.</span>")
var/total_yield = rand(1,3)
for(var/j = 0;j<=total_yield;j++)
var/obj/item/seeds/S = new(get_turf(host))
S.seed_type = name
S.update_seed()
var/total_yield = rand(1,3)
for(var/j = 0;j<=total_yield;j++)
var/obj/item/seeds/S = new(get_turf(host))
S.seed_type = name
S.update_seed()
+8 -6
View File
@@ -152,16 +152,18 @@
return ..()
/obj/machinery/portable_atmospherics/hydroponics/attack_ghost(var/mob/abstract/observer/user)
if(!(harvest && seed && ispath(seed.product_type, /mob)))
if(!(seed && ispath(seed.product_type, /mob)))
to_chat(user, SPAN_WARNING("This tray doesn't have any seeds, or the planted seeds does not spawn a mob!"))
return
var/datum/ghosttrap/plant/G = get_ghost_trap("living plant")
if(!G.assess_candidate(user))
if(!harvest)
to_chat(user, SPAN_WARNING("\The [src] isn't ready to harvest yet!"))
return
var/response = alert(user, "Are you sure you want to harvest this [seed.display_name]?", "Living plant request", "Yes", "No")
if(jobban_isbanned(user, "Dionaea"))
to_chat(user, SPAN_WARNING("You are banned from playing Dionae and other living plants!"))
return
var/response = alert(user, "Are you sure you want to harvest this [seed.display_name]?", "Living Plant Request", "Yes", "No")
if(response == "Yes")
harvest()
return
/obj/machinery/portable_atmospherics/hydroponics/attack_generic(var/mob/user)
@@ -80,6 +80,8 @@
var/hat_x_offset = 0
var/hat_y_offset = -13
var/rebooting = FALSE
/mob/living/silicon/robot/drone/can_be_possessed_by(var/mob/abstract/observer/possessor)
if(!istype(possessor) || !possessor.client || !possessor.ckey)
return FALSE
@@ -239,6 +241,9 @@
if(!allowed(usr))
to_chat(user, SPAN_WARNING("Access denied."))
return
if(rebooting)
to_chat(user, SPAN_WARNING("\The [src] is already rebooting!"))
return
user.visible_message(SPAN_NOTICE("\The [user] swipes [user.get_pronoun("his")] ID card through \the [src], attempting to reboot it."), SPAN_NOTICE("You swipe your ID card through \the [src], attempting to reboot it."))
request_player()
return
@@ -370,11 +375,17 @@
//Reboot procs.
/mob/living/silicon/robot/drone/Logout()
. = ..()
rebooting = FALSE
/mob/living/silicon/robot/drone/proc/request_player()
if(too_many_active_drones())
return
var/datum/ghosttrap/G = get_ghost_trap("maintenance drone")
G.request_player(src, "Someone is attempting to reboot a maintenance drone.", 30 SECONDS)
if(rebooting)
return
stat = CONSCIOUS
SSghostroles.add_spawn_atom("rebooted_maint_drone", src)
/mob/living/silicon/robot/drone/proc/transfer_personality(var/client/player)
if(!player)
+8 -6
View File
@@ -8,12 +8,14 @@
/turf/proc/create_diona_nymph()
var/mob/living/carbon/alien/diona/D = new(src)
var/datum/ghosttrap/plant/P = get_ghost_trap("living plant")
P.request_player(D, "A diona nymph has split off from its gestalt. ")
sleep(120)
if(D)
if(!D.ckey || !D.client)
D.death()
SSghostroles.add_spawn_atom("diona_nymph", D)
addtimer(CALLBACK(src, .proc/kill_diona_nymph, WEAKREF(D)), 3 MINUTES)
/turf/proc/kill_diona_nymph(var/datum/weakref/diona_ref)
var/mob/living/carbon/alien/diona/D = diona_ref.resolve()
if(D && (!D.ckey || !D.client))
SSghostroles.remove_spawn_atom("diona_nymph", D)
D.death()
//Probable future TODO: Refactor diona organs to be /obj/item/organ/external/bodypart/diona
//Having them not inherit from specific bodypart classes is a problem