Merge branch 'master' into upstream-merge-8222

This commit is contained in:
Heroman
2022-02-19 18:41:29 +10:00
1251 changed files with 947582 additions and 38891 deletions
+3 -2
View File
@@ -6,6 +6,8 @@
icon = 'icons/obj/apc_repair.dmi'
icon_state = "apc_frame"
refund_amt = 2
build_wall_only = TRUE
matter = list(MAT_STEEL = 100, MAT_GLASS = 30)
/obj/item/frame/apc/try_build(turf/on_wall, mob/user as mob)
if (get_dist(on_wall, user)>1)
@@ -29,8 +31,7 @@
to_chat(user, "<span class='warning'>There is another network terminal here.</span>")
return
else
var/obj/item/stack/cable_coil/C = new /obj/item/stack/cable_coil(loc)
C.amount = 10
new /obj/item/stack/cable_coil(loc, 10)
to_chat(user, "You cut the cables and disassemble the unused power terminal.")
qdel(T)
new /obj/machinery/power/apc(loc, ndir, 1)
+1
View File
@@ -6,6 +6,7 @@
force = 2
throwforce = 2
w_class = 2.0
matter = list(MAT_STEEL = 50)
var/broken
attack_verb = list("annoyed")
var/static/radial_examine = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_examine")
@@ -43,7 +43,9 @@
/mob/living/simple_mob/attack_ghost(mob/observer/dead/user as mob)
if(!ghostjoin)
return ..()
if(jobban_isbanned(user, "GhostRoles"))
to_chat(user, "<span class='warning'>You cannot inhabit this creature because you are banned from playing ghost roles.</span>")
return
if(!evaluate_ghost_join(user))
return ..()
@@ -74,6 +76,10 @@
// Clean up the simplemob
ghostjoin = FALSE
ghostjoin_icon()
if(capture_caught)
to_chat(src, "<span class='notice'>You are bound to [revivedby], follow their commands within reason and to the best of your abilities, and avoid betraying or abandoning them.</span><span class= warning> You are allied with [revivedby]. Do not attack anyone for no reason. Of course, you may do scenes as you like, but you must still respect preferences.</span>")
visible_message("[src]'s eyes flicker with a curious intelligence.", runemessage = "looks around")
return
if(revivedby != "no one")
to_chat(src, "<span class='notice'>Where once your life had been rough and scary, you have been assisted by [revivedby]. They seem to be the reason you are on your feet again... so perhaps you should help them out.</span> <span class= warning> Being as you were revived, you are allied with the station. Do not attack anyone unless they are threatening the one who revived you. And try to listen to the one who revived you within reason. Of course, you may do scenes as you like, but you must still respect preferences.</span>")
visible_message("[src]'s eyes flicker with a curious intelligence.", runemessage = "looks around")
@@ -93,6 +99,10 @@
to_chat(D, "<span class='notice'>Sorry, someone else has already inhabited [src].</span>")
return FALSE
if(capture_caught && !D.client.prefs.capture_crystal)
to_chat(D, "<span class='notice'>Sorry, [src] is participating in capture mechanics, and your preferences do not allow for that.</span>")
return FALSE
// Insert whatever ban checks you want here if we ever add simplemob bans
return TRUE
+77 -27
View File
@@ -1,3 +1,16 @@
/*
* Contains:
* Flashlights
* Lamps
* Flares
* Chemlights
* Slime Extract
*/
/*
* Flashlights
*/
/obj/item/device/flashlight
name = "flashlight"
desc = "A hand-held emergency light."
@@ -7,15 +20,15 @@
slot_flags = SLOT_BELT
matter = list(MAT_STEEL = 50,MAT_GLASS = 20)
action_button_name = "Toggle Flashlight"
light_system = MOVABLE_LIGHT_DIRECTIONAL
light_range = 4 //luminosity when on
light_power = 0.8 //lighting power when on
light_color = "#FFFFFF" //LIGHT_COLOR_INCANDESCENT_FLASHLIGHT //lighting colour when on
light_cone_y_offset = -7
var/on = 0
var/obj/item/weapon/cell/cell
var/cell_type = /obj/item/weapon/cell/device
var/power_usage = 1
@@ -26,7 +39,7 @@
if(power_use && cell_type)
cell = new cell_type(src)
update_brightness()
/obj/item/device/flashlight/Destroy()
@@ -232,24 +245,34 @@
w_class = ITEMSIZE_TINY
power_use = 0
/obj/item/device/flashlight/color //Default color is blue, just roll with it.
/obj/item/device/flashlight/color //Default color is blue
name = "blue flashlight"
desc = "A hand-held emergency light. This one is blue."
desc = "A small flashlight. This one is blue."
icon_state = "flashlight_blue"
/obj/item/device/flashlight/color/green
name = "green flashlight"
desc = "A small flashlight. This one is green."
icon_state = "flashlight_green"
/obj/item/device/flashlight/color/purple
name = "purple flashlight"
desc = "A small flashlight. This one is purple."
icon_state = "flashlight_purple"
/obj/item/device/flashlight/color/red
name = "red flashlight"
desc = "A hand-held emergency light. This one is red."
desc = "A small flashlight. This one is red."
icon_state = "flashlight_red"
/obj/item/device/flashlight/color/orange
name = "orange flashlight"
desc = "A hand-held emergency light. This one is orange."
desc = "A small flashlight. This one is orange."
icon_state = "flashlight_orange"
/obj/item/device/flashlight/color/yellow
name = "yellow flashlight"
desc = "A hand-held emergency light. This one is yellow."
desc = "A small flashlight. This one is yellow."
icon_state = "flashlight_yellow"
/obj/item/device/flashlight/maglight
@@ -273,7 +296,11 @@
w_class = ITEMSIZE_TINY
power_use = 0
// the desk lamps are a bit special
/*
* Lamps
*/
// pixar desk lamp
/obj/item/device/flashlight/lamp
name = "desk lamp"
desc = "A desk lamp with an adjustable mount."
@@ -286,14 +313,6 @@
on = 1
light_system = STATIC_LIGHT
// green-shaded desk lamp
/obj/item/device/flashlight/lamp/green
desc = "A classic green-shaded desk lamp."
icon_state = "lampgreen"
center_of_mass = list("x" = 15,"y" = 11)
light_color = "#FFC58F"
/obj/item/device/flashlight/lamp/verb/toggle_light()
set name = "Toggle light"
set category = "Object"
@@ -302,7 +321,23 @@
if(!usr.stat)
attack_self(usr)
// FLARES
// green-shaded desk lamp
/obj/item/device/flashlight/lamp/green
desc = "A classic green-shaded desk lamp."
icon_state = "lampgreen"
center_of_mass = list("x" = 15,"y" = 11)
light_color = "#FFC58F"
// clown lamp
/obj/item/device/flashlight/lamp/clown
desc = "A whacky banana peel shaped lamp."
icon_state = "bananalamp"
center_of_mass = list("x" = 15,"y" = 11)
/*
* Flares
*/
/obj/item/device/flashlight/flare
name = "flare"
@@ -368,18 +403,20 @@
START_PROCESSING(SSobj, src)
return 1
//Glowsticks
/*
* Chemlights
*/
/obj/item/device/flashlight/glowstick
name = "green glowstick"
desc = "A green military-grade glowstick."
desc = "A green military-grade chemical light."
w_class = ITEMSIZE_SMALL
light_system = MOVABLE_LIGHT
light_range = 4
light_power = 0.9
light_color = "#49F37C"
icon_state = "glowstick"
item_state = "glowstick"
icon_state = "glowstick_green"
item_state = "glowstick_green"
var/fuel = 0
power_use = 0
@@ -414,32 +451,45 @@
/obj/item/device/flashlight/glowstick/red
name = "red glowstick"
desc = "A red military-grade glowstick."
desc = "A red military-grade chemical light."
light_color = "#FC0F29"
icon_state = "glowstick_red"
item_state = "glowstick_red"
/obj/item/device/flashlight/glowstick/blue
name = "blue glowstick"
desc = "A blue military-grade glowstick."
desc = "A blue military-grade chemical light."
light_color = "#599DFF"
icon_state = "glowstick_blue"
item_state = "glowstick_blue"
/obj/item/device/flashlight/glowstick/orange
name = "orange glowstick"
desc = "A orange military-grade glowstick."
desc = "A orange military-grade chemical light."
light_color = "#FA7C0B"
icon_state = "glowstick_orange"
item_state = "glowstick_orange"
/obj/item/device/flashlight/glowstick/yellow
name = "yellow glowstick"
desc = "A yellow military-grade glowstick."
desc = "A yellow military-grade chemical light."
light_color = "#FEF923"
icon_state = "glowstick_yellow"
item_state = "glowstick_yellow"
/obj/item/device/flashlight/glowstick/radioisotope
name = "radioisotope glowstick"
desc = "A radioisotope powered chemical light. Escaping particles light up the area far brighter on similar levels to flares and for longer"
icon_state = "glowstick_isotope"
item_state = "glowstick_isotope"
light_range = 8
light_power = 0.1
light_color = "#49F37C"
/*
* Slime Extract
*/
/obj/item/device/flashlight/slime
gender = PLURAL
@@ -1,9 +0,0 @@
/obj/item/device/flashlight/glowstick/radioisotope
name = "radioisotope glowstick"
desc = "A radioisotope powered glowstick. Escaping particles light up the area far brighter on similar levels to flares and for longer"
icon_state = "glowstick_blue"
item_state = "glowstick_blue"
light_range = 8
light_power = 0.1
light_color = "#599DFF"
@@ -16,7 +16,7 @@
var/obj/item/device/encryptionkey/keyslot2 = null
var/ks1type = null
var/ks2type = null
drop_sound = 'sound/items/drop/component.ogg'
pickup_sound = 'sound/items/pickup/component.ogg'
@@ -62,10 +62,12 @@
/obj/item/device/radio/headset/receive_range(freq, level, aiOverride = 0)
if (aiOverride)
playsound(loc, 'sound/effects/radio_common.ogg', 20, 1, 1, preference = /datum/client_preference/radio_sounds)
return ..(freq, level)
if(ishuman(src.loc))
var/mob/living/carbon/human/H = src.loc
if(H.l_ear == src || H.r_ear == src)
playsound(loc, 'sound/effects/radio_common.ogg', 20, 1, 1, preference = /datum/client_preference/radio_sounds)
return ..(freq, level)
return -1
@@ -409,7 +409,7 @@ GLOBAL_LIST_BOILERPLATE(premade_tele_beacons, /obj/item/device/perfect_tele_beac
if(confirm == "Eat it!")
var/obj/belly/bellychoice = tgui_input_list(usr, "Which belly?","Select A Belly", L.vore_organs)
if(bellychoice)
user.visible_message("<span class='warning'>[user] is trying to stuff \the [src] into [user.gender == MALE ? "his" : user.gender == FEMALE ? "her" : "their"] [bellychoice]!</span>","<span class='notice'>You begin putting \the [src] into your [bellychoice]!</span>")
user.visible_message("<span class='warning'>[user] is trying to stuff \the [src] into [user.gender == MALE ? "his" : user.gender == FEMALE ? "her" : "their"] [bellychoice.name]!</span>","<span class='notice'>You begin putting \the [src] into your [bellychoice.name]!</span>")
if(do_after(user,5 SECONDS,src))
user.unEquip(src)
forceMove(bellychoice)
+97
View File
@@ -0,0 +1,97 @@
/obj/item/tabloid
name = "tabloid magazine"
desc = "It's one of those trashy tabloid magazines. It looks pretty out of date."
icon = 'icons/obj/magazine.dmi'
icon_state = "magazine"
var/headline
var/static/list/tabloid_states = icon_states('icons/obj/magazine.dmi')
var/static/list/tabloid_publishers = list(
"\improper Solar Enquirer",
"\improper Stellar Examiner",
"\improper Antares Daily",
"\improper Weekly Galactic News",
"\improper Spiral"
)
var/static/list/tabloid_headlines = list(
"NARCOALGORITHMS: ARE YOUR CHILDREN SAFE?",
"ARE GMO HUMANS POISONOUS IN BED?",
"TOP 10 REASONS WHY OTHER SPECIES ARE A HOAX",
"CENTENNIAL POSITRONIC EXTENDS LIFESPAN WITH 1 SIMPLE TRICK",
"TOP 10 DANGEROUS FOODS WITH CHEMICALS",
"NEW TERRIFYING TEEN TREND: SUN-DIVING",
"HAS YOUR SPOUSE BEEN REPLACED BY AN ALIEN IMPOSTER? STUDIES SUGGEST YES!",
"SPACE CAUSES CANCER: DOCTORS CONFIRM",
"ARE BODY SCANNERS TOO INVASIVE? FIND OUT INSIDE!",
"HAS SCIENCE GONE TOO FAR? LOCAL SCIENTIST DEBUNKS ALIEN THEORY, DECRIES THEM AS TUBE EXPERIMENTS GONE WRONG",
"100 DELICIOUS RECIPES LETHAL TO CARBON-BASED LIFE",
"TOP FIVE SPECIES WE DROVE TO EXTINCTION; NUMBER TWO WILL SHOCK YOU",
"LOCAL MAN HAS SEIZURE AFTER SAYING SKRELLIAN NAME; FORCED ASSIMILATION SOON?",
"RELIGION WAS RIGHT? SHOCK FINDINGS SHOW ALIEN SIMILARITY TO ANIMALS, EXISTENCE OF BOATS",
"TOP TEN REASONS WHY ONLY HUMANS ARE SENTIENT",
"LOCAL UNATHI SYMPATHIZER: 'I really think you should stop with these spacebaiting articles.'",
"DO UNATHI SYMPATHIZERS HATE THE HUMAN RACE?",
"WHICH PLANET HAS THE BEST LOVERS? THIS AND MORE INSIDE!",
"SHE SAID WE SHOULD SEE OTHER PEOPLE, SO I MARRIED A TESHARI PACK: FULL STORY INSIDE",
"LOSE WEIGHT THREE TIMES FASTER WITH THESE LOW-G MANEUVERS!",
"SHOCKING FIGURES REVEAL MORE TEENS DIE TO UNATHI HONOUR DUELS THAN GUN VIOLENCE",
"MY DAUGHTER JOINED A NEURAL COLLECTIVE AND NOW SHE CAN TASTE SPACETIME: FULL STORY INSIDE",
"WERE THE NAZIS PSYCHIC? ONE HISTORIAN TELLS ALL",
"TAJARANS: CUTE AND CUDDLY, OR INFILTRATING THE GOVERNMENT? FIND OUT MORE INSIDE",
"IS THE SOLAR GOVERNMENT CREATING AN AI SUPERINTELLIGENCE NEAR MERCURY? ONE EXPERT REVEALS SHOCKING INSIDER DETAILS!",
"TOP TEN HISTORICAL FIGURES THAT WERE TWO PROMETHEANS IN A TRENCHCOAT",
"ZADDAT: FACT OR FICTION?",
"TOP 10 SECRET AUGMENTS THE GOVERNMENT DOESN'T WANT YOU TO GET",
"ENLARGE YOUR MENTAL FACULTIES WITH THIS 1 WEIRD HAT",
"'HELP, MY SON THINKS HE'S A 20TH CENTURY VID CHARACTER CALLED SPOCK' AND MORE SHOCKING TALES INSIDE",
"18 RADICAL HIP IMPLANTS ALL THE KIDS ARE GETTING!",
"PRESERVED HEAD OF 21ST CENTURY CAPITALIST INSISTS THAT 'DYSON WALL' ONLY SANE SOLUTION TO RIMWARD MALCONTENTS",
"50 SHADES OF GREEN; BESTSELLING MULTISPECIES ROMANCE COMING TO CINEMAS",
"PLUTO: DWARF PLANET, OR SECRET RAMPANT AI FACILITY HELL-BENT ON CORRUPTING YOUR CHILDREN?",
"TOP TEN ANIME ALIENS. NUMBER 3 WILL SICKEN YOU",
"OCTUBER X'RALLBRE EXPOSED; NUDE PHOTOSHOOT LEAKS",
"WAR ON MARS AFTER NAKED MAN WAS FOUND; WERE THE ROMANS RIGHT?",
"REAL ALIENS ARGUE EARTH MOVIES RACIST!",
"HELP! I MARRIED A HEGEMONOUS SWARM INTELLIGENCE AND MY SON THINKS HE'S A ROUTER!",
"POSITRONICS: HUMAN INGENUITY AND GENEROSITY, OR A HORRIBLE MISTAKE? FIND OUT INSIDE!",
"TENTACLES OF TERROR: SKRELL BLACK OPS SEIGE NYX NAVAL DEPOT. SHOCKING PHOTOGRAPHS INSIDE!",
"THE FREE TRADER UNION: NEITHER FREE NOR A UNION. SHOCKING EXPOSE!",
"HAS THE FREE MARKET GONE TOO FAR? LUNA GLITTERPOP STAR AUCTIONS THIRD TESTICLE FOR TRANS-ORBITAL SHIPPING BONDS",
"THEY SAID IT WAS CANCER, BUT I KNEW IT WAS A TINY, SELF-REPLICATING CLONE OF RAY KURZWEIL: FULL STORY INSIDE",
"WHAT HAS TECHNOLOGY DONE? INDUSTRY BILLIONAIRE MARRIES OWN INFORMORPH MIND-COPY",
"REPTILLIAN ICE WARRIORS FROM ANOTHER WORLD LIVE INSIDE YOUR AIR DUCTS: HERE'S HOW TO GET RID OF THEM",
"10 CRITICAL THINGS YOU NEED TO KNOW ABOUT 'DRONEGATE'",
"THEY CALL THEM JUMPGATES BUT I'VE NEVER SEEN THEM JUMP: AN INDUSTRY INSIDER SPEAKS FOR THE FIRST TIME",
"EMERGENT INTELLIGENCES ARE STEALING YOUR BANK DETAILS, FETISHES: FOIL HAT RECIPE INSIDE",
"TIME TRAVELLERS ARE STEALING YOUR WIFI: 5 TIPS FOR DEFEATING HACKERS FROM THE FUTURE",
"'My mother was an alien spy': THIS CELEBRITY REVEAL WILL SHOCK AND AMAZE YOU",
"LUMINARY SCIENTIST SPEAKS: DIABETES IS A HYPERCORP RETROVIRUS!",
"'I REROUTED MY NEURAL CIRCUITRY SO THAT PAIN TASTES OF STRAWBERRIES' AND FIFTEEN OTHER CRAZY ALMACH STORIES",
"JOINING THE NAVY? HERE'S 15 EXPERT TIPS FOR AVOIDING BRAIN PARASITES"
)
/obj/item/tabloid/Initialize()
. = ..()
pixel_x = 5-rand(10)
pixel_x = 5-rand(10)
icon_state = pick(tabloid_states)
headline = pick(tabloid_headlines)
name = pick(tabloid_publishers)
/obj/item/tabloid/examine(mob/user, distance)
. = ..()
if(headline)
to_chat(user, "The headline screams, \"[headline]\"")
/obj/item/tabloid/attack_self(mob/user)
user.visible_message(SPAN_NOTICE("\The [user] leafs idly through \the [src]."))
if(headline)
to_chat(user, "Most of it is the usual tabloid garbage, but the headline story, \"[headline]\", holds your attention for awhile.")
if(tabloid_headlines[headline])
to_chat(user, tabloid_headlines[headline])
else
to_chat(user, "Most of it is the usual tabloid garbage. You find nothing of interest.")
return TRUE
+14
View File
@@ -259,6 +259,17 @@
new_desc = "A very retro APLU unit; didn't they retire these back in 2543?"
new_icon = "ripley-old"
allowed_types = list("ripley")
var/showpilot = TRUE
var/showpilot_lift = 5
/obj/item/device/kit/paint/ripley/customize(obj/mecha/M, mob/user)
if(showpilot)
M.show_pilot = TRUE
M.pilot_lift = 5
else
M.show_pilot = FALSE
M.pilot_lift = 0
. = ..()
/obj/item/device/kit/paint/ripley/death
name = "\"Reaper\" APLU customisation kit"
@@ -266,18 +277,21 @@
new_desc = "A terrifying, grim power loader. Why do those clamps have spikes?"
new_icon = "deathripley"
allowed_types = list("ripley","firefighter")
showpilot = FALSE
/obj/item/device/kit/paint/ripley/flames_red
name = "\"Firestarter\" APLU customisation kit"
new_name = "APLU \"Firestarter\""
new_desc = "A standard APLU exosuit with stylish orange flame decals."
new_icon = "ripley_flames_red"
showpilot = FALSE
/obj/item/device/kit/paint/ripley/flames_blue
name = "\"Burning Chrome\" APLU customisation kit"
new_name = "APLU \"Burning Chrome\""
new_desc = "A standard APLU exosuit with stylish blue flame decals."
new_icon = "ripley_flames_blue"
showpilot = FALSE
// Durand kits.
/obj/item/device/kit/paint/durand
@@ -8,6 +8,7 @@
R.add_language(LANGUAGE_ENOCHIAN, 1)
R.add_language(LANGUAGE_SLAVIC, 1)
R.add_language(LANGUAGE_DRUDAKAR, 1)
R.add_language(LANGUAGE_TAVAN, 1)
return 1
else
return 0
@@ -127,7 +127,7 @@ var/list/marker_beacon_colors = list(
if(istype(I, /obj/item/stack/marker_beacon))
var/obj/item/stack/marker_beacon/M = I
to_chat(user, "<span class='notice'>You start picking [src] up...</span>")
if(do_after(user, remove_speed, target = src) && M.amount + 1 <= M.max_amount)
if(do_after(user, remove_speed, target = src) && M.get_amount() + 1 <= M.max_amount)
M.add(1)
playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
qdel(src)
+48 -7
View File
@@ -17,7 +17,7 @@
center_of_mass = null
var/list/datum/stack_recipe/recipes
var/singular_name
var/amount = 1
VAR_PROTECTED/amount = 1
var/max_amount //also see stack recipes initialisation, param "max_res_amount" must be equal to this max_amount
var/stacktype //determines whether different stack types can merge
var/build_type = null //used when directly applied to a turf
@@ -29,12 +29,19 @@
var/pass_color = FALSE // Will the item pass its own color var to the created item? Dyed cloth, wood, etc.
var/strict_color_stacking = FALSE // Will the stack merge with other stacks that are different colors? (Dyed cloth, wood, etc)
/obj/item/stack/Initialize(var/ml, var/amount)
/obj/item/stack/Initialize(var/ml, var/starting_amount)
. = ..()
if(!stacktype)
stacktype = type
if(amount)
src.amount = amount
if(!isnull(starting_amount)) // Could be 0
// Negative numbers are 'give full stack', like -1
if(starting_amount < 0)
// But sometimes a coder forgot to define what that even means
if(max_amount)
starting_amount = max_amount
else
starting_amount = 1
set_amount(starting_amount, TRUE)
update_icon()
/obj/item/stack/Destroy()
@@ -229,12 +236,15 @@
//Return 1 if an immediate subsequent call to use() would succeed.
//Ensures that code dealing with stacks uses the same logic
/obj/item/stack/proc/can_use(var/used)
if (get_amount() < used)
if(used < 0 || used % 1)
stack_trace("Tried to use a bad stack amount: [used]")
return 0
if(get_amount() < used)
return 0
return 1
/obj/item/stack/proc/use(var/used)
if (!can_use(used))
if(!can_use(used))
return 0
if(!uses_charge)
amount -= used
@@ -251,6 +261,9 @@
return 1
/obj/item/stack/proc/add(var/extra)
if(extra < 0 || extra % 1)
stack_trace("Tried to add a bad stack amount: [extra]")
return 0
if(!uses_charge)
if(amount + extra > get_max_amount())
return 0
@@ -265,6 +278,27 @@
var/datum/matter_synth/S = synths[i]
S.add_charge(charge_costs[i] * extra)
/obj/item/stack/proc/set_amount(var/new_amount, var/no_limits = FALSE)
if(new_amount < 0 || new_amount % 1)
stack_trace("Tried to set a bad stack amount: [new_amount]")
return 0
// Clean up the new amount
new_amount = max(round(new_amount), 0)
// Can exceed max if you really want
if(new_amount > max_amount && !no_limits)
new_amount = max_amount
amount = new_amount
// Can set it to 0 without qdel if you really want
if(amount == 0 && !no_limits)
qdel(src)
return FALSE
return TRUE
/*
The transfer and split procs work differently than use() and add().
Whereas those procs take no action if the desired amount cannot be added or removed these procs will try to transfer whatever they can.
@@ -282,6 +316,10 @@
if (isnull(tamount))
tamount = src.get_amount()
if(tamount < 0 || tamount % 1)
stack_trace("Tried to transfer a bad stack amount: [tamount]")
return 0
var/transfer = max(min(tamount, src.get_amount(), (S.get_max_amount() - S.get_amount())), 0)
@@ -302,7 +340,10 @@
if(uses_charge)
return null
tamount = round(tamount)
if(tamount < 0 || tamount % 1)
stack_trace("Tried to split a bad stack amount: [tamount]")
return null
var/transfer = max(min(tamount, src.amount, initial(max_amount)), 0)
var/orig_amount = src.amount
+40 -83
View File
@@ -2,7 +2,7 @@
* Mech toys (previously labeled prizes, but that's unintuitive)
* Mech toy combat
*/
// Mech battle special attack types.
#define SPECIAL_ATTACK_HEAL 1
#define SPECIAL_ATTACK_DAMAGE 2
@@ -17,7 +17,7 @@
icon_state = "ripleytoy"
drop_sound = 'sound/mecha/mechstep.ogg'
reach = 2 // So you can battle across the table!
// Mech Battle Vars
var/timer = 0 // Timer when it'll be off cooldown
var/cooldown = 1.5 SECONDS // Cooldown between play sessions (and interactions)
@@ -34,7 +34,7 @@
var/special_attack_cooldown = 0 // Current cooldown of their special attack
var/wins = 0 // This mech's win count in combat
var/losses = 0 // ...And their loss count in combat
/obj/item/toy/mecha/Initialize()
. = ..()
desc = "Mini-Mecha action figure! Collect them all! Attack your friends or another mech with one to initiate epic mech combat! [desc]."
@@ -58,12 +58,11 @@
return 0 //not in range and not telekinetic
/**
* this proc combines "sleep" while also checking for if the battle should continue
* this proc combines "sleep" while also checking for if the battle should continue
*
* this goes through some of the checks - the toys need to be next to each other to fight!
* if it's player vs themself: They need to be able to "control" both mechs (either must be adjacent or using TK).
* if it's player vs player: Both players need to be able to "control" their mechs (either must be adjacent or using TK).
* if it's player vs mech (suicide): the mech needs to be in range of the player.
* if all the checks are TRUE, it does the sleeps, and returns TRUE. Otherwise, it returns FALSE.
* Arguments:
* * delay - the amount of time the sleep at the end of the check will sleep for
@@ -113,7 +112,7 @@
// If all that is good, then we can sleep peacefully.
sleep(delay)
return TRUE
//all credit to skasi for toy mech fun ideas
/obj/item/toy/mecha/attack_self(mob/user)
if(timer < world.time)
@@ -131,15 +130,15 @@
attack_self(user)
/**
* If you attack a mech with a mech, initiate combat between them
* If you attack a mech with a mech, initiate combat between them
*/
/obj/item/toy/mecha/attackby(obj/item/user_toy, mob/living/user)
if(istype(user_toy, /obj/item/toy/mecha))
if(istype(user_toy, /obj/item/toy/mecha))
var/obj/item/toy/mecha/M = user_toy
if(check_battle_start(user, M))
mecha_brawl(M, user)
..()
/**
* Attack is called from the user's toy, aimed at target(another human), checking for target's toy.
*/
@@ -196,48 +195,6 @@
if(wants_to_battle)
wants_to_battle = FALSE
to_chat(user, "<span class='notice'>You get the feeling they don't want to battle.</span>")
/**
* Starts a battle, toy mech vs player. Player... doesn't win. Commented out for now as suicide_act is not physically doable.
*/
/obj/item/toy/mecha/suicide_act(mob/living/carbon/user)
if(in_combat)
to_chat(user, "<span class='notice'>[src] is in battle, let it finish first.</span>")
return
var/datum/gender/T = gender_datums[user.get_visible_gender()]
user.visible_message("<span class='suicide'>[user] begins a fight [T.His] can't win with [src]! It looks like [T.His] trying to commit suicide!</span>")
in_combat = TRUE
sleep(1.5 SECONDS)
for(var/i in 1 to 4)
switch(i)
if(1, 3)
SpinAnimation(5, 0)
playsound(src, 'sound/mecha/mechstep.ogg', 30, TRUE)
user.adjustBruteLoss(25)
if(2)
user.SpinAnimation(5, 0)
playsound(user, 'sound/weapons/smash.ogg', 20, TRUE)
combat_health-- //we scratched it!
if(4)
visible_message(special_attack_cry + "!!")
if(!combat_sleep(1 SECONDS, null, user))
visible_message("PATHETIC.")
combat_health = max_combat_health
in_combat = FALSE
return (BRUTELOSS)
sleep(0.5 SECONDS)
user.adjustBruteLoss(450)
in_combat = FALSE
visible_message("AN EASY WIN. MY POWER INCREASES.") // steal a soul, become swole
color= "#ff7373"
max_combat_health = round(max_combat_health*1.5 + 0.1)
combat_health = max_combat_health
wins++
return (BRUTELOSS)
/obj/item/toy/mecha/examine()
. = ..()
@@ -284,9 +241,9 @@
sleep(1 SECONDS)
//--THE BATTLE BEGINS--
while(combat_health > 0 && attacker.combat_health > 0 && battle_length < MAX_BATTLE_LENGTH)
while(combat_health > 0 && attacker.combat_health > 0 && battle_length < MAX_BATTLE_LENGTH)
if(!combat_sleep(0.5 SECONDS, attacker, attacker_controller, opponent)) //combat_sleep checks everything we need to have checked for combat to continue
break
break
//before we do anything - deal with charged attacks
if(special_attack_charged)
@@ -312,7 +269,7 @@
attacker.special_attack_charged = TRUE
attacker_controller.visible_message("<span class='danger'> [attacker] begins charging its special attack!! </span>", \
"<span class='danger'> You begin charging [attacker]'s special attack! </span>")
else //just attack
else //just attack
attacker.SpinAnimation(5, 0)
playsound(attacker, 'sound/mecha/mechstep.ogg', 30, TRUE)
combat_health--
@@ -365,7 +322,7 @@
special_attack_charged = TRUE
src_controller.visible_message("<span class='danger'> [src] begins charging its special attack!! </span>", \
"<span class='danger'> You begin charging [src]'s special attack! </span>")
else //just attack
else //just attack
SpinAnimation(5, 0)
playsound(src, 'sound/mecha/mechstep.ogg', 30, TRUE)
attacker.combat_health--
@@ -376,12 +333,12 @@
attacker.combat_health--
playsound(attacker, 'sound/effects/meteorimpact.ogg', 20, TRUE)
src_controller.visible_message("<span class='boldwarning'> ...and lands a CRIPPLING BLOW! </span>", \
"<span class='boldwarning'> ...and you land a CRIPPLING blow on [attacker]! </span>", null)
"<span class='boldwarning'> ...and you land a CRIPPLING blow on [attacker]! </span>", null)
else
attacker_controller.visible_message("<span class='notice'> [src] and [attacker] stand around awkwardly.</span>", \
"<span class='notice'> You don't know what to do next.</span>")
"<span class='notice'> You don't know what to do next.</span>")
battle_length++
battle_length++
sleep(0.5 SECONDS)
/// Lines chosen for the winning mech
@@ -390,7 +347,7 @@
if(attacker.combat_health <= 0 && combat_health <= 0) //both lose
playsound(src, 'sound/machines/warning-buzzer.ogg', 20, TRUE)
attacker_controller.visible_message("<span class='boldnotice'> MUTUALLY ASSURED DESTRUCTION!! [src] and [attacker] both end up destroyed!</span>", \
"<span class='boldnotice'> Both [src] and [attacker] are destroyed!</span>")
"<span class='boldnotice'> Both [src] and [attacker] are destroyed!</span>")
else if(attacker.combat_health <= 0) //src wins
wins++
attacker.losses++
@@ -402,7 +359,7 @@
"<span class='notice'> You raise up [src] victoriously over [attacker]!</span>")
else if (combat_health <= 0) //attacker wins
attacker.wins++
losses++
losses++
playsound(src, 'sound/effects/light_flicker.ogg', 20, TRUE)
src_controller.visible_message("<span class='notice'> [src] collapses!</span>", \
"<span class='notice'> [src] collapses!</span>", null)
@@ -417,7 +374,7 @@
in_combat = FALSE
attacker.in_combat = FALSE
combat_health = max_combat_health
combat_health = max_combat_health
attacker.combat_health = attacker.max_combat_health
return
@@ -425,49 +382,49 @@
/**
* This proc checks if a battle can be initiated between src and attacker.
*
* Both SRC and attacker (if attacker is included) timers are checked if they're on cooldown, and
* Both SRC and attacker (if attacker is included) timers are checked if they're on cooldown, and
* both SRC and attacker (if attacker is included) are checked if they are in combat already.
* If any of the above are true, the proc returns FALSE and sends a message to user (and target, if included) otherwise, it returns TRUE
* Arguments:
* * user: the user who is initiating the battle
* * attacker: optional arg for checking two mechs at once
* * attacker: optional arg for checking two mechs at once
* * target: optional arg used in Mech PvP battles (if used, attacker is target's toy)
*/
/obj/item/toy/mecha/proc/check_battle_start(mob/living/carbon/user, obj/item/toy/mecha/attacker, mob/living/carbon/target)
var/datum/gender/T
/obj/item/toy/mecha/proc/check_battle_start(mob/living/carbon/user, obj/item/toy/mecha/attacker, mob/living/carbon/target)
var/datum/gender/T
if(target)
T = gender_datums[target.get_visible_gender()] // Doing this because Polaris Code has shitty gender datums and it's clunkier than FUCK.
if(attacker && attacker.in_combat)
to_chat(user, "<span class='notice'>[target ? T.His : "Your" ] [attacker.name] is in combat.</span>")
if(target)
if(target)
to_chat(target, "<span class='notice'>Your [attacker.name] is in combat.</span>")
return FALSE
return FALSE
if(in_combat)
to_chat(user, "<span class='notice'>Your [name] is in combat.</span>")
if(target)
if(target)
to_chat(target, "<span class='notice'>[T.His] [name] is in combat.</span>")
return FALSE
return FALSE
if(attacker && attacker.timer > world.time)
to_chat(user, "<span class='notice'>[target?T.His : "Your" ] [attacker.name] isn't ready for battle.</span>")
if(target)
if(target)
to_chat(target, "<span class='notice'>Your [attacker.name] isn't ready for battle.</span>")
return FALSE
return FALSE
if(timer > world.time)
to_chat(user, "<span class='notice'>Your [name] isn't ready for battle.</span>")
if(target)
if(target)
to_chat(target, "<span class='notice'>[T.His] [name] isn't ready for battle.</span>")
return FALSE
return FALSE
return TRUE
/**
* Processes any special attack moves that happen in the battle (called in the mechaBattle proc).
* Processes any special attack moves that happen in the battle (called in the mechaBattle proc).
*
* Makes the toy shout their special attack cry and updates its cooldown. Then, does the special attack.
* Arguments:
* * victim - the toy being hit by the special move
*/
/obj/item/toy/mecha/proc/special_attack_move(obj/item/toy/mecha/victim)
/obj/item/toy/mecha/proc/special_attack_move(obj/item/toy/mecha/victim)
visible_message(special_attack_cry + "!!")
special_attack_charged = FALSE
@@ -490,15 +447,15 @@
visible_message("I FORGOT MY SPECIAL ATTACK...")
/**
* Base proc for 'other' special attack moves.
* Base proc for 'other' special attack moves.
*
* This one is only for inheritance, each mech with an 'other' type move has their procs below.
* This one is only for inheritance, each mech with an 'other' type move has their procs below.
* Arguments:
* * victim - the toy being hit by the super special move (doesn't necessarily need to be used)
*/
/obj/item/toy/mecha/proc/super_special_attack(obj/item/toy/mecha/victim)
/obj/item/toy/mecha/proc/super_special_attack(obj/item/toy/mecha/victim)
visible_message("<span class='notice'> [src] does a cool flip.</span>")
/obj/random/mech_toy
name = "Random Mech Toy"
desc = "This is a random mech toy."
@@ -531,8 +488,8 @@
special_attack_type = SPECIAL_ATTACK_OTHER
special_attack_type_message = "instantly destroys the opposing mech if its health is less than this mech's health."
special_attack_cry = "KILLER CLAMP"
/obj/item/toy/mecha/deathripley/super_special_attack(obj/item/toy/mecha/victim)
/obj/item/toy/mecha/deathripley/super_special_attack(obj/item/toy/mecha/victim)
playsound(src, 'sound/weapons/sonic_jackhammer.ogg', 20, TRUE)
if(victim.combat_health < combat_health) // Instantly kills the other mech if it's health is below our's.
visible_message("EXECUTE!!")
@@ -565,7 +522,7 @@
special_attack_type_message = "puts the opposing mech's special move on cooldown and heals this mech."
special_attack_cry = "MEGA HORN"
/obj/item/toy/mecha/honk/super_special_attack(obj/item/toy/mecha/victim)
/obj/item/toy/mecha/honk/super_special_attack(obj/item/toy/mecha/victim)
playsound(src, 'sound/machines/honkbot_evil_laugh.ogg', 20, TRUE)
victim.special_attack_cooldown += 3 // Adds cooldown to the other mech and gives a minor self heal
combat_health++
@@ -620,7 +577,7 @@
special_attack_type_message = "has a lower cooldown than normal special moves, increases the opponent's cooldown, and deals damage."
special_attack_cry = "*wave"
/obj/item/toy/mecha/reticence/super_special_attack(obj/item/toy/mecha/victim)
/obj/item/toy/mecha/reticence/super_special_attack(obj/item/toy/mecha/victim)
special_attack_cooldown-- //Has a lower cooldown...
victim.special_attack_cooldown++ //and increases the opponent's cooldown by 1...
victim.combat_health-- //and some free damage.
+7 -133
View File
@@ -3,8 +3,6 @@
* Balloons
* Fake telebeacon
* Fake singularity
* Toy gun
* Toy crossbow
* Toy swords
* Toy bosun's whistle
* Snap pops
@@ -145,127 +143,6 @@
icon = 'icons/obj/singularity.dmi'
icon_state = "singularity_s1"
/*
* Toy crossbow
*/
/obj/item/toy/crossbow
name = "foam dart crossbow"
desc = "A weapon favored by many overactive children. Ages 8 and up."
icon = 'icons/obj/gun.dmi'
icon_state = "crossbow"
item_icons = list(
icon_l_hand = 'icons/mob/items/lefthand_guns.dmi',
icon_r_hand = 'icons/mob/items/righthand_guns.dmi',
)
slot_flags = SLOT_HOLSTER
w_class = ITEMSIZE_SMALL
attack_verb = list("attacked", "struck", "hit")
var/bullets = 5
drop_sound = 'sound/items/drop/gun.ogg'
/obj/item/toy/crossbow/examine(mob/user)
. = ..()
if(bullets && get_dist(user, src) <= 2)
. += "<span class='notice'>It is loaded with [bullets] foam darts!</span>"
/obj/item/toy/crossbow/attackby(obj/item/I as obj, mob/user as mob)
if(istype(I, /obj/item/toy/ammo/crossbow))
if(bullets <= 4)
user.drop_item()
qdel(I)
bullets++
to_chat(user, "<span class='notice'>You load the foam dart into the crossbow.</span>")
else
to_chat(usr, "<span class='warning'>It's already fully loaded.</span>")
/obj/item/toy/crossbow/afterattack(atom/target as mob|obj|turf|area, mob/user as mob, flag)
if(!isturf(target.loc) || target == user) return
if(flag) return
if (locate (/obj/structure/table, src.loc))
return
else if (bullets)
var/turf/trg = get_turf(target)
var/obj/effect/foam_dart_dummy/D = new/obj/effect/foam_dart_dummy(get_turf(src))
bullets--
D.icon_state = "foamdart"
D.name = "foam dart"
playsound(src, 'sound/items/syringeproj.ogg', 50, 1)
for(var/i=0, i<6, i++)
if (D)
if(D.loc == trg) break
step_towards(D,trg)
for(var/mob/living/M in D.loc)
if(!istype(M,/mob/living)) continue
if(M == user) continue
for(var/mob/O in viewers(world.view, D))
O.show_message(text("<span class='warning'>\The [] was hit by the foam dart!</span>", M), 1)
new /obj/item/toy/ammo/crossbow(M.loc)
qdel(D)
return
for(var/atom/A in D.loc)
if(A == user) continue
if(A.density)
new /obj/item/toy/ammo/crossbow(A.loc)
qdel(D)
sleep(1)
spawn(10)
if(D)
new /obj/item/toy/ammo/crossbow(D.loc)
qdel(D)
return
else if (bullets == 0)
user.Weaken(5)
for(var/mob/O in viewers(world.view, user))
O.show_message(text("<span class='warning'>\The [] realized they were out of ammo and starting scrounging for some!</span>", user), 1)
/obj/item/toy/crossbow/attack(mob/M as mob, mob/user as mob)
src.add_fingerprint(user)
// ******* Check
if (src.bullets > 0 && M.lying)
for(var/mob/O in viewers(M, null))
if(O.client)
O.show_message(text("<span class='danger'>\The [] casually lines up a shot with []'s head and pulls the trigger!</span>", user, M), 1, "<span class='warning'>You hear the sound of foam against skull</span>", 2)
O.show_message(text("<span class='warning'>\The [] was hit in the head by the foam dart!</span>", M), 1)
playsound(src, 'sound/items/syringeproj.ogg', 50, 1)
new /obj/item/toy/ammo/crossbow(M.loc)
src.bullets--
else if (M.lying && src.bullets == 0)
for(var/mob/O in viewers(M, null))
if (O.client) O.show_message(text("<span class='danger'>\The [] casually lines up a shot with []'s head, pulls the trigger, then realizes they are out of ammo and drops to the floor in search of some!</span>", user, M), 1, "<span class='warning'>You hear someone fall</span>", 2)
user.Weaken(5)
return
/obj/item/toy/ammo/crossbow
name = "foam dart"
desc = "It's nerf or nothing! Ages 8 and up."
icon = 'icons/obj/toy.dmi'
icon_state = "foamdart"
w_class = ITEMSIZE_TINY
slot_flags = SLOT_EARS
drop_sound = 'sound/items/drop/food.ogg'
/obj/effect/foam_dart_dummy
name = ""
desc = ""
icon = 'icons/obj/toy.dmi'
icon_state = "null"
anchored = TRUE
density = FALSE
/*
* Toy swords
*/
@@ -394,7 +271,6 @@
/*
* Bosun's whistle
*/
/obj/item/toy/bosunwhistle
name = "bosun's whistle"
desc = "A genuine Admiral Krush Bosun's Whistle, for the aspiring ship's captain! Suitable for ages 8 and up, do not swallow."
@@ -814,13 +690,6 @@
name = "void carp plushie"
icon_state = "voidcarp"
// Eris
/obj/structure/plushie/fumo
name = "Fumo"
desc = "A plushie of a....?."
icon_state = "fumoplushie"
phrase = "I just don't think about losing."
//Large plushies.
/obj/structure/plushie
name = "generic plush"
@@ -952,7 +821,7 @@
else
searching = FALSE
if(world.time - last_message <= 1 SECOND)
if(world.time - last_message <= 15 SECONDS)
return
if(user.a_intent == I_HELP)
user.visible_message("<span class='notice'><b>\The [user]</b> hugs [src]!</span>","<span class='notice'>You hug [src]!</span>")
@@ -1258,6 +1127,11 @@
icon_state = "therapygreen"
item_state = "egg3" // It's the green egg in items_left/righthand
/obj/item/toy/plushie/fumo
name = "Fumo"
desc = "A plushie of a....?"
icon_state = "fumoplushie"
pokephrase = "I just don't think about losing."
//Toy cult sword
/obj/item/toy/cultsword
@@ -1528,7 +1402,7 @@
name = "black king"
desc = "A black king chess piece."
description_info = "The King can move exactly one square horizontally, vertically, or diagonally. If your opponent captures this piece, you lose."
icon_state = "black_king"
icon_state = "black_king"
/// Balloon structures
+220 -35
View File
@@ -1,9 +1,42 @@
/* Virgo Toys!
* Contains:
* Mistletoe
* Plushies
* Pet rocks
* Chew toys
* Cat toys
* Fake flash
* Big red button
* Garden gnome
* Toy AI
* Hand buzzer
* Toy cuffs
* Toy nuke
* Toy gibber
* Toy xeno
* Russian revolver
* Trick revolver
* Toy chainsaw
* Random miniature spawner
* Snake popper
* Professor Who universal ID
* Professor Who sonic driver
* Action figures
*/
/*
* Mistletoe
*/
/obj/item/toy/mistletoe
name = "mistletoe"
desc = "You are supposed to kiss someone under these"
icon = 'icons/obj/toy_vr.dmi'
icon_state = "mistletoe"
/*
* Plushies
*/
/obj/item/toy/plushie/lizardplushie
name = "lizard plushie"
desc = "An adorable stuffed toy that resembles a lizardperson."
@@ -101,38 +134,6 @@
/obj/item/toy/plushie/vox/proc/cooldownreset()
cooldown = 0
/*
* 4/9/21 *
* IPC Plush
* Toaster plush
* Snake plush
* Cube plush
* Pip plush
* Moth plush
* Crab plush
* Possum plush
* Goose plush
* White mouse plush
* Pet rock
* Pet rock (m)
* Pet rock (f)
* Chew toys
* Cat toy * 2
* Toy flash
* Toy button
* Gnome
* Toy AI
* Buzzer ring
* Fake handcuffs
* Nuke toy
* Toy gibber
* Toy xeno
* Fake gun * 2
* Toy chainsaw
* Random tabletop miniature spawner
* snake popper
*/
/obj/item/toy/plushie/ipc
name = "IPC plushie"
desc = "A pleasing soft-toy of a monitor-headed robot. Toaster functionality included."
@@ -172,7 +173,6 @@
else
return ..()
/obj/item/toy/plushie/ipc/attack_self(mob/user as mob)
if(!cooldown)
playsound(user, 'sound/machines/ping.ogg', 10, 0)
@@ -274,7 +274,9 @@
/obj/item/toy/plushie/goose
name = "goose plushie"
desc = "An adorable likeness of a terrifying beast. It's simple existance chills you to the bone and compells you to hide any loose objects it might steal."
desc = "An adorable likeness of a terrifying beast. \
It's simple existance chills you to the bone and \
compells you to hide any loose objects it might steal."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "goose"
attack_verb = list("honked")
@@ -284,9 +286,54 @@
icon_state = "mouse"
icon = 'icons/obj/toy_vr.dmi'
/obj/item/toy/plushie/susred
name = "red spaceman plushie"
desc = "A suspicious looking red spaceman plushie. Why does it smell like the vents?"
icon = 'icons/obj/toy_vr.dmi'
icon_state = "sus_red"
attack_verb = list("stabbed", "slashed")
/obj/item/toy/plushie/ipc/toaster/attack_self(mob/user as mob)
if(!cooldown)
playsound(user, 'sound/weapons/slice.ogg', 10, 0)
src.visible_message("<span class='danger'>Stab!</span>")
cooldown = 1
addtimer(CALLBACK(src, .proc/cooldownreset), 50)
return ..()
/obj/item/toy/plushie/susblue
name = "blue spaceman plushie"
desc = "A dapper looking blue spaceman plushie. Looks very intuitive."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "sus_blue"
/obj/item/toy/plushie/suswhite
name = "white spaceman plushie"
desc = "A whiny looking white spaceman plushie. Looks like it could cry at any moment."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "sus_white"
/obj/item/toy/plushie/bigcat
name = "big cat plushie"
desc = "A big, fluffy looking cat that just looks very huggable."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "big_cat"
/obj/item/toy/plushie/basset
name = "basset plushie"
desc = "A sleepy looking basset hound plushie."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "basset"
/*
* Pet rocks
*/
/obj/item/toy/rock
name = "pet rock"
desc = "A stuffed version of the classic pet. The soft ones were made after kids kept throwing them at each other. It has a small piece of soft plastic that you can draw on if you wanted."
desc = "A stuffed version of the classic pet. \
The soft ones were made after kids kept throwing \
them at each other. It has a small piece of soft \
plastic that you can draw on if you wanted."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "rock"
attack_verb = list("grug'd", "unga'd")
@@ -307,6 +354,9 @@
to_chat(user, "You draw a face on the rock and pull aside the plastic slightly, revealing a small pink bow.")
return
/*
* Chew toys
*/
/obj/item/toy/chewtoy
name = "chew toy"
desc = "A red hard-rubber chew toy shaped like a bone. Perfect for your dog! You wouldn't want to chew on it, right?"
@@ -330,6 +380,9 @@
playsound(loc, 'sound/items/drop/plushie.ogg', 50, 1)
user.visible_message("<span class='notice'><b>\The [user]</b> gnaws on [src]!</span>","<span class='notice'>You gnaw on [src]!</span>")
/*
* Cat toys
*/
/obj/item/toy/cat_toy
name = "toy mouse"
desc = "A colorful toy mouse!"
@@ -349,6 +402,9 @@
slot_r_hand_str = 'icons/mob/items/righthand_material.dmi',
)
/*
* Fake flash
*/
/obj/item/toy/flash
name = "toy flash"
desc = "FOR THE REVOLU- Oh wait, that's just a toy."
@@ -374,6 +430,9 @@
/obj/item/toy/flash/proc/cooldownreset()
cooldown = 0
/*
* Big red button
*/
/obj/item/toy/redbutton
name = "big red button"
desc = "A big, plastic red button. Reads 'From HonkCo Pranks?' on the back."
@@ -394,12 +453,18 @@
else
to_chat(user, "<span class='alert'>Nothing happens.</span>")
/*
* Garden gnome
*/
/obj/item/toy/gnome
name = "garden gnome"
desc = "It's a gnome, not a gnelf. Made of weak ceramic."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "gnome"
/*
* Toy AI
*/
/obj/item/toy/AI
name = "toy AI"
desc = "A little toy model AI core with real law announcing action!"
@@ -434,6 +499,9 @@
/obj/item/toy/AI/proc/cooldownreset()
cooldown = 0
/*
* Hand buzzer
*/
/obj/item/clothing/gloves/ring/buzzer/toy
name = "steel ring"
desc = "Torus shaped finger decoration. It has a small piece of metal on the palm-side."
@@ -460,6 +528,9 @@
return 0
/*
* Toy cuffs
*/
/obj/item/weapon/handcuffs/fake
name = "plastic handcuffs"
desc = "Use this to keep plastic prisoners in line."
@@ -484,6 +555,9 @@
foldable = null
can_hold = list(/obj/item/weapon/handcuffs/fake, /obj/item/weapon/handcuffs/legcuffs/fake)
/*
* Toy nuke
*/
/obj/item/toy/nuke
name = "\improper Nuclear Fission Explosive toy"
desc = "A plastic model of a Nuclear Fission Explosive."
@@ -510,6 +584,9 @@
if(istype(I, /obj/item/weapon/disk/nuclear))
to_chat(user, "<span class='alert'>Nice try. Put that disk back where it belongs.</span>")
/*
* Toy gibber
*/
/obj/item/toy/minigibber
name = "miniature gibber"
desc = "A miniature recreation of NanoTrasen's famous meat grinder. Equipped with a special interlock that prevents insertion of organic material."
@@ -547,6 +624,9 @@
else ..()
/*
* Toy xeno
*/
/obj/item/toy/toy_xeno
icon = 'icons/obj/toy_vr.dmi'
icon_state = "xeno"
@@ -571,6 +651,9 @@
to_chat(user, "<span class='warning'>The string on [src] hasn't rewound all the way!</span>")
return
/*
* Russian revolver
*/
/obj/item/toy/russian_revolver
name = "russian revolver"
desc = "For fun and games!"
@@ -641,6 +724,9 @@
to_chat(user, "<span class='warning'>[src] needs to be reloaded.</span>")
return FALSE
/*
* Trick revolver
*/
/obj/item/toy/russian_revolver/trick_revolver
name = "\improper .357 revolver"
desc = "A suspicious revolver. Uses .357 ammo."
@@ -668,6 +754,9 @@
sleep(5)
icon_state = "[initial(icon_state)]"
/*
* Toy chainsaw
*/
/obj/item/toy/chainsaw
name = "Toy Chainsaw"
desc = "A toy chainsaw with a rubber edge. Ages 8 and up"
@@ -690,6 +779,9 @@
/obj/item/toy/chainsaw/proc/cooldownreset()
cooldown = 0
/*
* Random miniature spawner
*/
/obj/random/miniature
name = "Random miniature"
desc = "This is a random miniature."
@@ -699,6 +791,9 @@
/obj/random/miniature/item_to_spawn()
return pick(typesof(/obj/item/toy/character))
/*
* Snake popper
*/
/obj/item/toy/snake_popper
name = "bread tube"
desc = "Bread in a tube. Chewy...and surprisingly tasty."
@@ -775,3 +870,93 @@
real = 2
to_chat(user, "<span class='notice'>You short out the bluespace refill system of [src].</span>")
/*
* Professor Who universal ID
*/
/obj/item/clothing/under/universalid
name = "identification card"
desc = "A novelty identification card based on Professor Who's Universal ID."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "universal_id"
w_class = ITEMSIZE_TINY
slot_flags = SLOT_ID | SLOT_EARS
body_parts_covered = 0
equip_sound = null
sprite_sheets = null
item_state = "golem" //This is dumb and hacky but was here when I got here.
worn_state = "golem" //It's basically just a coincidentally black iconstate in the file.
/*
* Professor Who sonic driver
*/
/obj/item/weapon/tool/screwdriver/sdriver
name = "sonic driver"
desc = "A novelty screwdriver that uses tiny magnets to manipulate screws."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "sonic_driver"
item_state = "screwdriver_black"
usesound = 'sound/items/sonic_driver.ogg'
toolspeed = 1
random_color = FALSE
/*
* Professor Who time capsule
*/
/obj/item/weapon/storage/box/timecap
name = "action time capsule"
desc = "A toy recreation of the Time Capsule from Professor Who. Can hold up to two action figures."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "time_cap"
can_hold = list(/obj/item/toy/figure)
max_w_class = ITEMSIZE_TINY
max_storage_space = ITEMSIZE_COST_TINY * 2
use_sound = 'sound/machines/click.ogg'
drop_sound = 'sound/items/drop/accessory.ogg'
pickup_sound = 'sound/items/pickup/accessory.ogg'
/*
* Action figures
*/
/obj/item/toy/figure/ranger
name = "Space Ranger action figure"
desc = "A \"Space Life\" brand Space Ranger action figure."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "ranger"
toysay = "To the Fontier and beyond!"
/obj/item/toy/figure/leadbandit
name = "Bandit Leader action figure"
desc = "A \"Space Life\" brand Bandit Leader action figure."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "bandit_lead"
toysay = "Give us yer bluespace crystals!"
/obj/item/toy/figure/bandit
name = "Bandit action figure"
desc = "A \"Space Life\" brand Bandit action figure."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "bandit"
toysay = "Stick em' up!"
/obj/item/toy/figure/abe
name = "Action Abe action figure"
desc = "A \"Space Life\" brand Action Abe action figure."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "action_abe"
toysay = "Four score and seven decades ago..."
/obj/item/toy/figure/profwho
name = "Professor Who action figure"
desc = "A \"Space Life\" brand Professor Who action figure."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "prof_who"
toysay = "Smells like... bad wolf..."
/obj/item/toy/figure/prisoner
name = "prisoner action figure"
desc = "A \"Space Life\" brand prisoner action figure."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "prisoner"
toysay = "I did not hit her! I did not!"
+18
View File
@@ -8,6 +8,7 @@
desc = "This is rubbish."
drop_sound = 'sound/items/drop/wrapper.ogg'
pickup_sound = 'sound/items/pickup/wrapper.ogg'
matter = list(MAT_STEEL = 30)
var/age = 0
/obj/item/trash/New(var/newloc, var/_age)
@@ -248,6 +249,12 @@
drop_sound = 'sound/items/drop/soda.ogg'
pickup_sound = 'sound/items/pickup/soda.ogg'
/obj/item/trash/tomato
name = "empty tomato soup can"
icon_state = "tomato"
drop_sound = 'sound/items/drop/soda.ogg'
pickup_sound = 'sound/items/pickup/soda.ogg'
/obj/item/trash/spinach
name = "empty spinach can"
icon_state = "spinach"
@@ -409,3 +416,14 @@
name = "burrito packaging"
icon_state = "smolburrito"
/obj/item/trash/brainzsnax
name = "\improper BrainzSnax can"
icon_state = "brainzsnax"
drop_sound = 'sound/items/drop/soda.ogg'
pickup_sound = 'sound/items/pickup/soda.ogg'
/obj/item/trash/brainzsnaxred
name = "\improper BrainzSnax RED can"
icon_state = "brainzsnaxred"
drop_sound = 'sound/items/drop/soda.ogg'
pickup_sound = 'sound/items/pickup/soda.ogg'
@@ -18,6 +18,7 @@ AI MODULES
throw_range = 15
origin_tech = list(TECH_DATA = 3)
preserve_item = 1
matter = list(MAT_STEEL = 30, MAT_GLASS = 10)
var/datum/ai_laws/laws = null
/obj/item/weapon/aiModule/proc/install(var/atom/movable/AM, var/mob/living/user)
+3 -10
View File
@@ -16,7 +16,7 @@
item_icons = list(
slot_l_hand_str = 'icons/mob/items/lefthand_vr.dmi',
slot_r_hand_str = 'icons/mob/items/righthand_vr.dmi',
)
)
flags = NOBLUDGEON
force = 10
throwforce = 10
@@ -64,13 +64,6 @@
qdel_null(tool)
return ..()
/obj/item/weapon/pipe_dispenser/suicide_act(mob/user)
var/datum/gender/TU = gender_datums[user.get_visible_gender()]
user.visible_message("<span class='suicide'>[user] points the end of the RPD down [TU.his] throat and presses a button! It looks like [TU.hes] trying to commit suicide...</span>")
playsound(src, 'sound/machines/click.ogg', 50, 1)
playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
return(BRUTELOSS)
/obj/item/weapon/pipe_dispenser/attack_self(mob/user)
tgui_interact(user)
@@ -191,9 +184,9 @@
activate()
animate_deletion(A)
return
if((mode & PAINT_MODE)) //Paint pipes
if(istype(A, /obj/machinery/atmospherics/pipe))
if(!istype(A, /obj/machinery/atmospherics/pipe/simple/heat_exchanging) && istype(A, /obj/machinery/atmospherics/pipe))
var/obj/machinery/atmospherics/pipe/P = A
playsound(src, 'sound/machines/click.ogg', 50, 1)
P.change_color(pipe_colors[paint_color])
@@ -0,0 +1,845 @@
/obj/item/capture_crystal
name = "curious 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>"
. += "<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(!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/mob_was_deleted, TRUE)
RegisterSignal(U, COMSIG_PARENT_QDELETING, .proc/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))
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
bound_mob.forceMove(src.drop_location())
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/great
capture_chance_modifier = 1.5
/obj/item/capture_crystal/ultra
capture_chance_modifier = 2
/obj/item/capture_crystal/master
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/animal/wolf,
/mob/living/simple_mob/animal/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/otie/feral,
/mob/living/simple_mob/otie/feral/chubby,
/mob/living/simple_mob/otie/red,
/mob/living/simple_mob/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/animal/wolf = 10,
/mob/living/simple_mob/animal/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/animal/space/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/animal/wolf/direwolf),
list(/mob/living/simple_mob/animal/space/jelly),
list(
/mob/living/simple_mob/otie/feral,
/mob/living/simple_mob/otie/feral/chubby,
/mob/living/simple_mob/otie/red,
/mob/living/simple_mob/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.
@@ -254,6 +254,7 @@
desc = "A chocolate-coated biscuit stick."
icon_state = "pockystick"
item_state = "pocky"
type_butt = null
/obj/item/clothing/mask/chewable/candy/pocky/process()
chew()
@@ -207,8 +207,6 @@ CIGARETTE PACKETS ARE IN FANCY.DM
to_chat(M, "<span class='notice'>Your [name] goes out.</span>")
M.remove_from_mob(src) //un-equip it so the overlays can update
M.update_inv_wear_mask(0)
M.update_inv_l_hand(0)
M.update_inv_r_hand(1)
qdel(src)
else
new /obj/effect/decal/cleanable/ash(T)
@@ -221,8 +219,6 @@ CIGARETTE PACKETS ARE IN FANCY.DM
icon_state = initial(icon_state)
item_state = initial(item_state)
M.update_inv_wear_mask(0)
M.update_inv_l_hand(0)
M.update_inv_r_hand(1)
smoketime = 0
reagents.clear_reagents()
name = "empty [initial(name)]"
@@ -16,6 +16,7 @@
throwforce = 5.0
throw_speed = 3
throw_range = 15
matter = list(MAT_STEEL = 30, MAT_GLASS = 10)
var/build_path = null
var/board_type = new /datum/frame/frame_types/computer
var/list/req_components = null
@@ -60,3 +60,10 @@
build_path = /obj/machinery/computer/id_restorer
board_type = new /datum/frame/frame_types/id_restorer
matter = list(MAT_STEEL = 50, MAT_GLASS = 50)
/obj/item/weapon/circuitboard/security/xenobio
name = T_BOARD("xenobiology camera monitor")
build_path = /obj/machinery/computer/security/xenobio
network = list(NETWORK_XENOBIO)
req_access = list()
matter = list(MAT_STEEL = 50, MAT_GLASS = 50)
@@ -255,3 +255,13 @@
/obj/item/weapon/stock_parts/spring = 1,
/obj/item/stack/cable_coil = 5)
/obj/item/weapon/circuitboard/arf_generator
name = T_BOARD("atmospheric field generator")
build_path = /obj/machinery/atmospheric_field_generator
board_type = new /datum/frame/frame_types/arfgs
origin_tech = list(TECH_MAGNET = 4, TECH_POWER = 4, TECH_BIO = 3)
req_components = list(
/obj/item/weapon/stock_parts/micro_laser/high = 2, //field emitters
/obj/item/weapon/stock_parts/scanning_module = 1, //atmosphere sensor
/obj/item/weapon/stock_parts/capacitor/adv = 1, //for the JUICE
/obj/item/stack/cable_coil = 10)
@@ -17,4 +17,6 @@
build_path = /obj/machinery/mining/brace
board_type = new /datum/frame/frame_types/machine
origin_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 1)
req_components = list()
req_components = list(
/obj/item/weapon/stock_parts/manipulator = 1
)
@@ -37,6 +37,19 @@
sprite_name = "miniFE"
rand_overlays = 0
/obj/item/weapon/extinguisher/atmo
name = "atmospheric fire extinguisher"
desc = "A heavy duty fire extinguisher meant to fight large fires."
icon_state = "atmos_extinguisher0"
item_state = "atmos_extinguisher"
throwforce = 12
w_class = ITEMSIZE_LARGE
force = 3.0
max_water = 600
spray_particles = 3
sprite_name = "atmo_extinguisher"
rand_overlays = 0
/obj/item/weapon/extinguisher/Initialize()
create_reagents(max_water)
reagents.add_reagent("firefoam", max_water)
@@ -85,8 +85,8 @@
/obj/item/weapon/beach_ball/holoball,
/obj/item/toy/balloon,
/obj/item/toy/blink,
/obj/item/toy/crossbow,
/obj/item/weapon/gun/projectile/revolver/capgun,
/obj/item/weapon/gun/projectile/revolver/toy/crossbow,
/obj/item/weapon/storage/box/capguntoy,
/obj/item/toy/katana,
/obj/item/toy/mecha/deathripley,
/obj/item/toy/mecha/durand,
@@ -55,7 +55,7 @@
C.throw_mode_on()
/obj/item/weapon/grenade/chem_grenade/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W,/obj/item/device/assembly_holder) && (!stage || stage==1) && path != 2)
if(istype(W,/obj/item/device/assembly_holder) && (!stage || stage==1) && !detonator && path != 2)
var/obj/item/device/assembly_holder/det = W
if(istype(det.a_left,det.a_right.type) || (!isigniter(det.a_left) && !isigniter(det.a_right)))
to_chat(user, "<span class='warning'>Assembly must contain one igniter.</span>")
@@ -314,4 +314,3 @@
beakers += B1
beakers += B2
@@ -112,3 +112,6 @@
walk(src, null, null)
..()
return
/obj/item/weapon/grenade/vendor_action(var/obj/machinery/vending/V)
activate(V)
@@ -141,6 +141,7 @@ var/last_chew = 0
/obj/item/weapon/handcuffs/fuzzy
name = "fuzzy cuffs"
icon_state = "fuzzycuff"
breakouttime = 100 //VOREstation edit
desc = "Use this to keep... 'prisoners' in line."
/obj/item/weapon/handcuffs/cable
@@ -116,7 +116,6 @@
else
log_and_message_admins("attempted to emag \an [A].")
// Vorestation Edit: End of Edit
log_and_message_admins("emagged \an [A].")
if(uses<1)
user.visible_message("<span class='warning'>\The [src] fizzles and sparks - it seems it's been used once too often, and is now spent.</span>")
@@ -130,10 +129,10 @@
/obj/item/weapon/card/emag/attackby(obj/item/O as obj, mob/user as mob)
if(istype(O, /obj/item/stack/telecrystal))
var/obj/item/stack/telecrystal/T = O
if(T.amount < 1)
if(T.get_amount() < 1)
to_chat(usr, "<span class='notice'>You are not adding enough telecrystals to fuel \the [src].</span>")
return
uses += T.amount/2 //Gives 5 uses per 10 TC
uses += T.get_amount()*0.5 //Gives 5 uses per 10 TC
uses = CEILING(uses, 1) //Ensures no decimal uses nonsense, rounds up to be nice
to_chat(usr, "<span class='notice'>You add \the [O] to \the [src]. Increasing the uses of \the [src] to [uses].</span>")
qdel(O)
@@ -261,6 +261,10 @@
name = "Talon Pilot ID"
initial_sprite_stack = list("base-stamp-dark", "top-dark", "stamp-silhouette", "pips-purple", "stripe-purple")
/obj/item/weapon/card/id/talon/miner
name = "Talon Mining ID"
initial_sprite_stack = list("base-stamp-dark", "top-dark", "stamp-silhouette", "pips-brown", "stripe-brown")
/obj/item/weapon/card/id/talon/captain
name = "Talon Captain ID"
initial_sprite_stack = list("base-stamp-dark", "top-dark", "stamp-silhouette", "pips-gold", "stripe-gold")
@@ -73,6 +73,7 @@
/mob/living/carbon/human/set_id_info(var/obj/item/weapon/card/id/id_card)
..()
id_card.age = age
id_card.sex = capitalize(name_gender())
/obj/item/weapon/card/id/tgui_data(mob/user)
var/list/data = list()
@@ -208,6 +208,7 @@
"Shaft Miner" = "itg",
"Intern" = "itg",
"Talon Pilot" = "itg",
"Talon Miner" = "itg",
"Bartender" = "itg_green",
"Botanist" = "itg_green",
"Chef" = "itg_green",
@@ -233,7 +234,7 @@
"Field Medic" = "itg_white",
"Talon Doctor" = "itg_white",
"Atmospheric Technician" = "itg_orange",
"Station Engineer" = "itg_orange",
"Engineer" = "itg_orange",
"Off-duty Officer" = "itg_red",
"Off-duty Engineer" = "itg_orange",
"Off-duty Medic" = "itg_white",
@@ -35,6 +35,7 @@
source.add_language(LANGUAGE_CANILUNZT)
source.add_language(LANGUAGE_SLAVIC)
source.add_language(LANGUAGE_SOL_COMMON) //In case they're giving a xenomorph an implant or something.
source.add_language(LANGUAGE_TAVAN)
/obj/item/weapon/implant/vrlanguage/post_implant(mob/source)
source.mind.store_memory("A implant can be activated by using the smile emote, <B>say *smile</B> to attempt to activate.", 0, 0)
@@ -7,6 +7,7 @@
desc = "An implant allowing someone to speak the range of frequencies used in Galactic Common, as well as produce any phonemes that they usually cannot. Only helps with producing sounds, not understanding them."
known_implant = TRUE
var/list/languages = list(LANGUAGE_GALCOM) // List of languages that this assists with
initialize_loc = BP_HEAD
/obj/item/weapon/implant/language/post_implant(mob/M) // Amends the mob's voice organ, then deletes itself
if(ishuman(M))
@@ -117,11 +117,6 @@
if(max_fuel && get_dist(user, src) == 0)
. += "<span class = 'notice'>The [src] feels like it contains roughtly [get_fuel()] units of fuel left.</span>"
/obj/item/weapon/chainsaw/suicide_act(mob/user)
var/datum/gender/TU = gender_datums[user.get_visible_gender()]
to_chat(viewers(user), "<span class='danger'>[user] is lying down and pulling the chainsaw into [TU.him], it looks like [TU.he] [TU.is] trying to commit suicide!</span>")
return(BRUTELOSS)
/obj/item/weapon/chainsaw/update_icon()
if(on)
icon_state = "chainsaw1"
@@ -84,6 +84,13 @@
to_chat(user, SPAN_WARNING("You don't have anything on \the [src].")) //if we have help intent and no food scooped up DON'T STAB OURSELVES WITH THE FORK
return
/obj/item/weapon/material/kitchen/utensil/on_rag_wipe()
. = ..()
if(reagents.total_volume > 0)
reagents.clear_reagents()
cut_overlays()
return
/obj/item/weapon/material/kitchen/utensil/fork
name = "fork"
desc = "It's a fork. Sure is pointy."
@@ -71,13 +71,6 @@
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
drop_sound = 'sound/items/drop/knife.ogg'
/obj/item/weapon/material/knife/suicide_act(mob/user)
var/datum/gender/TU = gender_datums[user.get_visible_gender()]
to_chat(viewers(user), pick("<span class='danger'>\The [user] is slitting [TU.his] wrists with \the [src]! It looks like [TU.hes] trying to commit suicide.</span>", \
"<span class='danger'>\The [user] is slitting [TU.his] throat with \the [src]! It looks like [TU.hes] trying to commit suicide.</span>", \
"<span class='danger'>\The [user] is slitting [TU.his] stomach open with \the [src]! It looks like [TU.hes] trying to commit seppuku.</span>"))
return (BRUTELOSS)
// These no longer inherit from hatchets.
/obj/item/weapon/material/knife/tacknife
name = "tactical knife"
@@ -211,11 +211,6 @@
playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
return
/obj/item/weapon/material/whip/suicide_act(mob/user)
var/datum/gender/T = gender_datums[user.get_visible_gender()]
user.visible_message(span("danger", "\The [user] [T.is] strangling [T.himself] with \the [src]! It looks like [T.he] [T.is] trying to commit suicide."), span("danger", "You start to strangle yourself with \the [src]!"), span("danger", "You hear the sound of someone choking!"))
return (OXYLOSS)
/obj/item/weapon/material/whip/attack_self(mob/user)
user.visible_message("<span class='warning'>\The [user] cracks \the [src]!</span>")
playsound(src, 'sound/effects/snap.ogg', 50, 1)
@@ -17,12 +17,6 @@
unbreakable = 1 //It's already broken.
drops_debris = 0
/obj/item/weapon/material/shard/suicide_act(mob/user)
var/datum/gender/TU = gender_datums[user.get_visible_gender()]
to_chat(viewers(user), pick("<span class='danger'>\The [user] is slitting [TU.his] wrists with \the [src]! It looks like [TU.hes] trying to commit suicide.</span>",
"<span class='danger'>\The [user] is slitting [TU.his] throat with \the [src]! It looks like [TU.hes] trying to commit suicide.</span>"))
return (BRUTELOSS)
/obj/item/weapon/material/shard/set_material(var/new_material)
..(new_material)
if(!istype(material))
@@ -19,18 +19,8 @@
return 1
return 0
/obj/item/weapon/material/sword/suicide_act(mob/user)
var/datum/gender/TU = gender_datums[user.get_visible_gender()]
to_chat(viewers(user),"<span class='danger'>[user] is falling on the [src.name]! It looks like [TU.he] [TU.is] trying to commit suicide.</span>")
return(BRUTELOSS)
/obj/item/weapon/material/sword/katana
name = "katana"
desc = "Woefully underpowered in D20. This one looks pretty sharp."
icon_state = "katana"
slot_flags = SLOT_BELT | SLOT_BACK
/obj/item/weapon/material/sword/katana/suicide_act(mob/user)
var/datum/gender/TU = gender_datums[user.get_visible_gender()]
visible_message(span("danger", "[user] is slitting [TU.his] stomach open with \the [src.name]! It looks like [TU.hes] trying to commit seppuku."), span("danger", "You slit your stomach open with \the [src.name]!"), span("danger", "You hear the sound of flesh tearing open.")) // gory, but it gets the point across
return(BRUTELOSS)
slot_flags = SLOT_BELT | SLOT_BACK
@@ -13,7 +13,7 @@
/obj/item/weapon/whetstone/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/stack/material))
var/obj/item/stack/material/M = I
if(M.amount >= 5)
if(M.get_amount() >= 5)
to_chat(user, "You begin to refine the [src] with [M]...")
if(do_after(user, 70))
M.use(5)
@@ -117,13 +117,6 @@
add_fingerprint(user)
return
/obj/item/weapon/melee/energy/suicide_act(mob/user)
var/datum/gender/TU = gender_datums[user.get_visible_gender()]
if(active)
user.visible_message(pick("<span class='danger'>\The [user] is slitting [TU.his] stomach open with \the [src]! It looks like [TU.he] [TU.is] trying to commit seppuku.</span>",\
"<span class='danger'>\The [user] is falling on \the [src]! It looks like [TU.he] [TU.is] trying to commit suicide.</span>"))
return (BRUTELOSS|FIRELOSS)
/obj/item/weapon/melee/energy/attack(mob/M, mob/user)
if(active && use_cell)
if(!use_charge(hitcost))
@@ -238,11 +231,6 @@
damtype = BRUTE
to_chat(user, "<span class='notice'>\The [src] is de-energised. It's just a regular axe now.</span>")
/obj/item/weapon/melee/energy/axe/suicide_act(mob/user)
var/datum/gender/TU = gender_datums[user.get_visible_gender()]
visible_message("<span class='warning'>\The [user] swings \the [src] towards [TU.his] head! It looks like [TU.he] [TU.is] trying to commit suicide.</span>")
return (BRUTELOSS|FIRELOSS)
/obj/item/weapon/melee/energy/axe/charge
name = "charge axe"
desc = "An energised axe."
+14 -5
View File
@@ -8,13 +8,22 @@
w_class = ITEMSIZE_NORMAL
origin_tech = list(TECH_COMBAT = 4)
attack_verb = list("flogged", "whipped", "lashed", "disciplined")
hitsound = 'sound/weapons/whip.ogg'
reach = 2
/obj/item/weapon/melee/chainofcommand/suicide_act(mob/user)
var/datum/gender/T = gender_datums[user.get_visible_gender()]
user.visible_message(span("danger", "\The [user] [T.is] strangling [T.himself] with \the [src]! It looks like [T.he] [T.is] trying to commit suicide."), span("danger", "You start to strangle yourself with \the [src]!"), span("danger", "You hear the sound of someone choking!"))
return (OXYLOSS)
/obj/item/weapon/melee/chainofcommand/curator_whip
name = "leather whip"
desc = "A fine weapon for some treasure hunting."
icon_state = "curator_whip"
force = 5
throwforce = 5
origin_tech = list(TECH_COMBAT = 2)
/obj/item/weapon/melee/chainofcommand/curator_whip/toy
name = "toy whip"
desc = "A fake whip. Perfect for fake treasure hunting"
force = 2
throwforce = 2
/obj/item/weapon/melee/umbrella
name = "umbrella"
@@ -92,3 +92,11 @@
icon_state = "explorer_shield_P_lighted"
else
icon_state = "explorer_shield_P"
/obj/item/weapon/shield/primitive
name = "primitive shield"
desc = "A defensive object that is little more than planks strapped your arm"
icon = 'icons/obj/weapons.dmi'
icon_state = "buckler"
w_class = ITEMSIZE_LARGE
base_block_chance = 30
@@ -190,3 +190,14 @@
icon_override = 'icons/inventory/back/mob_vr.dmi'
item_state = "kr_rucksack"
icon_state = "kr_rucksack"
//strapless
/obj/item/weapon/storage/backpack/satchel/strapless
name = "strapless satchel"
desc = "A satchel for carrying a large number of supplies easily. Without Straps"
icon = 'icons/inventory/back/item_vr.dmi'
icon_override = 'icons/inventory/back/mob_vr.dmi'
icon_state = "satchel_strapless"
item_state_slots = null
+23 -25
View File
@@ -245,7 +245,7 @@
return 0
var/current = 0
for(var/obj/item/stack/material/S in contents)
current += S.amount
current += S.get_amount()
if(capacity == current)//If it's full, you're done
if(!stop_messages)
to_chat(usr, "<span class='warning'>The snatcher is full.</span>")
@@ -262,29 +262,27 @@
var/inserted = 0
var/current = 0
for(var/obj/item/stack/material/S2 in contents)
current += S2.amount
if(capacity < current + S.amount)//If the stack will fill it up
current += S2.get_amount()
if(capacity < current + S.get_amount())//If the stack will fill it up
amount = capacity - current
else
amount = S.amount
amount = S.get_amount()
for(var/obj/item/stack/material/sheet in contents)
if(S.type == sheet.type) // we are violating the amount limitation because these are not sane objects
sheet.amount += amount // they should only be removed through procs in this file, which split them up.
S.amount -= amount
if(S.type == sheet.type)
// we are violating the amount limitation because these are not sane objects
sheet.set_amount(sheet.get_amount() + amount, TRUE)
S.use(amount) // will qdel() if we use it all
inserted = 1
break
if(!inserted || !S.amount)
if(!inserted)
usr.remove_from_mob(S)
usr.update_icons() //update our overlays
if (usr.client && usr.s_active != src)
usr.client.screen -= S
S.dropped(usr)
if(!S.amount)
qdel(S)
else
S.loc = src
S.loc = src
orient2hud(usr)
if(usr.s_active)
@@ -305,7 +303,7 @@
for(var/obj/item/stack/material/I in contents)
adjusted_contents++
var/datum/numbered_display/D = new/datum/numbered_display(I)
D.number = I.amount
D.number = I.get_amount()
numbered_contents.Add( D )
var/row_num = 0
@@ -319,14 +317,14 @@
/obj/item/weapon/storage/bag/sheetsnatcher/quick_empty()
var/location = get_turf(src)
for(var/obj/item/stack/material/S in contents)
while(S.amount)
var/obj/item/stack/material/N = new S.type(location)
var/stacksize = min(S.amount,N.max_amount)
N.amount = stacksize
S.amount -= stacksize
N.update_icon()
if(!S.amount)
qdel(S) // todo: there's probably something missing here
var/cur_amount = S.get_amount()
var/full_stacks = round(cur_amount / S.max_amount) // Floor of current/max is amount of full stacks we make
var/remainder = cur_amount % S.max_amount // Current mod max is remainder after full sheets removed
for(var/i = 1 to full_stacks)
new S.type(location, S.max_amount)
if(remainder)
new S.type(location, remainder)
S.set_amount(0)
orient2hud(usr)
if(usr.s_active)
usr.s_active.show_to(usr)
@@ -342,10 +340,10 @@
//Therefore, make a new stack internally that has the remainder.
// -Sayu
if(S.amount > S.max_amount)
var/obj/item/stack/material/temp = new S.type(src)
temp.amount = S.amount - S.max_amount
S.amount = S.max_amount
if(S.get_amount() > S.max_amount)
var/newstack_amt = S.get_amount() - S.max_amount
new S.type(src, newstack_amt) // The one we'll keep to replace the one we give
S.set_amount(S.max_amount) // The one we hand to the clicker
return ..(S,new_location)
@@ -85,13 +85,24 @@
/obj/item/stack/cable_coil/random_belt
)
/obj/item/weapon/storage/belt/utility/atmostech
/obj/item/weapon/storage/belt/utility/full/multitool
starts_with = list(
/obj/item/weapon/tool/screwdriver,
/obj/item/weapon/tool/wrench,
/obj/item/weapon/weldingtool,
/obj/item/weapon/tool/crowbar,
/obj/item/weapon/tool/wirecutters,
/obj/item/stack/cable_coil/random_belt,
/obj/item/device/multitool
)
/obj/item/weapon/storage/belt/utility/atmostech
starts_with = list(
/obj/item/weapon/tool/screwdriver,
/obj/item/weapon/tool/wrench,
/obj/item/weapon/weldingtool,
/obj/item/weapon/tool/crowbar,
/obj/item/weapon/tool/wirecutters
)
/obj/item/weapon/storage/belt/utility/chief
@@ -111,6 +122,52 @@
/obj/item/device/analyzer
)
/obj/item/weapon/storage/belt/utility/holding
name = "tool-belt of holding"
desc = "A belt that uses localized bluespace pockets to hold more items than expected!"
icon_state = "utility_holding"
storage_slots = 14 //twice the amount as a normal belt
max_storage_space = ITEMSIZE_COST_NORMAL * 14
can_hold = list(
/obj/item/weapon/tool/crowbar,
/obj/item/weapon/tool/screwdriver,
/obj/item/weapon/weldingtool,
/obj/item/weapon/tool/wirecutters,
/obj/item/weapon/tool/wrench,
/obj/item/device/multitool,
/obj/item/device/flashlight,
/obj/item/weapon/cell/device,
/obj/item/stack/cable_coil,
/obj/item/device/t_scanner,
/obj/item/device/analyzer,
/obj/item/clothing/glasses,
/obj/item/clothing/gloves,
/obj/item/device/pda,
/obj/item/device/megaphone,
/obj/item/taperoll,
/obj/item/device/radio/headset,
/obj/item/device/robotanalyzer,
/obj/item/weapon/material/minihoe,
/obj/item/weapon/material/knife/machete/hatchet,
/obj/item/device/analyzer/plant_analyzer,
/obj/item/weapon/extinguisher/mini,
/obj/item/weapon/tape_roll,
/obj/item/device/integrated_electronics/wirer,
/obj/item/device/integrated_electronics/debugger,
/obj/item/weapon/shovel/spade,
/obj/item/stack/nanopaste,
/obj/item/weapon/cell, //this is a bigger belt, might as well make it hold bigger cells too
/obj/item/weapon/pipe_dispenser, //bigger belt for bigger tools
/obj/item/weapon/rcd, //see above
/obj/item/device/quantum_pad_booster,
/obj/item/weapon/inducer,
/obj/item/stack/material/steel,
/obj/item/stack/material/glass,
/obj/item/device/lightreplacer,
/obj/item/weapon/pickaxe/plasmacutter
)
/obj/item/weapon/storage/belt/medical
name = "medical belt"
desc = "Can hold various medical equipment."
@@ -149,6 +206,13 @@
desc = "A sturdy black webbing belt with attached pouches."
icon_state = "ems"
/obj/item/weapon/storage/belt/medical/holding
name = "medical belt of holding"
desc = "A belt that uses localized bluespace pockets to hold more items than expected!"
icon_state = "med_holding"
storage_slots = 14 //twice the amount as a normal belt
max_storage_space = ITEMSIZE_COST_NORMAL * 14
/obj/item/weapon/storage/belt/security
name = "security belt"
desc = "Can hold security gear like handcuffs and flashes."
@@ -325,10 +389,28 @@
max_w_class = ITEMSIZE_NORMAL
max_storage_space = ITEMSIZE_COST_NORMAL * 7
/obj/item/weapon/storage/belt/bandolier
name = "shotgun bandolier"
desc = "Designed to hold shotgun shells. Can't really hold more than that."
icon_state = "bandolier1"
storage_slots = 8
max_w_class = ITEMSIZE_TINY
can_hold = list(
/obj/item/ammo_casing/a12g,
/obj/item/ammo_casing/a12g/pellet,
/obj/item/ammo_casing/a12g/blank,
/obj/item/ammo_casing/a12g/practice,
/obj/item/ammo_casing/a12g/beanbag,
/obj/item/ammo_casing/a12g/stunshell,
/obj/item/ammo_casing/a12g/flash,
/obj/item/ammo_casing/a12g/emp,
/obj/item/ammo_casing/a12g/flechette
)
/obj/item/weapon/storage/belt/security/tactical/bandolier
name = "combat belt"
name = "combat bandolier"
desc = "Can hold security gear like handcuffs and flashes, with more pouches for more storage."
icon_state = "bandolier"
icon_state = "bandolier2"
/obj/item/weapon/storage/belt/janitor
name = "janitorial belt"
@@ -447,4 +529,13 @@
name = "ranger belt"
desc = "The fancy utility-belt holding the tools, cuffs and gadgets of the Go Go ERT-Rangers. The belt buckle is not real phoron, but it is still surprisingly comfortable to wear."
icon = 'icons/obj/clothing/ranger.dmi'
icon_state = "ranger_belt"
icon_state = "ranger_belt"
/obj/item/weapon/storage/belt/dbandolier
name = "\improper Donk-Soft bandolier"
desc = "A Donk-Soft bandolier! Carry your spare darts anywhere! Ages 8 and up."
icon_state = "dbandolier"
storage_slots = 8
can_hold = list(
/obj/item/ammo_casing/afoam_dart
)
@@ -22,6 +22,7 @@
/obj/item/weapon/storage/box
name = "box"
desc = "It's just an ordinary box."
icon = 'icons/obj/boxes.dmi'
icon_state = "box"
item_state = "syringe_kit"
center_of_mass = list("x" = 13,"y" = 10)
@@ -72,21 +73,29 @@
/obj/item/weapon/storage/box/survival
name = "emergency supply box"
desc = "A survival box issued to crew members for use in emergency situations."
icon_state = "survival"
starts_with = list(
/obj/item/weapon/tool/prybar/red,
/obj/item/clothing/glasses/goggles,
/obj/item/clothing/mask/breath
)
/obj/item/weapon/storage/box/survival/synth
name = "synthetic supply box"
desc = "A survival box issued to synthetic crew members for use in emergency situations."
icon_state = "survival_synth"
starts_with = list(
/obj/item/weapon/tool/prybar/red,
/obj/item/clothing/glasses/goggles
)
/obj/item/weapon/storage/box/survival/comp
name = "emergency supply box"
desc = "A comprehensive survival box issued to crew members for use in emergency situations. Contains additional supplies."
icon_state = "survival"
icon_state = "survival_comp"
starts_with = list(
/obj/item/weapon/tool/prybar/red,
/obj/item/clothing/glasses/goggles,
/obj/item/weapon/reagent_containers/hypospray/autoinjector,
/obj/item/stack/medical/bruise_pack,
/obj/item/device/flashlight/glowstick,
@@ -115,7 +124,7 @@
/obj/item/weapon/storage/box/syringegun
name = "box of syringe gun cartridges"
desc = "A box full of compressed gas cartridges."
icon_state = "syringe"
icon_state = "syringe2"
starts_with = list(/obj/item/weapon/syringe_cartridge = 7)
/obj/item/weapon/storage/box/beakers
@@ -127,6 +136,7 @@
/obj/item/weapon/storage/box/injectors
name = "box of DNA injectors"
desc = "This box contains injectors it seems."
icon_state = "dna"
starts_with = list(
/obj/item/weapon/dnainjector/h2m = 3,
/obj/item/weapon/dnainjector/m2h = 3
@@ -374,17 +384,19 @@
/obj/item/weapon/storage/box/condimentbottles
name = "box of condiment bottles"
desc = "It has a large ketchup smear on it."
icon_state = "condiment"
starts_with = list(/obj/item/weapon/reagent_containers/food/condiment = 7)
/obj/item/weapon/storage/box/cups
name = "box of paper cups"
desc = "It has pictures of paper cups on the front."
icon_state = "cups"
starts_with = list(/obj/item/weapon/reagent_containers/food/drinks/sillycup = 7)
/obj/item/weapon/storage/box/donkpockets
name = "box of donk-pockets"
desc = "<B>Instructions:</B> <I>Heat in microwave. Product will cool if not eaten within seven minutes.</I>"
icon_state = "donk_kit"
icon_state = "donkpocketbox"
starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/donkpocket = 7)
/obj/item/weapon/storage/box/sinpockets
@@ -450,6 +462,7 @@
/obj/item/weapon/storage/box/pillbottles
name = "box of pill bottles"
desc = "It has pictures of pill bottles on its front."
icon_state = "pillbox"
starts_with = list(/obj/item/weapon/storage/pill_bottle = 7)
/obj/item/weapon/storage/box/snappops
@@ -485,12 +498,12 @@
/obj/item/weapon/storage/box/autoinjectors
name = "box of injectors"
desc = "Contains autoinjectors."
icon_state = "syringe"
icon_state = "auto"
starts_with = list(/obj/item/weapon/reagent_containers/hypospray/autoinjector = 7)
/obj/item/weapon/storage/box/lights
name = "box of replacement bulbs"
icon = 'icons/obj/storage.dmi'
icon = 'icons/obj/boxes.dmi'
icon_state = "light"
desc = "This box is shaped on the inside so that only light tubes and bulbs fit."
item_state_slots = list(slot_r_hand_str = "syringe_kit", slot_l_hand_str = "syringe_kit")
@@ -555,3 +568,17 @@
name = "ambrosia deus seeds box"
desc = "Contains the seeds you need to get a proper healthy high."
starts_with = list(/obj/item/seeds/ambrosiadeusseed = 7)
/obj/item/weapon/storage/box/capguntoy
name = "\improper AlliCo \"Zipper\" Cap Gun"
icon = 'icons/obj/gun_toy.dmi'
icon_state = "cap_gun_box"
desc = "This box is shaped on the inside so that only the \"Zipper\" Capgun and extra caps can fit."
item_state_slots = list(slot_r_hand_str = "syringe_kit", slot_l_hand_str = "syringe_kit")
storage_slots = 2
max_w_class = ITEMSIZE_NORMAL
can_hold = list(/obj/item/weapon/gun/projectile/revolver/capgun, /obj/item/ammo_magazine/ammo_box/cap)
starts_with = list(
/obj/item/weapon/gun/projectile/revolver/capgun = 1,
/obj/item/ammo_magazine/ammo_box/cap = 1
)
@@ -1,27 +1,3 @@
/obj/item/weapon/storage/box/survival
starts_with = list(
/obj/item/weapon/tool/prybar/red,
/obj/item/clothing/glasses/goggles,
/obj/item/clothing/mask/breath
)
/obj/item/weapon/storage/box/survival/synth
starts_with = list(
/obj/item/weapon/tool/prybar/red,
/obj/item/clothing/glasses/goggles
)
/obj/item/weapon/storage/box/survival/comp
starts_with = list(
/obj/item/weapon/tool/prybar/red,
/obj/item/clothing/glasses/goggles,
/obj/item/weapon/reagent_containers/hypospray/autoinjector,
/obj/item/stack/medical/bruise_pack,
/obj/item/device/flashlight/glowstick,
/obj/item/weapon/reagent_containers/food/snacks/candy/proteinbar,
/obj/item/clothing/mask/breath
)
/obj/item/weapon/storage/box/explorerkeys
name = "box of volunteer headsets"
desc = "A box full of volunteer headsets, for issuing out to exploration volunteers."
@@ -39,7 +15,7 @@
/obj/item/weapon/storage/box/survival/space
name = "boxed emergency suit and helmet"
icon_state = "survivaleng"
icon_state = "survival_comp3"
starts_with = list(
/obj/item/clothing/suit/space/emergency,
/obj/item/clothing/head/helmet/space/emergency,
@@ -49,3 +25,14 @@
/obj/item/weapon/storage/secure/briefcase/trashmoney
starts_with = list(/obj/item/weapon/spacecash/c200 = 10)
/obj/item/weapon/storage/box/brainzsnax
name = "\improper BrainzSnax box"
icon_state = "brainzsnax_box"
desc = "A box designed to hold canned food. This one has BrainzSnax branding printed on it."
can_hold = list(/obj/item/weapon/reagent_containers/food/snacks/canned)
max_storage_space = ITEMSIZE_COST_NORMAL * 6
starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/canned/brainzsnax = 6)
/obj/item/weapon/storage/box/brainzsnax/red
starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/canned/brainzsnax/red = 6)
@@ -16,6 +16,10 @@
allow_quick_empty = TRUE
use_sound = 'sound/items/drop/flesh.ogg'
/obj/item/weapon/storage/vore_egg/Initialize()
. = ..()
randpixel_xy()
/obj/item/weapon/storage/vore_egg/open(mob/user as mob)
if(isobserver(user))
return
@@ -68,7 +68,8 @@
item_state = "candlebox5"
throwforce = 2
slot_flags = SLOT_BELT
max_storage_space = ITEMSIZE_COST_SMALL * 5
max_storage_space = ITEMSIZE_COST_TINY * 5
can_hold = list(/obj/item/weapon/flame/candle)
starts_with = list(/obj/item/weapon/flame/candle = 5)
/obj/item/weapon/storage/fancy/whitecandle_box
@@ -80,7 +81,8 @@
item_state = "whitecandlebox5"
throwforce = 2
slot_flags = SLOT_BELT
max_storage_space = ITEMSIZE_COST_SMALL * 5
max_storage_space = ITEMSIZE_COST_TINY * 5
can_hold = list(/obj/item/weapon/flame/candle)
starts_with = list(/obj/item/weapon/flame/candle/white = 5)
/obj/item/weapon/storage/fancy/blackcandle_box
@@ -92,7 +94,8 @@
item_state = "blackcandlebox5"
throwforce = 2
slot_flags = SLOT_BELT
max_storage_space = ITEMSIZE_COST_SMALL * 5
max_storage_space = ITEMSIZE_COST_TINY * 5
can_hold = list(/obj/item/weapon/flame/candle)
starts_with = list(/obj/item/weapon/flame/candle/black = 5)
@@ -15,7 +15,7 @@
can_hold = null
pocketable = TRUE
var/insert_delay = 0
var/insert_delay = 0 SECONDS
var/remove_delay = 2 SECONDS
/obj/item/weapon/storage/pouch/stall_insertion(obj/item/W, mob/user)
@@ -23,26 +23,23 @@
if(user.get_active_hand() == src || user.get_inactive_hand() == src)
return TRUE // Skip delay
if(insert_delay && !do_after(user, 2 SECONDS, src, needhand = TRUE, exclusive = TASK_USER_EXCLUSIVE))
return FALSE // Moved or whatever
if(insert_delay && !do_after(user, insert_delay, src, needhand = TRUE, exclusive = TASK_USER_EXCLUSIVE))
return FALSE // Moved while there is a delay
if(W in src)
return TRUE // Item is still inside
return FALSE
return TRUE //Now we're allowed to put the item in the pouch
/obj/item/weapon/storage/pouch/stall_removal(obj/item/W, mob/user)
// No delay if you have the pouch in your hands
if(user.get_active_hand() == src || user.get_inactive_hand() == src)
return TRUE // Skip delay
if(remove_delay && !do_after(user, 2 SECONDS, src, needhand = TRUE, exclusive = TASK_USER_EXCLUSIVE))
return FALSE // Moved or whatever
if(remove_delay && !do_after(user, remove_delay, src, needhand = TRUE, exclusive = TASK_USER_EXCLUSIVE))
return FALSE // Moved while there is a delay
if(W in src)
return TRUE // Item is still inside
return FALSE
return FALSE //Item was somehow already removed
/obj/item/weapon/storage/pouch/pocket_description(mob/haver, mob/examiner)
return "[src]"
@@ -679,6 +679,10 @@
if(!Adjacent(usr))
return
//VOREStation Add: No turf dumping if user is in a belly
if(isbelly(usr.loc))
return
drop_contents()
/obj/item/weapon/storage/proc/drop_contents() // why is this a proc? literally just for RPEDs
@@ -1,7 +1,10 @@
/*
* Toolboxes
*/
/obj/item/weapon/storage/toolbox
name = "toolbox"
desc = "Danger. Very robust."
icon = 'icons/obj/storage.dmi'
icon = 'icons/obj/storage_vr.dmi'
icon_state = "red"
item_state_slots = list(slot_r_hand_str = "toolbox_red", slot_l_hand_str = "toolbox_red")
center_of_mass = list("x" = 16,"y" = 11)
@@ -18,8 +21,10 @@
drop_sound = 'sound/items/drop/toolbox.ogg'
pickup_sound = 'sound/items/pickup/toolbox.ogg'
//Emergency
/obj/item/weapon/storage/toolbox/emergency
name = "emergency toolbox"
icon = 'icons/obj/storage_vr.dmi'
icon_state = "red"
item_state_slots = list(slot_r_hand_str = "toolbox_red", slot_l_hand_str = "toolbox_red")
starts_with = list(
@@ -34,8 +39,10 @@
new /obj/item/device/flashlight/flare(src)
. = ..()
//Mechanical
/obj/item/weapon/storage/toolbox/mechanical
name = "mechanical toolbox"
icon = 'icons/obj/storage_vr.dmi'
icon_state = "blue"
item_state_slots = list(slot_r_hand_str = "toolbox_blue", slot_l_hand_str = "toolbox_blue")
starts_with = list(
@@ -47,8 +54,10 @@
/obj/item/weapon/tool/wirecutters
)
//Electrical
/obj/item/weapon/storage/toolbox/electrical
name = "electrical toolbox"
icon = 'icons/obj/storage_vr.dmi'
icon_state = "yellow"
item_state_slots = list(slot_r_hand_str = "toolbox_yellow", slot_l_hand_str = "toolbox_yellow")
starts_with = list(
@@ -67,8 +76,10 @@
new /obj/item/stack/cable_coil/random(src,30)
calibrate_size()
//Syndicate
/obj/item/weapon/storage/toolbox/syndicate
name = "black and red toolbox"
icon = 'icons/obj/storage_vr.dmi'
icon_state = "syndicate"
item_state_slots = list(slot_r_hand_str = "toolbox_syndi", slot_l_hand_str = "toolbox_syndi")
origin_tech = list(TECH_COMBAT = 1, TECH_ILLEGAL = 1)
@@ -94,9 +105,43 @@
/obj/item/device/analyzer
)
//Brass
/obj/item/weapon/storage/toolbox/brass
name = "brass toolbox"
icon = 'icons/obj/storage_vr.dmi'
icon_state = "brass"
item_state_slots = list(slot_r_hand_str = "toolbox_yellow", slot_l_hand_str = "toolbox_yellow")
starts_with = list(
/obj/item/weapon/tool/crowbar/brass,
/obj/item/weapon/tool/wirecutters/brass,
/obj/item/weapon/tool/screwdriver/brass,
/obj/item/weapon/tool/wrench/brass,
/obj/item/weapon/weldingtool/brass
)
//Hydro
/obj/item/weapon/storage/toolbox/hydro
name = "hydroponic toolbox"
icon = 'icons/obj/storage_vr.dmi'
icon_state = "green"
item_state_slots = list(slot_r_hand_str = "toolbox_green", slot_l_hand_str = "toolbox_green")
starts_with = list(
/obj/item/device/analyzer/plant_analyzer,
/obj/item/weapon/material/minihoe,
/obj/item/weapon/material/knife/machete/hatchet,
/obj/item/weapon/tool/wirecutters/clippers/trimmers,
/obj/item/weapon/reagent_containers/spray/plantbgone,
/obj/item/weapon/reagent_containers/glass/beaker
)
/*
* Lunchboxes
*/
/obj/item/weapon/storage/toolbox/lunchbox
max_storage_space = ITEMSIZE_COST_SMALL * 4 //slightly smaller than a toolbox
name = "rainbow lunchbox"
icon = 'icons/obj/storage.dmi'
icon_state = "lunchbox_rainbow"
item_state_slots = list(slot_r_hand_str = "toolbox_pink", slot_l_hand_str = "toolbox_pink")
desc = "A little lunchbox. This one is the colors of the rainbow!"
@@ -125,6 +170,7 @@
/obj/item/weapon/storage/toolbox/lunchbox/heart
name = "heart lunchbox"
icon = 'icons/obj/storage.dmi'
icon_state = "lunchbox_lovelyhearts"
item_state_slots = list(slot_r_hand_str = "toolbox_pink", slot_l_hand_str = "toolbox_pink")
desc = "A little lunchbox. This one has cute little hearts on it!"
@@ -134,6 +180,7 @@
/obj/item/weapon/storage/toolbox/lunchbox/cat
name = "cat lunchbox"
icon = 'icons/obj/storage.dmi'
icon_state = "lunchbox_sciencecatshow"
item_state_slots = list(slot_r_hand_str = "toolbox_green", slot_l_hand_str = "toolbox_green")
desc = "A little lunchbox. This one has a cute little science cat from a popular show on it!"
@@ -143,6 +190,7 @@
/obj/item/weapon/storage/toolbox/lunchbox/nt
name = "NanoTrasen brand lunchbox"
icon = 'icons/obj/storage.dmi'
icon_state = "lunchbox_nanotrasen"
item_state_slots = list(slot_r_hand_str = "toolbox_blue", slot_l_hand_str = "toolbox_blue")
desc = "A little lunchbox. This one is branded with the NanoTrasen logo!"
@@ -152,6 +200,7 @@
/obj/item/weapon/storage/toolbox/lunchbox/mars
name = "\improper Mojave university lunchbox"
icon = 'icons/obj/storage.dmi'
icon_state = "lunchbox_marsuniversity"
item_state_slots = list(slot_r_hand_str = "toolbox_red", slot_l_hand_str = "toolbox_red")
desc = "A little lunchbox. This one is branded with the Mojave university logo!"
@@ -161,6 +210,7 @@
/obj/item/weapon/storage/toolbox/lunchbox/cti
name = "\improper CTI lunchbox"
icon = 'icons/obj/storage.dmi'
icon_state = "lunchbox_cti"
item_state_slots = list(slot_r_hand_str = "toolbox_blue", slot_l_hand_str = "toolbox_blue")
desc = "A little lunchbox. This one is branded with the CTI logo!"
@@ -170,6 +220,7 @@
/obj/item/weapon/storage/toolbox/lunchbox/nymph
name = "\improper Diona nymph lunchbox"
icon = 'icons/obj/storage.dmi'
icon_state = "lunchbox_dionanymph"
item_state_slots = list(slot_r_hand_str = "toolbox_yellow", slot_l_hand_str = "toolbox_yellow")
desc = "A little lunchbox. This one is an adorable Diona nymph on the side!"
@@ -179,6 +230,7 @@
/obj/item/weapon/storage/toolbox/lunchbox/syndicate
name = "black and red lunchbox"
icon = 'icons/obj/storage.dmi'
icon_state = "lunchbox_syndie"
item_state_slots = list(slot_r_hand_str = "toolbox_syndi", slot_l_hand_str = "toolbox_syndi")
desc = "A little lunchbox. This one is a sleek black and red, made of a durable steel!"
@@ -31,11 +31,6 @@
/obj/item/weapon/melee/baton/get_cell()
return bcell
/obj/item/weapon/melee/baton/suicide_act(mob/user)
var/datum/gender/TU = gender_datums[user.get_visible_gender()]
user.visible_message("<span class='suicide'>\The [user] is putting the live [name] in [TU.his] mouth! It looks like [TU.he] [TU.is] trying to commit suicide.</span>")
return (FIRELOSS)
/obj/item/weapon/melee/baton/MouseDrop(obj/over_object as obj)
if(!canremove)
return
@@ -84,12 +84,6 @@
attack_verb = list("drilled")
drop_sound = 'sound/items/drop/accessory.ogg'
/obj/item/weapon/surgical/surgicaldrill/suicide_act(mob/user)
var/datum/gender/TU = gender_datums[user.get_visible_gender()]
to_chat(viewers(user),pick("<span class='danger'>\The [user] is pressing \the [src] to [TU.his] temple and activating it! It looks like [TU.hes] trying to commit suicide.</span>",
"<span class='danger'>\The [user] is pressing \the [src] to [TU.his] chest and activating it! It looks like [TU.hes] trying to commit suicide.</span>"))
return (BRUTELOSS)
/*
* Scalpel
*/
@@ -110,13 +104,6 @@
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
drop_sound = 'sound/items/drop/knife.ogg'
/obj/item/weapon/surgical/scalpel/suicide_act(mob/user)
var/datum/gender/TU = gender_datums[user.get_visible_gender()]
to_chat(viewers(user),pick("<span class='danger'>\The [user] is slitting [TU.his] wrists with the [src.name]! It looks like [TU.hes] trying to commit suicide.</span>", \
"<span class='danger'>\The [user] is slitting [TU.his] throat with the [src.name]! It looks like [TU.hes] trying to commit suicide.</span>", \
"<span class='danger'>\The [user] is slitting [TU.his] stomach open with the [src.name]! It looks like [TU.hes] trying to commit seppuku.</span>"))
return (BRUTELOSS)
/*
* Researchable Scalpels
*/
@@ -0,0 +1,32 @@
/*
* Brass Tools
*/
//Crowbar
/obj/item/weapon/tool/crowbar/brass
icon_state = "crowbar_brass"
item_state = "crowbar"
//Cutters
/obj/item/weapon/tool/wirecutters/brass
icon_state = "cutters_brass"
item_state = "cutters_yellow"
//Screwdriver
/obj/item/weapon/tool/screwdriver/brass
icon_state = "screwdriver_brass"
item_state = "screwdriver_black"
//Wrench
/obj/item/weapon/tool/wrench/brass
icon_state = "wrench_brass"
item_state = "wrench_brass"
//Welder
/obj/item/weapon/weldingtool/brass
name = "brass welding tool"
desc = "A welder made from brass fittings."
icon_state = "brasswelder"
max_fuel = 20
origin_tech = list(TECH_ENGINEERING = 2, TECH_PHORON = 2)
matter = list(MAT_STEEL = 70, MAT_GLASS = 60)
@@ -1,7 +1,6 @@
/*
* Crowbar
*/
/obj/item/weapon/tool/crowbar
name = "crowbar"
desc = "Used to remove floors and to pry open doors."
@@ -27,6 +26,10 @@
icon_state = "red_crowbar"
item_state = "crowbar_red"
/obj/item/weapon/tool/crowbar/old
icon = 'icons/obj/tools.dmi'
icon_state = "old_crowbar"
item_state = "crowbar"
/datum/category_item/catalogue/anomalous/precursor_a/alien_crowbar
name = "Precursor Alpha Object - Hard Light Pry Tool"
@@ -7,11 +7,11 @@
desc = "A steel bar with a wedge, designed specifically for opening unpowered doors in an emergency. It comes in a variety of configurations - collect them all!"
icon = 'icons/obj/tools_vr.dmi'
icon_state = "prybar"
item_state = "crowbar"
slot_flags = SLOT_BELT
force = 4
throwforce = 5
pry = 1
item_state = "crowbar"
w_class = ITEMSIZE_SMALL
origin_tech = list(TECH_ENGINEERING = 1)
matter = list(MAT_STEEL = 30)
@@ -24,12 +24,6 @@
tool_qualities = list(TOOL_SCREWDRIVER)
var/random_color = TRUE
/obj/item/weapon/tool/screwdriver/suicide_act(mob/user)
var/datum/gender/TU = gender_datums[user.get_visible_gender()]
to_chat(viewers(user), pick("<span class='danger'>\The [user] is stabbing the [src.name] into [TU.his] temple! It looks like [TU.hes] trying to commit suicide.</span>", \
"<span class='danger'>\The [user] is stabbing the [src.name] into [TU.his] heart! It looks like [TU.hes] trying to commit suicide.</span>"))
return(BRUTELOSS)
/obj/item/weapon/tool/screwdriver/New()
if(random_color)
switch(pick("red","blue","purple","brown","green","cyan","yellow"))
@@ -21,7 +21,7 @@
//R&D tech level
origin_tech = list(TECH_ENGINEERING = 1)
tool_qualities = list(TOOL_WELDER)
//Welding tool specific stuff
@@ -375,7 +375,7 @@
/obj/item/weapon/weldingtool/hugetank
name = "upgraded welding tool"
desc = "A much larger welder with a huge tank."
icon_state = "indwelder"
icon_state = "upindwelder"
max_fuel = 80
w_class = ITEMSIZE_NORMAL
origin_tech = list(TECH_ENGINEERING = 3)
@@ -392,6 +392,9 @@
toolspeed = 2
eye_safety_modifier = 1 // Safer on eyes.
/obj/item/weapon/weldingtool/mini/two
icon_state = "miniwelder2"
/datum/category_item/catalogue/anomalous/precursor_a/alien_welder
name = "Precursor Alpha Object - Self Refueling Exothermic Tool"
desc = "An unwieldly tool which somewhat resembles a weapon, due to \
@@ -6,6 +6,7 @@
desc = "This cuts wires."
icon = 'icons/obj/tools.dmi'
icon_state = "cutters"
item_state = "cutters"
center_of_mass = list("x" = 18,"y" = 10)
slot_flags = SLOT_BELT
force = 6
@@ -26,9 +27,20 @@
var/random_color = TRUE
/obj/item/weapon/tool/wirecutters/New()
if(random_color && prob(50))
icon_state = "cutters-y"
item_state = "cutters_yellow"
if(random_color)
switch(pick("red","blue","yellow"))
if ("red")
icon_state = "cutters"
item_state = "cutters"
if ("blue")
icon_state = "cutters-b"
item_state = "cutters_blue"
if ("yellow")
icon_state = "cutters-y"
item_state = "cutters_yellow"
if (prob(75))
src.pixel_y = rand(0, 16)
..()
/obj/item/weapon/tool/wirecutters/attack(mob/living/carbon/C as mob, mob/user as mob)
@@ -25,6 +25,14 @@
usesound = 'sound/items/drill_use.ogg'
toolspeed = 0.5
/obj/item/weapon/tool/wrench/pipe
name = "pipe wrench"
desc = "A wrench used for plumbing. Can make a good makeshift weapon."
icon_state = "pipe_wrench"
slot_flags = SLOT_BELT
force = 8
throwforce = 10
/obj/item/weapon/tool/wrench/hybrid // Slower and bulkier than normal power tools, but it has the power of reach. If reach even worked half the time.
name = "strange wrench"
desc = "A wrench with many common uses. Can be usually found in your hand."
@@ -40,7 +48,6 @@
toolspeed = 0.5
reach = 2
/datum/category_item/catalogue/anomalous/precursor_a/alien_wrench
name = "Precursor Alpha Object - Fastener Torque Tool"
desc = "This is an object that has a distinctive tool shape. \
-5
View File
@@ -22,11 +22,6 @@
var/camo_net = FALSE
var/stun_length = 0.25 SECONDS
/obj/item/weapon/beartrap/suicide_act(mob/user)
var/datum/gender/T = gender_datums[user.get_visible_gender()]
to_chat(viewers(user),"<span class='danger'>[user] is putting the [src.name] on [T.his] head! It looks like [T.hes] trying to commit suicide.</span>")
return (BRUTELOSS)
/obj/item/weapon/beartrap/proc/can_use(mob/user)
return (user.IsAdvancedToolUser() && !issilicon(user) && !user.stat && !user.restrained())
@@ -12,11 +12,6 @@
drop_sound = 'sound/items/drop/sword.ogg'
pickup_sound = 'sound/items/pickup/sword.ogg'
/obj/item/weapon/nullrod/suicide_act(mob/user)
var/datum/gender/T = gender_datums[user.get_visible_gender()]
to_chat(viewers(user),"<span class='danger'>[user] is impaling [T.himself] with the [src.name]! It looks like [T.he] [T.is] trying to commit suicide.</span>")
return (BRUTELOSS|FIRELOSS)
/obj/item/weapon/nullrod/attack(mob/M as mob, mob/living/user as mob) //Paste from old-code to decult with a null rod.
add_attack_logs(user,M,"Hit with [src] (nullrod)")