Adds ghost click to posibrains.

Added ghost trap system used by plants and posibrains to get players. Added attack_ghost() to hydro trays and posibrains for the aforementioned.
Changelog.
Minor typo.
Topic fixes.
Minor fix.
This commit is contained in:
Zuhayr
2015-05-25 16:49:22 +09:30
parent 3cae318716
commit 88b3019e6c
8 changed files with 170 additions and 131 deletions

View File

@@ -1007,6 +1007,7 @@
#include "code\modules\food\recipes_microwave.dm"
#include "code\modules\games\cards.dm"
#include "code\modules\genetics\side_effects.dm"
#include "code\modules\ghosttrap\trap.dm"
#include "code\modules\holodeck\HolodeckControl.dm"
#include "code\modules\holodeck\HolodeckObjects.dm"
#include "code\modules\holodeck\HolodeckPrograms.dm"

View File

@@ -0,0 +1,114 @@
// 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/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/list/ban_checks = list("AI","Cyborg")
var/pref_check = BE_AI
var/ghost_trap_message = "They are occupying a positronic brain now."
var/ghost_trap_role = "Positronic Brain"
// Check for bans, proper atom types, etc.
/datum/ghosttrap/proc/assess_candidate(var/mob/dead/observer/candidate)
if(!istype(candidate) || !candidate.client || !candidate.ckey)
return 0
if(!candidate.MayRespawn())
candidate << "You have made use of the AntagHUD and hence cannot enter play as \a [object]."
return 0
if(islist(ban_checks))
for(var/bantype in ban_checks)
if(jobban_isbanned(candidate, "[bantype]"))
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)
if(!target)
return
for(var/mob/dead/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 && !(O.client.prefs.be_special & pref_check))
continue
if(O.client)
O << "[request_string]<a href='?src=\ref[src];candidate=\ref[O];target=\ref[target]'>Click here</a> if you wish to play as this option."
// Handles a response to request_player().
/datum/ghosttrap/Topic(href, href_list)
if(..())
return 1
if(href_list["candidate"] && href_list["target"])
var/mob/dead/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 && assess_candidate(candidate) && !target.ckey)
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)
target << "<b>You are a positronic brain, brought into existence on [station_name()].</b>"
target << "<b>As a synthetic intelligence, you answer to all crewmembers, as well as the AI.</b>"
target << "<b>Remember, the purpose of your existence is to serve the crew and the station. Above all else, do no harm.</b>"
target << "<b>Use say :b to speak to other artificial intelligences.</b>"
var/turf/T = get_turf(target)
T.visible_message("<span class='notice'>\The [src] 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)
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
// Doona 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)
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(host,/mob/living/carbon/alien/diona))
target << "<B>You are \a [target], one of a race of drifting interstellar plantlike creatures that sometimes share their seeds with human traders.</B>"
target << "<B>Too much darkness will send you into shock and starve you, but light will help you heal.</B>"

View File

@@ -680,7 +680,6 @@
total_yield = get_trait(TRAIT_YIELD) + rand(yield_mod)
total_yield = max(1,total_yield)
currently_querying = list()
for(var/i = 0;i<total_yield;i++)
var/obj/item/product
if(has_mob_product)

View File

@@ -1,15 +1,11 @@
/datum/seed
var/list/currently_querying // Used to avoid asking the same ghost repeatedly.
// 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
spawn(0)
request_player(host)
if(istype(host,/mob/living/simple_animal))
return
var/datum/ghosttrap/plant/P = get_ghost_trap("living plant")
P.request_player(host, "Someone is harvesting [display_name]. ")
spawn(75)
if(!host.ckey && !host.client)
host.death() // This seems redundant, but a lot of mobs don't
@@ -21,59 +17,3 @@
var/obj/item/seeds/S = new(get_turf(host))
S.seed_type = name
S.update_seed()
/datum/seed/proc/request_player(var/mob/living/host)
if(!host) return
for(var/mob/dead/observer/O in player_list)
if(jobban_isbanned(O, "Dionaea"))
continue
if(O.client && O.MayRespawn())
if(O.client.prefs.be_special & BE_PLANT && !(O.client in currently_querying))
currently_querying |= O.client
question(O.client,host)
/datum/seed/proc/question(var/client/C,var/mob/living/host)
spawn(0)
if(!C || !host || !(C.mob && istype(C.mob,/mob/dead))) return // We don't want to spam them repeatedly if they're already in a mob.
var/response = alert(C, "Someone is harvesting [display_name]. Would you like to play as one?", "Sentient plant harvest", "Yes", "No", "Never for this round.")
if(!C || !host || !(C.mob && istype(C.mob,/mob/dead))) return // ...or accidentally accept an invalid argument for transfer.
if(response == "Yes")
transfer_personality(C,host)
else if (response == "Never for this round")
C.prefs.be_special ^= BE_PLANT
currently_querying -= C
/datum/seed/proc/transfer_personality(var/client/player,var/mob/living/host)
//Something is wrong, abort.
if(!player || !host) return
//Host already has a controller, pike off slowpoke.
if(host.client && host.ckey) return
//Transfer them over.
host.ckey = player.ckey
if(player.mob && player.mob.mind)
player.mob.mind.transfer_to(host)
if(host.dna) host.dna.real_name = host.real_name
// Update mode specific HUD icons.
callHook("harvest_podman", list(host))
host << "\green <B>You awaken slowly, stirring into sluggish motion as the air caresses you.</B>"
// This is a hack, replace with some kind of species blurb proc.
if(istype(host,/mob/living/carbon/alien/diona))
host << "<B>You are [host], one of a race of drifting interstellar plantlike creatures that sometimes share their seeds with human traders.</B>"
host << "<B>Too much darkness will send you into shock and starve you, but light will help you heal.</B>"
var/newname = sanitizeSafe(input(host,"Enter a name, or leave blank for the default name.", "Name change","") as text, MAX_NAME_LEN)
if (newname != "")
host.real_name = newname
host.name = host.real_name

View File

@@ -129,7 +129,22 @@
return
return ..()
/obj/machinery/portable_atmospherics/hydroponics/attack_ghost(var/mob/dead/observer/user)
if(!(harvest && seed && seed.has_mob_product))
return
var/datum/ghosttrap/plant/G = get_ghost_trap("living plant")
if(!G.assess_candidate(user))
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)
// Why did I ever think this was a good idea. TODO: move this onto the nymph mob.
if(istype(user,/mob/living/carbon/alien/diona))
var/mob/living/carbon/alien/diona/nymph = user

View File

@@ -5,47 +5,41 @@
icon_state = "posibrain"
w_class = 3
origin_tech = "engineering=4;materials=4;bluespace=2;programming=4"
var/searching = 0
construction_cost = list(DEFAULT_WALL_MATERIAL=500,"glass"=500,"silver"=200,"gold"=200,"phoron"=100,"diamond"=10)
construction_time = 75
var/searching = 0
var/askDelay = 10 * 60 * 1
req_access = list(access_robotics)
locked = 0
mecha = null//This does not appear to be used outside of reference in mecha.dm.
/obj/item/device/mmi/digital/posibrain/New()
..()
brainmob.name = "[pick(list("PBU","HIU","SINA","ARMA","OSI"))]-[rand(100, 999)]"
brainmob.real_name = src.brainmob.name
/obj/item/device/mmi/digital/posibrain/attack_self(mob/user as mob)
if(brainmob && !brainmob.key && searching == 0)
/obj/item/device/mmi/digital/posibrain/attack_self(var/mob/user)
if(brainmob && !brainmob.key && !searching)
//Start the process of searching for a new user.
user << "\blue You carefully locate the manual activation switch and start the positronic brain's boot process."
user << "<span class='notice'>You carefully locate the manual activation switch and start the positronic brain's boot process.</span>"
icon_state = "posibrain-searching"
src.searching = 1
src.request_player()
searching = 1
var/datum/ghosttrap/G = get_ghost_trap("positronic brain")
G.request_player(brainmob, "A [src.name] has been booted by \the [user] in [get_area(user)]. ")
spawn(600) reset_search()
/obj/item/device/mmi/digital/posibrain/proc/request_player()
for(var/mob/dead/observer/O in player_list)
if(!O.MayRespawn())
continue
if(jobban_isbanned(O, "AI") && jobban_isbanned(O, "Cyborg"))
continue
if(O.client)
if(O.client.prefs.be_special & BE_AI)
question(O.client)
/obj/item/device/mmi/digital/posibrain/proc/question(var/client/C)
spawn(0)
if(!C) return
var/response = alert(C, "Someone is requesting a personality for a positronic brain. Would you like to play as one?", "Positronic brain request", "Yes", "No", "Never for this round")
/obj/item/device/mmi/digital/posibrain/attack_ghost(var/mob/dead/observer/user)
var/datum/ghosttrap/G = get_ghost_trap("positronic brain")
if(!G.assess_candidate(user))
return
var/response = alert(user, "Are you sure you want to play as a positronic brain?", "Positronic brain request", "Yes", "No")
if(response == "Yes")
response = alert(C, "Are you sure you want to play as a positronic brain?", "Positronic brain request", "Yes", "No")
if(!C || brainmob.key || 0 == searching) return //handle logouts that happen whilst the alert is waiting for a response, and responses issued after a brain has been located.
if(response == "Yes")
transfer_personality(C.mob)
else if (response == "Never for this round")
C.prefs.be_special ^= BE_AI
if(G.transfer_personality(user, brainmob))
var/turf/T = get_turf(src)
T.visible_message("<span class='notice'>\The [src] chimes quietly.</span>")
searching = 0
name = "positronic brain ([brainmob.name])"
icon_state = "posibrain-occupied"
return
/obj/item/device/mmi/digital/posibrain/transfer_identity(var/mob/living/carbon/H)
..()
@@ -55,33 +49,13 @@
icon_state = "posibrain-occupied"
return
/obj/item/device/mmi/digital/posibrain/proc/transfer_personality(var/mob/candidate)
announce_ghost_joinleave(candidate, 0, "They are occupying a positronic brain now.")
src.searching = 0
src.brainmob.mind = candidate.mind
src.brainmob.ckey = candidate.ckey
src.name = "positronic brain ([src.brainmob.name])"
src.brainmob << "<b>You are a positronic brain, brought into existence on [station_name()].</b>"
src.brainmob << "<b>As a synthetic intelligence, you answer to all crewmembers, as well as the AI.</b>"
src.brainmob << "<b>Remember, the purpose of your existence is to serve the crew and the station. Above all else, do no harm.</b>"
src.brainmob << "<b>Use say :b to speak to other artificial intelligences.</b>"
src.brainmob.mind.assigned_role = "Positronic Brain"
var/turf/T = get_turf_or_move(src.loc)
for (var/mob/M in viewers(T))
M.show_message("\blue The positronic brain chimes quietly.")
icon_state = "posibrain-occupied"
/obj/item/device/mmi/digital/posibrain/proc/reset_search() //We give the players sixty seconds to decide, then reset the timer.
if(src.brainmob && src.brainmob.key) return
src.searching = 0
/obj/item/device/mmi/digital/posibrain/proc/reset_search()
if(!searching || (src.brainmob && src.brainmob.key))
return
searching = 0
icon_state = "posibrain"
var/turf/T = get_turf_or_move(src.loc)
for (var/mob/M in viewers(T))
M.show_message("\blue The positronic brain buzzes quietly, and the golden lights fade away. Perhaps you could try again?")
var/turf/T = get_turf(src)
T.visible_message("<span class='notice'>\The [src] brain buzzes quietly, and the golden lights fade away. Perhaps you could try again?</span>")
/obj/item/device/mmi/digital/posibrain/examine(mob/user)
if(!..(user))
@@ -115,7 +89,3 @@
src.brainmob.emp_damage += rand(0,10)
..()
/obj/item/device/mmi/digital/posibrain/New()
..()
src.brainmob.name = "[pick(list("PBU","HIU","SINA","ARMA","OSI"))]-[rand(100, 999)]"
src.brainmob.real_name = src.brainmob.name

View File

@@ -1,15 +1,10 @@
/proc/spawn_diona_nymph_from_organ(var/obj/item/organ/organ)
if(!istype(organ))
return
//This is a terrible hack and I should be ashamed.
var/datum/seed/diona = plant_controller.seeds["diona"]
if(!diona)
qdel(src)
spawn(1) // So it has time to be thrown about by the gib() proc.
var/mob/living/carbon/alien/diona/D = new(get_turf(organ))
diona.request_player(D)
var/datum/ghosttrap/plant/P = get_ghost_trap("living plant")
P.request_player(D, "A diona nymph has split off from its gestalt. ")
qdel(organ)
/obj/item/organ/external/diona

View File

@@ -0,0 +1,5 @@
author: Zuhayr
delete-after: True
changes:
- rscadd: "Added a ghost requisition system for posibrains and living plants."
- rscadd: "Added attack_ghost() to hydro trays and posibrains to allow ghosts to enter them."