mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-04-13 07:21:44 +01:00
Revises the OOC notes panel a bit, and removes the OOC notes panel from character setup, in favor of just adding buttons to set the likes and dislikes there, rather than maintaining two different versions of the panel. Additionally, adds a 'print to chat' button to the panel, and to examine for the OOC notes. Changes the way the window is sent to the client so that it behaves more like character setup. This should mitigate edge cases where the panel appears off screen when SS13 is not being displayed on the primary monitor. It SHOULD also remember its position between sessions. Either way it should stay on your screen now. Also, for the print to chat, character directory, and any OOC notes panel that isn't yours, the LIKES and DISLIKES sections will show up conditionally depending on if they are actually set up. If there's nothing there, then they won't show up. This is presently an imperfect revision, as it only allows you to have one OOC notes panel open at a time. I would like you to be able to have more than one at a time, while also having the features to allow it to always appear on the screen, however, that will take some extra development time. Apart from that, this is fully functional.
860 lines
40 KiB
Plaintext
860 lines
40 KiB
Plaintext
/obj/item/capture_crystal
|
|
name = "capture crystal"
|
|
desc = "A silent, unassuming crystal in what appears to be some kind of steel housing."
|
|
icon = 'icons/obj/capture_crystal_vr.dmi'
|
|
icon_state = "inactive"
|
|
drop_sound = 'sound/items/drop/ring.ogg'
|
|
pickup_sound = 'sound/items/pickup/ring.ogg'
|
|
throwforce = 0
|
|
force = 0
|
|
action_button_name = "Command"
|
|
|
|
var/active = FALSE //Is it set up?
|
|
var/mob/living/owner //Reference to the owner
|
|
var/mob/living/bound_mob //Reference to our bound mob
|
|
var/spawn_mob_type //The kind of mob an inactive crystal will try to spawn when activated
|
|
var/activate_cooldown = 30 SECONDS //How long do we wait between unleashing and recalling
|
|
var/last_activate //Automatically set by things that try to move the bound mob or capture things
|
|
var/empty_icon = "empty"
|
|
var/full_icon = "full"
|
|
var/capture_chance_modifier = 1 //So we can have special subtypes with different capture rates!
|
|
|
|
/obj/item/capture_crystal/Initialize()
|
|
. = ..()
|
|
update_icon()
|
|
|
|
//Let's make sure we clean up our references and things if the crystal goes away (such as when it's digested)
|
|
/obj/item/capture_crystal/Destroy()
|
|
if(bound_mob)
|
|
if(bound_mob in contents)
|
|
unleash()
|
|
to_chat(bound_mob, "<span class='notice'>You feel like yourself again. You are no longer under the influence of \the [src]'s command.</span>")
|
|
UnregisterSignal(bound_mob, COMSIG_PARENT_QDELETING)
|
|
bound_mob.capture_caught = FALSE
|
|
bound_mob = null
|
|
if(owner)
|
|
UnregisterSignal(owner, COMSIG_PARENT_QDELETING)
|
|
owner = null
|
|
return ..()
|
|
|
|
/obj/item/capture_crystal/examine(user)
|
|
. = ..()
|
|
if(user == owner && bound_mob)
|
|
. += "<span class = 'notice'>[bound_mob]'s crystal</span>"
|
|
if(isanimal(bound_mob))
|
|
. += "<span class = 'notice'>[bound_mob.health / bound_mob.maxHealth * 100]%</span>"
|
|
if(bound_mob.ooc_notes)
|
|
. += "<span class = 'deptradio'>OOC Notes:</span> <a href='?src=\ref[bound_mob];ooc_notes=1'>\[View\]</a> - <a href='?src=\ref[src];print_ooc_notes_to_chat=1'>\[Print\]</a>"
|
|
. += "<span class='deptradio'><a href='?src=\ref[bound_mob];vore_prefs=1'>\[Mechanical Vore Preferences\]</a></span>"
|
|
|
|
//Command! This lets the owner toggle hostile on AI controlled mobs, or send a silent command message to your bound mob, wherever they may be.
|
|
/obj/item/capture_crystal/ui_action_click()
|
|
if(!ismob(loc))
|
|
return
|
|
var/mob/living/M = src.loc
|
|
if(M != owner)
|
|
to_chat(M, "<span class='notice'>\The [src] emits an unpleasant tone... It does not respond to your command.</span>")
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
else if(!bound_mob)
|
|
to_chat(M, "<span class='notice'>\The [src] emits an unpleasant tone... There is nothing to command.</span>")
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
else if(isanimal(bound_mob) && !bound_mob.client)
|
|
if(!isnull(bound_mob.get_AI_stance()))
|
|
var/datum/ai_holder/AI = bound_mob.ai_holder
|
|
AI.hostile = !AI.hostile
|
|
if(!AI.hostile)
|
|
AI.set_stance(STANCE_IDLE)
|
|
to_chat(M, span("notice", "\The [bound_mob] is now [AI.hostile ? "hostile" : "passive"]."))
|
|
log_admin("[key_name_admin(M)] set [bound_mob] to [AI.hostile].")
|
|
else if(bound_mob.client)
|
|
var/transmit_msg = tgui_input_text(usr, "What is your command?", "Command")
|
|
if(length(transmit_msg) >= MAX_MESSAGE_LEN)
|
|
to_chat(M, "<span class='danger'>Your message was TOO LONG!:[transmit_msg]</span>")
|
|
return
|
|
transmit_msg = sanitize(transmit_msg, max_length = MAX_MESSAGE_LEN)
|
|
if(isnull(transmit_msg))
|
|
to_chat(M, "<span class='notice'>You decided against it.</span>")
|
|
return
|
|
to_chat(bound_mob, "<span class='notice'>\The [owner] commands, '[transmit_msg]'</span>")
|
|
to_chat(M, "<span class='notice'>Your command has been transmitted, '[transmit_msg]'</span>")
|
|
log_admin("[key_name_admin(M)] sent the command, '[transmit_msg]' to [bound_mob].")
|
|
else
|
|
to_chat(M, "<span class='notice'>\The [src] emits an unpleasant tone... \The [bound_mob] is unresponsive.</span>")
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
|
|
//Lets the owner get AI controlled bound mobs to follow them, or tells player controlled mobs to follow them.
|
|
/obj/item/capture_crystal/verb/follow_owner()
|
|
set name = "Toggle Follow"
|
|
set category = "Object"
|
|
set src in usr
|
|
if(!ismob(loc))
|
|
return
|
|
var/mob/living/M = src.loc
|
|
if(M != owner)
|
|
to_chat(M, "<span class='notice'>\The [src] emits an unpleasant tone... It does not respond to your command.</span>")
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
else if(bound_mob.stat != CONSCIOUS)
|
|
to_chat(M, "<span class='notice'>\The [src] emits an unpleasant tone... \The [bound_mob] is not able to hear your command.</span>")
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
else if(bound_mob.client)
|
|
to_chat(bound_mob, "<span class='notice'>\The [owner] wishes for you to follow them.</span>")
|
|
else if(bound_mob in contents)
|
|
if(!bound_mob.ai_holder)
|
|
to_chat(M, "<span class='notice'>\The [src] emits an unpleasant tone... \The [bound_mob] is not able to follow your command.</span>")
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
return
|
|
var/datum/ai_holder/AI = bound_mob.ai_holder
|
|
if(AI.leader)
|
|
to_chat(M, "<span class='notice'>\The [src] chimes~ \The [bound_mob] stopped following [AI.leader].</span>")
|
|
AI.lose_follow(AI.leader)
|
|
else
|
|
AI.set_follow(M)
|
|
to_chat(M, "<span class='notice'>\The [src] chimes~ \The [bound_mob] started following following [AI.leader].</span>")
|
|
else if(!(bound_mob in view(M)))
|
|
to_chat(M, "<span class='notice'>\The [src] emits an unpleasant tone... \The [bound_mob] is not able to hear your command.</span>")
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
if(!bound_mob.ai_holder)
|
|
to_chat(M, "<span class='notice'>\The [src] emits an unpleasant tone... \The [bound_mob] is not able to follow your command.</span>")
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
return
|
|
var/datum/ai_holder/AI = bound_mob.ai_holder
|
|
if(AI.leader)
|
|
to_chat(M, "<span class='notice'>\The [src] chimes~ \The [bound_mob] stopped following [AI.leader].</span>")
|
|
AI.lose_follow(AI.leader)
|
|
else
|
|
AI.set_follow(M)
|
|
to_chat(M, "<span class='notice'>\The [src] chimes~ \The [bound_mob] started following following [AI.leader].</span>")
|
|
|
|
//Don't really want people 'haha funny' capturing and releasing one another willy nilly. So! If you wanna release someone, you gotta destroy the thingy.
|
|
//(Which is consistent with how it works with digestion anyway.)
|
|
/obj/item/capture_crystal/verb/destroy_crystal()
|
|
set name = "Destroy Crystal"
|
|
set category = "Object"
|
|
set src in usr
|
|
if(!ismob(loc))
|
|
return
|
|
var/mob/living/M = src.loc
|
|
if(M != owner)
|
|
to_chat(M, "<span class='notice'>\The [src] is too hard for you to break.</span>")
|
|
else
|
|
M.visible_message("\The [M] crushes \the [src] into dust...", "\The [src] cracks and disintegrates in your hand.")
|
|
qdel(src)
|
|
|
|
//If you catch something/someone and want to give it to someone else though, that's fine.
|
|
/obj/item/capture_crystal/verb/release_ownership()
|
|
set name = "Release Ownership"
|
|
set category = "Object"
|
|
set src in usr
|
|
if(!ismob(loc))
|
|
return
|
|
var/mob/living/M = src.loc
|
|
if(M != owner)
|
|
to_chat(M, "<span class='notice'>\The [src] emits an unpleasant tone... It does not respond to your command.</span>")
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
else
|
|
M.visible_message("\The [src] flickers in \the [M]'s hand and emits a little tone.", "\The [src] flickers in your hand and emits a little tone.")
|
|
playsound(src, 'sound/effects/capture-crystal-out.ogg', 75, 1, -1)
|
|
UnregisterSignal(owner, COMSIG_PARENT_QDELETING)
|
|
owner = null
|
|
|
|
//Let's make inviting ghosts be an option you can do instead of an automatic thing!
|
|
/obj/item/capture_crystal/verb/invite_ghost()
|
|
set name = "Enhance (Toggle Ghost Join)"
|
|
set category = "Object"
|
|
set src in usr
|
|
if(!ismob(loc))
|
|
return
|
|
var/mob/living/U = src.loc
|
|
if(!bound_mob)
|
|
to_chat(U, "<span class='notice'>\The [src] emits an unpleasant tone... There is nothing to enhance.</span>")
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
return
|
|
else if(U != owner)
|
|
to_chat(U, "<span class='notice'>\The [src] emits an unpleasant tone... It does not respond to your command.</span>")
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
return
|
|
else if(bound_mob.client || !isanimal(bound_mob))
|
|
to_chat(U, "<span class='notice'>\The [src] emits an unpleasant tone... \The [bound_mob] is not eligable for enhancement.</span>")
|
|
playsound(src, 'sound/effects/capture-crystal-problem.ogg', 75, 1, -1)
|
|
return //Need to type cast the mob so it can detect ghostjoin
|
|
var/mob/living/simple_mob/M = bound_mob
|
|
if(M.ghostjoin)
|
|
M.ghostjoin = FALSE
|
|
to_chat(U, "<span class='notice'>\The [bound_mob] is no longer eligable to be joined by ghosts.</span>")
|
|
else if(tgui_alert(U, "Do you want to offer your [bound_mob] up to ghosts to play as? There is no way undo this once a ghost takes over.", "Invite ghosts?",list("No","Yes")) == "Yes")
|
|
M.ghostjoin = TRUE
|
|
to_chat(U, "<span class='notice'>\The [bound_mob] is now eligable to be joined by ghosts. It will need to be out of the crystal to be able to be joined.</span>")
|
|
else
|
|
to_chat(U, "<span class='notice'>You decided against it.</span>")
|
|
|
|
/obj/item/capture_crystal/update_icon()
|
|
. = ..()
|
|
if(spawn_mob_type)
|
|
icon_state = full_icon
|
|
else if(!bound_mob)
|
|
icon_state = "inactive"
|
|
else if(bound_mob in contents)
|
|
icon_state = full_icon
|
|
else
|
|
icon_state = empty_icon
|
|
if(!cooldown_check())
|
|
icon_state = "[icon_state]-busy"
|
|
spawn(activate_cooldown) //If it's busy then we want to wait a bit to fix the sprite after the cooldown is done.
|
|
update_icon()
|
|
|
|
/obj/item/capture_crystal/proc/cooldown_check()
|
|
if(world.time < last_activate + activate_cooldown)
|
|
return FALSE
|
|
else return TRUE
|
|
|
|
/obj/item/capture_crystal/attack(mob/living/M, mob/living/user)
|
|
if(bound_mob)
|
|
if(!bound_mob.devourable) //Don't eat if prefs are bad
|
|
return
|
|
if(user.zone_sel.selecting == "mouth") //Click while targetting the mouth and you eat/feed the stored mob to whoever you clicked on
|
|
if(bound_mob in contents)
|
|
user.visible_message("\The [user] moves \the [src] to [M]'s [M.vore_selected]...")
|
|
M.perform_the_nom(M, bound_mob, M, M.vore_selected)
|
|
else if(M == user) //You don't have a mob, you ponder the orb instead of trying to capture yourself
|
|
user.visible_message("\The [user] ponders \the [src]...", "You ponder \the [src]...")
|
|
else if (cooldown_check()) //Try to capture someone without throwing
|
|
user.visible_message("\The [user] taps \the [M] with \the [src].")
|
|
activate(user, M)
|
|
else
|
|
to_chat(user, "<span class='notice'>\The [src] emits an unpleasant tone... It is not ready yet.</span>")
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
|
|
//Tries to unleash or recall your stored mob
|
|
/obj/item/capture_crystal/attack_self(mob/living/user)
|
|
if(bound_mob && !owner)
|
|
if(bound_mob == user)
|
|
to_chat(user, "<span class='notice'>\The [src] emits an unpleasant tone... It does not activate for you.</span>")
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
return
|
|
if(tgui_alert(user, "\The [src] hasn't got an owner. It has \the [bound_mob] registered to it. Would you like to claim this as yours?", "Claim ownership", list("No","Yes")) == "Yes")
|
|
owner = user
|
|
if(!cooldown_check())
|
|
to_chat(user, "<span class='notice'>\The [src] emits an unpleasant tone... It is not ready yet.</span>")
|
|
if(bound_mob)
|
|
playsound(src, 'sound/effects/capture-crystal-problem.ogg', 75, 1, -1)
|
|
else
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
else if(user == bound_mob) //You can't recall yourself
|
|
to_chat(user, "<span class='notice'>\The [src] emits an unpleasant tone... It does not activate for you.</span>")
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
else if(!active)
|
|
activate(user)
|
|
else
|
|
determine_action(user)
|
|
|
|
//Make it so the crystal knows if its mob references get deleted to make sure things get cleaned up
|
|
/obj/item/capture_crystal/proc/knowyoursignals(mob/living/M, mob/living/U)
|
|
RegisterSignal(M, COMSIG_PARENT_QDELETING, PROC_REF(mob_was_deleted), TRUE)
|
|
RegisterSignal(U, COMSIG_PARENT_QDELETING, PROC_REF(owner_was_deleted), TRUE)
|
|
|
|
//The basic capture command does most of the registration work.
|
|
/obj/item/capture_crystal/proc/capture(mob/living/M, mob/living/U)
|
|
if(!M.capture_crystal || M.capture_caught)
|
|
to_chat(U, "<span class='warning'>This creature is not suitable for capture.</span>")
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
return
|
|
knowyoursignals(M, U)
|
|
owner = U
|
|
if(isanimal(M))
|
|
var/mob/living/simple_mob/S = M
|
|
S.revivedby = U.name
|
|
if(!bound_mob)
|
|
bound_mob = M
|
|
bound_mob.capture_caught = TRUE
|
|
persist_storable = FALSE
|
|
desc = "A glowing crystal in what appears to be some kind of steel housing."
|
|
|
|
//Determines the capture chance! So you can't capture AI mobs if they're perfectly healthy and all that
|
|
/obj/item/capture_crystal/proc/capture_chance(mob/living/M, user)
|
|
if(capture_chance_modifier >= 100) //Master crystal always work
|
|
return 100
|
|
var/capture_chance = ((1 - (M.health / M.maxHealth)) * 100) //Inverted health percent! 100% = 0%
|
|
//So I don't know how this works but here's a kind of explanation
|
|
//Basic chance + ((Mob's max health - minimum calculated health) / (Max allowed health - Min allowed health)*(Chance at Max allowed health - Chance at minimum allowed health)
|
|
capture_chance += 35 + ((M.maxHealth - 5)/ (1000-5)*(-100 - 35))
|
|
//Basically! Mobs over 1000 max health will be unable to be caught without using status effects.
|
|
//Thanks Aronai!
|
|
var/effect_count = 0 //This will give you a smol chance to capture if you have applied status effects, even if the chance would ordinarily be <0
|
|
if(M.stat == UNCONSCIOUS)
|
|
capture_chance += 0.1
|
|
effect_count += 1
|
|
else if(M.stat == CONSCIOUS)
|
|
capture_chance *= 0.9
|
|
else
|
|
capture_chance = 0
|
|
if(M.weakened) //Haha you fall down
|
|
capture_chance += 0.1
|
|
effect_count += 1
|
|
if(M.stunned) //What's the matter???
|
|
capture_chance += 0.1
|
|
effect_count += 1
|
|
if(M.on_fire) //AAAAAAAA
|
|
capture_chance += 0.1
|
|
effect_count += 1
|
|
if(M.paralysis) //Oh noooo
|
|
capture_chance += 0.1
|
|
effect_count += 1
|
|
if(M.ai_holder.stance == STANCE_IDLE) //SNEAK ATTACK???
|
|
capture_chance += 0.1
|
|
effect_count += 1
|
|
|
|
capture_chance *= capture_chance_modifier
|
|
|
|
if(capture_chance <= 0)
|
|
capture_chance = 0 + effect_count
|
|
if(capture_chance <= 0)
|
|
capture_chance = 0
|
|
to_chat(user, "<span class='notice'>There's no chance... It needs to be weaker.</span>")
|
|
|
|
last_activate = world.time
|
|
log_admin("[user] threw a capture crystal at [M] and got [capture_chance]% chance to catch.")
|
|
return capture_chance
|
|
|
|
//Handles checking relevent bans, preferences, and asking the player if they want to be caught
|
|
/obj/item/capture_crystal/proc/capture_player(mob/living/M, mob/living/U)
|
|
if(jobban_isbanned(M, "GhostRoles"))
|
|
to_chat(U, "<span class='warning'>This creature is not suitable for capture.</span>")
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
else if(!M.capture_crystal || M.capture_caught)
|
|
to_chat(U, "<span class='warning'>This creature is not suitable for capture.</span>")
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
else if(tgui_alert(M, "Would you like to be caught by in [src] by [U]? You will be bound to their will.", "Become Caught",list("No","Yes")) == "Yes")
|
|
if(tgui_alert(M, "Are you really sure? The only way to undo this is to OOC escape while you're in the crystal.", "Become Caught", list("No","Yes")) == "Yes")
|
|
log_admin("[key_name(M)] has agreed to become caught by [key_name(U)].")
|
|
capture(M, U)
|
|
recall(U)
|
|
return
|
|
to_chat(U, "<span class='warning'>This creature is too strong willed to be captured.</span>")
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
|
|
//The clean up procs!
|
|
/obj/item/capture_crystal/proc/mob_was_deleted()
|
|
UnregisterSignal(bound_mob, COMSIG_PARENT_QDELETING)
|
|
UnregisterSignal(owner, COMSIG_PARENT_QDELETING)
|
|
bound_mob.capture_caught = FALSE
|
|
bound_mob = null
|
|
owner = null
|
|
active = FALSE
|
|
persist_storable = TRUE
|
|
update_icon()
|
|
|
|
/obj/item/capture_crystal/proc/owner_was_deleted()
|
|
UnregisterSignal(owner, COMSIG_PARENT_QDELETING)
|
|
owner = null
|
|
active = FALSE
|
|
update_icon()
|
|
|
|
//If the crystal hasn't been set up, it does this
|
|
/obj/item/capture_crystal/proc/activate(mob/living/user, target)
|
|
if(!cooldown_check()) //Are we ready to do things yet?
|
|
to_chat(thrower, "<span class='notice'>\The [src] clicks unsatisfyingly... It is not ready yet.</span>")
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
return
|
|
if(spawn_mob_type && !bound_mob) //We don't already have a mob, but we know what kind of mob we want
|
|
bound_mob = new spawn_mob_type(src) //Well let's spawn it then!
|
|
bound_mob.faction = user.faction
|
|
spawn_mob_type = null
|
|
capture(bound_mob, user)
|
|
if(bound_mob) //We have a mob! Let's finish setting up.
|
|
user.visible_message("\The [src] clicks, and then emits a small chime.", "\The [src] grows warm in your hand, something inside is awake.")
|
|
active = TRUE
|
|
if(!owner) //Do we have an owner? It's pretty unlikely that this would ever happen! But it happens, let's claim the crystal.
|
|
owner = user
|
|
if(isanimal(bound_mob))
|
|
var/mob/living/simple_mob/S = bound_mob
|
|
S.revivedby = user.name
|
|
determine_action(user, target)
|
|
return
|
|
else if(isliving(target)) //So we don't have a mob, let's try to claim one! Is the target a mob?
|
|
var/mob/living/M = target
|
|
last_activate = world.time
|
|
if(M.capture_caught) //Can't capture things that were already caught.
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
to_chat(user, "<span class='notice'>\The [src] clicks unsatisfyingly... \The [M] is already under someone else's control.</span>")
|
|
return
|
|
else if(M.stat == DEAD) //Is it dead? We can't influence dead things.
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
to_chat(user, "<span class='notice'>\The [src] clicks unsatisfyingly... \The [M] is not in a state to be captured.</span>")
|
|
return
|
|
else if(M.client) //Is it player controlled?
|
|
capture_player(M, user) //We have to do things a little differently if so.
|
|
return
|
|
else if(!isanimal(M)) //So it's not player controlled, but it's also not a simplemob?
|
|
to_chat(user, "<span class='warning'>This creature is not suitable for capture.</span>")
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
return
|
|
var/mob/living/simple_mob/S = M
|
|
if(!S.ai_holder) //We don't really want to capture simplemobs that don't have an AI
|
|
to_chat(user, "<span class='warning'>This creature is not suitable for capture.</span>")
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
else if(prob(capture_chance(S, user))) //OKAY! So we have an NPC simplemob with an AI, let's calculate its capture chance! It varies based on the mob's condition.
|
|
capture(S, user) //We did it! Woo! We capture it!
|
|
user.visible_message("\The [src] clicks, and then emits a small chime.", "Alright! \The [S] was caught!")
|
|
recall(user)
|
|
active = TRUE
|
|
else //Shoot, it didn't work and now it's mad!!!
|
|
S.ai_holder.go_wake()
|
|
S.ai_holder.target = user
|
|
S.ai_holder.track_target_position()
|
|
S.ai_holder.set_stance(STANCE_FIGHT)
|
|
user.visible_message("\The [src] bonks into \the [S], angering it!")
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
to_chat(user, "<span class='notice'>\The [src] clicks unsatisfyingly.</span>")
|
|
update_icon()
|
|
return
|
|
//The target is not a mob, so let's not do anything.
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
to_chat(user, "<span class='notice'>\The [src] clicks unsatisfyingly.</span>")
|
|
|
|
//We're using the crystal, but what will it do?
|
|
/obj/item/capture_crystal/proc/determine_action(mob/living/U, T)
|
|
if(!cooldown_check()) //Are we ready yet?
|
|
to_chat(thrower, "<span class='notice'>\The [src] clicks unsatisfyingly... It is not ready yet.</span>")
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
return //No
|
|
if(bound_mob in contents) //Do we have our mob?
|
|
if(T)
|
|
unleash(U, T) //Yes, let's let it out!
|
|
else
|
|
unleash(U)
|
|
else if (bound_mob) //Do we HAVE a mob?
|
|
recall(U) //Yes, let's try to put it back in the crystal
|
|
else //No we don't have a mob, let's reset the crystal.
|
|
to_chat(U, "<span class='notice'>\The [src] clicks unsatisfyingly.</span>")
|
|
active = FALSE
|
|
update_icon()
|
|
owner = null
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
|
|
//Let's try to call our mob back!
|
|
/obj/item/capture_crystal/proc/recall(mob/living/user)
|
|
if(bound_mob in view(user)) //We can only recall it if we can see it
|
|
var/turf/turfmemory = get_turf(bound_mob)
|
|
if(isanimal(bound_mob) && bound_mob.ai_holder)
|
|
var/mob/living/simple_mob/M = bound_mob
|
|
M.ai_holder.go_sleep() //AI doesn't need to think when it's in the crystal
|
|
bound_mob.forceMove(src)
|
|
last_activate = world.time
|
|
bound_mob.visible_message("\The [user]'s [src] flashes, disappearing [bound_mob] in an instant!!!", "\The [src] pulls you back into confinement in a flash of light!!!")
|
|
animate_action(turfmemory)
|
|
playsound(src, 'sound/effects/capture-crystal-in.ogg', 75, 1, -1)
|
|
update_icon()
|
|
else
|
|
to_chat(user, "<span class='notice'>\The [src] clicks and emits a small, unpleasant tone. \The [bound_mob] cannot be recalled.</span>")
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
|
|
//Let's let our mob out!
|
|
/obj/item/capture_crystal/proc/unleash(mob/living/user, atom/target)
|
|
if(!user && !target) //We got thrown but we're not sure who did it, let's go to where the crystal is
|
|
var/drop_loc = get_turf(src)
|
|
if (drop_loc)
|
|
bound_mob.forceMove(drop_loc)
|
|
return
|
|
if(!target) //We know who wants to let us out, but they didn't say where, so let's drop us on them
|
|
bound_mob.forceMove(user.drop_location())
|
|
else //We got thrown! Let's go where we got thrown
|
|
bound_mob.forceMove(target.drop_location())
|
|
last_activate = world.time
|
|
if(isanimal(bound_mob))
|
|
var/mob/living/simple_mob/M = bound_mob
|
|
M.ai_holder.go_wake() //Okay it's time to do work, let's wake up!
|
|
bound_mob.faction = owner.faction //Let's make sure we aren't hostile to our owner or their friends
|
|
bound_mob.visible_message("\The [user]'s [src] flashes, \the [bound_mob] appears in an instant!!!", "The world around you rematerialize as you are unleashed from the [src] next to \the [user]. You feel a strong compulsion to enact \the [owner]'s will.")
|
|
animate_action(get_turf(bound_mob))
|
|
playsound(src, 'sound/effects/capture-crystal-out.ogg', 75, 1, -1)
|
|
update_icon()
|
|
|
|
//Let's make a flashy sparkle when someone appears or disappears!
|
|
/obj/item/capture_crystal/proc/animate_action(atom/thing)
|
|
var/image/coolanimation = image('icons/obj/capture_crystal_vr.dmi', null, "animation")
|
|
coolanimation.plane = PLANE_LIGHTING_ABOVE
|
|
thing.overlays += coolanimation
|
|
sleep(11)
|
|
thing.overlays -= coolanimation
|
|
|
|
//IF the crystal somehow ends up in a tummy and digesting with a bound mob who doesn't want to be eaten, let's move them to the ground
|
|
/obj/item/capture_crystal/digest_act(var/atom/movable/item_storage = null)
|
|
if(bound_mob in contents && !bound_mob.devourable)
|
|
bound_mob.forceMove(src.drop_location())
|
|
return ..()
|
|
|
|
//We got thrown! Let's figure out what to do
|
|
/obj/item/capture_crystal/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, datum/callback/callback)
|
|
. = ..()
|
|
if(target == bound_mob && thrower != bound_mob) //We got thrown at our bound mob (and weren't thrown by the bound mob) let's ignore the cooldown and just put them back in
|
|
recall(thrower)
|
|
else if(!cooldown_check()) //OTHERWISE let's obey the cooldown
|
|
to_chat(thrower, "<span class='notice'>\The [src] emits an soft tone... It is not ready yet.</span>")
|
|
if(bound_mob)
|
|
playsound(src, 'sound/effects/capture-crystal-problem.ogg', 75, 1, -1)
|
|
else
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
else if(!active) //The ball isn't set up, let's try to set it up.
|
|
if(isliving(target)) //We're hitting a mob, let's try to capture it.
|
|
sleep(10)
|
|
activate(thrower, target)
|
|
return
|
|
sleep(10)
|
|
activate(thrower, src)
|
|
else if(!bound_mob) //We hit something else, and we don't have a mob, so we can't really do anything!
|
|
to_chat(thrower, "<span class='notice'>\The [src] clicks unpleasantly...</span>")
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
else if(bound_mob in contents) //We have our mob! Let's try to let it out.
|
|
sleep(10)
|
|
unleash(thrower, src)
|
|
update_icon()
|
|
else //Our mob isn't here, we can't do anything.
|
|
to_chat(thrower, "<span class='notice'>\The [src] clicks unpleasantly...</span>")
|
|
playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1)
|
|
|
|
/obj/item/capture_crystal/basic
|
|
|
|
/obj/item/capture_crystal/great
|
|
name = "great capture crystal"
|
|
capture_chance_modifier = 1.5
|
|
|
|
/obj/item/capture_crystal/ultra
|
|
name = "ultra capture crystal"
|
|
capture_chance_modifier = 2
|
|
|
|
/obj/item/capture_crystal/master
|
|
name = "master capture crystal"
|
|
capture_chance_modifier = 100
|
|
|
|
/obj/item/capture_crystal/cass
|
|
spawn_mob_type = /mob/living/simple_mob/vore/woof/cass
|
|
/obj/item/capture_crystal/adg
|
|
spawn_mob_type = /mob/living/simple_mob/mechanical/mecha/combat/gygax/dark/advanced
|
|
/obj/item/capture_crystal/bigdragon
|
|
spawn_mob_type = /mob/living/simple_mob/vore/bigdragon
|
|
/obj/item/capture_crystal/bigdragon/friendly
|
|
spawn_mob_type = /mob/living/simple_mob/vore/bigdragon/friendly
|
|
/obj/item/capture_crystal/teppi
|
|
spawn_mob_type = /mob/living/simple_mob/vore/alienanimals/teppi
|
|
/obj/item/capture_crystal/broodmother
|
|
spawn_mob_type = /mob/living/simple_mob/animal/giant_spider/broodmother
|
|
/obj/item/capture_crystal/skeleton
|
|
spawn_mob_type = /mob/living/simple_mob/vore/alienanimals/skeleton
|
|
/obj/item/capture_crystal/dustjumper
|
|
spawn_mob_type = /mob/living/simple_mob/vore/alienanimals/dustjumper
|
|
|
|
/obj/item/capture_crystal/random
|
|
var/static/list/possible_mob_types = list(
|
|
list(/mob/living/simple_mob/animal/goat),
|
|
list(
|
|
/mob/living/simple_mob/animal/passive/bird,
|
|
/mob/living/simple_mob/animal/passive/bird/azure_tit,
|
|
/mob/living/simple_mob/animal/passive/bird/black_bird,
|
|
/mob/living/simple_mob/animal/passive/bird/european_robin,
|
|
/mob/living/simple_mob/animal/passive/bird/goldcrest,
|
|
/mob/living/simple_mob/animal/passive/bird/ringneck_dove,
|
|
/mob/living/simple_mob/animal/passive/bird/parrot,
|
|
/mob/living/simple_mob/animal/passive/bird/parrot/black_headed_caique,
|
|
/mob/living/simple_mob/animal/passive/bird/parrot/budgerigar,
|
|
/mob/living/simple_mob/animal/passive/bird/parrot/budgerigar/blue,
|
|
/mob/living/simple_mob/animal/passive/bird/parrot/budgerigar/bluegreen,
|
|
/mob/living/simple_mob/animal/passive/bird/parrot/cockatiel,
|
|
/mob/living/simple_mob/animal/passive/bird/parrot/cockatiel/grey,
|
|
/mob/living/simple_mob/animal/passive/bird/parrot/cockatiel/white,
|
|
/mob/living/simple_mob/animal/passive/bird/parrot/cockatiel/yellowish,
|
|
/mob/living/simple_mob/animal/passive/bird/parrot/eclectus,
|
|
/mob/living/simple_mob/animal/passive/bird/parrot/grey_parrot,
|
|
/mob/living/simple_mob/animal/passive/bird/parrot/kea,
|
|
/mob/living/simple_mob/animal/passive/bird/parrot/pink_cockatoo,
|
|
/mob/living/simple_mob/animal/passive/bird/parrot/sulphur_cockatoo,
|
|
/mob/living/simple_mob/animal/passive/bird/parrot/white_caique,
|
|
/mob/living/simple_mob/animal/passive/bird/parrot/white_cockatoo
|
|
),
|
|
list(
|
|
/mob/living/simple_mob/animal/passive/cat,
|
|
/mob/living/simple_mob/animal/passive/cat/black
|
|
),
|
|
list(/mob/living/simple_mob/animal/passive/chick),
|
|
list(/mob/living/simple_mob/animal/passive/cow),
|
|
list(/mob/living/simple_mob/animal/passive/dog/brittany),
|
|
list(/mob/living/simple_mob/animal/passive/dog/corgi),
|
|
list(/mob/living/simple_mob/animal/passive/dog/tamaskan),
|
|
list(/mob/living/simple_mob/animal/passive/fox),
|
|
list(/mob/living/simple_mob/animal/passive/hare),
|
|
list(/mob/living/simple_mob/animal/passive/lizard),
|
|
list(/mob/living/simple_mob/animal/passive/mouse),
|
|
list(/mob/living/simple_mob/animal/passive/mouse/jerboa),
|
|
list(/mob/living/simple_mob/animal/passive/opossum),
|
|
list(/mob/living/simple_mob/animal/passive/pillbug),
|
|
list(/mob/living/simple_mob/animal/passive/snake),
|
|
list(/mob/living/simple_mob/animal/passive/tindalos),
|
|
list(/mob/living/simple_mob/animal/passive/yithian),
|
|
list(
|
|
/mob/living/simple_mob/vore/wolf,
|
|
/mob/living/simple_mob/vore/wolf/direwolf
|
|
),
|
|
list(/mob/living/simple_mob/vore/rabbit),
|
|
list(/mob/living/simple_mob/vore/redpanda),
|
|
list(/mob/living/simple_mob/vore/woof),
|
|
list(/mob/living/simple_mob/vore/fennec),
|
|
list(/mob/living/simple_mob/vore/fennix),
|
|
list(/mob/living/simple_mob/vore/hippo),
|
|
list(/mob/living/simple_mob/vore/horse),
|
|
list(/mob/living/simple_mob/vore/bee),
|
|
list(
|
|
/mob/living/simple_mob/animal/space/bear,
|
|
/mob/living/simple_mob/animal/space/bear/brown
|
|
),
|
|
list(
|
|
/mob/living/simple_mob/vore/otie/feral,
|
|
/mob/living/simple_mob/vore/otie/feral/chubby,
|
|
/mob/living/simple_mob/vore/otie/red,
|
|
/mob/living/simple_mob/vore/otie/red/chubby
|
|
),
|
|
list(/mob/living/simple_mob/animal/sif/diyaab),
|
|
list(/mob/living/simple_mob/animal/sif/duck),
|
|
list(/mob/living/simple_mob/animal/sif/frostfly),
|
|
list(
|
|
/mob/living/simple_mob/animal/sif/glitterfly =50,
|
|
/mob/living/simple_mob/animal/sif/glitterfly/rare = 1
|
|
),
|
|
list(
|
|
/mob/living/simple_mob/animal/sif/kururak = 10,
|
|
/mob/living/simple_mob/animal/sif/kururak/leader = 1,
|
|
/mob/living/simple_mob/animal/sif/kururak/hibernate = 2,
|
|
),
|
|
list(
|
|
/mob/living/simple_mob/animal/sif/sakimm = 10,
|
|
/mob/living/simple_mob/animal/sif/sakimm/intelligent = 1
|
|
),
|
|
list(/mob/living/simple_mob/animal/sif/savik) = 5,
|
|
list(
|
|
/mob/living/simple_mob/animal/sif/shantak = 10,
|
|
/mob/living/simple_mob/animal/sif/shantak/leader = 1
|
|
),
|
|
list(/mob/living/simple_mob/animal/sif/siffet),
|
|
list(/mob/living/simple_mob/animal/sif/tymisian),
|
|
list(
|
|
/mob/living/simple_mob/animal/giant_spider/nurse = 10,
|
|
/mob/living/simple_mob/animal/giant_spider/electric = 5,
|
|
/mob/living/simple_mob/animal/giant_spider/frost = 5,
|
|
/mob/living/simple_mob/animal/giant_spider/hunter = 10,
|
|
/mob/living/simple_mob/animal/giant_spider/ion = 5,
|
|
/mob/living/simple_mob/animal/giant_spider/lurker = 10,
|
|
/mob/living/simple_mob/animal/giant_spider/pepper = 10,
|
|
/mob/living/simple_mob/animal/giant_spider/phorogenic = 10,
|
|
/mob/living/simple_mob/animal/giant_spider/thermic = 5,
|
|
/mob/living/simple_mob/animal/giant_spider/tunneler = 10,
|
|
/mob/living/simple_mob/animal/giant_spider/webslinger = 5,
|
|
/mob/living/simple_mob/animal/giant_spider/broodmother = 1),
|
|
list(
|
|
/mob/living/simple_mob/vore/wolf = 10,
|
|
/mob/living/simple_mob/vore/wolf/direwolf = 5,
|
|
/mob/living/simple_mob/vore/greatwolf = 1,
|
|
/mob/living/simple_mob/vore/greatwolf/black = 1,
|
|
/mob/living/simple_mob/vore/greatwolf/grey = 1
|
|
),
|
|
list(/mob/living/simple_mob/creature/strong),
|
|
list(/mob/living/simple_mob/faithless/strong),
|
|
list(/mob/living/simple_mob/animal/goat),
|
|
list(
|
|
/mob/living/simple_mob/animal/sif/shantak/leader = 1,
|
|
/mob/living/simple_mob/animal/sif/shantak = 10),
|
|
list(/mob/living/simple_mob/animal/sif/savik,),
|
|
list(/mob/living/simple_mob/animal/sif/hooligan_crab),
|
|
list(
|
|
/mob/living/simple_mob/animal/space/alien = 50,
|
|
/mob/living/simple_mob/animal/space/alien/drone = 40,
|
|
/mob/living/simple_mob/animal/space/alien/sentinel = 25,
|
|
/mob/living/simple_mob/animal/space/alien/sentinel/praetorian = 15,
|
|
/mob/living/simple_mob/animal/space/alien/queen = 10,
|
|
/mob/living/simple_mob/animal/space/alien/queen/empress = 5,
|
|
/mob/living/simple_mob/animal/space/alien/queen/empress/mother = 1
|
|
),
|
|
list(/mob/living/simple_mob/animal/space/bats/cult/strong),
|
|
list(
|
|
/mob/living/simple_mob/animal/space/bear,
|
|
/mob/living/simple_mob/animal/space/bear/brown
|
|
),
|
|
list(
|
|
/mob/living/simple_mob/animal/space/carp = 50,
|
|
/mob/living/simple_mob/animal/space/carp/large = 10,
|
|
/mob/living/simple_mob/animal/space/carp/large/huge = 5
|
|
),
|
|
list(/mob/living/simple_mob/animal/space/goose),
|
|
list(/mob/living/simple_mob/vore/jelly),
|
|
list(/mob/living/simple_mob/animal/space/tree),
|
|
list(
|
|
/mob/living/simple_mob/vore/aggressive/corrupthound = 10,
|
|
/mob/living/simple_mob/vore/aggressive/corrupthound/prettyboi = 1,
|
|
),
|
|
list(/mob/living/simple_mob/vore/aggressive/deathclaw),
|
|
list(/mob/living/simple_mob/vore/aggressive/dino),
|
|
list(/mob/living/simple_mob/vore/aggressive/dragon),
|
|
list(/mob/living/simple_mob/vore/aggressive/dragon/virgo3b),
|
|
list(/mob/living/simple_mob/vore/aggressive/frog),
|
|
list(/mob/living/simple_mob/vore/aggressive/giant_snake),
|
|
list(/mob/living/simple_mob/vore/aggressive/mimic),
|
|
list(/mob/living/simple_mob/vore/aggressive/panther),
|
|
list(/mob/living/simple_mob/vore/aggressive/rat),
|
|
list(/mob/living/simple_mob/vore/bee),
|
|
list(
|
|
/mob/living/simple_mob/vore/sect_drone = 10,
|
|
/mob/living/simple_mob/vore/sect_queen = 1
|
|
),
|
|
list(/mob/living/simple_mob/vore/solargrub),
|
|
list(
|
|
/mob/living/simple_mob/vore/oregrub = 5,
|
|
/mob/living/simple_mob/vore/oregrub/lava = 1
|
|
),
|
|
list(/mob/living/simple_mob/vore/catgirl),
|
|
list(/mob/living/simple_mob/vore/wolfgirl),
|
|
list(
|
|
/mob/living/simple_mob/vore/lamia,
|
|
/mob/living/simple_mob/vore/lamia/albino,
|
|
/mob/living/simple_mob/vore/lamia/albino/bra,
|
|
/mob/living/simple_mob/vore/lamia/albino/shirt,
|
|
/mob/living/simple_mob/vore/lamia/bra,
|
|
/mob/living/simple_mob/vore/lamia/cobra,
|
|
/mob/living/simple_mob/vore/lamia/cobra/bra,
|
|
/mob/living/simple_mob/vore/lamia/cobra/shirt,
|
|
/mob/living/simple_mob/vore/lamia/copper,
|
|
/mob/living/simple_mob/vore/lamia/copper/bra,
|
|
/mob/living/simple_mob/vore/lamia/copper/shirt,
|
|
/mob/living/simple_mob/vore/lamia/green,
|
|
/mob/living/simple_mob/vore/lamia/green/bra,
|
|
/mob/living/simple_mob/vore/lamia/green/shirt,
|
|
/mob/living/simple_mob/vore/lamia/zebra,
|
|
/mob/living/simple_mob/vore/lamia/zebra/bra,
|
|
/mob/living/simple_mob/vore/lamia/zebra/shirt
|
|
),
|
|
list(
|
|
/mob/living/simple_mob/humanoid/merc = 100,
|
|
/mob/living/simple_mob/humanoid/merc/melee/sword = 50,
|
|
/mob/living/simple_mob/humanoid/merc/ranged = 25,
|
|
/mob/living/simple_mob/humanoid/merc/ranged/grenadier = 1,
|
|
/mob/living/simple_mob/humanoid/merc/ranged/ionrifle = 10,
|
|
/mob/living/simple_mob/humanoid/merc/ranged/laser = 5,
|
|
/mob/living/simple_mob/humanoid/merc/ranged/rifle = 5,
|
|
/mob/living/simple_mob/humanoid/merc/ranged/smg = 5,
|
|
/mob/living/simple_mob/humanoid/merc/ranged/sniper = 1,
|
|
/mob/living/simple_mob/humanoid/merc/ranged/space = 10,
|
|
/mob/living/simple_mob/humanoid/merc/ranged/technician = 5
|
|
),
|
|
list(
|
|
/mob/living/simple_mob/humanoid/pirate = 3,
|
|
/mob/living/simple_mob/humanoid/pirate/ranged = 1
|
|
),
|
|
list(/mob/living/simple_mob/mechanical/combat_drone),
|
|
list(/mob/living/simple_mob/mechanical/corrupt_maint_drone),
|
|
list(
|
|
/mob/living/simple_mob/mechanical/hivebot = 100,
|
|
/mob/living/simple_mob/mechanical/hivebot/ranged_damage = 20,
|
|
/mob/living/simple_mob/mechanical/hivebot/ranged_damage/backline = 10,
|
|
/mob/living/simple_mob/mechanical/hivebot/ranged_damage/basic = 20,
|
|
/mob/living/simple_mob/mechanical/hivebot/ranged_damage/dot = 5,
|
|
/mob/living/simple_mob/mechanical/hivebot/ranged_damage/ion = 20,
|
|
/mob/living/simple_mob/mechanical/hivebot/ranged_damage/laser = 10,
|
|
/mob/living/simple_mob/mechanical/hivebot/ranged_damage/rapid = 2,
|
|
/mob/living/simple_mob/mechanical/hivebot/ranged_damage/siege = 1,
|
|
/mob/living/simple_mob/mechanical/hivebot/ranged_damage/siege/emp = 5,
|
|
/mob/living/simple_mob/mechanical/hivebot/ranged_damage/siege/fragmentation = 1,
|
|
/mob/living/simple_mob/mechanical/hivebot/ranged_damage/siege/radiation = 1,
|
|
/mob/living/simple_mob/mechanical/hivebot/ranged_damage/strong = 3,
|
|
/mob/living/simple_mob/mechanical/hivebot/ranged_damage/strong/guard = 3,
|
|
/mob/living/simple_mob/mechanical/hivebot/support = 8,
|
|
/mob/living/simple_mob/mechanical/hivebot/support/commander = 5,
|
|
/mob/living/simple_mob/mechanical/hivebot/support/commander/autofollow = 10,
|
|
/mob/living/simple_mob/mechanical/hivebot/swarm = 20,
|
|
/mob/living/simple_mob/mechanical/hivebot/tank = 20,
|
|
/mob/living/simple_mob/mechanical/hivebot/tank/armored = 20,
|
|
/mob/living/simple_mob/mechanical/hivebot/tank/armored/anti_bullet = 20,
|
|
/mob/living/simple_mob/mechanical/hivebot/tank/armored/anti_laser = 20,
|
|
/mob/living/simple_mob/mechanical/hivebot/tank/armored/anti_melee = 20,
|
|
/mob/living/simple_mob/mechanical/hivebot/tank/meatshield = 20
|
|
),
|
|
list(/mob/living/simple_mob/mechanical/infectionbot),
|
|
list(/mob/living/simple_mob/mechanical/mining_drone),
|
|
list(/mob/living/simple_mob/mechanical/technomancer_golem),
|
|
list(
|
|
/mob/living/simple_mob/mechanical/viscerator,
|
|
/mob/living/simple_mob/mechanical/viscerator/piercing
|
|
),
|
|
list(/mob/living/simple_mob/mechanical/wahlem),
|
|
list(/mob/living/simple_mob/animal/passive/fox/syndicate),
|
|
list(/mob/living/simple_mob/animal/passive/fox),
|
|
list(/mob/living/simple_mob/vore/wolf/direwolf),
|
|
list(/mob/living/simple_mob/vore/jelly),
|
|
list(
|
|
/mob/living/simple_mob/vore/otie/feral,
|
|
/mob/living/simple_mob/vore/otie/feral/chubby,
|
|
/mob/living/simple_mob/vore/otie/red,
|
|
/mob/living/simple_mob/vore/otie/red/chubby
|
|
),
|
|
list(
|
|
/mob/living/simple_mob/shadekin/blue = 100,
|
|
/mob/living/simple_mob/shadekin/green = 50,
|
|
/mob/living/simple_mob/shadekin/orange = 20,
|
|
/mob/living/simple_mob/shadekin/purple = 60,
|
|
/mob/living/simple_mob/shadekin/red = 40,
|
|
/mob/living/simple_mob/shadekin/yellow = 1
|
|
),
|
|
list(
|
|
/mob/living/simple_mob/vore/aggressive/corrupthound,
|
|
/mob/living/simple_mob/vore/aggressive/corrupthound/prettyboi
|
|
),
|
|
list(/mob/living/simple_mob/vore/aggressive/deathclaw),
|
|
list(/mob/living/simple_mob/vore/aggressive/dino),
|
|
list(/mob/living/simple_mob/vore/aggressive/dragon),
|
|
list(/mob/living/simple_mob/vore/aggressive/dragon/virgo3b),
|
|
list(/mob/living/simple_mob/vore/aggressive/frog),
|
|
list(/mob/living/simple_mob/vore/aggressive/giant_snake),
|
|
list(/mob/living/simple_mob/vore/aggressive/mimic),
|
|
list(/mob/living/simple_mob/vore/aggressive/panther),
|
|
list(/mob/living/simple_mob/vore/aggressive/rat),
|
|
list(/mob/living/simple_mob/vore/bee),
|
|
list(/mob/living/simple_mob/vore/catgirl),
|
|
list(/mob/living/simple_mob/vore/cookiegirl),
|
|
list(/mob/living/simple_mob/vore/fennec),
|
|
list(/mob/living/simple_mob/vore/fennix),
|
|
list(/mob/living/simple_mob/vore/hippo),
|
|
list(/mob/living/simple_mob/vore/horse),
|
|
list(/mob/living/simple_mob/vore/oregrub),
|
|
list(/mob/living/simple_mob/vore/rabbit),
|
|
list(
|
|
/mob/living/simple_mob/vore/redpanda = 50,
|
|
/mob/living/simple_mob/vore/redpanda/fae = 1
|
|
),
|
|
list(
|
|
/mob/living/simple_mob/vore/sect_drone = 10,
|
|
/mob/living/simple_mob/vore/sect_queen = 1
|
|
),
|
|
list(/mob/living/simple_mob/vore/solargrub),
|
|
list(/mob/living/simple_mob/vore/woof),
|
|
list(/mob/living/simple_mob/vore/alienanimals/teppi),
|
|
list(/mob/living/simple_mob/vore/alienanimals/space_ghost),
|
|
list(/mob/living/simple_mob/vore/alienanimals/catslug),
|
|
list(/mob/living/simple_mob/vore/alienanimals/space_jellyfish),
|
|
list(/mob/living/simple_mob/vore/alienanimals/startreader),
|
|
list(/mob/living/simple_mob/vore/bigdragon),
|
|
list(
|
|
/mob/living/simple_mob/vore/leopardmander = 50,
|
|
/mob/living/simple_mob/vore/leopardmander/blue = 10,
|
|
/mob/living/simple_mob/vore/leopardmander/exotic = 1
|
|
),
|
|
list(/mob/living/simple_mob/vore/sheep),
|
|
list(/mob/living/simple_mob/vore/weretiger),
|
|
list(/mob/living/simple_mob/vore/alienanimals/skeleton),
|
|
list(/mob/living/simple_mob/vore/alienanimals/dustjumper)
|
|
)
|
|
|
|
/obj/item/capture_crystal/random/Initialize()
|
|
var/subchoice = pickweight(possible_mob_types) //Some of the lists have nested lists, so let's pick one of them
|
|
var/choice = pickweight(subchoice) //And then we'll pick something from whatever's left
|
|
spawn_mob_type = choice //Now when someone uses this, we'll spawn whatever we picked!
|
|
return ..()
|
|
|
|
/mob/living
|
|
var/capture_crystal = TRUE //If TRUE, the mob is capturable. Otherwise it isn't.
|
|
var/capture_caught = FALSE //If TRUE, the mob has already been caught, and so cannot be caught again.
|