mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-24 21:48:39 +01:00
Adds a subtle ghost poll (#79105)
## About The Pull Request This makes a new ghost poll system which doesn't give TGUI popups - instead, users are prompted to follow the POI and one of the orbiters is chosen. The old system remains in place, so you can still prompt if you want to. This gives two things: 1. A deadchat notification:  2. A screen alert:  ## Why It's Good For The Game As stated in #76507, popups are pretty annoying. This is halfway between a screen alert with no time limit and an event with more important pings. This is better because: 1. Less popup fatigue 2. You can SEE how many you're competing with 4. DRY ## Changelog 🆑 add: Adds a subtle ghost poll. This pings in dead chat and gives a screen alert, but no TGUI popup. Orbit the point of interest to be selected for the role. refactor: A number of ghost spawns now feature this alert. Write an issue report if anything breaks. /🆑 --------- Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
This commit is contained in:
@@ -45,15 +45,26 @@
|
||||
/datum/brain_trauma/special/imaginary_friend/proc/make_friend()
|
||||
friend = new(get_turf(owner), owner)
|
||||
|
||||
/// Tries an orbit poll for the imaginary friend
|
||||
/datum/brain_trauma/special/imaginary_friend/proc/get_ghost()
|
||||
set waitfor = FALSE
|
||||
var/list/mob/dead/observer/candidates = poll_candidates_for_mob("Do you want to play as [owner.real_name]'s imaginary friend?", ROLE_PAI, null, 7.5 SECONDS, friend, POLL_IGNORE_IMAGINARYFRIEND)
|
||||
if(LAZYLEN(candidates))
|
||||
var/mob/dead/observer/C = pick(candidates)
|
||||
friend.key = C.key
|
||||
friend_initialized = TRUE
|
||||
else
|
||||
var/datum/callback/to_call = CALLBACK(src, PROC_REF(add_friend))
|
||||
owner.AddComponent(/datum/component/orbit_poll, \
|
||||
ignore_key = POLL_IGNORE_IMAGINARYFRIEND, \
|
||||
job_bans = ROLE_PAI, \
|
||||
title = "[owner.real_name]'s imaginary friend", \
|
||||
to_call = to_call, \
|
||||
)
|
||||
|
||||
/// Yay more friends!
|
||||
/datum/brain_trauma/special/imaginary_friend/proc/add_friend(mob/dead/observer/ghost)
|
||||
if(isnull(ghost))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
friend.key = ghost.key
|
||||
friend_initialized = TRUE
|
||||
friend.log_message("became [key_name(owner)]'s split personality.", LOG_GAME)
|
||||
message_admins("[ADMIN_LOOKUPFLW(friend)] became [ADMIN_LOOKUPFLW(owner)]'s split personality.")
|
||||
|
||||
/mob/camera/imaginary_friend
|
||||
name = "imaginary friend"
|
||||
|
||||
@@ -32,17 +32,26 @@
|
||||
var/datum/action/cooldown/spell/personality_commune/owner_spell = new(src)
|
||||
owner_spell.Grant(owner_backseat)
|
||||
|
||||
|
||||
/// Attempts to get a ghost to play the personality
|
||||
/datum/brain_trauma/severe/split_personality/proc/get_ghost()
|
||||
set waitfor = FALSE
|
||||
var/list/mob/dead/observer/candidates = poll_candidates_for_mob("Do you want to play as [owner.real_name]'s [poll_role]?", ROLE_PAI, null, 7.5 SECONDS, stranger_backseat, POLL_IGNORE_SPLITPERSONALITY)
|
||||
if(LAZYLEN(candidates))
|
||||
var/mob/dead/observer/C = pick(candidates)
|
||||
stranger_backseat.key = C.key
|
||||
stranger_backseat.log_message("became [key_name(owner)]'s split personality.", LOG_GAME)
|
||||
message_admins("[ADMIN_LOOKUPFLW(stranger_backseat)] became [ADMIN_LOOKUPFLW(owner)]'s split personality.")
|
||||
else
|
||||
var/datum/callback/to_call = CALLBACK(src, PROC_REF(schism))
|
||||
owner.AddComponent(/datum/component/orbit_poll, \
|
||||
ignore_key = POLL_IGNORE_SPLITPERSONALITY, \
|
||||
job_bans = ROLE_PAI, \
|
||||
title = "[owner.real_name]'s [poll_role]", \
|
||||
to_call = to_call, \
|
||||
)
|
||||
|
||||
/// Ghost poll has concluded
|
||||
/datum/brain_trauma/severe/split_personality/proc/schism(mob/dead/observer/ghost)
|
||||
if(isnull(ghost))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
stranger_backseat.key = ghost.key
|
||||
stranger_backseat.log_message("became [key_name(owner)]'s split personality.", LOG_GAME)
|
||||
message_admins("[ADMIN_LOOKUPFLW(stranger_backseat)] became [ADMIN_LOOKUPFLW(owner)]'s split personality.")
|
||||
|
||||
|
||||
/datum/brain_trauma/severe/split_personality/on_life(seconds_per_tick, times_fired)
|
||||
if(owner.stat == DEAD)
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* A replacement for the standard poll_ghost_candidate.
|
||||
* Use this to subtly ask players to join - it picks from orbiters.
|
||||
* Please use named arguments for this.
|
||||
*
|
||||
* @params ignore_key - Required so it doesn't spam
|
||||
* @params job_bans - You can insert a list or single items here.
|
||||
* @params cb - Invokes this proc and appends the poll winner as the last argument, mob/dead/observer/ghost
|
||||
* @params title - Optional. Useful if the role name does not match the parent.
|
||||
*
|
||||
* @usage
|
||||
* ```
|
||||
* var/datum/callback/cb = CALLBACK(src, PROC_REF(do_stuff), arg1, arg2)
|
||||
* AddComponent(/datum/component/orbit_poll, \
|
||||
* ignore_key = POLL_IGNORE_EXAMPLE, \
|
||||
* job_bans = ROLE_EXAMPLE or list(ROLE_EXAMPLE, ROLE_EXAMPLE2), \
|
||||
* title = "Use this if you want something other than the parent name", \
|
||||
* to_call = cb, \
|
||||
* )
|
||||
*/
|
||||
/datum/component/orbit_poll
|
||||
/// Prevent players with this ban from being selected
|
||||
var/list/job_bans = list()
|
||||
/// Title of the role to announce after it's done
|
||||
var/title
|
||||
/// Proc to invoke whenever the poll is complete
|
||||
var/datum/callback/to_call
|
||||
|
||||
/datum/component/orbit_poll/Initialize( \
|
||||
ignore_key, \
|
||||
list/job_bans, \
|
||||
datum/callback/to_call, \
|
||||
title, \
|
||||
header = "Ghost Poll", \
|
||||
custom_message, \
|
||||
timeout = 20 SECONDS \
|
||||
)
|
||||
. = ..()
|
||||
if (!isatom(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
var/atom/owner = parent
|
||||
|
||||
src.job_bans |= job_bans
|
||||
src.title = title || owner.name
|
||||
src.to_call = to_call
|
||||
|
||||
var/message = custom_message || "[capitalize(src.title)] is looking for volunteers"
|
||||
|
||||
notify_ghosts("[message]. An orbiter will be chosen in [DisplayTimeText(timeout)].\n", \
|
||||
action = NOTIFY_ORBIT, \
|
||||
enter_link = "<a href='?src=[REF(src)];ignore=[ignore_key]'>(Ignore)</a>", \
|
||||
flashwindow = FALSE, \
|
||||
header = "Volunteers requested", \
|
||||
ignore_key = ignore_key, \
|
||||
source = parent \
|
||||
)
|
||||
|
||||
addtimer(CALLBACK(src, PROC_REF(end_poll)), timeout, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_STOPPABLE|TIMER_DELETE_ME)
|
||||
|
||||
/datum/component/orbit_poll/Topic(href, list/href_list)
|
||||
if(!href_list["ignore"])
|
||||
return
|
||||
|
||||
var/mob/user = usr
|
||||
|
||||
var/ignore_key = href_list["ignore"]
|
||||
if(tgui_alert(user, "Ignore further [title] alerts?", "Ignore Alert", list("Yes", "No"), 20 SECONDS, TRUE) != "Yes")
|
||||
return
|
||||
|
||||
GLOB.poll_ignore[ignore_key] |= user.ckey
|
||||
|
||||
/// Concludes the poll, picking one of the orbiters
|
||||
/datum/component/orbit_poll/proc/end_poll()
|
||||
if(QDELETED(parent))
|
||||
return
|
||||
|
||||
var/list/candidates = list()
|
||||
var/atom/owner = parent
|
||||
|
||||
var/datum/component/orbiter/orbiter_comp = owner.GetComponent(/datum/component/orbiter)
|
||||
if(isnull(orbiter_comp))
|
||||
phone_home()
|
||||
return
|
||||
|
||||
for(var/mob/dead/observer/ghost as anything in orbiter_comp.orbiter_list)
|
||||
if(QDELETED(ghost) || isnull(ghost.client))
|
||||
continue
|
||||
if(is_banned_from(ghost.ckey, job_bans))
|
||||
continue
|
||||
|
||||
candidates += ghost
|
||||
|
||||
if(!length(candidates))
|
||||
phone_home()
|
||||
return
|
||||
|
||||
var/mob/dead/observer/chosen = pick(candidates)
|
||||
|
||||
if(chosen)
|
||||
deadchat_broadcast("[key_name(chosen, include_name = FALSE)] was selected for the role ([title]).", "Ghost Poll: ", parent)
|
||||
|
||||
phone_home(chosen)
|
||||
|
||||
/// Make sure to call your parents my dude
|
||||
/datum/component/orbit_poll/proc/phone_home(mob/dead/observer/chosen)
|
||||
to_call.Invoke(chosen)
|
||||
qdel(src)
|
||||
@@ -57,21 +57,30 @@
|
||||
attempting_awakening = TRUE
|
||||
to_chat(awakener, span_notice("You attempt to wake the spirit of [parent]..."))
|
||||
|
||||
var/mob/dead/observer/candidates = poll_ghost_candidates("Do you want to play as the spirit of [awakener.real_name]'s blade?", ROLE_PAI, FALSE, 100, POLL_IGNORE_POSSESSED_BLADE)
|
||||
if(!LAZYLEN(candidates))
|
||||
to_chat(awakener, span_warning("[parent] is dormant. Maybe you can try again later."))
|
||||
attempting_awakening = FALSE
|
||||
return
|
||||
var/datum/callback/to_call = CALLBACK(src, PROC_REF(affix_spirit), awakener)
|
||||
parent.AddComponent(/datum/component/orbit_poll, \
|
||||
ignore_key = POLL_IGNORE_POSSESSED_BLADE, \
|
||||
job_bans = ROLE_PAI, \
|
||||
to_call = to_call, \
|
||||
title = "Spirit of [awakener.real_name]'s blade", \
|
||||
)
|
||||
|
||||
//Immediately unregister to prevent making a new spirit
|
||||
UnregisterSignal(parent, COMSIG_ITEM_ATTACK_SELF)
|
||||
|
||||
var/mob/dead/observer/chosen_spirit = pick(candidates)
|
||||
if(QDELETED(parent)) //if the thing that we're conjuring a spirit in has been destroyed, don't create a spirit
|
||||
to_chat(chosen_spirit, span_userdanger("The new vessel for your spirit has been destroyed! You remain an unbound ghost."))
|
||||
/// On conclusion of the ghost poll
|
||||
/datum/component/spirit_holding/proc/affix_spirit(mob/awakener, mob/dead/observer/ghost)
|
||||
if(isnull(ghost))
|
||||
to_chat(awakener, span_warning("[parent] is dormant. Maybe you can try again later."))
|
||||
attempting_awakening = FALSE
|
||||
return
|
||||
|
||||
if(QDELETED(parent)) //if the thing that we're conjuring a spirit in has been destroyed, don't create a spirit
|
||||
to_chat(ghost, span_userdanger("The new vessel for your spirit has been destroyed! You remain an unbound ghost."))
|
||||
return
|
||||
|
||||
bound_spirit = new(parent)
|
||||
bound_spirit.ckey = chosen_spirit.ckey
|
||||
bound_spirit.ckey = ghost.ckey
|
||||
bound_spirit.fully_replace_character_name(null, "The spirit of [parent]")
|
||||
bound_spirit.status_flags |= GODMODE
|
||||
bound_spirit.copy_languages(awakener, LANGUAGE_MASTER) //Make sure the sword can understand and communicate with the awakener.
|
||||
|
||||
@@ -28,26 +28,29 @@
|
||||
finding_candidate = FALSE
|
||||
return TRUE
|
||||
|
||||
/// Sets up the ghost poll
|
||||
/obj/item/aicard/syndie/loaded/proc/procure_ai(mob/user)
|
||||
var/datum/antagonist/nukeop/op_datum = user.mind?.has_antag_datum(/datum/antagonist/nukeop,TRUE)
|
||||
if(isnull(op_datum))
|
||||
balloon_alert(user, "invalid access!")
|
||||
return
|
||||
var/list/nuke_candidates = poll_ghost_candidates(
|
||||
question = "Do you want to play as a nuclear operative MODsuit AI?",
|
||||
jobban_type = ROLE_OPERATIVE,
|
||||
be_special_flag = ROLE_OPERATIVE_MIDROUND,
|
||||
poll_time = 15 SECONDS,
|
||||
ignore_category = POLL_IGNORE_SYNDICATE,
|
||||
|
||||
var/datum/callback/to_call = CALLBACK(src, PROC_REF(on_poll_concluded), user, op_datum)
|
||||
AddComponent(/datum/component/orbit_poll, \
|
||||
ignore_key = POLL_IGNORE_SYNDICATE, \
|
||||
job_bans = ROLE_OPERATIVE, \
|
||||
to_call = to_call, \
|
||||
title = "Nuclear Operative Modsuit AI" \
|
||||
)
|
||||
if(QDELETED(src))
|
||||
return
|
||||
if(!LAZYLEN(nuke_candidates))
|
||||
|
||||
/// Poll has concluded with a ghost, create the AI
|
||||
/obj/item/aicard/syndie/loaded/proc/on_poll_concluded(mob/user, datum/antagonist/nukeop/op_datum, mob/dead/observer/ghost)
|
||||
if(isnull(ghost))
|
||||
to_chat(user, span_warning("Unable to connect to S.E.L.F. dispatch. Please wait and try again later or use the intelliCard on your uplink to get your points refunded."))
|
||||
return
|
||||
|
||||
// pick ghost, create AI and transfer
|
||||
var/mob/dead/observer/ghos = pick(nuke_candidates)
|
||||
var/mob/living/silicon/ai/weak_syndie/new_ai = new /mob/living/silicon/ai/weak_syndie(get_turf(src), new /datum/ai_laws/syndicate_override, ghos)
|
||||
var/mob/living/silicon/ai/weak_syndie/new_ai = new /mob/living/silicon/ai/weak_syndie(get_turf(src), new /datum/ai_laws/syndicate_override, ghost)
|
||||
// create and apply syndie datum
|
||||
var/datum/antagonist/nukeop/nuke_datum = new()
|
||||
nuke_datum.send_to_spawnpoint = FALSE
|
||||
|
||||
@@ -189,14 +189,22 @@
|
||||
to_chat(src, span_notice("You attempt to produce a blobbernaut."))
|
||||
pick_blobbernaut_candidate(factory)
|
||||
|
||||
/** Polls ghosts to get a blobbernaut candidate. */
|
||||
/// Polls ghosts to get a blobbernaut candidate.
|
||||
/mob/camera/blob/proc/pick_blobbernaut_candidate(obj/structure/blob/special/factory/factory)
|
||||
if(!factory)
|
||||
if(isnull(factory))
|
||||
return
|
||||
|
||||
var/list/mob/dead/observer/candidates = poll_ghost_candidates("Do you want to play as a [blobstrain.name] blobbernaut?", ROLE_BLOB, ROLE_BLOB, 50)
|
||||
var/datum/callback/to_call = CALLBACK(src, PROC_REF(on_poll_concluded), factory)
|
||||
factory.AddComponent(/datum/component/orbit_poll, \
|
||||
ignore_key = POLL_IGNORE_BLOB, \
|
||||
job_bans = ROLE_BLOB, \
|
||||
to_call = to_call, \
|
||||
title = "Blobbernaut", \
|
||||
)
|
||||
|
||||
if(!length(candidates))
|
||||
/// Called when the ghost poll concludes
|
||||
/mob/camera/blob/proc/on_poll_concluded(obj/structure/blob/special/factory/factory, mob/dead/observer/ghost)
|
||||
if(isnull(ghost))
|
||||
to_chat(src, span_warning("You could not conjure a sentience for your blobbernaut. Your points have been refunded. Try again later."))
|
||||
add_points(BLOBMOB_BLOBBERNAUT_RESOURCE_COST)
|
||||
factory.assign_blobbernaut(null)
|
||||
@@ -205,8 +213,7 @@
|
||||
var/mob/living/basic/blob_minion/blobbernaut/minion/blobber = new(get_turf(factory))
|
||||
assume_direct_control(blobber)
|
||||
factory.assign_blobbernaut(blobber)
|
||||
var/mob/dead/observer/player = pick(candidates)
|
||||
blobber.assign_key(player.key, blobstrain)
|
||||
blobber.assign_key(ghost.key, blobstrain)
|
||||
RegisterSignal(blobber, COMSIG_HOSTILE_POST_ATTACKINGTARGET, PROC_REF(on_blobbernaut_attacked))
|
||||
|
||||
/// When one of our boys attacked something, we sometimes want to perform extra effects
|
||||
|
||||
@@ -318,7 +318,15 @@
|
||||
return TRUE
|
||||
|
||||
to_chat(user, "[span_userdanger("Capture failed!")]: The soul has already fled its mortal frame. You attempt to bring it back...")
|
||||
INVOKE_ASYNC(src, PROC_REF(get_ghost_to_replace_shade), victim, user)
|
||||
|
||||
var/datum/callback/to_call = CALLBACK(src, PROC_REF(on_poll_concluded), user, victim)
|
||||
AddComponent(/datum/component/orbit_poll, \
|
||||
ignore_key = POLL_IGNORE_SHADE, \
|
||||
job_bans = ROLE_CULTIST, \
|
||||
to_call = to_call, \
|
||||
title = "A shade" \
|
||||
)
|
||||
|
||||
return TRUE //it'll probably get someone ;)
|
||||
|
||||
///captures a shade that was previously released from a soulstone.
|
||||
@@ -430,33 +438,19 @@
|
||||
shade_datum = shade.mind.add_antag_datum(/datum/antagonist/shade_minion)
|
||||
shade_datum.update_master(user.real_name)
|
||||
|
||||
/**
|
||||
* Gets a ghost from dead chat to replace a missing player when a shade is created.
|
||||
*
|
||||
* Gets ran if a soulstone is used on a body that has no client to take over the shade.
|
||||
*
|
||||
* victim - the body that's being shaded
|
||||
* user - the mob shading the body
|
||||
*
|
||||
* Returns FALSE if no ghosts are available or the replacement fails.
|
||||
* Returns TRUE otherwise.
|
||||
*/
|
||||
/obj/item/soulstone/proc/get_ghost_to_replace_shade(mob/living/carbon/victim, mob/user)
|
||||
var/mob/dead/observer/chosen_ghost
|
||||
var/list/consenting_candidates = poll_ghost_candidates("Would you like to play as a Shade?", "Cultist", ROLE_CULTIST, 5 SECONDS, POLL_IGNORE_SHADE)
|
||||
if(length(consenting_candidates))
|
||||
chosen_ghost = pick(consenting_candidates)
|
||||
|
||||
if(!victim || user.incapacitated() || !user.is_holding(src) || !user.CanReach(victim, src))
|
||||
/// Called when a ghost is chosen to become a shade.
|
||||
/obj/item/soulstone/proc/on_poll_concluded(mob/living/master, mob/living/victim, mob/dead/observer/ghost)
|
||||
if(isnull(victim) || master.incapacitated() || !master.is_holding(src) || !master.CanReach(victim, src))
|
||||
return FALSE
|
||||
if(!chosen_ghost || !chosen_ghost.client)
|
||||
to_chat(user, span_danger("There were no spirits willing to become a shade."))
|
||||
if(isnull(ghost?.client))
|
||||
to_chat(master, span_danger("There were no spirits willing to become a shade."))
|
||||
return FALSE
|
||||
if(contents.len) //If they used the soulstone on someone else in the meantime
|
||||
if(length(contents)) //If they used the soulstone on someone else in the meantime
|
||||
return FALSE
|
||||
to_chat(user, "[span_info("<b>Capture successful!</b>:")] A spirit has entered [src], \
|
||||
to_chat(master, "[span_info("<b>Capture successful!</b>:")] A spirit has entered [src], \
|
||||
taking upon the identity of [victim].")
|
||||
init_shade(victim, user, shade_controller = chosen_ghost)
|
||||
init_shade(victim, master, shade_controller = ghost)
|
||||
|
||||
return TRUE
|
||||
|
||||
/proc/make_new_construct_from_class(construct_class, theme, mob/target, mob/creator, cultoverride, loc_override)
|
||||
|
||||
@@ -423,19 +423,31 @@
|
||||
using = TRUE
|
||||
balloon_alert(user, "you hold the scythe up...")
|
||||
ADD_TRAIT(src, TRAIT_NODROP, type)
|
||||
var/list/mob/dead/observer/candidates = poll_ghost_candidates("Do you want to play as [user.real_name]'s soulscythe?", ROLE_PAI, FALSE, 100, POLL_IGNORE_POSSESSED_BLADE)
|
||||
if(LAZYLEN(candidates))
|
||||
var/mob/dead/observer/picked_ghost = pick(candidates)
|
||||
soul.ckey = picked_ghost.ckey
|
||||
soul.copy_languages(user, LANGUAGE_MASTER) //Make sure the sword can understand and communicate with the user.
|
||||
soul.faction = list("[REF(user)]")
|
||||
balloon_alert(user, "the scythe glows up")
|
||||
add_overlay("soulscythe_gem")
|
||||
density = TRUE
|
||||
if(!ismob(loc))
|
||||
reset_spin()
|
||||
else
|
||||
balloon_alert(user, "the scythe is dormant!")
|
||||
|
||||
var/datum/callback/to_call = CALLBACK(src, PROC_REF(on_poll_concluded), user)
|
||||
AddComponent(/datum/component/orbit_poll, \
|
||||
ignore_key = POLL_IGNORE_POSSESSED_BLADE, \
|
||||
job_bans = ROLE_PAI, \
|
||||
to_call = to_call, \
|
||||
)
|
||||
|
||||
/// Ghost poll has concluded and a candidate has been chosen.
|
||||
/obj/item/soulscythe/proc/on_poll_concluded(mob/living/master, mob/dead/observer/ghost)
|
||||
if(isnull(ghost))
|
||||
balloon_alert(master, "the scythe is dormant!")
|
||||
REMOVE_TRAIT(src, TRAIT_NODROP, type)
|
||||
using = FALSE
|
||||
return
|
||||
|
||||
soul.ckey = ghost.ckey
|
||||
soul.copy_languages(master, LANGUAGE_MASTER) //Make sure the sword can understand and communicate with the master.
|
||||
soul.faction = list("[REF(master)]")
|
||||
balloon_alert(master, "the scythe glows")
|
||||
add_overlay("soulscythe_gem")
|
||||
density = TRUE
|
||||
if(!ismob(loc))
|
||||
reset_spin()
|
||||
|
||||
REMOVE_TRAIT(src, TRAIT_NODROP, type)
|
||||
using = FALSE
|
||||
|
||||
|
||||
@@ -84,26 +84,33 @@
|
||||
return
|
||||
attempt_grow()
|
||||
|
||||
///Attempt to burst an alien outside of the host, getting a ghost to play as the xeno.
|
||||
/// Attempt to burst an alien outside of the host, getting a ghost to play as the xeno.
|
||||
/obj/item/organ/internal/body_egg/alien_embryo/proc/attempt_grow(gib_on_success = TRUE)
|
||||
if(!owner || bursting)
|
||||
if(QDELETED(owner) || bursting)
|
||||
return
|
||||
|
||||
bursting = TRUE
|
||||
|
||||
var/list/candidates = poll_ghost_candidates("Do you want to play as an alien larva that will burst out of [owner.real_name]?", ROLE_ALIEN, ROLE_ALIEN, 100, POLL_IGNORE_ALIEN_LARVA)
|
||||
var/datum/callback/to_call = CALLBACK(src, PROC_REF(on_poll_concluded), gib_on_success)
|
||||
owner.AddComponent(/datum/component/orbit_poll, \
|
||||
ignore_key = POLL_IGNORE_ALIEN_LARVA, \
|
||||
job_bans = ROLE_ALIEN, \
|
||||
to_call = to_call, \
|
||||
custom_message = "An alien is bursting out of [owner.real_name]", \
|
||||
title = "alien larva" \
|
||||
)
|
||||
|
||||
if(QDELETED(src) || QDELETED(owner))
|
||||
/// Poll has concluded with a suitor
|
||||
/obj/item/organ/internal/body_egg/alien_embryo/proc/on_poll_concluded(gib_on_success, mob/dead/observer/ghost)
|
||||
if(QDELETED(owner))
|
||||
return
|
||||
|
||||
if(!candidates.len || !owner)
|
||||
if(isnull(ghost))
|
||||
bursting = FALSE
|
||||
stage = 5 // If no ghosts sign up for the Larva, let's regress our growth by one minute, we will try again!
|
||||
addtimer(CALLBACK(src, PROC_REF(advance_embryo_stage)), growth_time)
|
||||
return
|
||||
|
||||
var/mob/dead/observer/ghost = pick(candidates)
|
||||
|
||||
var/mutable_appearance/overlay = mutable_appearance('icons/mob/nonhuman-player/alien.dmi', "burst_lie")
|
||||
owner.add_overlay(overlay)
|
||||
|
||||
|
||||
@@ -705,19 +705,28 @@
|
||||
balloon_alert(user, "offering...")
|
||||
being_used = TRUE
|
||||
|
||||
var/list/candidates = poll_candidates_for_mob("Do you want to play as [dumb_mob.name]?", ROLE_SENTIENCE, ROLE_SENTIENCE, 5 SECONDS, dumb_mob, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm
|
||||
if(!LAZYLEN(candidates))
|
||||
var/datum/callback/to_call = CALLBACK(src, PROC_REF(on_poll_concluded), user, dumb_mob)
|
||||
dumb_mob.AddComponent(/datum/component/orbit_poll, \
|
||||
ignore_key = POLL_IGNORE_SENTIENCE_POTION, \
|
||||
job_bans = ROLE_SENTIENCE, \
|
||||
to_call = to_call, \
|
||||
)
|
||||
|
||||
/// Assign the chosen ghost to the mob
|
||||
/obj/item/slimepotion/slime/sentience/proc/on_poll_concluded(mob/user, mob/living/dumb_mob, mob/dead/observer/ghost)
|
||||
if(isnull(ghost))
|
||||
balloon_alert(user, "try again later!")
|
||||
being_used = FALSE
|
||||
return ..()
|
||||
return
|
||||
|
||||
var/mob/dead/observer/C = pick(candidates)
|
||||
dumb_mob.key = C.key
|
||||
dumb_mob.key = ghost.key
|
||||
dumb_mob.mind.enslave_mind_to_creator(user)
|
||||
SEND_SIGNAL(dumb_mob, COMSIG_SIMPLEMOB_SENTIENCEPOTION, user)
|
||||
|
||||
if(isanimal(dumb_mob))
|
||||
var/mob/living/simple_animal/smart_animal = dumb_mob
|
||||
smart_animal.sentience_act()
|
||||
|
||||
dumb_mob.mind.add_antag_datum(/datum/antagonist/sentient_creature)
|
||||
balloon_alert(user, "success")
|
||||
after_success(user, dumb_mob)
|
||||
|
||||
@@ -1058,6 +1058,7 @@
|
||||
#include "code\datums\components\omen.dm"
|
||||
#include "code\datums\components\on_hit_effect.dm"
|
||||
#include "code\datums\components\onwear_mood.dm"
|
||||
#include "code\datums\components\orbit_poll.dm"
|
||||
#include "code\datums\components\orbiter.dm"
|
||||
#include "code\datums\components\overlay_lighting.dm"
|
||||
#include "code\datums\components\palette.dm"
|
||||
|
||||
Reference in New Issue
Block a user