mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-21 13:05:36 +01:00
[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 🆑 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 /🆑 * transform the paper wizard from a simple to a basic --------- Co-authored-by: Ben10Omintrix <138636438+Ben10Omintrix@users.noreply.github.com>
This commit is contained in:
@@ -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" = (
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
. = ..()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 ..()
|
||||
@@ -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,
|
||||
|
||||
+4
-1
@@ -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"
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
/mob/living/simple_animal/hostile/boss/paper_wizard : /mob/living/basic/paper_wizard{@OLD}
|
||||
|
||||
Reference in New Issue
Block a user