From ed294532c6b716cb3a0d38bb4ffbd2aacef1322e Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Fri, 14 Jul 2023 19:10:55 +0200 Subject: [PATCH] [MIRROR] transform the paper wizard from a simple to a basic [MDB IGNORE] (#22452) * transform the paper wizard from a simple to a basic (#76688) ## About The Pull Request i transfered paper wizard from simple to a basic and i also gaved him new fetures he can go and do. now when he will go and walked when he walks there will be a paper effects when he goes to walk. also he will he will now go to look for paperes on the floor and then he will write stuff inside the paper, so a player can maybe distracted the wizard with a paper because the wizard will stop atacked him for a bit until he finished writted stuff inside the paper. i follow the instrucions in the learn-ai md to maked this to a new ai subtree behavier. ## Why It's Good For The Game the paper wizard is now a basic so he is a better ai and he also have more feture to gaved him depth mechanics ## Changelog :cl: refactor: paper wizard have been refactored, please report any bugs/unintended behavior refactor: refacted the datum/elememt/trial to an bespoken element add: paper wizard now have effects when he walking and he will now go and look for paperes and write stuff in them /:cl: * transform the paper wizard from a simple to a basic --------- Co-authored-by: Ben10Omintrix <138636438+Ben10Omintrix@users.noreply.github.com> --- .../SpaceRuins/originalcontent.dmm | 2 +- code/__DEFINES/ai.dm | 9 + .../basic_ai_behaviors/write_on_paper.dm | 16 ++ .../basic_subtrees/find_paper_and_write.dm | 23 ++ code/datums/elements/effect_trail.dm | 10 +- .../heretic/knowledge/cosmic_lore.dm | 4 +- .../antagonists/heretic/magic/star_blast.dm | 2 +- .../antagonists/heretic/magic/star_touch.dm | 4 +- .../mob/living/basic/heretic/star_gazer.dm | 2 +- .../paper_wizard/paper_abilities.dm | 90 ++++++++ .../space_fauna/paper_wizard/paper_wizard.dm | 196 ++++++++++++++++ .../hostile/bosses/paperwizard.dm | 210 ------------------ .../unit_tests/simple_animal_freeze.dm | 2 - tgstation.dme | 5 +- .../Scripts/76688_paper_wizard.txt | 2 + 15 files changed, 352 insertions(+), 225 deletions(-) create mode 100644 code/datums/ai/basic_mobs/basic_ai_behaviors/write_on_paper.dm create mode 100644 code/datums/ai/basic_mobs/basic_subtrees/find_paper_and_write.dm create mode 100644 code/modules/mob/living/basic/space_fauna/paper_wizard/paper_abilities.dm create mode 100644 code/modules/mob/living/basic/space_fauna/paper_wizard/paper_wizard.dm delete mode 100644 code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm create mode 100644 tools/UpdatePaths/Scripts/76688_paper_wizard.txt diff --git a/_maps/RandomRuins/SpaceRuins/originalcontent.dmm b/_maps/RandomRuins/SpaceRuins/originalcontent.dmm index 678f17b1739..ea2ca46c092 100644 --- a/_maps/RandomRuins/SpaceRuins/originalcontent.dmm +++ b/_maps/RandomRuins/SpaceRuins/originalcontent.dmm @@ -740,7 +740,7 @@ /turf/open/indestructible/paper, /area/ruin/space/has_grav/powered) "cc" = ( -/mob/living/simple_animal/hostile/boss/paper_wizard, +/mob/living/basic/paper_wizard, /turf/open/indestructible/paper, /area/ruin/space/has_grav/powered) "cd" = ( diff --git a/code/__DEFINES/ai.dm b/code/__DEFINES/ai.dm index 38d337ff982..8da69d6945c 100644 --- a/code/__DEFINES/ai.dm +++ b/code/__DEFINES/ai.dm @@ -310,6 +310,15 @@ /// Key where we store the charging apc ability #define BB_FESTIVE_APC "BB_festive_apc" +//Paperwizard AI keys +/// Key where we store the summon minions ability +#define BB_WIZARD_SUMMON_MINIONS "BB_summon_minions" +/// Key where we store the mimics ability +#define BB_WIZARD_MIMICS "BB_summon_mimics" +/// Key where we store the paper target +#define BB_FOUND_PAPER "BB_found_paper" +/// Key where we store the list of things we can write on a paper +#define BB_WRITING_LIST "BB_writing_list" /// Key where we store the tentacleing ability #define BB_GOLIATH_TENTACLES "BB_goliath_tentacles" /// Key where goliath stores a hole it wants to get into diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/write_on_paper.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/write_on_paper.dm new file mode 100644 index 00000000000..f5dba58416d --- /dev/null +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/write_on_paper.dm @@ -0,0 +1,16 @@ +/datum/ai_behavior/write_on_paper + +/datum/ai_behavior/write_on_paper/perform(seconds_per_tick, datum/ai_controller/controller, found_paper, list_of_writings) + . = ..() + var/mob/living/wizard = controller.pawn + var/list/writing_list = controller.blackboard[list_of_writings] + var/obj/item/paper/target = controller.blackboard[found_paper] + if(length(writing_list)) + target.add_raw_text(pick(writing_list)) + target.update_appearance() + wizard.dropItemToGround(target) + finish_action(controller, TRUE, found_paper) + +/datum/ai_behavior/write_on_paper/finish_action(datum/ai_controller/controller, succeeded, target_key) + . = ..() + controller.clear_blackboard_key(target_key) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/find_paper_and_write.dm b/code/datums/ai/basic_mobs/basic_subtrees/find_paper_and_write.dm new file mode 100644 index 00000000000..900d13e0a04 --- /dev/null +++ b/code/datums/ai/basic_mobs/basic_subtrees/find_paper_and_write.dm @@ -0,0 +1,23 @@ +/datum/ai_planning_subtree/find_paper_and_write + +/datum/ai_planning_subtree/find_paper_and_write/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + var/obj/item/inhand_paper = controller.blackboard[BB_SIMPLE_CARRY_ITEM] + var/mob/living/basic/wizard = controller.pawn + + if(!QDELETED(inhand_paper)) + controller.queue_behavior(/datum/ai_behavior/write_on_paper, BB_SIMPLE_CARRY_ITEM, BB_WRITING_LIST) + return SUBTREE_RETURN_FINISH_PLANNING + + var/obj/item/paper/target = controller.blackboard[BB_FOUND_PAPER] + + if(QDELETED(target)) + controller.queue_behavior(/datum/ai_behavior/find_and_set/empty_paper, BB_FOUND_PAPER, /obj/item/paper) + return + + if(get_turf(wizard) != get_turf(target)) + controller.queue_behavior(/datum/ai_behavior/travel_towards, BB_FOUND_PAPER) + return SUBTREE_RETURN_FINISH_PLANNING + + if(!(target in wizard.contents)) + controller.queue_behavior(/datum/ai_behavior/pick_up_item, BB_FOUND_PAPER, BB_SIMPLE_CARRY_ITEM) + return SUBTREE_RETURN_FINISH_PLANNING diff --git a/code/datums/elements/effect_trail.dm b/code/datums/elements/effect_trail.dm index 6e51188c0e4..d1d2fbec44a 100644 --- a/code/datums/elements/effect_trail.dm +++ b/code/datums/elements/effect_trail.dm @@ -3,14 +3,17 @@ */ /datum/element/effect_trail + element_flags = ELEMENT_BESPOKE + argument_hash_start_idx = 2 /// The effect used for the trail generation. - var/obj/effect/chosen_effect + var/chosen_effect -/datum/element/effect_trail/Attach(datum/target) +/datum/element/effect_trail/Attach(datum/target, chosen_effect = /obj/effect/forcefield/cosmic_field) . = ..() if(!ismovable(target)) return ELEMENT_INCOMPATIBLE RegisterSignal(target, COMSIG_MOVABLE_MOVED, PROC_REF(generate_effect)) + src.chosen_effect = chosen_effect /datum/element/effect_trail/Detach(datum/target) . = ..() @@ -23,6 +26,3 @@ var/turf/open/open_turf = get_turf(target_object) if(istype(open_turf)) new chosen_effect(open_turf) - -/datum/element/effect_trail/cosmic_trail - chosen_effect = /obj/effect/forcefield/cosmic_field/fast diff --git a/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm b/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm index 769b1586825..b6b7fa6f77b 100644 --- a/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm @@ -182,7 +182,7 @@ if(target.mind && target.stat != DEAD) increase_combo_duration() if(combo_counter == 4) - source.AddElement(/datum/element/effect_trail/cosmic_trail) + source.AddElement(/datum/element/effect_trail, /obj/effect/forcefield/cosmic_field/fast) third_target = second_target second_target = WEAKREF(target) @@ -191,7 +191,7 @@ second_target = null third_target = null if(combo_counter > 3) - source.RemoveElement(/datum/element/effect_trail/cosmic_trail) + source.RemoveElement(/datum/element/effect_trail, /obj/effect/forcefield/cosmic_field/fast) combo_duration = combo_duration_amount combo_counter = 0 new /obj/effect/temp_visual/cosmic_cloud(get_turf(source)) diff --git a/code/modules/antagonists/heretic/magic/star_blast.dm b/code/modules/antagonists/heretic/magic/star_blast.dm index 236fa313daf..297e24455e2 100644 --- a/code/modules/antagonists/heretic/magic/star_blast.dm +++ b/code/modules/antagonists/heretic/magic/star_blast.dm @@ -35,7 +35,7 @@ /obj/projectile/magic/star_ball/Initialize(mapload) . = ..() - AddElement(/datum/element/effect_trail/cosmic_trail) + AddElement(/datum/element/effect_trail, /obj/effect/forcefield/cosmic_field/fast) /obj/projectile/magic/star_ball/on_hit(atom/target, blocked = FALSE, pierce_hit) . = ..() diff --git a/code/modules/antagonists/heretic/magic/star_touch.dm b/code/modules/antagonists/heretic/magic/star_touch.dm index 64c5930e411..fa5a6f25287 100644 --- a/code/modules/antagonists/heretic/magic/star_touch.dm +++ b/code/modules/antagonists/heretic/magic/star_touch.dm @@ -230,7 +230,7 @@ /// What to add when the beam connects to a target /datum/status_effect/cosmic_beam/proc/on_beam_hit(mob/living/target) if(!istype(target, /mob/living/basic/star_gazer)) - target.AddElement(/datum/element/effect_trail/cosmic_trail) + target.AddElement(/datum/element/effect_trail, /obj/effect/forcefield/cosmic_field/fast) return /// What to process when the beam is connected to a target @@ -242,5 +242,5 @@ /// What to remove when the beam disconnects from a target /datum/status_effect/cosmic_beam/proc/on_beam_release(mob/living/target) if(!istype(target, /mob/living/basic/star_gazer)) - target.RemoveElement(/datum/element/effect_trail/cosmic_trail) + target.RemoveElement(/datum/element/effect_trail, /obj/effect/forcefield/cosmic_field/fast) return diff --git a/code/modules/mob/living/basic/heretic/star_gazer.dm b/code/modules/mob/living/basic/heretic/star_gazer.dm index e64f3e82ff2..ff4beb737d4 100644 --- a/code/modules/mob/living/basic/heretic/star_gazer.dm +++ b/code/modules/mob/living/basic/heretic/star_gazer.dm @@ -52,7 +52,7 @@ AddElement(/datum/element/footstep, FOOTSTEP_MOB_SHOE) AddElement(/datum/element/wall_smasher, ENVIRONMENT_SMASH_RWALLS) AddElement(/datum/element/simple_flying) - AddElement(/datum/element/effect_trail/cosmic_trail) + AddElement(/datum/element/effect_trail, /obj/effect/forcefield/cosmic_field/fast) AddElement(/datum/element/ai_target_damagesource) AddComponent(/datum/component/regenerator, outline_colour = "#b97a5d") ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) diff --git a/code/modules/mob/living/basic/space_fauna/paper_wizard/paper_abilities.dm b/code/modules/mob/living/basic/space_fauna/paper_wizard/paper_abilities.dm new file mode 100644 index 00000000000..0e3aaece9c0 --- /dev/null +++ b/code/modules/mob/living/basic/space_fauna/paper_wizard/paper_abilities.dm @@ -0,0 +1,90 @@ +/datum/action/cooldown/spell/conjure/wizard_summon_minions + name = "Summon Minions" + button_icon = 'icons/mob/actions/actions_minor_antag.dmi' + button_icon_state = "art_summon" + invocation = "Rise, my creations! Jump off your pages and into this realm!" + invocation_type = INVOCATION_SHOUT + spell_requirements = NONE + cooldown_time = 15 SECONDS + summon_type = list( + /mob/living/basic/stickman, + /mob/living/basic/stickman/ranged, + /mob/living/basic/stickman/dog, + ) + summon_radius = 1 + summon_amount = 2 + ///How many minions we summoned + var/summoned_minions = 0 + ///How many minions we can have at once + var/max_minions = 6 + + +/datum/action/cooldown/spell/conjure/wizard_summon_minions/can_cast_spell(feedback = TRUE) + . = ..() + if(!.) + return FALSE + if(summoned_minions >= max_minions) + return FALSE + return TRUE + +/datum/action/cooldown/spell/conjure/wizard_summon_minions/post_summon(atom/summoned_object, atom/cast_on) + var/mob/living/chosen_minion = summoned_object + RegisterSignals(chosen_minion, list(COMSIG_QDELETING, COMSIG_LIVING_DEATH), PROC_REF(lost_minion)) + summoned_minions++ + +/datum/action/cooldown/spell/conjure/wizard_summon_minions/proc/lost_minion(mob/source) + SIGNAL_HANDLER + + UnregisterSignal(source, list(COMSIG_QDELETING, COMSIG_LIVING_DEATH)) + summoned_minions-- + +/datum/action/cooldown/spell/pointed/wizard_mimic + name = "Craft Mimicry" + button_icon = 'icons/mob/actions/actions_minor_antag.dmi' + button_icon_state = "mimic_summon" + invocation = "My craft defines me, you could even say it IS me!" + invocation_type = INVOCATION_SHOUT + spell_requirements = NONE + cooldown_time = 25 SECONDS + ///when the clones will die + var/clone_lifespan = 15 SECONDS + ///list of clones + var/list/copies = list() + +/datum/action/cooldown/spell/pointed/wizard_mimic/Grant(mob/grant_to) + . = ..() + if(!owner) + return + RegisterSignal(owner, COMSIG_LIVING_HEALTH_UPDATE, PROC_REF(delete_clones)) + +/datum/action/cooldown/spell/pointed/wizard_mimic/is_valid_target(atom/cast_on) + if(!isliving(cast_on)) + return FALSE + return TRUE + +/datum/action/cooldown/spell/pointed/wizard_mimic/cast(mob/living/cast_on) + . = ..() + var/list/directions = GLOB.cardinals.Copy() + for(var/i in 1 to 3) + var/mob/living/basic/paper_wizard/copy/copy = new (get_step(cast_on, pick_n_take(directions))) + invocation(copy) + RegisterSignals(copy, list(COMSIG_QDELETING, COMSIG_LIVING_DEATH), PROC_REF(lost_minion)) + copies += copy + QDEL_IN(copy, clone_lifespan) + owner.forceMove(get_step(cast_on, pick_n_take(directions))) + +/datum/action/cooldown/spell/pointed/wizard_mimic/proc/lost_minion(mob/living/basic/paper_wizard/copy/source) + SIGNAL_HANDLER + + copies -= source + UnregisterSignal(source, list(COMSIG_QDELETING, COMSIG_LIVING_DEATH), PROC_REF(lost_minion)) + +/datum/action/cooldown/spell/pointed/wizard_mimic/proc/delete_clones(mob/source) + SIGNAL_HANDLER + + QDEL_LIST(copies) + +/datum/action/cooldown/spell/pointed/wizard_mimic/Destroy() + QDEL_LIST(copies) + return ..() + diff --git a/code/modules/mob/living/basic/space_fauna/paper_wizard/paper_wizard.dm b/code/modules/mob/living/basic/space_fauna/paper_wizard/paper_wizard.dm new file mode 100644 index 00000000000..3b32fbb4ce7 --- /dev/null +++ b/code/modules/mob/living/basic/space_fauna/paper_wizard/paper_wizard.dm @@ -0,0 +1,196 @@ +/mob/living/basic/paper_wizard + name = "Mjor the Creative" + desc = "A wizard with a taste for the arts." + mob_biotypes = MOB_ORGANIC|MOB_HUMANOID + faction = list(FACTION_HOSTILE, FACTION_STICKMAN) + icon = 'icons/mob/simple/simple_human.dmi' + icon_state = "paperwizard" + gender = MALE + + response_help_continuous = "brushes" + response_help_simple = "brush" + response_disarm_continuous = "pushes" + response_disarm_simple = "push" + basic_mob_flags = DEL_ON_DEATH + + maxHealth = 1000 + health = 1000 + melee_damage_lower = 10 + melee_damage_upper = 20 + obj_damage = 50 + attack_sound = 'sound/hallucinations/growl1.ogg' + ai_controller = /datum/ai_controller/basic_controller/paper_wizard + ///spell to summon minions + var/datum/action/cooldown/spell/conjure/wizard_summon_minions/summon + ///spell to summon clones + var/datum/action/cooldown/spell/pointed/wizard_mimic/mimic + ///the loot we will drop + var/static/list/dropped_loot = list(/obj/effect/temp_visual/paperwiz_dying) + + +/mob/living/basic/paper_wizard/Initialize(mapload) + . = ..() + apply_dynamic_human_appearance(src, mob_spawn_path = /obj/effect/mob_spawn/corpse/human/wizard/paper) + grant_abilities() + grant_loot() + AddElement(/datum/element/effect_trail, /obj/effect/temp_visual/paper_scatter) + +/mob/living/basic/paper_wizard/proc/grant_abilities() + summon = new(src) + summon.Grant(src) + ai_controller.set_blackboard_key(BB_WIZARD_SUMMON_MINIONS, summon) + mimic = new(src) + mimic.Grant(src) + ai_controller.set_blackboard_key(BB_WIZARD_MIMICS, mimic) + +/mob/living/basic/paper_wizard/proc/grant_loot() + AddElement(/datum/element/death_drops, dropped_loot) + +/mob/living/basic/paper_wizard/Destroy() + QDEL_NULL(summon) + QDEL_NULL(mimic) + return ..() + +/datum/ai_controller/basic_controller/paper_wizard + blackboard = list( + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_WRITING_LIST = list( + "I can turn the paper into gold and ink into diamonds!", + "Your fate is written and sealed!", + "You shall suffer the wrath of a thousand paper cuts!", + ) + ) + + ai_movement = /datum/ai_movement/basic_avoidance + idle_behavior = /datum/idle_behavior/idle_random_walk/less_walking + planning_subtrees = list( + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/targeted_mob_ability/wizard_mimic, + /datum/ai_planning_subtree/use_mob_ability/wizard_summon_minions, + /datum/ai_planning_subtree/basic_melee_attack_subtree, + /datum/ai_planning_subtree/attack_obstacle_in_path/paper_wizard, + /datum/ai_planning_subtree/find_paper_and_write, + ) + +/datum/ai_planning_subtree/attack_obstacle_in_path/paper_wizard + target_key = BB_FOUND_PAPER + attack_behaviour = /datum/ai_behavior/attack_obstructions/paper_wizard + +/datum/ai_behavior/attack_obstructions/paper_wizard + action_cooldown = 0.4 SECONDS + can_attack_turfs = TRUE + can_attack_dense_objects = TRUE + +/datum/ai_planning_subtree/targeted_mob_ability/wizard_mimic + ability_key = BB_WIZARD_MIMICS + finish_planning = FALSE + +/datum/ai_planning_subtree/use_mob_ability/wizard_summon_minions + ability_key = BB_WIZARD_SUMMON_MINIONS + finish_planning = FALSE + +/datum/ai_behavior/find_and_set/empty_paper + action_cooldown = 10 SECONDS + +/datum/ai_behavior/find_and_set/empty_paper/search_tactic(datum/ai_controller/controller, locate_path, search_range) + var/list/empty_papers = list() + + for(var/obj/item/paper/target_paper in oview(search_range, controller.pawn)) + if(target_paper.is_empty()) + empty_papers += target_paper + + if(empty_papers.len) + return pick(empty_papers) + +/mob/living/basic/paper_wizard/copy + desc = "'Tis a ruse!" + health = 1 + maxHealth = 1 + alpha = 200 + faction = list(FACTION_STICKMAN) + melee_damage_lower = 1 + melee_damage_upper = 5 + + ai_controller = /datum/ai_controller/basic_controller/wizard_copy + +/mob/living/basic/paper_wizard/copy/Initialize(mapload) + . = ..() + AddElement(/datum/element/relay_attackers) + RegisterSignal(src, COMSIG_ATOM_WAS_ATTACKED, PROC_REF(on_attacked)) + +/mob/living/basic/paper_wizard/copy/grant_abilities() + return + +/mob/living/basic/paper_wizard/copy/grant_loot() + return + +//Hit a fake? eat pain! +/mob/living/basic/paper_wizard/copy/proc/on_attacked(mob/source, mob/living/attacker, attack_flags) + SIGNAL_HANDLER + + if(!(attack_flags & (ATTACKER_STAMINA_ATTACK|ATTACKER_SHOVING))) + attacker.adjustBruteLoss(20) + to_chat(attacker, span_warning("The clone casts a spell to damage you before he dies!")) + + +/mob/living/basic/paper_wizard/copy/examine(mob/user) + . = ..() + if(isobserver(user)) + . += span_notice("It's an illusion - what is it hiding?") + else + new /obj/effect/temp_visual/small_smoke/halfsecond(get_turf(src)) + qdel(src) //I see through your ruse! + +/datum/ai_controller/basic_controller/wizard_copy + blackboard = list( + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + ) + + ai_movement = /datum/ai_movement/basic_avoidance + idle_behavior = /datum/idle_behavior/idle_random_walk + planning_subtrees = list( + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/basic_melee_attack_subtree, + ) + +//fancy effects +/obj/effect/temp_visual/paper_scatter + name = "scattering paper" + desc = "Pieces of paper scattering to the wind." + layer = ABOVE_NORMAL_TURF_LAYER + plane = GAME_PLANE + icon = 'icons/effects/effects.dmi' + icon_state = "paper_scatter" + anchored = TRUE + duration = 0.5 SECONDS + randomdir = FALSE + +/obj/effect/temp_visual/paperwiz_dying + name = "craft portal" + desc = "A wormhole sucking the wizard into the void. Neat." + layer = ABOVE_NORMAL_TURF_LAYER + plane = GAME_PLANE + icon = 'icons/effects/effects.dmi' + icon_state = "paperwiz_poof" + anchored = TRUE + duration = 1.8 SECONDS + randomdir = FALSE + +/obj/effect/temp_visual/paperwiz_dying/Initialize(mapload) + . = ..() + visible_message(span_boldannounce("The wizard cries out in pain as a gate appears behind him, sucking him in!")) + playsound(get_turf(src), 'sound/magic/mandswap.ogg', 50, vary = TRUE, pressure_affected = TRUE) + playsound(get_turf(src), 'sound/hallucinations/wail.ogg', 50, vary = TRUE, pressure_affected = TRUE) + RegisterSignal(src, COMSIG_PREQDELETED, PROC_REF(on_delete)) + +/obj/effect/temp_visual/paperwiz_dying/proc/on_delete() + SIGNAL_HANDLER + + for(var/mob/nearby in range(7, src)) + shake_camera(nearby, duration = 7 SECONDS, strength = 1) + var/turf/current_turf = get_turf(src) + playsound(current_turf,'sound/magic/summon_magic.ogg', 50, vary = TRUE, vary = TRUE) + new /obj/effect/temp_visual/paper_scatter(current_turf) + new /obj/item/clothing/suit/wizrobe/paper(current_turf) + new /obj/item/clothing/head/collectable/paper(current_turf) + diff --git a/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm b/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm deleted file mode 100644 index 15b439b425f..00000000000 --- a/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm +++ /dev/null @@ -1,210 +0,0 @@ -//Paper Wizard Boss -/mob/living/simple_animal/hostile/boss/paper_wizard - name = "Mjor the Creative" - desc = "A wizard with a taste for the arts." - mob_biotypes = MOB_ORGANIC|MOB_HUMANOID - boss_abilities = list(/datum/action/boss/wizard_summon_minions, /datum/action/boss/wizard_mimic) - faction = list(FACTION_HOSTILE,FACTION_STICKMAN) - del_on_death = TRUE - icon = 'icons/mob/simple/simple_human.dmi' - icon_state = "paperwizard" - ranged = TRUE - environment_smash = ENVIRONMENT_SMASH_NONE - minimum_distance = 3 - retreat_distance = 3 - obj_damage = 0 - melee_damage_lower = 10 - melee_damage_upper = 20 - health = 1000 - maxHealth = 1000 - loot = list(/obj/effect/temp_visual/paperwiz_dying) - projectiletype = /obj/projectile/temp - projectilesound = 'sound/weapons/emitter.ogg' - attack_sound = 'sound/hallucinations/growl1.ogg' - footstep_type = FOOTSTEP_MOB_SHOE - var/list/copies = list() - -/mob/living/simple_animal/hostile/boss/paper_wizard/Initialize(mapload) - . = ..() - apply_dynamic_human_appearance(src, mob_spawn_path = /obj/effect/mob_spawn/corpse/human/wizard/paper) - -/mob/living/simple_animal/hostile/boss/paper_wizard/Destroy() - QDEL_LIST(copies) - return ..() - -//Summon Ability -//Lets the wizard summon his art to fight for him -/datum/action/boss/wizard_summon_minions - name = "Summon Minions" - button_icon = 'icons/mob/actions/actions_minor_antag.dmi' - button_icon_state = "art_summon" - usage_probability = 40 - boss_cost = 30 - boss_type = /mob/living/simple_animal/hostile/boss/paper_wizard - needs_target = FALSE - say_when_triggered = "Rise, my creations! Jump off your pages and into this realm!" - ///How many minions we summoned - var/summoned_minions = 0 - ///How many minions we can have at once - var/max_minions = 6 - ///How many minions we should spawn - var/minions_to_summon = 3 - -/datum/action/boss/wizard_summon_minions/IsAvailable(feedback = FALSE) - . = ..() - if(!.) - return FALSE - if(summoned_minions >= max_minions) - return FALSE - return TRUE - -/datum/action/boss/wizard_summon_minions/Trigger(trigger_flags) - . = ..() - if(!.) - return - var/list/minions = list( - /mob/living/basic/stickman, - /mob/living/basic/stickman/ranged, - /mob/living/basic/stickman/dog) - var/list/directions = GLOB.cardinals.Copy() - var/summon_amount = min(minions_to_summon, max_minions - summoned_minions) - for(var/i in 1 to summon_amount) - var/atom/chosen_minion = pick_n_take(minions) - chosen_minion = new chosen_minion(get_step(boss, pick_n_take(directions))) - RegisterSignals(chosen_minion, list(COMSIG_QDELETING, COMSIG_LIVING_DEATH), PROC_REF(lost_minion)) - summoned_minions++ - -/// Called when a minion is qdeleted or dies, removes it from our minion list -/datum/action/boss/wizard_summon_minions/proc/lost_minion(mob/source) - SIGNAL_HANDLER - - UnregisterSignal(source, list(COMSIG_QDELETING, COMSIG_LIVING_DEATH)) - summoned_minions-- - -//Mimic Ability -//Summons mimics of himself with magical papercraft -//Hitting a decoy hurts nearby people excluding the wizard himself -//Hitting the wizard himself destroys all decoys -/datum/action/boss/wizard_mimic - name = "Craft Mimicry" - button_icon = 'icons/mob/actions/actions_minor_antag.dmi' - button_icon_state = "mimic_summon" - usage_probability = 30 - boss_cost = 40 - boss_type = /mob/living/simple_animal/hostile/boss/paper_wizard - say_when_triggered = "" - -/datum/action/boss/wizard_mimic/Trigger(trigger_flags) - if(..()) - var/mob/living/target - if(!boss.client) //AI's target - target = boss.target - else //random mob - var/list/threats = boss.PossibleThreats() - if(threats.len) - target = pick(threats) - if(target) - var/mob/living/simple_animal/hostile/boss/paper_wizard/wiz = boss - var/directions = GLOB.cardinals.Copy() - for(var/i in 1 to 3) - var/mob/living/simple_animal/hostile/boss/paper_wizard/copy/C = new (get_step(target,pick_n_take(directions))) - wiz.copies += C - C.original = wiz - C.say("My craft defines me, you could even say it IS me!") - wiz.say("My craft defines me, you could even say it IS me!") - wiz.forceMove(get_step(target,pick_n_take(directions))) - wiz.minimum_distance = 1 //so he doesn't run away and ruin everything - wiz.retreat_distance = 0 - else - boss.atb.refund(boss_cost) - -/mob/living/simple_animal/hostile/boss/paper_wizard/copy - desc = "'Tis a ruse!" - health = 1 - maxHealth = 1 - alpha = 200 - boss_abilities = list() - melee_damage_lower = 1 - melee_damage_upper = 5 - minimum_distance = 0 - retreat_distance = 0 - ranged = 0 - loot = list() - var/mob/living/simple_animal/hostile/boss/paper_wizard/original - -/mob/living/simple_animal/hostile/boss/paper_wizard/copy/Destroy() - if(original) - original.copies -= src - original = null - return ..() - -//Hit a fake? eat pain! -/mob/living/simple_animal/hostile/boss/paper_wizard/copy/adjustHealth(amount, updating_health = TRUE, forced = FALSE) - if(amount > 0) //damage - if(original) - original.minimum_distance = 3 - original.retreat_distance = 3 - for(var/c in original.copies) - qdel(c) - for(var/mob/living/L in range(5,src)) - if(L == original || istype(L, type)) - continue - L.adjustBruteLoss(50) - qdel(src) - else - . = ..() - -//Hit the real guy? copies go bai-bai -/mob/living/simple_animal/hostile/boss/paper_wizard/adjustHealth(amount, updating_health = TRUE, forced = FALSE) - . = ..() - if(. > 0)//damage - minimum_distance = 3 - retreat_distance = 3 - for(var/copy in copies) - qdel(copy) - -/mob/living/simple_animal/hostile/boss/paper_wizard/copy/examine(mob/user) - . = ..() - if(isobserver(user)) - . += span_notice("It's an illusion - what is it hiding?") - else - qdel(src) //I see through your ruse! - -//fancy effects -/obj/effect/temp_visual/paper_scatter - name = "scattering paper" - desc = "Pieces of paper scattering to the wind." - layer = ABOVE_NORMAL_TURF_LAYER - plane = GAME_PLANE - icon = 'icons/effects/effects.dmi' - icon_state = "paper_scatter" - anchored = TRUE - duration = 5 - randomdir = FALSE - -/obj/effect/temp_visual/paperwiz_dying - name = "craft portal" - desc = "A wormhole sucking the wizard into the void. Neat." - layer = ABOVE_NORMAL_TURF_LAYER - plane = GAME_PLANE - icon = 'icons/effects/effects.dmi' - icon_state = "paperwiz_poof" - anchored = TRUE - duration = 18 - randomdir = FALSE - -/obj/effect/temp_visual/paperwiz_dying/Initialize(mapload) - . = ..() - visible_message(span_boldannounce("The wizard cries out in pain as a gate appears behind him, sucking him in!")) - playsound(get_turf(src),'sound/magic/mandswap.ogg', 50, TRUE, TRUE) - playsound(get_turf(src),'sound/hallucinations/wail.ogg', 50, TRUE, TRUE) - -/obj/effect/temp_visual/paperwiz_dying/Destroy() - for(var/mob/M in range(7,src)) - shake_camera(M, 7, 1) - var/turf/T = get_turf(src) - playsound(T,'sound/magic/summon_magic.ogg', 50, TRUE, TRUE) - new /obj/effect/temp_visual/paper_scatter(T) - new /obj/item/clothing/suit/wizrobe/paper(T) - new /obj/item/clothing/head/collectable/paper(T) - return ..() diff --git a/code/modules/unit_tests/simple_animal_freeze.dm b/code/modules/unit_tests/simple_animal_freeze.dm index 8dd2eef9465..9a598747708 100644 --- a/code/modules/unit_tests/simple_animal_freeze.dm +++ b/code/modules/unit_tests/simple_animal_freeze.dm @@ -114,8 +114,6 @@ /mob/living/simple_animal/hostile/blob/blobspore/independent, /mob/living/simple_animal/hostile/blob/blobspore/weak, /mob/living/simple_animal/hostile/boss, - /mob/living/simple_animal/hostile/boss/paper_wizard, - /mob/living/simple_animal/hostile/boss/paper_wizard/copy, /mob/living/simple_animal/hostile/construct, /mob/living/simple_animal/hostile/construct/artificer, /mob/living/simple_animal/hostile/construct/artificer/angelic, diff --git a/tgstation.dme b/tgstation.dme index dc4c4336d6d..02242cda20f 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -854,8 +854,10 @@ #include "code\datums\ai\basic_mobs\basic_ai_behaviors\tipped_reaction.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\travel_towards.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\ventcrawling.dm" +#include "code\datums\ai\basic_mobs\basic_ai_behaviors\write_on_paper.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\attack_obstacle_in_path.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\find_food.dm" +#include "code\datums\ai\basic_mobs\basic_subtrees\find_paper_and_write.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\flee_target.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\opportunistic_ventcrawler.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\simple_attack_target.dm" @@ -4138,6 +4140,8 @@ #include "code\modules\mob\living\basic\space_fauna\netherworld\blankbody.dm" #include "code\modules\mob\living\basic\space_fauna\netherworld\creature.dm" #include "code\modules\mob\living\basic\space_fauna\netherworld\migo.dm" +#include "code\modules\mob\living\basic\space_fauna\paper_wizard\paper_abilities.dm" +#include "code\modules\mob\living\basic\space_fauna\paper_wizard\paper_wizard.dm" #include "code\modules\mob\living\basic\space_fauna\spider\giant_spider\giant_spider.dm" #include "code\modules\mob\living\basic\space_fauna\spider\giant_spider\giant_spider_ai.dm" #include "code\modules\mob\living\basic\space_fauna\spider\giant_spider\giant_spider_subtrees.dm" @@ -4385,7 +4389,6 @@ #include "code\modules\mob\living\simple_animal\hostile\wizard.dm" #include "code\modules\mob\living\simple_animal\hostile\zombie.dm" #include "code\modules\mob\living\simple_animal\hostile\bosses\boss.dm" -#include "code\modules\mob\living\simple_animal\hostile\bosses\paperwizard.dm" #include "code\modules\mob\living\simple_animal\hostile\constructs\artificer.dm" #include "code\modules\mob\living\simple_animal\hostile\constructs\constructs.dm" #include "code\modules\mob\living\simple_animal\hostile\constructs\harvester.dm" diff --git a/tools/UpdatePaths/Scripts/76688_paper_wizard.txt b/tools/UpdatePaths/Scripts/76688_paper_wizard.txt new file mode 100644 index 00000000000..1da513147f2 --- /dev/null +++ b/tools/UpdatePaths/Scripts/76688_paper_wizard.txt @@ -0,0 +1,2 @@ +/mob/living/simple_animal/hostile/boss/paper_wizard : /mob/living/basic/paper_wizard{@OLD} +