diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 7a581b816c1..c630c1714f7 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -342,11 +342,9 @@ /datum/mind/proc/memory_edit_wizard(mob/living/carbon/human/H) . = _memory_edit_header("wizard") - if(src in SSticker.mode.wizards) + if(has_antag_datum(/datum/antagonist/wizard)) . += "WIZARD|no" . += "
To lair, undress, dress up, let choose name." - if(!objective_holder.has_objectives()) - . += "
Objectives are empty! Randomize!" else . += "wizard|NO" @@ -927,24 +925,18 @@ switch(href_list["wizard"]) if("clear") - if(src in SSticker.mode.wizards) - SSticker.mode.wizards -= src - special_role = null - current.spellremove(current) - current.faction = list("Station") - SSticker.mode.update_wiz_icons_removed(src) - to_chat(current, "You have been brainwashed! You are no longer a wizard!") + if(has_antag_datum(/datum/antagonist/wizard)) + remove_antag_datum(/datum/antagonist/wizard) + log_admin("[key_name(usr)] has de-wizarded [key_name(current)]") message_admins("[key_name_admin(usr)] has de-wizarded [key_name_admin(current)]") if("wizard") - if(!(src in SSticker.mode.wizards)) - SSticker.mode.wizards += src - special_role = SPECIAL_ROLE_WIZARD - //ticker.mode.learn_basic_spells(current) - SSticker.mode.update_wiz_icons_added(src) - SEND_SOUND(current, sound('sound/ambience/antag/ragesmages.ogg')) - to_chat(current, "You are a Space Wizard!") - current.faction = list("wizard") + if(!has_antag_datum(/datum/antagonist/wizard)) + var/datum/antagonist/wizard/wizard = new /datum/antagonist/wizard() + wizard.should_equip_wizard = FALSE + wizard.should_name_pick = FALSE + add_antag_datum(wizard) + log_admin("[key_name(usr)] has wizarded [key_name(current)]") message_admins("[key_name_admin(usr)] has wizarded [key_name_admin(current)]") current.create_log(MISC_LOG, "[current] was made into a wizard by [key_name_admin(usr)]") @@ -953,18 +945,18 @@ log_admin("[key_name(usr)] has moved [key_name(current)] to the wizard's lair") message_admins("[key_name_admin(usr)] has moved [key_name_admin(current)] to the wizard's lair") if("dressup") - SSticker.mode.equip_wizard(current) + var/datum/antagonist/wizard/wizard = has_antag_datum(/datum/antagonist/wizard) + var/list/text_result = wizard.equip_wizard() + to_chat(current, chat_box_red(text_result.Join("
"))) log_admin("[key_name(usr)] has equipped [key_name(current)] as a wizard") message_admins("[key_name_admin(usr)] has equipped [key_name_admin(current)] as a wizard") if("name") - INVOKE_ASYNC(SSticker.mode, TYPE_PROC_REF(/datum/game_mode/wizard, name_wizard), current) + var/datum/antagonist/wizard/wizard = has_antag_datum(/datum/antagonist/wizard) + if(!istype(wizard)) + return + wizard.name_wizard() log_admin("[key_name(usr)] has allowed wizard [key_name(current)] to name themselves") message_admins("[key_name_admin(usr)] has allowed wizard [key_name_admin(current)] to name themselves") - if("autoobjectives") - SSticker.mode.forge_wizard_objectives(src) - to_chat(usr, "The objectives for wizard [key] have been generated. You can edit them and announce manually.") - log_admin("[key_name(usr)] has automatically forged wizard objectives for [key_name(current)]") - message_admins("[key_name_admin(usr)] has automatically forged wizard objectives for [key_name_admin(current)]") else if(href_list["changeling"]) @@ -1637,26 +1629,6 @@ SSticker.mode.blob_overminds += src special_role = SPECIAL_ROLE_BLOB_OVERMIND -/datum/mind/proc/make_Wizard() - if(!(src in SSticker.mode.wizards)) - SSticker.mode.wizards += src - special_role = SPECIAL_ROLE_WIZARD - assigned_role = SPECIAL_ROLE_WIZARD - //ticker.mode.learn_basic_spells(current) - if(!GLOB.wizardstart.len) - current.loc = pick(GLOB.latejoin) - to_chat(current, "HOT INSERTION, GO GO GO") - else - current.loc = pick(GLOB.wizardstart) - - SSticker.mode.equip_wizard(current) - for(var/obj/item/spellbook/S in current.contents) - S.op = 0 - INVOKE_ASYNC(SSticker.mode, TYPE_PROC_REF(/datum/game_mode/wizard, name_wizard), current) - SSticker.mode.forge_wizard_objectives(src) - SSticker.mode.greet_wizard(src) - SSticker.mode.update_wiz_icons_added(src) - /datum/mind/proc/make_Abductor() var/role = alert("Abductor Role?", "Role", "Agent", "Scientist") var/team = input("Abductor Team?", "Team?") in list(1,2,3,4) diff --git a/code/game/gamemodes/wizard/artefact.dm b/code/game/gamemodes/wizard/artefact.dm index a5d2c841b5f..3074242b50a 100644 --- a/code/game/gamemodes/wizard/artefact.dm +++ b/code/game/gamemodes/wizard/artefact.dm @@ -24,52 +24,40 @@ data["used"] = used return data -/obj/item/contract/ui_act(action, params) +/obj/item/contract/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) if(..()) return - var/mob/living/carbon/human/H = usr - if(used) return + INVOKE_ASYNC(src, PROC_REF(async_find_apprentice), action, ui.user) + SStgui.close_uis(src) +/obj/item/contract/proc/async_find_apprentice(action, user) + if(!ishuman(user)) + return + var/mob/living/carbon/human/H = user used = TRUE var/image/source = image('icons/obj/cardboard_cutout.dmi', "cutout_wizard") var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as the wizard apprentice of [H.real_name]?", ROLE_WIZARD, TRUE, source = source) - if(length(candidates)) - var/mob/C = pick(candidates) - new /obj/effect/particle_effect/smoke(H.loc) - var/mob/living/carbon/human/M = new/mob/living/carbon/human(H.loc) - M.key = C.key - to_chat(M, "You are [H.real_name]'s apprentice! You are bound by magic contract to follow [H.p_their()] orders and help [H.p_them()] in accomplishing [H.p_their()] goals.") - equip_apprentice(action, M, H) - var/wizard_name_first = pick(GLOB.wizard_first) - var/wizard_name_second = pick(GLOB.wizard_second) - var/randomname = "[wizard_name_first] [wizard_name_second]" - var/newname = sanitize(copytext_char(input(M, "You are the wizard's apprentice. Would you like to change your name to something else?", "Name change", randomname) as null|text, 1, MAX_NAME_LEN)) - - if(!newname) - newname = randomname - M.mind.name = newname - M.real_name = newname - M.name = newname - - var/datum/objective/protect/new_objective = new /datum/objective/protect - new_objective.target = H.mind - new_objective.explanation_text = "Protect and obey [H.real_name], your teacher." - M.mind.add_mind_objective(new_objective) - - SSticker.mode.apprentices += M.mind - M.mind.special_role = SPECIAL_ROLE_WIZARD_APPRENTICE - SSticker.mode.update_wiz_icons_added(M.mind) - dust_if_respawnable(C) - M.faction = list("wizard") - SStgui.close_uis(src) - else + if(!length(candidates)) used = FALSE to_chat(H, "Unable to reach your apprentice! You can either attack the spellbook with the contract to refund your points, or wait and try again later.") + return + new /obj/effect/particle_effect/smoke(get_turf(H)) + + var/mob/C = pick(candidates) + var/mob/living/carbon/human/M = new /mob/living/carbon/human(get_turf(H)) + M.key = C.key + + var/datum/antagonist/wizard/apprentice/apprentice = new /datum/antagonist/wizard/apprentice() + apprentice.my_teacher = H + apprentice.class_type = action + M.mind.add_antag_datum(apprentice) + + dust_if_respawnable(C) /obj/item/contract/attack_self(mob/user as mob) if(..()) @@ -81,67 +69,6 @@ ui_interact(user) -/obj/item/contract/proc/equip_apprentice(action, mob/living/carbon/human/M, mob/living/carbon/human/H) - M.equip_to_slot_or_del(new /obj/item/radio/headset(M), SLOT_HUD_LEFT_EAR) - if(action == "stealth") - M.equip_to_slot_or_del(new /obj/item/clothing/under/color/grey(M), SLOT_HUD_JUMPSUIT) - else - M.equip_to_slot_or_del(new /obj/item/clothing/under/color/lightpurple(M), SLOT_HUD_JUMPSUIT) - M.equip_to_slot_or_del(new /obj/item/storage/backpack(M), SLOT_HUD_BACK) - M.equip_to_slot_or_del(new /obj/item/storage/box(M), SLOT_HUD_IN_BACKPACK) - M.equip_to_slot_or_del(new /obj/item/teleportation_scroll/apprentice(M), SLOT_HUD_RIGHT_STORE) - switch(action) - if("fire") - M.mind.AddSpell(new /obj/effect/proc_holder/spell/fireball/apprentice(null)) - M.mind.AddSpell(new /obj/effect/proc_holder/spell/sacred_flame(null)) - ADD_TRAIT(M, TRAIT_RESISTHEAT, MAGIC_TRAIT) - ADD_TRAIT(M, TRAIT_RESISTHIGHPRESSURE, MAGIC_TRAIT) - M.mind.AddSpell(new /obj/effect/proc_holder/spell/ethereal_jaunt(null)) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(M), SLOT_HUD_SHOES) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/red(M), SLOT_HUD_OUTER_SUIT) - M.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/red(M), SLOT_HUD_HEAD) - to_chat(M, "Your service has not gone unrewarded. Under the tutelage of [H.real_name], you've acquired proficiency in the fundamentals of Firebending, enabling you to cast spells like Fireball, Sacred Flame, and Ethereal Jaunt.") - to_chat(M, "You are immune to fire, but you are NOT immune to the explosions caused by your fireballs. Neither is your teacher, for that matter. Be careful!") - if("translocation") - M.mind.AddSpell(new /obj/effect/proc_holder/spell/area_teleport/teleport(null)) - M.mind.AddSpell(new /obj/effect/proc_holder/spell/turf_teleport/blink(null)) - M.mind.AddSpell(new /obj/effect/proc_holder/spell/ethereal_jaunt(null)) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(M), SLOT_HUD_SHOES) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(M), SLOT_HUD_OUTER_SUIT) - M.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(M), SLOT_HUD_HEAD) - to_chat(M, "Your service has not gone unrewarded. While studying under [H.real_name], you mastered reality-bending mobility spells, allowing you to cast Teleport, Blink, and Ethereal Jaunt.") - if("restoration") - M.mind.AddSpell(new /obj/effect/proc_holder/spell/charge(null)) - M.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe/knock(null)) - var/obj/effect/proc_holder/spell/return_to_teacher/S = new /obj/effect/proc_holder/spell/return_to_teacher(null) - S.teacher = H.mind - M.mind.AddSpell(S) - M.equip_to_slot_or_del(new /obj/item/gun/magic/staff/healing(M), SLOT_HUD_RIGHT_HAND) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal/marisa(M), SLOT_HUD_SHOES) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/marisa(M), SLOT_HUD_OUTER_SUIT) - M.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/marisa(M), SLOT_HUD_HEAD) - to_chat(M, "Your service has not gone unrewarded. Under the guidance of [H.real_name], you've acquired life-saving survival spells. You can now cast Charge and Knock, and possess the ability to teleport back to your mentor.") - to_chat(M, "Your Charge spell can be used to recharge your Staff of Healing or reduce the cooldowns of your teacher, if you are grabbing them with empty hands.") - if("stealth") - M.mind.AddSpell(new /obj/effect/proc_holder/spell/mind_transfer(null)) - M.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe/knock(null)) - M.mind.AddSpell(new /obj/effect/proc_holder/spell/fireball/toolbox(null)) - M.mind.AddSpell(new /obj/effect/proc_holder/spell/disguise_self(null)) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(M), SLOT_HUD_SHOES) - M.equip_to_slot_or_del(new /obj/item/clothing/mask/gas(M), SLOT_HUD_WEAR_MASK) - M.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/yellow(M), SLOT_HUD_GLOVES) - M.equip_to_slot_or_del(new /obj/item/storage/belt/utility/full(M), SLOT_HUD_BELT) - to_chat(M, "Your service has not gone unrewarded. Under the mentorship of [H.real_name], you've mastered stealthy, robeless spells. You can now cast Mindswap, Knock, Homing Toolbox, and Disguise Self without the need for wizard robes.") - if("honk") - M.mind.AddSpell(new /obj/effect/proc_holder/spell/touch/banana/apprentice(null)) - M.mind.AddSpell(new /obj/effect/proc_holder/spell/ethereal_jaunt(null)) - M.mind.AddSpell(new /obj/effect/proc_holder/spell/summonitem(null)) - M.equip_to_slot_or_del(new /obj/item/gun/magic/staff/slipping(M), SLOT_HUD_RIGHT_HAND) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/clown_shoes/magical/nodrop(M), SLOT_HUD_SHOES) - M.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/clown(M), SLOT_HUD_OUTER_SUIT) - M.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/clown(M), SLOT_HUD_HEAD) - M.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clownwiz(M), SLOT_HUD_WEAR_MASK) - to_chat(M, "Your dedication pays off! Under [H.real_name]'s guidance, you've mastered magical honkings, seamlessly casting spells like Banana Touch, Ethereal Jaunt, and Instant Summons, while skillfully wielding a Staff of Slipping. Honk!") ///////////////////////////Veil Render////////////////////// diff --git a/code/game/gamemodes/wizard/raginmages.dm b/code/game/gamemodes/wizard/raginmages.dm index e710e024147..a524a17e5bf 100644 --- a/code/game/gamemodes/wizard/raginmages.dm +++ b/code/game/gamemodes/wizard/raginmages.dm @@ -2,7 +2,6 @@ name = "ragin' mages" config_tag = "raginmages" required_players = 20 - use_huds = TRUE but_wait_theres_more = TRUE var/max_mages = 0 var/making_mage = FALSE @@ -18,17 +17,6 @@ to_chat(world, "The current game mode is - Ragin' Mages!") to_chat(world, "The Space Wizard Federation is pissed, crew must help defeat all the Space Wizards invading the station!") -/datum/game_mode/wizard/raginmages/greet_wizard(datum/mind/wizard, you_are=1) - var/list/messages = list() - if(you_are) - messages.Add("You are the Space Wizard!") - messages.Add("The Space Wizards Federation has given you the following tasks:") - - messages.Add("Supreme Objective: Make sure the station pays for its actions against our diplomats. We might send more Wizards to the station if the situation is not developing in our favour.") - messages.Add(wizard.prepare_announce_objectives(title = FALSE)) - to_chat(wizard.current, chat_box_red(messages.Join("
"))) - wizard.current.create_log(MISC_LOG, "[wizard.current] was made into a wizard") - /datum/game_mode/wizard/raginmages/check_finished() var/wizards_alive = 0 var/wizard_cap = CEILING((num_players_started() / players_per_mage), 1) @@ -37,14 +25,14 @@ if(isnull(wizard.current)) continue if(wizard.current.stat == DEAD || isbrain(wizard.current) || !iscarbon(wizard.current)) - squabble_helper(wizard) - continue - if(wizard.current.stat == UNCONSCIOUS) - if(wizard.current.health < HEALTH_THRESHOLD_DEAD) //Lets make this not get funny rng crit involved + if(squabble_helper(wizard)) + continue + if(wizard.current.stat != CONSCIOUS) + if(wizard.current.health < HEALTH_THRESHOLD_DEAD || wizard.current.stat == DEAD) //Lets make this not get funny rng crit involved if(!squabble_helper(wizard)) to_chat(wizard.current, "The Space Wizard Federation is upset with your performance and have terminated your employment.") wizard.current.dust() // *REAL* ACTION!! *REAL* DRAMA!! *REAL* BLOODSHED!! - continue + continue if(!wizard.current.client) continue // Could just be a bad connection, so SSD wiz's shouldn't be gibbed over it, but they're not "alive" either @@ -126,7 +114,10 @@ making_mage = FALSE if(harry) var/mob/living/carbon/human/new_character = makeBody(harry) - new_character.mind.make_Wizard() // This puts them at the wizard spawn, worry not + var/datum/antagonist/wizard/wizard = new /datum/antagonist/wizard() + wizard.additional_text = "Make sure the station pays for its actions against our diplomats. We might send more Wizards to the station if the situation is not developing in our favour." + new_character.mind.add_antag_datum(wizard) + new_character.forceMove(pick(GLOB.wizardstart)) new_character.equip_to_slot_or_del(new /obj/item/reagent_containers/drinks/mugwort(harry), SLOT_HUD_IN_BACKPACK) // The first wiznerd can get their mugwort from the wizard's den, new ones will also need mugwort! mages_made++ diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm index c13da60ffc9..713904da0d1 100644 --- a/code/game/gamemodes/wizard/soulstone.dm +++ b/code/game/gamemodes/wizard/soulstone.dm @@ -451,8 +451,9 @@ if(user) S.faction |= "\ref[user]" //Add the master as a faction, allowing inter-mob cooperation if(iswizard(user)) - SSticker.mode.update_wiz_icons_added(S.mind) - S.mind.special_role = SPECIAL_ROLE_WIZARD_APPRENTICE + var/datum/antagonist/wizard/construct/construct = new /datum/antagonist/wizard/construct() + construct.my_creator = user + S.mind.add_antag_datum(construct) if(IS_CULTIST(user)) S.mind.add_antag_datum(/datum/antagonist/cultist) to_chat(S, "Your soul has been captured! You are now bound to the cult's will. Help them succeed in their goals at all costs.") diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index 66e13e9fb79..6c20df34f16 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -10,238 +10,116 @@ required_enemies = 1 recommended_enemies = 1 single_antag_positions = list() - var/use_huds = TRUE var/finished = FALSE var/but_wait_theres_more = FALSE + var/list/pre_wizards = list() /datum/game_mode/wizard/announce() to_chat(world, "The current game mode is - Wizard!") to_chat(world, "There is a SPACE WIZARD on the station. You can't let him achieve his objective!") -/datum/game_mode/wizard/can_start()//This could be better, will likely have to recode it later - if(!..()) - return 0 +/datum/game_mode/wizard/pre_setup() var/list/datum/mind/possible_wizards = get_players_for_role(ROLE_WIZARD) - if(possible_wizards.len==0) - return 0 + if(!length(possible_wizards)) + return FALSE var/datum/mind/wizard = pick(possible_wizards) - wizards += wizard + pre_wizards += wizard wizard.assigned_role = SPECIAL_ROLE_WIZARD //So they aren't chosen for other jobs. wizard.special_role = SPECIAL_ROLE_WIZARD - wizard.set_original_mob(wizard.current) - if(GLOB.wizardstart.len == 0) + if(!length(GLOB.wizardstart)) to_chat(wizard.current, "A starting location for you could not be found, please report this bug!") - return 0 - return 1 - -/datum/game_mode/wizard/pre_setup() - for(var/datum/mind/wiz in wizards) - wiz.current.loc = pick(GLOB.wizardstart) - ..() - return 1 + return FALSE + return TRUE /datum/game_mode/wizard/post_setup() - for(var/datum/mind/wizard in wizards) - log_game("[key_name(wizard)] has been selected as a Wizard") - forge_wizard_objectives(wizard) - equip_wizard(wizard.current) - INVOKE_ASYNC(src, PROC_REF(name_wizard), wizard.current) - greet_wizard(wizard) - if(use_huds) - update_wiz_icons_added(wizard) - + for(var/datum/mind/wiz in pre_wizards) + wiz.add_antag_datum(/datum/antagonist/wizard) + wiz.current.forceMove(pick(GLOB.wizardstart)) + pre_wizards.Cut() ..() -/datum/game_mode/proc/remove_wizard(datum/mind/wizard_mind) - if(wizard_mind in wizards) - SSticker.mode.wizards -= wizard_mind - wizard_mind.special_role = null - wizard_mind.current.create_attack_log("De-wizarded") - wizard_mind.current.create_log(CONVERSION_LOG, "De-wizarded") - wizard_mind.current.spellremove(wizard_mind.current) - wizard_mind.current.faction = list("Station") - if(issilicon(wizard_mind.current)) - to_chat(wizard_mind.current, "You have been turned into a robot! You can feel your magical powers fading away...") - else - to_chat(wizard_mind.current, "You have been brainwashed! You are no longer a wizard.") - SSticker.mode.update_wiz_icons_removed(wizard_mind) - -/datum/game_mode/proc/update_wiz_icons_added(datum/mind/wiz_mind) - var/datum/atom_hud/antag/wizhud = GLOB.huds[ANTAG_HUD_WIZ] - wizhud.join_hud(wiz_mind.current) - set_antag_hud(wiz_mind.current, ((wiz_mind in wizards) ? "hudwizard" : "apprentice")) - -/datum/game_mode/proc/update_wiz_icons_removed(datum/mind/wiz_mind) - var/datum/atom_hud/antag/wizhud = GLOB.huds[ANTAG_HUD_WIZ] - wizhud.leave_hud(wiz_mind.current) - set_antag_hud(wiz_mind.current, null) - -/datum/game_mode/proc/forge_wizard_objectives(datum/mind/wizard) - wizard.add_mind_objective(/datum/objective/wizchaos) - -/datum/game_mode/proc/name_wizard(mob/living/carbon/human/wizard_mob) - //Allows the wizard to choose a custom name or go with a random one. Spawn 0 so it does not lag the round starting. - var/wizard_name_first = pick(GLOB.wizard_first) - var/wizard_name_second = pick(GLOB.wizard_second) - var/randomname = "[wizard_name_first] [wizard_name_second]" - var/newname = sanitize(copytext_char(input(wizard_mob, "You are the Space Wizard. Would you like to change your name to something else?", "Name change", randomname) as null|text, 1, MAX_NAME_LEN)) - - if(!newname) - newname = randomname - - wizard_mob.real_name = newname - wizard_mob.name = newname - if(wizard_mob.mind) - wizard_mob.mind.name = newname - -/datum/game_mode/proc/greet_wizard(datum/mind/wizard, you_are=1) - addtimer(CALLBACK(wizard.current, TYPE_PROC_REF(/mob, playsound_local), null, 'sound/ambience/antag/ragesmages.ogg', 100, 0), 30) - var/list/messages = list() - if(you_are) - messages.Add("You are the Space Wizard!") - messages.Add("The Space Wizards Federation has given you the following tasks:") - - messages.Add(wizard.prepare_announce_objectives(title = FALSE)) - messages.Add("For more information, check the wiki page: ([GLOB.configuration.url.wiki_url]/index.php/Wizard)") - to_chat(wizard.current, chat_box_red(messages.Join("
"))) - wizard.current.create_log(MISC_LOG, "[wizard.current] was made into a wizard") - -/datum/game_mode/proc/equip_wizard(mob/living/carbon/human/wizard_mob) - if(!istype(wizard_mob)) - return - - //So zards properly get their items when they are admin-made. - qdel(wizard_mob.wear_suit) - qdel(wizard_mob.head) - qdel(wizard_mob.shoes) - qdel(wizard_mob.r_hand) - qdel(wizard_mob.r_store) - qdel(wizard_mob.l_store) - - if(isplasmaman(wizard_mob)) - wizard_mob.equipOutfit(new /datum/outfit/plasmaman/wizard) - wizard_mob.internal = wizard_mob.r_hand - wizard_mob.update_action_buttons_icon() - else - wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/under/color/lightpurple(wizard_mob), SLOT_HUD_JUMPSUIT) - wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(wizard_mob), SLOT_HUD_HEAD) - wizard_mob.dna.species.after_equip_job(null, wizard_mob) - wizard_mob.rejuvenate() //fix any damage taken by naked vox/plasmamen/etc while round setups - wizard_mob.equip_to_slot_or_del(new /obj/item/radio/headset(wizard_mob), SLOT_HUD_LEFT_EAR) - wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(wizard_mob), SLOT_HUD_SHOES) - wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(wizard_mob), SLOT_HUD_OUTER_SUIT) - wizard_mob.equip_to_slot_or_del(new /obj/item/storage/backpack/satchel(wizard_mob), SLOT_HUD_BACK) - if(wizard_mob.dna.species.speciesbox) - wizard_mob.equip_to_slot_or_del(new wizard_mob.dna.species.speciesbox(wizard_mob), SLOT_HUD_IN_BACKPACK) - else - wizard_mob.equip_to_slot_or_del(new /obj/item/storage/box/survival(wizard_mob), SLOT_HUD_IN_BACKPACK) - wizard_mob.equip_to_slot_or_del(new /obj/item/teleportation_scroll(wizard_mob), SLOT_HUD_RIGHT_STORE) - var/obj/item/spellbook/spellbook = new /obj/item/spellbook(wizard_mob) - spellbook.owner = wizard_mob - wizard_mob.equip_to_slot_or_del(spellbook, SLOT_HUD_LEFT_HAND) - - wizard_mob.faction = list("wizard") - wizard_mob.mind.offstation_role = TRUE - - - - to_chat(wizard_mob, "You will find a list of available spells in your spell book. Choose your magic arsenal carefully.") - to_chat(wizard_mob, "The spellbook is bound to you, and others cannot use it.") - to_chat(wizard_mob, "In your pockets you will find a teleport scroll. Use it as needed.") - wizard_mob.mind.store_memory("Remember: do not forget to prepare your spells.") - wizard_mob.update_icons() - wizard_mob.gene_stability += DEFAULT_GENE_STABILITY //magic - return TRUE - // Checks if the game should end due to all wizards and apprentices being dead, or MMI'd/Borged /datum/game_mode/wizard/check_finished() - var/wizards_alive = 0 - var/apprentices_alive = 0 + if(but_wait_theres_more) + return ..() // Wizards for(var/datum/mind/wizard in wizards) if(!iscarbon(wizard.current) || wizard.current.stat == DEAD) // wizard is in an MMI, don't count them as alive continue - wizards_alive++ + return ..() // Apprentices - if(!wizards_alive) - for(var/datum/mind/apprentice in apprentices) - if(!iscarbon(apprentice.current)) - continue - if(apprentice.current.stat==DEAD) - continue - if(istype(apprentice.current, /obj/item/mmi)) // apprentice is in an MMI, don't count them as alive - continue - apprentices_alive++ - - if(wizards_alive || apprentices_alive || but_wait_theres_more) + for(var/datum/mind/apprentice in apprentices) + if(!iscarbon(apprentice.current)) + continue + if(apprentice.current.stat == DEAD) + continue + if(istype(apprentice.current, /obj/item/mmi)) // apprentice is in an MMI, don't count them as alive + continue return ..() - else - finished = TRUE - return 1 + + finished = TRUE + return TRUE /datum/game_mode/wizard/declare_completion(ragin = 0) if(finished && !ragin) SSticker.mode_result = "wizard loss - wizard killed" to_chat(world, " The wizard[(wizards.len>1)?"s":""] has been killed by the crew! The Space Wizards Federation has been taught a lesson they will not soon forget!") ..() - return 1 + return TRUE /datum/game_mode/proc/auto_declare_completion_wizard() - if(length(wizards)) - var/list/text = list("
the wizards/witches were:") + if(!length(wizards)) + return + var/list/text = list("
the wizards/witches were:") - for(var/datum/mind/wizard in wizards) + for(var/datum/mind/wizard in wizards) - text += "
[wizard.get_display_key()] was [wizard.name] (" - if(wizard.current) - if(wizard.current.stat == DEAD) - text += "died" - else - text += "survived" - if(wizard.current.real_name != wizard.name) - text += " as [wizard.current.real_name]" + text += "
[wizard.get_display_key()] was [wizard.name] (" + if(wizard.current) + if(wizard.current.stat == DEAD) + text += "died" else - text += "body destroyed" - text += ")" + text += "survived" + if(wizard.current.real_name != wizard.name) + text += " as [wizard.current.real_name]" + else + text += "body destroyed" + text += ")" - var/count = 1 - var/wizardwin = 1 - for(var/datum/objective/objective in wizard.get_all_objectives(include_team = FALSE)) - if(objective.check_completion()) - text += "
Objective #[count]: [objective.explanation_text] Success!" - SSblackbox.record_feedback("nested tally", "wizard_objective", 1, list("[objective.type]", "SUCCESS")) - else - text += "
Objective #[count]: [objective.explanation_text] Fail." - SSblackbox.record_feedback("nested tally", "wizard_objective", 1, list("[objective.type]", "FAIL")) - wizardwin = 0 - count++ - - if(wizard.current && wizard.current.stat!=DEAD && wizardwin) - text += "
The wizard was successful!" - SSblackbox.record_feedback("tally", "wizard_success", 1, "SUCCESS") + var/count = 1 + var/wizardwin = 1 + for(var/datum/objective/objective in wizard.get_all_objectives(include_team = FALSE)) + if(objective.check_completion()) + text += "
Objective #[count]: [objective.explanation_text] Success!" + SSblackbox.record_feedback("nested tally", "wizard_objective", 1, list("[objective.type]", "SUCCESS")) else - text += "
The wizard has failed!" - SSblackbox.record_feedback("tally", "wizard_success", 1, "FAIL") - if(wizard.spell_list) - text += "
[wizard.name] used the following spells: " - var/i = 1 - for(var/obj/effect/proc_holder/spell/S in wizard.spell_list) - text += "[S.name]" - if(wizard.spell_list.len > i) - text += ", " - i++ - text += "
" + text += "
Objective #[count]: [objective.explanation_text] Fail." + SSblackbox.record_feedback("nested tally", "wizard_objective", 1, list("[objective.type]", "FAIL")) + wizardwin = 0 + count++ - return text.Join("") + if(wizard.current && wizard.current.stat != DEAD && wizardwin) + text += "
The wizard was successful!" + SSblackbox.record_feedback("tally", "wizard_success", 1, "SUCCESS") + else + text += "
The wizard has failed!" + SSblackbox.record_feedback("tally", "wizard_success", 1, "FAIL") + if(wizard.spell_list) + text += "
[wizard.name] used the following spells: " + text += english_list(wizard.spell_list) + + text += "
" + + return text.Join("") //OTHER PROCS //To batch-remove wizard spells. Linked to mind.dm -/mob/proc/spellremove(mob/M) +/mob/proc/spellremove() if(!mind) return for(var/obj/effect/proc_holder/spell/spell_to_remove in mind.spell_list) @@ -249,26 +127,10 @@ mind.spell_list -= spell_to_remove //To batch-remove mob spells. -/mob/proc/mobspellremove(mob/M) +/mob/proc/mobspellremove() for(var/obj/effect/proc_holder/spell/spell_to_remove in mob_spell_list) qdel(spell_to_remove) mob_spell_list -= spell_to_remove -/*Checks if the wizard can cast spells. -Made a proc so this is not repeated 14 (or more) times.*/ -/mob/proc/casting() -//Removed the stat check because not all spells require clothing now. - if(!istype(usr:wear_suit, /obj/item/clothing/suit/wizrobe)) - to_chat(usr, "I don't feel strong enough without my robe.") - return 0 - if(!istype(usr:shoes, /obj/item/clothing/shoes/sandal)) - to_chat(usr, "I don't feel strong enough without my sandals.") - return 0 - if(!istype(usr:head, /obj/item/clothing/head/wizard)) - to_chat(usr, "I don't feel strong enough without my hat.") - return 0 - else - return 1 - -/proc/iswizard(mob/living/M as mob) - return istype(M) && M.mind && SSticker && SSticker.mode && ((M.mind in SSticker.mode.wizards) || (M.mind in SSticker.mode.apprentices)) +/proc/iswizard(mob/living/M) + return istype(M) && M.mind?.has_antag_datum(/datum/antagonist/wizard) diff --git a/code/game/objects/items/weapons/dice.dm b/code/game/objects/items/weapons/dice.dm index a7f4fc10780..d3495458b8f 100644 --- a/code/game/objects/items/weapons/dice.dm +++ b/code/game/objects/items/weapons/dice.dm @@ -150,7 +150,7 @@ /obj/item/dice/d20/fate/diceroll(mob/user) . = ..() if(!used) - if(!ishuman(user) || !user.mind || (user.mind in SSticker.mode.wizards)) + if(!ishuman(user) || !user.mind || iswizard(user)) to_chat(user, "You feel the magic of the dice is restricted to ordinary humans!") return @@ -163,7 +163,7 @@ addtimer(CALLBACK(src, PROC_REF(effect), user, .), 1 SECONDS) /obj/item/dice/d20/fate/equipped(mob/user, slot) - if(!ishuman(user) || !user.mind || (user.mind in SSticker.mode.wizards)) + if(!ishuman(user) || !user.mind || iswizard(user)) to_chat(user, "You feel the magic of the dice is restricted to ordinary humans! You should leave it alone.") user.unEquip(src) diff --git a/code/game/objects/items/weapons/staff.dm b/code/game/objects/items/weapons/staff.dm index 8a749cd4179..255b2d4cfe1 100644 --- a/code/game/objects/items/weapons/staff.dm +++ b/code/game/objects/items/weapons/staff.dm @@ -58,7 +58,7 @@ ..() /obj/item/staff/broom/dropped(mob/user) - if((user.mind in SSticker.mode.wizards) && user.flying) + if(iswizard(user) && user.flying) user.flying = FALSE ..() diff --git a/code/modules/admin/misc_admin_procs.dm b/code/modules/admin/misc_admin_procs.dm index 81de0ed78b3..35b1a6c8121 100644 --- a/code/modules/admin/misc_admin_procs.dm +++ b/code/modules/admin/misc_admin_procs.dm @@ -647,9 +647,9 @@ GLOBAL_VAR_INIT(nologevent, 0) antag_list += "Cultist" if(M.mind in SSticker.mode.syndicates) antag_list += "Nuclear Operative" - if(M.mind in SSticker.mode.wizards) + if(iswizard(M)) antag_list += "Wizard" - if(M.mind in SSticker.mode.changelings) + if(ischangeling(M)) antag_list += "Changeling" if(M.mind in SSticker.mode.abductors) antag_list += "Abductor" diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index af3031c6805..e9801ac73f9 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -147,10 +147,11 @@ candidates -= selected var/mob/living/carbon/human/new_character = makeBody(selected) - new_character.mind.make_Wizard() + new_character.mind.add_antag_datum(/datum/antagonist/wizard) + new_character.forceMove(pick(GLOB.wizardstart)) dust_if_respawnable(selected) - return 1 - return 0 + return TRUE + return FALSE /datum/admins/proc/makeCult() diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index beb312f2dc4..335b6bd6ea2 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -455,9 +455,11 @@ Traitors and the like can also be revived with the previous role mostly intact. else new_character.mind.add_antag_datum(/datum/antagonist/traitor) if("Wizard") - new_character.loc = pick(GLOB.wizardstart) + new_character.forceMove(pick(GLOB.wizardstart)) //ticker.mode.learn_basic_spells(new_character) - SSticker.mode.equip_wizard(new_character) + var/datum/antagonist/wizard/wizard = new_character.mind.has_antag_datum(/datum/antagonist/wizard) + if(istype(wizard)) + wizard.equip_wizard() if("Syndicate") var/obj/effect/landmark/synd_spawn = locate("landmark*Syndicate-Spawn") if(synd_spawn) diff --git a/code/modules/antagonists/wizard/datum_apprentice.dm b/code/modules/antagonists/wizard/datum_apprentice.dm new file mode 100644 index 00000000000..a638a34c2da --- /dev/null +++ b/code/modules/antagonists/wizard/datum_apprentice.dm @@ -0,0 +1,102 @@ +/datum/antagonist/wizard/apprentice + name = "Wizard Apprentice" + special_role = SPECIAL_ROLE_WIZARD_APPRENTICE + antag_hud_name = "apprentice" + antag_datum_blacklist = list(/datum/antagonist/wizard/construct) + + /// Temporary reference to a mob for purposes of objectives, and general text for the apprentice. + var/mob/living/my_teacher + /// The class type of this apprentice, + var/class_type + +/datum/antagonist/wizard/apprentice/greet() + . = ..() + . += "You are [my_teacher.real_name]'s apprentice! You are bound by magic contract to follow [my_teacher.p_their()] orders and help [my_teacher.p_them()] in accomplishing [my_teacher.p_their()] goals." + +/datum/antagonist/wizard/apprentice/give_objectives() + var/datum/objective/protect/new_objective = new /datum/objective/protect + new_objective.target = my_teacher.mind + new_objective.explanation_text = "Protect and obey [my_teacher.real_name], your teacher." + add_antag_objective(new_objective) + +/datum/antagonist/wizard/apprentice/on_gain() + . = ..() + my_teacher = null // all uses of my_teacher come before this, so lets clean up the reference. + +/datum/antagonist/wizard/apprentice/add_owner_to_gamemode() + SSticker.mode.apprentices |= owner + +/datum/antagonist/wizard/apprentice/remove_owner_from_gamemode() + SSticker.mode.apprentices -= owner + +/datum/antagonist/wizard/apprentice/equip_wizard() + if(!class_type) + CRASH("/datum/antagonist/wizard/apprentice was never assigned a class_type") + var/mob/living/carbon/human/new_wiz = owner.current + new_wiz.equip_to_slot_or_del(new /obj/item/radio/headset(new_wiz), SLOT_HUD_LEFT_EAR) + if(class_type == "stealth") + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/under/color/grey(new_wiz), SLOT_HUD_JUMPSUIT) + else + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/under/color/lightpurple(new_wiz), SLOT_HUD_JUMPSUIT) + new_wiz.equip_to_slot_or_del(new /obj/item/storage/backpack(new_wiz), SLOT_HUD_BACK) + new_wiz.equip_to_slot_or_del(new /obj/item/storage/box(new_wiz), SLOT_HUD_IN_BACKPACK) + new_wiz.equip_to_slot_or_del(new /obj/item/teleportation_scroll/apprentice(new_wiz), SLOT_HUD_RIGHT_STORE) + + var/list/messages = list() + switch(class_type) + if("fire") + new_wiz.mind.AddSpell(new /obj/effect/proc_holder/spell/fireball/apprentice(null)) + new_wiz.mind.AddSpell(new /obj/effect/proc_holder/spell/sacred_flame(null)) + ADD_TRAIT(new_wiz, TRAIT_RESISTHEAT, MAGIC_TRAIT) + ADD_TRAIT(new_wiz, TRAIT_RESISTHIGHPRESSURE, MAGIC_TRAIT) + new_wiz.mind.AddSpell(new /obj/effect/proc_holder/spell/ethereal_jaunt(null)) + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(new_wiz), SLOT_HUD_SHOES) + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/red(new_wiz), SLOT_HUD_OUTER_SUIT) + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/red(new_wiz), SLOT_HUD_HEAD) + messages += "Your service has not gone unrewarded. Under the tutelage of [my_teacher.real_name], you've acquired proficiency in the fundamentals of Firebending, enabling you to cast spells like Fireball, Sacred Flame, and Ethereal Jaunt." + messages += "You are immune to fire, but you are NOT immune to the explosions caused by your fireballs. Neither is your teacher, for that matter. Be careful!" + if("translocation") + new_wiz.mind.AddSpell(new /obj/effect/proc_holder/spell/area_teleport/teleport(null)) + new_wiz.mind.AddSpell(new /obj/effect/proc_holder/spell/turf_teleport/blink(null)) + new_wiz.mind.AddSpell(new /obj/effect/proc_holder/spell/ethereal_jaunt(null)) + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(new_wiz), SLOT_HUD_SHOES) + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(new_wiz), SLOT_HUD_OUTER_SUIT) + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(new_wiz), SLOT_HUD_HEAD) + messages += "Your service has not gone unrewarded. While studying under [my_teacher.real_name], you mastered reality-bending mobility spells, allowing you to cast Teleport, Blink, and Ethereal Jaunt." + if("restoration") + new_wiz.mind.AddSpell(new /obj/effect/proc_holder/spell/charge(null)) + new_wiz.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe/knock(null)) + var/obj/effect/proc_holder/spell/return_to_teacher/S = new /obj/effect/proc_holder/spell/return_to_teacher(null) + S.teacher = my_teacher.mind + new_wiz.mind.AddSpell(S) + new_wiz.equip_to_slot_or_del(new /obj/item/gun/magic/staff/healing(new_wiz), SLOT_HUD_RIGHT_HAND) + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal/marisa(new_wiz), SLOT_HUD_SHOES) + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/marisa(new_wiz), SLOT_HUD_OUTER_SUIT) + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/marisa(new_wiz), SLOT_HUD_HEAD) + messages += "Your service has not gone unrewarded. Under the guidance of [my_teacher.real_name], you've acquired life-saving survival spells. You can now cast Charge and Knock, and possess the ability to teleport back to your mentor." + messages += "Your Charge spell can be used to recharge your Staff of Healing or reduce the cooldowns of your teacher, if you are grabbing them with empty hands." + if("stealth") + new_wiz.mind.AddSpell(new /obj/effect/proc_holder/spell/mind_transfer(null)) + new_wiz.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe/knock(null)) + new_wiz.mind.AddSpell(new /obj/effect/proc_holder/spell/fireball/toolbox(null)) + new_wiz.mind.AddSpell(new /obj/effect/proc_holder/spell/disguise_self(null)) + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(new_wiz), SLOT_HUD_SHOES) + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/mask/gas(new_wiz), SLOT_HUD_WEAR_MASK) + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/gloves/color/yellow(new_wiz), SLOT_HUD_GLOVES) + new_wiz.equip_to_slot_or_del(new /obj/item/storage/belt/utility/full(new_wiz), SLOT_HUD_BELT) + messages += "Your service has not gone unrewarded. Under the mentorship of [my_teacher.real_name], you've mastered stealthy, robeless spells. You can now cast Mindswap, Knock, Homing Toolbox, and Disguise Self without the need for wizard robes." + if("honk") + new_wiz.mind.AddSpell(new /obj/effect/proc_holder/spell/touch/banana/apprentice(null)) + new_wiz.mind.AddSpell(new /obj/effect/proc_holder/spell/ethereal_jaunt(null)) + new_wiz.mind.AddSpell(new /obj/effect/proc_holder/spell/summonitem(null)) + new_wiz.equip_to_slot_or_del(new /obj/item/gun/magic/staff/slipping(new_wiz), SLOT_HUD_RIGHT_HAND) + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/shoes/clown_shoes/magical/nodrop(new_wiz), SLOT_HUD_SHOES) + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/clown(new_wiz), SLOT_HUD_OUTER_SUIT) + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/clown(new_wiz), SLOT_HUD_HEAD) + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clownwiz(new_wiz), SLOT_HUD_WEAR_MASK) + messages += "Your dedication pays off! Under [my_teacher.real_name]'s guidance, you've mastered magical honkings, seamlessly casting spells like Banana Touch, Ethereal Jaunt, and Instant Summons, while skillfully wielding a Staff of Slipping. Honk!" + + return messages + +/datum/antagonist/wizard/apprentice/full_on_wizard() + return FALSE diff --git a/code/modules/antagonists/wizard/datum_wiz_construct.dm b/code/modules/antagonists/wizard/datum_wiz_construct.dm new file mode 100644 index 00000000000..d678a0fc209 --- /dev/null +++ b/code/modules/antagonists/wizard/datum_wiz_construct.dm @@ -0,0 +1,36 @@ +/datum/antagonist/wizard/construct + name = "Magical Construct" + special_role = SPECIAL_ROLE_WIZARD_APPRENTICE + antag_hud_name = "apprentice" + antag_datum_blacklist = list(/datum/antagonist/wizard/apprentice) + + should_equip_wizard = FALSE + should_name_pick = FALSE + /// Temporary reference to a mob for purposes of objectives, and general text for the apprentice. + var/mob/living/my_creator + +/datum/antagonist/wizard/construct/greet() + . = ..() + . += "You are [my_creator.real_name]'s construct! You are bound by magic to follow [my_creator.p_their()] orders and help [my_creator.p_them()] in accomplishing [my_creator.p_their()] goals." + +/datum/antagonist/wizard/construct/give_objectives() + var/datum/objective/protect/new_objective = new /datum/objective/protect + new_objective.target = my_creator.mind + new_objective.explanation_text = "Protect and obey [my_creator.real_name], your creator." + add_antag_objective(new_objective) + +/datum/antagonist/wizard/construct/on_gain() + . = ..() + my_creator = null // all uses of my_creator come before this, so lets clean up the reference. + +/datum/antagonist/wizard/construct/add_owner_to_gamemode() + SSticker.mode.apprentices |= owner + +/datum/antagonist/wizard/construct/remove_owner_from_gamemode() + SSticker.mode.apprentices -= owner + +/datum/antagonist/wizard/construct/equip_wizard() + return + +/datum/antagonist/wizard/construct/full_on_wizard() + return FALSE diff --git a/code/modules/antagonists/wizard/datum_wizard.dm b/code/modules/antagonists/wizard/datum_wizard.dm new file mode 100644 index 00000000000..90a5fb17e85 --- /dev/null +++ b/code/modules/antagonists/wizard/datum_wizard.dm @@ -0,0 +1,118 @@ +//Greetings from the Wizard Federation!! +/datum/antagonist/wizard + name = "Wizard" + roundend_category = "wizards" + job_rank = ROLE_WIZARD + special_role = SPECIAL_ROLE_WIZARD + give_objectives = TRUE + antag_hud_name = "hudwizard" + antag_hud_type = ANTAG_HUD_WIZ + clown_gain_text = "Your new magical powers has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself." + clown_removal_text = "You lose your magical powers and return to your own clumsy, clownish self." + wiki_page_name = "Wizard" + var/should_equip_wizard = TRUE + var/should_name_pick = TRUE + var/additional_text + +/datum/antagonist/wizard/on_gain() + . = ..() + owner.current.faction -= "neutral" + owner.current.faction |= "wizard" + owner.offstation_role = TRUE + if(should_name_pick) + name_wizard() + SEND_SOUND(owner.current, 'sound/ambience/antag/ragesmages.ogg') + +/datum/antagonist/wizard/greet() + . = ..() + if(additional_text) + . += additional_text + +/datum/antagonist/wizard/finalize_antag() + var/list/messages = list() + if(should_equip_wizard) + messages = equip_wizard() + if(full_on_wizard()) + messages += "Remember to bring your magical Mugwort Tea, it will slowly heal you when you drink it." + return messages + +/datum/antagonist/wizard/detach_from_owner() + owner.current.faction |= "neutral" + owner.current.faction -= "wizard" + owner.offstation_role = FALSE + owner.current.spellremove() + return ..() + +/datum/antagonist/wizard/farewell() + if(owner?.current) + to_chat(owner.current, "You have been brainwashed! You are no longer a [name]!") + +/datum/antagonist/wizard/add_owner_to_gamemode() + SSticker.mode.wizards |= owner + +/datum/antagonist/wizard/remove_owner_from_gamemode() + SSticker.mode.wizards -= owner + +/datum/antagonist/wizard/give_objectives() + add_antag_objective(/datum/objective/wizchaos) + +/datum/antagonist/wizard/proc/name_wizard() + INVOKE_ASYNC(src, PROC_REF(_name_wizard)) + +/datum/antagonist/wizard/proc/_name_wizard() + PRIVATE_PROC(TRUE) + var/wizard_name_first = pick(GLOB.wizard_first) + var/wizard_name_second = pick(GLOB.wizard_second) + var/randomname = "[wizard_name_first] [wizard_name_second]" + var/newname = sanitize(copytext(input(owner.current, "You are the Space Wizard. Would you like to change your name to something else?", "Name change", randomname) as null|text,1,MAX_NAME_LEN)) + + if(!newname) + newname = randomname + owner.current.rename_character(owner.current.real_name, newname) + +/datum/antagonist/wizard/proc/equip_wizard() + if(!ishuman(owner.current)) + return + var/mob/living/carbon/human/new_wiz = owner.current + + //So zards properly get their items when they are admin-made. + qdel(new_wiz.wear_suit) + qdel(new_wiz.head) + qdel(new_wiz.shoes) + qdel(new_wiz.r_hand) + qdel(new_wiz.r_store) + qdel(new_wiz.l_store) + + if(isplasmaman(new_wiz)) + new_wiz.equipOutfit(new /datum/outfit/plasmaman/wizard) + new_wiz.internal = new_wiz.r_hand + new_wiz.update_action_buttons_icon() + else + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/under/color/lightpurple(new_wiz), SLOT_HUD_JUMPSUIT) + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(new_wiz), SLOT_HUD_HEAD) + new_wiz.dna.species.after_equip_job(null, new_wiz) + new_wiz.rejuvenate() //fix any damage taken by naked vox/plasmamen/etc while round setups + new_wiz.equip_to_slot_or_del(new /obj/item/radio/headset(new_wiz), SLOT_HUD_LEFT_EAR) + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(new_wiz), SLOT_HUD_SHOES) + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(new_wiz), SLOT_HUD_OUTER_SUIT) + new_wiz.equip_to_slot_or_del(new /obj/item/storage/backpack/satchel(new_wiz), SLOT_HUD_BACK) + if(new_wiz.dna.species.speciesbox) + new_wiz.equip_to_slot_or_del(new new_wiz.dna.species.speciesbox(new_wiz), SLOT_HUD_IN_BACKPACK) + else + new_wiz.equip_to_slot_or_del(new /obj/item/storage/box/survival(new_wiz), SLOT_HUD_IN_BACKPACK) + new_wiz.equip_to_slot_or_del(new /obj/item/teleportation_scroll(new_wiz), SLOT_HUD_RIGHT_STORE) + var/obj/item/spellbook/spellbook = new /obj/item/spellbook(new_wiz) + spellbook.owner = new_wiz + new_wiz.equip_to_slot_or_del(spellbook, SLOT_HUD_LEFT_HAND) + + var/list/reading = list() + reading += "You will find a list of available spells in your spell book. Choose your magic arsenal carefully." + reading += "The spellbook is bound to you, and others cannot use it." + reading += "In your pockets you will find a teleport scroll. Use it as needed." + new_wiz.mind.store_memory("Remember: do not forget to prepare your spells.") + new_wiz.update_icons() + new_wiz.gene_stability += DEFAULT_GENE_STABILITY //magic + return reading + +/datum/antagonist/wizard/proc/full_on_wizard() + return TRUE diff --git a/code/modules/clothing/shoes/magboots.dm b/code/modules/clothing/shoes/magboots.dm index 25f49a27a8b..fb1bce27ee5 100644 --- a/code/modules/clothing/shoes/magboots.dm +++ b/code/modules/clothing/shoes/magboots.dm @@ -155,15 +155,16 @@ magical = TRUE /obj/item/clothing/shoes/magboots/wizard/attack_self(mob/user) - if(user) - if(user.mind in SSticker.mode.wizards) - if(magpulse) //faint blue light when shoes are turned on gives a reason to turn them off when not needed in maint - set_light(0) - else - set_light(2, 1, LIGHT_COLOR_LIGHTBLUE) - ..() - else - to_chat(user, "You poke the gem on [src]. Nothing happens.") + if(!user) + return + if(!iswizard(user)) + to_chat(user, "You poke the gem on [src]. Nothing happens.") + return + if(magpulse) //faint blue light when shoes are turned on gives a reason to turn them off when not needed in maint + set_light(0) + else + set_light(2, 1, LIGHT_COLOR_LIGHTBLUE) + ..() /obj/item/clothing/shoes/magboots/gravity diff --git a/code/modules/mob/dead/observer/orbit.dm b/code/modules/mob/dead/observer/orbit.dm index 715f18cccc5..bd621a2f4cf 100644 --- a/code/modules/mob/dead/observer/orbit.dm +++ b/code/modules/mob/dead/observer/orbit.dm @@ -111,8 +111,6 @@ if(SSticker && SSticker.mode) other_antags += list( "Blob" = (mind.special_role == SPECIAL_ROLE_BLOB), - "Wizard" = (mind in SSticker.mode.wizards), - "Wizard's Apprentice" = (mind in SSticker.mode.apprentices), "Nuclear Operative" = (mind in SSticker.mode.syndicates), "Abductor" = (mind in SSticker.mode.abductors) ) diff --git a/code/modules/mob/living/carbon/human/species/grey.dm b/code/modules/mob/living/carbon/human/species/grey.dm index 9902aaf0c1b..21de51a0324 100644 --- a/code/modules/mob/living/carbon/human/species/grey.dm +++ b/code/modules/mob/living/carbon/human/species/grey.dm @@ -66,17 +66,18 @@ /datum/species/grey/after_equip_job(datum/job/J, mob/living/carbon/human/H) var/translator_pref = H.client.prefs.active_character.speciesprefs - if(translator_pref || ((ismindshielded(H) || J.job_department_flags & DEP_FLAG_COMMAND) && HAS_TRAIT(H, TRAIT_WINGDINGS))) - if(J.title == "Mime") - return - if(J.title == "Clown") - var/obj/item/organ/internal/cyberimp/brain/speech_translator/clown/implant = new - implant.insert(H) - else - var/obj/item/organ/internal/cyberimp/brain/speech_translator/implant = new - implant.insert(H) - if(!translator_pref) - to_chat(H, "A speech translator implant has been installed due to your role on the station.") + if(translator_pref || ((ismindshielded(H) || J?.job_department_flags & DEP_FLAG_COMMAND) && HAS_TRAIT(H, TRAIT_WINGDINGS))) + if(istype(J)) + if(J.title == "Mime") + return + if(J.title == "Clown") + var/obj/item/organ/internal/cyberimp/brain/speech_translator/clown/implant = new + implant.insert(H) + return + var/obj/item/organ/internal/cyberimp/brain/speech_translator/implant = new + implant.insert(H) + if(!translator_pref && istype(J)) + to_chat(H, "A speech translator implant has been installed due to your role on the station.") /datum/species/grey/handle_reagents(mob/living/carbon/human/H, datum/reagent/R) if(R.id == "sacid" || R.id == "facid") diff --git a/code/modules/mob/living/silicon/silicon_login.dm b/code/modules/mob/living/silicon/silicon_login.dm index 6592a4d6a33..3786144abc6 100644 --- a/code/modules/mob/living/silicon/silicon_login.dm +++ b/code/modules/mob/living/silicon/silicon_login.dm @@ -3,7 +3,7 @@ if(mind && SSticker && SSticker.mode) SSticker.mode.remove_revolutionary(mind, 1) mind.remove_antag_datum(/datum/antagonist/cultist) - SSticker.mode.remove_wizard(mind) + mind.remove_antag_datum(/datum/antagonist/wizard) mind.remove_antag_datum(/datum/antagonist/changeling) mind.remove_antag_datum(/datum/antagonist/vampire) SSticker.mode.remove_abductor(mind) diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index 0889c60fb81..b02d0a309f7 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -48,11 +48,13 @@ /mob/living/simple_animal/hostile/construct/Destroy() mind?.remove_antag_datum(/datum/antagonist/cultist, silent_removal = TRUE) + mind?.remove_antag_datum(/datum/antagonist/wizard/construct, silent_removal = TRUE) remove_held_body() return ..() /mob/living/simple_animal/hostile/construct/death(gibbed) mind?.remove_antag_datum(/datum/antagonist/cultist, silent_removal = TRUE) + mind?.remove_antag_datum(/datum/antagonist/wizard/construct, silent_removal = TRUE) if(held_body) // Null check for empty bodies held_body.forceMove(get_turf(src)) SSticker.mode?.cult_team?.add_cult_immunity(held_body) diff --git a/code/modules/mob/living/simple_animal/shade.dm b/code/modules/mob/living/simple_animal/shade.dm index 17e52b478a8..ca63f9a1217 100644 --- a/code/modules/mob/living/simple_animal/shade.dm +++ b/code/modules/mob/living/simple_animal/shade.dm @@ -36,6 +36,7 @@ /mob/living/simple_animal/shade/Destroy() mind?.remove_antag_datum(/datum/antagonist/cultist, silent_removal = TRUE) + mind?.remove_antag_datum(/datum/antagonist/wizard/construct, silent_removal = TRUE) return ..() /mob/living/simple_animal/shade/attackby(obj/item/O, mob/user) //Marker -Agouri diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 20014d64459..b2b39500d14 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -7,8 +7,8 @@ s_active.close(src) QDEL_NULL(hud_used) if(mind && mind.current == src) - spellremove(src) - mobspellremove(src) + spellremove() + mobspellremove() QDEL_LIST_CONTENTS(viruses) QDEL_LIST_CONTENTS(actions) for(var/alert in alerts) diff --git a/paradise.dme b/paradise.dme index 0fe422233ef..9109a7e1c8d 100644 --- a/paradise.dme +++ b/paradise.dme @@ -1468,6 +1468,9 @@ #include "code\modules\antagonists\vampire\vampire_powers\hemomancer_powers.dm" #include "code\modules\antagonists\vampire\vampire_powers\umbrae_powers.dm" #include "code\modules\antagonists\vampire\vampire_powers\vampire_powers.dm" +#include "code\modules\antagonists\wizard\datum_apprentice.dm" +#include "code\modules\antagonists\wizard\datum_wiz_construct.dm" +#include "code\modules\antagonists\wizard\datum_wizard.dm" #include "code\modules\arcade\arcade_base.dm" #include "code\modules\arcade\arcade_prize.dm" #include "code\modules\arcade\claw_game.dm"