diff --git a/code/__DEFINES/gamemode.dm b/code/__DEFINES/gamemode.dm index d4c9eebed37..0208c376777 100644 --- a/code/__DEFINES/gamemode.dm +++ b/code/__DEFINES/gamemode.dm @@ -53,6 +53,7 @@ #define SPECIAL_ROLE_MIND_FLAYER "Mind Flayer" #define SPECIAL_ROLE_VAMPIRE_THRALL "Vampire Thrall" #define SPECIAL_ROLE_WIZARD "Wizard" +#define SPECIAL_ROLE_WIZARD_ADEPT "Wizard Adept" #define SPECIAL_ROLE_WIZARD_APPRENTICE "Wizard Apprentice" #define SPECIAL_ROLE_XENOMORPH "Xenomorph" #define SPECIAL_ROLE_XENOMORPH_QUEEN "Xenomorph Queen" diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 21245dc3fde..a696947cbfc 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -420,6 +420,18 @@ . += _memory_edit_role_enabled(ROLE_NINJA) +/datum/mind/proc/memory_edit_wizard_adept(mob/living/carbon/human/H) + . = _memory_edit_header("wizard_adept") + var/datum/antagonist/wizard/wiz = has_antag_datum(/datum/antagonist/wizard/adept) + if(wiz) + . += "WIZARD ADEPT|no" + if(!wiz.has_antag_objectives()) + . += "
Objectives are empty! Randomize!" + else + . += "wizard_adept|NO" + + . += _memory_edit_role_enabled(ROLE_WIZARD) + /datum/mind/proc/memory_edit_mind_flayer(mob/living/carbon/human/H) . = _memory_edit_header("mind_flayer") var/datum/antagonist/mindflayer/flayer = has_antag_datum(/datum/antagonist/mindflayer) @@ -619,6 +631,8 @@ sections["vampire"] = memory_edit_vampire(H) /** SPACE NINJA */ sections["space_ninja"] = memory_edit_space_ninja(H) + /** WIZARD ADEPT **/ + sections["wizard_adept"] = memory_edit_wizard_adept(H) /** MINDFLAYER ***/ sections["mind_flayer"] = memory_edit_mind_flayer(H) /** HERETIC ***/ @@ -1196,6 +1210,19 @@ to_chat(current, "Your training awakens, and a myserious set of gear teleports in around you... You are a Space Ninja!") message_admins("[key_name(usr)] has ninja'd [key_name(current)].") + else if(href_list["wizard_adept"]) + switch(href_list["wizard_adept"]) + if("clear") + if(has_antag_datum(/datum/antagonist/wizard/adept)) + remove_antag_datum(/datum/antagonist/wizard/adept) + log_admin("[key_name(usr)] has de-wizard adept'd [key_name(current)].") + message_admins("[key_name(usr)] has de-wizard adept'd [key_name(current)].") + if("wizard_adept") + make_wizard_adept() + log_admin("[key_name(usr)] has wizard adept'd [key_name(current)].") + to_chat(current, "Your sorcerous mind remembers your spellcasting! You are a Space Wizard Adept!") + message_admins("[key_name(usr)] has wizard adept'd [key_name(current)].") + else if(href_list["vampthrall"]) switch(href_list["vampthrall"]) if("clear") @@ -1858,6 +1885,11 @@ add_antag_datum(/datum/antagonist/space_ninja) SSticker.mode.ninjas |= src +/datum/mind/proc/make_wizard_adept() + if(!has_antag_datum(/datum/antagonist/wizard/adept)) + add_antag_datum(/datum/antagonist/wizard/adept) + SSticker.mode.wizards |= src + /datum/mind/proc/make_heretic() if(!has_antag_datum(/datum/antagonist/heretic)) add_antag_datum(/datum/antagonist/heretic) diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 56390217672..5bfe341dadb 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -72,6 +72,8 @@ var/list/datum/mind/pre_mindflayers = list() /// A list of all minds which have the wizard special role var/list/datum/mind/wizards = list() + /// A list of all minds that are wizard adepts + var/list/datum/mind/adepts = list() /// A list of all minds that are wizard apprentices var/list/datum/mind/apprentices = list() /// A list of all minds that are ninjas diff --git a/code/modules/antagonists/wizard/datum_adept.dm b/code/modules/antagonists/wizard/datum_adept.dm new file mode 100644 index 00000000000..1865c8e828c --- /dev/null +++ b/code/modules/antagonists/wizard/datum_adept.dm @@ -0,0 +1,104 @@ +/datum/antagonist/wizard/adept + name = "Wizard Adept" + special_role = SPECIAL_ROLE_WIZARD_ADEPT + antag_datum_blacklist = list(/datum/antagonist/wizard/construct, /datum/antagonist/wizard/apprentice) + + /// Potential offensive spell list + var/list/offense_spells = list( + /datum/spell/genetic/mutate, + /datum/spell/blind, + /datum/spell/fireball, + /datum/spell/fireball/toolbox, + /datum/spell/sacred_flame, + /datum/spell/rod_form, + /datum/spell/charge_up/bounce/lightning, + /datum/spell/infinite_guns, + ) + /// Potential defensive spell list + var/list/defense_spells = list( + /datum/spell/projectile/magic_missile, + /datum/spell/emplosion/disable_tech, + /datum/spell/forcewall, + /datum/spell/aoe/conjure/timestop, + /datum/spell/aoe/repulse, + /datum/spell/rathens, + ) + /// Potential mobility spell list + var/list/mobility_spells = list( + /datum/spell/turf_teleport/blink, + /datum/spell/area_teleport/teleport, + /datum/spell/ethereal_jaunt, + /datum/spell/spacetime_dist, + /datum/spell/aoe/knock, + ) + /// Potential support spell list + var/list/support_spells = list( + /datum/spell/smoke, + /datum/spell/disguise_self, + /datum/spell/aoe/conjure/summon_cheese, + ) + /// Potential support item list + var/list/support_items = list( + /obj/item/gun/magic/wand/resurrection, + /obj/item/guardiancreator, + /obj/item/tarot_generator/wizard, + /obj/item/gun/magic/wand/fireball, + ) + +/datum/antagonist/wizard/adept/greet() + . = ..() + . += SPAN_DANGER("You are an adept wizard! You are a fully trained wizard, ready to embark on one of your first journeys into the application of space magic!") + +/datum/antagonist/wizard/adept/give_objectives() + var/datum/objective/wizchaos/new_objective = new /datum/objective/wizchaos + new_objective.explanation_text = "Distract, harass, and impede Nanotrasen's crew!" + add_antag_objective(new_objective) + +/datum/antagonist/wizard/adept/equip_wizard() + var/mob/living/carbon/human/new_wiz = owner.current + new_wiz.delete_equipment() + new_wiz.equip_to_slot_or_del(new /obj/item/radio/headset(new_wiz), ITEM_SLOT_LEFT_EAR) + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/under/color/lightpurple(new_wiz), ITEM_SLOT_JUMPSUIT) + new_wiz.equip_to_slot_or_del(new /obj/item/storage/backpack(new_wiz), ITEM_SLOT_BACK) + new_wiz.equip_to_slot_or_del(new /obj/item/teleportation_scroll/apprentice(new_wiz), ITEM_SLOT_RIGHT_POCKET) + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(new_wiz), ITEM_SLOT_SHOES) + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(new_wiz), ITEM_SLOT_OUTER_SUIT) + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(new_wiz), ITEM_SLOT_HEAD) + if(new_wiz.dna.species.speciesbox) + new_wiz.equip_to_slot_or_del(new new_wiz.dna.species.speciesbox(new_wiz), ITEM_SLOT_IN_BACKPACK) + else + new_wiz.equip_to_slot_or_del(new /obj/item/storage/box/survival(new_wiz), ITEM_SLOT_IN_BACKPACK) + if(isvox(new_wiz)) + new_wiz.equip_to_slot_or_del(new /obj/item/clothing/mask/breath/vox/respirator(new_wiz), ITEM_SLOT_MASK) + new_wiz.equip_to_slot_or_del(new /obj/item/tank/internals/emergency_oxygen/double/vox(new_wiz), ITEM_SLOT_RIGHT_HAND) + new_wiz.internal = new_wiz.r_hand + + var/datum/spell/offense = pick(offense_spells) + new_wiz.mind.AddSpell(new offense(null)) + if(offense == /datum/spell/sacred_flame) + ADD_TRAIT(new_wiz, TRAIT_RESISTHEAT, MAGIC_TRAIT) + ADD_TRAIT(new_wiz, TRAIT_RESISTHIGHPRESSURE, MAGIC_TRAIT) + + var/datum/spell/defense = pick(defense_spells) + new_wiz.mind.AddSpell(new defense(null)) + + var/datum/spell/mobility = pick(mobility_spells) + new_wiz.mind.AddSpell(new mobility(null)) + + if(pick(0, 1)) + var/datum/spell/support = pick(support_spells) + new_wiz.mind.AddSpell(new support(null)) + else + var/obj/item/support = pick(support_items) + new_wiz.equip_to_slot_or_del(new support(new_wiz), ITEM_SLOT_IN_BACKPACK) + + new_wiz.rejuvenate() + +/datum/antagonist/wizard/adept/add_owner_to_gamemode() + SSticker.mode.adepts |= owner + +/datum/antagonist/wizard/adept/remove_owner_from_gamemode() + SSticker.mode.adepts -= owner + +/datum/antagonist/wizard/adept/full_on_wizard() + return FALSE diff --git a/code/modules/events/event_container.dm b/code/modules/events/event_container.dm index 8e587c2ad04..b0344b7234c 100644 --- a/code/modules/events/event_container.dm +++ b/code/modules/events/event_container.dm @@ -219,6 +219,7 @@ GLOBAL_LIST_EMPTY(event_last_fired) new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/disease_outbreak, 8, TRUE), new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/revenant, 9), new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/space_ninja, 9), + new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/wizard_adept, 5), new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/spawn_morph, 16, is_one_shot = TRUE), new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/aurora_caelus, 5, is_one_shot = TRUE), //new /datum/event_meta(EVENT_LEVEL_MAJOR, /datum/event/spawn_pulsedemon, 20, is_one_shot = TRUE) diff --git a/code/modules/events/wizard/wizard_adept.dm b/code/modules/events/wizard/wizard_adept.dm new file mode 100644 index 00000000000..0df34a3a173 --- /dev/null +++ b/code/modules/events/wizard/wizard_adept.dm @@ -0,0 +1,83 @@ +/datum/event/wizard_adept + name = "Wizard Adept" + role_weights = list(ASSIGNMENT_SECURITY = 2) + role_requirements = list(ASSIGNMENT_CREW = 20, ASSIGNMENT_SECURITY = 2) + nominal_severity = EVENT_LEVEL_MAJOR + +/datum/event/wizard_adept/start() + INVOKE_ASYNC(src, PROC_REF(poll_wiz_adept)) + +/datum/event/wizard_adept/proc/poll_wiz_adept(list/potential_wizards) + var/list/candidates = list() + if(!potential_wizards) + candidates = SSghost_spawns.poll_candidates("Do you want to play as a Wizard Adept?", ROLE_WIZARD, TRUE) + else + candidates = potential_wizards + if(!length(candidates)) + kill() + return + var/mob/new_wizard + while(length(candidates)) + new_wizard = pick_n_take(candidates) + if(jobban_isbanned(new_wizard, ROLE_TRAITOR)) + continue + break + if(!new_wizard) + kill() + return + + var/gender_pref = input_async(new_wizard, "Please select a gender (10 seconds):", list("Male", "Female")) + addtimer(CALLBACK(src, PROC_REF(get_species), candidates, new_wizard, gender_pref), 10 SECONDS) + +/datum/event/wizard_adept/proc/get_species(list/potential_wizards, mob/new_wizard, datum/async_input/gender_pref) + gender_pref.close() + var/sel_gender = gender_pref.result + if(!sel_gender) // Player was AFK and did not select a gender + poll_wiz_adept(potential_wizards) + return + var/species_pref = input_async(new_wizard, "Please select a species (10 seconds):", list("Human", "Tajaran", "Skrell", "Unathi", "Diona", "Vulpkanin", "Nian", "Drask", "Kidan", "Grey", "Skkulakin", "Vox", "Slime", "Machine", "Random")) + addtimer(CALLBACK(src, PROC_REF(create_ninja), potential_wizards, new_wizard, sel_gender, species_pref), 10 SECONDS) + +/datum/event/wizard_adept/proc/create_ninja(list/potential_wizards, mob/new_wizard, sel_gender, datum/async_input/species_pref) + species_pref.close() + var/sel_species = species_pref.result + if(!sel_species) // Player was AFK and did not select a species + poll_wiz_adept(potential_wizards) + return + if(!new_wizard || !new_wizard.client) + poll_wiz_adept(potential_wizards) + return + + if(!length(GLOB.wizardstart)) + message_admins("Unable to spawn wizard adept - no valid spawn locations.") + return + + var/mob/living/carbon/human/M = new(pick(GLOB.wizardstart)) + + M.ckey = new_wizard.ckey + dust_if_respawnable(new_wizard) + + if(sel_gender == "Male") + M.change_gender(MALE) + M.change_body_type(MALE) + else + M.change_gender(FEMALE) + M.change_body_type(FEMALE) + + if(sel_species == "Random") + sel_species = pick("Human", "Tajaran", "Skrell", "Unathi", "Diona", "Vulpkanin", "Nian", "Drask", "Kidan", "Grey", "Skkulakin", "Vox", "Slime", "Machine") + if(sel_species == "Slime") + sel_species = "Slime People" + var/datum/species/S = GLOB.all_species[sel_species] + var/species = S.type + M.set_species(species, TRUE) + M.dna.ready_dna(M) + M.cleanSE() + M.overeatduration = 0 + M.age = rand(30, 50) + M.regenerate_icons() + + M.mind = new + M.mind.bind_to(M) + M.mind.set_original_mob(M) + M.mind.make_wizard_adept() diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index 4fab420b4d4..cc9696833e0 100644 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -583,7 +583,7 @@ /datum/reagent/consumable/mugwort/on_mob_life(mob/living/M) var/update_flags = STATUS_UPDATE_NONE - if(ishuman(M) && M.mind?.special_role == SPECIAL_ROLE_WIZARD) + if(ishuman(M) && (M.mind?.special_role == SPECIAL_ROLE_WIZARD || M.mind?.special_role == SPECIAL_ROLE_WIZARD_ADEPT)) update_flags |= M.adjustToxLoss(-1 * REAGENTS_EFFECT_MULTIPLIER, FALSE) update_flags |= M.adjustOxyLoss(-1 * REAGENTS_EFFECT_MULTIPLIER, FALSE) update_flags |= M.adjustBruteLoss(-1 * REAGENTS_EFFECT_MULTIPLIER, FALSE) diff --git a/paradise.dme b/paradise.dme index 7e7300afa9c..63db91f3361 100644 --- a/paradise.dme +++ b/paradise.dme @@ -1901,6 +1901,7 @@ #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_adept.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" @@ -2317,6 +2318,7 @@ #include "code\modules\events\shuttle_loan\shuttle_loan_datum.dm" #include "code\modules\events\shuttle_loan\shuttle_loan_event.dm" #include "code\modules\events\wizard\ghost_wizard_spells.dm" +#include "code\modules\events\wizard\wizard_adept.dm" #include "code\modules\fish\fish_eggs.dm" #include "code\modules\fish\fish_items.dm" #include "code\modules\fish\fish_types.dm"