diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 4b96db2f5a..42b452ee25 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -7,7 +7,6 @@ "oderwat.indent-rainbow", "rexebin.darkpurple-black", "dbaeumer.vscode-eslint", - "editorconfig.editorconfig", "donkie.vscode-tgstation-test-adapter", "icrawl.discord-vscode", "esbenp.prettier-vscode" diff --git a/code/ATMOSPHERICS/datum_pipeline.dm b/code/ATMOSPHERICS/datum_pipeline.dm index 64b5490472..7a1f5cce95 100644 --- a/code/ATMOSPHERICS/datum_pipeline.dm +++ b/code/ATMOSPHERICS/datum_pipeline.dm @@ -161,16 +161,14 @@ if(istype(target, /turf/simulated)) var/turf/simulated/modeled_location = target - - if(modeled_location.special_temperature)//First do special interactions then the usuall stuff - var/delta_temp = modeled_location.special_temperature - air.temperature//2200C - 20C = 2180K - //assuming aluminium with thermal conductivity 235 W * K / m, Copper (400), Silver (430), steel (50), gold (320) - var/heat_gain = 23500 * 100 * delta_temp - air.add_thermal_energy(heat_gain) - if(network) - network.update = 1 - + if (modeled_location.special_temperature) + air.temperature += thermal_conductivity * (modeled_location.special_temperature - air.temperature) + if (air.temperature < TCMB) + air.temperature = TCMB + if (network) + network.update = TRUE + if(modeled_location.blocks_air) if((modeled_location.heat_capacity>0) && (partial_heat_capacity>0)) diff --git a/code/__defines/dcs/signals.dm b/code/__defines/dcs/signals.dm index 1ae4237a0d..06fb819b07 100644 --- a/code/__defines/dcs/signals.dm +++ b/code/__defines/dcs/signals.dm @@ -400,10 +400,6 @@ ///called when removing a given item from a mob, from mob/living/carbon/remove_embedded_object(mob/living/carbon/target, /obj/item) #define COMSIG_CARBON_EMBED_REMOVAL "item_embed_remove_safe" -// /mob/living/simple_animal/hostile signals -#define COMSIG_HOSTILE_ATTACKINGTARGET "hostile_attackingtarget" - #define COMPONENT_HOSTILE_NO_ATTACK (1<<0) - // /obj signals ///from base of obj/deconstruct(): (disassembled) diff --git a/code/__defines/materials.dm b/code/__defines/materials.dm index 9536547c1d..e9ec7a357a 100644 --- a/code/__defines/materials.dm +++ b/code/__defines/materials.dm @@ -54,6 +54,8 @@ #define MAT_PLATINUM "platinum" #define MAT_TRITIUM "tritium" #define MAT_DEUTERIUM "deuterium" +#define MAT_CONCRETE "concrete" +#define MAT_PLASTEELREBAR "plasteel rebar" #define DEFAULT_TABLE_MATERIAL MAT_PLASTIC diff --git a/code/__defines/nifsoft.dm b/code/__defines/nifsoft.dm index cca614f1fb..114ee32779 100644 --- a/code/__defines/nifsoft.dm +++ b/code/__defines/nifsoft.dm @@ -40,9 +40,10 @@ #define NIF_SIZECHANGE 33 #define NIF_SOULCATCHER 34 #define NIF_WORLDBEND 35 +#define NIF_MALWARE 36 // Must be equal to the highest number above -#define TOTAL_NIF_SOFTWARE 35 +#define TOTAL_NIF_SOFTWARE 36 ////////////////////// // NIF flag list hints diff --git a/code/_onclick/hud/popups_vr.dm b/code/_onclick/hud/popups_vr.dm new file mode 100644 index 0000000000..76e72224ef --- /dev/null +++ b/code/_onclick/hud/popups_vr.dm @@ -0,0 +1,71 @@ +/obj/screen/popup + name = "popup" + desc = "NOTICE ME!" + + icon = 'icons/mob/screen1_popups.dmi' + plane = PLANE_PLAYER_HUD_ABOVE + layer = INFINITY + + var/close_button_x_start + var/close_button_x_end + var/close_button_y_start + var/close_button_y_end + + var/client/holder + +/obj/screen/popup/Click(location, control,params) + var/list/PL = params2list(params) + var/icon_x = text2num(PL["icon-x"]) + var/icon_y = text2num(PL["icon-y"]) + if(check_click_spot(icon_x, icon_y)) + close_popup() + else + popup_action() + +/obj/screen/popup/proc/popup_action() + return + +/obj/screen/popup/proc/close_popup() + holder.screen -= src + qdel(src) + +/obj/screen/popup/proc/check_click_spot(click_x, click_y) + if((click_x <= close_button_x_end) && (click_x >= close_button_x_start)) + if((click_y <= close_button_y_end) && (click_y >= close_button_y_start)) + return TRUE + return FALSE + +/obj/screen/popup/proc/get_random_screen_location() + var/loc_x = rand(1,11) + var/loc_x_offset = rand(0,16) + var/loc_y = rand(1,12) + var/loc_y_offset = rand(0,16) + return "[loc_x]:[loc_x_offset],[loc_y]:[loc_y_offset]" + +/client/proc/create_fake_ad_popup(popup_type) + if(!src) + return + var/obj/screen/popup/ad = new popup_type() + ad.screen_loc = ad.get_random_screen_location() + src.screen |= ad + ad.holder = src + +/client/proc/create_fake_ad_popup_multiple(popup_type, popup_amount) + if(!src) + return + for(var/i = 0, i < popup_amount, i++) + create_fake_ad_popup(popup_type) + +/obj/screen/popup/default + name = "CLICK ME" + + icon_state = "popup1" + + close_button_x_start = 118 + close_button_x_end = 126 + close_button_y_start = 86 + close_button_y_end = 94 + +/obj/screen/popup/default/New() + ..() + icon_state = "popup[rand(1,4)]" \ No newline at end of file diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 8954bf45bc..72e2219ad8 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -167,6 +167,9 @@ vis_contents -= hover_overlays_cache[hovering_choice] hovering_choice = choice + if(!choice) + return + var/obj/effect/overlay/zone_sel/overlay_object = hover_overlays_cache[choice] if(!overlay_object) overlay_object = new @@ -174,7 +177,6 @@ hover_overlays_cache[choice] = overlay_object vis_contents += overlay_object - /obj/effect/overlay/zone_sel icon = 'icons/mob/zone_sel.dmi' mouse_opacity = MOUSE_OPACITY_TRANSPARENT @@ -240,7 +242,7 @@ update_icon() /obj/screen/zone_sel/update_icon() - cut_overlay(selecting_appearance) + cut_overlays() selecting_appearance = mutable_appearance('icons/mob/zone_sel.dmi', "[selecting]") add_overlay(selecting_appearance) @@ -985,4 +987,4 @@ else //"0" is still length 1 so this means it's over 999 overlays += image('icons/mob/screen_ammo.dmi', src, "o9") overlays += image('icons/mob/screen_ammo.dmi', src, "t9") - overlays += image('icons/mob/screen_ammo.dmi', src, "h9") \ No newline at end of file + overlays += image('icons/mob/screen_ammo.dmi', src, "h9") diff --git a/code/datums/supplypacks/hospitality.dm b/code/datums/supplypacks/hospitality.dm index bcf472a0b9..544ad90b6e 100644 --- a/code/datums/supplypacks/hospitality.dm +++ b/code/datums/supplypacks/hospitality.dm @@ -47,7 +47,7 @@ cost = 10 containertype = /obj/structure/closet/crate/gilthari containername = "crate of bar supplies" - + /datum/supply_pack/hospitality/cookingoil name = "Cooking oil tank crate" contains = list(/obj/structure/reagent_dispensers/cookingoil) @@ -96,6 +96,15 @@ containertype = /obj/structure/closet/crate/centauri containername = "Painting equipment" +/datum/supply_pack/hospitality/holywater + name = "Holy water crate" + contains = list( + /obj/item/weapon/reagent_containers/food/drinks/bottle/holywater = 3 + ) + cost = 15 + containertype = /obj/structure/closet/crate/gilthari + containername = "holy water crate" + /datum/supply_pack/randomised/hospitality/ group = "Hospitality" diff --git a/code/datums/supplypacks/materials.dm b/code/datums/supplypacks/materials.dm index 3268d05a46..d06238dc41 100644 --- a/code/datums/supplypacks/materials.dm +++ b/code/datums/supplypacks/materials.dm @@ -83,4 +83,11 @@ containertype = /obj/structure/closet/crate/grayson containername = "Linoleum crate" cost = 15 - contains = list(/obj/fiftyspawner/linoleum) \ No newline at end of file + contains = list(/obj/fiftyspawner/linoleum) + +/datum/supply_pack/materials/concrete + name = "Concrete" + cost = 10 + containertype = /obj/structure/closet/crate/grayson + contains = list(/obj/fiftyspawner/concrete) + containername = "Concrete bricks crate" \ No newline at end of file diff --git a/code/datums/supplypacks/munitions.dm b/code/datums/supplypacks/munitions.dm index 73d150fd03..64567176a0 100644 --- a/code/datums/supplypacks/munitions.dm +++ b/code/datums/supplypacks/munitions.dm @@ -75,6 +75,19 @@ containername = "Shotgun crate" access = access_armory /* VOREStation edit -- This is a bad idea. -- So is this. + +/datum/supply_pack/munitions/shotgunsemi + name = "Weapons - Semi-Automatic Shotgun crate" + contains = list( + /obj/item/ammo_magazine/ammo_box/b12g, + /obj/item/ammo_magazine/ammo_box/b12g/pellet, + /obj/item/weapon/gun/projectile/shotgun/semi = 2 + ) + cost = 100 + containertype = /obj/structure/closet/crate/secure/weapon + containername = "Semi-Auto Shotgun crate" + access = access_armory + /datum/supply_pack/munitions/erifle name = "Weapons - Energy marksman" contains = list(/obj/item/weapon/gun/energy/sniperrifle = 2) @@ -307,4 +320,4 @@ cost = 500 containertype = /obj/structure/closet/crate/secure containername = "Light machine gun crate" - access = access_armory \ No newline at end of file + access = access_armory diff --git a/code/datums/supplypacks/vending_refills_vr.dm b/code/datums/supplypacks/vending_refills_vr.dm index 348193a1bf..bfa42113f7 100644 --- a/code/datums/supplypacks/vending_refills_vr.dm +++ b/code/datums/supplypacks/vending_refills_vr.dm @@ -18,11 +18,6 @@ name = "SweatMAX Vendor Refill Cartridge" cost = 10 -/datum/supply_pack/vending_refills/hotfood - contains = list(/obj/item/weapon/refill_cartridge/autoname/food/hotfood) - name = "Hot Foods Vendor Refill Cartridge" - cost = 10 - /datum/supply_pack/vending_refills/weeb contains = list(/obj/item/weapon/refill_cartridge/autoname/food/weeb) name = "Nippon-tan Vendor Refill Cartridge" @@ -122,7 +117,6 @@ num_contained = 5 contains = list(/obj/item/weapon/refill_cartridge/autoname/food/snack, /obj/item/weapon/refill_cartridge/autoname/food/fitness, - /obj/item/weapon/refill_cartridge/autoname/food/hotfood, /obj/item/weapon/refill_cartridge/autoname/food/weeb, /obj/item/weapon/refill_cartridge/autoname/food/sol, /obj/item/weapon/refill_cartridge/autoname/food/snix, diff --git a/code/datums/supplypacks/voidsuits.dm b/code/datums/supplypacks/voidsuits.dm index 2d1ae7c99a..c28b3e9559 100644 --- a/code/datums/supplypacks/voidsuits.dm +++ b/code/datums/supplypacks/voidsuits.dm @@ -266,4 +266,13 @@ cost = 150 containertype = /obj/structure/closet/crate/oculum containername = "Vox Engineering Hardsuit" + +/datum/supply_pack/voidsuits/voxsec + name = "Vox Security Hardsuit" + contains = list (/obj/item/weapon/rig/vox/security) + cost = 90 + containertype = /obj/structure/closet/crate/secure/heph + containername = "Vox security Rigsuit Crate" + access = access_security + //ChompEdit End diff --git a/code/datums/uplink/armor.dm b/code/datums/uplink/armor.dm index 0d7d814310..362aec5d92 100644 --- a/code/datums/uplink/armor.dm +++ b/code/datums/uplink/armor.dm @@ -6,25 +6,25 @@ /datum/uplink_item/item/armor/combat name = "Combat Armor Set" - item_cost = 60 + item_cost = 30 path = /obj/item/weapon/storage/box/syndie_kit/combat_armor /datum/uplink_item/item/armor/heavy_vest name = "Heavy Armor Vest" - item_cost = 40 + item_cost = 20 path = /obj/item/clothing/suit/storage/vest/heavy/merc /datum/uplink_item/item/armor/gorlexsuit name = "Mercenary Voidsuit" - item_cost = 40 + item_cost = 20 path = /obj/item/weapon/storage/box/syndie_kit/voidsuit /datum/uplink_item/item/armor/gorlexsuit_fire name = "Mercenary Voidsuit (Fire)" - item_cost = 40 + item_cost = 20 path = /obj/item/weapon/storage/box/syndie_kit/voidsuit/fire /datum/uplink_item/item/armor/combat name = "Combat Platecarrier Set" - item_cost = 60 + item_cost = 30 path = /obj/item/clothing/suit/armor/pcarrier/merc diff --git a/code/datums/uplink/medical.dm b/code/datums/uplink/medical.dm index c7b0b0d123..c1ff848877 100644 --- a/code/datums/uplink/medical.dm +++ b/code/datums/uplink/medical.dm @@ -6,88 +6,108 @@ /datum/uplink_item/item/medical/onegativeblood name = "O- Blood Pack" - item_cost = 5 + item_cost = 1 path = /obj/item/weapon/reagent_containers/blood/OMinus /datum/uplink_item/item/medical/sinpockets name = "Box of Sin-Pockets" - item_cost = 5 + item_cost = 1 path = /obj/item/weapon/storage/box/sinpockets /datum/uplink_item/item/medical/ambrosiaseeds name = "Box of 7x ambrosia seed packets" - item_cost = 5 + item_cost = 1 path = /obj/item/weapon/storage/box/ambrosia /datum/uplink_item/item/medical/clotting name = "Clotting Medicine injector" - item_cost = 10 + item_cost = 5 path = /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting /datum/uplink_item/item/medical/clotting_case name = "Clotting Medicine case" - item_cost = 20 + item_cost = 10 desc = "A case of three myelamine injectors. Can rapidly remove and stow up to six injectors." path = /obj/item/weapon/storage/quickdraw/syringe_case/clotting /datum/uplink_item/item/medical/bonemeds name = "Bone Repair injector" - item_cost = 10 + item_cost = 5 path = /obj/item/weapon/reagent_containers/hypospray/autoinjector/bonemed /datum/uplink_item/item/medical/clonemeds name = "Clone injector" - item_cost = 15 + item_cost = 5 path = /obj/item/weapon/reagent_containers/hypospray/autoinjector/clonemed /datum/uplink_item/item/medical/bonemeds_case name = "Bone Repair case" - item_cost = 20 + item_cost = 10 desc = "A case of three osteodaxon injectors. Can rapidly remove and stow up to six injectors." path = /obj/item/weapon/storage/quickdraw/syringe_case/bonemed /datum/uplink_item/item/medical/clonemeds_case name = "Clone case" - item_cost = 30 + item_cost = 10 desc = "A case of three rezadone injectors. Can rapidly remove and stow up to six injectors." path = /obj/item/weapon/storage/quickdraw/syringe_case/clonemed /datum/uplink_item/item/medical/ambrosiadeusseeds name = "Box of 7x ambrosia deus seed packets" - item_cost = 10 + item_cost = 5 path = /obj/item/weapon/storage/box/ambrosiadeus /datum/uplink_item/item/medical/freezer name = "Portable Freezer" - item_cost = 10 + item_cost = 1 path = /obj/item/weapon/storage/box/freezer /datum/uplink_item/item/medical/monkeycubes name = "Box, Monkey Cubes" - item_cost = 10 + item_cost = 1 path = /obj/item/weapon/storage/box/monkeycubes /datum/uplink_item/item/medical/farwacubes name = "Box, Farwa Cubes" - item_cost = 10 + item_cost = 1 path = /obj/item/weapon/storage/box/monkeycubes /datum/uplink_item/item/medical/neaeracubes name = "Box, Neaera Cubes" - item_cost = 10 + item_cost = 1 path = /obj/item/weapon/storage/box/monkeycubes/neaeracubes /datum/uplink_item/item/medical/stokcubes name = "Box, Stok Cubes" - item_cost = 10 + item_cost = 1 path = /obj/item/weapon/storage/box/monkeycubes/stokcubes /datum/uplink_item/item/medical/surgery name = "Surgery kit" - item_cost = 45 + item_cost = 5 path = /obj/item/weapon/storage/firstaid/surgery +/datum/uplink_item/item/medical/toxins + name = "Anti-toxins medical kit" + item_cost = 5 + path = /obj/item/weapon/storage/firstaid/toxin + +/datum/uplink_item/item/medical/o2 + name = "oxygen deprivation medical kit" + item_cost = 5 + path = /obj/item/weapon/storage/firstaid/o2 + +/datum/uplink_item/item/medical/fire + name = "fire medical kit" + item_cost = 5 + path = /obj/item/weapon/storage/firstaid/fire + +/datum/uplink_item/item/medical/adv + name = "advanced medical kit" + item_cost = 10 + path = /obj/item/weapon/storage/firstaid/adv + /datum/uplink_item/item/medical/combat name = "Combat medical kit" - item_cost = 60 + item_cost = 20 path = /obj/item/weapon/storage/firstaid/combat diff --git a/code/datums/uplink/visible_weapons.dm b/code/datums/uplink/visible_weapons.dm index b939e953de..f8526c022a 100644 --- a/code/datums/uplink/visible_weapons.dm +++ b/code/datums/uplink/visible_weapons.dm @@ -139,6 +139,11 @@ item_cost = 75 path = /obj/item/weapon/gun/projectile/shotgun/pump/combat +/datum/uplink_item/item/visible_weapons/semishotgun + name = "Semi-Automatic Shotgun" + item_cost = 100 + path = /obj/item/weapon/gun/projectile/shotgun/semi + /datum/uplink_item/item/visible_weapons/leveraction name = "Lever Action Rifle" item_cost = 50 diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 31d1d07f2b..e8f9e2fe13 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -465,7 +465,7 @@ var/list/mob/living/forced_ambiance_list = new /area/proc/prison_break(break_lights = TRUE, open_doors = TRUE, open_blast_doors = FALSE) //CHOMP Edit set blast doors to FALSE var/obj/machinery/power/apc/theAPC = get_apc() - if(theAPC.operating) + if(theAPC && theAPC.operating) if(break_lights) for(var/obj/machinery/power/apc/temp_apc in src) temp_apc.overload_lighting(70) diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index 5a414430ea..570fbf32ab 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -393,7 +393,7 @@ var/global/datum/controller/occupations/job_master //Equip custom gear loadout. var/list/custom_equip_slots = list() var/list/custom_equip_leftovers = list() - if(H.client.prefs.gear && H.client.prefs.gear.len && !(job.mob_type & JOB_SILICON)) + if(H.client && H.client.prefs && H.client.prefs.gear && H.client.prefs.gear.len && !(job.mob_type & JOB_SILICON)) for(var/thing in H.client.prefs.gear) var/datum/gear/G = gear_datums[thing] if(!G) //Not a real gear datum (maybe removed, as this is loaded from their savefile) diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm index 35a060863e..0226d0bc66 100644 --- a/code/game/machinery/cryo.dm +++ b/code/game/machinery/cryo.dm @@ -189,7 +189,7 @@ var/mob/M = grab.affecting qdel(grab) put_mob(M) - + return /obj/machinery/atmospherics/unary/cryo_cell/MouseDrop_T(var/mob/target, var/mob/user) //Allows borgs to put people into cryo without external assistance @@ -226,6 +226,9 @@ if(occupant.bodytemperature < 225) if(occupant.getToxLoss()) occupant.adjustToxLoss(max(-1, -20/occupant.getToxLoss())) + if(occupant.radiation || occupant.accumulated_rads) + occupant.radiation -= 25 + occupant.accumulated_rads -= 25 var/heal_brute = occupant.getBruteLoss() ? min(1, 20/occupant.getBruteLoss()) : 0 var/heal_fire = occupant.getFireLoss() ? min(1, 20/occupant.getFireLoss()) : 0 occupant.heal_organ_damage(heal_brute,heal_fire) diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 38ac815cff..3b8d179cfa 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -475,8 +475,8 @@ //Handle job slot/tater cleanup. var/job = to_despawn.mind.assigned_role - job_master.FreeRole(job) + to_despawn.mind.assigned_role = null if(to_despawn.mind.objectives.len) qdel(to_despawn.mind.objectives) diff --git a/code/game/machinery/door_control.dm b/code/game/machinery/door_control.dm index 6e5618d39e..6a66f568cd 100644 --- a/code/game/machinery/door_control.dm +++ b/code/game/machinery/door_control.dm @@ -149,6 +149,41 @@ M.close() return +//CHOMP Add start +/obj/machinery/button/remote/blast_door/bear + name = "stuffed bear" + icon = 'icons/obj/stationobjs_vr.dmi' + icon_state = "stuffedbear" + desc = "A stuffed and mounted bear. Quite a statement piece, but holds a curious glare." + density = 1 + +/obj/machinery/button/remote/blast_door/bear/attack_hand(mob/user as mob) //code to stop bear ever reverting to standard button sprites + if(..()) + return + + add_fingerprint(user) + if(stat & (NOPOWER|BROKEN)) + return + + if(!allowed(user) && (wires & 1)) + to_chat(user, "Access Denied") + flick("doorctrl-denied",src) + return + + use_power(5) + icon_state = "stuffedbear" + desiredstate = !desiredstate + trigger(user) + spawn(15) + update_icon() + +/obj/machinery/button/remote/blast_door/bear/update_icon() + if(stat & NOPOWER) + icon_state = "stuffedbear" + else + icon_state = "stuffedbear" +//CHOMP Add end + /* Emitter remote control */ diff --git a/code/game/machinery/doors/blast_door.dm b/code/game/machinery/doors/blast_door.dm index cc8227147c..9c6950bfbe 100644 --- a/code/game/machinery/doors/blast_door.dm +++ b/code/game/machinery/doors/blast_door.dm @@ -319,6 +319,15 @@ density = FALSE opacity = 0 +/obj/machinery/door/blast/regular/bookcase //CHOMP Add code block + name = "bookcase" + desc = "On closer inspection, the array of books is decorative and built into the frame." + icon_state = "bookcase1" + icon_state_open = "bookcase0" + icon_state_opening = "bookcasec0" + icon_state_closed = "bookcase1" + icon_state_closing = "bookcasec1" + // SUBTYPE: Shutters // Nicer looking, and also weaker, shutters. Found in kitchen and similar areas. /obj/machinery/door/blast/shutters @@ -456,4 +465,4 @@ #undef BLAST_DOOR_CRUSH_DAMAGE -#undef SHUTTER_CRUSH_DAMAGE \ No newline at end of file +#undef SHUTTER_CRUSH_DAMAGE diff --git a/code/game/machinery/frame.dm b/code/game/machinery/frame.dm index d651ad2025..6c71e63207 100644 --- a/code/game/machinery/frame.dm +++ b/code/game/machinery/frame.dm @@ -81,31 +81,6 @@ frame_class = FRAME_CLASS_MACHINE frame_size = 4 -/datum/frame/frame_types/oven - name = "Oven" - frame_class = FRAME_CLASS_MACHINE - frame_size = 4 - -/datum/frame/frame_types/fryer - name = "Fryer" - frame_class = FRAME_CLASS_MACHINE - frame_size = 4 - -/datum/frame/frame_types/grill - name = "Grill" - frame_class = FRAME_CLASS_MACHINE - frame_size = 4 - -/datum/frame/frame_types/cerealmaker - name = "Cereal Maker" - frame_class = FRAME_CLASS_MACHINE - frame_size = 4 - -/datum/frame/frame_types/candymachine - name = "Candy Machine" - frame_class = FRAME_CLASS_MACHINE - frame_size = 4 - /datum/frame/frame_types/fax name = "Fax" frame_class = FRAME_CLASS_MACHINE @@ -221,7 +196,7 @@ frame_style = FRAME_STYLE_WALL x_offset = 28 y_offset = 28 - + /datum/frame/frame_types/arfgs name = "ARF Generator" frame_class = FRAME_CLASS_MACHINE diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm index 115e5e710a..9781ad98a0 100644 --- a/code/game/machinery/recharger.dm +++ b/code/game/machinery/recharger.dm @@ -10,7 +10,7 @@ active_power_usage = 40000 //40 kW var/efficiency = 40000 //will provide the modified power rate when upgraded var/obj/item/charging = null - var/list/allowed_devices = list(/obj/item/weapon/gun/energy, /obj/item/weapon/melee/baton, /obj/item/modular_computer, /obj/item/weapon/computer_hardware/battery_module, /obj/item/weapon/cell, /obj/item/device/suit_cooling_unit/emergency, /obj/item/device/flashlight, /obj/item/device/electronic_assembly, /obj/item/weapon/weldingtool/electric, /obj/item/ammo_magazine/smart, /obj/item/device/flash, /obj/item/device/defib_kit, /obj/item/ammo_casing/microbattery, /obj/item/device/paicard, /obj/item/ammo_magazine/cell_mag, /obj/item/weapon/gun/projectile/cell_loaded) // CHOMPedit: medigun stuff + var/list/allowed_devices = list(/obj/item/weapon/gun/energy, /obj/item/weapon/melee/baton, /obj/item/modular_computer, /obj/item/weapon/computer_hardware/battery_module, /obj/item/weapon/cell, /obj/item/device/suit_cooling_unit/emergency, /obj/item/device/flashlight, /obj/item/device/electronic_assembly, /obj/item/weapon/weldingtool/electric, /obj/item/ammo_magazine/smart, /obj/item/device/flash, /obj/item/device/defib_kit, /obj/item/ammo_casing/microbattery, /obj/item/device/paicard, /obj/item/ammo_magazine/cell_mag, /obj/item/weapon/gun/projectile/cell_loaded, /obj/item/device/personal_shield_generator) // CHOMPedit: medigun stuff var/icon_state_charged = "recharger2" var/icon_state_charging = "recharger1" var/icon_state_idle = "recharger0" //also when unpowered @@ -28,7 +28,8 @@ . += "[charging ? "[charging]" : "Nothing"] is in [src]." if(charging) var/obj/item/weapon/cell/C = charging.get_cell() - . += "Current charge: [C.charge] / [C.maxcharge]" + if(C) // Sometimes we get things without cells in it. + . += "Current charge: [C.charge] / [C.maxcharge]" /obj/machinery/recharger/attackby(obj/item/weapon/G as obj, mob/user as mob) var/allowed = 0 diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm index d2adbad8da..44459d1b96 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -100,12 +100,13 @@ // Also recharge their internal battery. if(H.isSynthetic() && H.nutrition < 500) //VOREStation Edit - H.nutrition = min(H.nutrition+10, 500) //VOREStation Edit + H.nutrition = min(H.nutrition+(10*(1-H.species.synthetic_food_coeff)), 500) //VOREStation Edit cell.use(7000/450*10) // And clear up radiation - if(H.radiation > 0) - H.radiation = max(H.radiation - rand(5, 15), 0) + if(H.radiation > 0 || H.accumulated_rads > 0) + H.radiation = max(H.radiation - 25, 0) + H.accumulated_rads = max(H.accumulated_rads - 25, 0) if(H.wearing_rig) // stepping into a borg charger to charge your rig and fix your shit var/obj/item/weapon/rig/wornrig = H.get_rig() diff --git a/code/game/objects/banners.dm b/code/game/objects/banners.dm index 0e4aaef6d8..d491e41119 100644 --- a/code/game/objects/banners.dm +++ b/code/game/objects/banners.dm @@ -31,6 +31,12 @@ desc = "A banner with the symbol of the Solar Confederate Government." catalogue_data = list(/datum/category_item/catalogue/information/organization/solgov) +/obj/item/weapon/banner/altevian + name = "\improper Altevian Hegemony Banner" + icon_state = "banner-altevian" + desc = "A banner that flies for the pride of the hegemony." + //catalogue_data = list(/datum/category_item/catalogue/information/organization/altevian_hegemony) // TODO? + //VOREStation Removal //CHOMP re-addition. Seriously? You commented this out for your lore? What's wrong with JUST NOT SPAWNING IT or something. /obj/item/weapon/banner/virgov name = "\improper VirGov banner" diff --git a/code/game/objects/effects/spawners/graffiti.dm b/code/game/objects/effects/spawners/graffiti.dm index afac11f4f1..9450c90206 100644 --- a/code/game/objects/effects/spawners/graffiti.dm +++ b/code/game/objects/effects/spawners/graffiti.dm @@ -25,4 +25,4 @@ C.name = name - qdel(src) + return INITIALIZE_HINT_QDEL diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm index eb2aefeb5c..c22ddaa46f 100644 --- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm +++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm @@ -24,6 +24,18 @@ icon_state = "smoke" duration = 50 +/obj/effect/temp_visual/glitch + icon_state = "glitch" + duration = 5 + +/obj/effect/temp_visual/confuse + icon_state = "confuse" + duration = 5 + +/obj/effect/temp_visual/pre_confuse + icon_state = "pre_confuse" + duration = 5 + /obj/effect/temp_visual/impact_effect icon_state = "impact_bullet" plane = PLANE_LIGHTING_ABOVE // So they're visible even in a shootout in maint. diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 2ed58f88ee..645168b041 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -106,7 +106,7 @@ var/drop_sound = "generic_drop" var/tip_timer // reference to timer id for a tooltip we might open soon - + var/no_random_knockdown = FALSE //stops item from being able to randomly knock people down in combat /obj/item/Initialize(mapload) //CHOMPedit I stg I'm going to overwrite these many uncommented edits. @@ -222,9 +222,12 @@ /obj/item/attack_hand(mob/living/user as mob) if (!user) return - if(anchored) - to_chat(user, span("notice", "\The [src] won't budge, you can't pick it up!")) - return + if(anchored) // Start CHOMPStation Edit + if(hascall(src, "attack_self")) + return src.attack_self(user) + else + to_chat ("This is anchored and you can't lift it.") + return // End CHOMPStation Edit if (hasorgans(user)) var/mob/living/carbon/human/H = user var/obj/item/organ/external/temp = H.organs_by_name["r_hand"] diff --git a/code/game/objects/items/devices/personal_shield_generator_vr.dm b/code/game/objects/items/devices/personal_shield_generator_vr.dm new file mode 100644 index 0000000000..d6b63c4c41 --- /dev/null +++ b/code/game/objects/items/devices/personal_shield_generator_vr.dm @@ -0,0 +1,601 @@ +// TO ANYBODY LOOKING AT THIS FILE: +// Everything is mostly commented on to give as much detailed information as possible. +// Some things may be difficult to understand, but every variable in here has a comment explaining what it is/does. +// The base unit, the 'personal_shield_generator' is a backpack, comes with a gun, and has normal numbers for everything. +// The belt units do NOT come with a gun and have a cell that is half the capacity of backpack units. +// These can be VERY, VERY, VERY strong if too many are handed out, the cell is too strong, or the modifier is too strong. +// Additionally, if you are mapping any of these in, ensure you map in the /loaded versions or else they won't have a battery. +// I have also made it so you can modify everything about them, including the modifier they give and the cell, which can be changed via mapping. + +// In essence, these can be viewed as an extra layer of armor that has upsides and downsides with more extensive features. +// Shield generators apply PRE armor. Ultimately this shouldn't matter too much, but it makes more sense this way. +// There are a good amount of variants in here, ranging from mining to security to misc ones. +// If you want to make a variant, you need to only change modifier_type and make the modifier desired. + + +/obj/item/device/personal_shield_generator + name = "personal shield generator" + desc = "A personal shield generator." + icon = 'icons/obj/items_vr.dmi' + icon_state = "shieldpack_basic" + item_state = "defibunit" //Placeholder + slot_flags = SLOT_BACK + force = 5 + throwforce = 6 + preserve_item = 1 + w_class = ITEMSIZE_HUGE //It's a giant shield generator!!! + unacidable = TRUE + origin_tech = list(TECH_MATERIAL = 6, TECH_COMBAT = 8, TECH_POWER = 6, TECH_DATA = 4) //These are limited AND high tech. Breaking one of them down is massive. + action_button_name = "Toggle Shield" + var/obj/item/weapon/gun/energy/gun/generator/active_weapon + var/obj/item/weapon/cell/device/bcell = null + + + var/generator_hit_cost = 100 // Power used when a special effect (such as a bullet being blocked) is performed! Could also be expanded to other things. + var/generator_active_cost = 10 // Power used when turned on. + var/damage_cost = 25 // 40 damage absorbed per 1000 charge. + var/modifier_type = /datum/modifier/shield_projection // What type of modifier will it add? Used for variant modifiers! + + var/has_weapon = 1 // Backpack units generally have weapons. + var/shield_active = 0 // If the shield gen is active. + var/effect_color = "#99FFFF" // Allows for changing shield colors. Default cyan. + +/obj/item/device/personal_shield_generator/get_cell() + return bcell + +/obj/item/device/personal_shield_generator/New() + ..() + if(ispath(bcell)) + bcell = new bcell(src) + + if(has_weapon) + if(ispath(active_weapon)) + active_weapon = new active_weapon(src, src) + active_weapon.power_supply = bcell + else + active_weapon = new(src, src) + active_weapon.power_supply = bcell + else + verbs -= /obj/item/device/personal_shield_generator/verb/weapon_toggle + STOP_PROCESSING(SSobj, src) //We do this so it doesn't start processing until it's first used. + update_icon() + +/obj/item/device/personal_shield_generator/Destroy() + . = ..() + QDEL_NULL(active_weapon) + QDEL_NULL(bcell) + +/obj/item/device/personal_shield_generator/loaded //starts with a cell + bcell = /obj/item/weapon/cell/device/shield_generator/backpack + + +/obj/item/device/personal_shield_generator/update_icon() + if(shield_active) + icon_state = "shieldpack_basic_on" + else + icon_state = "shieldpack_basic" + +/obj/item/device/personal_shield_generator/examine(mob/user) + . = ..() + if(Adjacent(user)) + if(bcell) + . += "The internal cell is [round(bcell.percent() )]% charged." + else + . += "The device has no cell installed." + return + if(damage_cost) //Prevention of dividing by 0 errors. + . += "It reads that it can take [bcell.charge/damage_cost] more damage before the shield goes down." + if(bcell.self_recharge && bcell.charge_amount) + . += "This model is self charging and will take [bcell.maxcharge/bcell.charge_amount] seconds to fully charge from empty." + if(bcell.rigged) + . += "A red flashing 'WARNING' is visible on the display, noting that the cell is unstable and requires replacement." + + +/* //This would be cool, but we need sprites. + cut_overlays() + + if(has_weapon && active_weapon && active_weapon.loc == src) //in case gun gets destroyed somehow. + add_overlay("[initial(icon_state)]-paddles") + if(bcell) + if(bcell.check_charge(generator_hit_cost)) //Can we take a blow? + add_overlay("[initial(icon_state)]-powered") + else if(has_weapon && active_weapon) + if(bcell.check_charge(active_weapon.charge_cost)) //We got enough to go pew pew? + add_overlay("[initial(icon_state)]-powered") + + var/ratio = CEILING(bcell.percent()/25, 1) * 25 + add_overlay("[initial(icon_state)]-charge[ratio]") + else + add_overlay("[initial(icon_state)]-nocell") +*/ + +/obj/item/device/personal_shield_generator/emp_act(severity) + if(bcell && shield_active) + switch(severity) + if(1) //Point blank EMP shots have a good chance of burning the cell charge. + if(prob(50)) + bcell.emp_act(severity) + if(prob(5)) //1 in 20% chance to fry the battery completly, which has a 1/10 chance of making the battery explode on next use. + bcell.corrupt() //Not too bad if you slotted a battery in. Disasterous if it has a self-charging battery. + if(bcell.rigged) //Did the above just rig the cell? Turn it off. Don't immediately have it go boom. Instead have the cell blow soon-ish. + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(5, 1, src) + s.start() + shield_active = 0 + if(bcell.charge_delay) //It WILL blow up soon. Downside of self-charging cells. + to_chat(src.loc, "Your shield generator sparks and suddenly goes down! A warning message pops up on screen: \ + 'WARNING, INTERNAL CELL MELTDOWN IMMINENT. TIME TILL EXPLOSION: [bcell.charge_delay/10] SECONDS. DISCARD UNIT IMMEDIATELY!'") + else //It won't blow up unless you turn it back on again. Upside of using non-charging cells. + to_chat(src.loc, "Your shield generator sparks and suddenly goes down! A warning message pops up on screen: \ + 'WARNING, INTERNAL CELL CRITICALLY DAMAGED. REPLACE CELL IMMEDIATELY.'") + STOP_PROCESSING(SSobj, src) + update_icon() + else + if(prob(25)) + bcell.emp_act(severity) + ..() + +/obj/item/device/personal_shield_generator/ui_action_click() + toggle_shield() + +/obj/item/device/personal_shield_generator/attack_hand(mob/user) + if(loc == user) + toggle_shield() + else + ..() + +/obj/item/device/personal_shield_generator/AltClick(mob/living/user) + weapon_toggle() + +/obj/item/device/personal_shield_generator/MouseDrop() + if(ismob(src.loc)) + if(!CanMouseDrop(src)) + return + var/mob/M = src.loc + if(!M.unEquip(src)) + return + src.add_fingerprint(usr) + M.put_in_any_hand_if_possible(src) + + +/obj/item/device/personal_shield_generator/attackby(obj/item/weapon/W, mob/user, params) + if(W == active_weapon) + reattach_gun(user) + else if(istype(W, /obj/item/weapon/cell)) + if(bcell) + to_chat(user, "\The [src] already has a cell.") + else if(!istype(W, /obj/item/weapon/cell/device/weapon)) //Weapon cells only! + to_chat(user, "This cell will not fit in the device.") + else + if(!user.unEquip(W)) + return + W.forceMove(src) + bcell = W + if(active_weapon) + active_weapon.power_supply = bcell + to_chat(user, "You install a cell in \the [src].") + update_icon() + + else if(W.is_screwdriver()) + if(bcell) + if(istype(bcell, /obj/item/weapon/cell/device/shield_generator)) //No stealing self charging batteries! + var/choice = tgui_alert(user, "A popup appears on the device 'REMOVING THE INTERNAL CELL WILL DESTROY THE BATTERY. DO YOU WISH TO CONTINUE?'...Well, do you?", "Selection List", list("Cancel", "Remove")) + if(choice == "Remove") //Warned you... + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(5, 1, src) + s.start() + bcell.forceMove(get_turf(src.loc)) + qdel(bcell) + bcell = null //Sanity. + if(active_weapon) + reattach_gun() //Put the gun back if it's out. No shooting if we don't have a cell! + active_weapon.power_supply = null //No power cell anymore! + to_chat(user, "You remove the cell from \the [src], destroying the battery.") + update_icon() + return + else + return + else + bcell.update_icon() + bcell.forceMove(get_turf(src.loc)) + bcell = null + if(active_weapon) + reattach_gun() //Put the gun back if it's out. No shooting if we don't have a cell! + active_weapon.power_supply = null //No power cell anymore! + to_chat(user, "You remove the cell from \the [src].") + update_icon() + else if(istype(W,/obj/item/device/multitool)) + var/new_color = input(usr, "Choose a color to set the shield to!", "", effect_color) as color|null + if(new_color) + effect_color = new_color + else + return ..() + +// TODO: EMAG ACT +// Perhaps make it so emagging the generator gives two options: One to rig the cell (stealthily) and one to disable the safeties (supercharge it) +// Disabling the safeties would make it a stronger variant but boost the 'damage_cost' perhaps. Dunno. +// We're an RP server so emags don't come into play except for random trash finds. Meaning it'd be RNG if you could 'supercharge' your shield genrator. +// This would kind of be like people being able to emag the NIFSoft for bloodletters & all the buffs that come with an emagged NIFSoft. +// Making it so emagging the weapon it comes with would also be a good idea. Different modes, perhaps? + +/* +/obj/item/device/personal_shield_generator/emag_act(var/remaining_charges, var/mob/user) + if(active_weapon) + . = active_weapon.emag_act(user) + update_icon() + return +*/ + +//Gun stuff + + +/obj/item/device/personal_shield_generator/verb/toggle_shield() + set name = "Toggle Shield" + set category = "Object" + + var/mob/living/carbon/human/user = usr + + if(user.last_special > world.time) + return + user.last_special = world.time + 10 //No spamming! + + if(!bcell || !bcell.check_charge(generator_hit_cost) || !bcell.check_charge(generator_active_cost)) + to_chat(user, "You require a charged cell to do this!") + return + + if(!slot_check()) + to_chat(user, "You need to equip [src] before starting the shield up!") + return + else + if(shield_active) + shield_active = !shield_active //Deactivate the shield! + to_chat(user, "You deactive the shield!") + user.remove_modifiers_of_type(/datum/modifier/shield_projection) + STOP_PROCESSING(SSobj, src) + playsound(src, 'sound/weapons/saberoff.ogg', 50, 1) //Shield turning off! PLACEHOLDER + else + shield_active = !shield_active + to_chat(user, "You activate the shield!") + user.remove_modifiers_of_type(/datum/modifier/shield_projection) //Just to make sure they aren't using two at once! + user.add_modifier(modifier_type) + user.update_modifier_visuals() //Forces coloration to WORK. + START_PROCESSING(SSobj, src) //Let's only bother draining power when we're being used! + playsound(src, 'sound/weapons/saberon.ogg', 50, 1) //Shield turning off! PLACEHOLDER + update_icon() + +/obj/item/device/personal_shield_generator/verb/weapon_toggle() //Make this work on Alt-Click + set name = "Toggle Gun" + set category = "Object" + + var/mob/living/carbon/human/user = usr + + if(user.last_special > world.time) + return + user.last_special = world.time + 10 //No spamming! + + if(!active_weapon) + to_chat(user, "The gun is missing!") + return + + if(!bcell) + to_chat(user, "The gun requires a power supply!") + return + + if(active_weapon.loc != src) + reattach_gun(user) //Remove from their hands and back onto the defib unit + return + + if(!slot_check()) + to_chat(user, "You need to equip [src] before taking out [active_weapon].") + else + if(!usr.put_in_hands(active_weapon)) //Detach the gun into the user's hands + to_chat(user, "You need a free hand to hold the gun!") + update_icon() //success + +/obj/item/device/personal_shield_generator/process() + if(!bcell) //They removed the battery midway. + if(istype(loc, /mob/living/carbon/human)) //We on someone? Tell them it turned off. + var/mob/living/carbon/human/user = loc + to_chat(user, "The shield deactivates! An error message pops up on screen: 'Cell missing. Cell replacement required.'") + user.remove_modifiers_of_type(/datum/modifier/shield_projection) + shield_active = 0 + STOP_PROCESSING(SSobj, src) + update_icon() + playsound(src, 'sound/weapons/saberoff.ogg', 50, 1) //Shield turning off! PLACEHOLDER + return + + if(shield_active) + if(bcell.rigged) //They turned it back on after it was rigged to go boom. + if(istype(loc, /mob/living/carbon/human)) //Deactivate the shield, first. You're not getting reduced damage... + var/mob/living/carbon/human/user = loc + to_chat(user, "The shield deactivates, an error message popping up on screen: 'Cell Reactor Critically damaged. Cell replacement required.'") + user.remove_modifiers_of_type(/datum/modifier/shield_projection) + + if(active_weapon) //Retract the gun. There's about to be no cell anymore. + reattach_gun() + active_weapon.power_supply = null + + bcell.use(generator_active_cost) //Causes it to go boom. + bcell = null + shield_active = 0 + STOP_PROCESSING(SSobj, src) + update_icon() + return + + else //Normal operation. + bcell.use(generator_active_cost) + + if(bcell.charge < generator_hit_cost || bcell.charge < generator_active_cost) //Out of charge... + shield_active = 0 + if(istype(loc, /mob/living/carbon/human)) //We on someone? Tell them it turned off. + var/mob/living/carbon/human/user = loc + to_chat(user, "The shield deactivates, an error message popping up on screen: 'Cell out of charge.'") + user.remove_modifiers_of_type(/datum/modifier/shield_projection) + STOP_PROCESSING(SSobj, src) + update_icon() + playsound(src, 'sound/weapons/saberoff.ogg', 50, 1) //Shield turning off! PLACEHOLDER + return + + + +//checks that the base unit is in the correct slot to be used +/obj/item/device/personal_shield_generator/proc/slot_check() + var/mob/M = loc + if(!istype(M)) + return 0 //not equipped + + if((slot_flags & SLOT_BACK) && M.get_equipped_item(slot_back) == src) + return 1 + if((slot_flags & SLOT_BELT) && M.get_equipped_item(slot_belt) == src) + return 1 + //RIGSuit compatability. This shouldn't be possible, however, except for select RIGs. + if((slot_flags & SLOT_BACK) && M.get_equipped_item(slot_s_store) == src) + return 1 + if((slot_flags & SLOT_BELT) && M.get_equipped_item(slot_s_store) == src) + return 1 + + return 0 + +/obj/item/device/personal_shield_generator/dropped(mob/user) + ..() + reattach_gun(user) //A gun attached to a base unit should never exist outside of their base unit or the mob equipping the base unit + +/obj/item/device/personal_shield_generator/proc/reattach_gun(mob/user) + if(!active_weapon) return + + if(ismob(active_weapon.loc)) + var/mob/M = active_weapon.loc + if(M.drop_from_inventory(active_weapon, src)) + to_chat(user, "\The [active_weapon] snaps back into the main unit.") + else + active_weapon.forceMove(src) + + update_icon() + +//The gun + +/obj/item/weapon/gun/energy/gun/generator //The gun attached to the personal shield generator. + name = "generator gun" + desc = "A gun that is attached to the battery of the personal shield generator." + icon_state = "egunstun" + item_state = null //so the human update icon uses the icon_state instead. + fire_delay = 8 + use_external_power = TRUE + cell_type = null //No cell! It runs off the cell in the shield_gen! + + projectile_type = /obj/item/projectile/beam/stun/med + modifystate = "egunstun" + + firemodes = list( + list(mode_name="stun", projectile_type=/obj/item/projectile/beam/stun/med, modifystate="egunstun", fire_sound='sound/weapons/Taser.ogg', charge_cost = 240), + list(mode_name="lethal", projectile_type=/obj/item/projectile/beam, modifystate="egunkill", fire_sound='sound/weapons/Laser.ogg', charge_cost = 480), + ) + + var/obj/item/device/personal_shield_generator/shield_generator //The generator we are linked to! + var/wielded = 0 + var/cooldown = 0 + var/busy = 0 + +/obj/item/weapon/gun/energy/gun/generator/New(newloc, obj/item/device/personal_shield_generator/shield_gen) + ..(newloc) + shield_generator = shield_gen + power_supply = shield_generator.bcell + +/* //Unused. Use for large guns. +/obj/item/weapon/gun/energy/gun/generator/update_held_icon() + var/mob/living/M = loc + if(istype(M) && M.item_is_in_hands(src) && !M.hands_are_full()) + wielded = 1 + name = "[initial(name)] (wielded)" + else + wielded = 0 + name = initial(name) + update_icon() + ..() +*/ + +/obj/item/weapon/gun/energy/gun/generator/proc/can_use(mob/user, mob/M) + if(busy) + return 0 + if(!check_charge(charge_cost)) + to_chat(user, "\The [src] doesn't have enough charge left to do that.") + return 0 + if(!wielded && !isrobot(user)) + to_chat(user, "You need to wield the gun with both hands before you can use it on someone!") + return 0 + if(cooldown) + to_chat(user, "\The [src] are re-energizing!") + return 0 + return 1 + +// TODO: EMP ACT +// The cell already gets hit and can have some nasty effects when EMP'd, so this isn't too much of a concern. + +/* +/obj/item/weapon/gun/energy/gun/generator/emp_act(severity) + ..() +*/ + +/obj/item/weapon/gun/energy/gun/generator/dropped(mob/user) + ..() //update twohanding + if(shield_generator) + shield_generator.reattach_gun(user) + +/obj/item/weapon/gun/energy/proc/check_charge(var/charge_amt) //In case using any other guns. + return 0 + +/obj/item/weapon/gun/energy/proc/checked_use(var/charge_amt) //In case using any other guns. + return 0 + +/obj/item/weapon/gun/energy/gun/generator/check_charge(var/charge_amt) + return (shield_generator.bcell && shield_generator.bcell.check_charge(charge_amt)) + +/obj/item/weapon/gun/energy/gun/generator/checked_use(var/charge_amt) + return (shield_generator.bcell && shield_generator.bcell.checked_use(charge_amt)) + + + +//VARIANTS. + +/obj/item/device/personal_shield_generator/belt + name = "personal shield generator" + desc = "A personal shield generator." + icon_state = "shieldpack_basic" + item_state = "defibunit" + w_class = ITEMSIZE_LARGE //No putting these in backpacks! + slot_flags = SLOT_BELT + has_weapon = 0 //No gun with the belt! + +/obj/item/device/personal_shield_generator/belt/loaded + bcell = /obj/item/weapon/cell/device/shield_generator + +/obj/item/device/personal_shield_generator/belt/update_icon() + if(shield_active) + icon_state = "shieldpack_basic_on" + else + icon_state = "shieldpack_basic" + +/obj/item/device/personal_shield_generator/belt/bruteburn //Example of a modified generator. + modifier_type = /datum/modifier/shield_projection/bruteburn +/obj/item/device/personal_shield_generator/belt/bruteburn/loaded //If mapped in, ONLY put loaded ones down. + bcell = /obj/item/weapon/cell/device/shield_generator + +// Mining belts +/obj/item/device/personal_shield_generator/belt/mining + name = "mining PSG" + desc = "A personal shield generator designed for mining. It has a warning on the back: 'Do NOT expose the shield to stun-based weaponry.'" + modifier_type = /datum/modifier/shield_projection/mining + +/obj/item/device/personal_shield_generator/belt/mining/loaded + bcell = /obj/item/weapon/cell/device/shield_generator + +/obj/item/device/personal_shield_generator/belt/mining/update_icon() + if(shield_active) + icon_state = "shieldpack_mining_on" + else + icon_state = "shieldpack_mining" + +/obj/item/borg/upgrade/shield_upgrade + name = "mining PSG upgrade disk." + desc = "A upgrade disk that, when slotted into a mining shield generator, upgrades the efficiency of the internal software, providing a stronger shield \ + in exchange for being weaker to stun-based weaponry." + icon = 'icons/obj/objects_vr.dmi' + icon_state = "modkit" + w_class = ITEMSIZE_SMALL + +/obj/item/device/personal_shield_generator/belt/mining/attackby(obj/item/weapon/W, mob/user, params) + if(modifier_type == /datum/modifier/shield_projection/mining/strong) + to_chat(user, "This shield generator is already upgraded!") + return + if(istype(W, /obj/item/borg/upgrade/shield_upgrade)) + modifier_type = /datum/modifier/shield_projection/mining/strong + to_chat(user, "You upgrade the [src] with the [W]!") + user.drop_from_inventory(W) + qdel(W) + else + ..() + + +//Security belts + +/obj/item/device/personal_shield_generator/belt/security + name = "security PSG" + desc = "A personal shield generator designed for security." + modifier_type = /datum/modifier/shield_projection/security/weak + +/obj/item/device/personal_shield_generator/belt/security/loaded + bcell = /obj/item/weapon/cell/device/shield_generator + +/obj/item/device/personal_shield_generator/belt/security/update_icon() + if(shield_active) + icon_state = "shieldpack_security_on" + else + icon_state = "shieldpack_security" + +//Misc belts. Admin-spawn only atm. + +/obj/item/device/personal_shield_generator/belt/adminbus + desc = "You should not see this. You REALLY should not see this. If you do, you have either been blessed or are about to be the target of some sick prank." + modifier_type = /datum/modifier/shield_projection/admin + generator_hit_cost = 0 + generator_active_cost = 0 + shield_active = 0 + damage_cost = 0 + bcell = /obj/item/weapon/cell/device/shield_generator + +/obj/item/device/personal_shield_generator/belt/parry //The 'provides one second of pure immunity to brute/burn/halloss' belt. + name = "PSG variant-P" //Not meant to be used in any serious capacity. + desc = "A personal shield generator that sacrifices long-term usability in exchange for a strong, short-lived shield projection, enabling the user to be nigh \ + impervious for a second." + modifier_type = /datum/modifier/shield_projection/parry + generator_hit_cost = 0 //No cost for being hit. + damage_cost = 0//No cost for blocking effects. + generator_active_cost = 100 //However, it disables the tick immediately after being turned on. + shield_active = 0 + bcell = /obj/item/weapon/cell/device/shield_generator/parry + +// Backpacks. These are meant to be MUCH stronger in exchange for the fact that you are giving up a backpack slot. +// HOWEVER, be careful with these. They come loaded with a gun in them, so they shouldn't be handed out willy-nilly. + +/obj/item/device/personal_shield_generator/security + name = "security PSG" + desc = "A personal shield generator designed for security. Comes with a built in defense pistol." + modifier_type = /datum/modifier/shield_projection/security + +/obj/item/device/personal_shield_generator/security/loaded + bcell = /obj/item/weapon/cell/device/shield_generator/backpack + +/obj/item/device/personal_shield_generator/security/strong + modifier_type = /datum/modifier/shield_projection/security/strong + +/obj/item/device/personal_shield_generator/security/strong/loaded + bcell = /obj/item/weapon/cell/device/shield_generator/backpack + +/obj/item/device/personal_shield_generator/security/update_icon() + if(shield_active) + icon_state = "shieldpack_security_on" + else + icon_state = "shieldpack_security" + +//Power cells. +/obj/item/weapon/cell/device/shield_generator //The base power cell the shield gen comes with. + name = "shield generator battery" + desc = "A self charging battery which houses a micro-nuclear reactor. Takes a while to start charging." + maxcharge = 2400 + self_recharge = TRUE + charge_amount = 80 //After the charge_delay is over, charges the cell over 30 seconds. + charge_delay = 600 //Takes a minute before it starts to recharge. + +/obj/item/weapon/cell/device/shield_generator/backpack //The base power cell the backpack units come with. Double the charge vs the belt. + maxcharge = 4800 + charge_amount = 160 + +/obj/item/weapon/cell/device/shield_generator/upgraded //A stronger version of the normal cell. Double the maxcharge, halved charge time. + maxcharge = 4800 + charge_amount = 320 + charge_delay = 300 + +/obj/item/weapon/cell/device/shield_generator/parry //The cell for the 'parry' shield gen. + maxcharge = 100 + charge_amount = 100 + charge_delay = 20 //Starts charging two seconds after it's discharged. \ No newline at end of file diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index e8ba830cae..147b7327e8 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -322,7 +322,7 @@ GLOBAL_DATUM(autospeaker, /mob/living/silicon/ai/announcer) GLOB.autospeaker.SetName(from) Broadcast_Message(connection, GLOB.autospeaker, 0, "*garbled automated announcement*", src, - message_to_multilingual(message), from, "Automated Announcement", from, "synthesized voice", + message_to_multilingual(message, GLOB.all_languages[LANGUAGE_GALCOM]), from, "Automated Announcement", from, "synthesized voice", DATA_FAKE, 0, zlevels, connection.frequency, states) //VOREStation Edit // Interprets the message mode when talking into a radio, possibly returning a connection datum diff --git a/code/game/objects/items/devices/scanners/health.dm b/code/game/objects/items/devices/scanners/health.dm index ba1c960d9d..a747dc5f09 100644 --- a/code/game/objects/items/devices/scanners/health.dm +++ b/code/game/objects/items/devices/scanners/health.dm @@ -105,17 +105,40 @@ if(M.radiation) if(advscan >= 2 && showadvscan == 1) var/severity = "" - if(M.radiation >= 75) + if(M.radiation >= 1500) + severity = "Lethal" + else if(M.radiation >= 600) severity = "Critical" else if(M.radiation >= 50) + else if(M.radiation >= 400) severity = "Severe" else if(M.radiation >= 25) + else if(M.radiation >= 300) severity = "Moderate" else if(M.radiation >= 1) + else if(M.radiation >= 100) severity = "Low" dat += "[severity] levels of radiation detected. [(severity == "Critical") ? " Immediate treatment advised." : ""]
" + dat += "[severity] levels of acute radiation sickness detected. [round(M.radiation/50)]Gy. [(severity == "Critical" || severity == "Lethal") ? " Immediate treatment advised." : ""]
" else dat += "Radiation detected.
" + dat += "Acute radiation sickness detected.
" + if(M.accumulated_rads) + if(advscan >= 2 && showadvscan == 1) + var/severity = "" + if(M.accumulated_rads >= 1500) + severity = "Critical" + else if(M.accumulated_rads >= 600) + severity = "Severe" + else if(M.accumulated_rads >= 400) + severity = "Moderate" + else if(M.accumulated_rads >= 300) + severity = "Mild" + else if(M.accumulated_rads >= 100) + severity = "Low" + dat += "[severity] levels of chronic radiation sickness detected. [round(M.accumulated_rads/50)]Gy.
" + else + dat += "Chronic radiation sickness detected.
" if(iscarbon(M)) var/mob/living/carbon/C = M if(C.reagents.total_volume) diff --git a/code/game/objects/items/falling_object_attack_vr.dm b/code/game/objects/items/falling_object_attack_vr.dm new file mode 100644 index 0000000000..879fee9fde --- /dev/null +++ b/code/game/objects/items/falling_object_attack_vr.dm @@ -0,0 +1,45 @@ +/obj/effect/calldown_attack + anchored = TRUE + density = FALSE + unacidable = TRUE + mouse_opacity = 0 + icon = 'icons/effects/effects.dmi' + icon_state = "drop_marker" + +/obj/effect/calldown_attack/Initialize(mapload) + ..() + return INITIALIZE_HINT_LATELOAD + +/obj/effect/calldown_attack/LateInitialize() + var/delay = rand(25, 30) + spawn(delay-7) + new /obj/effect/falling_effect/calldown_attack(src.loc) + spawn(delay) + qdel(src) + + +/obj/effect/falling_effect/calldown_attack + falling_type = /obj/effect/illusionary_fall + crushing = FALSE + + +/obj/effect/illusionary_fall + anchored = TRUE + density = FALSE + mouse_opacity = 0 + icon = 'icons/effects/random_stuff_vr.dmi' + +/obj/effect/illusionary_fall/Initialize(mapload) + .=..() + icon_state = "[rand(1,33)]" + +/obj/effect/illusionary_fall/end_fall(var/crushing = FALSE) + for(var/mob/living/L in loc) + var/target_zone = ran_zone() + var/blocked = L.run_armor_check(target_zone, "melee") + var/soaked = L.get_armor_soak(target_zone, "melee") + + if(!L.apply_damage(35, BRUTE, target_zone, blocked, soaked)) + break + playsound(src, 'sound/effects/clang2.ogg', 50, 1) + qdel(src) \ No newline at end of file diff --git a/code/game/objects/items/falling_object_vr.dm b/code/game/objects/items/falling_object_vr.dm index 2769b7f013..f1c6d235bd 100644 --- a/code/game/objects/items/falling_object_vr.dm +++ b/code/game/objects/items/falling_object_vr.dm @@ -8,9 +8,10 @@ var/falling_type = /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/margherita var/crushing = TRUE -/obj/effect/falling_effect/Initialize(mapload, type = /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/margherita) +/obj/effect/falling_effect/Initialize(mapload, type) ..() - falling_type = type + if(type) + falling_type = type return INITIALIZE_HINT_LATELOAD /obj/effect/falling_effect/LateInitialize() diff --git a/code/game/objects/items/toys/toys_vr.dm b/code/game/objects/items/toys/toys_vr.dm index 386d73aaa9..d114b6e4ab 100644 --- a/code/game/objects/items/toys/toys_vr.dm +++ b/code/game/objects/items/toys/toys_vr.dm @@ -1084,4 +1084,27 @@ T = get_turf(src) new /obj/effect/decal/cleanable/confetti(T) else - to_chat(user, "The [src] is already spent!") \ No newline at end of file + to_chat(user, "The [src] is already spent!") + +/* + * Snow Globes + */ +/obj/item/weapon/toy/snowglobe + name = "snowglobe" + icon = 'icons/obj/snowglobe_vr.dmi' + +/obj/item/weapon/toy/snowglobe/snowvillage + desc = "Depicts a small, quaint village buried in snow." + icon_state = "smolsnowvillage" + +/obj/item/weapon/toy/snowglobe/tether + desc = "Depicts a massive space elevator reaching to the sky." + icon_state = "smoltether" + +/obj/item/weapon/toy/snowglobe/stellardelight + desc = "Depicts an interstellar spacecraft." + icon_state = "smolstellardelight" + +/obj/item/weapon/toy/snowglobe/rascalspass + desc = "Depicts a nanotrasen facility on a temperate world." + icon_state = "smolrascalspass" diff --git a/code/game/objects/items/trash_vr.dm b/code/game/objects/items/trash_vr.dm index bb18141f4f..1f6cf5d3a8 100644 --- a/code/game/objects/items/trash_vr.dm +++ b/code/game/objects/items/trash_vr.dm @@ -44,4 +44,19 @@ /obj/item/trash/ratjuice name = "\improper Space-Safe Meal package" icon = 'icons/obj/trash_vr.dmi' - icon_state = "altevian_juice-trash" \ No newline at end of file + icon_state = "altevian_juice-trash" + +/obj/item/trash/ratfruitcake + name = "\improper Flavor Unit package" + icon = 'icons/obj/trash_vr.dmi' + icon_state = "altevian_fruitcake-trash" + +/obj/item/trash/ratpackburger + name = "\improper Prepackaged Meal Tray" + icon = 'icons/obj/trash_vr.dmi' + icon_state = "altevian_pack_burger-trash" + +/obj/item/trash/ratpackcheese + name = "\improper Prepackaged Meal Tray" + icon = 'icons/obj/trash_vr.dmi' + icon_state = "altevian_pack_cheese-trash" \ No newline at end of file diff --git a/code/game/objects/items/weapons/circuitboards/machinery/kitchen_appliances.dm b/code/game/objects/items/weapons/circuitboards/machinery/kitchen_appliances.dm index 4343090655..4a5307fa12 100644 --- a/code/game/objects/items/weapons/circuitboards/machinery/kitchen_appliances.dm +++ b/code/game/objects/items/weapons/circuitboards/machinery/kitchen_appliances.dm @@ -16,7 +16,7 @@ name = T_BOARD("oven") desc = "The circuitboard for an oven." build_path = /obj/machinery/appliance/cooker/oven - board_type = new /datum/frame/frame_types/oven + board_type = new /datum/frame/frame_types/machine matter = list(MAT_STEEL = 50, MAT_GLASS = 50) req_components = list( /obj/item/weapon/stock_parts/capacitor = 3, @@ -27,17 +27,17 @@ name = T_BOARD("deep fryer") desc = "The circuitboard for a deep fryer." build_path = /obj/machinery/appliance/cooker/fryer - board_type = new /datum/frame/frame_types/fryer + board_type = new /datum/frame/frame_types/machine req_components = list( /obj/item/weapon/stock_parts/capacitor = 3, /obj/item/weapon/stock_parts/scanning_module = 1, /obj/item/weapon/stock_parts/matter_bin = 2) - + /obj/item/weapon/circuitboard/grill name = T_BOARD("grill") desc = "The circuitboard for an industrial grill." build_path = /obj/machinery/appliance/cooker/grill - board_type = new /datum/frame/frame_types/grill + board_type = new /datum/frame/frame_types/machine req_components = list( /obj/item/weapon/stock_parts/capacitor = 3, /obj/item/weapon/stock_parts/scanning_module = 1, @@ -47,7 +47,7 @@ name = T_BOARD("cereal maker") desc = "The circuitboard for a cereal maker." build_path = /obj/machinery/appliance/mixer/cereal - board_type = new /datum/frame/frame_types/cerealmaker + board_type = new /datum/frame/frame_types/machine req_components = list( /obj/item/weapon/stock_parts/capacitor = 3, /obj/item/weapon/stock_parts/scanning_module = 1, @@ -57,7 +57,7 @@ name = T_BOARD("candy machine") desc = "The circuitboard for a candy machine." build_path = /obj/machinery/appliance/mixer/candy - board_type = new /datum/frame/frame_types/candymachine + board_type = new /datum/frame/frame_types/machine req_components = list( /obj/item/weapon/stock_parts/capacitor = 3, /obj/item/weapon/stock_parts/scanning_module = 1, diff --git a/code/game/objects/items/weapons/melee/energy_vr.dm b/code/game/objects/items/weapons/melee/energy_vr.dm index 1d188d03ca..62f3201619 100644 --- a/code/game/objects/items/weapons/melee/energy_vr.dm +++ b/code/game/objects/items/weapons/melee/energy_vr.dm @@ -5,4 +5,21 @@ icon = 'icons/obj/weapons_vr.dmi' item_icons = list(slot_l_hand_str = 'icons/mob/items/lefthand_melee_vr.dmi', slot_r_hand_str = 'icons/mob/items/righthand_melee_vr.dmi') colorable = FALSE - lcolor = "#FFFFFF" \ No newline at end of file + lcolor = "#FFFFFF" + +/obj/item/weapon/melee/energy/sword/altevian + name = "plasma blade cutter" + desc = "A device used as both defense and operational purposes to cut through most metals. This is usually seen on engineers from the altevian hegemony when working salvaging derelicts." + icon_state = "altevian-cutter" + item_state = "altevian-cutter" + icon = 'icons/obj/weapons_vr.dmi' + item_icons = list(slot_l_hand_str = 'icons/mob/items/lefthand_melee_vr.dmi', slot_r_hand_str = 'icons/mob/items/righthand_melee_vr.dmi') + colorable = FALSE + lcolor = "#FFFFFF" + +/obj/item/weapon/melee/energy/sword/altevian/update_icon() + ..() + if(active) + icon_state = "[initial(icon_state)]_active" + else + icon_state = initial(icon_state) \ No newline at end of file diff --git a/code/game/objects/items/weapons/melee/misc_vr.dm b/code/game/objects/items/weapons/melee/misc_vr.dm index b14a36e1f4..d06c4b82bf 100644 --- a/code/game/objects/items/weapons/melee/misc_vr.dm +++ b/code/game/objects/items/weapons/melee/misc_vr.dm @@ -13,4 +13,22 @@ sharp = TRUE edge = FALSE attack_verb = list("stabbed", "lunged at", "dextrously struck", "sliced", "lacerated", "impaled", "diced", "charioted") - hitsound = 'sound/weapons/bladeslice.ogg' \ No newline at end of file + hitsound = 'sound/weapons/bladeslice.ogg' + +/obj/item/weapon/melee/altevian_wrench + name = "Hull Systems Multi-Wrench" + desc = "A wrench designed with a method to help secure and access bolts, hatches, and airlocks on altevian designed vessels. This operates as nothing more than a massive wrench when used for other purposes." + icon = 'icons/obj/weapons_vr.dmi' + icon_state = "altevian-wrench" + item_icons = list( + slot_l_hand_str = 'icons/mob/items/lefthand_melee_vr.dmi', + slot_r_hand_str = 'icons/mob/items/righthand_melee_vr.dmi', + ) + slot_flags = SLOT_BACK + force = 25 + throwforce = 15 + w_class = ITEMSIZE_HUGE + sharp = FALSE + edge = FALSE + attack_verb = list("whacked", "slammed", "bashed", "wrenched", "fixed", "bolted", "clonked", "bonked") + hitsound = 'sound/weapons/smash.ogg' \ No newline at end of file diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm index 325980756f..50b6e9ba8c 100644 --- a/code/game/objects/items/weapons/storage/backpack.dm +++ b/code/game/objects/items/weapons/storage/backpack.dm @@ -59,7 +59,7 @@ //Please don't clutter the parent storage item with stupid hacks. /obj/item/weapon/storage/backpack/holding/can_be_inserted(obj/item/W as obj, stop_messages = 0) if(istype(W, /obj/item/weapon/storage/backpack/holding)) - return 1 + return FALSE return ..() /obj/item/weapon/storage/backpack/santabag diff --git a/code/game/objects/items/weapons/storage/backpack_vr.dm b/code/game/objects/items/weapons/storage/backpack_vr.dm index 5588969224..1a872e99ac 100644 --- a/code/game/objects/items/weapons/storage/backpack_vr.dm +++ b/code/game/objects/items/weapons/storage/backpack_vr.dm @@ -45,8 +45,9 @@ return var/datum/sprite_accessory/tail/taur/TT = H.tail_style - item_state = "[icon_base]_[TT.icon_sprite_tag]" //icon_sprite_tag is something like "deer" - return 1 + if(istype(TT)) + item_state = "[icon_base]_[TT.icon_sprite_tag]" //icon_sprite_tag is something like "deer" + return 1 diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm index bdfb3397ce..12fd0191f7 100644 --- a/code/game/objects/items/weapons/storage/bags.dm +++ b/code/game/objects/items/weapons/storage/bags.dm @@ -295,7 +295,6 @@ 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) diff --git a/code/game/objects/random/guns_and_ammo.dm b/code/game/objects/random/guns_and_ammo.dm index 1e94a8b2c9..9d6053336d 100644 --- a/code/game/objects/random/guns_and_ammo.dm +++ b/code/game/objects/random/guns_and_ammo.dm @@ -98,6 +98,7 @@ prob(2);/obj/item/weapon/gun/projectile/shotgun/pump/combat, prob(4);/obj/item/weapon/gun/projectile/shotgun/pump/rifle, prob(3);/obj/item/weapon/gun/projectile/shotgun/pump/rifle/lever, + prob(2);/obj/item/weapon/gun/projectile/shotgun/semi, prob(2);/obj/item/weapon/gun/projectile/silenced) /obj/random/projectile/sec @@ -119,7 +120,8 @@ return pick(prob(4);/obj/item/weapon/gun/projectile/shotgun/doublebarrel, prob(3);/obj/item/weapon/gun/projectile/shotgun/doublebarrel/sawn, prob(3);/obj/item/weapon/gun/projectile/shotgun/pump, - prob(1);/obj/item/weapon/gun/projectile/shotgun/pump/combat) + prob(1);/obj/item/weapon/gun/projectile/shotgun/pump/combat, + prob(1);/obj/item/weapon/gun/projectile/shotgun/semi) /obj/random/handgun name = "Random Handgun" @@ -494,6 +496,10 @@ prob(1);list( /obj/item/weapon/gun/projectile/shotgun/pump/combat, /obj/item/ammo_magazine/ammo_box/b12g + ), + prob(1);list( + /obj/item/weapon/gun/projectile/shotgun/semi, + /obj/item/ammo_magazine/ammo_box/b12g ) ) diff --git a/code/game/objects/random/mapping.dm b/code/game/objects/random/mapping.dm index 8c762c0e23..0fa2cfb40e 100644 --- a/code/game/objects/random/mapping.dm +++ b/code/game/objects/random/mapping.dm @@ -77,7 +77,6 @@ prob(3);/obj/machinery/vending/fitness, prob(4);/obj/machinery/vending/cigarette, prob(3);/obj/machinery/vending/giftvendor, - prob(1);/obj/machinery/vending/hotfood, prob(5);/obj/machinery/vending/weeb, prob(5);/obj/machinery/vending/sol, prob(5);/obj/machinery/vending/snix, diff --git a/code/game/objects/structures/crates_lockers/closets/job_closets.dm b/code/game/objects/structures/crates_lockers/closets/job_closets.dm index e1a58bb0ca..86cb04e20d 100644 --- a/code/game/objects/structures/crates_lockers/closets/job_closets.dm +++ b/code/game/objects/structures/crates_lockers/closets/job_closets.dm @@ -33,6 +33,7 @@ /obj/item/clothing/under/sl_suit = 2, /obj/item/clothing/under/rank/bartender = 2, /obj/item/clothing/under/rank/bartender/skirt, + /obj/item/clothing/suit/storage/hooded/wintercoat/bar, /obj/item/clothing/under/dress/dress_saloon, /obj/item/clothing/accessory/wcoat = 2, /obj/item/clothing/shoes/black = 2, @@ -70,6 +71,7 @@ /obj/item/clothing/under/dress/maid/janitor, /obj/item/device/radio/headset/headset_service, /obj/item/weapon/cartridge/janitor, + /obj/item/clothing/suit/storage/hooded/wintercoat/janitor, /obj/item/clothing/gloves/black, /obj/item/clothing/head/soft/purple, /obj/item/clothing/head/beret/purple, @@ -127,4 +129,4 @@ /obj/item/weapon/storage/box/lights/mixed = 3, /obj/item/weapon/storage/box/mousetraps = 1, /obj/item/weapon/grenade/chem_grenade/cleaner = 4 - ) \ No newline at end of file + ) diff --git a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm index 70272f8681..404554cfa7 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm @@ -40,6 +40,7 @@ /obj/item/device/radio/headset/headset_med, /obj/item/device/radio/headset/headset_med/alt, /obj/item/clothing/suit/storage/hooded/wintercoat/medical, + /obj/item/clothing/suit/storage/hooded/wintercoat/medical/alt, /obj/item/clothing/shoes/boots/winter/medical, /obj/item/clothing/under/rank/nursesuit, /obj/item/clothing/head/nursehat, @@ -105,6 +106,7 @@ /obj/item/clothing/suit/storage/toggle/fr_jacket, /obj/item/clothing/suit/storage/toggle/labcoat/emt, /obj/item/clothing/suit/storage/hooded/wintercoat/medical/para, + /obj/item/clothing/shoes/boots/winter/medical, /obj/item/device/radio/headset/headset_med/alt, /obj/item/weapon/cartridge/medical, /obj/item/weapon/storage/briefcase/inflatable, diff --git a/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm b/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm index a23147b0c5..890a55deab 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm @@ -60,7 +60,7 @@ /obj/item/clothing/suit/storage/toggle/labcoat, /obj/item/clothing/suit/storage/toggle/labcoat/modern, /obj/item/clothing/shoes/white, - /obj/item/weapon/melee/umbrella, // vorestation addition, + /obj/item/weapon/melee/umbrella, /obj/item/clothing/glasses/science, /obj/item/device/radio/headset/headset_sci, /obj/item/weapon/storage/belt/archaeology, @@ -85,4 +85,4 @@ /obj/item/device/measuring_tape, /obj/item/weapon/pickaxe/hand, /obj/item/weapon/storage/bag/fossils, - /obj/item/weapon/hand_labeler) \ No newline at end of file + /obj/item/weapon/hand_labeler) diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index 883ac3d8f3..c420cd20b2 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -60,7 +60,7 @@ /obj/item/clothing/under/suit_jacket/teal/skirt, /obj/item/clothing/glasses/sunglasses, /obj/item/clothing/suit/storage/hooded/wintercoat/hop, - /obj/item/clothing/head/caphat/hop/beret/, + /obj/item/clothing/head/caphat/hop/beret, /obj/item/clothing/head/caphat/hop/beret/white) diff --git a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm index b684024374..dd0a327628 100644 --- a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm +++ b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm @@ -251,6 +251,7 @@ starts_with = list( /obj/item/clothing/under/rank/roboticist = 2, /obj/item/clothing/suit/storage/toggle/labcoat = 2, + /obj/item/clothing/suit/storage/hooded/wintercoat/science/robotics, /obj/item/clothing/shoes/black = 2, /obj/item/clothing/gloves/black = 2, /obj/item/weapon/storage/backpack/toxins, @@ -274,6 +275,7 @@ /obj/item/clothing/under/rank/chemist/skirt = 2, /obj/item/clothing/shoes/white = 2, /obj/item/clothing/suit/storage/toggle/labcoat/chemist = 2, + /obj/item/clothing/suit/storage/hooded/wintercoat/medical/chemist, /obj/item/weapon/storage/backpack/chemistry = 2, /obj/item/weapon/storage/backpack/satchel/chem = 2, /obj/item/weapon/storage/bag/chemistry = 2,) @@ -301,6 +303,7 @@ /obj/item/clothing/under/rank/virologist/skirt = 2, /obj/item/clothing/shoes/white = 2, /obj/item/clothing/suit/storage/toggle/labcoat/virologist = 2, + /obj/item/clothing/suit/storage/hooded/wintercoat/medical/viro, /obj/item/clothing/mask/surgical = 2, /obj/item/weapon/storage/backpack/virology = 2, /obj/item/weapon/storage/backpack/satchel/vir = 2) diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm index 6846b52066..1698593f91 100644 --- a/code/game/objects/structures/door_assembly.dm +++ b/code/game/objects/structures/door_assembly.dm @@ -155,7 +155,7 @@ bound_height = width * world.icon_size /obj/structure/door_assembly/proc/rename_door(mob/living/user) - var/t = sanitizeSafe(tgui_input_text(user, "Enter the name for the windoor.", src.name, src.created_name, MAX_NAME_LEN), MAX_NAME_LEN) + var/t = sanitizeSafe(tgui_input_text(user, "Enter the name for the [base_name].", src.name, src.created_name, MAX_NAME_LEN), MAX_NAME_LEN) if(!in_range(src, user) && src.loc != user) return created_name = t update_state() diff --git a/code/game/objects/structures/signs.dm b/code/game/objects/structures/signs.dm index 8befbe1800..dfa33067dc 100644 --- a/code/game/objects/structures/signs.dm +++ b/code/game/objects/structures/signs.dm @@ -275,6 +275,28 @@ desc = "Next to the extremely long list of names and job titles. Beneath the image, someone has scratched the word \"PACKETS\"" icon_state = "kiddieplaque" +//CHOMP Add start +/obj/structure/sign/kiddieplaque/poi1 + name = "expeditionary corps frame" + desc = "An old framed photograph of four figures in retro mining gear wielding harpoons. They look ready for a fight." + icon_state = "explorerplaque" + +/obj/structure/sign/kiddieplaque/poi2 + name = "expeditionary corps frame" + desc = "An old framed photograph of an oversized harpoon cannon." + icon_state = "explorerplaque2" + +/obj/structure/sign/kiddieplaque/poi3 + name = "expeditionary corps frame" + desc = "An old framed photograph of a gigantic black bear. Even through print it's chilling to examine." + icon_state = "explorerplaque3" + +/obj/structure/sign/kiddieplaque/poi4 + name = "expeditionary corps frame" + desc = "An old framed paper map littered with notes. Looks like the creator was marking the location of deposits." + icon_state = "explorerplaque4" +//CHOMP Add end + /obj/structure/sign/atmosplaque name = "\improper FEA atmospherics division plaque" desc = "This plaque commemorates the fall of the Atmos FEA division. For all the charred, dizzy, and brittle men who have died in its hands." diff --git a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm index 5466582125..d21dfc0579 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm @@ -93,14 +93,52 @@ color = null applies_material_colour = 0 -// Leaving this in for the sake of compilation. /obj/structure/bed/chair/comfy + name = "comfy chair" desc = "It's a chair. It looks comfy." icon_state = "comfychair" base_icon = "comfychair" -/obj/structure/bed/chair/comfy/brown/New(var/newloc,var/newmaterial) - ..(newloc,"steel","leather") +/obj/structure/bed/chair/comfy/update_icon() + ..() + var/image/I = image(icon, "[base_icon]_over") + I.layer = ABOVE_MOB_LAYER + I.plane = MOB_PLANE + I.color = material.icon_colour + add_overlay(I) + if(padding_material) + I = image(icon, "[base_icon]_padding_over") + I.layer = ABOVE_MOB_LAYER + I.plane = MOB_PLANE + I.color = padding_material.icon_colour + add_overlay(I) + +/obj/structure/bed/chair/comfy/brown/Initialize(var/ml,var/newmaterial) + . = ..(ml, MAT_STEEL, MAT_LEATHER) + +/obj/structure/bed/chair/comfy/red/Initialize(var/ml,var/newmaterial) + . = ..(ml, MAT_STEEL, "carpet") + +/obj/structure/bed/chair/comfy/teal/Initialize(var/ml,var/newmaterial) + . = ..(ml, MAT_STEEL, "teal") + +/obj/structure/bed/chair/comfy/black/Initialize(var/ml,var/newmaterial) + . = ..(ml, MAT_STEEL, "black") + +/obj/structure/bed/chair/comfy/green/Initialize(var/ml,var/newmaterial) + . = ..(ml, MAT_STEEL, "green") + +/obj/structure/bed/chair/comfy/purp/Initialize(var/ml,var/newmaterial) + . = ..(ml, MAT_STEEL, "purple") + +/obj/structure/bed/chair/comfy/blue/Initialize(var/ml,var/newmaterial) + . = ..(ml, MAT_STEEL, "blue") + +/obj/structure/bed/chair/comfy/beige/Initialize(var/ml,var/newmaterial) + . = ..(ml, MAT_STEEL, "beige") + +/obj/structure/bed/chair/comfy/lime/Initialize(var/ml,var/newmaterial) + . = ..(ml, MAT_STEEL, "lime") /obj/structure/bed/chair/comfy/red/New(var/newloc,var/newmaterial) ..(newloc,"steel","carpet") @@ -108,29 +146,50 @@ /obj/structure/bed/chair/comfy/teal/New(var/newloc,var/newmaterial) ..(newloc,"steel","teal") -/obj/structure/bed/chair/comfy/black/New(var/newloc,var/newmaterial) - ..(newloc,"steel","black") +/obj/structure/bed/chair/comfy/yellow/Initialize(var/ml,var/newmaterial) + . = ..(ml, MAT_STEEL, "yellow") -/obj/structure/bed/chair/comfy/green/New(var/newloc,var/newmaterial) - ..(newloc,"steel","green") +/obj/structure/bed/chair/comfy/orange/Initialize(var/ml,var/newmaterial) + . = ..(ml, MAT_STEEL, "orange") -/obj/structure/bed/chair/comfy/purp/New(var/newloc,var/newmaterial) - ..(newloc,"steel","purple") +/obj/structure/bed/chair/comfy/rounded + name = "rounded chair" + desc = "It's a rounded chair. It looks comfy." + icon_state = "roundedchair" + base_icon = "roundedchair" -/obj/structure/bed/chair/comfy/blue/New(var/newloc,var/newmaterial) - ..(newloc,"steel","blue") +/obj/structure/bed/chair/comfy/rounded/brown/Initialize(var/ml,var/newmaterial) + . = ..(ml, MAT_STEEL, MAT_LEATHER) -/obj/structure/bed/chair/comfy/beige/New(var/newloc,var/newmaterial) - ..(newloc,"steel","beige") +/obj/structure/bed/chair/comfy/rounded/red/Initialize(var/ml,var/newmaterial) + . = ..(ml, MAT_STEEL, "carpet") -/obj/structure/bed/chair/comfy/lime/New(var/newloc,var/newmaterial) - ..(newloc,"steel","lime") +/obj/structure/bed/chair/comfy/rounded/teal/Initialize(var/ml,var/newmaterial) + . = ..(ml, MAT_STEEL, "teal") -/obj/structure/bed/chair/comfy/yellow/New(var/newloc,var/newmaterial) - ..(newloc,"steel","yellow") +/obj/structure/bed/chair/comfy/rounded/black/Initialize(var/ml,var/newmaterial) + . = ..(ml, MAT_STEEL, "black") -/obj/structure/bed/chair/comfy/orange/New(var/newloc,var/newmaterial) - ..(newloc,"steel","orange") +/obj/structure/bed/chair/comfy/rounded/green/Initialize(var/ml,var/newmaterial) + . = ..(ml, MAT_STEEL, "green") + +/obj/structure/bed/chair/comfy/rounded/purple/Initialize(var/ml,var/newmaterial) + . = ..(ml, MAT_STEEL, "purple") + +/obj/structure/bed/chair/comfy/rounded/blue/Initialize(var/ml,var/newmaterial) + . = ..(ml, MAT_STEEL, "blue") + +/obj/structure/bed/chair/comfy/rounded/beige/Initialize(var/ml,var/newmaterial) + . = ..(ml, MAT_STEEL, "beige") + +/obj/structure/bed/chair/comfy/rounded/lime/Initialize(var/ml,var/newmaterial) + . = ..(ml, MAT_STEEL, "lime") + +/obj/structure/bed/chair/comfy/rounded/yellow/Initialize(var/ml,var/newmaterial) + . = ..(ml, MAT_STEEL, "yellow") + +/obj/structure/bed/chair/comfy/rounded/orange/Initialize(var/ml,var/newmaterial) + . = ..(ml, MAT_STEEL, "orange") /obj/structure/bed/chair/office anchored = FALSE @@ -146,7 +205,7 @@ /obj/structure/bed/chair/office/Moved(atom/old_loc, direction, forced = FALSE) . = ..() - + playsound(src, 'sound/effects/roll.ogg', 100, 1) /obj/structure/bed/chair/office/handle_buckled_mob_movement(atom/new_loc, direction, movetime) diff --git a/code/game/turfs/flooring/flooring.dm b/code/game/turfs/flooring/flooring.dm index 4b9686a25e..9a921ab260 100644 --- a/code/game/turfs/flooring/flooring.dm +++ b/code/game/turfs/flooring/flooring.dm @@ -615,4 +615,15 @@ var/list/flooring_types footstep_sounds = list("human" = list( 'sound/effects/footstep/lava1.ogg', 'sound/effects/footstep/lava2.ogg', - 'sound/effects/footstep/lava3.ogg')) \ No newline at end of file + 'sound/effects/footstep/lava3.ogg')) + +/decl/flooring/concrete + name = "concrete" + desc = "A flat area of concrete flooring." + icon = 'icons/turf/concrete.dmi' + icon_base = "concrete" + is_plating = FALSE //VOREStation edit. It's a lot cooler if it's actual tile. + can_paint = 1 //VOREStation edit. Let's allow for some fun. + can_engrave = 1 //VOREStation edit. Fun. + flags = TURF_ACID_IMMUNE | TURF_CAN_BREAK | TURF_REMOVE_CROWBAR + \ No newline at end of file diff --git a/code/game/turfs/flooring/flooring_premade.dm b/code/game/turfs/flooring/flooring_premade.dm index 5793c761bc..ff735044db 100644 --- a/code/game/turfs/flooring/flooring_premade.dm +++ b/code/game/turfs/flooring/flooring_premade.dm @@ -527,3 +527,9 @@ add_overlay(image(icon = 'icons/turf/outdoors.dmi', icon_state = "snow_footprints", dir = text2num(d))) //**** Here ends snow **** + +/turf/simulated/floor/concrete + name = "concrete" + icon = 'icons/turf/concrete.dmi' + icon_state = "concrete" + initial_flooring = /decl/flooring/concrete diff --git a/code/game/turfs/simulated/floor_types.dm b/code/game/turfs/simulated/floor_types.dm index a2a6cdeea2..104aff268b 100644 --- a/code/game/turfs/simulated/floor_types.dm +++ b/code/game/turfs/simulated/floor_types.dm @@ -116,7 +116,7 @@ /turf/simulated/shuttle/proc/underlay_update() if(!takes_underlays) //Basically, if it's not forced, and we don't care, don't do it. - return //CHOMP Edit removed 0. Sarcastically quoting the above comment ^ "Basically, if it's not stupposed to store a fucking value, don't store a fucking value." + return var/turf/under //May be a path or a turf var/mutable_appearance/us = new(src) //We'll use this for changes later diff --git a/code/game/turfs/simulated/outdoors/outdoors_vr.dm b/code/game/turfs/simulated/outdoors/outdoors_vr.dm index 48972b9f1e..536fea57c6 100644 --- a/code/game/turfs/simulated/outdoors/outdoors_vr.dm +++ b/code/game/turfs/simulated/outdoors/outdoors_vr.dm @@ -42,7 +42,7 @@ "dirt9" = 1 ) flooring_override = pickweight(possibledirts) - return ..() + return ..() /turf/simulated/floor/outdoors/newdirt_nograss @@ -62,7 +62,7 @@ "dirt9" = 1 ) flooring_override = pickweight(possibledirts) - return ..() + return ..() /turf/simulated/floor/outdoors/sidewalk name = "sidewalk" @@ -116,10 +116,10 @@ "[initial(icon_state)]7" = 2, "[initial(icon_state)]8" = 2, "[initial(icon_state)]9" = 2, - "[initial(icon_state)]10" = 2 + "[initial(icon_state)]10" = 2 ) flooring_override = pickweight(possibledirts) - return ..() + return ..() /turf/simulated/floor/outdoors/sidewalk/side icon_state = "side-walk" @@ -141,3 +141,18 @@ build_type = /obj/item/stack/tile/floor/sidewalk/slab /obj/item/stack/tile/floor/sidewalk/slab + +/obj/item/stack/tile/floor/concrete //Proper concrete tile. + name = "concrete tile" + singular_name = "floor tile" + desc = "A concrete tile fit for covering a section of floor." + icon_state = "tile" + force = 6.0 + matter = list(DEFAULT_WALL_MATERIAL = SHEET_MATERIAL_AMOUNT / 4) + throwforce = 15.0 + throw_speed = 5 + throw_range = 20 + no_variants = TRUE + +/decl/flooring/concrete + build_type = /obj/item/stack/tile/floor/concrete diff --git a/code/game/turfs/simulated/wall_icon.dm b/code/game/turfs/simulated/wall_icon.dm index 788f6c5452..7abc69e3b2 100644 --- a/code/game/turfs/simulated/wall_icon.dm +++ b/code/game/turfs/simulated/wall_icon.dm @@ -16,10 +16,10 @@ if(reinf_material) name = "reinforced [material.display_name] wall" - desc = "It seems to be a section of hull reinforced with [reinf_material.display_name] and plated with [material.display_name]." + desc = "It seems to be a section of wall reinforced with [reinf_material.display_name] and plated with [material.display_name]." else name = "[material.display_name] wall" - desc = "It seems to be a section of hull plated with [material.display_name]." + desc = "It seems to be a section of wall plated with [material.display_name]." if(material.opacity > 0.5 && !opacity) set_light(1) @@ -77,6 +77,9 @@ I = image(wall_masks, reinf_material.icon_reinf) I.color = reinf_material.icon_colour add_overlay(I) + var/image/texture = material.get_wall_texture() + if(texture) + add_overlay(texture) if(damage != 0) var/integrity = material.integrity diff --git a/code/game/turfs/simulated/wall_types.dm b/code/game/turfs/simulated/wall_types.dm index 52b2c30ab0..29aae0672a 100644 --- a/code/game/turfs/simulated/wall_types.dm +++ b/code/game/turfs/simulated/wall_types.dm @@ -78,6 +78,18 @@ /turf/simulated/wall/resin/Initialize(mapload) . = ..(mapload, "resin",null,"resin") +/turf/simulated/wall/concrete + icon_state = "brick" + +/turf/simulated/wall/concrete/Initialize(mapload) + . = ..(mapload, "concrete") //3strong + +/turf/simulated/wall/r_concrete + icon_state = "rbrick" + +/turf/simulated/wall/r_concrete/Initialize(mapload) + . = ..(mapload, "concrete","plasteel rebar") //3strong + // Kind of wondering if this is going to bite me in the butt. /turf/simulated/wall/skipjack/Initialize(mapload) . = ..(mapload, "alienalloy") @@ -325,10 +337,9 @@ /obj/structure/hull_corner name = "hull corner" plane = OBJ_PLANE - 1 - icon = 'icons/turf/wall_masks.dmi' icon_state = "hull_corner" - + anchored = TRUE density = TRUE breakable = TRUE @@ -344,6 +355,7 @@ return list(dir, turn(dir,90)) /obj/structure/hull_corner/proc/update_look() + cut_overlays() var/turf/simulated/wall/T for(var/direction in get_dirs_to_test()) T = get_step(src, direction) @@ -363,7 +375,7 @@ I.color = R.icon_colour add_overlay(I) break - + if(!T) warning("Hull corner at [x],[y] not placed adjacent to a hull it can find.") @@ -393,7 +405,7 @@ /turf/simulated/wall/eris/can_join_with_low_wall(var/obj/structure/low_wall/WF) return istype(WF, /obj/structure/low_wall/eris) - + /turf/simulated/wall/eris/special_wall_connections(list/dirs, list/inrange) ..() for(var/direction in cardinal) @@ -414,7 +426,7 @@ if(decided_to_blend) dirs += direction break blend_obj_loop // breaks outer loop - + /turf/simulated/wall/eris/r_wall icon_state = "rgeneric" /turf/simulated/wall/eris/r_wall/Initialize(mapload) @@ -427,7 +439,7 @@ wall_masks = 'icons/turf/wall_masks_bay.dmi' var/list/blend_objects = list(/obj/machinery/door) var/list/noblend_objects = list(/obj/machinery/door/window, /obj/machinery/door/firedoor) - + var/stripe_color // Adds a colored stripe to the walls /turf/simulated/wall/bay/can_join_with_low_wall(var/obj/structure/low_wall/WF) @@ -441,7 +453,7 @@ I = image(wall_masks, "stripe[wall_connections[i]]", dir = 1<<(i-1)) I.color = stripe_color add_overlay(I) - + /turf/simulated/wall/bay/special_wall_connections(list/dirs, list/inrange) ..() for(var/direction in cardinal) @@ -744,4 +756,4 @@ wall_base_state = "darkwall_rwindow" #undef WINDOW_GLASS -#undef WINDOW_RGLASS \ No newline at end of file +#undef WINDOW_RGLASS diff --git a/code/modules/admin/admin_verb_lists_vr.dm b/code/modules/admin/admin_verb_lists_vr.dm index cbbeab71ad..c7f6745c43 100644 --- a/code/modules/admin/admin_verb_lists_vr.dm +++ b/code/modules/admin/admin_verb_lists_vr.dm @@ -8,7 +8,7 @@ var/list/admin_verbs_default = list( /client/proc/cmd_mod_say, //VOREStation Add, /client/proc/cmd_event_say, //VOREStation Add, /client/proc/cmd_mentor_ticket_panel, - /client/proc/cmd_mentor_say + /client/proc/cmd_mentor_say, // /client/proc/hide_verbs, //hides all our adminverbs, //VOREStation Remove, // /client/proc/hide_most_verbs, //hides all our hideable adminverbs, //VOREStation Remove, // /client/proc/debug_variables, //allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify, //VOREStation Remove, @@ -18,6 +18,8 @@ var/list/admin_verbs_default = list( // /client/proc/cmd_mod_say, // /client/proc/deadchat //toggles deadchat on/off, // /client/proc/toggle_ahelp_sound, + /client/proc/toggle_admin_global_looc, + /client/proc/toggle_admin_deadchat ) var/list/admin_verbs_admin = list( diff --git a/code/modules/admin/verbs/buildmode.dm b/code/modules/admin/verbs/buildmode.dm index d9aacdcaca..485cc88e22 100644 --- a/code/modules/admin/verbs/buildmode.dm +++ b/code/modules/admin/verbs/buildmode.dm @@ -364,7 +364,7 @@ if(ispath(holder.buildmode.objholder,/turf)) var/turf/T = get_turf(object) T.ChangeTurf(holder.buildmode.objholder) - else + else if(ispath(holder.buildmode.objholder)) var/obj/A = new holder.buildmode.objholder (get_turf(object)) A.set_dir(holder.builddir.dir) else if(pa.Find("right")) diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 960d3a6b99..ceba8367ff 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -530,8 +530,9 @@ Traitors and the like can also be revived with the previous role mostly intact. if(equipment) if(charjob) job_master.EquipRank(new_character, charjob, 1, announce) - new_character.mind.assigned_role = charjob - new_character.mind.role_alt_title = job_master.GetPlayerAltTitle(new_character, charjob) + if(new_character.mind) + new_character.mind.assigned_role = charjob + new_character.mind.role_alt_title = job_master.GetPlayerAltTitle(new_character, charjob) equip_custom_items(new_character) //CHOMPEdit readded to enable custom_item.txt //If desired, add records. diff --git a/code/modules/admin/verbs/smite_vr.dm b/code/modules/admin/verbs/smite_vr.dm index 750a8c0bea..5ac60fcfc1 100644 --- a/code/modules/admin/verbs/smite_vr.dm +++ b/code/modules/admin/verbs/smite_vr.dm @@ -146,6 +146,7 @@ var/redspace_abduction_z redspace_abduction_z = -1 to_chat(user,"This is the first use of the verb this shift, it will take a minute to configure the abduction z-level. It will be z[world.maxz+1].") var/z = ++world.maxz + world.max_z_changed() for(var/x = 1 to world.maxx) for(var/y = 1 to world.maxy) var/turf/T = locate(x,y,z) @@ -232,7 +233,7 @@ var/redspace_abduction_z to_chat(target, "Autosaving your progress, please wait...") target << 'sound/effects/ding.ogg' - + var/static/list/bad_tips = list( "Did you know that black shoes protect you from electrocution while hacking?", "Did you know that airlocks always have a wire that disables ID checks?", diff --git a/code/modules/asset_cache/asset_list_items.dm b/code/modules/asset_cache/asset_list_items.dm index 98b3a55a9b..c9c35312f7 100644 --- a/code/modules/asset_cache/asset_list_items.dm +++ b/code/modules/asset_cache/asset_list_items.dm @@ -154,10 +154,10 @@ // /datum/asset/simple/fontawesome // ) -// /datum/asset/simple/jquery -// assets = list( -// "jquery.min.js" = 'code/modules/goonchat/browserassets/js/jquery.min.js', -// ) +/datum/asset/simple/jquery + assets = list( + "jquery.min.js" = 'code/modules/tooltip/jquery.min.js', + ) // /datum/asset/simple/goonchat // assets = list( @@ -300,10 +300,20 @@ name = "vore" /datum/asset/spritesheet/vore/register() - var/icon/downscaled = icon('modular_chomp/icons/mob/screen_full_vore_ch.dmi') //CHOMPedit + var/icon/downscaled = icon('modular_chomp/icons/mob/screen_full_vore_ch.dmi') //CHOMPedit: preserving save data downscaled.Scale(240, 240) InsertAll("", downscaled) ..() + +/datum/asset/spritesheet/vore_fixed //This should be getting loaded in the TGUI vore panel but the game refuses to do so, for some reason. It only loads the vore spritesheet. //CHOMPedit + name = "fixedvore" //CHOMPedit + +/datum/asset/spritesheet/vore_fixed/register() //CHOMPedi start: preserving save data + var/icon/downscaledVF = icon('icons/mob/screen_full_vore.dmi') + downscaledVF.Scale(240, 240) + InsertAll("", downscaledVF) //CHOMpedit end + ..() + //VOREStation Add End // // Representative icons for each research design @@ -520,20 +530,5 @@ "southern_cross_nanomap_z9.png" = 'icons/_nanomaps/southern_cross_nanomap_z9.png', "southern_cross_nanomap_z10.png" = 'icons/_nanomaps/southern_cross_nanomap_z10.png', "southern_cross_nanomap_z11.png" = 'icons/_nanomaps/southern_cross_nanomap_z11.png', - //"tether_nanomap_z1.png" = 'icons/_nanomaps/tether_nanomap_z1.png', - //"tether_nanomap_z2.png" = 'icons/_nanomaps/tether_nanomap_z2.png', - //"tether_nanomap_z3.png" = 'icons/_nanomaps/tether_nanomap_z3.png', - //"tether_nanomap_z4.png" = 'icons/_nanomaps/tether_nanomap_z4.png', - //"tether_nanomap_z5.png" = 'icons/_nanomaps/tether_nanomap_z5.png', - //"tether_nanomap_z6.png" = 'icons/_nanomaps/tether_nanomap_z6.png', - //"tether_nanomap_z7.png" = 'icons/_nanomaps/tether_nanomap_z7.png', - //"tether_nanomap_z8.png" = 'icons/_nanomaps/tether_nanomap_z8.png', - //"tether_nanomap_z9.png" = 'icons/_nanomaps/tether_nanomap_z9.png', - //"tether_nanomap_z10.png" = 'icons/_nanomaps/tether_nanomap_z10.png', - //"tether_nanomap_z13.png" = 'icons/_nanomaps/tether_nanomap_z13.png', - //"tether_nanomap_z14.png" = 'icons/_nanomaps/tether_nanomap_z14.png', - //"stellardelight_nanomap_z1.png" = 'icons/_nanomaps/sd_deck1.png', - //"stellardelight_nanomap_z2.png" = 'icons/_nanomaps/sd_deck2.png', - //"stellardelight_nanomap_z3.png" = 'icons/_nanomaps/sd_deck3.png', // CHOMP Edit End ) diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index cff2875e7d..98e1c2d51d 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -208,6 +208,8 @@ prefs.last_id = computer_id //these are gonna be used for banning prefs.client = src // Only relevant if we reloaded it from the global list, otherwise prefs/New sets it + hook_vr("client_new",list(src)) //VOREStation Code. For now this only loads vore prefs, so better put before mob.Login() call but after normal prefs are loaded. + . = ..() //calls mob.Login() prefs.sanitize_preferences() if(prefs) @@ -252,8 +254,6 @@ if(config.aggressive_changelog) src.changes() - hook_vr("client_new",list(src)) //VOREStation Code - if(config.paranoia_logging) var/alert = FALSE //VOREStation Edit start. if(isnum(player_age) && player_age == 0) diff --git a/code/modules/client/preference_setup/general/02_language.dm b/code/modules/client/preference_setup/general/02_language.dm index 25d8c2c10e..9ceb693bd2 100644 --- a/code/modules/client/preference_setup/general/02_language.dm +++ b/code/modules/client/preference_setup/general/02_language.dm @@ -9,7 +9,8 @@ /datum/category_item/player_setup_item/general/language/load_character(var/savefile/S) S["language"] >> pref.alternate_languages S["extra_languages"] >> pref.extra_languages - testing("LANGSANI: Loaded from [pref.client]'s character [pref.real_name || "-name not yet loaded-"] savefile: [english_list(pref.alternate_languages || list())]") + if(islist(pref.alternate_languages)) // Because aparently it may not be? + testing("LANGSANI: Loaded from [pref.client]'s character [pref.real_name || "-name not yet loaded-"] savefile: [english_list(pref.alternate_languages || list())]") S["language_prefixes"] >> pref.language_prefixes //CHOMPEdit Begin S["species"] >> pref.species @@ -19,7 +20,8 @@ /datum/category_item/player_setup_item/general/language/save_character(var/savefile/S) S["language"] << pref.alternate_languages S["extra_languages"] << pref.extra_languages - testing("LANGSANI: Saved to [pref.client]'s character [pref.real_name || "-name not yet loaded-"] savefile: [english_list(pref.alternate_languages || list())]") + if(islist(pref.alternate_languages)) // Because aparently it may not be? + testing("LANGSANI: Loaded from [pref.client]'s character [pref.real_name || "-name not yet loaded-"] savefile: [english_list(pref.alternate_languages || list())]") S["language_prefixes"] << pref.language_prefixes S["language_custom_keys"] << pref.language_custom_keys diff --git a/code/modules/client/preference_setup/global/setting_datums.dm b/code/modules/client/preference_setup/global/setting_datums.dm index 11ef5d994b..f7ca6bf963 100644 --- a/code/modules/client/preference_setup/global/setting_datums.dm +++ b/code/modules/client/preference_setup/global/setting_datums.dm @@ -422,3 +422,9 @@ var/list/_client_preferences_by_type key = "CHAT_RLOOC" enabled_description = "Show" disabled_description = "Hide" + +/datum/client_preference/holder/show_staff_dsay + description ="Staff Deadchat" + key = "CHAT_ADSAY" + enabled_description = "Show" + disabled_description = "Hide" diff --git a/code/modules/client/preference_setup/loadout/loadout_suit.dm b/code/modules/client/preference_setup/loadout/loadout_suit.dm index 3041af9e90..14cc60208d 100644 --- a/code/modules/client/preference_setup/loadout/loadout_suit.dm +++ b/code/modules/client/preference_setup/loadout/loadout_suit.dm @@ -194,6 +194,11 @@ path = /obj/item/clothing/suit/storage/apron/overalls cost = 1 +/datum/gear/suit/altevian_apron + display_name = "crafters pride apron" + path = /obj/item/clothing/suit/storage/apron/altevian + cost = 1 + /datum/gear/suit/cyberpunk display_name = "cyberpunk jacket" path = /obj/item/clothing/suit/cyberpunk diff --git a/code/modules/client/preference_setup/loadout/loadout_xeno_vr.dm b/code/modules/client/preference_setup/loadout/loadout_xeno_vr.dm index 9e4a87cb6d..f014232fe3 100644 --- a/code/modules/client/preference_setup/loadout/loadout_xeno_vr.dm +++ b/code/modules/client/preference_setup/loadout/loadout_xeno_vr.dm @@ -86,6 +86,23 @@ //whitelisted = SPECIES_TAJ sort_category = "Xenowear" +/datum/gear/mask/altevian_breath + display_name = "spacer tuned mask (Altevian)" + path = /obj/item/clothing/mask/altevian_breath + sort_category = "Xenowear" + +/datum/gear/uniform/altevian_outfit + description = "A uniform commonly seen from altevians during their work. The material on this uniform seems to be made of durable thread that can handle the stress of most matters of labor." + display_name = "altevian duty jumpsuit selection (Altevian)" + sort_category = "Xenowear" + +/datum/gear/uniform/altevian_outfit/New() + ..() + var/list/pants = list() + for(var/obj/item/clothing/under/altevian/uniform_type as anything in typesof(/obj/item/clothing/under/altevian)) + pants[initial(uniform_type.name)] = uniform_type + gear_tweaks += new/datum/gear_tweak/path(sortAssoc(pants)) + // Taur stuff /datum/gear/suit/taur/drake_cloak display_name = "drake cloak (Drake-taur)" diff --git a/code/modules/client/preference_setup/traits/trait_defines.dm b/code/modules/client/preference_setup/traits/trait_defines.dm index 9eb4793b5e..aaca85b086 100644 --- a/code/modules/client/preference_setup/traits/trait_defines.dm +++ b/code/modules/client/preference_setup/traits/trait_defines.dm @@ -7,9 +7,12 @@ /datum/trait/modifier/apply_trait_post_spawn(mob/living/L) L.add_modifier(modifier_type) +/datum/trait/modifier/is_available() + return !!modifier_type + /datum/trait/modifier/generate_desc() var/new_desc = desc - if(!modifier_type) + if(!is_available()) new_desc = "[new_desc] This trait is not implemented yet." return new_desc var/datum/modifier/M = new modifier_type() diff --git a/code/modules/client/preference_setup/traits/traits.dm b/code/modules/client/preference_setup/traits/traits.dm index 806086c9a7..b4e9b63734 100644 --- a/code/modules/client/preference_setup/traits/traits.dm +++ b/code/modules/client/preference_setup/traits/traits.dm @@ -7,6 +7,9 @@ var/list/trait_categories = list() // The categories available for the trait men //create a list of trait datums for(var/trait_type in typesof(/datum/trait) - list(/datum/trait, /datum/trait/modifier)) var/datum/trait/T = new trait_type + if(!T.is_available()) + qdel(T) + continue if(!T.name) error("Trait Menu - Missing name: [T.type]") @@ -173,6 +176,9 @@ var/list/trait_categories = list() // The categories available for the trait men return result +/datum/trait/proc/is_available() + return TRUE + // Similar to above, but uses the above two procs, in one place. // Returns TRUE is everything is well. /datum/trait/proc/validate(var/list/current_traits, var/datum/category_item/player_setup_item/traits/setup) @@ -193,4 +199,4 @@ var/list/trait_categories = list() // The categories available for the trait men for(var/trait in mind.traits) var/datum/trait/T = trait_datums[trait] if(istype(T)) - T.apply_trait_post_spawn(src) \ No newline at end of file + T.apply_trait_post_spawn(src) diff --git a/code/modules/client/preferences_toggle_procs.dm b/code/modules/client/preferences_toggle_procs.dm index 6df855d1eb..0e83638e88 100644 --- a/code/modules/client/preferences_toggle_procs.dm +++ b/code/modules/client/preferences_toggle_procs.dm @@ -512,7 +512,7 @@ CHOMPRemove. Bundled voice sounds into emote/whisper/subtle. Going this extra le to_chat(src,"You will [ (is_preference_enabled(pref_path)) ? "now" : "no longer"] receive debug logs.") SScharacter_setup.queue_preferences_save(prefs) - feedback_add_details("admin_verb","TBeSpecial") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + feedback_add_details("admin_verb","TADebugLogs") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! //Mods /client/proc/toggle_attack_logs() @@ -527,4 +527,33 @@ CHOMPRemove. Bundled voice sounds into emote/whisper/subtle. Going this extra le to_chat(src,"You will [ (is_preference_enabled(pref_path)) ? "now" : "no longer"] receive attack logs.") SScharacter_setup.queue_preferences_save(prefs) - feedback_add_details("admin_verb","TBeSpecial") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + feedback_add_details("admin_verb","TAAttackLogs") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +//General +/client/proc/toggle_admin_global_looc() + set name = "Toggle Admin Global LOOC Visibility" + set category = "Preferences" + set desc = "Toggles seeing LOOC messages outside your actual LOOC range." + + var/pref_path = /datum/client_preference/holder/show_rlooc + + if(holder) + toggle_preference(pref_path) + to_chat(src,"You will [ (is_preference_enabled(pref_path)) ? "now" : "no longer"] hear global LOOC.") + SScharacter_setup.queue_preferences_save(prefs) + + feedback_add_details("admin_verb","TAGlobalLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/client/proc/toggle_admin_deadchat() + set name = "Toggle Admin Living Deadchat" + set category = "Preferences" + set desc = "Toggles seeing deadchat while not observing." + + var/pref_path = /datum/client_preference/holder/show_staff_dsay + + if(holder) + toggle_preference(pref_path) + to_chat(src,"You will [ (is_preference_enabled(pref_path)) ? "now" : "no longer"] hear deadchat while not observing.") + SScharacter_setup.queue_preferences_save(prefs) + + feedback_add_details("admin_verb","TADeadchat") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/client/preferences_vr.dm b/code/modules/client/preferences_vr.dm index 8b0b72f8bb..df898e15f6 100644 --- a/code/modules/client/preferences_vr.dm +++ b/code/modules/client/preferences_vr.dm @@ -100,7 +100,7 @@ else to_chat(src, "You are now catchable.") prefs.capture_crystal = 1 - if(L) + if(L && istype(L)) L.capture_crystal = prefs.capture_crystal SScharacter_setup.queue_preferences_save(prefs) diff --git a/code/modules/client/stored_item.dm b/code/modules/client/stored_item.dm index 88dbbe2ee8..fda2dcc9c8 100644 --- a/code/modules/client/stored_item.dm +++ b/code/modules/client/stored_item.dm @@ -254,3 +254,5 @@ persist_storable = FALSE /obj/item/weapon/spacecasinocash persist_storable = FALSE +/obj/item/device/personal_shield_generator + persist_storable = FALSE diff --git a/code/modules/clothing/masks/breath_vr.dm b/code/modules/clothing/masks/breath_vr.dm index 47c5fdb64b..706371a67a 100644 --- a/code/modules/clothing/masks/breath_vr.dm +++ b/code/modules/clothing/masks/breath_vr.dm @@ -2,3 +2,20 @@ name = "transparent breath mask" item_state = "golem" //This is dumb and hacky but was here when I got here. sprite_sheets = null + +/obj/item/clothing/mask/altevian_breath + name = "Spacer Tuned Mask" + desc = "A mask designed for long-term use in areas where breathing comes at a premium." + icon_state = "altevian-mask" + icon = 'icons/inventory/face/item_vr.dmi' + icon_override = 'icons/inventory/face/mob_vr.dmi' + sprite_sheets = null + item_state_slots = list(slot_r_hand_str = "breath", slot_l_hand_str = "breath") + item_flags = AIRTIGHT|FLEXIBLEMATERIAL + body_parts_covered = FACE + w_class = ITEMSIZE_SMALL + gas_transfer_coefficient = 0.10 + permeability_coefficient = 0.50 + species_restricted = list(SPECIES_ALTEVIAN) + pickup_sound = 'sound/items/pickup/component.ogg' + drop_sound = 'sound/items/drop/component.ogg' diff --git a/code/modules/clothing/spacesuits/rig/suits/alien.dm b/code/modules/clothing/spacesuits/rig/suits/alien.dm index 95fbe88ca3..96a3c731a7 100644 --- a/code/modules/clothing/spacesuits/rig/suits/alien.dm +++ b/code/modules/clothing/spacesuits/rig/suits/alien.dm @@ -189,3 +189,32 @@ ) //ChompEdit Ends + + +//Chompedit Begins + +/obj/item/weapon/rig/vox/security + name = "sturdy alien control module" + suit_type = "dense alien" + icon_state = "vox_rig" + desc = "A medium weight, alien control module. Built sturdy for security engagements." + armor = list (melee = 60, bullet = 50, laser = 40, energy = 10, bomb = 20, bio = 100, rad = 50) //CE suit values but shuffled to a tighter focus on the job hazards + flags = PHORONGUARD + item_flags = THICKMATERIAL + siemens_coefficient = 0.5 + offline_slowdown = 5 + slowdown = 0 + emp_protection = 40 //change this to 30 if too high. + + req_one_access = list() + allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/storage) + offline_vision_restriction = 1 + + initial_modules = list( + ) + + air_type = /obj/item/weapon/tank/vox + + max_heat_protection_temperature = FIRE_HELMET_MAX_HEAT_PROTECTION_TEMPERATURE + + //ChompEdit Ends diff --git a/code/modules/clothing/spacesuits/void/event_vr.dm b/code/modules/clothing/spacesuits/void/event_vr.dm index dd8e8fce2c..e62e53e7f3 100644 --- a/code/modules/clothing/spacesuits/void/event_vr.dm +++ b/code/modules/clothing/spacesuits/void/event_vr.dm @@ -88,11 +88,11 @@ /obj/item/clothing/suit/space/void/hev name = "hazardous environment suit" desc = "Has a strange smell to it, but you feel like it might be an old friend." - + icon = 'icons/inventory/suit/item_vr.dmi' default_worn_icon = 'icons/inventory/suit/mob_vr.dmi' icon_state = "hev_orange" - + sprite_sheets = ALL_VR_SPRITE_SHEETS_SUIT_MOB sprite_sheets_obj = ALL_VR_SPRITE_SHEETS_SUIT_ITEM @@ -103,11 +103,11 @@ /obj/item/clothing/head/helmet/space/void/hev name = "hazardous environment helmet" desc = "Has a strange smell to it, but you feel like it might be an old friend." - + icon = 'icons/inventory/head/item_vr.dmi' default_worn_icon = 'icons/inventory/head/mob_vr.dmi' icon_state = "hev_orange" - + sprite_sheets = ALL_VR_SPRITE_SHEETS_HEAD_MOB sprite_sheets_obj = ALL_VR_SPRITE_SHEETS_HEAD_ITEM @@ -119,11 +119,11 @@ /obj/item/clothing/suit/space/void/makeshift name = "makeshift voidsuit" desc = "This is not something you should use if you have other options, but it's better than nothing!" - + icon = 'icons/inventory/suit/item_vr.dmi' default_worn_icon = 'icons/inventory/suit/mob_vr.dmi' icon_state = "makeshift_void" - + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0) sprite_sheets = ALL_VR_SPRITE_SHEETS_SUIT_MOB @@ -132,7 +132,7 @@ /obj/item/clothing/head/helmet/space/void/makeshift name = "makeshift voidsuit helmet" desc = "This is not something you should use if you have other options, but it's better than nothing!" - + icon = 'icons/inventory/head/item_vr.dmi' default_worn_icon = 'icons/inventory/head/mob_vr.dmi' icon_state = "makeshift_void" @@ -146,26 +146,26 @@ /obj/item/clothing/suit/space/void/custodian name = "custodian suit" desc = "Vacuum-capable armor for a Custodian to do their duty." - + icon = 'icons/inventory/suit/item_vr.dmi' default_worn_icon = 'icons/inventory/suit/mob_vr.dmi' icon_state = "custodian" armor = list("melee" = 70, "bullet" = 70, "laser" = 70, "energy" = 50, "bomb" = 40, "bio" = 0, "rad" = 20) - + sprite_sheets = ALL_VR_SPRITE_SHEETS_SUIT_MOB sprite_sheets_obj = ALL_VR_SPRITE_SHEETS_SUIT_ITEM /obj/item/clothing/head/helmet/space/void/custodian name = "custodian helmet" desc = "Vacuum-capable helmet for a Custodian to do their duty." - + icon = 'icons/inventory/head/item_vr.dmi' default_worn_icon = 'icons/inventory/head/mob_vr.dmi' icon_state = "custodian" armor = list("melee" = 70, "bullet" = 70, "laser" = 70, "energy" = 50, "bomb" = 40, "bio" = 0, "rad" = 20) - + sprite_sheets = ALL_VR_SPRITE_SHEETS_HEAD_MOB sprite_sheets_obj = ALL_VR_SPRITE_SHEETS_HEAD_ITEM @@ -173,7 +173,7 @@ /obj/item/clothing/suit/space/void/aether name = "\improper Aether voidsuit" desc = "This suit seems rather high-end for a standard voidsuit. The air in it has a hint of 'new car smell', courtesy of Aether Atmospherics." - + icon = 'icons/inventory/suit/item_vr.dmi' default_worn_icon = 'icons/inventory/suit/mob_vr.dmi' icon_state = "moebiussuit" @@ -186,7 +186,7 @@ /obj/item/clothing/head/helmet/space/void/aether name = "\improper Aether voidsuit helmet" desc = "Aether Atmospherics thought that giving this helmet selectable colored lighting would improve market penetration. Very comfortable, regardless." - + icon = 'icons/inventory/head/item_vr.dmi' default_worn_icon = 'icons/inventory/head/mob_vr.dmi' icon_state = "moebiushelm_White" @@ -212,21 +212,49 @@ /obj/item/clothing/suit/space/void/excelsior name = "\improper Excelsior voidsuit" desc = "A space suit from a particular spaceship: Excelsior." - + icon = 'icons/inventory/suit/item_vr.dmi' default_worn_icon = 'icons/inventory/suit/mob_vr.dmi' icon_state = "excelsior" - + sprite_sheets = ALL_VR_SPRITE_SHEETS_SUIT_MOB sprite_sheets_obj = ALL_VR_SPRITE_SHEETS_SUIT_ITEM /obj/item/clothing/head/helmet/space/void/excelsior name = "\improper Excelsior voidsuit helmet" desc = "A space helmet from a particular spaceship: Excelsior." - + icon = 'icons/inventory/head/item_vr.dmi' default_worn_icon = 'icons/inventory/head/mob_vr.dmi' icon_state = "excelsior" - + sprite_sheets = ALL_VR_SPRITE_SHEETS_HEAD_MOB sprite_sheets_obj = ALL_VR_SPRITE_SHEETS_HEAD_ITEM + + +/obj/item/clothing/suit/space/void/altevian_heartbreaker + name = "\improper heartbreaker voidsuit" + desc = "The altevians' newest iteration of their armored suits. This one is tailored for zero-g environments, and while it can function in an area with gravity, it'll put a strain on even the most athletic of individuals." + + icon = 'icons/inventory/suit/item_vr_altevian.dmi' + default_worn_icon = 'icons/inventory/suit/mob_vr_altevian.dmi' + icon_state = "rig-heartbreaker" + + armor = list("melee" = 90, "bullet" = 90, "laser" = 90, "energy" = 90, "bomb" = 90, "bio" = 100, "rad" = 80) + + species_restricted = list(SPECIES_ALTEVIAN) + no_cycle = TRUE + slowdown = 2.5 + +/obj/item/clothing/head/helmet/space/void/altevian_heartbreaker + name = "\improper heartbreaker helmet" + desc = "The altevians' newest iteration of their armored suits. This one is tailored for zero-g environments, and while it can function in an area with gravity, it'll put a strain on even the most athletic of individuals." + + icon = 'icons/inventory/head/item_vr_altevian.dmi' + default_worn_icon = 'icons/inventory/head/mob_vr_altevian.dmi' + icon_state = "rig0-heartbreaker" + + armor = list("melee" = 90, "bullet" = 90, "laser" = 90, "energy" = 90, "bomb" = 90, "bio" = 100, "rad" = 80) + + species_restricted = list(SPECIES_ALTEVIAN) + no_cycle = TRUE diff --git a/code/modules/clothing/suits/jobs.dm b/code/modules/clothing/suits/jobs.dm index d2ba4b26d9..1341af1b69 100644 --- a/code/modules/clothing/suits/jobs.dm +++ b/code/modules/clothing/suits/jobs.dm @@ -19,6 +19,12 @@ icon_state = "apron_white" item_state_slots = list(slot_r_hand_str = "apronchef", slot_l_hand_str = "apronchef") +/obj/item/clothing/suit/storage/apron/altevian + name = "Multi-purpose Crafters' Pride" + desc = "An apron designed by the space faring species that can hold an array of tools and other trinkets. It's made with a high-quality material." + icon_state = "apron_altevian" + item_state_slots = list(slot_r_hand_str = null, slot_l_hand_str = null) + //Captain /obj/item/clothing/suit/captunic name = "site manager's parade tunic" diff --git a/code/modules/clothing/under/altevian_vr.dm b/code/modules/clothing/under/altevian_vr.dm index 51f3bbef3b..89c44205f9 100644 --- a/code/modules/clothing/under/altevian_vr.dm +++ b/code/modules/clothing/under/altevian_vr.dm @@ -44,3 +44,32 @@ icon_state = "altevian-pants-cargo" worn_state = "altevian-pants-cargo" starting_accessories = list(/obj/item/clothing/accessory/jacket/altevian/cargo) + +/obj/item/clothing/under/altevian + name = "Altevian Duty Jumpsuit" + desc = "A uniform commonly seen from altevians during their work. The material on this uniform seems to be made of durable thread that can handle the stress of most matters of labor." + icon = 'icons/inventory/uniform/item_vr.dmi' + icon_override = 'icons/inventory/uniform/mob_vr.dmi' + icon_state = "altevian-specialist" + worn_state = "altevian-specialist" + species_restricted = list(SPECIES_ALTEVIAN) + +/obj/item/clothing/under/altevian/sci + name = "Altevian Science Duty Jumpsuit" + icon_state = "altevian-specialist-sci" + worn_state = "altevian-specialist-sci" + +/obj/item/clothing/under/altevian/med + name = "Altevian Medical Duty Jumpsuit" + icon_state = "altevian-specialist-med" + worn_state = "altevian-specialist-med" + +/obj/item/clothing/under/altevian/sec + name = "Altevian Security Duty Jumpsuit" + icon_state = "altevian-specialist-sec" + worn_state = "altevian-specialist-sec" + +/obj/item/clothing/under/altevian/eng + name = "Altevian Engineering Duty Jumpsuit" + icon_state = "altevian-specialist-eng" + worn_state = "altevian-specialist-eng" \ No newline at end of file diff --git a/code/modules/economy/vending_machines.dm b/code/modules/economy/vending_machines.dm index 1984cc8154..97a6ed2aa6 100644 --- a/code/modules/economy/vending_machines.dm +++ b/code/modules/economy/vending_machines.dm @@ -47,17 +47,21 @@ /obj/item/weapon/reagent_containers/food/drinks/glass2/shot = 10, /obj/item/weapon/reagent_containers/food/drinks/glass2/pint = 10, /obj/item/weapon/reagent_containers/food/drinks/glass2/mug = 10, - /obj/item/weapon/reagent_containers/food/drinks/glass2/wine = 10, /obj/item/weapon/reagent_containers/food/drinks/glass2/carafe = 2, //VOREStation Add - Carafes and Pitchers /obj/item/weapon/reagent_containers/food/drinks/glass2/pitcher = 2, //VOREStation Add - Carafes and Pitchers + /obj/item/weapon/reagent_containers/food/drinks/glass2/wine = 10, + /obj/item/weapon/reagent_containers/food/drinks/bottle/whitewine = 5, + /obj/item/weapon/reagent_containers/food/drinks/bottle/grapejuice = 5, /obj/item/weapon/reagent_containers/food/drinks/metaglass = 10, /obj/item/weapon/reagent_containers/food/drinks/metaglass/metapint = 10, + /obj/item/weapon/reagent_containers/glass/beaker/stopperedbottle = 10, /obj/item/weapon/reagent_containers/food/drinks/bottle/gin = 5, /obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe = 5, /obj/item/weapon/reagent_containers/food/drinks/bottle/bluecuracao = 5, /obj/item/weapon/reagent_containers/food/drinks/bottle/cognac = 5, /obj/item/weapon/reagent_containers/food/drinks/bottle/grenadine = 5, /obj/item/weapon/reagent_containers/food/condiment/cookingoil = 5, + /obj/item/weapon/reagent_containers/food/condiment/cornoil = 5, /obj/item/weapon/reagent_containers/food/drinks/bottle/kahlua = 5, /obj/item/weapon/reagent_containers/food/drinks/bottle/melonliquor = 5, /obj/item/weapon/reagent_containers/food/drinks/bottle/peppermintschnapps = 5, @@ -70,8 +74,6 @@ /obj/item/weapon/reagent_containers/food/drinks/bottle/vermouth = 5, /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka = 5, /obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey = 5, - /obj/item/weapon/reagent_containers/food/drinks/bottle/wine = 5, - /obj/item/weapon/reagent_containers/food/drinks/bottle/whitewine = 5, /obj/item/weapon/reagent_containers/food/drinks/bottle/grapejuice = 5, /obj/item/weapon/reagent_containers/food/drinks/bottle/jager = 5, /obj/item/weapon/reagent_containers/food/drinks/bottle/small/ale = 15, diff --git a/code/modules/economy/vending_machines_vr.dm b/code/modules/economy/vending_machines_vr.dm index dbe287f9df..668208216b 100644 --- a/code/modules/economy/vending_machines_vr.dm +++ b/code/modules/economy/vending_machines_vr.dm @@ -3548,8 +3548,14 @@ product_ads = "Perfectly edible!;Squeaky clean foods!;Cheesed to meet you!;Made for spacers, by spacers, of spacers!" products = list(/obj/item/weapon/reagent_containers/food/snacks/ratprotein = 15, /obj/item/weapon/reagent_containers/food/snacks/ratveggies = 15, - /obj/item/weapon/reagent_containers/food/snacks/ratliquid = 15) + /obj/item/weapon/reagent_containers/food/snacks/ratliquid = 15, + /obj/item/weapon/reagent_containers/food/snacks/ratfruitcake = 15, + /obj/item/weapon/reagent_containers/food/snacks/ratpackburger = 8, + /obj/item/weapon/reagent_containers/food/snacks/ratpackcheese = 8) prices = list(/obj/item/weapon/reagent_containers/food/snacks/ratprotein = 8, /obj/item/weapon/reagent_containers/food/snacks/ratveggies = 8, - /obj/item/weapon/reagent_containers/food/snacks/ratliquid = 8) + /obj/item/weapon/reagent_containers/food/snacks/ratliquid = 8, + /obj/item/weapon/reagent_containers/food/snacks/ratfruitcake = 8, + /obj/item/weapon/reagent_containers/food/snacks/ratpackburger = 10, + /obj/item/weapon/reagent_containers/food/snacks/ratpackcheese = 10) diff --git a/code/modules/economy/vending_refills.dm b/code/modules/economy/vending_refills.dm index 7e8547ca19..9b35de8c2a 100644 --- a/code/modules/economy/vending_refills.dm +++ b/code/modules/economy/vending_refills.dm @@ -49,7 +49,6 @@ icon_state = "rc_food" refill_type = list(/obj/machinery/vending/snack, /obj/machinery/vending/fitness, - /obj/machinery/vending/hotfood, /obj/machinery/vending/weeb, /obj/machinery/vending/sol, /obj/machinery/vending/snix, @@ -104,9 +103,6 @@ /obj/item/weapon/refill_cartridge/autoname/food/fitness refill_type = /obj/machinery/vending/fitness -/obj/item/weapon/refill_cartridge/autoname/food/hotfood - refill_type = /obj/machinery/vending/hotfood - /obj/item/weapon/refill_cartridge/autoname/food/weeb refill_type = /obj/machinery/vending/weeb diff --git a/code/modules/events/prison_break.dm b/code/modules/events/prison_break.dm index f2675a0ede..d5eb151d3f 100644 --- a/code/modules/events/prison_break.dm +++ b/code/modules/events/prison_break.dm @@ -64,7 +64,7 @@ var/obj/machinery/power/apc/theAPC = null for(var/area/A in areas) theAPC = A.get_apc() - if(theAPC.operating) //If the apc's off, it's a little hard to overload the lights. + if(theAPC && theAPC.operating) //If the apc's off, it's a little hard to overload the lights. for(var/obj/machinery/light/L in A) L.flicker(10) diff --git a/code/modules/examine/descriptions/devices.dm b/code/modules/examine/descriptions/devices.dm index 7b5c0019a4..a929873e0f 100644 --- a/code/modules/examine/descriptions/devices.dm +++ b/code/modules/examine/descriptions/devices.dm @@ -29,4 +29,18 @@ /obj/item/device/assembly/electronic_assembly description_info = "This is the casing for the 'device' type of electronic assembly. It behaves like any other 'assembly' type device such as an igniter or signaler \ - and can be attached to others in the same way. Use the 'toggle-open' verb (right click) or a crowbar to pop the electronic device open to add components and close when finished." \ No newline at end of file + and can be attached to others in the same way. Use the 'toggle-open' verb (right click) or a crowbar to pop the electronic device open to add components and close when finished." + +/obj/item/device/personal_shield_generator + description_info = "This is a personal shield generator. Depending on the type, it can either be worn on your backpack slot, your belt slot, or in a rigsuit \ + storage slot. It runs on an internal battery, which is usually self-charging. Some versions come with a gun. To active the shield, click the button in the upper \ + right of the screen, use the 'Toggle Shield' command under your objects tab, or click the device itself while it is on you. Some units come with an active weapon \ + which can be taken out at any time by Alt-clicking the device. If the device requires a cell, a screwdriver can be used. The shield slowly drains charge while \ + active and becomes weaker with each individual strike taken. Additonally, the device can be colored via use of a multitool." + + description_fluff = "A relatively new invention, made in a collaboration between Hephaestus Industries and a startup known as Kuznetsova Enterprise in the year \ + 2322. Numerous variants of the device have been made for specific tasks, ranging from riot control, mining, biohazard containment, and search and rescue, among \ + others. Most of the devices share the flaw that electrical attacks can easily overload the device and cause a shield failure, encouraging combatants to swap to \ + the use of stun-based electric weaponry when shield generators are in use. Most shield devices are self-charging, running off a micro-nuclear reactor built into \ + the chassis itself, although some variants exist without this capability and can have normal cells inserted into them. Larger units boast the capability of \ + storing a weapon, although without upgraded batteries the usage of said weapon is ill-advised." \ No newline at end of file diff --git a/code/modules/food/food/drinks/bottle.dm b/code/modules/food/food/drinks/bottle.dm index df16e4960b..9dcd17c256 100644 --- a/code/modules/food/food/drinks/bottle.dm +++ b/code/modules/food/food/drinks/bottle.dm @@ -12,6 +12,7 @@ var/obj/item/weapon/reagent_containers/glass/rag/rag = null var/rag_underlay = "rag" + var/violent_throw = FALSE /obj/item/weapon/reagent_containers/food/drinks/bottle/on_reagent_change() return // To suppress price updating. Bottles have their own price tags. @@ -29,18 +30,26 @@ return ..() //when thrown on impact, bottles smash and spill their contents +/obj/item/weapon/reagent_containers/food/drinks/bottle/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, datum/callback/callback) + . = ..() + if(istype(thrower) && thrower.a_intent == I_HURT) + violent_throw = TRUE + throw_source = get_turf(thrower) + /obj/item/weapon/reagent_containers/food/drinks/bottle/throw_impact(atom/hit_atom, var/speed) ..() - var/mob/M = thrower - if(isGlass && istype(M) && M.a_intent == I_HURT) + if(isGlass && violent_throw) var/throw_dist = get_dist(throw_source, loc) - if(speed >= throw_speed && smash_check(throw_dist)) //not as reliable as smashing directly + if(smash_check(throw_dist)) //not as reliable as smashing directly if(reagents) hit_atom.visible_message("The contents of \the [src] splash all over [hit_atom]!") reagents.splash(hit_atom, reagents.total_volume) src.smash(loc, hit_atom) + violent_throw = FALSE + throw_source = null + /obj/item/weapon/reagent_containers/food/drinks/bottle/proc/smash_check(var/distance) if(!isGlass || !smash_duration) return 0 diff --git a/code/modules/food/food/snacks.dm b/code/modules/food/food/snacks.dm index 11d7a172dc..ad34247ece 100644 --- a/code/modules/food/food/snacks.dm +++ b/code/modules/food/food/snacks.dm @@ -34,6 +34,8 @@ var/package_trash /// Packaged meals switch to this state when opened, if set var/package_open_state + /// Packaged meals that have opening animation + var/package_opening_state /// If this is canned. If true, it will print a message and ask you to open it var/canned = FALSE @@ -269,6 +271,8 @@ user.put_in_hands(T) if(package_open_state) icon_state = package_open_state + if(package_opening_state) + flick(package_opening_state, src) /obj/item/weapon/reagent_containers/food/snacks/proc/uncan(mob/user) canned = FALSE @@ -6897,7 +6901,7 @@ nutriment_desc = list("apple" = 1, "sweetness" = 1) bitesize = 2 -/obj/item/weapon/reagent_containers/food/snacks/appleberry/Initialize() +/obj/item/weapon/reagent_containers/food/snacks/canned/appleberry/Initialize() . = ..() reagents.add_reagent("milk", 8) reagents.add_reagent("sugar", 5) diff --git a/code/modules/food/food/snacks_vr.dm b/code/modules/food/food/snacks_vr.dm index 23935f6207..b1e3e878c2 100644 --- a/code/modules/food/food/snacks_vr.dm +++ b/code/modules/food/food/snacks_vr.dm @@ -773,7 +773,7 @@ /obj/item/weapon/reagent_containers/food/snacks/donkpocket/ascended/Initialize() . = ..() reagents.add_reagent("uranium", 3) - reagents.add_reagent("pyrotoxin", 3) + reagents.add_reagent("thermite_v", 3) // Altevian Foobs @@ -826,3 +826,38 @@ /obj/item/weapon/reagent_containers/food/snacks/ratsteak/Initialize() . = ..() reagents.add_reagent("protein", 3) + +/obj/item/weapon/reagent_containers/food/snacks/ratfruitcake + name = "Premade Fruit Block" + desc = "A block of processed material that is infused with a mix of fruits and matter of such." + icon = 'icons/obj/food_vr.dmi' + icon_state = "altevian_fruitcake" + package_open_state = "altevian_fruitcake-open" + package = TRUE + trash = /obj/item/trash/ratfruitcake + nutriment_amt = 2 + nutriment_desc = list("fruitiness" = 4) + +/obj/item/weapon/reagent_containers/food/snacks/ratpackburger + name = "Altevian Prepackaged Meal - Burger" + desc = "A unique twist on what most know as MREs. This seems to be made with using bluespace tech and other methods of preserving an items freshness that it's like someone just ordered this from a restaurant just minutes ago. This one seems to be of burger and fries!" + icon = 'icons/obj/food_vr.dmi' + icon_state = "altevian_pack_burger" + package_open_state = "altevian_pack_burger-open" + package_opening_state = "altevian_pack_burger-opening" + package = TRUE + trash = /obj/item/trash/ratpackburger + nutriment_amt = 2 + nutriment_desc = list("fresh buns" = 2, "burger patty" = 4, "pickles" = 1) + +/obj/item/weapon/reagent_containers/food/snacks/ratpackcheese + name = "Generations Novelty Packaged Wedge" + desc = "Using the popular method of packaging that altevians use, they seemed to also use it for other methods. This one appears to have no real markings on it, save for its different coloring, and an image of the altevian emblem." + icon = 'icons/obj/food_vr.dmi' + icon_state = "altevian_pack_cheese" + package_open_state = "altevian_pack_cheese-open" + package_opening_state = "altevian_pack_cheese-opening" + package = TRUE + trash = /obj/item/trash/ratpackcheese + nutriment_amt = 2 + nutriment_desc = list("gourmand cheese" = 4) diff --git a/code/modules/games/cards.dm b/code/modules/games/cards.dm index 52ad80641a..c3f1a6dc3e 100644 --- a/code/modules/games/cards.dm +++ b/code/modules/games/cards.dm @@ -400,11 +400,13 @@ /obj/item/weapon/hand/update_icon(var/direction = 0) - if(!cards.len) + var/cardNumber = cards.len + + if(!cardNumber) qdel(src) return - else if(cards.len > 1) - name = "hand of cards" + else if(cardNumber > 1) + name = "hand of cards ([cardNumber])" desc = "Some playing cards." else name = "a playing card" @@ -413,7 +415,7 @@ cut_overlays() - if(cards.len == 1) + if(cardNumber == 1) var/datum/playingcard/P = cards[1] var/image/I = new(src.icon, (concealed ? "[P.back_icon]" : "[P.card_icon]") ) I.pixel_x += (-5+rand(10)) @@ -421,7 +423,7 @@ add_overlay(I) return - var/offset = FLOOR(20/cards.len, 1) + var/offset = FLOOR(20/cardNumber, 1) var/matrix/M = matrix() if(direction) @@ -453,6 +455,7 @@ add_overlay(I) i++ + /obj/item/weapon/hand/dropped(mob/user as mob) if(locate(/obj/structure/table, loc)) src.update_icon(user.dir) diff --git a/code/modules/holodeck/HolodeckObjects.dm b/code/modules/holodeck/HolodeckObjects.dm index c8b324d6f4..cf2a19f46a 100644 --- a/code/modules/holodeck/HolodeckObjects.dm +++ b/code/modules/holodeck/HolodeckObjects.dm @@ -4,6 +4,7 @@ // Holographic racks are in code/modules/tables/rack.dm /turf/simulated/floor/holofloor + desc = "A convincing simulation." thermal_conductivity = 0 flags = TURF_ACID_IMMUNE @@ -281,6 +282,7 @@ no_random_knockdown = TRUE /obj/item/weapon/holo/esword + name = "holographic energy sword" desc = "May the force be within you. Sorta." icon_state = "esword" var/lcolor diff --git a/code/modules/materials/fifty_spawner_mats.dm b/code/modules/materials/fifty_spawner_mats.dm index 6ba191522f..e7e850a916 100644 --- a/code/modules/materials/fifty_spawner_mats.dm +++ b/code/modules/materials/fifty_spawner_mats.dm @@ -12,6 +12,10 @@ name = "stack of marble" type_to_spawn = /obj/item/stack/material/marble +/obj/fiftyspawner/concrete + name = "stack of concrete" + type_to_spawn = /obj/item/stack/material/concrete + /obj/fiftyspawner/diamond name = "stack of diamond" type_to_spawn = /obj/item/stack/material/diamond @@ -72,6 +76,10 @@ name = "stack of plasteel" type_to_spawn = /obj/item/stack/material/plasteel +/obj/fiftyspawner/plasteel/rebar + name = "stack of plasteel rebars" + type_to_spawn = /obj/item/stack/material/plasteel/rebar + /obj/fiftyspawner/plasteel/hull name = "stack of plasteel hull" type_to_spawn = /obj/item/stack/material/plasteel/hull diff --git a/code/modules/materials/materials/_materials.dm b/code/modules/materials/materials/_materials.dm index 168fd67938..99027a8de7 100644 --- a/code/modules/materials/materials/_materials.dm +++ b/code/modules/materials/materials/_materials.dm @@ -373,4 +373,7 @@ var/list/name_to_material new /datum/stack_recipe("[display_name] knife", /obj/item/weapon/material/knife/plastic, 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE), new /datum/stack_recipe("[display_name] blade", /obj/item/weapon/material/butterflyblade, 6, time = 20, one_per_turf = 0, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE), new /datum/stack_recipe("[display_name] defense wire", /obj/item/weapon/material/barbedwire, 10, time = 1 MINUTE, one_per_turf = 0, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE) - ) \ No newline at end of file + ) + +/datum/material/proc/get_wall_texture() + return diff --git a/code/modules/materials/materials/metals/plasteel.dm b/code/modules/materials/materials/metals/plasteel.dm index 8146980057..8ec47e84f2 100644 --- a/code/modules/materials/materials/metals/plasteel.dm +++ b/code/modules/materials/materials/metals/plasteel.dm @@ -24,8 +24,17 @@ new /datum/stack_recipe("dark floor tile", /obj/item/stack/tile/floor/dark, 1, 4, 20, recycle_material = "[name]"), new /datum/stack_recipe("roller bed", /obj/item/roller, 5, time = 30, on_floor = 1, recycle_material = "[name]"), new /datum/stack_recipe("whetstone", /obj/item/weapon/whetstone, 2, time = 10, recycle_material = "[name]"), + new /datum/stack_recipe("plasteel rebar", /obj/item/stack/material/plasteel/rebar, 1, time = 5, recycle_material = "[name]"), new /datum/stack_recipe_list("reinforced low walls",list( new /datum/stack_recipe("reinforced low wall (bay style)", /obj/structure/low_wall/bay/reinforced, 3, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", recycle_material = "[name]"), new /datum/stack_recipe("reinforced low wall (eris style)", /obj/structure/low_wall/eris/reinforced, 3, one_per_turf = 1, on_floor = 1, supplied_material = "[name]", recycle_material = "[name]") )), - ) \ No newline at end of file + ) + +/datum/material/plasteel/rebar //to give a different reinforced overlay + name = MAT_PLASTEELREBAR + icon_reinf = "reinf_metal" + icon_colour = "#6A6A6A" + stack_type = /obj/item/stack/material/plasteel/rebar + sheet_singular_name = "rod" + sheet_plural_name = "rods" diff --git a/code/modules/materials/materials/metals/steel.dm b/code/modules/materials/materials/metals/steel.dm index cc6a58792a..99afcd385d 100644 --- a/code/modules/materials/materials/metals/steel.dm +++ b/code/modules/materials/materials/metals/steel.dm @@ -15,19 +15,19 @@ new /datum/stack_recipe("dark office chair", /obj/structure/bed/chair/office/dark, 5, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"), new /datum/stack_recipe("light office chair", /obj/structure/bed/chair/office/light, 5, one_per_turf = 1, on_floor = 1, recycle_material = "[name]") )), - new /datum/stack_recipe_list("comfy chairs", list( - new /datum/stack_recipe("beige comfy chair", /obj/structure/bed/chair/comfy/beige, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"), - new /datum/stack_recipe("black comfy chair", /obj/structure/bed/chair/comfy/black, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"), - new /datum/stack_recipe("brown comfy chair", /obj/structure/bed/chair/comfy/brown, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"), - new /datum/stack_recipe("lime comfy chair", /obj/structure/bed/chair/comfy/lime, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"), - new /datum/stack_recipe("teal comfy chair", /obj/structure/bed/chair/comfy/teal, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"), - new /datum/stack_recipe("red comfy chair", /obj/structure/bed/chair/comfy/red, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"), - new /datum/stack_recipe("blue comfy chair", /obj/structure/bed/chair/comfy/blue, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"), - new /datum/stack_recipe("purple comfy chair", /obj/structure/bed/chair/comfy/purp, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"), - new /datum/stack_recipe("green comfy chair", /obj/structure/bed/chair/comfy/green, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"), - new /datum/stack_recipe("yellow comfy chair", /obj/structure/bed/chair/comfy/yellow, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"), - new /datum/stack_recipe("orange comfy chair", /obj/structure/bed/chair/comfy/orange, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"), - )), + new /datum/stack_recipe_list("rounded chairs", list( + new /datum/stack_recipe("beige rounded chair", /obj/structure/bed/chair/comfy/rounded/beige, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"), + new /datum/stack_recipe("black rounded chair", /obj/structure/bed/chair/comfy/rounded/black, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"), + new /datum/stack_recipe("brown rounded chair", /obj/structure/bed/chair/comfy/rounded/brown, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"), + new /datum/stack_recipe("lime rounded chair", /obj/structure/bed/chair/comfy/rounded/lime, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"), + new /datum/stack_recipe("teal rounded chair", /obj/structure/bed/chair/comfy/rounded/teal, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"), + new /datum/stack_recipe("red rounded chair", /obj/structure/bed/chair/comfy/rounded/red, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"), + new /datum/stack_recipe("blue rounded chair", /obj/structure/bed/chair/comfy/rounded/blue, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"), + new /datum/stack_recipe("purple rounded chair", /obj/structure/bed/chair/comfy/rounded/purple, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"), + new /datum/stack_recipe("green rounded chair", /obj/structure/bed/chair/comfy/rounded/green, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"), + new /datum/stack_recipe("yellow rounded chair", /obj/structure/bed/chair/comfy/rounded/yellow, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"), + new /datum/stack_recipe("orange rounded chair", /obj/structure/bed/chair/comfy/rounded/orange, 2, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"), + )), new /datum/stack_recipe_list("airlock assemblies", list( new /datum/stack_recipe("standard airlock assembly", /obj/structure/door_assembly, 4, time = 50, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"), new /datum/stack_recipe("command airlock assembly", /obj/structure/door_assembly/door_assembly_com, 4, time = 50, one_per_turf = 1, on_floor = 1, recycle_material = "[name]"), @@ -86,4 +86,4 @@ new /datum/stack_recipe("apc frame", /obj/item/frame/apc, 2, recycle_material = "[name]"), new /datum/stack_recipe("desk bell", /obj/item/weapon/deskbell, 1, on_floor = 1, supplied_material = "[name]"), new /datum/stack_recipe("tanning rack", /obj/structure/tanning_rack, 3, one_per_turf = TRUE, time = 20, on_floor = TRUE, supplied_material = "[name]") - ) \ No newline at end of file + ) diff --git a/code/modules/materials/materials/stone.dm b/code/modules/materials/materials/stone.dm index 340f7d0dec..486d812c87 100644 --- a/code/modules/materials/materials/stone.dm +++ b/code/modules/materials/materials/stone.dm @@ -39,7 +39,7 @@ icon_colour = "#9e9c99" weight = 20 hardness = 30 - integrity = 100 + integrity = 100 stack_type = /obj/item/stack/material/flint supply_conversion_value = 2 sheet_singular_name = "piece" @@ -47,4 +47,35 @@ /datum/material/stone/flint/generate_recipes() return -//VOREStation Addition End +//VOREStation Addition End + +/datum/material/stone/concrete + name = MAT_CONCRETE + stack_type = /obj/item/stack/material/concrete + icon_base = "brick" + icon_colour = COLOR_GRAY + integrity = 150 + melting_point = 1550 + protectiveness = 10 + weight = 27 + hardness = 60 + var/image/texture + +/datum/material/stone/concrete/generate_recipes() + ..() + recipes += list( + new /datum/stack_recipe_list("Concrete Pathing",list( + new /datum/stack_recipe("Concrete Flooring", /obj/item/stack/tile/floor/concrete, 1, 4, 20, recycle_material = "[name]"), + new /datum/stack_recipe("Concrete Sidewalk", /obj/item/stack/tile/floor/sidewalk, 1, 4, 20, recycle_material = "[name]"), + new /datum/stack_recipe("Concrete Sidewalk (Side)", /obj/item/stack/tile/floor/sidewalk/side, 1, 4, 20, recycle_material = "[name]"), + new /datum/stack_recipe("Concrete Sidewalk (Slab)", /obj/item/stack/tile/floor/sidewalk/slab, 1, 4, 20, recycle_material = "[name]") + )), + ) + +/datum/material/stone/concrete/New() + . = ..() + texture = image('icons/turf/wall_texture.dmi', "concrete") + texture.blend_mode = BLEND_MULTIPLY + +/datum/material/stone/concrete/get_wall_texture() + return texture diff --git a/code/modules/materials/sheets/metals/metal.dm b/code/modules/materials/sheets/metals/metal.dm index 256f80696b..9c999f73f0 100644 --- a/code/modules/materials/sheets/metals/metal.dm +++ b/code/modules/materials/sheets/metals/metal.dm @@ -12,6 +12,19 @@ no_variants = FALSE apply_colour = TRUE +/obj/item/stack/material/plasteel/rebar + name = MAT_PLASTEELREBAR + icon_state = "rods" + default_type = MAT_PLASTEELREBAR + apply_colour = 1 + +/obj/item/stack/material/plasteel/rebar/update_icon() + var/amount = get_amount() + if((amount <= 5) && (amount > 0)) + icon_state = "rods-[amount]" + else + icon_state = "rods" + /obj/item/stack/material/durasteel name = "durasteel" icon_state = "sheet-durasteel" //CHOMPedit - replace materials update diff --git a/code/modules/materials/sheets/stone.dm b/code/modules/materials/sheets/stone.dm index e7c5593f67..c30766cda4 100644 --- a/code/modules/materials/sheets/stone.dm +++ b/code/modules/materials/sheets/stone.dm @@ -22,4 +22,11 @@ drop_sound = 'sound/items/drop/boots.ogg' pickup_sound = 'sound/items/pickup/boots.ogg' pass_color = TRUE - apply_colour = TRUE + apply_colour = TRUE + +/obj/item/stack/material/concrete + name = "concrete brick" + icon_state = "brick" + default_type = "concrete" + no_variants = FALSE + apply_colour = 1 diff --git a/code/modules/mining/abandonedcrates.dm b/code/modules/mining/abandonedcrates.dm index d6e72e4e33..cf595a0821 100644 --- a/code/modules/mining/abandonedcrates.dm +++ b/code/modules/mining/abandonedcrates.dm @@ -19,7 +19,7 @@ generate_loot() /obj/structure/closet/crate/secure/loot/proc/generate_loot() - var/loot = rand(1, 99) + var/loot = rand(1, 100) switch(loot) if(1 to 5) // Common things go, 5% new/obj/item/weapon/reagent_containers/food/drinks/bottle/rum(src) @@ -140,6 +140,8 @@ if(99) new/obj/item/weapon/storage/belt/champion(src) new/obj/item/clothing/mask/luchador(src) + if(100) + new/obj/item/device/personal_shield_generator/belt/mining/loaded(src) /obj/structure/closet/crate/secure/loot/togglelock(mob/user as mob) if(!locked) diff --git a/code/modules/mining/ore_redemption_machine/equipment_vendor.dm b/code/modules/mining/ore_redemption_machine/equipment_vendor.dm index 2f8ab107ed..6dd1f84f37 100644 --- a/code/modules/mining/ore_redemption_machine/equipment_vendor.dm +++ b/code/modules/mining/ore_redemption_machine/equipment_vendor.dm @@ -126,6 +126,7 @@ EQUIPMENT("Thalers - 1000", /obj/item/weapon/spacecash/c1000, 10000), EQUIPMENT("Umbrella", /obj/item/weapon/melee/umbrella/random, 200), EQUIPMENT("Whiskey", /obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey, 125), + EQUIPMENT("Mining PSG Upgrade Disk", /obj/item/borg/upgrade/shield_upgrade, 2500), ) prize_list["Extra"] = list() // Used in child vendors //VOREStation Edit End diff --git a/code/modules/mob/_modifiers/modifiers_vr.dm b/code/modules/mob/_modifiers/modifiers_vr.dm index a56bc5d2e0..2de03120d4 100644 --- a/code/modules/mob/_modifiers/modifiers_vr.dm +++ b/code/modules/mob/_modifiers/modifiers_vr.dm @@ -1,3 +1,51 @@ +/datum/modifier + var/effect_color // Allows for coloring of modifiers. + var/coloration_applied = 0 // Tells the game is coloration has been applied already or not. + var/icon_override = 0 // Tells the game if it should use modifer_effects_vr.dmi or not. + // ENERGY CODE. Variables to allow for energy based modifiers. + var/energy_based // Sees if the modifier is based on something electronic based. + var/energy_cost // How much the modifier uses per action/special effect blocked. For base values. + var/damage_cost // How much energy is used when numbers are involed. For values, such as taking damage. Ex: (Damage*damage_cost) + var/obj/item/weapon/cell/energy_source = null // The source of the above. + + // RESISTANCES CODE. Variable to enable external damage resistance modifiers. This is not unlike armor. + // 0 = immune || < 0 = heals || 1 = full damage || >1 = increased damage. + // It should never be below zero as it is not intended to do such, but you are free to experiment! + // Ex: Max_brute_resistance = 0. Min_brute resistance = 1. When started, provides 100% resistance to brute. When cell is dying, goes down to 0% resistance. + // Max is the MAXIMUM % multiplier that will be taken at a MAX charge. Min is the MINIMUM % multiplier that will be taken at a MINIMUM charge. + // Think of it like this: Minimum = what happens at minimum charge. Max = what happens at maximum charge. + // Why do I mention this so much? Because even /I/ got confused, and I wrote this thing! + var/min_damage_resistance + var/max_damage_resistance + var/effective_damage_resistance + + var/min_brute_resistance + var/max_brute_resistance + var/effective_brute_resistance + + var/min_fire_resistance + var/max_fire_resistance + var/effective_fire_resistance + + var/min_tox_resistance + var/max_tox_resistance + var/effective_tox_resistance + + var/min_oxy_resistance + var/max_oxy_resistance + var/effective_oxy_resistance + + var/min_clone_resistance + var/max_clone_resistance + var/effective_clone_resistance + + var/min_hal_resistance + var/max_hal_resistance + var/effective_hal_resistance + // Resistances end + + + /datum/modifier/underwater_stealth name = "underwater stealth" desc = "You are currently underwater, rendering it more difficult to see you and enabling you to move quicker, thanks to your aquatic nature." @@ -30,4 +78,258 @@ if(water_floor.depth < 1) //You're not in deep enough water anymore. expire(silent = FALSE) else - expire(silent = FALSE) \ No newline at end of file + expire(silent = FALSE) + + + + + + + + + +/datum/modifier/shield_projection + name = "Shield Projection" + desc = "You are currently protected by a shield, rendering nigh impossible to hit you through conventional means." + + on_created_text = "Your shield generator buzzes on." + on_expired_text = "Your shield generator buzzes off." + stacks = MODIFIER_STACK_FORBID //No stacking shields. If you put one one your belt and backpack it won't work. + + icon_override = 1 + mob_overlay_state = "deflect" + siemens_coefficient = 2 //Stun weapons drain 100% charge per point of damage. They're good at blocking lasers and bullets but not good at blocking stun beams! + energy_based = 1 + energy_cost = 99999 //This is changed to the shield_generator's energy_cost. + damage_cost = 50 //This is how much battery is used per damage unit absorbed. Higher damage means higher charge use per damage absorbed. Changed below! + + //Not actually in use until effective resistances are set. Just here so it doesn't have to be placed down for all the variants. Less lines. + max_damage_resistance = 1 + max_brute_resistance = 1 + max_fire_resistance = 1 + max_tox_resistance = 1 + max_oxy_resistance = 1 + max_clone_resistance = 1 + max_hal_resistance = 1 + min_damage_resistance = 1 + min_brute_resistance = 1 + min_fire_resistance = 1 + min_tox_resistance = 1 + min_oxy_resistance = 1 + min_clone_resistance = 1 + min_hal_resistance = 1 + +/* // These are not set, but left here as an example. All three (min,max,effective) must be set or BAD THINGS will happen. + min_brute_resistance = 1 // Min = WHAT HAPPENS AT MINIMUM CHARGE + max_brute_resistance = 0 // MAX = WHAT HAPPENS AT MAXIMUM CHARGE + effective_brute_resistance = 1 //Just tells the game that it has vars. Done to use less checks. + + min_fire_resistance = 1 + max_fire_resistance = 0 + effective_fire_resistance = 1 + disable_duration_percent = 1 //THIS CAN ALSO BE USED! Don't be too afraid to use this one, but use it sparingly! +*/ + var/obj/item/device/personal_shield_generator/shield_generator //This is the shield generator you're wearing! + + +/datum/modifier/shield_projection/on_applied() + return + +/datum/modifier/shield_projection/on_expire() //Don't need to modify this! + return + +/datum/modifier/shield_projection/check_if_valid() //Let's check to make sure you got the stuff and set the vars. Don't need to modify this for any subtypes! + if(ishuman(holder)) //Only humans can use this! Other things later down the line might use the same stuff this does, but the shield generator is human only! + var/mob/living/carbon/human/H = holder + if(istype(H.get_equipped_item(slot_back), /obj/item/device/personal_shield_generator)) + shield_generator = H.get_equipped_item(slot_back) //Sets the var on the modifier that the shield gen is their back shield gen. + else if(istype(H.get_equipped_item(slot_belt), /obj/item/device/personal_shield_generator)) + shield_generator = H.get_equipped_item(slot_belt) //No need for other checks. If they got hit by this, they just turned it on. + else if(istype(H.get_equipped_item(slot_s_store), /obj/item/device/personal_shield_generator) ) //Rigsuits. + shield_generator = H.get_equipped_item(slot_s_store) + else + expire(silent = TRUE) + if(shield_generator) //Sanity. + energy_source = shield_generator.bcell + energy_cost = shield_generator.generator_hit_cost + damage_cost = shield_generator.damage_cost + effect_color = shield_generator.effect_color + if(!coloration_applied) //Does a check if colors have been applied. If not, updates the color. + H.update_modifier_visuals() //This can only happen on the next tick, unfortunately, not the same tick the modifier is applied. Thus, must be done here. + coloration_applied = 1 + else + expire(silent = TRUE) + + +/datum/modifier/shield_projection/tick() //When the shield generator runs out of charge, it'll remove this naturally. + if(holder.stat == DEAD) + expire(silent = TRUE) //If you're dead the generator stops protecting you but keeps running. + if(!shield_generator || !shield_generator.slot_check()) //No shield to begin with/shield is not on them any longer. + expire(silent = FALSE) + + var/shield_efficiency = (energy_source.charge/energy_source.maxcharge) //1 = complete resistance. 0 = no resistance. Must be adjusted for subtypes! + if(!isnull(effective_damage_resistance)) + effective_damage_resistance = min_damage_resistance + (max_damage_resistance - min_damage_resistance) * shield_efficiency + + if(!isnull(effective_brute_resistance)) + effective_brute_resistance = min_brute_resistance + (max_brute_resistance - min_brute_resistance) * shield_efficiency + + if(!isnull(effective_fire_resistance)) + effective_fire_resistance = min_fire_resistance + (max_fire_resistance - min_fire_resistance) * shield_efficiency + + if(!isnull(effective_tox_resistance)) + effective_tox_resistance = min_tox_resistance + (max_tox_resistance - min_tox_resistance) * shield_efficiency + + if(!isnull(effective_oxy_resistance)) + effective_oxy_resistance = min_oxy_resistance + (max_oxy_resistance - min_oxy_resistance) * shield_efficiency + + if(!isnull(effective_clone_resistance)) + effective_clone_resistance = min_clone_resistance + (max_clone_resistance - min_clone_resistance) * shield_efficiency + + if(!isnull(effective_hal_resistance)) + effective_hal_resistance = min_hal_resistance + (max_hal_resistance - min_hal_resistance) * shield_efficiency + +//Shield variants. + +//Simple. Goes from 100% resistance to 0% resistance depending on charge. This is mostly an example of a shield variant. +/datum/modifier/shield_projection/bruteburn + max_brute_resistance = 0 + effective_brute_resistance = 1 + + max_fire_resistance = 0 + effective_fire_resistance = 1 + +/datum/modifier/shield_projection/bruteburn/weak + max_brute_resistance = 0.5 + max_fire_resistance = 0.5 + +//SECURITY VARIANTS +/datum/modifier/shield_projection/security // Security backpack. 50% resistance at full charge. 10% resistance for the last shot taken. + max_brute_resistance = 0.50 + min_brute_resistance = 0.9 + effective_brute_resistance = 1 + + max_fire_resistance = 0.5 + min_fire_resistance = 0.9 + effective_fire_resistance = 1 + + max_hal_resistance = 0.5 + min_hal_resistance = 0.9 + effective_hal_resistance = 1 + + disable_duration_percent = 0.75 + +/datum/modifier/shield_projection/security/weak // Security belt. + max_brute_resistance = 0.75 + min_brute_resistance = 0.95 + max_fire_resistance = 0.75 + min_fire_resistance = 0.95 + max_hal_resistance = 0.75 + min_hal_resistance = 0.95 + +/datum/modifier/shield_projection/security/strong // Dunno. Upgraded variant of security backpack? + max_brute_resistance = 0.25 + max_fire_resistance = 0.25 + max_hal_resistance = 0.25 + siemens_coefficient = 1.5 //Not as weak as normal, but still weak. + disable_duration_percent = 0.5 + + +//MINING VARIANTS +/datum/modifier/shield_projection/mining //Base mining belt. 30% resistance that fades to 15% resistance + max_brute_resistance = 0.70 + min_brute_resistance = 0.85 + effective_brute_resistance = 1 + + max_fire_resistance = 0.70 + min_brute_resistance = 0.85 + effective_fire_resistance = 1 + + max_hal_resistance = 1.5 // No mobs should be shooting you with halloss. If this happens, it means you're using it wrong!!! + min_hal_resistance = 1.5 + effective_hal_resistance = 1 + + disable_duration_percent = 0.75 //Miners often come into contact with things that can stun them. + +/datum/modifier/shield_projection/mining/strong // Mining belt, but upgraded. Even weaker to halloss! + max_brute_resistance = 0.55 + min_brute_resistance = 0.75 + max_fire_resistance = 0.55 + min_fire_resistance = 0.75 + disable_duration_percent = 0.5 + + max_hal_resistance = 2 + min_hal_resistance = 2 + +//MISC VARIANTS + +/datum/modifier/shield_projection/biohazard //The odd-ball damage types. Provides near-complete immunity while it's up. + min_tox_resistance = 0.25 + max_tox_resistance = 0 + effective_tox_resistance = 1 + + min_oxy_resistance = 0.25 + max_oxy_resistance = 0 + effective_oxy_resistance = 1 + + min_clone_resistance = 0.25 + max_clone_resistance = 0 + effective_clone_resistance = 1 + +/datum/modifier/shield_projection/admin // Adminbus. + on_created_text = "Your shield generator activates and you feel the power of the tesla buzzing around you." + on_expired_text = "Your shield generator deactivates, leaving you feeling weak and vulnerable." + siemens_coefficient = 0 + disable_duration_percent = 0 + min_damage_resistance = 0 + max_damage_resistance = 0 + effective_damage_resistance = 0 + min_brute_resistance = 0 + max_brute_resistance = 0 + effective_brute_resistance = 0 + min_fire_resistance = 0 + max_fire_resistance = 0 + effective_fire_resistance = 0 + min_tox_resistance = 0 + max_tox_resistance = 0 + effective_tox_resistance = 0 + min_oxy_resistance = 0 + max_oxy_resistance = 0 + effective_oxy_resistance = 0 + min_clone_resistance = 0 + max_clone_resistance = 0 + effective_clone_resistance = 0 + min_hal_resistance = 0 + max_hal_resistance = 0 + effective_hal_resistance = 0 + +/datum/modifier/shield_projection/broken //For broken variants. Good if possible randomization is included for packs spawned on PoIs. + max_brute_resistance = 2 + min_brute_resistance = 2 + effective_brute_resistance = 1 + + max_fire_resistance = 2 + min_fire_resistance = 2 + effective_fire_resistance = 1 + +/datum/modifier/shield_projection/inverted //Becomes stronger the weaker the cell is. Means the last shot taken will be the weakest. Example just to show it can be done. + max_brute_resistance = 1 + min_brute_resistance = 0 + effective_brute_resistance = 1 + + max_fire_resistance = 1 + min_fire_resistance = 0 + effective_fire_resistance = 1 + +/datum/modifier/shield_projection/parry //Intended for 'parry' shields, which only last for a single second before running out of charge + max_brute_resistance = 0 + min_brute_resistance = 0 + effective_brute_resistance = 1 + + max_fire_resistance = 0 + min_fire_resistance = 0 + effective_fire_resistance = 1 + + max_hal_resistance = 0 + min_hal_resistance = 0 + effective_hal_resistance = 1 \ No newline at end of file diff --git a/code/modules/mob/dead/observer/free_vr.dm b/code/modules/mob/dead/observer/free_vr.dm index 2cfd6ad024..a3c63de197 100644 --- a/code/modules/mob/dead/observer/free_vr.dm +++ b/code/modules/mob/dead/observer/free_vr.dm @@ -18,7 +18,7 @@ var/global/list/prevent_respawns = list() //Why are you clicking this button? if(!mind || !mind.assigned_role) - to_chat(src,"Either you haven't played this round, or you already used this verb.") + to_chat(src,"Either you haven't played this round, you already used this verb or you left round properly already.") return //Add them to the nope list diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 1da2ae1081..622f539040 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -125,7 +125,7 @@ add_overlay(H.overlays_standing) default_pixel_x = body.default_pixel_x default_pixel_y = body.default_pixel_y - if(!T) + if(!T && length(latejoin)) T = pick(latejoin) //Safety in case we cannot find the body's position if(T) forceMove(T) diff --git a/code/modules/mob/living/bot/bot.dm b/code/modules/mob/living/bot/bot.dm index bec833476f..1d36c892cd 100644 --- a/code/modules/mob/living/bot/bot.dm +++ b/code/modules/mob/living/bot/bot.dm @@ -297,7 +297,8 @@ return /mob/living/bot/proc/handleFrustrated(var/targ) - obstacle = targ ? target_path[1] : patrol_path[1] + if((targ && LAZYLEN(target_path)) || LAZYLEN(patrol_path)) + obstacle = targ ? target_path[1] : patrol_path[1] target_path = list() patrol_path = list() return @@ -577,4 +578,4 @@ feeding = FALSE can_be_drop_pred = FALSE - return ..() \ No newline at end of file + return ..() diff --git a/code/modules/mob/living/carbon/human/death_vr.dm b/code/modules/mob/living/carbon/human/death_vr.dm index 24bae5c7c2..d29f660946 100644 --- a/code/modules/mob/living/carbon/human/death_vr.dm +++ b/code/modules/mob/living/carbon/human/death_vr.dm @@ -25,7 +25,7 @@ //Technically allows metagaming by allowing buddies to turn on digestion for like 2 seconds // to finish off critically wounded friends to avoid resleeving sickness, but like // *kill those people* ok? - if(B.digest_mode == DM_DIGEST) + if(B.digest_mode == DM_DIGEST || B.digest_mode == DM_SELECT) H.mind?.vore_death = TRUE //Hooks need to return true otherwise they're considered having failed diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index 645d563ad0..d8dda93705 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -115,8 +115,12 @@ if(amount > 0) for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_brute_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_brute_damage_percent if(nif && nif.flag_check(NIF_C_BRUTEARMOR,NIF_FLAGS_COMBAT)){amount *= 0.7} //VOREStation Edit - NIF mod for damage resistance for this type of damage take_overall_damage(amount, 0) @@ -133,8 +137,12 @@ if(amount > 0) for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_fire_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_fire_damage_percent if(nif && nif.flag_check(NIF_C_BURNARMOR,NIF_FLAGS_COMBAT)){amount *= 0.7} //VOREStation Edit - NIF mod for damage resistance for this type of damage take_overall_damage(0, amount) @@ -153,8 +161,12 @@ if(amount > 0) for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_brute_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_brute_damage_percent if(nif && nif.flag_check(NIF_C_BRUTEARMOR,NIF_FLAGS_COMBAT)){amount *= 0.7} //VOREStation Edit - NIF mod for damage resistance for this type of damage O.take_damage(amount, 0, sharp=is_sharp(damage_source), edge=has_edge(damage_source), used_weapon=damage_source) @@ -175,8 +187,12 @@ if(amount > 0) for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_fire_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_fire_damage_percent if(nif && nif.flag_check(NIF_C_BURNARMOR,NIF_FLAGS_COMBAT)){amount *= 0.7} //VOREStation Edit - NIF mod for damage resistance for this type of damage O.take_damage(0, amount, sharp=is_sharp(damage_source), edge=has_edge(damage_source), used_weapon=damage_source) @@ -485,6 +501,53 @@ This function restores all organs. if(!def_zone) def_zone = ran_zone(def_zone) organ = get_organ(check_zone(def_zone)) + for(var/datum/modifier/M in modifiers) //MODIFIER STUFF. It's best to do this RIGHT before armor is calculated, so it's done here! This is the 'forcefield' defence. + if(damagetype == BRUTE && (!isnull(M.effective_brute_resistance))) + if(M.energy_based) + M.energy_source.use(M.damage_cost * damage) + damage = damage * M.effective_brute_resistance + continue + if((damagetype == BURN || damagetype == ELECTROCUTE) && (!isnull(M.effective_fire_resistance))) + if(M.energy_based) + M.energy_source.use(M.damage_cost * damage) + damage = damage * M.effective_fire_resistance + continue + if(damagetype == TOX && (!isnull(M.effective_tox_resistance))) + if(M.energy_based) + M.energy_source.use(M.damage_cost * damage) + damage = damage * M.effective_tox_resistance + continue + if(damagetype == OXY && (!isnull(M.effective_oxy_resistance))) + if(M.energy_based) + M.energy_source.use(M.damage_cost * damage) + damage = damage * M.effective_oxy_resistance + continue + if(damagetype == CLONE && (!isnull(M.effective_clone_resistance))) + if(M.energy_based) + M.energy_source.use(M.damage_cost * damage) + damage = damage * M.effective_clone_resistance + continue + if(damagetype == HALLOSS && (!isnull(M.effective_hal_resistance))) + if(M.energy_based) + M.energy_source.use(M.damage_cost * damage) + damage = damage * M.effective_hal_resistance + continue + if(damagetype == SEARING && (!isnull(M.effective_fire_resistance) || !isnull(M.effective_brute_resistance))) + if(M.energy_based) + M.energy_source.use(M.damage_cost * damage) + var/damage_mitigation = 0//Used for dual calculations. + if(!isnull(M.effective_fire_resistance)) + damage_mitigation += round((1/3)*damage * M.effective_fire_resistance) + if(!isnull(M.effective_brute_resistance)) + damage_mitigation += round((2/3)*damage * M.effective_brute_resistance) + damage -= damage_mitigation + continue + if(damagetype == BIOACID && (isSynthetic() && (!isnull(M.effective_fire_resistance))) || (!isSynthetic() && M.effective_tox_resistance)) + if(isSynthetic()) + damage = damage * M.effective_fire_resistance + else + damage = damage * M.effective_tox_resistance + continue //Handle other types of damage if((damagetype != BRUTE) && (damagetype != BURN)) if(damagetype == HALLOSS) @@ -523,8 +586,12 @@ This function restores all organs. for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*damage) damage *= M.incoming_damage_percent if(!isnull(M.incoming_brute_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*damage) damage *= M.incoming_brute_damage_percent if(organ.take_damage(damage, 0, sharp, edge, used_weapon)) @@ -536,8 +603,12 @@ This function restores all organs. for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*damage) damage *= M.incoming_damage_percent if(!isnull(M.incoming_brute_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*damage) damage *= M.incoming_fire_damage_percent if(organ.take_damage(0, damage, sharp, edge, used_weapon)) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index f8c266a95b..7648908cc8 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -37,6 +37,18 @@ emp_act var/armor = getarmor_organ(organ, "bullet") if(!prob(armor/2)) //Even if the armor doesn't stop the bullet from hurting you, it might stop it from embedding. var/hit_embed_chance = P.embed_chance + (P.damage - armor) //More damage equals more chance to embed + + //Modifiers can make bullets less likely to embed! These are the normal modifiers and shouldn't be related to energy stuff, but they can be anyways! + for(var/datum/modifier/M in modifiers) + if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.energy_cost) //We use energy_cost here for special effects, such as embedding. + hit_embed_chance = hit_embed_chance*M.incoming_damage_percent + if(P.damage_type == BRUTE && (!isnull(M.incoming_brute_damage_percent))) + if(M.energy_based) + M.energy_source.use(M.energy_cost) + hit_embed_chance = hit_embed_chance*M.incoming_brute_damage_percent + if(prob(max(hit_embed_chance, 0))) var/obj/item/weapon/material/shard/shrapnel/SP = new() SP.name = (P.name != "shrapnel")? "[P.name] shrapnel" : "shrapnel" @@ -381,9 +393,28 @@ emp_act // if(buckled && buckled == AM) // return // Don't get hit by the thing we're buckled to. + //VORESTATION EDIT START - Allows for thrown vore! + //Throwing a prey into a pred takes priority. After that it checks to see if the person being thrown is a pred. + if(istype(AM, /mob/living)) + var/mob/living/thrown_mob = AM + if((can_be_drop_pred && throw_vore) && (thrown_mob.devourable && thrown_mob.throw_vore && thrown_mob.can_be_drop_prey)) //Prey thrown into pred. + vore_selected.nom_mob(thrown_mob) //Eat them!!! + visible_message("[thrown_mob] is thrown right into [src]'s [lowertext(vore_selected.name)]!") + if(thrown_mob.loc != vore_selected) + thrown_mob.forceMove(vore_selected) //Double check. Should never happen but...Weirder things have happened! + add_attack_logs(thrown_mob.thrower,src,"Devoured [thrown_mob.name] via throw vore.") + return //We can stop here. We don't need to calculate damage or anything else. They're eaten. + else if((can_be_drop_prey && throw_vore && devourable) && (thrown_mob.can_be_drop_pred && thrown_mob.throw_vore)) //Pred thrown into prey. + visible_message("[src] suddenly slips inside of [thrown_mob]'s [lowertext(thrown_mob.vore_selected.name)] as [thrown_mob] flies into them!") + thrown_mob.vore_selected.nom_mob(src) //Eat them!!! + if(src.loc != thrown_mob.vore_selected) + src.forceMove(thrown_mob.vore_selected) //Double check. Should never happen but...Weirder things have happened! + add_attack_logs(thrown_mob.LAssailant,src,"Was Devoured by [thrown_mob.name] via throw vore.") + return + //VORESTATION EDIT END - Allows for thrown vore! + if(istype(AM,/obj/)) var/obj/O = AM - if(in_throw_mode && speed <= THROWFORCE_SPEED_DIVISOR) //empty active hand and we're in throw mode if(canmove && !restrained()) if(isturf(O.loc)) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 9857513e7e..5763041914 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -248,9 +248,28 @@ to_chat(src, "Your legs won't respond properly, you fall down!") Weaken(10) +// RADIATION! Everyone's favorite thing in the world! So let's get some numbers down off the bat. +// 50 rads = 1Bq. This means 1 rad = 0.02Bq. +// However, unless I am a smoothbrained dumbo, absorbed rads are in Gy. Not Bq. +// So let's just assume that 50 rads = 1Gy. Make life easier! + +// ACUTE RADIATION (The stuff that the 'radiation' variable takes care of. Remember, 50radiation=1Gy.): +// Without care: 1-2Gy has a (0-5%) mortality chance. 2-6 (5-95%) 6-8 (95-100)% 8-30 (100%) >30 (100%) +// With care: 1-2Gy (0-5%), 2-6 (5-50%), 6-8 (50-100%), 8-30 (99-100%) >30 (100%) +// So let's make our thresholds based on this! 50-100, 100-300, 300-400, 400-1500, and anything above 1500! +// In reality, however, nobody should ever go above 300 radiation, which is why the cutoff before the really bad effects start to happen being +// 300 radiation is good. For reference: Breaking an artifact deals ~300 rads with no resistance. Getting shot with a lvl 3 PA deals 300 rads with no resistance. +// Nobody outside of engineering should ever have to worry about being irradiated over 300 and start getting organ damage.. -/mob/living/carbon/human/handle_mutations_and_radiation() +// CHRONIC RADIATION (The stuff that 'accumulated_rads' takes care of): +// This is more or less for if someone was exposed for a long time to radiation or just finished being treated for extreme ARS. +// These are meant to be annoying effects to nudge someone towards medical, but not lethal or deadly. +// Things such as loss of taste, eye damage, dropping items in your hand, being temporaily weakened, etc. Stuff to annoy them and get them to fix their rads. + +// Additionally, RADIATION_SPEED_COEFFICIENT = 0.1 + +/mob/living/carbon/human/handle_mutations_and_radiation() //Radiation rework! Now with 'accumulated_rads' if(inStasisNow()) return @@ -267,12 +286,15 @@ if(gene.is_active(src)) gene.OnMobLife(src) - radiation = CLAMP(radiation,0,250) - + radiation = CLAMP(radiation,0,2500) //Max of 50Gy. If you reach that...You're going to wish you were dead. You probably will be dead. + accumulated_rads = CLAMP(accumulated_rads,0,2500) //Max of 50Gy as well. You should never get higher than this. You will be dead before you can reach this. + var/obj/item/organ/internal/I = null //Used for further down below when an organ is picked. if(!radiation) if(species.appearance_flags & RADIATION_GLOWS) set_light(0) - else + if(accumulated_rads) + accumulated_rads -= RADIATION_SPEED_COEFFICIENT //Accumulated rads slowly dissipate very slowly. Get to medical to get it treated! + else if(((life_tick % 5 == 0) && radiation) || (radiation > 600)) //Radiation is a slow, insidious killer. Unless you get a massive dose, then the onset is sudden! if(species.appearance_flags & RADIATION_GLOWS) set_light(max(1,min(5,radiation/15)), max(1,min(10,radiation/25)), species.get_flesh_colour(src)) // END DOGSHIT SNOWFLAKE @@ -299,42 +321,139 @@ return //VOREStation Addition end: shadekin - var/damage = 0 - radiation -= 1 * RADIATION_SPEED_COEFFICIENT - if(radiation > 2.5 && prob(25)) // Safe for a little over 2m at the recommended maximum safe dosage of 0.05Bq - damage = 1 + if(reagents.has_reagent("prussian_blue")) //Prussian Blue temporarily stops radiation effects. + return - if (radiation > 50) + var/damage = 0 + + + if (radiation < 50) //Less than 1.0 Gy. No side effects. + radiation -= 10 * RADIATION_SPEED_COEFFICIENT + accumulated_rads += 10 * RADIATION_SPEED_COEFFICIENT //No escape from accumulated rads. + + else if (radiation >= 50 && radiation < 100) //Equivalent of 1.0-2.0 Gy. Minimum stage you start seeing effects. damage = 1 - radiation -= 1 * RADIATION_SPEED_COEFFICIENT + radiation -= 10 * RADIATION_SPEED_COEFFICIENT + accumulated_rads += 10 * RADIATION_SPEED_COEFFICIENT if(!isSynthetic()) - if(prob(5) && prob(100 * RADIATION_SPEED_COEFFICIENT)) - radiation -= 5 * RADIATION_SPEED_COEFFICIENT - to_chat(src, "You feel weak.") - Weaken(3) - if(!lying) - emote("collapse") + if(prob(5) && prob(100 * RADIATION_SPEED_COEFFICIENT) && !weakened) + to_chat(src, "You feel exhausted.") + AdjustWeakened(3) if(prob(5) && prob(100 * RADIATION_SPEED_COEFFICIENT) && species.get_bodytype() == SPECIES_HUMAN) //apes go bald if((h_style != "Bald" || f_style != "Shaved" )) to_chat(src, "Your hair falls out.") h_style = "Bald" f_style = "Shaved" update_hair() + if(prob(1) && prob(100 * RADIATION_SPEED_COEFFICIENT)) //Rare chance of vomiting. + spawn vomit() - if (radiation > 75) + else if (radiation >= 100 && radiation < 300) //Equivalent of 2.0 to 6.0 Gy. Nobody should ever be above this without extreme negligence. damage = 3 - radiation -= 1 * RADIATION_SPEED_COEFFICIENT + radiation -= 30 * RADIATION_SPEED_COEFFICIENT + accumulated_rads += 30 * RADIATION_SPEED_COEFFICIENT if(!isSynthetic()) if(prob(5)) take_overall_damage(0, 5 * RADIATION_SPEED_COEFFICIENT, used_weapon = "Radiation Burns") if(prob(1)) - to_chat(src, "You feel strange!") adjustCloneLoss(5 * RADIATION_SPEED_COEFFICIENT) emote("gasp") + if(prob(5) && prob(100 * RADIATION_SPEED_COEFFICIENT)) + spawn vomit() + if(prob(10) && !weakened) + to_chat(src, "You feel sick.") + AdjustWeakened(3) - if (radiation > 150) - damage = 6 - radiation -= 4 * RADIATION_SPEED_COEFFICIENT + else if (radiation >= 300 && radiation < 400) //Equivalent of 6.0 to 8.0 Gy. + damage = 5 + radiation -= 50 * RADIATION_SPEED_COEFFICIENT + accumulated_rads += 50 * RADIATION_SPEED_COEFFICIENT + if(!isSynthetic()) + if(prob(15)) + take_overall_damage(0, 10 * RADIATION_SPEED_COEFFICIENT, used_weapon = "Radiation Burns") + if(prob(2)) + adjustCloneLoss(5 * RADIATION_SPEED_COEFFICIENT) + emote("gasp") + if(prob(10) && prob(100 * RADIATION_SPEED_COEFFICIENT)) + spawn vomit() + if(prob(15) && !weakened) + to_chat(src, "You feel horribly ill.") + AdjustWeakened(3) + if(prob(5) && internal_organs.len) + I = pick(internal_organs) //Internal organ damage...Not good. Not good at all. + if(istype(I)) I.add_autopsy_data("Radiation Induced Cancerous Growth", damage) + I.take_damage(damage * species.radiation_mod * RADIATION_SPEED_COEFFICIENT) + + + else if (radiation >= 400 && radiation < 1500) //Equivalent of 8.0 to 30 Gy. + damage = 10 + radiation -= 100 * RADIATION_SPEED_COEFFICIENT + accumulated_rads += 100 * RADIATION_SPEED_COEFFICIENT + if(!isSynthetic()) + if(prob(25)) + take_overall_damage(0, 15 * RADIATION_SPEED_COEFFICIENT, used_weapon = "Radiation Burns") + if(prob(5)) + I = internal_organs_by_name[O_EYES] + if(I) + if(istype(I)) I.add_autopsy_data("Radiation Burns", damage) + I.take_damage(damage * species.radiation_mod * RADIATION_SPEED_COEFFICIENT) + to_chat(src, "Your eyes burn!") + eye_blurry += 10 + if(prob(4)) + adjustCloneLoss(5 * RADIATION_SPEED_COEFFICIENT) + emote("gasp") + if(prob(25) && prob(100 * RADIATION_SPEED_COEFFICIENT)) + spawn vomit() + if(prob(20) && !weakened) + to_chat(src, "You feel like your insides are burning!") + AdjustWeakened(5) + if(prob(5)) + to_chat(src, "Your entire body feels like it's on fire!") + adjustHalLoss(5) + if(prob(10) && internal_organs.len) + I = pick(internal_organs) //Internal organ damage...Not good. Not good at all. + if(istype(I)) I.add_autopsy_data("Radiation Induced Cancerous Growth", damage) + I.take_damage(damage * species.radiation_mod * RADIATION_SPEED_COEFFICIENT) + + else if (radiation >= 1500) //Above 30Gy. You had to get absolutely blasted with rads for this. + damage = 30 + radiation -= 300 * RADIATION_SPEED_COEFFICIENT + accumulated_rads += 300 * RADIATION_SPEED_COEFFICIENT + + if(!isSynthetic()) + take_overall_damage(0, damage * RADIATION_SPEED_COEFFICIENT, used_weapon = "Radiation Burns") //3 burn damage a tick as your body melts. + adjustCloneLoss(15 * RADIATION_SPEED_COEFFICIENT) //1.5 cloneloss a tick as your cells mutate and break down. + + I = internal_organs_by_name[O_EYES] + if(I) + I.add_autopsy_data("Radiation Burns", damage * species.radiation_mod * RADIATION_SPEED_COEFFICIENT) + I.take_damage(damage * species.radiation_mod * RADIATION_SPEED_COEFFICIENT) //3 eye damage a tick as your eyes melt down. + eye_blurry += 10 + + if(prob(50) && prob(100 * RADIATION_SPEED_COEFFICIENT)) + spawn vomit() + if(!paralysis && prob(30) && prob(100 * RADIATION_SPEED_COEFFICIENT)) //CNS is shutting down. + to_chat(src, "You have a seizure!") + Paralyse(10) + make_jittery(1000) + if(!lying) + emote("collapse") + if(get_active_hand() && prob(15)) //CNS is shutting down. + to_chat(src, "Your hand won't respond properly, you drop what you're holding!") + drop_item() + if(internal_organs.len) + I = pick(internal_organs) //Internal organ damage...Not good. Not good at all. + if(istype(I)) I.add_autopsy_data("Radiation Induced Cancerous Growth", damage * species.radiation_mod * RADIATION_SPEED_COEFFICIENT) + I.take_damage(damage * species.radiation_mod * RADIATION_SPEED_COEFFICIENT) + +/* //Not-so-sparkledog code. TODO: Make a pref for 'special game interactions' that allows interactions that align with prefs to occur. + if(radiation >= 250) //Special effect stuff that occurs at certain rad levels. + if(prob(1) && prob(radiation/2 * RADIATION_SPEED_COEFFICIENT) && allow_spontaneous_tf) //If you've got spontaneous TF...well... + scramble(1, src, 3) //I tried to base this on how many rads you took and it was...Hilarious. Sparkledogs everywhere. + //For the most part, 3 strength will simply change colors. If you get really unlucky, it can do more TF's. + //Math: 250 rads = 1/800 chance + //500 rads = 1/400 chance chance. Etc. +*/ if(damage) damage *= species.radiation_mod @@ -344,6 +463,47 @@ var/obj/item/organ/external/O = pick(organs) if(istype(O)) O.add_autopsy_data("Radiation Poisoning", damage) + // Begin long-term radiation effects + // Loss of taste occurs at 100 (2Gy) and is handled in taste.dm + // These are all done one after another, so duplication is not required. Someone at 400rads will have the 100&400 effects. + if(!radiation && accumulated_rads >= 100 && !reagents.has_reagent("prussian_blue")) //Let's not hit them with long term effects when they're actively being hit with rads. + if(!isSynthetic()) + I = internal_organs_by_name[O_EYES] + if(I) //Eye stuff + if(prob(5) && prob(accumulated_rads * RADIATION_SPEED_COEFFICIENT)) + to_chat(src, "Your eyes water.") + eye_blurry += 5 + if(accumulated_rads > 300) // (6Gy) + if(prob(2) && prob(accumulated_rads * RADIATION_SPEED_COEFFICIENT)) + to_chat(src, "Your eyes burn.") + I.add_autopsy_data("Radiation Burns", 1 * species.radiation_mod * RADIATION_SPEED_COEFFICIENT) + I.take_damage(1 * species.radiation_mod * RADIATION_SPEED_COEFFICIENT) //0.1 damage. Not a lot, but enough to tell you to get to medical. + eye_blurry += 10 + + if(accumulated_rads > 200) // (4Gy) + if(prob(5) && prob(accumulated_rads * RADIATION_SPEED_COEFFICIENT)) + to_chat(src, "Your feel nauseated.") + spawn vomit() + if(!weakened && prob(2) && prob(accumulated_rads * RADIATION_SPEED_COEFFICIENT)) + to_chat(src, "Your feel exhausted.") + AdjustWeakened(3) + if(accumulated_rads > 300) // (6Gy) + if(get_active_hand() && prob(15) && prob(100 * RADIATION_SPEED_COEFFICIENT)) //CNS is shutting down. + to_chat(src, "Your hand won't respond properly, you drop what you're holding!") + drop_item() + if(accumulated_rads > 700) // (12Gy) + if(!paralysis && prob(1) && prob(100 * RADIATION_SPEED_COEFFICIENT)) //1 in 1000 chance per tick. + to_chat(src, "You have a seizure!") + Paralyse(10) + make_jittery(1000) + if(!lying) + emote("collapse") + + else //The synthetic effects! + return //Nothing for now. + + + /** breathing **/ /mob/living/carbon/human/handle_chemical_smoke(var/datum/gas_mixture/environment) @@ -1419,7 +1579,9 @@ else clear_alert("high") - if(!isbelly(loc)) clear_fullscreen("belly") //VOREStation Add - Belly fullscreens safety + if(!isbelly(loc)) //VOREStation Add - Belly fullscreens safety + clear_fullscreen("belly") + //clear_fullscreen("belly2") //For multilayered stomachs. Not currently implemented. if(config.welder_vision) var/found_welder diff --git a/code/modules/mob/living/carbon/human/species/outsider/vox.dm b/code/modules/mob/living/carbon/human/species/outsider/vox.dm index da0e0e0b9b..5093c4e821 100644 --- a/code/modules/mob/living/carbon/human/species/outsider/vox.dm +++ b/code/modules/mob/living/carbon/human/species/outsider/vox.dm @@ -46,6 +46,7 @@ breath_type = "nitrogen" //CHOMPedit poison_type = "oxygen" + ideal_air_type = /datum/gas_mixture/belly_air/vox siemens_coefficient = 0.2 flags = NO_SCAN | NO_DEFIB @@ -110,6 +111,3 @@ H.internal = locate(/obj/item/weapon/tank) in H.contents if(istype(H.internal,/obj/item/weapon/tank) && H.internals) H.internals.icon_state = "internal1" - -/datum/species/vox/get_perfect_belly_air_type() - return /datum/gas_mixture/belly_air/vox diff --git a/code/modules/mob/living/carbon/human/species/species_getters_vr.dm b/code/modules/mob/living/carbon/human/species/species_getters_vr.dm index 8bccade358..140923062c 100644 --- a/code/modules/mob/living/carbon/human/species/species_getters_vr.dm +++ b/code/modules/mob/living/carbon/human/species/species_getters_vr.dm @@ -7,4 +7,7 @@ return wing_animation /datum/species/proc/get_perfect_belly_air_type(var/mob/living/carbon/human/H) - return /datum/gas_mixture/belly_air //Default \ No newline at end of file + if(ideal_air_type) + return ideal_air_type //Whatever we want + else + return /datum/gas_mixture/belly_air //Default \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/species_vr.dm b/code/modules/mob/living/carbon/human/species/species_vr.dm index ef4e8252bd..77d15d000a 100644 --- a/code/modules/mob/living/carbon/human/species/species_vr.dm +++ b/code/modules/mob/living/carbon/human/species/species_vr.dm @@ -30,6 +30,8 @@ var/list/copy_vars = list("base_species", "icobase", "deform", "tail", "tail_animation", "icobase_tail", "color_mult", "primitive_form", "appearance_flags", "flesh_color", "base_color", "blood_mask", "damage_mask", "damage_overlays", "move_trail", "has_floating_eyes") var/trait_points = 0 + var/ideal_air_type = null // Set to something else if you breathe something else from default composition. Used for inbelly air. + var/micro_size_mod = 0 // How different is our size for interactions that involve us being small? var/macro_size_mod = 0 // How different is our size for interactions that involve us being big? var/digestion_nutrition_modifier = 1 diff --git a/code/modules/mob/living/carbon/human/species/station/station.dm b/code/modules/mob/living/carbon/human/species/station/station.dm index 5ff11b6c9c..d54928b455 100644 --- a/code/modules/mob/living/carbon/human/species/station/station.dm +++ b/code/modules/mob/living/carbon/human/species/station/station.dm @@ -426,6 +426,7 @@ hazard_low_pressure = 220 // Dangerously low pressure. safe_pressure = 400 poison_type = "nitrogen" // technically it's a partial pressure thing but IDK if we can emulate that + ideal_air_type = /datum/gas_mixture/belly_air/zaddat genders = list(FEMALE, PLURAL) //females are polyp-producing, infertile females and males are nigh-identical @@ -501,9 +502,6 @@ if(!(K in covered)) H.apply_damage(light_amount/4, BURN, K, 0, 0, "Abnormal growths") -/datum/species/zaddat/get_perfect_belly_air_type() - return /datum/gas_mixture/belly_air/zaddat - /datum/species/diona name = SPECIES_DIONA name_plural = "Dionaea" diff --git a/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm b/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm index 38d6c68933..f0dafec0a6 100644 --- a/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm +++ b/code/modules/mob/living/carbon/human/species/station/station_special_abilities_vr.dm @@ -1154,7 +1154,6 @@ to_chat(src, "You successfully drag \the [target] into the water, slipping them into your [vore_selected].") target.forceMove(src.vore_selected) - /mob/living/carbon/human/proc/toggle_pain_module() set name = "Toggle pain simulation." set desc = "Turn on your pain simulation for that organic experience! Or turn it off for repairs, or if it's too much." @@ -1166,8 +1165,6 @@ to_chat(src, " You turn on your pain simulators ") synth_cosmetic_pain = !synth_cosmetic_pain -<<<<<<< HEAD -======= //This is the 'long vore' ability. Also known as "Grab Prey with appendage" or "Long Predatorial Reach". Or simply "Tongue Vore" //It involves projectiles (which means it can be VV'd onto a gun for shenanigans) @@ -1194,12 +1191,14 @@ var/new_color = input(usr, "Choose a color to set your appendage to!", "", appendage_color) as color|null if(new_color) appendage_color = new_color + if(choice == "Functionality") //Easy way to set color so we don't bloat up the menu with even more buttons. var/choice2 = tgui_alert(usr, "Choose if you want to be pulled to the target or pull them to you!", "Functionality Setting", list("Pull target to self", "Pull self to target")) if(choice2 == "Pull target to self") appendage_alt_setting = 0 else appendage_alt_setting = 1 + else var/list/targets = list() //IF IT IS NOT BROKEN. DO NOT FIX IT. @@ -1378,5 +1377,4 @@ name = "tongue ball" hitsound = 'sound/vore/sunesound/pred/schlorp.ogg' hitsound_wall = 'sound/vore/sunesound/pred/schlorp.ogg' - zaptype = /obj/item/projectile/beam/appendage ->>>>>>> 6285a02b37... Merge pull request #13731 from Cameron653/TONGUE_EDIT + zaptype = /obj/item/projectile/beam/appendage \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/station/traits_vr/negative.dm b/code/modules/mob/living/carbon/human/species/station/traits_vr/negative.dm index 35a56f9b42..25bb2c5aaf 100644 --- a/code/modules/mob/living/carbon/human/species/station/traits_vr/negative.dm +++ b/code/modules/mob/living/carbon/human/species/station/traits_vr/negative.dm @@ -136,12 +136,12 @@ /datum/trait/negative/breathes/phoron name = "Phoron Breather" desc = "You breathe phoron instead of oxygen (which is poisonous to you), much like a Vox." - var_changes = list("breath_type" = "phoron", "poison_type" = "oxygen") + var_changes = list("breath_type" = "phoron", "poison_type" = "oxygen", "ideal_air_type" = /datum/gas_mixture/belly_air/vox) /datum/trait/negative/breathes/nitrogen name = "Nitrogen Breather" desc = "You breathe nitrogen instead of oxygen (which is poisonous to you). Incidentally, phoron isn't poisonous to breathe to you." - var_changes = list("breath_type" = "nitrogen", "poison_type" = "oxygen") + var_changes = list("breath_type" = "nitrogen", "poison_type" = "oxygen", "ideal_air_type" = /datum/gas_mixture/belly_air/nitrogen_breather) /datum/trait/negative/monolingual name = "Monolingual" diff --git a/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm b/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm index db5b35c749..30ce470894 100644 --- a/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm +++ b/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm @@ -122,6 +122,16 @@ H.verbs |= /mob/living/carbon/human/proc/succubus_drain_finalize H.verbs |= /mob/living/carbon/human/proc/succubus_drain_lethal +/datum/trait/neutral/long_vore + name = "Long Predatorial Reach" + desc = "Makes you able to use your tongue to grab creatures." + cost = 0 + custom_only = FALSE + +/datum/trait/neutral/long_vore/apply(var/datum/species/S,var/mob/living/carbon/human/H) + ..(S,H) + H.verbs |= /mob/living/proc/long_vore + /datum/trait/neutral/feeder name = "Feeder" desc = "Allows you to feed your prey using your own body." @@ -166,11 +176,12 @@ /datum/trait/neutral/synth_chemfurnace name = "Biofuel Processor" - desc = "You are able to gain energy through consuming and processing normal food. Energy-dense foods such as protein bars and survival food will yield the best results." + desc = "You are able to gain energy through consuming and processing normal food, at the cost of significantly slower recharging via cyborg chargers. Energy-dense foods such as protein bars and survival food will yield the best results." cost = 0 custom_only = FALSE can_take = SYNTHETICS var_changes = list("organic_food_coeff" = 0.75, "synthetic_food_coeff" = 1) //CHOMPEdit: Increase values + excludes = list(/datum/trait/neutral/biofuel_value_down) /datum/trait/neutral/glowing_eyes name = "Glowing Eyes" @@ -608,7 +619,7 @@ /datum/trait/neutral/biofuel_value_down name = "Discount Biofuel processor" - desc = "You are able to gain energy through consuming and processing normal food. Unfortunately, it is half as effective as premium models." + desc = "You are able to gain energy through consuming and processing normal food. Unfortunately, it is half as effective as premium models. On the plus side, you still recharge from charging stations fairly efficiently." cost = 0 custom_only = FALSE can_take = SYNTHETICS diff --git a/code/modules/mob/living/carbon/human/species/station/xenochimera_trait_vr.dm b/code/modules/mob/living/carbon/human/species/station/xenochimera_trait_vr.dm index 663e6eec76..680e9d69bb 100644 --- a/code/modules/mob/living/carbon/human/species/station/xenochimera_trait_vr.dm +++ b/code/modules/mob/living/carbon/human/species/station/xenochimera_trait_vr.dm @@ -144,3 +144,13 @@ ), autohiss_exempt = list("Vespinae")) excludes = list(/datum/trait/neutral/autohiss_tajaran, /datum/trait/neutral/autohiss_unathi) +//End YW edit + +/datum/trait/positive/cocoon_tf/xenochimera + sort = TRAIT_SORT_SPECIES + allowed_species = list(SPECIES_XENOCHIMERA) + custom_only = FALSE + name = "Xenochimera: Cocoon Spinner" + desc = "Allows you to build a cocoon around yourself, using it to transform your body if you desire." + cost = 0 + category = 0 diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index c94959a13a..e0c9397f0e 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -1137,8 +1137,14 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() var/image/effects = new() for(var/datum/modifier/M in modifiers) if(M.mob_overlay_state) - var/image/I = image(icon = 'icons/mob/modifier_effects.dmi', icon_state = M.mob_overlay_state) - effects.overlays += I // Leaving this as overlays += + if(M.icon_override) //VOREStation Edit. Override for the modifer icon. + var/image/I = image(icon = 'icons/mob/modifier_effects_vr.dmi', icon_state = M.mob_overlay_state) + I.color = M.effect_color + effects.overlays += I // Leaving this as overlays += + else + var/image/I = image(icon = 'icons/mob/modifier_effects.dmi', icon_state = M.mob_overlay_state) + I.color = M.effect_color + effects.overlays += I // Leaving this as overlays += overlays_standing[MODIFIER_EFFECTS_LAYER] = effects diff --git a/code/modules/mob/living/carbon/taste.dm b/code/modules/mob/living/carbon/taste.dm index f02e704721..150f67d955 100644 --- a/code/modules/mob/living/carbon/taste.dm +++ b/code/modules/mob/living/carbon/taste.dm @@ -11,6 +11,9 @@ from.trans_to_holder(temp, amount, multiplier, 1) var/text_output = temp.generate_taste_message(src) + if(accumulated_rads >= 100) //If you're irradiated, you can't taste! + text_output = "nothing" + if(text_output != last_taste_text || last_taste_time + 100 < world.time) //We dont want to spam the same message over and over again at the person. Give it a bit of a buffer. to_chat(src, "You can taste [text_output].")//no taste means there are too many tastes and not enough flavor. diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index 4eaab77926..a865a6b05d 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -13,6 +13,53 @@ to_world_log("## DEBUG: apply_damage() was called on [src], with [damage] damage, and an armor value of [blocked].") if(!damage || (blocked >= 100)) return 0 + for(var/datum/modifier/M in modifiers) //MODIFIER STUFF. It's best to do this RIGHT before armor is calculated, so it's done here! This is the 'forcefield' defence. + if(damagetype == BRUTE && (!isnull(M.effective_brute_resistance))) + if(M.energy_based) + M.energy_source.use(M.damage_cost * damage) + damage = damage * M.effective_brute_resistance + continue + if((damagetype == BURN || damagetype == ELECTROCUTE)&& (!isnull(M.effective_fire_resistance))) + if(M.energy_based) + M.energy_source.use(M.damage_cost * damage) + damage = damage * M.effective_fire_resistance + continue + if(damagetype == TOX && (!isnull(M.effective_tox_resistance))) + if(M.energy_based) + M.energy_source.use(M.damage_cost * damage) + damage = damage * M.effective_tox_resistance + continue + if(damagetype == OXY && (!isnull(M.effective_oxy_resistance))) + if(M.energy_based) + M.energy_source.use(M.damage_cost * damage) + damage = damage * M.effective_oxy_resistance + continue + if(damagetype == CLONE && (!isnull(M.effective_clone_resistance))) + if(M.energy_based) + M.energy_source.use(M.damage_cost * damage) + damage = damage * M.effective_clone_resistance + continue + if(damagetype == HALLOSS && (!isnull(M.effective_hal_resistance))) + if(M.energy_based) + M.energy_source.use(M.damage_cost * damage) + damage = damage * M.effective_hal_resistance + continue + if(damagetype == SEARING && (!isnull(M.effective_fire_resistance) || !isnull(M.effective_brute_resistance))) + if(M.energy_based) + M.energy_source.use(M.damage_cost * damage) + var/damage_mitigation = 0//Used for dual calculations. + if(!isnull(M.effective_fire_resistance)) + damage_mitigation += round((1/3)*damage * M.effective_fire_resistance) + if(!isnull(M.effective_brute_resistance)) + damage_mitigation += round((2/3)*damage * M.effective_brute_resistance) + damage -= damage_mitigation + continue + if(damagetype == BIOACID && (isSynthetic() && (!isnull(M.effective_fire_resistance))) || (!isSynthetic() && M.effective_tox_resistance)) + if(isSynthetic()) + damage = damage * M.effective_fire_resistance + else + damage = damage * M.effective_tox_resistance + continue if(soaked) if(soaked >= round(damage*0.8)) damage -= round(damage*0.8) @@ -55,6 +102,7 @@ /mob/living/proc/apply_damages(var/brute = 0, var/burn = 0, var/tox = 0, var/oxy = 0, var/clone = 0, var/halloss = 0, var/def_zone = null, var/blocked = 0) if(blocked >= 100) return 0 + // INSERT MODIFIER CODE HERE... But no, really, only two things in the game use it, quad and viruses. The former is admin-only and the latter wouldn't be affected logically, but would if shield code was inerted here. If you really want, you can copy&paste the above and modify it to adjust brute/burn/etc. I do not advise this however. if(brute) apply_damage(brute, BRUTE, def_zone, blocked) if(burn) apply_damage(burn, BURN, def_zone, blocked) if(tox) apply_damage(tox, TOX, def_zone, blocked) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index e0f7d9a14b..0d6fc27ae9 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -192,8 +192,12 @@ if(amount > 0) for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_brute_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_brute_damage_percent else if(amount < 0) for(var/datum/modifier/M in modifiers) @@ -219,8 +223,12 @@ if(amount > 0) for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_oxy_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_oxy_damage_percent else if(amount < 0) for(var/datum/modifier/M in modifiers) @@ -243,8 +251,12 @@ if(amount > 0) for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_tox_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_tox_damage_percent else if(amount < 0) for(var/datum/modifier/M in modifiers) @@ -273,8 +285,12 @@ if(amount > 0) for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_fire_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_fire_damage_percent else if(amount < 0) for(var/datum/modifier/M in modifiers) @@ -298,8 +314,12 @@ if(amount > 0) for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_clone_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_clone_damage_percent else if(amount < 0) for(var/datum/modifier/M in modifiers) @@ -331,6 +351,9 @@ if(status_flags & GODMODE) return 0 //godmode if(amount > 0) for(var/datum/modifier/M in modifiers) + if(M.energy_based && (!isnull(M.incoming_hal_damage_percent) || !isnull(M.disable_duration_percent))) + M.energy_source.use(M.damage_cost*amount) // Cost of the Damage absorbed. + M.energy_source.use(M.energy_cost) // Cost of the Effect absorbed. if(!isnull(M.incoming_damage_percent)) amount *= M.incoming_damage_percent if(!isnull(M.incoming_hal_damage_percent)) @@ -1088,6 +1111,7 @@ src.inertia_dir = get_dir(target, src) step(src, inertia_dir) item.throw_at(target, throw_range, item.throw_speed, src) + item.throwing = 1 //Small edit so thrown interactions actually work! return TRUE else return FALSE diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index e695ce96bd..9d5c38d701 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -324,6 +324,28 @@ src.anchored = TRUE src.pinned += O + //VORESTATION EDIT START - Allows for thrown vore! + //Throwing a prey into a pred takes priority. After that it checks to see if the person being thrown is a pred. + if(istype(AM, /mob/living)) + var/mob/living/thrown_mob = AM + if(!client && !thrown_mob.allowmobvore) + return //The mob is AI controlled and the prey doesn't allow for mob vore allowed, don't even bother. + if((can_be_drop_pred && throw_vore) && (thrown_mob.devourable && thrown_mob.throw_vore && thrown_mob.can_be_drop_prey)) //Prey thrown into pred. + vore_selected.nom_mob(thrown_mob) //Eat them!!! + visible_message("[thrown_mob] is thrown right into [src]'s [lowertext(vore_selected.name)]!") + if(thrown_mob.loc != vore_selected) + thrown_mob.forceMove(vore_selected) //Double check. Should never happen but...Weirder things have happened! + add_attack_logs(thrown_mob.thrower,src,"Devoured [thrown_mob.name] via throw vore.") + return //We can stop here. We don't need to calculate damage or anything else. They're eaten. + else if((can_be_drop_prey && throw_vore && devourable) && (thrown_mob.can_be_drop_pred && thrown_mob.throw_vore)) //Pred thrown into prey. + visible_message("[src] suddenly slips inside of [thrown_mob]'s [lowertext(thrown_mob.vore_selected.name)] as [thrown_mob] flies into them!") + thrown_mob.vore_selected.nom_mob(src) //Eat them!!! + if(src.loc != thrown_mob.vore_selected) + src.forceMove(thrown_mob.vore_selected) //Double check. Should never happen but...Weirder things have happened! + add_attack_logs(thrown_mob.LAssailant,src,"Was Devoured by [thrown_mob.name] via throw vore.") + return + //VORESTATION EDIT END - Allows for thrown vore! + /mob/living/proc/embed(var/obj/O, var/def_zone=null) O.loc = src src.embedded += O diff --git a/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm b/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm index 2678af4853..26ab8389a4 100644 --- a/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm +++ b/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm @@ -598,9 +598,12 @@ volume = T.reagents.total_volume if(water) water.add_charge(volume) + if(T.ckey) + GLOB.prey_digested_roundstat++ if(patient == T) patient_laststat = null patient = null + T.mind?.vore_death = TRUE qdel(T) //Pick a random item to deal with (if there are any) diff --git a/code/modules/mob/living/silicon/robot/robot_modules/station.dm b/code/modules/mob/living/silicon/robot/robot_modules/station.dm index 4babec0baa..76a479a80d 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules/station.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules/station.dm @@ -680,7 +680,8 @@ var/global/list/robot_modules = list( src.emag.reagents = R R.my_atom = src.emag R.add_reagent("beer2", 50) - src.emag.name = "Mickey Finn's Special Brew" + src.emag.name = "Auntie Hong's Final Sip" + src.emag.desc = "A bottle of very special mix of alcohol and poison. Some may argue that there's alcohol to die for, but Auntie Hong took it to next level." /obj/item/weapon/robot_module/robot/clerical/general name = "clerical robot module" diff --git a/code/modules/mob/living/silicon/robot/robot_modules/station_vr.dm b/code/modules/mob/living/silicon/robot/robot_modules/station_vr.dm index 128bffbc09..0127068772 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules/station_vr.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules/station_vr.dm @@ -1084,13 +1084,7 @@ src.modules += new /obj/item/weapon/tray/robotray(src) src.modules += new /obj/item/weapon/reagent_containers/borghypo/service(src) - src.emag = new /obj/item/weapon/reagent_containers/food/drinks/bottle/small/beer(src) - var/datum/reagents/N = new/datum/reagents(50) - src.emag.reagents = N - N.my_atom = src.emag - N.add_reagent("beer2", 50) - src.emag.name = "Mickey Finn's Special Brew" R.icon = 'icons/mob/widerobot_colors_vr.dmi' R.wideborg_dept = 'icons/mob/widerobot_colors_vr.dmi' R.hands.icon = 'icons/mob/screen1_robot_vr.dmi' @@ -1110,9 +1104,6 @@ /obj/item/weapon/robot_module/robot/booze/respawn_consumable(var/mob/living/silicon/robot/R, var/amount) var/obj/item/weapon/reagent_containers/food/condiment/enzyme/E = locate() in src.modules E.reagents.add_reagent("enzyme", 2 * amount) - if(src.emag) - var/obj/item/weapon/reagent_containers/food/drinks/bottle/small/beer/B = src.emag - B.reagents.add_reagent("beer2", 2 * amount) //CHOMP addition start BORGHYPO /obj/item/weapon/reagent_containers/borghypo/service/booze @@ -1206,4 +1197,3 @@ R.verbs -= /mob/living/proc/shred_limb R.verbs -= /mob/living/silicon/robot/proc/rest_style ..() -// CH changes - Unity Hound end diff --git a/code/modules/mob/living/simple_mob/simple_mob_vr.dm b/code/modules/mob/living/simple_mob/simple_mob_vr.dm index a8ac7e6cac..9f22991009 100644 --- a/code/modules/mob/living/simple_mob/simple_mob_vr.dm +++ b/code/modules/mob/living/simple_mob/simple_mob_vr.dm @@ -265,6 +265,7 @@ "The juices pooling beneath you sizzle against your sore skin.", "The churning walls slowly pulverize you into meaty nutrients.", "The stomach glorps and gurgles as it tries to work you into slop.") + can_be_drop_pred = TRUE // Mobs will eat anyone that decides to drop/slip into them by default. /mob/living/simple_mob/Bumped(var/atom/movable/AM, yes) if(tryBumpNom(AM)) diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/jellyfish.dm b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/jellyfish.dm index 1393213736..86aa800248 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/jellyfish.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/jellyfish.dm @@ -85,7 +85,9 @@ GLOBAL_VAR_INIT(jellyfish_count, 0) /mob/living/simple_mob/vore/alienanimals/space_jellyfish/init_vore() - ..() + if(!voremob_loaded) + return + .=..() var/obj/belly/B = vore_selected B.name = "internal chamber" B.desc = "It's smooth and translucent. You can see the world around you distort and wobble with the movement of the space jellyfish. It floats casually, while the delicate flesh seems to form to you. It's surprisingly cool, and flickers with its own light. You're on display for all to see, trapped within the confines of this strange space alien!" diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/spookyghost.dm b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/spookyghost.dm index 13b88dd2e2..8bae5e7852 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/spookyghost.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/spookyghost.dm @@ -208,7 +208,8 @@ /mob/living/simple_mob/vore/alienanimals/spooky_ghost/apply_melee_effects(var/atom/A) var/mob/living/L = A - L.hallucination += rand(1,50) + if(L && istype(L)) + L.hallucination += rand(1,50) /mob/living/simple_mob/vore/alienanimals/spooky_ghost/Life() . = ..() diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/startreader.dm b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/startreader.dm index 4fdaa364ad..41eae89376 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/startreader.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/startreader.dm @@ -110,12 +110,13 @@ violent_breakthrough = TRUE /mob/living/simple_mob/vore/alienanimals/startreader/apply_melee_effects(mob/living/L) + if(!isliving(L)) + return if(L.weakened) //Don't stun people while they're already stunned! That's SILLY! return if(prob(15)) - if(isliving(L)) - visible_message("\The [src] trips \the [L]!!") - L.weakened += rand(1,10) + visible_message("\The [src] trips \the [L]!!") + L.weakened += rand(1,10) /mob/living/simple_mob/vore/alienanimals/startreader/Life() . = ..() diff --git a/code/modules/mob/living/simple_mob/subtypes/occult/unknown.dm b/code/modules/mob/living/simple_mob/subtypes/occult/unknown.dm new file mode 100644 index 0000000000..7ad77018e8 --- /dev/null +++ b/code/modules/mob/living/simple_mob/subtypes/occult/unknown.dm @@ -0,0 +1,347 @@ +#define GA_ADS 0 +#define GA_CALLDOWN 1 +#define GA_SPEEDUP 2 +#define GA_ILLUSION 3 +#define GA_BULLETHELL 4 +#define GA_LINES 5 +#define GA_CONFUSION 6 + +/mob/living/simple_mob/glitch_boss + name = "CLICK ME!!!" + desc = "WELCOME TO %location_data% THIS IS YOUR HOME NOW PLEASE INPUT CREDIT CARD CREDENTIALS BELOW" + tt_desc = "BEST TOOLBAR PROVIDER SINCE 2098" + icon = 'icons/mob/unknown_boss.dmi' + icon_state = "glitch_boss" + icon_living = "glitch_boss" + icon_dead = "glitch_boss_dead" + + faction = "MATH" + + maxHealth = 2000 + health = 2000 + evasion = -75 // Its hitbox is broken ;_; + + melee_damage_lower = 20 + melee_damage_upper = 40 + attack_armor_pen = 20 + + base_attack_cooldown = 2.5 SECONDS + + projectiletype = /obj/item/projectile/energy/slow_orb + projectilesound = 'sound/effects/uncloak.ogg' + + special_attack_min_range = 0 + special_attack_max_range = 10 + special_attack_cooldown = 20 SECONDS + ai_holder_type = /datum/ai_holder/simple_mob/ranged/aggressive/bossmob_glitch + + var/next_special_attack = GA_ADS + var/recently_used_attack = GA_SPEEDUP + var/all_special_attacks = list(GA_ADS, GA_CALLDOWN, GA_LINES, GA_BULLETHELL, GA_ILLUSION, GA_CONFUSION, GA_SPEEDUP) + + loot_list = list(/obj/item/device/nif/glitch = 100) + +/obj/item/projectile/energy/slow_orb + name = "TROJAN" + icon_state = "glitch" + damage = 50 + speed = 6 + damage_type = ELECTROCUTE + agony = 15 + check_armour = "energy" + armor_penetration = 40 + + fire_sound = 'sound/effects/uncloak.ogg' + combustion = TRUE + +/mob/living/simple_mob/glitch_boss/death(gibbed, deathmessage="suddenly %runtime error in unknown.dm, line 56%") + . = ..() + new /obj/effect/temp_visual/glitch(get_turf(src)) + qdel(src) + +/mob/living/simple_mob/glitch_boss/updatehealth() + . = ..() + + if(health < maxHealth*0.25) + special_attack_cooldown = 5 SECONDS + icon_state = "glitch_boss_25" + icon_living = "glitch_boss_25" + else if(health < maxHealth*0.5) + special_attack_cooldown = 10 SECONDS + icon_state = "glitch_boss_50" + icon_living = "glitch_boss_50" + else if (health < maxHealth*0.75) + special_attack_cooldown = 15 SECONDS + icon_state = "glitch_boss_75" + icon_living = "glitch_boss_75" + +/mob/living/simple_mob/glitch_boss/proc/create_illusions(atom/A) + var/list/possible_turfs = list() + for(var/turf/T in view(4, src)) + if(T.density || T == get_turf(src)) // Our turf is always eligible + continue + var/blocked = FALSE + for(var/atom/movable/AM in T) + if(AM.density) + blocked = TRUE + break + if(!blocked) + possible_turfs += T + + if(possible_turfs.len <= 1) + return + + var/illusion_amount = min(possible_turfs.len, 4) // Not including our spot + var/list/actual_turfs = list() + actual_turfs += get_turf(src) + for(var/i = 0, i < illusion_amount, i++) + var/turf_to_add = pick(possible_turfs) + actual_turfs += turf_to_add + possible_turfs -= turf_to_add + + for(var/i = 0, i < illusion_amount, i++) + var/chosen_turf = pick(actual_turfs) + var/type_to_spawn = prob(15) ? /mob/living/simple_mob/glitch_boss_fake/strong : /mob/living/simple_mob/glitch_boss_fake + var/mob/living/simple_mob/newmob = new type_to_spawn(chosen_turf) + newmob.icon_living = src.icon_living + newmob.icon_state = src.icon_state + new /obj/effect/temp_visual/glitch(chosen_turf) + actual_turfs -= chosen_turf + + var/move_turf = pick(actual_turfs) + src.forceMove(move_turf) + new /obj/effect/temp_visual/glitch(move_turf) + +/mob/living/simple_mob/glitch_boss/proc/make_ads(atom/A) + var/list/potential_targets = list() + for(var/mob/living/mob in view(7, src)) + if(mob.client && mob.faction != faction) + potential_targets += mob + if(potential_targets.len) + var/iteration = clamp(potential_targets.len, 1, 4) + for(var/i = 0, i < iteration, i++) + if(!(potential_targets.len)) + break + var/mob/target = pick(potential_targets) + potential_targets -= target + if(target.client) + target.client.create_fake_ad_popup_multiple(/obj/screen/popup/default, 5) + +/mob/living/simple_mob/glitch_boss/proc/bombardment(atom/A) + var/list/potential_targets = ai_holder.list_targets() + for(var/atom/entry in potential_targets) + if(istype(entry, /mob/living/simple_mob/glitch_boss_fake)) + potential_targets -= entry + if(potential_targets.len) + var/iteration = clamp(potential_targets.len, 1, 3) + for(var/i = 0, i < iteration, i++) + if(!(potential_targets.len)) + break + var/mob/target = pick(potential_targets) + potential_targets -= target + spawn_bombardments(target) + +/mob/living/simple_mob/glitch_boss/proc/spawn_bombardments(atom/target) + var/list/bomb_range = block(locate(target.x-1, target.y-1, target.z), locate(target.x+1, target.y+1, target.z)) + new /obj/effect/calldown_attack(get_turf(target)) + bomb_range -= get_turf(target) + for(var/i = 0, i < 4, i++) + var/turf/T = pick(bomb_range) + new /obj/effect/calldown_attack(T) + bomb_range -= T + +/mob/living/simple_mob/glitch_boss/proc/bomb_lines(atom/A) + var/list/potential_targets = ai_holder.list_targets() + for(var/atom/entry in potential_targets) + if(istype(entry, /mob/living/simple_mob/glitch_boss_fake)) + potential_targets -= entry + if(potential_targets.len) + var/iteration = clamp(potential_targets.len, 1, 3) + for(var/i = 0, i < iteration, i++) + if(!(potential_targets.len)) + break + var/mob/target = pick(potential_targets) + potential_targets -= target + spawn_lines(target) + +/mob/living/simple_mob/glitch_boss/proc/spawn_lines(atom/target) + var/alignment = rand(1,2) // 1 for vertical, 2 for horizontal + var/list/line_range = list() + var/turf/T = get_turf(target) + line_range += T + for(var/i = 1, i <= 7, i++) + switch(alignment) + if(1) + if(T.x-i > 0) + line_range += locate(T.x-i, T.y, T.z) + if(T.x+i <= world.maxx) + line_range += locate(T.x+i, T.y, T.z) + if(2) + if(T.y-i > 0) + line_range += locate(T.x, T.y-i, T.z) + if(T.y+i <= world.maxy) + line_range += locate(T.x, T.y+i, T.z) + for(var/turf/dropspot in line_range) + new /obj/effect/calldown_attack(dropspot) + +/mob/living/simple_mob/glitch_boss/proc/confuse_inflict(atom/A) + var/list/potential_targets = ai_holder.list_targets() + for(var/atom/entry in potential_targets) + if(istype(entry, /mob/living/simple_mob/glitch_boss_fake)) + potential_targets -= entry + if(potential_targets.len < 2) + return + potential_targets -= A + var/mob/living/target + while(!target && potential_targets.len) + var/candidate = pick(potential_targets) + if(isliving(candidate)) + target = candidate + break + else + potential_targets -= candidate + + if(target && istype(target)) + if(target.client) + to_chat(target, "You feel as though you are losing your sense of direction! Brace yourself!") + new /obj/effect/temp_visual/pre_confuse(get_turf(target)) + spawn(5 SECONDS) + if(target) + target.Confuse(3) + if(target.client) + to_chat(target, "You feel confused!") + new /obj/effect/temp_visual/confuse(get_turf(target)) + +/mob/living/simple_mob/glitch_boss/proc/bullethell(atom/A) + set waitfor = FALSE + + var/sd = dir2angle(dir) + var/list/offsets = list(45, 45, 20, 10) + + for(var/i = 0, i<4, i++) + for(var/j = 0, j <4, j++) + var/obj/item/projectile/energy/slow_orb/shot = new(get_turf(src)) + shot.firer = src + shot.fire(sd) + sd += 90 + sd += pick(offsets) + sleep(20) + +/mob/living/simple_mob/glitch_boss/proc/speed_up_boost(atom/A) + if(base_attack_cooldown == initial(base_attack_cooldown)) + base_attack_cooldown = 1 SECOND + var/duration = (special_attack_cooldown == 5 SECONDS) ? 5 SECONDS : 10 SECONDS + spawn(duration) + base_attack_cooldown = initial(base_attack_cooldown) + +/mob/living/simple_mob/glitch_boss/do_special_attack(atom/A) + . = TRUE + recently_used_attack = next_special_attack + switch(next_special_attack) + if(GA_ADS) + make_ads(A) + if(GA_CALLDOWN) + bombardment(A) + if(GA_LINES) + bomb_lines(A) + if(GA_BULLETHELL) + bullethell(A) + if(GA_ILLUSION) + create_illusions(A) + if(GA_CONFUSION) + confuse_inflict(A) + if(GA_SPEEDUP) + speed_up_boost(A) + +/datum/ai_holder/simple_mob/ranged/aggressive/bossmob_glitch + wander = TRUE + pointblank = TRUE + intelligence_level = AI_SMART + vision_range = 10 + closest_distance = 4 + +/datum/ai_holder/simple_mob/ranged/bossmob_glitch/pre_special_attack(atom/A) + var/mob/living/simple_mob/glitch_boss/GB + if(istype(holder, /mob/living/simple_mob/glitch_boss)) + GB = holder + if(GB) + if(isliving(A) || ismecha(A)) + var/list/possible_attacks = list() + possible_attacks += GB.all_special_attacks - GB.recently_used_attack + var/illusion_count = 0 + var/list/potential_targets = list_targets() + for(var/atom/illusion_maybe in potential_targets) + if(istype(illusion_maybe, /mob/living/simple_mob/glitch_boss_fake)) + illusion_count++ + potential_targets -= illusion_maybe + if(potential_targets.len < 2) + possible_attacks -= GA_CONFUSION + possible_attacks += GA_SPEEDUP // Double chance when fighting single target + if(illusion_count > 4) + possible_attacks -= GA_ILLUSION + if(!(possible_attacks.len)) + GB.next_special_attack = GA_BULLETHELL + else + GB.next_special_attack = pick(possible_attacks) + else + GB.next_special_attack = GA_BULLETHELL + + + +/mob/living/simple_mob/glitch_boss_fake + name = "CLICK ME!!!" + desc = "WELCOME TO %location_data% THIS IS YOUR HOME NOW PLEASE INPUT CREDIT CARD CREDENTIALS BELOW" + tt_desc = "BEST TOOLBAR PROVIDER SINCE 2098" + icon = 'icons/mob/unknown_boss.dmi' + icon_state = "glitch_boss" + icon_living = "glitch_boss" + icon_dead = "glitch_boss_dead" + faction = "MATH" + + maxHealth = 20 + health = 20 + evasion = -75 + + melee_damage_lower = 0 + melee_damage_upper = 0 + attack_armor_pen = 0 + + base_attack_cooldown = 2.5 SECONDS + + projectiletype = /obj/item/projectile/energy/slow_orb_fake + projectilesound = 'sound/effects/uncloak.ogg' + + var/prob_respawn = 15 + + ai_holder_type = /datum/ai_holder/simple_mob/ranged/aggressive/bossmob_glitch_fake + +/mob/living/simple_mob/glitch_boss_fake/strong + maxHealth = 100 + health = 100 + prob_respawn = 60 + +/mob/living/simple_mob/glitch_boss_fake/death(gibbed, deathmessage="disappears in cloud of static.") + new /obj/effect/temp_visual/glitch(get_turf(src)) + if(prob(prob_respawn)) + new /mob/living/simple_mob/glitch_boss_fake(get_turf(src)) + qdel(src) + +/obj/item/projectile/energy/slow_orb_fake + name = "TROJAN" + icon_state = "glitch" + damage = 0 + speed = 6 + damage_type = ELECTROCUTE + agony = 0 + check_armour = "energy" + armor_penetration = 0 + + fire_sound = 'sound/effects/uncloak.ogg' + combustion = TRUE + +/datum/ai_holder/simple_mob/ranged/aggressive/bossmob_glitch_fake //Same AI, but without special attack calculation stuff + wander = TRUE + pointblank = TRUE + intelligence_level = AI_SMART + vision_range = 9 + closest_distance = 4 \ No newline at end of file diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/frog.dm b/code/modules/mob/living/simple_mob/subtypes/vore/frog.dm index 07bcf6b99d..bd033b9f32 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/frog.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/frog.dm @@ -29,6 +29,7 @@ icon = 'icons/mob/vore.dmi' movement_cooldown = 4 //fast as fucc boie. + can_be_drop_pred = 1 //They can tongue vore. meat_amount = 4 meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat @@ -39,6 +40,10 @@ ai_holder_type = /datum/ai_holder/simple_mob/melee + special_attack_min_range = 1 + special_attack_max_range = 5 + special_attack_cooldown = 100 + // Pepe is love, not hate. /mob/living/simple_mob/vore/aggressive/frog/New() if(rand(1,1000000) == 1) @@ -46,6 +51,21 @@ desc = "You found a rare Pepe. Screenshot for good luck." ..() +/mob/living/simple_mob/vore/aggressive/frog/do_special_attack(atom/A) + set_AI_busy(TRUE) + do_windup_animation(A, 20) + addtimer(CALLBACK(src, .proc/chargeend, A), 20) + +/mob/living/simple_mob/vore/aggressive/frog/proc/chargeend(atom/A) + if(stat) //you are dead + set_AI_busy(FALSE) + return + playsound(src, 'sound/vore/sunesound/pred/schlorp.ogg', 25) + var/obj/item/projectile/beam/appendage/appendage_attack = new /obj/item/projectile/beam/appendage(get_turf(loc)) + appendage_attack.old_style_target(A, src) + appendage_attack.launch_projectile(A, BP_TORSO, src) + set_AI_busy(FALSE) + // Activate Noms! /mob/living/simple_mob/vore/aggressive/frog vore_active = 1 diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/solarmoth_ch.dm b/code/modules/mob/living/simple_mob/subtypes/vore/solarmoth_ch.dm index 9beab0285c..3f1fb2ef94 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/solarmoth_ch.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/solarmoth_ch.dm @@ -17,19 +17,19 @@ var/mycolour = COLOR_BLUE //Variable Lighting colours var/original_temp = null //Value to remember temp - var/set_temperature = T0C + 450 //Sets the target point of 450 degrees celsius - var/heating_power = 100000 //This controls the strength at which it heats the environment. // The number seems ridiculous but this is actually pretty reasonable - Lunar + var/set_temperature = T0C + 10000 //Sets the target point of 10k degrees celsius + var/heating_power = 100000 //This controls the strength at which it heats the environment. var/emp_heavy = 2 var/emp_med = 4 var/emp_light = 7 var/emp_long = 10 faction = "grubs" - maxHealth = 200 // Tanky fuckers. - health = 200 // Tanky fuckers. + maxHealth = 400 // Tanky fuckers. + health = 400 // Tanky fuckers. - melee_damage_lower = 5 - melee_damage_upper = 10 + melee_damage_lower = 1 + melee_damage_upper = 5 movement_cooldown = 5 @@ -59,18 +59,18 @@ minbodytemp = 0 heat_damage_per_tick = 0 //Even if the atmos stuff doesn't work, at least it won't take any damage. - armor = list( - "melee" = -50, - "bullet" = 0, - "laser" = 50, - "energy" = 50, - "bomb" = 25, + armor = list( + "melee" = 0, + "bullet" = 90, + "laser" = 100, + "energy" = 100, + "bomb" = 100, "bio" = 100, "rad" = 100) /datum/say_list/solarmoth emote_see = list("flutters") - + /mob/living/simple_mob/vore/solarmoth/apply_melee_effects(var/atom/A) if(isliving(A)) var/mob/living/L = A @@ -106,17 +106,17 @@ if(heat_transfer > 0 && env.temperature < T0C + 200) //This should start heating the room at a moderate pace up to 200 degrees celsius. heat_transfer = min(heat_transfer , heating_power) //limit by the power rating of the heater removed.add_thermal_energy(heat_transfer) - - else if(heat_transfer > 0 && env.temperature < set_temperature) //Set temperature is 450 degrees celsius. Heating rate should increase between 200 and 450 C. - heating_power = original_temp*100 + + else if(heat_transfer > 0 && env.temperature < set_temperature) //Set temperature is 10,000 degrees celsius. So this thing will start cooking crazy hot between the temperatures of 200C and 10,000C. + heating_power = original_temp*100 //Changed to work variable -shark //FLAME ON! This will make the moth heat up the room at an incredible rate. heat_transfer = min(heat_transfer , heating_power) //limit by the power rating of the heater. Except it's hot, so yeah. removed.add_thermal_energy(heat_transfer) - + else return env.merge(removed) - + //Since I'm changing hyper mode to be variable we need to store old power @@ -132,10 +132,11 @@ /mob/living/simple_mob/vore/solarmoth/death() explode() ..() - + /mob/living/simple_mob/vore/solarmoth/gib() //This baby will explode no matter what you do to it. explode() ..() + /mob/living/simple_mob/vore/solarmoth/handle_light() @@ -156,7 +157,9 @@ /mob/living/simple_mob/vore/solarmoth/lunarmoth name = "lunarmoth" desc = "A majestic sparkling lunarmoth. Also a slight engineering hazard." + var/nospampls = 0 + cold_damage_per_tick = 0 //ATMOS set_temperature = T0C - 10000 @@ -169,7 +172,7 @@ if(prob(25)) for(var/obj/machinery/light/light in range(5, src)) if(prob(50)) - light.broken() + light.broken() if(prob(10)) for(var/obj/structure/window/window in range(5, src)) if(prob(50)) @@ -180,7 +183,7 @@ visible_message("Emergency Shutter malfunction!") door.blocked = 0 door.open(1) - + spawn(100) nospampls = 0 @@ -188,5 +191,4 @@ ..() if(!nospampls) chilltheglass() //shatter and broken calls for glass and lights. Also some special thing. - - + diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/vore.dm b/code/modules/mob/living/simple_mob/subtypes/vore/vore.dm index 2c26069dff..6b3abf5134 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/vore.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/vore.dm @@ -1,6 +1,7 @@ /mob/living/simple_mob/vore mob_class = MOB_CLASS_ANIMAL mob_bump_flag = 0 + can_be_drop_pred = 1 /mob/living/simple_mob var/nameset @@ -19,17 +20,15 @@ can_be_drop_prey = client.prefs_vr.can_be_drop_prey can_be_drop_pred = client.prefs_vr.can_be_drop_pred latejoin_vore = client.prefs_vr.latejoin_vore //CHOMPedit + throw_vore = client.prefs_vr.throw_vore allow_spontaneous_tf = client.prefs_vr.allow_spontaneous_tf digest_leave_remains = client.prefs_vr.digest_leave_remains allowmobvore = client.prefs_vr.allowmobvore permit_healbelly = client.prefs_vr.permit_healbelly noisy = client.prefs_vr.noisy selective_preference = client.prefs_vr.selective_preference -<<<<<<< HEAD -======= appendage_color = client.prefs_vr.appendage_color appendage_alt_setting = client.prefs_vr.appendage_alt_setting ->>>>>>> 6285a02b37... Merge pull request #13731 from Cameron653/TONGUE_EDIT drop_vore = client.prefs_vr.drop_vore stumble_vore = client.prefs_vr.stumble_vore diff --git a/code/modules/mob/mob_defines_vr.dm b/code/modules/mob/mob_defines_vr.dm index ab784564d2..fcc56470c5 100644 --- a/code/modules/mob/mob_defines_vr.dm +++ b/code/modules/mob/mob_defines_vr.dm @@ -8,6 +8,7 @@ var/obj/screen/xenochimera/danger_level/xenochimera_danger_display = null var/size_multiplier = 1 //multiplier for the mob's icon size + var/accumulated_rads = 0 // For radiation stuff. /mob/drop_location() if(temporary_form) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index c36a48f13f..0a4e270ed6 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -408,7 +408,7 @@ var/list/intents = list(I_HELP,I_DISARM,I_GRAB,I_HURT) return // Can't talk in deadchat if you can't see it. for(var/mob/M in player_list) - if(M.client && ((!istype(M, /mob/new_player) && M.stat == DEAD) || (M.client.holder && M.client.holder.rights)) && M.is_preference_enabled(/datum/client_preference/show_dsay)) + if(M.client && ((!istype(M, /mob/new_player) && M.stat == DEAD) || (M.client.holder && M.client.holder.rights && M.is_preference_enabled(/datum/client_preference/holder/show_staff_dsay))) && M.is_preference_enabled(/datum/client_preference/show_dsay)) var/follow var/lname if(M.forbid_seeing_deadchat && !M.client.holder) @@ -438,7 +438,7 @@ var/list/intents = list(I_HELP,I_DISARM,I_GRAB,I_HURT) /proc/say_dead_object(var/message, var/obj/subject = null) for(var/mob/M in player_list) - if(M.client && ((!istype(M, /mob/new_player) && M.stat == DEAD) || (M.client.holder && M.client.holder.rights)) && M.is_preference_enabled(/datum/client_preference/show_dsay)) + if(M.client && ((!istype(M, /mob/new_player) && M.stat == DEAD) || (M.client.holder && M.client.holder.rights && M.is_preference_enabled(/datum/client_preference/holder/show_staff_dsay))) && M.is_preference_enabled(/datum/client_preference/show_dsay)) var/follow var/lname = "Game Master" if(M.forbid_seeing_deadchat && !M.client.holder) diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm index 883fbcc5b2..510ce77a26 100644 --- a/code/modules/mob/new_player/sprite_accessories.dm +++ b/code/modules/mob/new_player/sprite_accessories.dm @@ -1605,27 +1605,27 @@ shaved icon_state = "facial_dwarf" /datum/sprite_accessory/facial_hair/threeOclock - name = "3 O'clock Shadow" + name = "3 O-clock Shadow" icon_state = "facial_3oclock" /datum/sprite_accessory/facial_hair/threeOclockstache - name = "3 O'clock Shadow and Moustache" + name = "3 O-clock Shadow and Moustache" icon_state = "facial_3oclockmoustache" /datum/sprite_accessory/facial_hair/fiveOclock - name = "5 O'clock Shadow" + name = "5 O-clock Shadow" icon_state = "facial_5oclock" /datum/sprite_accessory/facial_hair/fiveOclockstache - name = "5 O'clock Shadow and Moustache" + name = "5 O-clock Shadow and Moustache" icon_state = "facial_5oclockmoustache" /datum/sprite_accessory/facial_hair/sevenOclock - name = "7 O'clock Shadow" + name = "7 O-clock Shadow" icon_state = "facial_7oclock" /datum/sprite_accessory/facial_hair/sevenOclockstache - name = "7 O'clock Shadow and Moustache" + name = "7 O-clock Shadow and Moustache" icon_state = "facial_7oclockmoustache" /datum/sprite_accessory/facial_hair/mutton diff --git a/code/modules/mob/new_player/sprite_accessories_vr.dm b/code/modules/mob/new_player/sprite_accessories_vr.dm index 8316425ea8..e9ccadbf86 100644 --- a/code/modules/mob/new_player/sprite_accessories_vr.dm +++ b/code/modules/mob/new_player/sprite_accessories_vr.dm @@ -569,7 +569,7 @@ var/desc = "You should not see this..." /datum/sprite_accessory/hair_accessory/verie_hair_glow - name = "verie's hair glow" + name = "veries hair glow" desc = "" icon_state = "verie_hair_glow" ignores_lighting = 1 diff --git a/code/modules/multiz/ladders.dm b/code/modules/multiz/ladders.dm index 0f9edf04c8..0a01004d19 100644 --- a/code/modules/multiz/ladders.dm +++ b/code/modules/multiz/ladders.dm @@ -11,7 +11,7 @@ var/obj/structure/ladder/target_up var/obj/structure/ladder/target_down - var/const/climb_time = 2 SECONDS + var/climb_time = 2 SECONDS /obj/structure/ladder/Initialize() . = ..() diff --git a/code/modules/nifsoft/nif.dm b/code/modules/nifsoft/nif.dm index 8a2740782e..f6f342ca19 100644 --- a/code/modules/nifsoft/nif.dm +++ b/code/modules/nifsoft/nif.dm @@ -455,6 +455,10 @@ You can also set the stat of a NIF to NIF_TEMPFAIL without any issues to disable if(!NS || NS != old_soft) return FALSE //what?? + if(!NS.can_uninstall) + notify("The software \"[NS]\" refuses to be uninstalled.",TRUE) + return FALSE + nifsofts[old_soft.list_pos] = null power_usage -= old_soft.p_drain @@ -632,6 +636,18 @@ You can also set the stat of a NIF to NIF_TEMPFAIL without any issues to disable bioadap = TRUE gib_nodrop = TRUE +/obj/item/device/nif/glitch + name = "weird NIF" + desc = "A NIF of a very dubious origin. It seems to be more durable than normal one... But are you sure about this?" + durability = 300 + bioadap = TRUE + starting_software = list( + /datum/nifsoft/commlink, + /datum/nifsoft/soulcatcher, + /datum/nifsoft/ar_civ, + /datum/nifsoft/malware + ) + //////////////////////////////// // Special Promethean """surgery""" /obj/item/device/nif/attack(mob/living/M, mob/living/user, var/target_zone) diff --git a/code/modules/nifsoft/nifsoft.dm b/code/modules/nifsoft/nifsoft.dm index f4f3135b8e..06490cf3c5 100644 --- a/code/modules/nifsoft/nifsoft.dm +++ b/code/modules/nifsoft/nifsoft.dm @@ -38,6 +38,8 @@ var/vision_flags_mob = 0 var/darkness_view = 0 + var/can_uninstall = TRUE + var/list/planes_enabled = null // List of vision planes this nifsoft enables when active var/vision_exclusive = FALSE //Whether or not this NIFSoft provides exclusive vision modifier @@ -67,6 +69,8 @@ //Called when the software is removed from the NIF /datum/nifsoft/proc/uninstall() + if(!can_uninstall) + return nif.uninstall(src) if(nif) if(active) deactivate() diff --git a/code/modules/nifsoft/software/05_health.dm b/code/modules/nifsoft/software/05_health.dm index 5e213781fa..1553d1337e 100644 --- a/code/modules/nifsoft/software/05_health.dm +++ b/code/modules/nifsoft/software/05_health.dm @@ -21,7 +21,8 @@ if((. = ..())) a_drain = initial(a_drain) mode = initial(mode) - nif.human.Stasis(0) + if(nif.human) // What if we deactivate because human is gone? + nif.human.Stasis(0) /datum/nifsoft/medichines_org/life() if((. = ..())) diff --git a/code/modules/nifsoft/software/15_misc.dm b/code/modules/nifsoft/software/15_misc.dm index 8e7101395f..1c6bfb2e5f 100644 --- a/code/modules/nifsoft/software/15_misc.dm +++ b/code/modules/nifsoft/software/15_misc.dm @@ -173,3 +173,29 @@ var/mob/living/carbon/human/H = human H.hide_alt_appearance("animals", justme) alt_farmanimals -= nif.human + +/datum/nifsoft/malware + name = "Cool Kidz Toolbar" + desc = "Best toolbar in business since 2098." + list_pos = NIF_MALWARE + cost = 1987 + wear = 0 + illegal = TRUE + vended = FALSE + tick_flags = NIF_ALWAYSTICK + var/last_ads + can_uninstall = FALSE + +/datum/nifsoft/malware/activate() + if((. = ..())) + to_chat(nif.human,"Runtime error in 15_misc.dm, line 189.") + +/datum/nifsoft/malware/install() + if((. = ..())) + last_ads = world.time + +/datum/nifsoft/malware/life() + if((. = ..())) + if(nif.human.client && world.time - last_ads > rand(10 MINUTES, 15 MINUTES) && prob(1)) + last_ads = world.time + nif.human.client.create_fake_ad_popup_multiple(/obj/screen/popup/default, 5) \ No newline at end of file diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index fe69463090..912889c5f6 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -735,7 +735,7 @@ Note that amputating the affected organ does in fact remove the infection from t for(var/datum/wound/W in wounds) // wounds can disappear after 10 minutes at the earliest - if(W.damage <= 0 && W.created + 10 * 10 * 60 <= world.time) + if(W.damage <= 0 && W.created + 10 MINUTES <= world.time) wounds -= W continue // let the GC handle the deletion of the wound diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 774e6bbd61..fb4299b6bf 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -375,7 +375,7 @@ t = replacetext(t, "\[row\]", "") t = replacetext(t, "\[cell\]", "") t = replacetext(t, "\[logo\]", "") //CHOMPEdit - t = replacetext(t, "\[sglogo\]", "") //CHOMPEdit + t = replacetext(t, "\[sglogo\]", "") //CHOMPEdit t = "[t]" else // If it is a crayon, and he still tries to use these, make them empty! @@ -451,7 +451,7 @@ var/raw = tgui_input_text(usr, "Enter what you want to write:", "Write", multiline = TRUE, prevent_enter = TRUE) if(!raw) return - + var/t = sanitize(raw, MAX_PAPER_MESSAGE_LEN, extra = 0) if(!t) return @@ -534,7 +534,7 @@ /obj/item/weapon/paper/attackby(obj/item/weapon/P as obj, mob/user as mob) ..() var/clown = 0 - if(user.mind && (user.mind.assigned_role == "Clown")) + if(user.mind && ((user.mind.role_alt_title == "Clown") || (user.mind.role_alt_title == "Jester") || (user.mind.role_alt_title == "Fool"))) // CHOMPStation Edit - Let clows/fools/jesters use clown stamps clown = 1 if(istype(P, /obj/item/weapon/tape_roll)) diff --git a/code/modules/power/port_gen_vr.dm b/code/modules/power/port_gen_vr.dm index 0744a9143d..2b891643a6 100644 --- a/code/modules/power/port_gen_vr.dm +++ b/code/modules/power/port_gen_vr.dm @@ -316,7 +316,7 @@ /obj/machinery/power/rtg/reg/unbuckle_mob(mob/living/buckled_mob, force = FALSE) . = ..() - buckled_mob.pixel_y = initial(buckled_mob.pixel_y) + buckled_mob.pixel_y = buckled_mob.default_pixel_y /obj/machinery/power/rtg/reg/RefreshParts() var/n = 0 diff --git a/code/modules/projectiles/guns/energy/altevian_vr.dm b/code/modules/projectiles/guns/energy/altevian_vr.dm new file mode 100644 index 0000000000..150d05c421 --- /dev/null +++ b/code/modules/projectiles/guns/energy/altevian_vr.dm @@ -0,0 +1,59 @@ +/obj/item/weapon/gun/energy/altevian + name = "Magneto-Electric Energy Projector" + desc = "A hand-held version of an energy weapon for the Altevian Hegemony. This one seems to be made for more proper civilian use with its reduced charge capacity, but ease of handling." + icon_state = "meep" + item_state = "meep" + fire_delay = 8 + slot_flags = SLOT_BELT + w_class = ITEMSIZE_NORMAL + force = 5 + origin_tech = list(TECH_COMBAT = 3, TECH_MAGNET = 2) + matter = list(MAT_STEEL = 1000) + projectile_type = /obj/item/projectile/beam/meeplaser + charge_cost = 150 + +/obj/item/weapon/gun/energy/altevian/large + name = "Proto-Reactive Beam Thruster" + desc = "A standard issue energy rifle seen for defensive purposes for a space faring rodent species. The beams are tuned for proper suppression." + icon_state = "altevian-pdw" + item_state = "altevian-pdw" + slot_flags = SLOT_BELT + w_class = ITEMSIZE_LARGE + force = 10 + origin_tech = list(TECH_COMBAT = 3, TECH_MAGNET = 4) + matter = list(MAT_STEEL = 2000) + projectile_type = /obj/item/projectile/beam/meeplaser/strong + charge_cost = 300 + +/obj/item/projectile/beam/meeplaser + name = "meep beam" + icon_state = "meep" + damage = 15 + light_color = "#77A6E1" + hud_state = "laser_disabler" + + muzzle_type = /obj/effect/projectile/muzzle/meeplaser + tracer_type = /obj/effect/projectile/tracer/meeplaser + impact_type = /obj/effect/projectile/impact/meeplaser + +/obj/item/projectile/beam/meeplaser/strong + name = "repeater beam" + damage = 35 + +/obj/effect/projectile/muzzle/meeplaser + icon_state = "muzzle_meep" + light_range = 2 + light_power = 0.5 + light_color = "#77A6E1" + +/obj/effect/projectile/tracer/meeplaser + icon_state = "meep" + light_range = 2 + light_power = 0.5 + light_color = "#77A6E1" + +/obj/effect/projectile/impact/meeplaser + icon_state = "impact_meep" + light_range = 2 + light_power = 0.5 + light_color = "#77A6E1" \ No newline at end of file diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator_vr.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator_vr.dm index 3b95676eee..22dd450169 100644 --- a/code/modules/projectiles/guns/energy/kinetic_accelerator_vr.dm +++ b/code/modules/projectiles/guns/energy/kinetic_accelerator_vr.dm @@ -382,13 +382,6 @@ . = TRUE if(src in KA.modkits) // Sanity check to prevent installing the same modkit twice thanks to occasional click/lag delays. return FALSE - // if(minebot_upgrade) - // if(minebot_exclusive && !istype(KA.loc, /mob/living/simple_animal/hostile/mining_drone)) - // to_chat(user, "The modkit you're trying to install is only rated for minebot use.") - // return FALSE - // else if(istype(KA.loc, /mob/living/simple_animal/hostile/mining_drone)) - // to_chat(user, "The modkit you're trying to install is not rated for minebot use.") - // return FALSE if(denied_type) var/number_of_denied = 0 for(var/A in KA.get_modkits()) diff --git a/code/modules/projectiles/guns/projectile/altevian_vr.dm b/code/modules/projectiles/guns/projectile/altevian_vr.dm new file mode 100644 index 0000000000..29d4800fcd --- /dev/null +++ b/code/modules/projectiles/guns/projectile/altevian_vr.dm @@ -0,0 +1,39 @@ +/obj/item/weapon/gun/projectile/altevian + name = "Altevian Rivet Repeater" + desc = "An offensive weapon designed by the altevians that is used for decompression and maximizes structural damage while also serving as a good method of personnel damage." + magazine_type = /obj/item/ammo_magazine/sam48 + allowed_magazines = list(/obj/item/ammo_magazine/sam48) + projectile_type = /obj/item/projectile/bullet/sam48 + icon_state = "altevian-repeater" + item_state = "altevian-repeater" + caliber = ".48" + load_method = MAGAZINE + +/obj/item/weapon/gun/projectile/altevian/update_icon() + if(ammo_magazine) + icon_state = initial(icon_state) + else + icon_state = "[initial(icon_state)]-e" + +/obj/item/ammo_magazine/sam48 + name = "ammo clip (SAM .48)" + icon_state = "sam48" + desc = "Standard Altevian Munition clip, caliber .48." + caliber = ".48" + ammo_type = /obj/item/ammo_casing/sam48 + mag_type = MAGAZINE + matter = list(MAT_STEEL = 240) + max_ammo = 5 + multiple_sprites = 1 + +/obj/item/ammo_casing/sam48 + desc = "A .48 bolt casing." + caliber = ".48" + projectile_type = /obj/item/projectile/bullet/sam48 + matter = list(MAT_STEEL = 30) + +/obj/item/projectile/bullet/sam48 + fire_sound = 'sound/weapons/gunshot4.ogg' + icon_state = "sam48" + damage = 49 + hud_state = "pistol_special" diff --git a/code/modules/projectiles/guns/projectile/shotgun.dm b/code/modules/projectiles/guns/projectile/shotgun.dm index 5e87e05cfc..51e7827721 100644 --- a/code/modules/projectiles/guns/projectile/shotgun.dm +++ b/code/modules/projectiles/guns/projectile/shotgun.dm @@ -226,3 +226,18 @@ w_class = ITEMSIZE_NORMAL force = 5 sawn_off = TRUE + +//Sjorgen Inertial Shotgun +/obj/item/weapon/gun/projectile/shotgun/semi + name = "semi-automatic shotgun" + desc = "A shotgun with a simple, yet effective recoil inertia loading mechanism for semi-automatic fire. This gun uses 12 gauge ammunition." + description_fluff = "Looking back on yet another venerable design, Hedberg-Hammarstrom settled on a pattern of shotgun that both had the reliability of a well proven semi-automatic loading system in addition to a striking visual aesthetic that would be appealing to even the most discerning of firearm collectors." + icon_state = "sjorgen" + item_state = "shotgun" + w_class = ITEMSIZE_LARGE + caliber = "12g" + origin_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 2) + slot_flags = SLOT_BACK + load_method = SINGLE_CASING + max_shells = 5 + ammo_type = /obj/item/ammo_casing/a12g/beanbag diff --git a/code/modules/reagents/machinery/dispenser/cartridge_presets.dm b/code/modules/reagents/machinery/dispenser/cartridge_presets.dm index f0515d3904..07c41ba940 100644 --- a/code/modules/reagents/machinery/dispenser/cartridge_presets.dm +++ b/code/modules/reagents/machinery/dispenser/cartridge_presets.dm @@ -139,6 +139,10 @@ spawn_reagent = "greentea" /obj/item/weapon/reagent_containers/chem_disp_cartridge/decaf spawn_reagent = "decaf" +/obj/item/weapon/reagent_containers/chem_disp_cartridge/chaitea + spawn_reagent = "chaitea" +/obj/item/weapon/reagent_containers/chem_disp_cartridge/decafchai + spawn_reagent = "chaiteadecaf" // ERT /obj/item/weapon/reagent_containers/chem_disp_cartridge/inaprov diff --git a/code/modules/reagents/machinery/dispenser/dispenser_presets.dm b/code/modules/reagents/machinery/dispenser/dispenser_presets.dm index ab54cd06b4..916c506a2e 100644 --- a/code/modules/reagents/machinery/dispenser/dispenser_presets.dm +++ b/code/modules/reagents/machinery/dispenser/dispenser_presets.dm @@ -144,5 +144,7 @@ /obj/item/weapon/reagent_containers/chem_disp_cartridge/lime, /obj/item/weapon/reagent_containers/chem_disp_cartridge/berry, /obj/item/weapon/reagent_containers/chem_disp_cartridge/greentea, - /obj/item/weapon/reagent_containers/chem_disp_cartridge/decaf + /obj/item/weapon/reagent_containers/chem_disp_cartridge/decaf, + /obj/item/weapon/reagent_containers/chem_disp_cartridge/chaitea, + /obj/item/weapon/reagent_containers/chem_disp_cartridge/decafchai ) diff --git a/code/modules/reagents/reactions/instant/instant.dm b/code/modules/reagents/reactions/instant/instant.dm index 2bb809ccef..299ec6d448 100644 --- a/code/modules/reagents/reactions/instant/instant.dm +++ b/code/modules/reagents/reactions/instant/instant.dm @@ -689,6 +689,15 @@ required_reagents = list("liquidcarpeto" = 2, "plasticide" = 1) carpet_type = /obj/item/stack/tile/carpet/oracarpet +/decl/chemical_reaction/instant/concrete + name = "Concrete" + id = "concretereagent" + required_reagents = list("calcium" = 2, "silicate" = 2, "water" = 2) + result_amount = 1 + +/decl/chemical_reaction/instant/concrete/on_reaction(var/datum/reagents/holder, var/created_volume) + new /obj/item/stack/material/concrete(get_turf(holder.my_atom), created_volume) + return /* Grenade reactions */ @@ -1232,4 +1241,4 @@ id = "spidertoxin_neutral" result = "protein" required_reagents = list("enzyme" = 1, "spidertoxin" = 1, "sifsap" = 1) - result_amount = 1 \ No newline at end of file + result_amount = 1 diff --git a/code/modules/reagents/reactions/instant/instant_vr.dm b/code/modules/reagents/reactions/instant/instant_vr.dm index 4691fd5a4e..adc3869294 100644 --- a/code/modules/reagents/reactions/instant/instant_vr.dm +++ b/code/modules/reagents/reactions/instant/instant_vr.dm @@ -181,6 +181,13 @@ catalysts = list("phoron" = 5) result_amount = 3 +/decl/chemical_reaction/instant/prussian_blue + name = "Prussian Blue" + id = "prussian_blue" + result = "prussian_blue" + required_reagents = list("carbon" = 3, "iron" = 1, "nitrogen" = 3) + result_amount = 7 + /////////////////////////////////////////////////////////////////////////////////// /// Reagent colonies. /decl/chemical_reaction/instant/meatcolony diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index 8548fdd36d..86f1b261bf 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -263,6 +263,16 @@ /obj/item/weapon/reagent_containers/glass/beaker/sulphuric prefill = list("sacid" = 60) +/obj/item/weapon/reagent_containers/glass/beaker/stopperedbottle + name = "stoppered bottle" + desc = "A stoppered bottle for keeping beverages fresh." + icon_state = "stopperedbottle" + center_of_mass = list("x" = 16,"y" = 13) + volume = 120 + amount_per_transfer_from_this = 10 + possible_transfer_amounts = list(5,10,15,25,30,60,120) + flags = OPENCONTAINER + /obj/item/weapon/reagent_containers/glass/bucket desc = "It's a bucket." name = "bucket" diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index 9072ffafc8..da64f6a808 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -251,7 +251,7 @@ name = "purity hypo" desc = "A refined version of the standard autoinjector, allowing greater capacity. This variant excels at \ resolving viruses, infections, radiation, and genetic maladies." - filled_reagents = list("spaceacillin" = 9, "arithrazine" = 5, "ryetalyn" = 1) + filled_reagents = list("spaceacillin" = 4, "arithrazine" = 5, "prussian_blue" = 5, "ryetalyn" = 1) /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/pain name = "pain hypo" diff --git a/code/modules/reagents/reagents/medicine.dm b/code/modules/reagents/reagents/medicine.dm index 42b7969e4d..897c125b45 100644 --- a/code/modules/reagents/reagents/medicine.dm +++ b/code/modules/reagents/reagents/medicine.dm @@ -1128,6 +1128,7 @@ if(alien == IS_DIONA) return M.radiation = max(M.radiation - 30 * removed * M.species.chem_strength_heal, 0) + M.accumulated_rads = max(M.accumulated_rads - 30 * removed * M.species.chem_strength_heal, 0) /datum/reagent/arithrazine name = "Arithrazine" @@ -1145,6 +1146,7 @@ if(alien == IS_DIONA) return M.radiation = max(M.radiation - 70 * removed * M.species.chem_strength_heal, 0) + M.accumulated_rads = max(M.accumulated_rads - 70 * removed * M.species.chem_strength_heal, 0) M.adjustToxLoss(-10 * removed) if(prob(60)) M.take_organ_damage(4 * removed, 0) diff --git a/code/modules/reagents/reagents/medicine_vr.dm b/code/modules/reagents/reagents/medicine_vr.dm index 2d336597fb..fa72ab17a5 100644 --- a/code/modules/reagents/reagents/medicine_vr.dm +++ b/code/modules/reagents/reagents/medicine_vr.dm @@ -94,3 +94,22 @@ M.remove_a_modifier_of_type(/datum/modifier/resleeving_sickness) M.remove_a_modifier_of_type(/datum/modifier/faux_resleeving_sickness) */ //CHOMPStation removal end + + + +/datum/reagent/prussian_blue //We don't have iodine, so prussian blue we go. + name = "Prussian Blue" + id = "prussian_blue" + description = "Prussian Blue is an medication used to temporarily pause the effects of radiation poisoning to allow for treatment. Does not treat radiation sickness on its own." + taste_description = "salt" + reagent_state = SOLID + color = "#003153" //Blue! + metabolism = REM * 0.25//20 ticks to do things per unit injected. This means injecting 30u will give you 10 minutes to do what you need. + overdose = REAGENTS_OVERDOSE + scannable = 1 + +/datum/reagent/prussian_blue/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) + if(alien == IS_DIONA) + return + if(prob(10)) //Miniscule chance of removing some toxins. + M.adjustToxLoss(-10 * removed) diff --git a/code/modules/research/designs/circuit_assembly.dm b/code/modules/research/designs/circuit_assembly.dm index c637e450d2..e9271d6d5c 100644 --- a/code/modules/research/designs/circuit_assembly.dm +++ b/code/modules/research/designs/circuit_assembly.dm @@ -71,15 +71,61 @@ build_path = /obj/item/device/electronic_assembly/large sort_string = "UDAAC" -/datum/design/item/integrated_circuitry/assembly/custom_circuit_assembly_drone - name = "Drone custom assembly" +// CHOMPStation Edit Start +/datum/design/item/integrated_circuitry/assembly/custom_circuit_assembly_drone_a + name = "type-a electronic drone assembly" desc = "A customizable assembly optimized for autonomous devices." - id = "assembly-drone" + id = "assembly-drone-a" req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4, TECH_POWER = 4) materials = list(MAT_STEEL = 30000) build_path = /obj/item/device/electronic_assembly/drone sort_string = "UDAAD" +/datum/design/item/integrated_circuitry/assembly/custom_circuit_assembly_drone_b + name = "type-b electronic drone assembly" + desc = "It's a case, for building mobile electronics with. This one is armed and dangerous." + id = "assembly-drone-b" + req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4, TECH_POWER = 4) + materials = list(MAT_STEEL = 30000) + build_path = /obj/item/device/electronic_assembly/drone/arms + sort_string = "UDAAD" + +/datum/design/item/integrated_circuitry/assembly/custom_circuit_assembly_drone_c + name = "type-c electronic drone assembly" + desc = "It's a case, for building mobile electronics with. This one resembles a Securitron." + id = "assembly-drone-c" + req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4, TECH_POWER = 4) + materials = list(MAT_STEEL = 30000) + build_path = /obj/item/device/electronic_assembly/drone/secbot + sort_string = "UDAAD" + +/datum/design/item/integrated_circuitry/assembly/custom_circuit_assembly_drone_d + name = "type-d electronic drone assembly" + desc = "It's a case, for building mobile electronics with. This one resembles a Medibot" + id = "assembly-drone-d" + req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4, TECH_POWER = 4) + materials = list(MAT_STEEL = 30000) + build_path = /obj/item/device/electronic_assembly/drone/medbot + sort_string = "UDAAD" + +/datum/design/item/integrated_circuitry/assembly/custom_circuit_assembly_drone_e + name = "type-e electronic drone assembly" + desc = "It's a case, for building mobile electronics with. This one has a generic bot design." + id = "assembly-drone-e" + req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4, TECH_POWER = 4) + materials = list(MAT_STEEL = 30000) + build_path = /obj/item/device/electronic_assembly/drone/genbot + sort_string = "UDAAD" +/datum/design/item/integrated_circuitry/assembly/custom_circuit_assembly_drone_f + name = "type-f electronic drone assembly" + desc = "It's a case, for building mobile electronics with. This one has a hominoid design." + id = "assembly-drone-f" + req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4, TECH_POWER = 4) + materials = list(MAT_STEEL = 30000) + build_path = /obj/item/device/electronic_assembly/drone/android + sort_string = "UDAAD" +// CHOMPStation Edit End + /datum/design/item/integrated_circuitry/assembly/custom_circuit_assembly_device name = "Device custom assembly" desc = "An customizable assembly designed to interface with other devices." @@ -96,4 +142,4 @@ req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 4, TECH_POWER = 3, TECH_BIO = 5) materials = list(MAT_STEEL = 2000) build_path = /obj/item/weapon/implant/integrated_circuit - sort_string = "UDAAF" \ No newline at end of file + sort_string = "UDAAF" diff --git a/code/modules/tgui/states/notcontained.dm b/code/modules/tgui/states/notcontained.dm index 01811d427f..56b789e3c0 100644 --- a/code/modules/tgui/states/notcontained.dm +++ b/code/modules/tgui/states/notcontained.dm @@ -21,6 +21,3 @@ GLOBAL_DATUM_INIT(tgui_notcontained_state, /datum/tgui_state/notcontained_state, /mob/living/silicon/notcontained_can_use_tgui_topic(src_object) return default_can_use_tgui_topic(src_object) // Silicons use default bevhavior. - -/mob/living/simple_animal/drone/notcontained_can_use_tgui_topic(src_object) - return default_can_use_tgui_topic(src_object) // Drones use default bevhavior. diff --git a/code/modules/tooltip/jquery.min.js b/code/modules/tooltip/jquery.min.js new file mode 100644 index 0000000000..0f60b7bd0d --- /dev/null +++ b/code/modules/tooltip/jquery.min.js @@ -0,0 +1,5 @@ +/*! jQuery v1.11.3 | (c) 2005, 2015 jQuery Foundation, Inc. | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.3",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b="length"in a&&a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,aa=/[+~]/,ba=/'|\\/g,ca=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),da=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(ba,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",ea,!1):e.attachEvent&&e.attachEvent("onunload",ea)),p=!f(g),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ca,da),a[3]=(a[3]||a[4]||a[5]||"").replace(ca,da),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ca,da).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(ca,da).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sa(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function ta(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sa(ta(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ca,da),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1; + +return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML="
a",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function aa(){return!0}function ba(){return!1}function ca(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),ha=/^\s+/,ia=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ja=/<([\w:]+)/,ka=/\s*$/g,ra={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:k.htmlSerialize?[0,"",""]:[1,"X
","
"]},sa=da(y),ta=sa.appendChild(y.createElement("div"));ra.optgroup=ra.option,ra.tbody=ra.tfoot=ra.colgroup=ra.caption=ra.thead,ra.th=ra.td;function ua(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ua(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function va(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wa(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xa(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function ya(a){var b=pa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function za(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Aa(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Ba(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xa(b).text=a.text,ya(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!ga.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(ta.innerHTML=a.outerHTML,ta.removeChild(f=ta.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ua(f),h=ua(a),g=0;null!=(e=h[g]);++g)d[g]&&Ba(e,d[g]);if(b)if(c)for(h=h||ua(a),d=d||ua(f),g=0;null!=(e=h[g]);g++)Aa(e,d[g]);else Aa(a,f);return d=ua(f,"script"),d.length>0&&za(d,!i&&ua(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=da(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(la.test(f)){h=h||o.appendChild(b.createElement("div")),i=(ja.exec(f)||["",""])[1].toLowerCase(),l=ra[i]||ra._default,h.innerHTML=l[1]+f.replace(ia,"<$1>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&ha.test(f)&&p.push(b.createTextNode(ha.exec(f)[0])),!k.tbody){f="table"!==i||ka.test(f)?""!==l[1]||ka.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ua(p,"input"),va),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ua(o.appendChild(f),"script"),g&&za(h),c)){e=0;while(f=h[e++])oa.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ua(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&za(ua(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ua(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fa,""):void 0;if(!("string"!=typeof a||ma.test(a)||!k.htmlSerialize&&ga.test(a)||!k.leadingWhitespace&&ha.test(a)||ra[(ja.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ia,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ua(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ua(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&na.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ua(i,"script"),xa),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ua(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,ya),j=0;f>j;j++)d=g[j],oa.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qa,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Ca,Da={};function Ea(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fa(a){var b=y,c=Da[a];return c||(c=Ea(a,b),"none"!==c&&c||(Ca=(Ca||m("