mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-24 04:27:35 +01:00
Basic diona nymphs, spiderbots, and crabs (#30377)
* Basic nymphs, spiderbots, and crabs * Nutrition fix * Forgot a line * Cooldown on eat --------- Signed-off-by: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
//Look Sir, free crabs!
|
||||
/mob/living/basic/crab
|
||||
name = "crab"
|
||||
desc = "A hard-shelled crustacean. Seems quite content to lounge around all the time."
|
||||
icon_state = "crab"
|
||||
icon_living = "crab"
|
||||
icon_dead = "crab_dead"
|
||||
speak_emote = list("clicks")
|
||||
butcher_results = list(/obj/item/food/meat = 1)
|
||||
response_help_continuous = "pets"
|
||||
response_help_simple = "pet"
|
||||
response_disarm_continuous = "pushes"
|
||||
response_disarm_simple = "push"
|
||||
response_harm_continuous = "stomps"
|
||||
response_harm_simple = "stomp"
|
||||
friendly_verb_continuous = "pinches"
|
||||
friendly_verb_simple = "pinch"
|
||||
ventcrawler = VENTCRAWLER_ALWAYS
|
||||
can_hide = TRUE
|
||||
gold_core_spawnable = FRIENDLY_SPAWN
|
||||
|
||||
ai_controller = /datum/ai_controller/basic_controller/crab
|
||||
|
||||
/mob/living/basic/crab/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/wears_collar)
|
||||
AddElement(/datum/element/ai_retaliate)
|
||||
AddElement(/datum/element/sideways_movement)
|
||||
|
||||
/mob/living/basic/crab/valid_respawn_target_for(mob/user)
|
||||
. = ..()
|
||||
return TRUE
|
||||
|
||||
// COFFEE! SQUEEEEEEEEE!
|
||||
/mob/living/basic/crab/coffee
|
||||
name = "Coffee"
|
||||
real_name = "Coffee"
|
||||
desc = "It's Coffee, the other pet!"
|
||||
gold_core_spawnable = NO_SPAWN
|
||||
|
||||
/mob/living/basic/crab/evil
|
||||
name = "Evil Crab"
|
||||
real_name = "Evil Crab"
|
||||
desc = "Unnerving, isn't it? It has to be planning something nefarious..."
|
||||
icon_state = "evilcrab"
|
||||
icon_living = "evilcrab"
|
||||
icon_dead = "evilcrab_dead"
|
||||
response_help_continuous = "pokes"
|
||||
response_help_simple = "poke"
|
||||
response_disarm_continuous = "shoves"
|
||||
response_disarm_simple = "shove"
|
||||
gold_core_spawnable = HOSTILE_SPAWN
|
||||
|
||||
/// Crabs don't do much, but they want to live. They will flee when attacked, but will opportunistically melee attack people who do
|
||||
/datum/ai_controller/basic_controller/crab
|
||||
blackboard = list(
|
||||
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
|
||||
)
|
||||
ai_traits = AI_FLAG_STOP_MOVING_WHEN_PULLED | AI_FLAG_PAUSE_DURING_DO_AFTER
|
||||
ai_movement = /datum/ai_movement/basic_avoidance
|
||||
idle_behavior = /datum/idle_behavior/idle_random_walk
|
||||
planning_subtrees = list(
|
||||
/datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee,
|
||||
/datum/ai_planning_subtree/flee_target,
|
||||
/datum/ai_planning_subtree/basic_melee_attack_subtree/opportunistic,
|
||||
/datum/ai_planning_subtree/random_speech/crab,
|
||||
)
|
||||
|
||||
|
||||
/datum/ai_planning_subtree/random_speech/crab
|
||||
speech_chance = 5
|
||||
emote_hear = list("clicks")
|
||||
emote_see = list("clacks")
|
||||
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* Tiny babby plant critter plus procs.
|
||||
*/
|
||||
|
||||
//Mob defines.
|
||||
#define GESTALT_ALERT "gestalt screen alert"
|
||||
#define NYMPH_ALERT "nymph screen alert"
|
||||
|
||||
/mob/living/basic/diona_nymph
|
||||
name = "diona nymph"
|
||||
icon = 'icons/mob/monkey.dmi'
|
||||
icon_state = "nymph"
|
||||
icon_living = "nymph"
|
||||
icon_dead = "nymph_dead"
|
||||
icon_resting = "nymph_sleep"
|
||||
pass_flags = PASSTABLE | PASSMOB
|
||||
mob_biotypes = MOB_ORGANIC | MOB_PLANT
|
||||
mob_size = MOB_SIZE_SMALL
|
||||
ventcrawler = VENTCRAWLER_ALWAYS
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
minimum_survivable_temperature = 0
|
||||
|
||||
maxHealth = 50
|
||||
health = 50
|
||||
|
||||
voice_name = "diona nymph"
|
||||
speak_emote = list("chirrups")
|
||||
|
||||
response_help_continuous = "pets"
|
||||
response_help_simple = "pet"
|
||||
response_disarm_continuous = "pushes"
|
||||
response_disarm_simple = "push"
|
||||
response_harm_continuous = "kicks"
|
||||
response_harm_simple = "kick"
|
||||
|
||||
melee_damage_lower = 5
|
||||
melee_damage_upper = 8
|
||||
melee_attack_cooldown_min = 1.5 SECONDS
|
||||
melee_attack_cooldown_max = 2.5 SECONDS
|
||||
attack_verb_continuous = "bites"
|
||||
attack_verb_simple = "bite"
|
||||
attack_sound = 'sound/weapons/bite.ogg'
|
||||
|
||||
ai_controller = /datum/ai_controller/basic_controller/diona_nymph
|
||||
|
||||
var/list/donors = list()
|
||||
holder_type = /obj/item/holder/diona
|
||||
|
||||
/// Amount of blood donors needed to evolve
|
||||
var/evolve_donors = 5
|
||||
/// Amount of blood donors needed for understand language
|
||||
var/awareness_donors = 3
|
||||
/// Amount of nutrition needed before evolving
|
||||
var/nutrition_need = 500
|
||||
/// List of stuff (mice) that we want to eat
|
||||
var/static/list/edibles = list(
|
||||
/obj/item/food/grown,
|
||||
)
|
||||
|
||||
var/datum/action/innate/diona_nymph/merge/merge_action = new()
|
||||
var/datum/action/innate/diona_nymph/evolve/evolve_action = new()
|
||||
var/datum/action/innate/diona_nymph/steal_blood/steal_blood_action = new()
|
||||
|
||||
/mob/living/basic/diona_nymph/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/wears_collar)
|
||||
if(name == initial(name)) // To stop named dionas becoming generic.
|
||||
name = "[name] ([rand(1, 1000)])"
|
||||
real_name = name
|
||||
add_language("Rootspeak")
|
||||
merge_action.Grant(src)
|
||||
evolve_action.Grant(src)
|
||||
steal_blood_action.Grant(src)
|
||||
AddElement(/datum/element/ai_retaliate)
|
||||
AddElement(/datum/element/basic_eating, heal_amt_ = 2, food_types_ = edibles)
|
||||
RegisterSignal(src, COMSIG_MOB_PRE_EAT, PROC_REF(check_full))
|
||||
RegisterSignal(src, COMSIG_MOB_ATE, PROC_REF(consume))
|
||||
ai_controller.set_blackboard_key(BB_BASIC_FOODS, typecacheof(edibles))
|
||||
|
||||
/datum/action/innate/diona_nymph/merge
|
||||
name = "Merge with gestalt"
|
||||
button_icon = 'icons/mob/human_races/r_diona.dmi'
|
||||
button_icon_state = "preview"
|
||||
|
||||
/datum/action/innate/diona_nymph/merge/Activate()
|
||||
var/mob/living/basic/diona_nymph/user = owner
|
||||
user.merge()
|
||||
|
||||
/datum/action/innate/diona_nymph/evolve
|
||||
name = "Evolve"
|
||||
button_icon = 'icons/obj/cloning.dmi'
|
||||
button_icon_state = "pod_cloning"
|
||||
|
||||
/datum/action/innate/diona_nymph/evolve/Activate()
|
||||
var/mob/living/basic/diona_nymph/user = owner
|
||||
user.evolve()
|
||||
|
||||
/datum/action/innate/diona_nymph/steal_blood
|
||||
name = "Steal blood"
|
||||
button_icon = 'icons/goonstation/objects/iv.dmi'
|
||||
button_icon_state = "bloodbag"
|
||||
|
||||
/datum/action/innate/diona_nymph/steal_blood/Activate()
|
||||
var/mob/living/basic/diona_nymph/user = owner
|
||||
user.steal_blood()
|
||||
|
||||
/mob/living/basic/diona_nymph/UnarmedAttack(atom/A)
|
||||
// Can't attack your gestalt
|
||||
if(isdiona(A) && (src in A.contents))
|
||||
visible_message("[src] wiggles around a bit.")
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/living/basic/diona_nymph/run_resist()
|
||||
if(!split())
|
||||
..()
|
||||
|
||||
/mob/living/basic/diona_nymph/attack_hand(mob/living/carbon/human/M)
|
||||
// Let people pick the little buggers up.
|
||||
if(M.a_intent == INTENT_HELP)
|
||||
if(isdiona(M))
|
||||
to_chat(M, "You feel your being twine with that of [src] as it merges with your biomass.")
|
||||
to_chat(src, "You feel your being twine with that of [M] as you merge with its biomass.")
|
||||
// adds a screen alert that can call resist
|
||||
throw_alert(GESTALT_ALERT, /atom/movable/screen/alert/nymph, new_master = src)
|
||||
M.throw_alert(NYMPH_ALERT, /atom/movable/screen/alert/gestalt, new_master = src)
|
||||
forceMove(M)
|
||||
else if(isrobot(M))
|
||||
M.visible_message("<span class='notice'>[M] playfully boops [src] on the head!</span>", "<span class='notice'>You playfully boop [src] on the head!</span>")
|
||||
else
|
||||
get_scooped(M)
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/living/basic/diona_nymph/proc/merge()
|
||||
if(stat != CONSCIOUS)
|
||||
return FALSE
|
||||
|
||||
var/list/choices = list()
|
||||
for(var/mob/living/carbon/human/H in view(1,src))
|
||||
if(!(Adjacent(H)) || !isdiona(H))
|
||||
continue
|
||||
choices += H
|
||||
|
||||
if(!length(choices))
|
||||
to_chat(src, "<span class='warning'>No suitable diona nearby.</span>")
|
||||
return FALSE
|
||||
|
||||
var/mob/living/M = tgui_input_list(src, "Who do you wish to merge with?", "Nymph Merging", choices)
|
||||
|
||||
// input can take a while, so re-validate
|
||||
if(!M || !src || !(Adjacent(M)) || stat != CONSCIOUS)
|
||||
return FALSE
|
||||
|
||||
if(isdiona(M))
|
||||
to_chat(M, "You feel your being twine with that of [src] as it merges with your biomass.")
|
||||
M.status_flags |= PASSEMOTES
|
||||
to_chat(src, "You feel your being twine with that of [M] as you merge with its biomass.")
|
||||
forceMove(M)
|
||||
// adds a screen alert that can call resist
|
||||
throw_alert(GESTALT_ALERT, /atom/movable/screen/alert/nymph, new_master = src)
|
||||
M.throw_alert(NYMPH_ALERT, /atom/movable/screen/alert/gestalt, new_master = src)
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/mob/living/basic/diona_nymph/proc/split(forced = FALSE)
|
||||
if((stat != CONSCIOUS && !forced) || !isdiona(loc))
|
||||
return FALSE
|
||||
var/mob/living/carbon/human/D = loc
|
||||
var/turf/T = get_turf(src)
|
||||
if(!T)
|
||||
return FALSE
|
||||
to_chat(loc, "You feel a pang of loss as [src] splits away from your biomass.")
|
||||
to_chat(src, "You wiggle out of the depths of [loc]'s biomass and plop to the ground.")
|
||||
forceMove(T)
|
||||
|
||||
var/hasMobs = FALSE
|
||||
for(var/atom/A in D.contents)
|
||||
if(ismob(A) || istype(A, /obj/item/holder))
|
||||
hasMobs = TRUE
|
||||
if(!hasMobs)
|
||||
D.status_flags &= ~PASSEMOTES
|
||||
D.clear_alert(NYMPH_ALERT)
|
||||
|
||||
clear_alert(GESTALT_ALERT)
|
||||
return TRUE
|
||||
|
||||
/mob/living/basic/diona_nymph/proc/evolve()
|
||||
if(stat != CONSCIOUS)
|
||||
return FALSE
|
||||
|
||||
if(length(donors) < evolve_donors)
|
||||
to_chat(src, "<span class='warning'>You need more blood in order to ascend to a new state of consciousness...</span>")
|
||||
return FALSE
|
||||
|
||||
if(nutrition < nutrition_need)
|
||||
to_chat(src, "<span class='warning'>You need to binge on weeds in order to have the energy to grow...</span>")
|
||||
return FALSE
|
||||
|
||||
if(isdiona(loc) && !split()) // if it's merged with diona, needs to able to split before evolving
|
||||
return FALSE
|
||||
|
||||
visible_message("<span class='danger'>[src] begins to shift and quiver, and erupts in a shower of shed bark as it splits into a tangle of nearly a dozen new dionaea.</span>","<span class='danger'>You begin to shift and quiver, feeling your awareness splinter. All at once, we consume our stored nutrients to surge with growth, splitting into a tangle of at least a dozen new dionaea. We have attained our gestalt form.</span>")
|
||||
|
||||
if(master_commander)
|
||||
to_chat(src, "<span class='userdanger'>As you evolve, your mind grows out of it's restraints. You are no longer loyal to [master_commander]!</span>")
|
||||
|
||||
var/mob/living/carbon/human/diona/adult = new(get_turf(loc))
|
||||
adult.set_species(/datum/species/diona)
|
||||
|
||||
if(istype(loc, /obj/item/holder/diona))
|
||||
var/obj/item/holder/diona/L = loc
|
||||
forceMove(L.loc)
|
||||
qdel(L)
|
||||
|
||||
for(var/datum/language/L in languages)
|
||||
adult.add_language(L.name)
|
||||
adult.regenerate_icons()
|
||||
|
||||
adult.name = "diona ([rand(100,999)])"
|
||||
adult.real_name = adult.name
|
||||
adult.ckey = ckey
|
||||
adult.real_name = adult.dna.species.get_random_name() // I hate this being here of all places but unfortunately dna is based on real_name!
|
||||
// [Nymph -> Diona] is from xenobio (or botany) and does not give vampires usuble blood and cannot be converted by cult.
|
||||
ADD_TRAIT(adult.mind, TRAIT_XENOBIO_SPAWNED_HUMAN, ROUNDSTART_TRAIT)
|
||||
|
||||
for(var/obj/item/W in contents)
|
||||
drop_item_to_ground(W)
|
||||
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
/mob/living/basic/diona_nymph/proc/check_full(datum/source, obj/item/potential_food)
|
||||
SIGNAL_HANDLER // COMSIG_MOB_PRE_EAT
|
||||
if(nutrition >= nutrition_need) // Prevents griefing by overeating food items without evolving.
|
||||
to_chat(src, "<span class='warning'>You're too full to consume this! Perhaps it's time to grow bigger...</span>")
|
||||
return COMSIG_MOB_TERMINATE_EAT
|
||||
|
||||
// Consumes plant matter other than weeds to evolve
|
||||
/mob/living/basic/diona_nymph/proc/consume(datum/source, obj/item/potential_food)
|
||||
SIGNAL_HANDLER // COMSIG_MOB_ATE
|
||||
if(potential_food.reagents.get_reagent_amount("nutriment") + potential_food.reagents.get_reagent_amount("plantmatter") < 1)
|
||||
adjust_nutrition(2)
|
||||
else
|
||||
adjust_nutrition((potential_food.reagents.get_reagent_amount("nutriment") + potential_food.reagents.get_reagent_amount("plantmatter")) * 2)
|
||||
|
||||
/mob/living/basic/diona_nymph/proc/steal_blood()
|
||||
if(stat != CONSCIOUS)
|
||||
return FALSE
|
||||
|
||||
var/list/choices = list()
|
||||
for(var/mob/living/carbon/human/H in oview(1,src))
|
||||
if(Adjacent(H) && H.dna && !(NO_BLOOD in H.dna.species.species_traits))
|
||||
choices += H
|
||||
|
||||
if(!length(choices))
|
||||
to_chat(src, "<span class='warning'>No suitable blood donors nearby.</span>")
|
||||
return FALSE
|
||||
|
||||
var/mob/living/carbon/human/M = tgui_input_list(src, "Who do you wish to take a sample from?", "Blood Sampling", choices)
|
||||
|
||||
if(!M || !src || !(Adjacent(M)) || stat != CONSCIOUS) //input can take a while, so re-validate
|
||||
return FALSE
|
||||
|
||||
if(!M.dna || (NO_BLOOD in M.dna.species.species_traits))
|
||||
to_chat(src, "<span class='warning'>That donor has no blood to take.</span>")
|
||||
return FALSE
|
||||
|
||||
if(donors.Find(M.real_name))
|
||||
to_chat(src, "<span class='warning'>That donor offers you nothing new.</span>")
|
||||
return FALSE
|
||||
|
||||
visible_message("<span class='danger'>[src] flicks out a feeler and neatly steals a sample of [M]'s blood.</span>","<span class='danger'>You flick out a feeler and neatly steal a sample of [M]'s blood.</span>")
|
||||
donors += M.real_name
|
||||
for(var/datum/language/L in M.languages)
|
||||
if(!(L.flags & HIVEMIND))
|
||||
languages |= L
|
||||
|
||||
spawn(25)
|
||||
update_progression()
|
||||
|
||||
/mob/living/basic/diona_nymph/proc/update_progression()
|
||||
if(stat != CONSCIOUS || !length(donors))
|
||||
return FALSE
|
||||
|
||||
if(length(donors) == evolve_donors)
|
||||
to_chat(src, "<span class='noticealien'>You feel ready to move on to your next stage of growth.</span>")
|
||||
else if(length(donors) == awareness_donors)
|
||||
universal_understand = TRUE
|
||||
to_chat(src, "<span class='noticealien'>You feel your awareness expand, and realize you know how to understand the creatures around you.</span>")
|
||||
else
|
||||
to_chat(src, "<span class='noticealien'>The blood seeps into your small form, and you draw out the echoes of memories and personality from it, working them into your budding mind.</span>")
|
||||
|
||||
|
||||
/mob/living/basic/diona_nymph/put_in_hands(obj/item/W)
|
||||
W.forceMove(get_turf(src))
|
||||
W.layer = initial(W.layer)
|
||||
W.plane = initial(W.plane)
|
||||
W.dropped()
|
||||
|
||||
/mob/living/basic/diona_nymph/put_in_active_hand(obj/item/W)
|
||||
to_chat(src, "<span class='warning'>You don't have any hands!</span>")
|
||||
return
|
||||
|
||||
/mob/living/basic/diona_nymph/valid_respawn_target_for(mob/user)
|
||||
if(!jobban_isbanned(user, ROLE_NYMPH))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/// Diona nymphs want to eat plant matter to get to evolution stage, but won't evolve or sample blood on their own. They flee when attacked.
|
||||
/datum/ai_controller/basic_controller/diona_nymph
|
||||
blackboard = list(
|
||||
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
|
||||
)
|
||||
ai_traits = AI_FLAG_STOP_MOVING_WHEN_PULLED | AI_FLAG_PAUSE_DURING_DO_AFTER
|
||||
ai_movement = /datum/ai_movement/basic_avoidance
|
||||
idle_behavior = /datum/idle_behavior/idle_random_walk
|
||||
planning_subtrees = list(
|
||||
/datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee,
|
||||
/datum/ai_planning_subtree/flee_target,
|
||||
/datum/ai_planning_subtree/find_food/diona_nymph,
|
||||
/datum/ai_planning_subtree/random_speech/diona_nymph,
|
||||
)
|
||||
|
||||
/datum/ai_planning_subtree/find_food/diona_nymph
|
||||
|
||||
/datum/ai_planning_subtree/find_food/diona_nymph/select_behaviors(datum/ai_controller/controller, seconds_per_tick)
|
||||
var/mob/living/basic/diona_nymph/nymph = controller.pawn
|
||||
if(nymph.nutrition >= nymph.nutrition_need)
|
||||
// Put eating on cooldown so it doesn't keep trying to eat.
|
||||
var/food_cooldown = controller.blackboard[BB_EAT_FOOD_COOLDOWN] || EAT_FOOD_COOLDOWN
|
||||
controller.set_blackboard_key(BB_NEXT_FOOD_EAT, world.time + food_cooldown)
|
||||
return SUBTREE_RETURN_FINISH_PLANNING
|
||||
return ..()
|
||||
|
||||
/datum/ai_planning_subtree/random_speech/diona_nymph
|
||||
speech_chance = 5
|
||||
emote_hear = list("chirrups.")
|
||||
emote_see = list("chirrups.")
|
||||
|
||||
#undef GESTALT_ALERT
|
||||
#undef NYMPH_ALERT
|
||||
@@ -0,0 +1,184 @@
|
||||
// No AI controller for these guys - they should be inert if they're not player controlled.
|
||||
/mob/living/basic/spiderbot
|
||||
name = "Spider-bot"
|
||||
desc = "A skittering robotic friend!" // More like ultimate shitter
|
||||
icon = 'icons/mob/robots.dmi'
|
||||
icon_state = "spiderbot-chassis"
|
||||
icon_living = "spiderbot-chassis"
|
||||
icon_dead = "spiderbot-smashed"
|
||||
universal_speak = TRUE
|
||||
health = 40
|
||||
maxHealth = 40
|
||||
pass_flags = PASSTABLE
|
||||
|
||||
melee_damage_lower = 2
|
||||
melee_damage_upper = 2
|
||||
melee_damage_type = BURN
|
||||
attack_verb_continuous = "shocks"
|
||||
attack_verb_simple = "shocks"
|
||||
attack_sound = "sparks"
|
||||
|
||||
response_help_continuous = "pets"
|
||||
response_help_simple = "pet"
|
||||
response_disarm_continuous = "shoos"
|
||||
response_disarm_simple = "shoo"
|
||||
response_harm_continuous = "stomps on"
|
||||
response_harm_simple = "stomps on"
|
||||
speed = 0
|
||||
mob_biotypes = MOB_ROBOTIC
|
||||
mob_size = MOB_SIZE_SMALL
|
||||
speak_emote = list("beeps", "clicks", "chirps")
|
||||
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
minimum_survivable_temperature = 0
|
||||
maximum_survivable_temperature = 500
|
||||
|
||||
can_hide = TRUE
|
||||
ventcrawler = VENTCRAWLER_ALWAYS
|
||||
loot = list(/obj/effect/decal/cleanable/blood/gibs/robot)
|
||||
basic_mob_flags = DEL_ON_DEATH
|
||||
|
||||
/// Is it getting ready to explode?
|
||||
var/emagged = FALSE
|
||||
/// MMI it contains
|
||||
var/obj/item/mmi/mmi = null
|
||||
/// Who emagged the spiderbot
|
||||
var/mob/emagged_master = null
|
||||
|
||||
/mob/living/basic/spiderbot/Destroy()
|
||||
if(emagged)
|
||||
QDEL_NULL(mmi)
|
||||
explosion(get_turf(src), -1, -1, 3, 5, cause = "Emagged spiderbot destruction")
|
||||
else
|
||||
eject_brain()
|
||||
return ..()
|
||||
|
||||
/mob/living/basic/spiderbot/item_interaction(mob/living/user, obj/item/O, list/modifiers)
|
||||
if(istype(O, /obj/item/mmi))
|
||||
var/obj/item/mmi/B = O
|
||||
if(mmi) // There's already a brain in it.
|
||||
to_chat(user, "<span class='warning'>There's already a brain in [src]!</span>")
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
if(!B.brainmob)
|
||||
to_chat(user, "<span class='warning'>Sticking an empty MMI into the frame would sort of defeat the purpose.</span>")
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
if(!B.brainmob.key)
|
||||
var/ghost_can_reenter = 0
|
||||
if(B.brainmob.mind)
|
||||
for(var/mob/dead/observer/ghost in GLOB.player_list)
|
||||
if(ghost.ghost_flags & GHOST_CAN_REENTER && ghost.mind == B.brainmob.mind)
|
||||
ghost_can_reenter = 1
|
||||
break
|
||||
for(var/mob/living/basic/S in GLOB.player_list)
|
||||
if(HAS_TRAIT(S, TRAIT_RESPAWNABLE))
|
||||
ghost_can_reenter = 1
|
||||
break
|
||||
if(!ghost_can_reenter)
|
||||
to_chat(user, "<span class='notice'>[B] is completely unresponsive; there's no point.</span>")
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
if(B.brainmob.stat == DEAD)
|
||||
to_chat(user, "<span class='warning'>[B] is dead. Sticking it into the frame would sort of defeat the purpose.</span>")
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
if(jobban_isbanned(B.brainmob, "Cyborg") || jobban_isbanned(B.brainmob, "nonhumandept"))
|
||||
to_chat(user, "<span class='warning'>[B] does not seem to fit.</span>")
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
to_chat(user, "<span class='notice'>You install [B] in [src]!</span>")
|
||||
|
||||
user.drop_item()
|
||||
B.forceMove(src)
|
||||
mmi = B
|
||||
transfer_personality(B)
|
||||
|
||||
update_icon()
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
else if(istype(O, /obj/item/card/id) || istype(O, /obj/item/pda))
|
||||
if(!mmi)
|
||||
to_chat(user, "<span class='warning'>There's no reason to swipe your ID - the spiderbot has no brain to remove.</span>")
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
if(emagged)
|
||||
to_chat(user, "<span class='warning'>[src] doesn't seem to respond.</span>")
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
var/obj/item/card/id/id_card
|
||||
|
||||
if(istype(O, /obj/item/card/id))
|
||||
id_card = O
|
||||
else
|
||||
var/obj/item/pda/pda = O
|
||||
id_card = pda.id
|
||||
|
||||
if(ACCESS_ROBOTICS in id_card.access)
|
||||
to_chat(user, "<span class='notice'>You swipe your access card and pop the brain out of [src].</span>")
|
||||
eject_brain()
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You swipe your card, with no effect.</span>")
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
/mob/living/basic/spiderbot/welder_act(mob/user, obj/item/I)
|
||||
if(user.a_intent != INTENT_HELP)
|
||||
return
|
||||
if(user == src) // No self-repair dummy
|
||||
return
|
||||
if(health >= maxHealth)
|
||||
to_chat(user, "<span class='warning'>[src] does not need repairing!</span>")
|
||||
return
|
||||
. = TRUE
|
||||
if(!I.use_tool(src, user, volume = I.tool_volume))
|
||||
return
|
||||
adjustHealth(-5)
|
||||
add_fingerprint(user)
|
||||
user.visible_message("[user] repairs [src]!","<span class='notice'>You repair [src].</span>")
|
||||
|
||||
/mob/living/basic/spiderbot/emag_act(mob/living/user)
|
||||
if(emagged)
|
||||
to_chat(user, "<span class='warning'>[src] doesn't seem to respond.</span>")
|
||||
return 0
|
||||
else
|
||||
emagged = TRUE
|
||||
to_chat(user, "<span class='notice'>You short out the security protocols and rewrite [src]'s internal memory.</span>")
|
||||
to_chat(src, "<span class='userdanger'>You have been emagged; you are now completely loyal to [user] and [user.p_their()] every order!</span>")
|
||||
emagged_master = user
|
||||
add_attack_logs(user, src, "Emagged")
|
||||
maxHealth = 60
|
||||
health = 60
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 15
|
||||
attack_sound = 'sound/machines/defib_zap.ogg'
|
||||
return TRUE
|
||||
|
||||
/mob/living/basic/spiderbot/proc/transfer_personality(obj/item/mmi/M)
|
||||
mind = M.brainmob.mind
|
||||
mind.key = M.brainmob.key
|
||||
ckey = M.brainmob.ckey
|
||||
name = "Spider-bot ([M.brainmob.name])"
|
||||
if(emagged)
|
||||
to_chat(src, "<span class='userdanger'>You have been emagged; you are now completely loyal to [emagged_master] and [emagged_master.p_their()] every order!</span>")
|
||||
|
||||
/mob/living/basic/spiderbot/update_icon_state()
|
||||
if(mmi)
|
||||
if(istype(mmi, /obj/item/mmi))
|
||||
icon_state = "spiderbot-chassis-mmi"
|
||||
icon_living = "spiderbot-chassis-mmi"
|
||||
if(istype(mmi, /obj/item/mmi/robotic_brain))
|
||||
icon_state = "spiderbot-chassis-posi"
|
||||
icon_living = "spiderbot-chassis-posi"
|
||||
|
||||
else
|
||||
icon_state = "spiderbot-chassis"
|
||||
icon_living = "spiderbot-chassis"
|
||||
|
||||
/mob/living/basic/spiderbot/proc/eject_brain()
|
||||
if(mmi)
|
||||
var/turf/T = get_turf(src)
|
||||
mmi.forceMove(T)
|
||||
if(mind)
|
||||
mind.transfer_to(mmi.brainmob)
|
||||
mmi = null
|
||||
name = "Spider-bot"
|
||||
update_icon()
|
||||
Reference in New Issue
Block a user