From e5ec6c761b54c6bb2f169355e5d9022e6d4389bb Mon Sep 17 00:00:00 2001 From: Zuhayr Date: Sun, 22 Nov 2015 20:46:49 +1030 Subject: [PATCH] Adds a possession system for ghost mousedrop(). Currently allows for control of mice, drones and use of drone fabricators. --- code/__defines/mobs.dm | 3 ++ code/_helpers/game.dm | 3 ++ code/_helpers/mobs.dm | 4 +- code/controllers/configuration.dm | 5 ++ code/modules/mob/dead/observer/observer.dm | 31 ++++++++---- code/modules/mob/living/living.dm | 40 +++++++++++++++ code/modules/mob/living/living_defines.dm | 1 + .../mob/living/silicon/robot/drone/drone.dm | 26 ++++++++++ .../silicon/robot/drone/drone_manufacturer.dm | 50 ++++++++++--------- .../living/simple_animal/friendly/mouse.dm | 1 + 10 files changed, 128 insertions(+), 36 deletions(-) diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm index c72678fdc84..37d1a619c71 100644 --- a/code/__defines/mobs.dm +++ b/code/__defines/mobs.dm @@ -125,3 +125,6 @@ #define FLASH_PROTECTION_NONE 0 #define FLASH_PROTECTION_MODERATE 1 #define FLASH_PROTECTION_MAJOR 2 + +#define ANIMAL_SPAWN_DELAY round(config.respawn_delay / 6) +#define DRONE_SPAWN_DELAY round(config.respawn_delay / 3) \ No newline at end of file diff --git a/code/_helpers/game.dm b/code/_helpers/game.dm index 4eec974e670..cf955a022c7 100644 --- a/code/_helpers/game.dm +++ b/code/_helpers/game.dm @@ -532,3 +532,6 @@ datum/projectile_data /proc/SecondsToTicks(var/seconds) return seconds * 10 + +/proc/round_is_spooky(var/spookiness_threshold = config.cult_ghostwriter_req_cultists) + return (cult.current_antagonists.len > spookiness_threshold) diff --git a/code/_helpers/mobs.dm b/code/_helpers/mobs.dm index 6e2a7fae360..ac3b4b7e4ae 100644 --- a/code/_helpers/mobs.dm +++ b/code/_helpers/mobs.dm @@ -61,12 +61,12 @@ proc/random_facial_hair_style(gender, species = "Human") f_style = pick(valid_facialhairstyles) return f_style - + proc/sanitize_name(name, species = "Human") var/datum/species/current_species if(species) current_species = all_species[species] - + return current_species ? current_species.sanitize_name(name) : sanitizeName(name) proc/random_name(gender, species = "Human") diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index ad0eaa689d8..9dec281ed86 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -214,6 +214,8 @@ var/list/gamemode_cache = list() var/list/language_prefixes = list(",","#","-")//Default language prefixes + var/ghosts_can_possess_animals = 0 + /datum/configuration/New() var/list/L = typesof(/datum/game_mode) - /datum/game_mode for (var/T in L) @@ -420,6 +422,9 @@ var/list/gamemode_cache = list() if ("githuburl") config.githuburl = value + if ("ghosts_can_possess_animals") + config.ghosts_can_possess_animals = value + if ("guest_jobban") config.guest_jobban = 1 diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index f6c84d77759..451afd48743 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -462,7 +462,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp src << "Spawning as a mouse is currently disabled." return - if(!MayRespawn(1, round(config.respawn_delay / 6))) + if(!MayRespawn(1, ANIMAL_SPAWN_DELAY)) return var/turf/T = get_turf(src) @@ -507,12 +507,28 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp //This is called when a ghost is drag clicked to something. /mob/dead/observer/MouseDrop(atom/over) if(!usr || !over) return - if (isobserver(usr) && usr.client && usr.client.holder && isliving(over)) - if (usr.client.holder.cmd_ghost_drag(src,over)) + if(isobserver(usr) && usr.client && isliving(over)) + var/mob/living/M = over + // If they an admin, see if control can be resolved. + if(usr.client.holder && usr.client.holder.cmd_ghost_drag(src,M)) + return + // Otherwise, see if we can possess the target. + if(usr == src && try_possession(M)) + return + if(istype(over, /obj/machinery/drone_fabricator)) + if(try_drone_spawn(src, over)) return return ..() +/mob/dead/observer/proc/try_possession(var/mob/living/M) + if(!config.ghosts_can_possess_animals) + usr << "Ghosts are not permitted to possess animals." + return 0 + if(!M.can_be_possessed_by(src)) + return 0 + return M.do_possession(src) + //Used for drawing on walls with blood puddles as a spooky ghost. /mob/dead/verb/bloody_doodle() @@ -530,12 +546,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp if (usr != src) return 0 //something is terribly wrong - var/ghosts_can_write - if(ticker.mode.name == "cult") - if(cult.current_antagonists.len > config.cult_ghostwriter_req_cultists) - ghosts_can_write = 1 - - if(!ghosts_can_write) + if(!round_is_spooky()) src << "\red The veil is not thin enough for you to do that." return @@ -662,7 +673,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp /mob/proc/can_admin_interact() return 0 - + /mob/dead/observer/can_admin_interact() return check_rights(R_ADMIN, 0, src) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 73e8137faf0..656fae59927 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -810,3 +810,43 @@ default behaviour is: ear_damage = damage if(deaf >= 0) ear_deaf = deaf + +/mob/living/proc/can_be_possessed_by(var/mob/dead/observer/possessor) + if(!istype(possessor)) + return 0 + if(!possession_candidate) + possessor << "That animal cannot be possessed." + return 0 + if(jobban_isbanned(possessor, "Animal")) + possessor << "You are banned from animal roles." + return 0 + if(!possessor.MayRespawn(1,ANIMAL_SPAWN_DELAY)) + return 0 + return 1 + +/mob/living/proc/do_possession(var/mob/dead/observer/possessor) + + if(!(istype(possessor) && possessor.ckey)) + return 0 + + if(src.ckey || src.client) + possessor << "\The [src] already has a player." + return 0 + + message_admins("[key_name_admin(possessor)] has taken control of \the [src].") + log_admin("[key_name(possessor)] took control of \the [src].") + src.ckey = possessor.ckey + qdel(possessor) + + if(round_is_spooky(6)) // Six or more active cultists. + src << "You reach out with tendrils of ectoplasm and invade the mind of \the [src]..." + src << "You have assumed direct control of \the [src]." + src << "Due to the spookiness of the round, you have taken control of the poor animal as an invading, possessing spirit - roleplay accordingly." + src.universal_speak = 1 + src.universal_understand = 1 + //src.cultify() // Maybe another time. + return + + src << "You are now \the [src]!" + src << "Remember to stay in character for a mob of this type!" + return 1 diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 5a671afe992..2164c7ec187 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -43,3 +43,4 @@ var/fire_stacks var/failed_last_breath = 0 //This is used to determine if the mob failed a breath. If they did fail a brath, they will attempt to breathe each tick, otherwise just once per 4 ticks. + var/possession_candidate // Can be possessed by ghosts if unplayed. \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/drone/drone.dm b/code/modules/mob/living/silicon/robot/drone/drone.dm index 56d608fd658..e1239181470 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone.dm @@ -36,6 +36,7 @@ var/list/mob_hat_cache = list() req_access = list(access_engine, access_robotics) integrated_light_power = 3 local_transmit = 1 + possession_candidate = 1 mob_bump_flag = SIMPLE_ANIMAL mob_swap_flags = SIMPLE_ANIMAL @@ -57,6 +58,31 @@ var/list/mob_hat_cache = list() holder_type = /obj/item/weapon/holder/drone +/mob/living/silicon/robot/drone/can_be_possessed_by(var/mob/dead/observer/possessor) + if(!istype(possessor)) + return 0 + if(!config.allow_drone_spawn) + src << "Playing as drones is not currently permitted." + return 0 + if(jobban_isbanned(possessor,"Cyborg")) + usr << "You are banned from playing synthetics and cannot spawn as a drone." + return 0 + if(!possessor.MayRespawn(1,DRONE_SPAWN_DELAY)) + return 0 + return 1 + +/mob/living/silicon/robot/drone/do_possession(var/mob/dead/observer/possessor) + if(!(istype(possessor) && possessor.ckey)) + return 0 + if(src.ckey || src.client) + possessor << "\The [src] already has a player." + return 0 + message_admins("[key_name_admin(possessor)] has taken control of \the [src].") + log_admin("[key_name(possessor)] took control of \the [src].") + transfer_personality(possessor.client) + qdel(possessor) + return 1 + /mob/living/silicon/robot/drone/Destroy() if(hat) hat.loc = get_turf(src) diff --git a/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm b/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm index f82a669f5df..0ddc764dbe5 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm @@ -85,45 +85,47 @@ drone_progress = 0 -/mob/dead/verb/join_as_drone() - +/mob/dead/observer/verb/join_as_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(ticker.current_state < GAME_STATE_PLAYING) - src << "The game hasn't started yet!" + user << "The game hasn't started yet!" return if(!(config.allow_drone_spawn)) - src << "That verb is not currently permitted." + user << "That verb is not currently permitted." return - if (!src.stat) + if(jobban_isbanned(user,"Cyborg")) + user << "You are banned from playing synthetics and cannot spawn as a drone." return - if (usr != src) - return 0 //something is terribly wrong - - if(jobban_isbanned(src,"Cyborg")) - usr << "You are banned from playing synthetics and cannot spawn as a drone." + if(!user.MayRespawn(1, DRONE_SPAWN_DELAY)) return - if(!MayRespawn(1, round(config.respawn_delay / 3))) - return + if(!fabricator) - var/list/all_fabricators = list() - for(var/obj/machinery/drone_fabricator/DF in world) - if(DF.stat & NOPOWER || !DF.produce_drones) - continue - if(DF.drone_progress >= 100) + var/list/all_fabricators = list() + for(var/obj/machinery/drone_fabricator/DF in machines) + if((DF.stat & NOPOWER) || !DF.produce_drones || DF.drone_progress < 100) + continue all_fabricators[DF.fabricator_tag] = DF - if(!all_fabricators.len) - src << "There are no available drone spawn points, sorry." - return + if(!all_fabricators.len) + user << "There are no available drone spawn points, sorry." + return - var/choice = input(src,"Which fabricator do you wish to use?") as null|anything in all_fabricators - if(choice) - var/obj/machinery/drone_fabricator/chosen_fabricator = all_fabricators[choice] - chosen_fabricator.create_drone(src.client) + 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 \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm index f2cc7686c0b..85d1cc15849 100644 --- a/code/modules/mob/living/simple_animal/friendly/mouse.dm +++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm @@ -29,6 +29,7 @@ universal_understand = 1 holder_type = /obj/item/weapon/holder/mouse mob_size = MOB_MINISCULE + possession_candidate = 1 /mob/living/simple_animal/mouse/Life() ..()