diff --git a/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm b/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm index 966d009c9b4..5788ded0be5 100644 --- a/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm +++ b/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm @@ -1003,78 +1003,3 @@ species.has_glowing_eyes = !species.has_glowing_eyes update_eyes() to_chat(src, "Your eyes [species.has_glowing_eyes ? "are now" : "are no longer"] glowing.") - -//Welcome to the adapted borer code. -/mob/living/proc/dominate_predator() - set category = "Abilities" - set name = "Dominate Predator" - set desc = "Connect to and dominate the brain of your predator." - - if(isbelly(loc)) - to_chat(src, "You are not inside a predator body.") - return - - var/mob/living/pred = loc.loc - - if(src.stat) - to_chat(src, "You cannot do that in your current state.") - return - - if(!pred.ckey) - to_chat(src, "\The [src] isn't able to be dominated.") - return - - if(tgui_alert(src, "You are attempting to take over [pred], are you sure? Ensure that their preferences align with this kind of play.", "Take Over Predator",list("No","Yes")) != "Yes") - return - to_chat(src, "You attempt to exert your control over \the [pred]...") - log_admin("[key_name_admin(src)] attempted to take over [pred].") - if(tgui_alert(M, "\The [src] has elected to attempt to take control of you. Is this something you will allow to happen?", "Allow Prey Domination",list("No","Yes")) != "Yes") - to_chat(src, "\The [pred] declined your request for control.") - return - if(tgui_alert(M, "Are you sure? If you should decide to revoke this, you will have the ability to do so in your 'Abilities' tab.", "Allow Prey Domination",list("No","Yes")) != "Yes") - return - to_chat(pred, "You can feel the will of another overwriting your own, control of your body being sapped away from you...") - to_chat(src, "You can feel the will of your host diminishing as you exert your will over them!") - if(!do_after(src, 10 SECONDS, exclusive = TRUE) || !isbelly(loc) || loc.loc != pred) - to_chat(src, "You are not inside \the [pred]'s body, your attempt to link up with them has been interrupted.") - to_chat(pred, "The dominant sensation fades away...") - return - - to_chat(src, "You plunge your conciousness into \the [pred], assuming control over their very body, leaving your own behind within \the [pred]'s [loc].") - to_chat(pred, "You feel your body move on its own, as you are pushed to the background, and an alien consciousness displaces yours.") - - var/mob/living/dominated_brain/pred_brain = new mob/living/dominated_brain(src, src, pred) - // pred -> brain - var/pred_id = pred.computer_id - var/pred_ip = pred.lastKnownIP - pred.computer_id = null - pred.lastKnownIP = null - - pred_brain.ckey = pred.ckey - - pred_brain.name = pred.name - - if(!pred_brain.computer_id) - pred_brain.computer_id = pred_id - - if(!pred_brain.lastKnownIP) - pred_brain.lastKnownIP = pred_ip - - // prey -> pred - var/prey_id = src.computer_id - var/prey_ip= src.lastKnownIP - src.computer_id = null - src.lastKnownIP = null - - pred.ckey = src.ckey - - if(!pred.computer_id) - pred.computer_id = s2h_id - - if(!pred.lastKnownIP) - pred.lastKnownIP = s2h_ip - - controlling = 1 - - pred.verbs += /mob/living/proc/release_predator - pred.verbs += /mob/living/proc/punish_host diff --git a/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm b/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm index 67067c24a28..3c8157a8a7a 100644 --- a/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm +++ b/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm @@ -481,14 +481,12 @@ ..(S,H) H.update_transform() -/////WOWIE///// - /datum/trait/neutral/dominate_predator name = "Dominate Predator" - desc = "Makes you able to gain nutrition from draining prey in your grasp." + desc = "Allows you to attempt to take control of a predator while inside of their belly." cost = 0 custom_only = FALSE /datum/trait/neutral/dominate_predator/apply(var/datum/species/S,var/mob/living/carbon/human/H) ..(S,H) - H.verbs |= /mob/living/carbon/human/proc/dominate_predator \ No newline at end of file + H.verbs |= /mob/living/proc/dominate_predator \ No newline at end of file diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/dominated_brain.dm b/code/modules/mob/living/simple_mob/subtypes/vore/dominated_brain.dm index bc73a17137a..7684ad35caf 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/dominated_brain.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/dominated_brain.dm @@ -1,54 +1,64 @@ ///// A mob that gets used when prey dominate predators. Will automatically delete itself if it's not inside a mob. /mob/living/dominated_brain - name = "dominated brain" - desc = "Someone who has taken a back seat within their own body." - icon = 'icons/obj/surgery.dmi' + name = "dominated brain" + desc = "Someone who has taken a back seat within their own body." + icon = 'icons/obj/surgery.dmi' icon_state = "brain1" - var/original_body //The body this brain originally belongs to - var/dominating_body //The body that dominated this brain - var/original_ckey - var/dominating_ckey + var/mob/living/prey_body //The body of the person who dominated the brain + var/prey_ckey //The ckey of the person who dominated the brain + var/prey_name //In case the body is missing. ;3c + var/mob/living/pred_body //The body of the person who was dominated + var/pred_ckey //The ckey of the person who was dominated -/mob/living/dominated_brain/New(loc, var/mob/living/prey, var/mob/living/pred) - . = ..() - name = pred.name - original_body = pred - dominating_body = prey - original_ckey = pred.ckey - dominating_ckey = prey.ckey +/mob/living/dominated_brain/New(loc, var/mob/living/pred, preyname, var/mob/living/prey) + . = ..() + name = pred.name + prey_name = preyname + if(prey) + prey_body = prey + pred_body = pred /mob/living/dominated_brain/Initialize() if(!isliving(loc)) - qdel(src) - return - . = ..() - RegisterSignal(original_body, COMSIG_PARENT_QDELETING, .proc/ob_was_deleted, TRUE) - RegisterSignal(dominating_body, COMSIG_PARENT_QDELETING, .proc/db_was_deleted, TRUE) + qdel(src) + return + . = ..() + lets_register_our_signals() + verbs += /mob/living/dominated_brain/proc/resist_control -/mob/living/dominated_brain/proc/ob_was_deleted() - if(original_body) - UnregisterSignal(original_body, COMSIG_PARENT_QDELETING) - original_body = null -/mob/living/dominated_brain/proc/db_was_deleted() - if(dominating_body) - UnregisterSignal(dominating_body, COMSIG_PARENT_QDELETING) - dominating_body = null +/mob/living/dominated_brain/proc/lets_register_our_signals() + if(prey_body) + RegisterSignal(prey_body, COMSIG_PARENT_QDELETING, .proc/prey_was_deleted, TRUE) + RegisterSignal(pred_body, COMSIG_PARENT_QDELETING, .proc/pred_was_deleted, TRUE) + +/mob/living/dominated_brain/proc/lets_unregister_our_signals() + prey_was_deleted() + pred_was_deleted() + +/mob/living/dominated_brain/proc/prey_was_deleted() + if(prey_body) + UnregisterSignal(prey_body, COMSIG_PARENT_QDELETING) + prey_body = null + +/mob/living/dominated_brain/proc/pred_was_deleted() + if(pred_body) + UnregisterSignal(pred_body, COMSIG_PARENT_QDELETING) + pred_body = null /mob/living/dominated_brain/Destroy() - ob_was_deleted() - db_was_deleted() - . = ..() + lets_unregister_our_signals() + . = ..() -/mob/living/captive_brain/say(var/message, var/datum/language/speaking = null, var/whispering = 0) +/mob/living/dominated_brain/say(var/message, var/datum/language/speaking = null, var/whispering = 0) if (src.client) if(client.prefs.muted & MUTE_IC) to_chat(src, "You cannot speak in IC (muted).") return - if(loc = original_body) + if(loc == pred_body) message = sanitize(message) if (!message) @@ -57,9 +67,12 @@ if (stat == 2) return say_dead(message) - var/mob/living/simple_mob/animal/borer/B = src.loc - to_chat(src, "You whisper silently, \"[message]\"") - to_chat(B.host, "The captive mind of [src] whispers, \"[message]\"") + to_chat(src, "You think, \"[message]\"") + to_chat(pred_body, "The captive mind of \the [src] thinks, \"[message]\"") + for(var/I in pred_body.contents) + if(istype(I, /mob/living/dominated_brain) && I != src) + var/mob/living/dominated_brain/db + to_chat(db, "The captive mind of \the [src] thinks, \"[message]\"") for (var/mob/M in player_list) if (istype(M, /mob/new_player)) @@ -67,45 +80,352 @@ else if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears)) to_chat(M, "The captive mind of [src] whispers, \"[message]\"") -/mob/living/captive_brain/me_verb(message as text) +/mob/living/dominated_brain/me_verb(message as text) if (src.client) if(client.prefs.muted & MUTE_IC) - to_chat(src, "You cannot speak in IC (muted).") + to_chat(src, "You cannot speak in IC (muted).") return - to_chat(src, "You cannot emote as a captive mind.") + if(loc == pred_body) + + message = sanitize(message) + if (!message) + return + log_emote(message,src) + if (stat == 2) + return say_dead(message) + + to_chat(src, "\The [src] [message]") + to_chat(pred_body, "\The [src] [message]") + for(var/I in pred_body.contents) + if(istype(I, /mob/living/dominated_brain) && I != src) + var/mob/living/dominated_brain/db + to_chat(db, "\The [src] [message]") + + for (var/mob/M in player_list) + if (istype(M, /mob/new_player)) + continue + else if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears)) + to_chat(M, "\The [src] [message]") return -/mob/living/captive_brain/emote(var/message) +/mob/living/dominated_brain/emote(var/message) if (src.client) if(client.prefs.muted & MUTE_IC) - to_chat(src, "You cannot speak in IC (muted).") + to_chat(src, "You cannot speak in IC (muted).") return - to_chat(src, "You cannot emote as a captive mind.") + if(loc == pred_body) + + message = sanitize(message) + if (!message) + return + log_emote(message,src) + if (stat == 2) + return say_dead(message) + + to_chat(src, "\The [src] [message]") + to_chat(pred_body, "\The [src] [message]") + for(var/I in pred_body.contents) + if(istype(I, /mob/living/dominated_brain) && I != src) + var/mob/living/dominated_brain/db + to_chat(db, "\The [src] [message]") + + for (var/mob/M in player_list) + if (istype(M, /mob/new_player)) + continue + else if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears)) + to_chat(M, "\The [src] [message]") return -/mob/living/captive_brain/process_resist() +/mob/living/dominated_brain/process_resist() //Resisting control by an alien mind. - if(istype(src.loc, /mob/living/simple_mob/animal/borer)) - var/mob/living/simple_mob/animal/borer/B = src.loc - var/mob/living/captive_brain/H = src - - to_chat(H, "You begin doggedly resisting the parasite's control (this will take approximately sixty seconds).") - to_chat(B.host, "You feel the captive mind of [src] begin to resist your control.") - - spawn(rand(200,250)+B.host.brainloss) - if(!B || !B.controlling) return - - B.host.adjustBrainLoss(rand(0.1,0.5)) - to_chat(H, "With an immense exertion of will, you regain control of your body!") - to_chat(B.host, "You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you.") - B.detatch() - verbs -= /mob/living/carbon/proc/release_control - verbs -= /mob/living/carbon/proc/punish_host - verbs -= /mob/living/carbon/proc/spawn_larvae - + if(pred_body.ckey == pred_ckey) + dominate_predator() + return + if(tgui_alert(src, "Do you want to wrest control over your body back from \the [prey_name]?", "Regain Control",list("No","Yes")) != "Yes") return + to_chat(src, "You begin to resist \the [prey_name]'s control!!!") + to_chat(pred_body, "You feel the captive mind of [src] begin to resist your control.") + + if(!do_after(src, 10 SECONDS, exclusive = TRUE) || !isbelly(loc) || loc.loc != pred_body) + to_chat(src, "Your attempt to regain control has been interrupted...") + to_chat(pred_body, "The dominant sensation fades away...") + return + restore_control() ..() +/mob/living/dominated_brain/proc/restore_control(ask = TRUE) + + if(ask && disconnect_time || client && ((client.inactivity / 10) / 60 > 10)) + if(tgui_alert(src, "Your predator's mind does not seem to be active presently. Releasing control in this state may leave you stuck in whatever state you find yourself in. Are you sure?", "Release Control",list("No","Yes")) != "Yes") + return + var/pred_id = src.computer_id + var/pred_ip = src.lastKnownIP + var/prey_id = pred_body.computer_id + var/prey_ip = pred_body.lastKnownIP + var/mob/living/prey_goes_here + + if(prey_body && prey_body.loc.loc == pred_body) //The prey body exists and is here, let's handle the prey! + + prey_goes_here = prey_body + src.computer_id = null + src.lastKnownIP = null + + else if(prey_body) //It exists, but it's not here, let's spawn them a temporary home. + var/mob/living/dominated_brain/ndb = new /mob/living/dominated_brain(pred_body, pred_body, prey_name, prey_body) + ndb.prey_ckey = src.prey_ckey + ndb.pred_ckey = src.pred_ckey + ndb.handle_langs() + + prey_goes_here = ndb + + else //The prey body does not exist, let's put them in the back seat instead! + var/mob/living/dominated_brain/ndb = new /mob/living/dominated_brain(pred_body, pred_body, prey_name) + ndb.prey_ckey = src.prey_ckey + ndb.pred_ckey = src.pred_ckey + ndb.handle_langs() + + prey_goes_here = ndb + + /////////////////// + if(!prey_goes_here.computer_id) + prey_goes_here.computer_id = prey_id + + if(!prey_goes_here.lastKnownIP) + prey_goes_here.lastKnownIP = prey_ip + + + // Handle Pred + pred_body.verbs -= /mob/living/proc/release_predator + pred_body.verbs -= /mob/living/proc/psay + pred_body.verbs -= /mob/living/proc/pme + + pred_body.computer_id = null + pred_body.lastKnownIP = null + + + if(!pred_body.computer_id) + pred_body.computer_id = pred_id + + if(!pred_body.lastKnownIP) + pred_body.lastKnownIP = pred_ip + + //Now actually put the people in the mobs + log_and_message_admins("I am going to try to set [prey_goes_here] ckey to [prey_ckey] and [pred_body] ckey to [pred_ckey]") + prey_goes_here.ckey = src.prey_ckey + pred_body.ckey = src.pred_ckey + log_and_message_admins("I set [prey_goes_here] ckey to [prey_goes_here.ckey] and [pred_body] ckey to [pred_body.ckey]") + log_and_message_admins("I'n deleting [src]. They have [ckey] for a ckey") + qdel(src) + +/mob/living/dominated_brain/proc/handle_langs() + var/list/addlangs = list() + var/list/thinglist = list() + thinglist += pred_body + for(var/i in loc) + if(istype(i,/mob/living/dominated_brain)) + thinglist += i + for(var/mob/living/p in thinglist) + for(var/L in p.languages) + if(L in p.temp_languages) + p.languages -= L + p.temp_languages -= L + else + addlangs += L + for(var/mob/living/p in thinglist) + for(var/L in addlangs) + if(L in p.languages) + continue + else + p.temp_languages += L + p.languages += L + +//Welcome to the adapted borer code. +/mob/living/proc/dominate_predator() + set category = "Abilities" + set name = "Dominate Predator" + set desc = "Connect to and dominate the brain of your predator." + + var/mob/living/pred + + if(isbelly(src.loc)) + pred = loc.loc + else if(isliving(src.loc)) + pred = loc + else + to_chat(src, "You are not inside anyone.") + return + + if(src.stat == DEAD) + to_chat(src, "You cannot do that in your current state.") + return + + if(!pred.ckey) + to_chat(src, "\The [pred] isn't able to be dominated.") + return + + for(var/mob/living/dominated_brain/L in pred.contents) + if(istype(L, /mob/living/dominated_brain)) + if(L.pred_ckey != pred.ckey) + to_chat(src, "\The [pred] is already dominated, and cannot be controlled at this time.") + return + + if(tgui_alert(src, "You are attempting to take over [pred], are you sure? Ensure that their preferences align with this kind of play.", "Take Over Predator",list("No","Yes")) != "Yes") + return + to_chat(src, "You attempt to exert your control over \the [pred]...") + log_admin("[key_name_admin(src)] attempted to take over [pred].") + if(tgui_alert(pred, "\The [src] has elected to attempt to take control of you. Is this something you will allow to happen?", "Allow Prey Domination",list("No","Yes")) != "Yes") + to_chat(src, "\The [pred] declined your request for control.") + return + if(tgui_alert(pred, "Are you sure? If you should decide to revoke this, you will have the ability to do so in your 'Abilities' tab.", "Allow Prey Domination",list("No","Yes")) != "Yes") + return + to_chat(pred, "You can feel the will of another overwriting your own, control of your body being sapped away from you...") + to_chat(src, "You can feel the will of your host diminishing as you exert your will over them!") + if(!do_after(src, 10 SECONDS, exclusive = TRUE) || !isbelly(loc) || loc.loc != pred) + to_chat(src, "Your attempt to regain control has been interrupted...") + to_chat(pred, "The dominant sensation fades away...") + return + + to_chat(src, "You plunge your conciousness into \the [pred], assuming control over their very body, leaving your own behind within \the [pred]'s [loc].") + to_chat(pred, "You feel your body move on its own, as you are pushed to the background, and an alien consciousness displaces yours.") + var/mob/living/dominated_brain/pred_brain + if(istype(src, /mob/living/dominated_brain)) + pred_brain = new /mob/living/dominated_brain(pred, pred, name) //We have to play musical chairs with 3 bodies, or everyone gets d/ced + else + pred_brain = new /mob/living/dominated_brain(pred, pred, name, src) + + pred_brain.prey_ckey = src.ckey + pred_brain.pred_ckey = pred.ckey + pred_brain.handle_langs() + + // pred -> brain + var/pred_id = pred.computer_id + var/pred_ip = pred.lastKnownIP + pred.computer_id = null + pred.lastKnownIP = null + + if(!pred_brain.computer_id) + pred_brain.computer_id = pred_id + + if(!pred_brain.lastKnownIP) + pred_brain.lastKnownIP = pred_ip + + // prey -> pred + + var/prey_id = src.computer_id + var/prey_ip = src.lastKnownIP + src.computer_id = null + src.lastKnownIP = null + + if(!pred.computer_id) + pred.computer_id = prey_id + + if(!pred.lastKnownIP) + pred.lastKnownIP = prey_ip + + pred.verbs += /mob/living/proc/release_predator + pred.verbs += /mob/living/proc/psay + pred.verbs += /mob/living/proc/pme + + //Now actually put the people in the mobs + pred_brain.ckey = pred_brain.pred_ckey + pred.ckey = pred_brain.prey_ckey + +/mob/living/proc/release_predator() + set category = "Abilities" + set name = "Restore Control" + set desc = "Release control of your predator's body." + + for(var/I in contents) + if(istype(I, /mob/living/dominated_brain)) + var/mob/living/dominated_brain/db = I + db.restore_control() + return + to_chat(src, "You haven't been taken over, and shouldn't have this verb. I'll clean that up for you. Report this on the github, it is a bug.") + verbs -= /mob/living/proc/release_predator + +/mob/living/dominated_brain/proc/resist_control() + set category = "Abilities" + set name = "Resist Control" + set desc = "Attempt to resist control." + log_and_message_admins("I am going to try to process the resist verb. I have [pred_body]'s ckey as [pred_body.ckey] and [pred_ckey] as the pred's ckey.") + if(pred_body.ckey == pred_ckey) + log_and_message_admins("I think the pred is in control of their own body so I'll just run dominate_predator instead of restore_control.") + dominate_predator() + return + log_and_message_admins("I am going to run restore_control, as [pred_body.ckey] is not the same as [pred_ckey]") + to_chat(src, "You begin to resist \the [prey_name]'s control!!!") + to_chat(pred_body, "You feel the captive mind of [src] begin to resist your control.") + + if(do_after(src, 10 SECONDS, exclusive = TRUE)) + restore_control() + else + to_chat(src, "Your attempt to regain control has been interrupted...") + to_chat(pred_body, "The dominant sensation fades away...") + +/mob/living/proc/psay(message as text|null) + set category = "Abilities" + set name = "Prey Say (psay)" + set desc = "Emote to a dominated predator/prey." + + if (src.client) + if(client.prefs.muted & MUTE_IC) + to_chat(src, "You cannot speak in IC (muted).") + return + message = sanitize(message) + if (!message) + message = input(usr, "Type a message to emote.","Emote to prey") as text|null + if (!message) + return + + var/f = FALSE + for(var/I in contents) + if(istype(I, /mob/living/dominated_brain)) + var/mob/living/dominated_brain/db = I + to_chat(db, "\The [src] thinks, \"[message]\"") + f = TRUE + if(f) + to_chat(src, "You think \"[message]\"") + for (var/mob/M in player_list) + if (istype(M, /mob/new_player)) + continue + else if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears)) + to_chat(M, "\The [src] thinks, \"[message]\"") + log_say(message,src) + else + to_chat(src, "There is no one inside you to talk to...") + return + +/mob/living/proc/pme(message as text|null) + set category = "Abilities" + set name = "Prey Emote (pme)" + set desc = "Emote to a dominated predator/prey." + + if (src.client) + if(client.prefs.muted & MUTE_IC) + to_chat(src, "You cannot speak in IC (muted).") + return + message = sanitize(message) + if (!message) + message = input(usr, "Type a message to emote.","Emote to prey") as text|null + if (!message) + return + var/f = FALSE + for(var/I in contents) + if(istype(I, /mob/living/dominated_brain)) + var/mob/living/dominated_brain/db = I + to_chat(db, "\The [src] [message]") + f = TRUE + if(f) + to_chat(src, "\The [src] [message]") + for (var/mob/M in player_list) + if (istype(M, /mob/new_player)) + continue + else if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears)) + to_chat(M, "\The [src] [message]") + log_emote(message,src) + else + to_chat(src, "There is no one inside you to talk to...") + return \ No newline at end of file diff --git a/maps/virgo_minitest/virgo_minitest-sector-3.dmm b/maps/virgo_minitest/virgo_minitest-sector-3.dmm index d1d6b15a0d5..f0f58d57ede 100644 --- a/maps/virgo_minitest/virgo_minitest-sector-3.dmm +++ b/maps/virgo_minitest/virgo_minitest-sector-3.dmm @@ -41,7 +41,7 @@ "al" = ( /obj/structure/closet/cabinet, /obj/item/weapon/gun/projectile/shotgun/doublebarrel, -/obj/item/weapon/storage/box/beanbags, +/obj/item/ammo_magazine/ammo_box/b12g/beanbag, /turf/simulated/floor/wood, /area/awaymission/wwmines) "am" = (