Merge branch 'master' into master

This commit is contained in:
Izac Joof Forsgren
2020-08-10 23:15:30 +02:00
committed by GitHub
214 changed files with 7027 additions and 3702 deletions

View File

@@ -116,6 +116,8 @@ What is the naming convention for planes or layers?
#define HUD_LAYER 20 // Above lighting, but below obfuscation. For in-game HUD effects (whereas SCREEN_LAYER is for abstract/OOC things like inventory slots) #define HUD_LAYER 20 // Above lighting, but below obfuscation. For in-game HUD effects (whereas SCREEN_LAYER is for abstract/OOC things like inventory slots)
#define SCREEN_LAYER 22 // Mob HUD/effects layer #define SCREEN_LAYER 22 // Mob HUD/effects layer
#define PLANE_STATUS 2 //Status Indicators that show over mobs' heads when certain things like stuns affect them.
#define PLANE_ADMIN1 3 //Purely for shenanigans (below lighting) #define PLANE_ADMIN1 3 //Purely for shenanigans (below lighting)
#define PLANE_PLANETLIGHTING 4 //Lighting on planets #define PLANE_PLANETLIGHTING 4 //Lighting on planets
#define PLANE_LIGHTING 5 //Where the lighting (and darkness) lives #define PLANE_LIGHTING 5 //Where the lighting (and darkness) lives
@@ -138,8 +140,6 @@ What is the naming convention for planes or layers?
#define PLANE_MESONS 30 //Stuff seen with mesons, like open ceilings. This is 30 for downstreams. #define PLANE_MESONS 30 //Stuff seen with mesons, like open ceilings. This is 30 for downstreams.
#define PLANE_STATUS 31 //Status Indicators that show over mobs' heads when certain things like stuns affect them.
#define PLANE_ADMIN2 33 //Purely for shenanigans (above lighting) #define PLANE_ADMIN2 33 //Purely for shenanigans (above lighting)
#define PLANE_BUILDMODE 39 //Things that only show up when you have buildmode on #define PLANE_BUILDMODE 39 //Things that only show up when you have buildmode on

View File

@@ -432,3 +432,5 @@
#define EXAMINE_SKIPFEET 0x0100 #define EXAMINE_SKIPFEET 0x0100
#define MAX_NUTRITION 5000 //VOREStation Edit #define MAX_NUTRITION 5000 //VOREStation Edit
#define FAKE_INVIS_ALPHA_THRESHOLD 127 // If something's alpha var is at or below this number, certain things will pretend it is invisible.

View File

@@ -41,3 +41,11 @@
// 5 10 20 40 80 160 // 5 10 20 40 80 160
// 10 40 160 640 2560 // 10 40 160 640 2560
// Defines for Exosuit components.
#define MECH_HULL "Hull"
#define MECH_ACTUATOR "Actuator"
#define MECH_ARMOR "Plating"
#define MECH_GAS "Life Support"
#define MECH_ELECTRIC "Firmware"

View File

@@ -289,6 +289,11 @@ Turf and target are seperate in case you want to teleport some distance from a t
/proc/format_frequency(var/f) /proc/format_frequency(var/f)
return "[round(f / 10)].[f % 10]" return "[round(f / 10)].[f % 10]"
//Opposite of format, returns as a number
/proc/unformat_frequency(frequency)
frequency = text2num(frequency)
return frequency * 10
//This will update a mob's name, real_name, mind.name, data_core records, pda and id //This will update a mob's name, real_name, mind.name, data_core records, pda and id

View File

@@ -148,6 +148,41 @@ var/list/radiochannels = list(
"Talon" = TALON_FREQ //VOREStation Add "Talon" = TALON_FREQ //VOREStation Add
) )
// Hey, if anyone ever needs to update tgui/packages/tgui/constants.js with new radio channels
// I've kept this around just for you.
/* /client/verb/generate_tgui_radio_constants()
set name = "Generate TGUI Radio Constants"
set category = "Generate TGUI Radio Constants"
var/list/channel_info = list()
for(var/i in RADIO_LOW_FREQ to RADIO_HIGH_FREQ)
for(var/key in radiochannels)
if(i == radiochannels[key])
channel_info.Add(list(list("name" = key, "freq" = i, "color" = frequency_span_class(i))))
for(var/list/channel in channel_info)
switch(channel["color"])
if("deadsay") channel["color"] = "#530FAD"
if("radio") channel["color"] = "#008000"
if("deptradio") channel["color"] = "#ff00ff"
if("newscaster") channel["color"] = "#750000"
if("comradio") channel["color"] = "#193A7A"
if("syndradio") channel["color"] = "#6D3F40"
if("centradio") channel["color"] = "#5C5C8A"
if("airadio") channel["color"] = "#FF00FF"
if("entradio") channel["color"] = "#339966"
if("secradio") channel["color"] = "#A30000"
if("engradio") channel["color"] = "#A66300"
if("medradio") channel["color"] = "#008160"
if("sciradio") channel["color"] = "#993399"
if("supradio") channel["color"] = "#5F4519"
if("srvradio") channel["color"] = "#6eaa2c"
if("expradio") channel["color"] = "#555555"
to_chat(src, json_encode(channel_info)) */
// central command channels, i.e deathsquid & response teams // central command channels, i.e deathsquid & response teams
var/list/CENT_FREQS = list(ERT_FREQ, DTH_FREQ) var/list/CENT_FREQS = list(ERT_FREQ, DTH_FREQ)

View File

@@ -255,13 +255,13 @@ SUBSYSTEM_DEF(tgui)
* *
* return int The number of UIs closed. * return int The number of UIs closed.
**/ **/
/datum/controller/subsystem/tgui/proc/close_user_uis(mob/user, datum/src_object) /datum/controller/subsystem/tgui/proc/close_user_uis(mob/user, datum/src_object, logout = FALSE)
var/count = 0 var/count = 0
if(length(user?.tgui_open_uis) == 0) if(length(user?.tgui_open_uis) == 0)
return count return count
for(var/datum/tgui/ui in user.tgui_open_uis) for(var/datum/tgui/ui in user.tgui_open_uis)
if(isnull(src_object) || ui.src_object == src_object) if(isnull(src_object) || ui.src_object == src_object)
ui.close() ui.close(logout = logout)
count++ count++
return count return count
@@ -315,7 +315,7 @@ SUBSYSTEM_DEF(tgui)
* return int The number of UIs closed. * return int The number of UIs closed.
**/ **/
/datum/controller/subsystem/tgui/proc/on_logout(mob/user) /datum/controller/subsystem/tgui/proc/on_logout(mob/user)
return close_user_uis(user) return close_user_uis(user, logout = TRUE)
/** /**
* private * private

View File

@@ -33,6 +33,12 @@
path =/obj/item/ammo_casing/a12g/stunshell path =/obj/item/ammo_casing/a12g/stunshell
hidden = 1 hidden = 1
/datum/category_item/autolathe/arms/flechetteshell
name = "ammunition (flechette cartridge, shotgun)"
path =/obj/item/ammo_casing/a12g/flechette
hidden = 1
man_rating = 2
////////////////// //////////////////
/*Ammo magazines*/ /*Ammo magazines*/
////////////////// //////////////////
@@ -64,6 +70,18 @@
name = "pistol magazine (.45 flash)" name = "pistol magazine (.45 flash)"
path =/obj/item/ammo_magazine/m45/flash path =/obj/item/ammo_magazine/m45/flash
/datum/category_item/autolathe/arms/pistol_45ap
name = "pistol magazine (.45 armor piercing)"
path =/obj/item/ammo_magazine/m45/ap
hidden = 1
resources = list(DEFAULT_WALL_MATERIAL = 500, MAT_PLASTEEL = 300)
/datum/category_item/autolathe/arms/pistol_45hp
name = "pistol magazine (.45 hollowpoint)"
path =/obj/item/ammo_magazine/m45/hp
hidden = 1
resources = list(DEFAULT_WALL_MATERIAL = 500, MAT_PLASTIC = 200)
/datum/category_item/autolathe/arms/pistol_45uzi /datum/category_item/autolathe/arms/pistol_45uzi
name = "uzi magazine (.45)" name = "uzi magazine (.45)"
path =/obj/item/ammo_magazine/m45uzi path =/obj/item/ammo_magazine/m45uzi
@@ -138,6 +156,12 @@
name = "top-mounted SMG magazine (9mm flash)" name = "top-mounted SMG magazine (9mm flash)"
path =/obj/item/ammo_magazine/m9mmt/flash path =/obj/item/ammo_magazine/m9mmt/flash
/datum/category_item/autolathe/arms/smg_9mmap
name = "top-mounted SMG magazine (9mm armor piercing)"
path =/obj/item/ammo_magazine/m9mmt/ap
hidden = 1
man_rating = 2
/////// 10mm /////// 10mm
/datum/category_item/autolathe/arms/smg_10mm /datum/category_item/autolathe/arms/smg_10mm
name = "SMG magazine (10mm)" name = "SMG magazine (10mm)"

View File

@@ -71,6 +71,7 @@ var/datum/category_collection/autolathe/autolathe_recipes
var/is_stack // Creates multiple of an item if applied to non-stack items var/is_stack // Creates multiple of an item if applied to non-stack items
var/max_stack var/max_stack
var/no_scale var/no_scale
var/man_rating = 0
/datum/category_item/autolathe/dd_SortValue() /datum/category_item/autolathe/dd_SortValue()
return name return name

View File

@@ -98,6 +98,18 @@
is_stack = TRUE is_stack = TRUE
no_scale = TRUE //prevents material duplication exploits no_scale = TRUE //prevents material duplication exploits
/datum/category_item/autolathe/general/plasteel
name = "plasteel sheets"
path =/obj/item/stack/material/plasteel
is_stack = TRUE
no_scale = TRUE //prevents material duplication exploits
/datum/category_item/autolathe/general/plastic
name = "plastic sheets"
path =/obj/item/stack/material/plastic
is_stack = TRUE
no_scale = TRUE //prevents material duplication exploits
//TFF 24/12/19 - Let people print more spray bottles if needed. //TFF 24/12/19 - Let people print more spray bottles if needed.
/datum/category_item/autolathe/general/spraybottle /datum/category_item/autolathe/general/spraybottle
name = "spray bottle" name = "spray bottle"
@@ -137,6 +149,12 @@
name = "light fixture battery" name = "light fixture battery"
path =/obj/item/weapon/cell/emergency_light path =/obj/item/weapon/cell/emergency_light
/datum/category_item/autolathe/general/idcard
name = "ID Card"
path = /obj/item/weapon/card/id
resources = list(DEFAULT_WALL_MATERIAL = 100, MAT_GLASS = 100, MAT_PLASTIC = 300)
man_rating = 2
/datum/category_item/autolathe/general/handcuffs /datum/category_item/autolathe/general/handcuffs
name = "handcuffs" name = "handcuffs"
path =/obj/item/weapon/handcuffs path =/obj/item/weapon/handcuffs

View File

@@ -332,6 +332,19 @@ var/global/list/PDA_Manifest = list()
var/datum/job/J = SSjob.get_job(assignment) var/datum/job/J = SSjob.get_job(assignment)
hidden = J?.offmap_spawn hidden = J?.offmap_spawn
/* Note: Due to cached_character_icon, a number of emergent properties occur due to the initialization
* order of readied-up vs latejoiners. Namely, latejoiners will get a uniform in their datacore picture, but readied-up will
* not. This is due to the fact that SSticker calls data_core.manifest_inject() inside of ticker/proc/create_characters(),
* but does not equip them until ticker/proc/equip_characters(), which is called later. So, this proc is literally called before
* they ever get their equipment, and so it can't get a picture of them in their equipment.
* Latejoiners do not have this problem, because /mob/new_player/proc/AttemptLateSpawn calls EquipRank() before it calls
* this proc, which means that they're already clothed by the time they get their picture taken here.
* The COMPILE_OVERLAYS() here is just to bypass SSoverlays taking for-fucking-ever to update the mob, since we're about to
* take a picture of them, we want all the overlays.
*/
COMPILE_OVERLAYS(H)
SSoverlays.queue -= H
var/id = generate_record_id() var/id = generate_record_id()
//General Record //General Record
var/datum/data/record/G = CreateGeneralRecord(H, id, hidden) var/datum/data/record/G = CreateGeneralRecord(H, id, hidden)
@@ -418,8 +431,8 @@ var/global/list/PDA_Manifest = list()
var/icon/side var/icon/side
if(H) if(H)
var/icon/charicon = cached_character_icon(H) var/icon/charicon = cached_character_icon(H)
front = icon(charicon, dir = SOUTH) front = icon(charicon, dir = SOUTH, frame = 1)
side = icon(charicon, dir = WEST) side = icon(charicon, dir = WEST, frame = 1)
else // Sending null things through browse_rsc() makes a runtime and breaks the console trying to view the record. else // Sending null things through browse_rsc() makes a runtime and breaks the console trying to view the record.
front = icon('html/images/no_image32.png') front = icon('html/images/no_image32.png')
side = icon('html/images/no_image32.png') side = icon('html/images/no_image32.png')

View File

@@ -4,7 +4,7 @@
mid_sounds = list('sound/machines/shower/shower_mid1.ogg'=1,'sound/machines/shower/shower_mid2.ogg'=1,'sound/machines/shower/shower_mid3.ogg'=1) mid_sounds = list('sound/machines/shower/shower_mid1.ogg'=1,'sound/machines/shower/shower_mid2.ogg'=1,'sound/machines/shower/shower_mid3.ogg'=1)
mid_length = 10 mid_length = 10
end_sound = 'sound/machines/shower/shower_end.ogg' end_sound = 'sound/machines/shower/shower_end.ogg'
volume = 20 volume = 15
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -89,6 +89,7 @@
name = "Stationery - sticky notes (50)" name = "Stationery - sticky notes (50)"
contains = list(/obj/item/sticky_pad/random) contains = list(/obj/item/sticky_pad/random)
cost = 10 cost = 10
containertype = /obj/structure/closet/crate/ummarcar
containername = "\improper Sticky notes crate" containername = "\improper Sticky notes crate"
/datum/supply_pack/supply/spare_pda /datum/supply_pack/supply/spare_pda

View File

@@ -154,7 +154,7 @@
/datum/wires/tgui_act(action, list/params) /datum/wires/tgui_act(action, list/params)
if(..()) if(..())
return return TRUE
var/mob/user = usr var/mob/user = usr
if(!interactable(user)) if(!interactable(user))

View File

@@ -371,20 +371,22 @@ var/list/mob/living/forced_ambiance_list = new
L.lastarea = newarea L.lastarea = newarea
L.lastareachange = world.time L.lastareachange = world.time
play_ambience(L) play_ambience(L, initial = TRUE)
if(no_spoilers) if(no_spoilers)
L.disable_spoiler_vision() L.disable_spoiler_vision()
/area/proc/play_ambience(var/mob/living/L) /area/proc/play_ambience(var/mob/living/L, initial = TRUE)
// Ambience goes down here -- make sure to list each area seperately for ease of adding things in later, thanks! Note: areas adjacent to each other should have the same sounds to prevent cutoff when possible.- LastyScratch // Ambience goes down here -- make sure to list each area seperately for ease of adding things in later, thanks! Note: areas adjacent to each other should have the same sounds to prevent cutoff when possible.- LastyScratch
if(!(L && L.is_preference_enabled(/datum/client_preference/play_ambiance))) return if(!(L && L.is_preference_enabled(/datum/client_preference/play_ambiance))) return
// If we previously were in an area with force-played ambiance, stop it. // If we previously were in an area with force-played ambiance, stop it.
if(L in forced_ambiance_list) if((L in forced_ambiance_list) && initial)
L << sound(null, channel = CHANNEL_AMBIENCE_FORCED) L << sound(null, channel = CHANNEL_AMBIENCE_FORCED)
forced_ambiance_list -= L forced_ambiance_list -= L
if(forced_ambience) if(forced_ambience)
if(L in forced_ambiance_list)
return
if(forced_ambience.len) if(forced_ambience.len)
forced_ambiance_list |= L forced_ambiance_list |= L
var/sound/chosen_ambiance = pick(forced_ambience) var/sound/chosen_ambiance = pick(forced_ambience)

View File

@@ -127,6 +127,7 @@ var/global/list/datum/dna/gene/dna_genes[0]
new_dna.species=species new_dna.species=species
new_dna.body_markings=body_markings.Copy() new_dna.body_markings=body_markings.Copy()
new_dna.base_species=base_species //VOREStation Edit new_dna.base_species=base_species //VOREStation Edit
new_dna.custom_species=custom_species //VOREStaton Edit
new_dna.species_traits=species_traits.Copy() //VOREStation Edit new_dna.species_traits=species_traits.Copy() //VOREStation Edit
new_dna.blood_color=blood_color //VOREStation Edit new_dna.blood_color=blood_color //VOREStation Edit
for(var/b=1;b<=DNA_SE_LENGTH;b++) for(var/b=1;b<=DNA_SE_LENGTH;b++)

View File

@@ -455,13 +455,13 @@
/obj/machinery/computer/scan_consolenew/tgui_act(action, params) /obj/machinery/computer/scan_consolenew/tgui_act(action, params)
if(..()) if(..())
return FALSE // don't update uis return TRUE
if(!istype(usr.loc, /turf)) if(!istype(usr.loc, /turf))
return FALSE // don't update uis return TRUE
if(!src || !src.connected) if(!src || !src.connected)
return FALSE // don't update uis return TRUE
if(irradiating) // Make sure that it isn't already irradiating someone... if(irradiating) // Make sure that it isn't already irradiating someone...
return FALSE // don't update uis return TRUE
add_fingerprint(usr) add_fingerprint(usr)

View File

@@ -293,7 +293,7 @@
/obj/machinery/sleeper/tgui_act(action, params, datum/tgui/ui, datum/tgui_state/state) /obj/machinery/sleeper/tgui_act(action, params, datum/tgui/ui, datum/tgui_state/state)
if(..()) if(..())
return return TRUE
if(!controls_inside && usr == occupant) if(!controls_inside && usr == occupant)
return return
if(panel_open) if(panel_open)

View File

@@ -216,7 +216,11 @@
var/reagentData[0] var/reagentData[0]
if(H.reagents.reagent_list.len >= 1) if(H.reagents.reagent_list.len >= 1)
for(var/datum/reagent/R in H.reagents.reagent_list) for(var/datum/reagent/R in H.reagents.reagent_list)
reagentData[++reagentData.len] = list("name" = R.name, "amount" = R.volume) reagentData[++reagentData.len] = list(
"name" = R.name,
"amount" = R.volume,
"overdose" = (R.overdose && R.volume > R.overdose) ? TRUE : FALSE,
)
else else
reagentData = null reagentData = null
@@ -225,7 +229,11 @@
var/ingestedData[0] var/ingestedData[0]
if(H.ingested.reagent_list.len >= 1) if(H.ingested.reagent_list.len >= 1)
for(var/datum/reagent/R in H.ingested.reagent_list) for(var/datum/reagent/R in H.ingested.reagent_list)
ingestedData[++ingestedData.len] = list("name" = R.name, "amount" = R.volume) ingestedData[++ingestedData.len] = list(
"name" = R.name,
"amount" = R.volume,
"overdose" = (R.overdose && R.volume > R.overdose) ? TRUE : FALSE,
)
else else
ingestedData = null ingestedData = null
@@ -315,7 +323,7 @@
/obj/machinery/bodyscanner/tgui_act(action, params) /obj/machinery/bodyscanner/tgui_act(action, params)
if(..()) if(..())
return return TRUE
. = TRUE . = TRUE
switch(action) switch(action)

View File

@@ -12,8 +12,8 @@
circuit = /obj/item/weapon/circuitboard/autolathe circuit = /obj/item/weapon/circuitboard/autolathe
var/datum/category_collection/autolathe/machine_recipes var/datum/category_collection/autolathe/machine_recipes
var/list/stored_material = list(DEFAULT_WALL_MATERIAL = 0, "glass" = 0) var/list/stored_material = list(DEFAULT_WALL_MATERIAL = 0, MAT_GLASS = 0, MAT_PLASTEEL = 0, MAT_PLASTIC = 0)
var/list/storage_capacity = list(DEFAULT_WALL_MATERIAL = 0, "glass" = 0) var/list/storage_capacity = list(DEFAULT_WALL_MATERIAL = 0, MAT_GLASS = 0, MAT_PLASTEEL = 0, MAT_PLASTIC = 0)
var/datum/category_group/autolathe/current_category var/datum/category_group/autolathe/current_category
var/hacked = 0 var/hacked = 0
@@ -26,6 +26,9 @@
var/datum/wires/autolathe/wires = null var/datum/wires/autolathe/wires = null
var/mb_rating = 0
var/man_rating = 0
var/filtertext var/filtertext
/obj/machinery/autolathe/Initialize() /obj/machinery/autolathe/Initialize()
@@ -64,6 +67,9 @@
var/list/material_bottom = list("<tr>") var/list/material_bottom = list("<tr>")
for(var/material in stored_material) for(var/material in stored_material)
if(material != DEFAULT_WALL_MATERIAL && material != MAT_GLASS) // Don't show the Extras unless people care enough to put them in.
if(stored_material[material] <= 0)
continue
material_top += "<td width = '25%' align = center><b>[material]</b></td>" material_top += "<td width = '25%' align = center><b>[material]</b></td>"
material_bottom += "<td width = '25%' align = center>[stored_material[material]]<b>/[storage_capacity[material]]</b></td>" material_bottom += "<td width = '25%' align = center>[stored_material[material]]<b>/[storage_capacity[material]]</b></td>"
@@ -72,7 +78,9 @@
dat += "<h2>Printable Designs</h2><h3>Showing: <a href='?src=\ref[src];change_category=1'>[current_category]</a>.</h3></center><table width = '100%'>" dat += "<h2>Printable Designs</h2><h3>Showing: <a href='?src=\ref[src];change_category=1'>[current_category]</a>.</h3></center><table width = '100%'>"
for(var/datum/category_item/autolathe/R in current_category.items) for(var/datum/category_item/autolathe/R in current_category.items)
if(R.hidden && !hacked) if(R.hidden && !hacked) // Illegal or nonstandard.
continue
if(R.man_rating > man_rating) // Advanced parts.
continue continue
if(filtertext && findtext(R.name, filtertext) == 0) if(filtertext && findtext(R.name, filtertext) == 0)
continue continue
@@ -311,14 +319,16 @@
//Updates overall lathe storage size. //Updates overall lathe storage size.
/obj/machinery/autolathe/RefreshParts() /obj/machinery/autolathe/RefreshParts()
..() ..()
var/mb_rating = 0 mb_rating = 0
var/man_rating = 0 man_rating = 0
for(var/obj/item/weapon/stock_parts/matter_bin/MB in component_parts) for(var/obj/item/weapon/stock_parts/matter_bin/MB in component_parts)
mb_rating += MB.rating mb_rating += MB.rating
for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts) for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
man_rating += M.rating man_rating += M.rating
storage_capacity[DEFAULT_WALL_MATERIAL] = mb_rating * 25000 storage_capacity[DEFAULT_WALL_MATERIAL] = mb_rating * 25000
storage_capacity[MAT_PLASTIC] = mb_rating * 20000
storage_capacity[MAT_PLASTEEL] = mb_rating * 16250
storage_capacity["glass"] = mb_rating * 12500 storage_capacity["glass"] = mb_rating * 12500
build_time = 50 / man_rating build_time = 50 / man_rating
mat_efficiency = 1.1 - man_rating * 0.1// Normally, price is 1.25 the amount of material, so this shouldn't go higher than 0.6. Maximum rating of parts is 5 mat_efficiency = 1.1 - man_rating * 0.1// Normally, price is 1.25 the amount of material, so this shouldn't go higher than 0.6. Maximum rating of parts is 5

View File

@@ -129,7 +129,7 @@
/obj/machinery/computer/operating/tgui_act(action, params) /obj/machinery/computer/operating/tgui_act(action, params)
if(..()) if(..())
return return TRUE
if((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon))) if((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon)))
usr.set_machine(src) usr.set_machine(src)

View File

@@ -14,17 +14,7 @@
/obj/item/clothing/suit/syndicatefake = 2, /obj/item/clothing/suit/syndicatefake = 2,
/obj/item/weapon/storage/fancy/crayons = 2, /obj/item/weapon/storage/fancy/crayons = 2,
/obj/item/toy/spinningtoy = 2, /obj/item/toy/spinningtoy = 2,
/obj/item/toy/prize/ripley = 1, /obj/random/mech_toy = 1,
/obj/item/toy/prize/fireripley = 1,
/obj/item/toy/prize/deathripley = 1,
/obj/item/toy/prize/gygax = 1,
/obj/item/toy/prize/durand = 1,
/obj/item/toy/prize/honk = 1,
/obj/item/toy/prize/marauder = 1,
/obj/item/toy/prize/seraph = 1,
/obj/item/toy/prize/mauler = 1,
/obj/item/toy/prize/odysseus = 1,
/obj/item/toy/prize/phazon = 1,
/obj/item/weapon/reagent_containers/spray/waterflower = 1, /obj/item/weapon/reagent_containers/spray/waterflower = 1,
/obj/random/action_figure = 1, /obj/random/action_figure = 1,
/obj/random/plushie = 1, /obj/random/plushie = 1,

View File

@@ -198,7 +198,7 @@
/obj/machinery/computer/cloning/tgui_act(action, params) /obj/machinery/computer/cloning/tgui_act(action, params)
if(..()) if(..())
return return TRUE
. = TRUE . = TRUE
switch(tgui_modal_act(src, action, params)) switch(tgui_modal_act(src, action, params))

View File

@@ -170,7 +170,7 @@
data["virus"] = list() data["virus"] = list()
for(var/ID in virusDB) for(var/ID in virusDB)
var/datum/data/record/v = virusDB[ID] var/datum/data/record/v = virusDB[ID]
data["virus"] += list(list("name" = v.fields["name"], "D" = v)) data["virus"] += list(list("name" = v.fields["name"], "D" = "\ref[v]"))
if(MED_DATA_MEDBOT) if(MED_DATA_MEDBOT)
data["medbots"] = list() data["medbots"] = list()
for(var/mob/living/bot/medbot/M in mob_list) for(var/mob/living/bot/medbot/M in mob_list)
@@ -198,7 +198,7 @@
/obj/machinery/computer/med_data/tgui_act(action, params) /obj/machinery/computer/med_data/tgui_act(action, params)
if(..()) if(..())
return return TRUE
if(!data_core.general.Find(active1)) if(!data_core.general.Find(active1))
active1 = null active1 = null
@@ -266,16 +266,9 @@
active2 = null active2 = null
if("vir") if("vir")
var/datum/data/record/v = locate(params["vir"]) var/datum/data/record/v = locate(params["vir"])
var/list/payload = list( if(!istype(v))
id = v.fields["id"], return FALSE
name = v.fields["name"], tgui_modal_message(src, "virus", "", null, v.fields["tgui_description"])
max_stages = "Unknown",
spread_text = v.fields["spread type"],
cure = v.fields["antigen"],
desc = v.fields["description"],
severity = "Unknown"
);
tgui_modal_message(src, "virus", "", null, payload)
if("del_all") if("del_all")
for(var/datum/data/record/R in data_core.medical) for(var/datum/data/record/R in data_core.medical)
qdel(R) qdel(R)
@@ -508,3 +501,6 @@
icon_screen = "medlaptop" icon_screen = "medlaptop"
circuit = /obj/item/weapon/circuitboard/med_data/laptop circuit = /obj/item/weapon/circuitboard/med_data/laptop
density = 0 density = 0
#undef FIELD
#undef MED_FIELD

View File

@@ -141,7 +141,7 @@
/obj/machinery/atmospherics/unary/cryo_cell/tgui_act(action, params) /obj/machinery/atmospherics/unary/cryo_cell/tgui_act(action, params)
if(..() || usr == occupant) if(..() || usr == occupant)
return return TRUE
. = TRUE . = TRUE
switch(action) switch(action)

View File

@@ -1127,6 +1127,7 @@ About the new airlock wires panel:
SetWeakened(5) SetWeakened(5)
var/turf/T = get_turf(src) var/turf/T = get_turf(src)
T.add_blood(src) T.add_blood(src)
return 1
/mob/living/carbon/airlock_crush(var/crush_damage) /mob/living/carbon/airlock_crush(var/crush_damage)
. = ..() . = ..()

View File

@@ -10,6 +10,9 @@
// UPDATE 06.04.2018 // UPDATE 06.04.2018
// The emag thing wasn't working as intended, manually overwrote it. // The emag thing wasn't working as intended, manually overwrote it.
#define BLAST_DOOR_CRUSH_DAMAGE 40
#define SHUTTER_CRUSH_DAMAGE 5 // YW Edit - Shutter damage 5.
/obj/machinery/door/blast /obj/machinery/door/blast
name = "Blast Door" name = "Blast Door"
desc = "That looks like it doesn't open easily." desc = "That looks like it doesn't open easily."
@@ -24,6 +27,8 @@
var/icon_state_closing = null var/icon_state_closing = null
var/open_sound = 'sound/machines/blastdooropen.ogg' var/open_sound = 'sound/machines/blastdooropen.ogg'
var/close_sound = 'sound/machines/blastdoorclose.ogg' var/close_sound = 'sound/machines/blastdoorclose.ogg'
var/damage = BLAST_DOOR_CRUSH_DAMAGE
var/multiplier = 1 // The multiplier for how powerful our YEET is.
closed_layer = ON_WINDOW_LAYER // Above airlocks when closed closed_layer = ON_WINDOW_LAYER // Above airlocks when closed
var/id = 1.0 var/id = 1.0
@@ -61,9 +66,13 @@
SSradiation.resistance_cache.Remove(get_turf(src)) SSradiation.resistance_cache.Remove(get_turf(src))
return return
// Has to be in here, comment at the top is older than the emag_act code on doors proper // Proc: emag_act()
// Description: Emag action to allow blast doors to double their yeet distance and speed.
/obj/machinery/door/blast/emag_act() /obj/machinery/door/blast/emag_act()
return -1 if(!emagged)
emagged = 1
multiplier = 2 // Haha emag go yeet
return 1
// Blast doors are triggered remotely, so nobody is allowed to physically influence it. // Blast doors are triggered remotely, so nobody is allowed to physically influence it.
/obj/machinery/door/blast/allowed(mob/M) /obj/machinery/door/blast/allowed(mob/M)
@@ -88,6 +97,10 @@
// Parameters: None // Parameters: None
// Description: Closes the door. No checks are done inside this proc. // Description: Closes the door. No checks are done inside this proc.
/obj/machinery/door/blast/proc/force_close() /obj/machinery/door/blast/proc/force_close()
// Blast door turf checks. We do this before the door closes to prevent it from failing after the door is closed, because obv a closed door will block any adjacency checks.
var/turf/T = get_turf(src)
var/list/yeet_turfs = T.CardinalTurfs(TRUE)
src.operating = 1 src.operating = 1
playsound(src, close_sound, 100, 1) playsound(src, close_sound, 100, 1)
src.layer = closed_layer src.layer = closed_layer
@@ -99,6 +112,14 @@
sleep(15) sleep(15)
src.operating = 0 src.operating = 0
// Blast door crushing.
for(var/turf/turf in locs)
for(var/atom/movable/AM in turf)
if(AM.airlock_crush(damage))
if(LAZYLEN(yeet_turfs))
AM.throw_at(get_edge_target_turf(src, get_dir(src, pick(yeet_turfs))), (rand(1,3) * multiplier), (rand(2,4) * multiplier)) // YEET.
take_damage(damage*0.2)
// Proc: force_toggle() // Proc: force_toggle()
// Parameters: None // Parameters: None
// Description: Opens or closes the door, depending on current state. No checks are done inside this proc. // Description: Opens or closes the door, depending on current state. No checks are done inside this proc.
@@ -300,3 +321,7 @@ obj/machinery/door/blast/regular/open
icon_state_closed = "shutter1" icon_state_closed = "shutter1"
icon_state_closing = "shutterc1" icon_state_closing = "shutterc1"
icon_state = "shutter1" icon_state = "shutter1"
damage = SHUTTER_CRUSH_DAMAGE
#undef BLAST_DOOR_CRUSH_DAMAGE
#undef SHUTTER_CRUSH_DAMAGE

View File

@@ -213,6 +213,13 @@ Class Procs:
/obj/machinery/proc/inoperable(var/additional_flags = 0) /obj/machinery/proc/inoperable(var/additional_flags = 0)
return (stat & (NOPOWER | BROKEN | additional_flags)) return (stat & (NOPOWER | BROKEN | additional_flags))
// Duplicate of below because we don't want to fuck around with CanUseTopic in TGUI
// TODO: Replace this with can_interact from /tg/
/obj/machinery/tgui_status(mob/user)
if(!interact_offline && (stat & (NOPOWER | BROKEN)))
return STATUS_CLOSE
return ..()
/obj/machinery/CanUseTopic(var/mob/user) /obj/machinery/CanUseTopic(var/mob/user)
if(!interact_offline && (stat & (NOPOWER | BROKEN))) if(!interact_offline && (stat & (NOPOWER | BROKEN)))
return STATUS_CLOSE return STATUS_CLOSE

View File

@@ -17,6 +17,14 @@
max_special_equip = 1 max_special_equip = 1
cargo_capacity = 1 cargo_capacity = 1
starting_components = list(
/obj/item/mecha_parts/component/hull/durable,
/obj/item/mecha_parts/component/actuator,
/obj/item/mecha_parts/component/armor/reinforced,
/obj/item/mecha_parts/component/gas,
/obj/item/mecha_parts/component/electrical
)
/* /*
/obj/mecha/combat/range_action(target as obj|mob|turf) /obj/mecha/combat/range_action(target as obj|mob|turf)
if(internal_damage&MECHA_INT_CONTROL_LOST) if(internal_damage&MECHA_INT_CONTROL_LOST)

View File

@@ -5,8 +5,8 @@
initial_icon = "durand" initial_icon = "durand"
step_in = 4 step_in = 4
dir_in = 1 //Facing North. dir_in = 1 //Facing North.
health = 400 health = 300
maxhealth = 400 //Don't forget to update the /old variant if you change this number. maxhealth = 300 //Don't forget to update the /old variant if you change this number.
deflect_chance = 20 deflect_chance = 20
damage_absorption = list("brute"=0.5,"fire"=1.1,"bullet"=0.65,"laser"=0.85,"energy"=0.9,"bomb"=0.8) damage_absorption = list("brute"=0.5,"fire"=1.1,"bullet"=0.65,"laser"=0.85,"energy"=0.9,"bomb"=0.8)
max_temperature = 30000 max_temperature = 30000
@@ -23,6 +23,14 @@
max_universal_equip = 1 max_universal_equip = 1
max_special_equip = 1 max_special_equip = 1
starting_components = list(
/obj/item/mecha_parts/component/hull/durable,
/obj/item/mecha_parts/component/actuator,
/obj/item/mecha_parts/component/armor/military,
/obj/item/mecha_parts/component/gas,
/obj/item/mecha_parts/component/electrical
)
defence_mode_possible = 1 defence_mode_possible = 1
/* /*
@@ -73,5 +81,5 @@
/obj/mecha/combat/durand/old/New() /obj/mecha/combat/durand/old/New()
..() ..()
health = 25 health = 25
maxhealth = 350 //Just slightly worse. maxhealth = 250 //Just slightly worse.
cell.charge = rand(0, (cell.charge/2)) cell.charge = rand(0, (cell.charge/2))

View File

@@ -5,8 +5,8 @@
initial_icon = "gygax" initial_icon = "gygax"
step_in = 3 step_in = 3
dir_in = 1 //Facing North. dir_in = 1 //Facing North.
health = 300 health = 250
maxhealth = 300 //Don't forget to update the /old variant if you change this number. maxhealth = 250 //Don't forget to update the /old variant if you change this number.
deflect_chance = 15 deflect_chance = 15
damage_absorption = list("brute"=0.75,"fire"=1,"bullet"=0.8,"laser"=0.7,"energy"=0.85,"bomb"=1) damage_absorption = list("brute"=0.75,"fire"=1,"bullet"=0.8,"laser"=0.7,"energy"=0.85,"bomb"=1)
max_temperature = 25000 max_temperature = 25000
@@ -21,6 +21,14 @@
max_universal_equip = 1 max_universal_equip = 1
max_special_equip = 1 max_special_equip = 1
starting_components = list(
/obj/item/mecha_parts/component/hull/lightweight,
/obj/item/mecha_parts/component/actuator,
/obj/item/mecha_parts/component/armor/marshal,
/obj/item/mecha_parts/component/gas,
/obj/item/mecha_parts/component/electrical
)
overload_possible = 1 overload_possible = 1
//Not quite sure how to move those yet. //Not quite sure how to move those yet.
@@ -58,17 +66,12 @@
max_universal_equip = 1 max_universal_equip = 1
max_special_equip = 2 max_special_equip = 2
/obj/mecha/combat/gygax/dark/Initialize() starting_equipment = list(
..() /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot,
var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/grenade/clusterbang,
ME.attach(src) /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay,
ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/grenade/clusterbang /obj/item/mecha_parts/mecha_equipment/teleporter
ME.attach(src) )
ME = new /obj/item/mecha_parts/mecha_equipment/teleporter
ME.attach(src)
ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay
ME.attach(src)
return
/obj/mecha/combat/gygax/dark/add_cell(var/obj/item/weapon/cell/C=null) /obj/mecha/combat/gygax/dark/add_cell(var/obj/item/weapon/cell/C=null)
if(C) if(C)
@@ -101,6 +104,14 @@
max_universal_equip = 1 max_universal_equip = 1
max_special_equip = 1 max_special_equip = 1
starting_components = list(
/obj/item/mecha_parts/component/hull,
/obj/item/mecha_parts/component/actuator,
/obj/item/mecha_parts/component/armor/lightweight,
/obj/item/mecha_parts/component/gas,
/obj/item/mecha_parts/component/electrical
)
var/obj/item/clothing/glasses/hud/health/mech/hud var/obj/item/clothing/glasses/hud/health/mech/hud
/obj/mecha/combat/gygax/serenity/New() /obj/mecha/combat/gygax/serenity/New()

View File

@@ -5,8 +5,8 @@
icon_state = "marauder" icon_state = "marauder"
initial_icon = "marauder" initial_icon = "marauder"
step_in = 5 step_in = 5
health = 500 health = 350
maxhealth = 500 //Don't forget to update the /old variant if you change this number. maxhealth = 350 //Don't forget to update the /old variant if you change this number.
deflect_chance = 25 deflect_chance = 25
damage_absorption = list("brute"=0.5,"fire"=0.7,"bullet"=0.45,"laser"=0.6,"energy"=0.7,"bomb"=0.7) damage_absorption = list("brute"=0.5,"fire"=0.7,"bullet"=0.45,"laser"=0.6,"energy"=0.7,"bomb"=0.7)
max_temperature = 60000 max_temperature = 60000
@@ -29,6 +29,21 @@
zoom_possible = 1 zoom_possible = 1
thrusters_possible = 1 thrusters_possible = 1
starting_components = list(
/obj/item/mecha_parts/component/hull/durable,
/obj/item/mecha_parts/component/actuator,
/obj/item/mecha_parts/component/armor/military,
/obj/item/mecha_parts/component/gas,
/obj/item/mecha_parts/component/electrical
)
starting_equipment = list(
/obj/item/mecha_parts/mecha_equipment/weapon/energy/pulse,
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive,
/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay,
/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster
)
/obj/mecha/combat/marauder/seraph /obj/mecha/combat/marauder/seraph
desc = "Heavy-duty, command-type exosuit. This is a custom model, utilized only by high-ranking military personnel." desc = "Heavy-duty, command-type exosuit. This is a custom model, utilized only by high-ranking military personnel."
name = "Seraph" name = "Seraph"
@@ -37,12 +52,20 @@
initial_icon = "seraph" initial_icon = "seraph"
operation_req_access = list(access_cent_creed) operation_req_access = list(access_cent_creed)
step_in = 3 step_in = 3
health = 550 health = 450
wreckage = /obj/effect/decal/mecha_wreckage/seraph wreckage = /obj/effect/decal/mecha_wreckage/seraph
internal_damage_threshold = 20 internal_damage_threshold = 20
force = 55 force = 55
max_equip = 5 max_equip = 5
starting_equipment = list(
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot,
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive,
/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay,
/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster,
/obj/item/mecha_parts/mecha_equipment/teleporter
)
//Note that is the Mauler //Note that is the Mauler
/obj/mecha/combat/marauder/mauler /obj/mecha/combat/marauder/mauler
desc = "Heavy-duty, combat exosuit, developed off of the existing Marauder model." desc = "Heavy-duty, combat exosuit, developed off of the existing Marauder model."
@@ -53,40 +76,6 @@
wreckage = /obj/effect/decal/mecha_wreckage/mauler wreckage = /obj/effect/decal/mecha_wreckage/mauler
mech_faction = MECH_FACTION_SYNDI mech_faction = MECH_FACTION_SYNDI
//Note that is the default Marauder
/obj/mecha/combat/marauder/Initialize()
..()
var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/energy/pulse
ME.attach(src)
ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive
ME.attach(src)
ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay(src)
ME.attach(src)
ME = new /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster(src)
ME.attach(src)
return
//Note that this is the seraph.
/obj/mecha/combat/marauder/seraph/Initialize()
..()//Let it equip whatever is needed.
var/obj/item/mecha_parts/mecha_equipment/ME
if(equipment.len)//Now to remove it and equip anew.
for(ME in equipment)
ME.detach()
qdel(ME)
ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot(src)
ME.attach(src)
ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive(src)
ME.attach(src)
ME = new /obj/item/mecha_parts/mecha_equipment/teleporter(src)
ME.attach(src)
ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay(src)
ME.attach(src)
ME = new /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster(src)
ME.attach(src)
return
//I'll break this down later //I'll break this down later
/obj/mecha/combat/marauder/relaymove(mob/user,direction) /obj/mecha/combat/marauder/relaymove(mob/user,direction)
if(user != src.occupant) //While not "realistic", this piece is player friendly. if(user != src.occupant) //While not "realistic", this piece is player friendly.
@@ -150,17 +139,10 @@
/obj/mecha/combat/marauder/old /obj/mecha/combat/marauder/old
desc = "Heavy-duty, combat exosuit, developed after the Durand model. Rarely found among civilian populations. This one is particularly worn looking and likely isn't as sturdy." desc = "Heavy-duty, combat exosuit, developed after the Durand model. Rarely found among civilian populations. This one is particularly worn looking and likely isn't as sturdy."
starting_equipment = null
/obj/mecha/combat/marauder/old/New() /obj/mecha/combat/marauder/old/New()
..() ..()
health = 25 health = 25
maxhealth = 400 //Just slightly worse. maxhealth = 300 //Just slightly worse.
cell.charge = rand(0, (cell.charge/2)) cell.charge = rand(0, (cell.charge/2))
/obj/mecha/combat/marauder/old/Initialize()
..()
var/obj/item/mecha_parts/mecha_equipment/ME
if(equipment.len)
for(ME in equipment)
ME.detach()
qdel(ME)
return

View File

@@ -25,15 +25,24 @@
max_universal_equip = 3 max_universal_equip = 3
max_special_equip = 4 max_special_equip = 4
phasing_possible = 1 starting_components = list(
switch_dmg_type_possible = 1 /obj/item/mecha_parts/component/hull/durable,
/obj/item/mecha_parts/component/actuator,
/obj/item/mecha_parts/component/armor/alien,
/obj/item/mecha_parts/component/gas,
/obj/item/mecha_parts/component/electrical
)
cloak_possible = TRUE
phasing_possible = TRUE
switch_dmg_type_possible = TRUE
/obj/mecha/combat/phazon/equipped/Initialize() /obj/mecha/combat/phazon/equipped/Initialize()
..() ..()
var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/tool/rcd starting_equipment = list(
ME.attach(src) /obj/item/mecha_parts/mecha_equipment/tool/rcd,
ME = new /obj/item/mecha_parts/mecha_equipment/gravcatapult /obj/item/mecha_parts/mecha_equipment/gravcatapult
ME.attach(src) )
return return
/* Leaving this until we are really sure we don't need it for reference. /* Leaving this until we are really sure we don't need it for reference.
@@ -95,8 +104,9 @@
max_universal_equip = 2 max_universal_equip = 2
max_special_equip = 2 max_special_equip = 2
phasing_possible = 1 phasing_possible = TRUE
switch_dmg_type_possible = 1 switch_dmg_type_possible = TRUE
cloak_possible = FALSE
/obj/mecha/combat/phazon/janus/take_damage(amount, type="brute") /obj/mecha/combat/phazon/janus/take_damage(amount, type="brute")
..() ..()

View File

@@ -0,0 +1,155 @@
/obj/item/mecha_parts/component
name = "mecha component"
icon = 'icons/mecha/mech_component.dmi'
icon_state = "component"
w_class = ITEMSIZE_HUGE
origin_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2)
var/component_type = null
var/obj/mecha/chassis = null
var/start_damaged = FALSE
var/emp_resistance = 0 // Amount of emp 'levels' removed.
var/list/required_type = null // List, if it exists. Exosuits meant to use the component (Unique var changes / effects)
var/integrity
var/integrity_danger_mod = 0.5 // Multiplier for comparison to max_integrity before problems start.
var/max_integrity = 100
var/step_delay = 0
var/relative_size = 30 // Percent chance for the component to be hit.
var/internal_damage_flag // If set, the component will toggle the flag on or off if it is destroyed / severely damaged.
/obj/item/mecha_parts/component/examine(mob/user)
. = ..()
var/show_integrity = round(integrity/max_integrity*100, 0.1)
switch(show_integrity)
if(85 to 100)
. += "It's fully intact."
if(65 to 85)
. += "It's slightly damaged."
if(45 to 65)
. += "<span class='notice'>It's badly damaged.</span>"
if(25 to 45)
. += "<span class='warning'>It's heavily damaged.</span>"
if(2 to 25)
. += "<span class='warning'><b>It's falling apart.</b></span>"
if(0 to 1)
. += "<span class='warning'><b>It is completely destroyed.</b></span>"
/obj/item/mecha_parts/component/Initialize()
..()
integrity = max_integrity
if(start_damaged)
integrity = round(integrity * integrity_danger_mod)
/obj/item/mecha_parts/component/Destroy()
detach()
return ..()
// Damage code.
/obj/item/mecha_parts/component/emp_act(var/severity = 4)
if(severity + emp_resistance > 4)
return
severity = clamp(severity + emp_resistance, 1, 4)
take_damage((4 - severity) * round(integrity * 0.1, 0.1))
/obj/item/mecha_parts/component/proc/adjust_integrity(var/amt = 0)
integrity = clamp(integrity + amt, 0, max_integrity)
return
/obj/item/mecha_parts/component/proc/damage_part(var/dam_amt = 0, var/type = BRUTE)
if(dam_amt <= 0)
return FALSE
adjust_integrity(-1 * dam_amt)
if(chassis && internal_damage_flag)
if(get_efficiency() < 0.5)
chassis.check_for_internal_damage(list(internal_damage_flag), TRUE)
return TRUE
/obj/item/mecha_parts/component/proc/get_efficiency()
var/integ_limit = round(max_integrity * integrity_danger_mod)
if(integrity < integ_limit)
var/int_percent = round(integrity / integ_limit, 0.1)
return int_percent
return 1
// Attach/Detach code.
/obj/item/mecha_parts/component/proc/attach(var/obj/mecha/target, var/mob/living/user)
if(target)
if(!(component_type in target.internal_components))
if(user)
to_chat(user, "<span class='notice'>\The [target] doesn't seem to have anywhere to put \the [src].</span>")
return FALSE
if(target.internal_components[component_type])
if(user)
to_chat(user, "<span class='notice'>\The [target] already has a [component_type] installed!</span>")
return FALSE
chassis = target
if(user)
user.drop_from_inventory(src)
forceMove(target)
if(internal_damage_flag)
if(integrity > (max_integrity * integrity_danger_mod))
if(chassis.hasInternalDamage(internal_damage_flag))
chassis.clearInternalDamage(internal_damage_flag)
else
chassis.check_for_internal_damage(list(internal_damage_flag))
chassis.internal_components[component_type] = src
if(user)
chassis.visible_message("<span class='notice'>[user] installs \the [src] in \the [chassis].</span>")
return TRUE
return FALSE
/obj/item/mecha_parts/component/proc/detach()
if(chassis)
chassis.internal_components[component_type] = null
if(internal_damage_flag && chassis.hasInternalDamage(internal_damage_flag)) // If the module has been removed, it's kind of unfair to keep it causing problems by being damaged. It's nonfunctional either way.
chassis.clearInternalDamage(internal_damage_flag)
forceMove(get_turf(chassis))
chassis = null
return TRUE
/obj/item/mecha_parts/component/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W,/obj/item/stack/nanopaste))
var/obj/item/stack/nanopaste/NP = W
if(integrity < max_integrity)
while(integrity < max_integrity && NP)
if(do_after(user, 1 SECOND, src) && NP.use(1))
adjust_integrity(10)
return
return ..()
// Various procs to handle different calls by Exosuits. IE, movement actions, damage actions, etc.
/obj/item/mecha_parts/component/proc/get_step_delay()
return step_delay
/obj/item/mecha_parts/component/proc/handle_move()
return

View File

@@ -0,0 +1,37 @@
/obj/item/mecha_parts/component/actuator
name = "mecha actuator"
icon = 'icons/mecha/mech_component.dmi'
icon_state = "motor"
w_class = ITEMSIZE_HUGE
origin_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2)
component_type = MECH_ACTUATOR
start_damaged = FALSE
emp_resistance = 1
required_type = null // List, if it exists. Exosuits meant to use the component.
integrity_danger_mod = 0.6 // Multiplier for comparison to max_integrity before problems start.
max_integrity = 50
internal_damage_flag = MECHA_INT_CONTROL_LOST
var/strafing_multiplier = 1.5
/obj/item/mecha_parts/component/actuator/get_step_delay()
return step_delay
/obj/item/mecha_parts/component/actuator/hispeed
name = "overclocked mecha actuator"
step_delay = -1
emp_resistance = -1
integrity_danger_mod = 0.7
max_integrity = 60
strafing_multiplier = 1.2

View File

@@ -0,0 +1,238 @@
/obj/item/mecha_parts/component/armor
name = "mecha plating"
icon = 'icons/mecha/mech_component.dmi'
icon_state = "armor"
w_class = ITEMSIZE_HUGE
origin_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 2)
component_type = MECH_ARMOR
start_damaged = FALSE
emp_resistance = 4
required_type = null // List, if it exists. Exosuits meant to use the component.
integrity_danger_mod = 0.4 // Multiplier for comparison to max_integrity before problems start.
max_integrity = 120
internal_damage_flag = MECHA_INT_TEMP_CONTROL
step_delay = 1
var/deflect_chance = 10
var/list/damage_absorption = list(
"brute"= 0.8,
"fire"= 1.2,
"bullet"= 0.9,
"laser"= 1,
"energy"= 1,
"bomb"= 1,
"bio"= 1,
"rad"= 1
)
var/damage_minimum = 10
var/minimum_penetration = 0
var/fail_penetration_value = 0.66
/obj/item/mecha_parts/component/armor/mining
name = "blast-resistant mecha plating"
step_delay = 2
max_integrity = 80
damage_absorption = list(
"brute"=0.8,
"fire"=0.8,
"bullet"=1.2,
"laser"=1.2,
"energy"=1,
"bomb"=0.5,
"bio"=1,
"rad"=1
)
/obj/item/mecha_parts/component/armor/lightweight
name = "lightweight mecha plating"
max_integrity = 50
step_delay = 0
damage_absorption = list(
"brute"=1,
"fire"=1.4,
"bullet"=1.1,
"laser"=1.2,
"energy"=1,
"bomb"=1,
"bio"=1,
"rad"=1
)
/obj/item/mecha_parts/component/armor/reinforced
name = "reinforced mecha plating"
step_delay = 4
max_integrity = 80
minimum_penetration = 10
damage_absorption = list(
"brute"=0.7,
"fire"=1,
"bullet"=0.7,
"laser"=0.85,
"energy"=1,
"bomb"=0.8
)
/obj/item/mecha_parts/component/armor/military
name = "military grade mecha plating"
step_delay = 6
max_integrity = 100
emp_resistance = 2
required_type = list(/obj/mecha/combat)
damage_minimum = 15
minimum_penetration = 25
damage_absorption = list(
"brute"=0.5,
"fire"=1.1,
"bullet"=0.65,
"laser"=0.85,
"energy"=0.9,
"bomb"=0.8
)
/obj/item/mecha_parts/component/armor/military/attach(var/obj/mecha/target, var/mob/living/user)
. = ..()
if(.)
var/typepass = FALSE
for(var/type in required_type)
if(istype(chassis, type))
typepass = TRUE
if(typepass)
step_delay = 3
else
step_delay = initial(step_delay)
/obj/item/mecha_parts/component/armor/marshal
name = "marshal mecha plating"
step_delay = 5
max_integrity = 100
emp_resistance = 3
deflect_chance = 15
minimum_penetration = 10
required_type = list(/obj/mecha/combat)
damage_absorption = list(
"brute"=0.75,
"fire"=1,
"bullet"=0.8,
"laser"=0.7,
"energy"=0.85,
"bomb"=1
)
/obj/item/mecha_parts/component/armor/marshal/attach(var/obj/mecha/target, var/mob/living/user)
. = ..()
if(.)
var/typepass = FALSE
for(var/type in required_type)
if(istype(chassis, type))
typepass = TRUE
if(typepass)
step_delay = 2
else
step_delay = initial(step_delay)
/obj/item/mecha_parts/component/armor/marshal/reinforced
name = "blackops mecha plating"
step_delay = 5
damage_absorption = list(
"brute"=0.6,
"fire"=0.8,
"bullet"=0.6,
"laser"=0.5,
"energy"=0.65,
"bomb"=0.8
)
/obj/item/mecha_parts/component/armor/military/marauder
name = "cutting edge mecha plating"
step_delay = 4
max_integrity = 150
emp_resistance = 3
required_type = list(/obj/mecha/combat/marauder)
deflect_chance = 25
damage_minimum = 30
minimum_penetration = 25
damage_absorption = list(
"brute"=0.5,
"fire"=0.7,
"bullet"=0.45,
"laser"=0.6,
"energy"=0.7,
"bomb"=0.7
)
/obj/item/mecha_parts/component/armor/military/marauder/attach(var/obj/mecha/target, var/mob/living/user)
. = ..()
if(.)
var/typepass = FALSE
for(var/type in required_type)
if(istype(chassis, type))
typepass = TRUE
if(typepass)
step_delay = 1
else
step_delay = initial(step_delay)
/obj/item/mecha_parts/component/armor/alien
name = "strange mecha plating"
step_delay = 3
damage_absorption = list(
"brute"=0.7,
"fire"=0.7,
"bullet"=0.7,
"laser"=0.7,
"energy"=0.7,
"bomb"=0.7
)
/obj/item/mecha_parts/component/armor/alien/attach(var/obj/mecha/target, var/mob/living/user)
. = ..()
if(.)
if(istype(target, /obj/mecha/combat/phazon/janus))
step_delay = -1
else if(istype(target, /obj/mecha/combat/phazon))
step_delay = -3
else
step_delay = initial(step_delay)

View File

@@ -0,0 +1,31 @@
/obj/item/mecha_parts/component/electrical
name = "mecha electrical harness"
icon = 'icons/mecha/mech_component.dmi'
icon_state = "board"
w_class = ITEMSIZE_HUGE
origin_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2)
component_type = MECH_ELECTRIC
emp_resistance = 1
integrity_danger_mod = 0.4
max_integrity = 40
step_delay = 0
relative_size = 20
internal_damage_flag = MECHA_INT_SHORT_CIRCUIT
var/charge_cost_mod = 1
/obj/item/mecha_parts/component/electrical/high_current
name = "efficient mecha electrical harness"
emp_resistance = 0
max_integrity = 30
relative_size = 10
charge_cost_mod = 0.6

View File

@@ -0,0 +1,33 @@
/obj/item/mecha_parts/component/hull
name = "mecha hull"
icon = 'icons/mecha/mech_component.dmi'
icon_state = "hull"
w_class = ITEMSIZE_HUGE
origin_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2)
component_type = MECH_HULL
emp_resistance = 0 // Amount of emp 'levels' removed.
required_type = null // List, if it exists. Exosuits meant to use the component.
integrity_danger_mod = 0.5 // Multiplier for comparison to max_integrity before problems start.
max_integrity = 50
internal_damage_flag = MECHA_INT_FIRE
step_delay = 2
/obj/item/mecha_parts/component/hull/durable
name = "durable mecha hull"
step_delay = 4
integrity_danger_mod = 0.3
max_integrity = 100
/obj/item/mecha_parts/component/hull/lightweight
name = "lightweight mecha hull"
step_delay = 1
integrity_danger_mod = 0.3

View File

@@ -0,0 +1,28 @@
/obj/item/mecha_parts/component/gas
name = "mecha life-support"
icon = 'icons/mecha/mech_component.dmi'
icon_state = "lifesupport"
w_class = ITEMSIZE_HUGE
origin_tech = list(TECH_DATA = 2, TECH_ENGINEERING = 2)
component_type = MECH_GAS
emp_resistance = 1
integrity_danger_mod = 0.4
max_integrity = 40
step_delay = 0
relative_size = 20
internal_damage_flag = MECHA_INT_TANK_BREACH
/obj/item/mecha_parts/component/gas/reinforced
name = "reinforced mecha life-support"
emp_resistance = 2
max_integrity = 80
relative_size = 40

View File

@@ -28,6 +28,8 @@
var/ready_sound = 'sound/mecha/mech_reload_default.ogg' //Sound to play once the fire delay passed. var/ready_sound = 'sound/mecha/mech_reload_default.ogg' //Sound to play once the fire delay passed.
var/enable_special = FALSE // Will the tool do its special? var/enable_special = FALSE // Will the tool do its special?
var/step_delay = 0 // Does the component slow/speed up the suit?
/obj/item/mecha_parts/mecha_equipment/proc/do_after_cooldown(target=1) /obj/item/mecha_parts/mecha_equipment/proc/do_after_cooldown(target=1)
sleep(equip_cooldown) sleep(equip_cooldown)
set_ready_state(1) set_ready_state(1)
@@ -273,3 +275,6 @@
/obj/item/mecha_parts/mecha_equipment/proc/MoveAction() //Allows mech equipment to do an action upon the mech moving /obj/item/mecha_parts/mecha_equipment/proc/MoveAction() //Allows mech equipment to do an action upon the mech moving
return return
/obj/item/mecha_parts/mecha_equipment/proc/get_step_delay() // Equipment returns its slowdown or speedboost.
return step_delay

View File

@@ -9,6 +9,8 @@
var/deflect_coeff = 1.15 var/deflect_coeff = 1.15
var/damage_coeff = 0.8 var/damage_coeff = 0.8
step_delay = 1
equip_type = EQUIP_HULL equip_type = EQUIP_HULL
/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/get_equip_info() /obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/get_equip_info()

View File

@@ -9,6 +9,8 @@
var/deflect_coeff = 1.15 var/deflect_coeff = 1.15
var/damage_coeff = 0.8 var/damage_coeff = 0.8
step_delay = 2
equip_type = EQUIP_HULL equip_type = EQUIP_HULL
/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/handle_projectile_contact(var/obj/item/projectile/Proj, var/inc_damage) /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/handle_projectile_contact(var/obj/item/projectile/Proj, var/inc_damage)

View File

@@ -11,6 +11,8 @@
var/icon/droid_overlay var/icon/droid_overlay
var/list/repairable_damage = list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH) var/list/repairable_damage = list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH)
step_delay = 1
equip_type = EQUIP_HULL equip_type = EQUIP_HULL
/obj/item/mecha_parts/mecha_equipment/repair_droid/New() /obj/item/mecha_parts/mecha_equipment/repair_droid/New()
@@ -79,8 +81,23 @@
RD.chassis.clearInternalDamage(int_dam_flag) RD.chassis.clearInternalDamage(int_dam_flag)
repaired = 1 repaired = 1
break break
if(health_boost<0 || RD.chassis.health < initial(RD.chassis.health))
var/obj/item/mecha_parts/component/AC = RD.chassis.internal_components[MECH_ARMOR]
var/obj/item/mecha_parts/component/HC = RD.chassis.internal_components[MECH_HULL]
var/damaged_armor = AC.integrity < AC.max_integrity
var/damaged_hull = HC.integrity < HC.max_integrity
if(health_boost<0 || RD.chassis.health < initial(RD.chassis.health) || damaged_armor || damaged_hull)
RD.chassis.health += min(health_boost, initial(RD.chassis.health)-RD.chassis.health) RD.chassis.health += min(health_boost, initial(RD.chassis.health)-RD.chassis.health)
if(AC)
AC.adjust_integrity(round(health_boost * 0.5, 0.5))
if(HC)
HC.adjust_integrity(round(health_boost * 0.5, 0.5))
repaired = 1 repaired = 1
if(repaired) if(repaired)
if(RD.chassis.use_power(RD.energy_drain)) if(RD.chassis.use_power(RD.energy_drain))

View File

@@ -7,6 +7,8 @@
energy_drain = 20 energy_drain = 20
range = 0 range = 0
step_delay = 1
var/obj/item/shield_projector/line/exosuit/my_shield = null var/obj/item/shield_projector/line/exosuit/my_shield = null
var/my_shield_type = /obj/item/shield_projector/line/exosuit var/my_shield_type = /obj/item/shield_projector/line/exosuit
var/icon/drone_overlay var/icon/drone_overlay
@@ -66,9 +68,11 @@
my_shield.attack_self(chassis.occupant) my_shield.attack_self(chassis.occupant)
if(my_shield.active) if(my_shield.active)
set_ready_state(0) set_ready_state(0)
step_delay = 4
log_message("Activated.") log_message("Activated.")
else else
set_ready_state(1) set_ready_state(1)
step_delay = 1
log_message("Deactivated.") log_message("Deactivated.")
/obj/item/mecha_parts/mecha_equipment/combat_shield/Topic(href, href_list) /obj/item/mecha_parts/mecha_equipment/combat_shield/Topic(href, href_list)

View File

@@ -9,6 +9,8 @@
energy_drain = OMNI_SHIELD_DRAIN energy_drain = OMNI_SHIELD_DRAIN
range = 0 range = 0
step_delay = 1
var/obj/item/shield_projector/shields = null var/obj/item/shield_projector/shields = null
var/shield_type = /obj/item/shield_projector/rectangle/mecha var/shield_type = /obj/item/shield_projector/rectangle/mecha
@@ -42,9 +44,11 @@
shields.set_on(!shields.active) shields.set_on(!shields.active)
if(shields.active) if(shields.active)
set_ready_state(0) set_ready_state(0)
step_delay = 4
log_message("Activated.") log_message("Activated.")
else else
set_ready_state(1) set_ready_state(1)
step_delay = 1
log_message("Deactivated.") log_message("Deactivated.")
/obj/item/mecha_parts/mecha_equipment/omni_shield/Topic(href, href_list) /obj/item/mecha_parts/mecha_equipment/omni_shield/Topic(href, href_list)

View File

@@ -7,6 +7,9 @@
equip_type = EQUIP_HULL equip_type = EQUIP_HULL
var/slowdown_multiplier = 0.75 // How much does the exosuit multiply its slowdown by if it's the proper type?
/*
/obj/item/mecha_parts/mecha_equipment/speedboost/attach(obj/mecha/M as obj) /obj/item/mecha_parts/mecha_equipment/speedboost/attach(obj/mecha/M as obj)
..() ..()
if(enable_special) if(enable_special)
@@ -14,6 +17,13 @@
else else
chassis.step_in = 6 // Improper parts slow the mech down chassis.step_in = 6 // Improper parts slow the mech down
return return
*/
/obj/item/mecha_parts/mecha_equipment/speedboost/get_step_delay()
if(enable_special)
return -1
else
return 3
/obj/item/mecha_parts/mecha_equipment/speedboost/detach() /obj/item/mecha_parts/mecha_equipment/speedboost/detach()
chassis.step_in = initial(chassis.step_in) chassis.step_in = initial(chassis.step_in)

View File

@@ -11,6 +11,8 @@
projectile = /obj/item/projectile/arc/fragmentation/mortar projectile = /obj/item/projectile/arc/fragmentation/mortar
projectile_energy_cost = 600 projectile_energy_cost = 600
step_delay = 2
origin_tech = list(TECH_MATERIAL = 4, TECH_COMBAT = 5, TECH_ILLEGAL = 3) origin_tech = list(TECH_MATERIAL = 4, TECH_COMBAT = 5, TECH_ILLEGAL = 3)
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/mortar/action_checks(atom/target) /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/mortar/action_checks(atom/target)

View File

@@ -11,6 +11,8 @@
deviation = 0.7 deviation = 0.7
projectile_energy_cost = 25 projectile_energy_cost = 25
step_delay = 2
origin_tech = list(TECH_MATERIAL = 3, TECH_COMBAT = 4) origin_tech = list(TECH_MATERIAL = 3, TECH_COMBAT = 4)
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot/rigged /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot/rigged

View File

@@ -52,6 +52,8 @@
projectile = /obj/item/projectile/beam/heavylaser projectile = /obj/item/projectile/beam/heavylaser
fire_sound = 'sound/weapons/lasercannonfire.ogg' fire_sound = 'sound/weapons/lasercannonfire.ogg'
step_delay = 2
origin_tech = list(TECH_MATERIAL = 3, TECH_COMBAT = 4, TECH_MAGNET = 4) origin_tech = list(TECH_MATERIAL = 3, TECH_COMBAT = 4, TECH_MAGNET = 4)
/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy/rigged /obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy/rigged

View File

@@ -2,6 +2,8 @@
var/missile_speed = 2 var/missile_speed = 2
var/missile_range = 30 var/missile_range = 30
step_delay = 2
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/Fire(atom/movable/AM, atom/target, turf/aimloc) /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/Fire(atom/movable/AM, atom/target, turf/aimloc)
AM.throw_at(target,missile_range, missile_speed, chassis) AM.throw_at(target,missile_range, missile_speed, chassis)
@@ -19,6 +21,8 @@
missile_range = 15 missile_range = 15
required_type = /obj/mecha //Why restrict it to just mining or combat mechs? required_type = /obj/mecha //Why restrict it to just mining or combat mechs?
step_delay = 0
equip_type = EQUIP_UTILITY equip_type = EQUIP_UTILITY
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flare/Fire(atom/movable/AM, atom/target, turf/aimloc) /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flare/Fire(atom/movable/AM, atom/target, turf/aimloc)

View File

@@ -7,6 +7,8 @@
energy_drain = 30 energy_drain = 30
step_delay = 2
projectile = /obj/item/projectile/bullet/incendiary/flamethrower/large projectile = /obj/item/projectile/bullet/incendiary/flamethrower/large
fire_sound = 'sound/weapons/towelwipe.ogg' fire_sound = 'sound/weapons/towelwipe.ogg'

View File

@@ -16,3 +16,5 @@
projectile_energy_cost = 40 projectile_energy_cost = 40
fire_cooldown = 3 fire_cooldown = 3
origin_tech = list(TECH_MATERIAL = 4, TECH_COMBAT = 5, TECH_PHORON = 2, TECH_ILLEGAL = 1) origin_tech = list(TECH_MATERIAL = 4, TECH_COMBAT = 5, TECH_PHORON = 2, TECH_ILLEGAL = 1)
step_delay = 1

View File

@@ -12,6 +12,8 @@
var/auto_rearm = 0 //Does the weapon reload itself after each shot? var/auto_rearm = 0 //Does the weapon reload itself after each shot?
required_type = list(/obj/mecha/combat, /obj/mecha/working/hoverpod/combatpod) required_type = list(/obj/mecha/combat, /obj/mecha/working/hoverpod/combatpod)
step_delay = 1
equip_type = EQUIP_WEAPON equip_type = EQUIP_WEAPON
/obj/item/mecha_parts/mecha_equipment/weapon/action_checks(atom/target) /obj/item/mecha_parts/mecha_equipment/weapon/action_checks(atom/target)

View File

@@ -7,6 +7,11 @@
#define MELEE 1 #define MELEE 1
#define RANGED 2 #define RANGED 2
#define MECHA_OPERATING 0
#define MECHA_BOLTS_SECURED 1
#define MECHA_PANEL_LOOSE 2
#define MECHA_CELL_OPEN 3
#define MECHA_CELL_OUT 4
#define MECH_FACTION_NT "nano" #define MECH_FACTION_NT "nano"
#define MECH_FACTION_SYNDI "syndi" #define MECH_FACTION_SYNDI "syndi"
@@ -48,7 +53,7 @@
var/fail_penetration_value = 0.66 //By how much failing to penetrate reduces your shit. 66% by default. var/fail_penetration_value = 0.66 //By how much failing to penetrate reduces your shit. 66% by default.
var/obj/item/weapon/cell/cell var/obj/item/weapon/cell/cell
var/state = 0 var/state = MECHA_OPERATING
var/list/log = new var/list/log = new
var/last_message = 0 var/last_message = 0
var/add_req_access = 1 var/add_req_access = 1
@@ -108,6 +113,24 @@
var/max_universal_equip = 2 var/max_universal_equip = 2
var/max_special_equip = 1 var/max_special_equip = 1
var/list/starting_equipment = null // List containing starting tools.
// Mech Components, similar to Cyborg, but Bigger.
var/list/internal_components = list(
MECH_HULL = null,
MECH_ACTUATOR = null,
MECH_ARMOR = null,
MECH_GAS = null,
MECH_ELECTRIC = null
)
var/list/starting_components = list(
/obj/item/mecha_parts/component/hull,
/obj/item/mecha_parts/component/actuator,
/obj/item/mecha_parts/component/armor,
/obj/item/mecha_parts/component/gas,
/obj/item/mecha_parts/component/electrical
)
//Working exosuit vars //Working exosuit vars
var/list/cargo = list() var/list/cargo = list()
var/cargo_capacity = 3 var/cargo_capacity = 3
@@ -148,6 +171,8 @@
var/smoke_cooldown = 100 //How long you have between uses. var/smoke_cooldown = 100 //How long you have between uses.
var/datum/effect/effect/system/smoke_spread/smoke_system = new var/datum/effect/effect/system/smoke_spread/smoke_system = new
var/cloak_possible = FALSE // Can this exosuit innately cloak?
////All of those are for the HUD buttons in the top left. See Grant and Remove procs in mecha_actions. ////All of those are for the HUD buttons in the top left. See Grant and Remove procs in mecha_actions.
var/datum/action/innate/mecha/mech_eject/eject_action = new var/datum/action/innate/mecha/mech_eject/eject_action = new
@@ -164,10 +189,20 @@
var/datum/action/innate/mecha/mech_cycle_equip/cycle_action = new var/datum/action/innate/mecha/mech_cycle_equip/cycle_action = new
var/datum/action/innate/mecha/mech_switch_damtype/switch_damtype_action = new var/datum/action/innate/mecha/mech_switch_damtype/switch_damtype_action = new
var/datum/action/innate/mecha/mech_toggle_phasing/phasing_action = new var/datum/action/innate/mecha/mech_toggle_phasing/phasing_action = new
var/datum/action/innate/mecha/mech_toggle_cloaking/cloak_action = new
var/weapons_only_cycle = FALSE //So combat mechs don't switch to their equipment at times. var/weapons_only_cycle = FALSE //So combat mechs don't switch to their equipment at times.
/obj/mecha/Initialize()
..()
for(var/path in starting_components)
var/obj/item/mecha_parts/component/C = new path(src)
C.attach(src)
if(starting_equipment && LAZYLEN(starting_equipment))
for(var/path in starting_equipment)
var/obj/item/mecha_parts/mecha_equipment/ME = new path(src)
ME.attach(src)
/obj/mecha/drain_power(var/drain_check) /obj/mecha/drain_power(var/drain_check)
@@ -245,6 +280,15 @@
else else
E.forceMove(loc) E.forceMove(loc)
E.destroy() E.destroy()
for(var/slot in internal_components)
var/obj/item/mecha_parts/component/C = internal_components[slot]
if(istype(C))
C.damage_part(rand(10, 20))
C.detach()
WR.crowbar_salvage += C
C.forceMove(WR)
if(cell) if(cell)
WR.crowbar_salvage += cell WR.crowbar_salvage += cell
cell.forceMove(WR) cell.forceMove(WR)
@@ -256,6 +300,11 @@
for(var/obj/item/mecha_parts/mecha_equipment/E in equipment) for(var/obj/item/mecha_parts/mecha_equipment/E in equipment)
E.detach(loc) E.detach(loc)
E.destroy() E.destroy()
for(var/slot in internal_components)
var/obj/item/mecha_parts/component/C = internal_components[slot]
if(istype(C))
C.detach()
qdel(C)
if(cell) if(cell)
qdel(cell) qdel(cell)
if(internal_tank) if(internal_tank)
@@ -351,6 +400,26 @@
/obj/mecha/examine(mob/user) /obj/mecha/examine(mob/user)
. = ..() . = ..()
var/obj/item/mecha_parts/component/armor/AC = internal_components[MECH_ARMOR]
var/obj/item/mecha_parts/component/hull/HC = internal_components[MECH_HULL]
if(AC)
. += "It has [AC] attached. [AC.get_efficiency()<0.5?"It is severely damaged.":""]"
else
. += "It has no armor plating."
if(HC)
if(!AC || AC.get_efficiency() < 0.7)
. += "It has [HC] attached. [HC.get_efficiency()<0.5?"It is severely damaged.":""]"
else
. += "You cannot tell what type of hull it has."
else
. += "It does not seem to have a completed hull."
var/integrity = health/initial(health)*100 var/integrity = health/initial(health)*100
switch(integrity) switch(integrity)
if(85 to 100) if(85 to 100)
@@ -536,6 +605,12 @@
user.forceMove(get_turf(src)) user.forceMove(get_turf(src))
to_chat(user, "You climb out from [src]") to_chat(user, "You climb out from [src]")
return 0 return 0
var/obj/item/mecha_parts/component/hull/HC = internal_components[MECH_HULL]
if(!HC)
occupant_message("<span class='notice'>You can't operate an exosuit that doesn't have a hull!</span>")
return
if(connected_port) if(connected_port)
if(world.time - last_message > 20) if(world.time - last_message > 20)
src.occupant_message("<span class='warning'>Unable to move while connected to the air system port</span>") src.occupant_message("<span class='warning'>Unable to move while connected to the air system port</span>")
@@ -562,6 +637,44 @@
return call((proc_res["dyndomove"]||src), "dyndomove")(direction) return call((proc_res["dyndomove"]||src), "dyndomove")(direction)
/obj/mecha/proc/get_step_delay()
var/tally = 0
if(overload)
tally = min(1, round(step_in/2))
for(var/slot in internal_components)
var/obj/item/mecha_parts/component/C = internal_components[slot]
if(C && C.get_step_delay())
tally += C.get_step_delay()
for(var/obj/item/mecha_parts/mecha_equipment/ME in equipment)
if(ME.get_step_delay())
tally += ME.get_step_delay()
var/obj/item/mecha_parts/component/actuator/actuator = internal_components[MECH_ACTUATOR]
if(!actuator) // Relying purely on hydraulic pumps. You're going nowhere fast.
tally = 2 SECONDS
return tally
tally += 0.5 SECONDS * (1 - actuator.get_efficiency()) // Damaged actuators run slower, slowing as damage increases beyond its threshold.
if(strafing)
tally = round(tally * actuator.strafing_multiplier)
for(var/obj/item/mecha_parts/mecha_equipment/ME in equipment)
if(istype(ME, /obj/item/mecha_parts/mecha_equipment/speedboost))
var/obj/item/mecha_parts/mecha_equipment/speedboost/SB = ME
for(var/path in ME.required_type)
if(istype(src, path))
tally = round(tally * SB.slowdown_multiplier)
break
break
return max(1, round(tally))
/obj/mecha/proc/dyndomove(direction) /obj/mecha/proc/dyndomove(direction)
if(!can_move) if(!can_move)
return 0 return 0
@@ -600,7 +713,6 @@
health-- health--
if(health < initial(health) - initial(health)/3) if(health < initial(health) - initial(health)/3)
overload = 0 overload = 0
step_in = initial(step_in)
step_energy_drain = initial(step_energy_drain) step_energy_drain = initial(step_energy_drain)
src.occupant_message("<font color='red'>Leg actuators damage threshold exceded. Disabling overload.</font>") src.occupant_message("<font color='red'>Leg actuators damage threshold exceded. Disabling overload.</font>")
@@ -656,7 +768,7 @@
if(!src.check_for_support()) if(!src.check_for_support())
src.pr_inertial_movement.start(list(src,direction)) src.pr_inertial_movement.start(list(src,direction))
src.log_message("<span class='warning'>Movement control lost. Inertial movement started.</span>") src.log_message("<span class='warning'>Movement control lost. Inertial movement started.</span>")
if(do_after(step_in)) if(do_after(get_step_delay()))
can_move = 1 can_move = 1
return 1 return 1
return 0 return 0
@@ -708,7 +820,7 @@
flick("[initial_icon]-phase", src) flick("[initial_icon]-phase", src)
src.loc = get_step(src,src.dir) src.loc = get_step(src,src.dir)
src.use_power(phasing_energy_drain) src.use_power(phasing_energy_drain)
sleep(step_in*3) sleep(get_step_delay() * 3)
can_phase = TRUE can_phase = TRUE
occupant_message("Phazed.") occupant_message("Phazed.")
. = ..(obstacle) . = ..(obstacle)
@@ -785,16 +897,57 @@
update_damage_alerts() update_damage_alerts()
if(amount) if(amount)
var/damage = absorbDamage(amount,type) var/damage = absorbDamage(amount,type)
damage = components_handle_damage(damage,type)
health -= damage health -= damage
update_health() update_health()
log_append_to_last("Took [damage] points of damage. Damage type: \"[type]\".",1) log_append_to_last("Took [damage] points of damage. Damage type: \"[type]\".",1)
return return
/obj/mecha/proc/components_handle_damage(var/damage, var/type = BRUTE)
var/obj/item/mecha_parts/component/armor/AC = internal_components[MECH_ARMOR]
if(AC)
var/armor_efficiency = AC.get_efficiency()
var/damage_change = armor_efficiency * (damage * 0.5) * AC.damage_absorption[type]
AC.damage_part(damage_change, type)
damage -= damage_change
var/obj/item/mecha_parts/component/hull/HC = internal_components[MECH_HULL]
if(HC)
if(HC.integrity)
var/hull_absorb = round(rand(5, 10) / 10, 0.1) * damage
HC.damage_part(hull_absorb, type)
damage -= hull_absorb
for(var/obj/item/mecha_parts/component/C in (internal_components - list(MECH_HULL, MECH_ARMOR)))
if(prob(C.relative_size))
var/damage_part_amt = round(damage / 4, 0.1)
C.damage_part(damage_part_amt)
damage -= damage_part_amt
return damage
/obj/mecha/proc/get_damage_absorption()
var/obj/item/mecha_parts/component/armor/AC = internal_components[MECH_ARMOR]
if(!istype(AC))
return
else
if(AC.get_efficiency() > 0.25)
return AC.damage_absorption
return
/obj/mecha/proc/absorbDamage(damage,damage_type) /obj/mecha/proc/absorbDamage(damage,damage_type)
return call((proc_res["dynabsorbdamage"]||src), "dynabsorbdamage")(damage,damage_type) return call((proc_res["dynabsorbdamage"]||src), "dynabsorbdamage")(damage,damage_type)
/obj/mecha/proc/dynabsorbdamage(damage,damage_type) /obj/mecha/proc/dynabsorbdamage(damage,damage_type)
return damage*(listgetindex(damage_absorption,damage_type) || 1) return damage*(listgetindex(get_damage_absorption(),damage_type) || 1)
/obj/mecha/airlock_crush(var/crush_damage) /obj/mecha/airlock_crush(var/crush_damage)
..() ..()
@@ -818,10 +971,20 @@
user.setClickCooldown(user.get_attack_speed()) user.setClickCooldown(user.get_attack_speed())
src.log_message("Attack by hand/paw. Attacker - [user].",1) src.log_message("Attack by hand/paw. Attacker - [user].",1)
var/obj/item/mecha_parts/component/armor/ArmC = internal_components[MECH_ARMOR]
var/temp_deflect_chance = deflect_chance
if(!ArmC)
temp_deflect_chance = 1
else
temp_deflect_chance = round(ArmC.get_efficiency() * ArmC.deflect_chance + (defence_mode ? 25 : 0))
if(istype(user,/mob/living/carbon/human)) if(istype(user,/mob/living/carbon/human))
var/mob/living/carbon/human/H = user var/mob/living/carbon/human/H = user
if(H.species.can_shred(user)) if(H.species.can_shred(user))
if(!prob(src.deflect_chance)) if(!prob(temp_deflect_chance))
src.take_damage(15) //The take_damage() proc handles armor values src.take_damage(15) //The take_damage() proc handles armor values
if(prob(25)) //Why would they get free internal damage. At least make it a bit RNG. if(prob(25)) //Why would they get free internal damage. At least make it a bit RNG.
src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
@@ -838,7 +1001,7 @@
user.visible_message("<span class='danger'>\The [user] hits \the [src]. Nothing happens.</span>","<span class='danger'>You hit \the [src] with no visible effect.</span>") user.visible_message("<span class='danger'>\The [user] hits \the [src]. Nothing happens.</span>","<span class='danger'>You hit \the [src] with no visible effect.</span>")
src.log_append_to_last("Armor saved.") src.log_append_to_last("Armor saved.")
return return
else if ((HULK in user.mutations) && !prob(src.deflect_chance)) else if ((HULK in user.mutations) && !prob(temp_deflect_chance))
src.take_damage(15) //The take_damage() proc handles armor values src.take_damage(15) //The take_damage() proc handles armor values
if(prob(25)) //Hulks punch hard but lets not give them consistent internal damage. if(prob(25)) //Hulks punch hard but lets not give them consistent internal damage.
src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
@@ -856,11 +1019,30 @@
//I think this is relative to throws. //I think this is relative to throws.
/obj/mecha/proc/dynhitby(atom/movable/A) /obj/mecha/proc/dynhitby(atom/movable/A)
var/obj/item/mecha_parts/component/armor/ArmC = internal_components[MECH_ARMOR]
var/temp_deflect_chance = deflect_chance
var/temp_damage_minimum = damage_minimum
var/temp_minimum_penetration = minimum_penetration
var/temp_fail_penetration_value = fail_penetration_value
if(!ArmC)
temp_deflect_chance = 0
temp_damage_minimum = 0
temp_minimum_penetration = 0
temp_fail_penetration_value = 1
else
temp_deflect_chance = round(ArmC.get_efficiency() * ArmC.deflect_chance + (defence_mode ? 25 : 0))
temp_damage_minimum = round(ArmC.get_efficiency() * ArmC.damage_minimum)
temp_minimum_penetration = round(ArmC.get_efficiency() * ArmC.minimum_penetration)
temp_fail_penetration_value = round(ArmC.get_efficiency() * ArmC.fail_penetration_value)
if(istype(A, /obj/item/mecha_parts/mecha_tracking)) if(istype(A, /obj/item/mecha_parts/mecha_tracking))
A.forceMove(src) A.forceMove(src)
src.visible_message("The [A] fastens firmly to [src].") src.visible_message("The [A] fastens firmly to [src].")
return return
if(prob(src.deflect_chance) || istype(A, /mob)) if(prob(temp_deflect_chance) || istype(A, /mob))
src.occupant_message("<span class='notice'>\The [A] bounces off the armor.</span>") src.occupant_message("<span class='notice'>\The [A] bounces off the armor.</span>")
src.visible_message("\The [A] bounces off \the [src] armor") src.visible_message("\The [A] bounces off \the [src] armor")
src.log_append_to_last("Armor saved.") src.log_append_to_last("Armor saved.")
@@ -873,18 +1055,18 @@
var/pass_damage = O.throwforce var/pass_damage = O.throwforce
var/pass_damage_reduc_mod var/pass_damage_reduc_mod
if(pass_damage <= damage_minimum)//Too little to go through. if(pass_damage <= temp_damage_minimum)//Too little to go through.
src.occupant_message("<span class='notice'>\The [A] bounces off the armor.</span>") src.occupant_message("<span class='notice'>\The [A] bounces off the armor.</span>")
src.visible_message("\The [A] bounces off \the [src] armor") src.visible_message("\The [A] bounces off \the [src] armor")
return return
else if(O.armor_penetration < minimum_penetration) //If you don't have enough pen, you won't do full damage else if(O.armor_penetration < temp_minimum_penetration) //If you don't have enough pen, you won't do full damage
src.occupant_message("<span class='notice'>\The [A] struggles to bypass \the [src] armor.</span>") src.occupant_message("<span class='notice'>\The [A] struggles to bypass \the [src] armor.</span>")
src.visible_message("\The [A] struggles to bypass \the [src] armor") src.visible_message("\The [A] struggles to bypass \the [src] armor")
pass_damage_reduc_mod = fail_penetration_value //This will apply to reduce damage to 2/3 or 66% by default pass_damage_reduc_mod = temp_fail_penetration_value //This will apply to reduce damage to 2/3 or 66% by default
else else
src.occupant_message("<span class='notice'>\The [A] manages to pierces \the [src] armor.</span>") src.occupant_message("<span class='notice'>\The [A] manages to pierce \the [src] armor.</span>")
src.visible_message("\The [A] manages to pierces \the [src] armor") // src.visible_message("\The [A] manages to pierce \the [src] armor")
pass_damage_reduc_mod = 1 pass_damage_reduc_mod = 1
@@ -911,7 +1093,26 @@
return return
/obj/mecha/proc/dynbulletdamage(var/obj/item/projectile/Proj) /obj/mecha/proc/dynbulletdamage(var/obj/item/projectile/Proj)
if(prob(src.deflect_chance)) var/obj/item/mecha_parts/component/armor/ArmC = internal_components[MECH_ARMOR]
var/temp_deflect_chance = deflect_chance
var/temp_damage_minimum = damage_minimum
var/temp_minimum_penetration = minimum_penetration
var/temp_fail_penetration_value = fail_penetration_value
if(!ArmC)
temp_deflect_chance = 0
temp_damage_minimum = 0
temp_minimum_penetration = 0
temp_fail_penetration_value = 1
else
temp_deflect_chance = round(ArmC.get_efficiency() * ArmC.deflect_chance + (defence_mode ? 25 : 0))
temp_damage_minimum = round(ArmC.get_efficiency() * ArmC.damage_minimum)
temp_minimum_penetration = round(ArmC.get_efficiency() * ArmC.minimum_penetration)
temp_fail_penetration_value = round(ArmC.get_efficiency() * ArmC.fail_penetration_value)
if(prob(temp_deflect_chance))
src.occupant_message("<span class='notice'>The armor deflects incoming projectile.</span>") src.occupant_message("<span class='notice'>The armor deflects incoming projectile.</span>")
src.visible_message("The [src.name] armor deflects the projectile") src.visible_message("The [src.name] armor deflects the projectile")
src.log_append_to_last("Armor saved.") src.log_append_to_last("Armor saved.")
@@ -930,19 +1131,19 @@
for(var/obj/item/mecha_parts/mecha_equipment/ME in equipment) for(var/obj/item/mecha_parts/mecha_equipment/ME in equipment)
pass_damage = ME.handle_projectile_contact(Proj, pass_damage) pass_damage = ME.handle_projectile_contact(Proj, pass_damage)
if(pass_damage < damage_minimum)//too pathetic to really damage you. if(pass_damage < temp_damage_minimum)//too pathetic to really damage you.
src.occupant_message("<span class='notice'>The armor deflects incoming projectile.</span>") src.occupant_message("<span class='notice'>The armor deflects incoming projectile.</span>")
src.visible_message("The [src.name] armor deflects\the [Proj]") src.visible_message("The [src.name] armor deflects\the [Proj]")
return return
else if(Proj.armor_penetration < minimum_penetration) //If you don't have enough pen, you won't do full damage else if(Proj.armor_penetration < temp_minimum_penetration) //If you don't have enough pen, you won't do full damage
src.occupant_message("<span class='notice'>\The [Proj] struggles to pierce \the [src] armor.</span>") src.occupant_message("<span class='notice'>\The [Proj] struggles to pierce \the [src] armor.</span>")
src.visible_message("\The [Proj] struggles to pierce \the [src] armor") src.visible_message("\The [Proj] struggles to pierce \the [src] armor")
pass_damage_reduc_mod = fail_penetration_value //This will apply to reduce damage to 2/3 or 66% by default pass_damage_reduc_mod = temp_fail_penetration_value //This will apply to reduce damage to 2/3 or 66% by default
else //You go through completely because you use AP. Nice. else //You go through completely because you use AP. Nice.
src.occupant_message("<span class='notice'>\The [Proj] manages to pierce \the [src] armor.</span>") src.occupant_message("<span class='notice'>\The [Proj] manages to pierce \the [src] armor.</span>")
src.visible_message("\The [Proj] manages to pierce \the [src] armor") // src.visible_message("\The [Proj] manages to pierce \the [src] armor")
pass_damage_reduc_mod = 1 pass_damage_reduc_mod = 1
pass_damage = (pass_damage_reduc_mod*pass_damage)//Apply damage reduction before usage. pass_damage = (pass_damage_reduc_mod*pass_damage)//Apply damage reduction before usage.
@@ -974,24 +1175,34 @@
//This refer to whenever you are caught in an explosion. //This refer to whenever you are caught in an explosion.
/obj/mecha/ex_act(severity) /obj/mecha/ex_act(severity)
var/obj/item/mecha_parts/component/armor/ArmC = internal_components[MECH_ARMOR]
var/temp_deflect_chance = deflect_chance
if(!ArmC)
temp_deflect_chance = 0
else
temp_deflect_chance = round(ArmC.get_efficiency() * ArmC.deflect_chance + (defence_mode ? 25 : 0))
src.log_message("Affected by explosion of severity: [severity].",1) src.log_message("Affected by explosion of severity: [severity].",1)
if(prob(src.deflect_chance)) if(prob(temp_deflect_chance))
severity++ severity++
src.log_append_to_last("Armor saved, changing severity to [severity].") src.log_append_to_last("Armor saved, changing severity to [severity].")
switch(severity) switch(severity)
if(1.0) if(1.0)
qdel(src) src.take_damage(initial(src.health), "bomb")
if(2.0) if(2.0)
if (prob(30)) if (prob(30))
qdel(src) src.take_damage(initial(src.health), "bomb")
else else
src.take_damage(initial(src.health)/2) //The take_damage() proc handles armor values src.take_damage(initial(src.health)/2, "bomb")
src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1) src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1)
if(3.0) if(3.0)
if (prob(5)) if (prob(5))
qdel(src) qdel(src)
else else
src.take_damage(initial(src.health)/5) //The take_damage() proc handles armor values src.take_damage(initial(src.health)/5, "bomb")
src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1) src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1)
return return
@@ -1038,20 +1249,39 @@
src.log_message("Attacked by [W]. Attacker - [user]") src.log_message("Attacked by [W]. Attacker - [user]")
var/pass_damage_reduc_mod //Modifer for failing to bring AP. var/pass_damage_reduc_mod //Modifer for failing to bring AP.
if(prob(src.deflect_chance)) //Does your attack get deflected outright. var/obj/item/mecha_parts/component/armor/ArmC = internal_components[MECH_ARMOR]
var/temp_deflect_chance = deflect_chance
var/temp_damage_minimum = damage_minimum
var/temp_minimum_penetration = minimum_penetration
var/temp_fail_penetration_value = fail_penetration_value
if(!ArmC)
temp_deflect_chance = 0
temp_damage_minimum = 0
temp_minimum_penetration = 0
temp_fail_penetration_value = 1
else
temp_deflect_chance = round(ArmC.get_efficiency() * ArmC.deflect_chance + (defence_mode ? 25 : 0))
temp_damage_minimum = round(ArmC.get_efficiency() * ArmC.damage_minimum)
temp_minimum_penetration = round(ArmC.get_efficiency() * ArmC.minimum_penetration)
temp_fail_penetration_value = round(ArmC.get_efficiency() * ArmC.fail_penetration_value)
if(prob(temp_deflect_chance)) //Does your attack get deflected outright.
src.occupant_message("<span class='notice'>\The [W] bounces off [src.name].</span>") src.occupant_message("<span class='notice'>\The [W] bounces off [src.name].</span>")
to_chat(user, "<span class='danger'>\The [W] bounces off [src.name].</span>") to_chat(user, "<span class='danger'>\The [W] bounces off [src.name].</span>")
src.log_append_to_last("Armor saved.") src.log_append_to_last("Armor saved.")
else if(W.force < damage_minimum) //Is your attack too PATHETIC to do anything. 3 damage to a person shouldn't do anything to a mech. else if(W.force < temp_damage_minimum) //Is your attack too PATHETIC to do anything. 3 damage to a person shouldn't do anything to a mech.
src.occupant_message("<span class='notice'>\The [W] bounces off the armor.</span>") src.occupant_message("<span class='notice'>\The [W] bounces off the armor.</span>")
src.visible_message("\The [W] bounces off \the [src] armor") src.visible_message("\The [W] bounces off \the [src] armor")
return return
else if(W.armor_penetration < minimum_penetration) //If you don't have enough pen, you won't do full damage else if(W.armor_penetration < temp_minimum_penetration) //If you don't have enough pen, you won't do full damage
src.occupant_message("<span class='notice'>\The [W] struggles to bypass \the [src] armor.</span>") src.occupant_message("<span class='notice'>\The [W] struggles to bypass \the [src] armor.</span>")
src.visible_message("\The [W] struggles to bypass \the [src] armor") src.visible_message("\The [W] struggles to bypass \the [src] armor")
pass_damage_reduc_mod = fail_penetration_value //This will apply to reduce damage to 2/3 or 66% by default pass_damage_reduc_mod = temp_fail_penetration_value //This will apply to reduce damage to 2/3 or 66% by default
else else
pass_damage_reduc_mod = 1 //Just making sure. pass_damage_reduc_mod = 1 //Just making sure.
@@ -1080,6 +1310,11 @@
to_chat(user, "[src]-MMI interface initialization failed.") to_chat(user, "[src]-MMI interface initialization failed.")
return return
if(istype(W, /obj/item/device/robotanalyzer))
var/obj/item/device/robotanalyzer/RA = W
RA.do_scan(src, user)
return
if(istype(W, /obj/item/mecha_parts/mecha_equipment)) if(istype(W, /obj/item/mecha_parts/mecha_equipment))
var/obj/item/mecha_parts/mecha_equipment/E = W var/obj/item/mecha_parts/mecha_equipment/E = W
spawn() spawn()
@@ -1090,6 +1325,20 @@
else else
to_chat(user, "You were unable to attach [W] to [src]") to_chat(user, "You were unable to attach [W] to [src]")
return return
if(istype(W, /obj/item/mecha_parts/component) && state == MECHA_CELL_OUT)
var/obj/item/mecha_parts/component/MC = W
spawn()
if(MC.attach(src))
user.drop_item()
MC.forceMove(src)
user.visible_message("[user] installs \the [W] in \the [src]", "You install \the [W] in \the [src].")
return
if(istype(W, /obj/item/weapon/card/robot))
var/obj/item/weapon/card/robot/RoC = W
return attackby(RoC.dummy_card, user)
if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda))
if(add_req_access || maint_access) if(add_req_access || maint_access)
if(internals_access_allowed(usr)) if(internals_access_allowed(usr))
@@ -1106,23 +1355,39 @@
else else
to_chat(user, "<span class='warning'>Maintenance protocols disabled by operator.</span>") to_chat(user, "<span class='warning'>Maintenance protocols disabled by operator.</span>")
else if(W.is_wrench()) else if(W.is_wrench())
if(state==1) if(state==MECHA_BOLTS_SECURED)
state = 2 state = MECHA_PANEL_LOOSE
to_chat(user, "You undo the securing bolts.") to_chat(user, "You undo the securing bolts.")
else if(state==2) else if(state==MECHA_PANEL_LOOSE)
state = 1 state = MECHA_BOLTS_SECURED
to_chat(user, "You tighten the securing bolts.") to_chat(user, "You tighten the securing bolts.")
return return
else if(W.is_crowbar()) else if(W.is_crowbar())
if(state==2) if(state==MECHA_PANEL_LOOSE)
state = 3 state = MECHA_CELL_OPEN
to_chat(user, "You open the hatch to the power unit") to_chat(user, "You open the hatch to the power unit")
else if(state==3) else if(state==MECHA_CELL_OPEN)
state=2 state=MECHA_PANEL_LOOSE
to_chat(user, "You close the hatch to the power unit") to_chat(user, "You close the hatch to the power unit")
else if(state==MECHA_CELL_OUT)
var/list/removable_components = list()
for(var/slot in internal_components)
var/obj/item/mecha_parts/component/MC = internal_components[slot]
if(istype(MC))
removable_components[MC.name] = MC
else
to_chat(user, "<span class='notice'>\The [src] appears to be missing \the [slot].</span>")
var/remove = input(user, "Which component do you want to pry out?", "Remove Component") as null|anything in removable_components
if(!remove)
return
var/obj/item/mecha_parts/component/RmC = removable_components[remove]
RmC.detach()
return return
else if(istype(W, /obj/item/stack/cable_coil)) else if(istype(W, /obj/item/stack/cable_coil))
if(state == 3 && hasInternalDamage(MECHA_INT_SHORT_CIRCUIT)) if(state >= MECHA_CELL_OPEN && hasInternalDamage(MECHA_INT_SHORT_CIRCUIT))
var/obj/item/stack/cable_coil/CC = W var/obj/item/stack/cable_coil/CC = W
if(CC.use(2)) if(CC.use(2))
clearInternalDamage(MECHA_INT_SHORT_CIRCUIT) clearInternalDamage(MECHA_INT_SHORT_CIRCUIT)
@@ -1134,19 +1399,19 @@
if(hasInternalDamage(MECHA_INT_TEMP_CONTROL)) if(hasInternalDamage(MECHA_INT_TEMP_CONTROL))
clearInternalDamage(MECHA_INT_TEMP_CONTROL) clearInternalDamage(MECHA_INT_TEMP_CONTROL)
to_chat(user, "You repair the damaged temperature controller.") to_chat(user, "You repair the damaged temperature controller.")
else if(state==3 && src.cell) else if(state==MECHA_CELL_OPEN && src.cell)
src.cell.forceMove(src.loc) src.cell.forceMove(src.loc)
src.cell = null src.cell = null
state = 4 state = MECHA_CELL_OUT
to_chat(user, "You unscrew and pry out the powercell.") to_chat(user, "You unscrew and pry out the powercell.")
src.log_message("Powercell removed") src.log_message("Powercell removed")
else if(state==4 && src.cell) else if(state==MECHA_CELL_OUT && src.cell)
state=3 state=MECHA_CELL_OPEN
to_chat(user, "You screw the cell in place") to_chat(user, "You screw the cell in place")
return return
else if(istype(W, /obj/item/device/multitool)) else if(istype(W, /obj/item/device/multitool))
if(state>=3 && src.occupant) if(state>=MECHA_CELL_OPEN && src.occupant)
to_chat(user, "You attempt to eject the pilot using the maintenance controls.") to_chat(user, "You attempt to eject the pilot using the maintenance controls.")
if(src.occupant.stat) if(src.occupant.stat)
src.go_out() src.go_out()
@@ -1158,7 +1423,7 @@
return return
else if(istype(W, /obj/item/weapon/cell)) else if(istype(W, /obj/item/weapon/cell))
if(state==4) if(state==MECHA_CELL_OUT)
if(!src.cell) if(!src.cell)
to_chat(user, "You install the powercell") to_chat(user, "You install the powercell")
user.drop_item() user.drop_item()
@@ -1191,6 +1456,28 @@
user.visible_message("[user] attaches [W] to [src].", "You attach [W] to [src]") user.visible_message("[user] attaches [W] to [src].", "You attach [W] to [src]")
return return
else if(istype(W,/obj/item/stack/nanopaste))
if(state >= MECHA_PANEL_LOOSE)
var/obj/item/stack/nanopaste/NP = W
for(var/slot in internal_components)
var/obj/item/mecha_parts/component/C = internal_components[slot]
if(C)
if(C.integrity < C.max_integrity)
while(C.integrity < C.max_integrity && NP && do_after(user, 1 SECOND, src))
if(NP.use(1))
C.adjust_integrity(10)
to_chat(user, "<span class='notice'>You repair damage to \the [C].</span>")
return
else
to_chat(user, "<span class='notice'>You can't reach \the [src]'s internal components.</span>")
return
else else
call((proc_res["dynattackby"]||src), "dynattackby")(W,user) call((proc_res["dynattackby"]||src), "dynattackby")(W,user)
/* /*
@@ -1299,7 +1586,8 @@
return return
/obj/mecha/remove_air(amount) /obj/mecha/remove_air(amount)
if(use_internal_tank) var/obj/item/mecha_parts/component/gas/GC = internal_components[MECH_GAS]
if(use_internal_tank && (GC && prob(GC.get_efficiency() * 100)))
return cabin_air.remove(amount) return cabin_air.remove(amount)
else else
var/turf/T = get_turf(src) var/turf/T = get_turf(src)
@@ -1314,7 +1602,8 @@
/obj/mecha/proc/return_pressure() /obj/mecha/proc/return_pressure()
. = 0 . = 0
if(use_internal_tank) var/obj/item/mecha_parts/component/gas/GC = internal_components[MECH_GAS]
if(use_internal_tank && (GC && prob(GC.get_efficiency() * 100)))
. = cabin_air.return_pressure() . = cabin_air.return_pressure()
else else
var/datum/gas_mixture/t_air = get_turf_air() var/datum/gas_mixture/t_air = get_turf_air()
@@ -1325,7 +1614,8 @@
//skytodo: //No idea what you want me to do here, mate. //skytodo: //No idea what you want me to do here, mate.
/obj/mecha/proc/return_temperature() /obj/mecha/proc/return_temperature()
. = 0 . = 0
if(use_internal_tank) var/obj/item/mecha_parts/component/gas/GC = internal_components[MECH_GAS]
if(use_internal_tank && (GC && prob(GC.get_efficiency() * 100)))
. = cabin_air.temperature . = cabin_air.temperature
else else
var/datum/gas_mixture/t_air = get_turf_air() var/datum/gas_mixture/t_air = get_turf_air()
@@ -1387,6 +1677,10 @@
if(usr != occupant) if(usr != occupant)
return return
var/obj/item/mecha_parts/component/gas/GC = internal_components[MECH_GAS]
if(!GC)
return
for(var/turf/T in locs) for(var/turf/T in locs)
var/obj/machinery/atmospherics/portables_connector/possible_port = locate(/obj/machinery/atmospherics/portables_connector) in T var/obj/machinery/atmospherics/portables_connector/possible_port = locate(/obj/machinery/atmospherics/portables_connector) in T
if(possible_port) if(possible_port)
@@ -1449,6 +1743,16 @@
/obj/mecha/proc/internal_tank() /obj/mecha/proc/internal_tank()
if(usr!=src.occupant) if(usr!=src.occupant)
return return
var/obj/item/mecha_parts/component/gas/GC = internal_components[MECH_GAS]
if(!GC)
to_chat(occupant, "<span class='warning'>The life support systems don't seem to respond.</span>")
return
if(!prob(GC.get_efficiency() * 100))
to_chat(occupant, "<span class='warning'>\The [GC] shudders and barks, before returning to how it was before.</span>")
return
use_internal_tank = !use_internal_tank use_internal_tank = !use_internal_tank
src.occupant_message("Now taking air from [use_internal_tank?"internal airtank":"environment"].") src.occupant_message("Now taking air from [use_internal_tank?"internal airtank":"environment"].")
src.log_message("Now taking air from [use_internal_tank?"internal airtank":"environment"].") src.log_message("Now taking air from [use_internal_tank?"internal airtank":"environment"].")
@@ -1579,6 +1883,8 @@
verbs -= /obj/mecha/verb/toggle_phasing verbs -= /obj/mecha/verb/toggle_phasing
if(!switch_dmg_type_possible) if(!switch_dmg_type_possible)
verbs -= /obj/mecha/verb/switch_damtype verbs -= /obj/mecha/verb/switch_damtype
if(!cloak_possible)
verbs -= /obj/mecha/verb/toggle_cloak
occupant.in_enclosed_vehicle = 1 //Useful for when you need to know if someone is in a mecho. occupant.in_enclosed_vehicle = 1 //Useful for when you need to know if someone is in a mecho.
update_cell_alerts() update_cell_alerts()
@@ -1697,9 +2003,14 @@
/obj/mecha/proc/internals_access_allowed(mob/living/carbon/human/H) /obj/mecha/proc/internals_access_allowed(mob/living/carbon/human/H)
if(istype(H))
for(var/atom/ID in list(H.get_active_hand(), H.wear_id, H.belt)) for(var/atom/ID in list(H.get_active_hand(), H.wear_id, H.belt))
if(src.check_access(ID,src.internals_req_access)) if(src.check_access(ID,src.internals_req_access))
return 1 return 1
else if(istype(H, /mob/living/silicon/robot))
var/mob/living/silicon/robot/R = H
if(src.check_access(R.idcard,src.internals_req_access))
return 1
return 0 return 0
@@ -1799,9 +2110,15 @@
var/tank_pressure = internal_tank ? round(internal_tank.return_pressure(),0.01) : "None" var/tank_pressure = internal_tank ? round(internal_tank.return_pressure(),0.01) : "None"
var/tank_temperature = internal_tank ? internal_tank.return_temperature() : "Unknown" var/tank_temperature = internal_tank ? internal_tank.return_temperature() : "Unknown"
var/cabin_pressure = round(return_pressure(),0.01) var/cabin_pressure = round(return_pressure(),0.01)
var/obj/item/mecha_parts/component/hull/HC = internal_components[MECH_HULL]
var/obj/item/mecha_parts/component/armor/AC = internal_components[MECH_ARMOR]
var/output = {"[report_internal_damage()] var/output = {"[report_internal_damage()]
<b>Armor Integrity: </b>[AC?"[round(AC.integrity / AC.max_integrity * 100, 0.1)]%":"<span class='warning'>ARMOR MISSING</span>"]<br>
<b>Hull Integrity: </b>[HC?"[round(HC.integrity / HC.max_integrity * 100, 0.1)]%":"<span class='warning'>HULL MISSING</span>"]<br>
[integrity<30?"<font color='red'><b>DAMAGE LEVEL CRITICAL</b></font><br>":null] [integrity<30?"<font color='red'><b>DAMAGE LEVEL CRITICAL</b></font><br>":null]
<b>Integrity: </b> [integrity]%<br> <b>Chassis Integrity: </b> [integrity]%<br>
<b>Powercell charge: </b>[isnull(cell_charge)?"No powercell installed":"[cell.percent()]%"]<br> <b>Powercell charge: </b>[isnull(cell_charge)?"No powercell installed":"[cell.percent()]%"]<br>
<b>Air source: </b>[use_internal_tank?"Internal Airtank":"Environment"]<br> <b>Air source: </b>[use_internal_tank?"Internal Airtank":"Environment"]<br>
<b>Airtank pressure: </b>[tank_pressure]kPa<br> <b>Airtank pressure: </b>[tank_pressure]kPa<br>
@@ -2109,15 +2426,15 @@
if(!in_range(src, usr)) return if(!in_range(src, usr)) return
var/mob/user = top_filter.getMob("user") var/mob/user = top_filter.getMob("user")
if(user) if(user)
if(state==0) if(state==MECHA_OPERATING)
state = 1 state = MECHA_BOLTS_SECURED
to_chat(user, "The securing bolts are now exposed.") to_chat(user, "The securing bolts are now exposed.")
else if(state==1) else if(state==MECHA_BOLTS_SECURED)
state = 0 state = MECHA_OPERATING
to_chat(user, "The securing bolts are now hidden.") to_chat(user, "The securing bolts are now hidden.")
output_maintenance_dialog(top_filter.getObj("id_card"),user) output_maintenance_dialog(top_filter.getObj("id_card"),user)
return return
if(href_list["set_internal_tank_valve"] && state >=1) if(href_list["set_internal_tank_valve"] && state >=MECHA_BOLTS_SECURED)
if(!in_range(src, usr)) return if(!in_range(src, usr)) return
var/mob/user = top_filter.getMob("user") var/mob/user = top_filter.getMob("user")
if(user) if(user)
@@ -2125,7 +2442,7 @@
if(new_pressure) if(new_pressure)
internal_tank_valve = new_pressure internal_tank_valve = new_pressure
to_chat(user, "The internal pressure valve has been set to [internal_tank_valve]kPa.") to_chat(user, "The internal pressure valve has been set to [internal_tank_valve]kPa.")
if(href_list["remove_passenger"] && state >= 1) if(href_list["remove_passenger"] && state >= MECHA_BOLTS_SECURED)
var/mob/user = top_filter.getMob("user") var/mob/user = top_filter.getMob("user")
var/list/passengers = list() var/list/passengers = list()
for (var/obj/item/mecha_parts/mecha_equipment/tool/passenger/P in contents) for (var/obj/item/mecha_parts/mecha_equipment/tool/passenger/P in contents)
@@ -2284,6 +2601,13 @@
/obj/mecha/proc/dynusepower(amount) /obj/mecha/proc/dynusepower(amount)
update_cell_alerts() update_cell_alerts()
var/obj/item/mecha_parts/component/electrical/EC = internal_components[MECH_ELECTRIC]
if(EC)
amount = amount * (2 - EC.get_efficiency()) * EC.charge_cost_mod
else
amount *= 5
if(get_charge()) if(get_charge())
cell.use(amount) cell.use(amount)
return 1 return 1
@@ -2291,6 +2615,13 @@
/obj/mecha/proc/give_power(amount) /obj/mecha/proc/give_power(amount)
update_cell_alerts() update_cell_alerts()
var/obj/item/mecha_parts/component/electrical/EC = internal_components[MECH_ELECTRIC]
if(!EC)
amount /= 4
else
amount *= EC.get_efficiency()
if(!isnull(get_charge())) if(!isnull(get_charge()))
cell.give(amount) cell.give(amount)
return 1 return 1
@@ -2306,6 +2637,19 @@
//This is for mobs mostly. //This is for mobs mostly.
/obj/mecha/attack_generic(var/mob/user, var/damage, var/attack_message) /obj/mecha/attack_generic(var/mob/user, var/damage, var/attack_message)
var/obj/item/mecha_parts/component/armor/ArmC = internal_components[MECH_ARMOR]
var/temp_deflect_chance = deflect_chance
var/temp_damage_minimum = damage_minimum
if(!ArmC)
temp_deflect_chance = 1
temp_damage_minimum = 0
else
temp_deflect_chance = round(ArmC.get_efficiency() * ArmC.deflect_chance + (defence_mode ? 25 : 0))
temp_damage_minimum = round(ArmC.get_efficiency() * ArmC.damage_minimum)
user.setClickCooldown(user.get_attack_speed()) user.setClickCooldown(user.get_attack_speed())
if(!damage) if(!damage)
return 0 return 0
@@ -2313,14 +2657,14 @@
src.log_message("Attacked. Attacker - [user].",1) src.log_message("Attacked. Attacker - [user].",1)
user.do_attack_animation(src) user.do_attack_animation(src)
if(prob(src.deflect_chance))//Deflected if(prob(temp_deflect_chance))//Deflected
src.log_append_to_last("Armor saved.") src.log_append_to_last("Armor saved.")
src.occupant_message("<span class='notice'>\The [user]'s attack is stopped by the armor.</span>") src.occupant_message("<span class='notice'>\The [user]'s attack is stopped by the armor.</span>")
visible_message("<span class='notice'>\The [user] rebounds off [src.name]'s armor!</span>") visible_message("<span class='notice'>\The [user] rebounds off [src.name]'s armor!</span>")
user.attack_log += text("\[[time_stamp()]\] <font color='red'>attacked [src.name]</font>") user.attack_log += text("\[[time_stamp()]\] <font color='red'>attacked [src.name]</font>")
playsound(src, 'sound/weapons/slash.ogg', 50, 1, -1) playsound(src, 'sound/weapons/slash.ogg', 50, 1, -1)
else if(damage < damage_minimum)//Pathetic damage levels just don't harm MECH. else if(damage < temp_damage_minimum)//Pathetic damage levels just don't harm MECH.
src.occupant_message("<span class='notice'>\The [user]'s doesn't dent \the [src] paint.</span>") src.occupant_message("<span class='notice'>\The [user]'s doesn't dent \the [src] paint.</span>")
src.visible_message("\The [user]'s attack doesn't dent \the [src] armor") src.visible_message("\The [user]'s attack doesn't dent \the [src] armor")
src.log_append_to_last("Armor saved.") src.log_append_to_last("Armor saved.")

View File

@@ -35,6 +35,8 @@
phasing_action.Grant(user, src) phasing_action.Grant(user, src)
if(switch_dmg_type_possible) if(switch_dmg_type_possible)
switch_damtype_action.Grant(user, src) switch_damtype_action.Grant(user, src)
if(cloak_possible)
cloak_action.Grant(user, src)
/obj/mecha/proc/RemoveActions(mob/living/user, human_occupant = 0) /obj/mecha/proc/RemoveActions(mob/living/user, human_occupant = 0)
if(human_occupant) if(human_occupant)
@@ -52,7 +54,7 @@
phasing_action.Remove(user, src) phasing_action.Remove(user, src)
switch_damtype_action.Remove(user, src) switch_damtype_action.Remove(user, src)
overload_action.Remove(user, src) overload_action.Remove(user, src)
cloak_action.Remove(user, src)
// //
@@ -242,6 +244,15 @@
/datum/action/innate/mecha/mech_toggle_cloaking
name = "Toggle Mech phasing"
button_icon_state = "mech_phasing_off"
/datum/action/innate/mecha/mech_toggle_cloaking/Activate()
button_icon_state = "mech_phasing_[chassis.cloaked ? "off" : "on"]"
button.UpdateIcon()
chassis.toggle_cloaking()
///// /////
@@ -293,12 +304,10 @@
return return
if(overload) if(overload)
overload = 0 overload = 0
step_in = initial(step_in)
step_energy_drain = initial(step_energy_drain) step_energy_drain = initial(step_energy_drain)
src.occupant_message("<font color='blue'>You disable leg actuators overload.</font>") src.occupant_message("<font color='blue'>You disable leg actuators overload.</font>")
else else
overload = 1 overload = 1
step_in = min(1, round(step_in/2))
step_energy_drain = step_energy_drain*overload_coeff step_energy_drain = step_energy_drain*overload_coeff
src.occupant_message("<font color='red'>You enable leg actuators overload.</font>") src.occupant_message("<font color='red'>You enable leg actuators overload.</font>")
src.log_message("Toggled leg actuators overload.") src.log_message("Toggled leg actuators overload.")
@@ -422,6 +431,25 @@
return return
/obj/mecha/verb/toggle_cloak()
set category = "Exosuit Interface"
set name = "Toggle cloaking"
set src = usr.loc
set popup_menu = 0
toggle_cloaking()
/obj/mecha/proc/toggle_cloaking()
if(usr!=src.occupant)
return
if(cloaked)
uncloak()
else
cloak()
src.occupant_message("<font color=\"[cloaked?"#00f\">En":"#f00\">Dis"]abled cloaking.</font>")
return
/obj/mecha/verb/toggle_weapons_only_cycle() /obj/mecha/verb/toggle_weapons_only_cycle()
set category = "Exosuit Interface" set category = "Exosuit Interface"
set name = "Toggle weapons only cycling" set name = "Toggle weapons only cycling"
@@ -435,4 +463,3 @@
weapons_only_cycle = !weapons_only_cycle weapons_only_cycle = !weapons_only_cycle
src.occupant_message("<font color=\"[weapons_only_cycle?"#00f\">En":"#f00\">Dis"]abled weapons only cycling.</font>") src.occupant_message("<font color=\"[weapons_only_cycle?"#00f\">En":"#f00\">Dis"]abled weapons only cycling.</font>")
return return

View File

@@ -9,6 +9,14 @@
cargo_capacity = 1 cargo_capacity = 1
starting_components = list(
/obj/item/mecha_parts/component/hull,
/obj/item/mecha_parts/component/actuator,
/obj/item/mecha_parts/component/armor/lightweight,
/obj/item/mecha_parts/component/gas,
/obj/item/mecha_parts/component/electrical
)
/obj/mecha/medical/Initialize() /obj/mecha/medical/Initialize()
. = ..() . = ..()
var/turf/T = get_turf(src) var/turf/T = get_turf(src)

View File

@@ -1,4 +1,4 @@
/obj/mecha/medical/odysseus/ /obj/mecha/medical/odysseus
desc = "These exosuits are developed and produced by Vey-Med. (&copy; All rights reserved)." desc = "These exosuits are developed and produced by Vey-Med. (&copy; All rights reserved)."
name = "Odysseus" name = "Odysseus"
catalogue_data = list( catalogue_data = list(
@@ -9,8 +9,8 @@
initial_icon = "odysseus" initial_icon = "odysseus"
step_in = 2 step_in = 2
max_temperature = 15000 max_temperature = 15000
health = 120 health = 70
maxhealth = 120 maxhealth = 70
wreckage = /obj/effect/decal/mecha_wreckage/odysseus wreckage = /obj/effect/decal/mecha_wreckage/odysseus
internal_damage_threshold = 35 internal_damage_threshold = 35
deflect_chance = 15 deflect_chance = 15
@@ -139,5 +139,5 @@
/obj/mecha/medical/odysseus/old/New() /obj/mecha/medical/odysseus/old/New()
..() ..()
health = 25 health = 25
maxhealth = 100 //Just slightly worse. maxhealth = 50 //Just slightly worse.
cell.charge = rand(0, (cell.charge/2)) cell.charge = rand(0, (cell.charge/2))

View File

@@ -28,7 +28,8 @@
//operation_req_access = list(access_hos) //operation_req_access = list(access_hos)
damage_absorption = list("brute"=1,"fire"=1,"bullet"=1,"laser"=1,"energy"=1,"bomb"=1) damage_absorption = list("brute"=1,"fire"=1,"bullet"=1,"laser"=1,"energy"=1,"bomb"=1)
var/am = "d3c2fbcadca903a41161ccc9df9cf948" var/am = "d3c2fbcadca903a41161ccc9df9cf948"
damage_minimum = 0 //Incoming damage lower than this won't actually deal damage. Scrapes shouldn't be a real thing.
minimum_penetration = 0 //Incoming damage won't be fully applied if you don't have at least 20. Almost all AP clears this.
/obj/mecha/micro/melee_action(target as obj|mob|turf) /obj/mecha/micro/melee_action(target as obj|mob|turf)
if(internal_damage&MECHA_INT_CONTROL_LOST) if(internal_damage&MECHA_INT_CONTROL_LOST)

View File

@@ -30,6 +30,7 @@
max_equip = 3 max_equip = 3
max_micro_utility_equip = 0 max_micro_utility_equip = 0
max_micro_weapon_equip = 3 max_micro_weapon_equip = 3
damage_minimum = 5 //A teeny bit of armor
/obj/effect/decal/mecha_wreckage/micro/sec/polecat /obj/effect/decal/mecha_wreckage/micro/sec/polecat
name = "Polecat wreckage" name = "Polecat wreckage"

View File

@@ -14,6 +14,14 @@
minimum_penetration = 10 minimum_penetration = 10
starting_components = list(
/obj/item/mecha_parts/component/hull/durable,
/obj/item/mecha_parts/component/actuator,
/obj/item/mecha_parts/component/armor/mining,
/obj/item/mecha_parts/component/gas,
/obj/item/mecha_parts/component/electrical
)
/obj/mecha/working/ripley/Destroy() /obj/mecha/working/ripley/Destroy()
for(var/atom/movable/A in src.cargo) for(var/atom/movable/A in src.cargo)
A.loc = loc A.loc = loc

View File

@@ -46,6 +46,8 @@ var/global/list/image/fluidtrack_cache=list()
var/coming_state="blood1" var/coming_state="blood1"
var/going_state="blood2" var/going_state="blood2"
var/updatedtracks=0 var/updatedtracks=0
persistent = TRUE
generic_filth = FALSE
// dir = id in stack // dir = id in stack
var/list/setdirs=list( var/list/setdirs=list(

View File

@@ -1,3 +1,10 @@
/*
USAGE NOTE
For decals, the var Persistent = 'has already been saved', and is primarily used to prevent duplicate savings of generic filth (filth.dm).
This also means 'TRUE' can be used to define a decal as "Do not save at all, even as a generic replacement." if a dirt decal is considered 'too common' to save.
generic_filth = TRUE means when the decal is saved, it will be switched out for a generic green 'filth' decal.
*/
/obj/effect/decal/cleanable /obj/effect/decal/cleanable
plane = DIRTY_PLANE plane = DIRTY_PLANE
var/persistent = FALSE var/persistent = FALSE

View File

@@ -15,3 +15,14 @@
light_range = 5 light_range = 5
light_power = 3 light_power = 3
light_color = "#FFFFFF" light_color = "#FFFFFF"
/obj/effect/map_effect/perma_light/concentrated
name = "permanent light (concentrated)"
light_range = 2
light_power = 5
/obj/effect/map_effect/perma_light/concentrated/incandescent
name = "permanent light (concentrated incandescent)"
light_color = LIGHT_COLOR_INCANDESCENT_TUBE

View File

@@ -0,0 +1,344 @@
GLOBAL_LIST_EMPTY(all_portal_masters)
/*
Portal map effects allow a mapper to join two distant places together, while looking somewhat seamlessly connected.
This can allow for very strange PoIs that twist and turn in what appear to be physically impossible ways.
Portals do have some specific requirements when mapping them in;
- There must by one, and only one `/obj/effect/map_effect/portal/master` for each side of a portal.
- Both sides need to have matching `portal_id`s in order to link to each other.
- Each side must face opposite directions, e.g. if side A faces SOUTH, side B must face NORTH.
- Each side must have the same orientation, e.g. horizontal on both sides, or vertical on both sides.
- Portals can be made to be longer than 1x1 with `/obj/effect/map_effect/portal/line`s,
but both sides must have the same length.
- If portal lines are added, they must form a straight line and be next to a portal master or another portal line.
- If portal lines are used, both portal masters should be in the same relative position among the lines.
E.g. both being on the left most side on a horizontal row.
Portals also have some limitations to be aware of when mapping. Some of these are not an issue if you're trying to make an 'obvious' portal;
- The objects seen through portals are purely visual, which has many implications,
such as simple_mob AIs being blind to mobs on the other side of portals.
- Objects on the other side of a portal can be interacted with if the interaction has no range limitation,
or the distance between the two portal sides happens to be less than the interaction max range. Examine will probably work,
while picking up an item that appears to be next to you will fail.
- Sounds currently are not carried across portals.
- Mismatched lighting between each portal end can make the portal look obvious.
- Portals look weird when observing as a ghost, or otherwise when able to see through walls. Meson vision will also spoil the illusion.
- Walls that change icons based on neightboring walls can give away that a portal is nearby if both sides don't have a similar transition.
- Projectiles that pass through portals will generally work as intended, however aiming and firing upon someone on the other side of a portal
will likely be weird due to the click targeting the real position of the thing clicked instead of the apparent position.
Thrown objects suffer a similar fate.
- The tiles that are visually shown across a portal are determined based on visibility at the time of portal initialization,
and currently don't update, meaning that opacity changes are not reflected, e.g. a wall is deconstructed, or an airlock is opened.
- There is currently a small but somewhat noticable pause in mob movement when moving across a portal,
as a result of the mob's glide animation being inturrupted by a teleport.
- Gas is not transferred through portals, and ZAS is oblivious to them.
A lot of those limitations can potentially be solved with some more work. Otherwise, portals work best in static environments like Points of Interest,
when portals are shortly lived, or when portals are made to be obvious with special effects.
*/
/obj/effect/map_effect/portal
name = "portal subtype"
invisibility = 0
opacity = TRUE
plane = TURF_PLANE
layer = ABOVE_TURF_LAYER
appearance_flags = PIXEL_SCALE|KEEP_TOGETHER // Removed TILE_BOUND so things not visible on the other side stay hidden from the viewer.
var/obj/effect/map_effect/portal/counterpart = null // The portal line or master that this is connected to, on the 'other side'.
// Information used to apply `pixel_[x|y]` offsets so that the visuals line up.
// Set automatically by `calculate_dimensions()`.
var/total_height = 0 // Measured in tiles.
var/total_width = 0
var/portal_distance_x = 0 // How far the portal is from the left edge, in tiles.
var/portal_distance_y = 0 // How far the portal is from the top edge.
/obj/effect/map_effect/portal/Destroy()
vis_contents = null
if(counterpart)
counterpart.counterpart = null // Disconnect our counterpart from us
counterpart = null // Now disconnect us from them.
return ..()
// Called when something touches the portal, and usually teleports them to the other side.
/obj/effect/map_effect/portal/Crossed(atom/movable/AM)
if(AM.is_incorporeal())
return
..()
if(!AM)
return
if(!counterpart)
return
go_through_portal(AM)
/obj/effect/map_effect/portal/proc/go_through_portal(atom/movable/AM)
// TODO: Find a way to fake the glide or something.
if(isliving(AM))
var/mob/living/L = AM
if(L.pulling)
var/atom/movable/pulled = L.pulling
L.stop_pulling()
// For some reason, trying to put the pulled object behind the person makes the drag stop and it doesn't even move to the other side.
// pulled.forceMove(get_turf(counterpart))
pulled.forceMove(counterpart.get_focused_turf())
L.forceMove(counterpart.get_focused_turf())
L.start_pulling(pulled)
else
L.forceMove(counterpart.get_focused_turf())
else
AM.forceMove(counterpart.get_focused_turf())
// 'Focused turf' is the turf directly in front of a portal,
// and it is used both as the destination when crossing, as well as the PoV for visuals.
/obj/effect/map_effect/portal/proc/get_focused_turf()
return get_step(get_turf(src), dir)
// Determines the size of the block of turfs inside `vis_contents`, and where the portal is in relation to that.
/obj/effect/map_effect/portal/proc/calculate_dimensions()
var/highest_x = 0
var/lowest_x = 0
var/highest_y = 0
var/lowest_y = 0
// First pass is for finding the top right corner.
for(var/thing in vis_contents)
var/turf/T = thing
if(T.x > highest_x)
highest_x = T.x
if(T.y > highest_y)
highest_y = T.y
lowest_x = highest_x
lowest_y = highest_y
// Second one is for the bottom left corner.
for(var/thing in vis_contents)
var/turf/T = thing
if(T.x < lowest_x)
lowest_x = T.x
if(T.y < lowest_y)
lowest_y = T.y
// Now calculate the dimensions.
total_width = (highest_x - lowest_x) + 1
total_height = (highest_y - lowest_y) + 1
// Find how far the portal is from the edges.
var/turf/focused_T = counterpart.get_focused_turf()
portal_distance_x = lowest_x - focused_T.x
portal_distance_y = lowest_y - focused_T.y
// Portal masters manage everything else involving portals.
// This is the base type. Use `/side_a` or `/side_b` with matching IDs for actual portals.
/obj/effect/map_effect/portal/master
name = "portal master"
show_messages = TRUE // So portals can hear and see, and relay to the other side.
var/portal_id = "test" // For a portal to be made, both the A and B sides need to share the same ID value.
var/list/portal_lines = list()
/obj/effect/map_effect/portal/master/Initialize()
GLOB.all_portal_masters += src
find_lines()
..()
return INITIALIZE_HINT_LATELOAD
/obj/effect/map_effect/portal/master/LateInitialize()
find_counterparts()
make_visuals()
apply_offset()
/obj/effect/map_effect/portal/master/Destroy()
GLOB.all_portal_masters -= src
for(var/thing in portal_lines)
qdel(thing)
return ..()
/obj/effect/map_effect/portal/master/proc/find_lines()
var/list/dirs_to_search = list( turn(dir, 90), turn(dir, -90) )
for(var/dir_to_search in dirs_to_search)
var/turf/current_T = get_turf(src)
while(current_T)
current_T = get_step(current_T, dir_to_search)
var/obj/effect/map_effect/portal/line/line = locate() in current_T
if(line)
portal_lines += line
line.my_master = src
else
break
// Connects both sides of a portal together.
/obj/effect/map_effect/portal/master/proc/find_counterparts()
for(var/thing in GLOB.all_portal_masters)
var/obj/effect/map_effect/portal/master/M = thing
if(M == src)
continue
if(M.counterpart)
continue
if(M.portal_id == src.portal_id)
counterpart = M
M.counterpart = src
if(portal_lines.len)
for(var/i = 1 to portal_lines.len)
var/obj/effect/map_effect/portal/line/our_line = portal_lines[i]
var/obj/effect/map_effect/portal/line/their_line = M.portal_lines[i]
our_line.counterpart = their_line
their_line.counterpart = our_line
break
if(!counterpart)
crash_with("Portal master [type] ([x],[y],[z]) could not find another portal master with a matching portal_id ([portal_id]).")
/obj/effect/map_effect/portal/master/proc/make_visuals()
var/list/observed_turfs = list()
for(var/thing in portal_lines + src)
var/obj/effect/map_effect/portal/P = thing
P.name = null
P.icon_state = null
if(!P.counterpart)
return
var/turf/T = P.counterpart.get_focused_turf()
P.vis_contents += T
var/list/things = dview(world.view, T)
for(var/turf/turf in things)
if(get_dir(turf, T) & P.dir)
if(turf in observed_turfs) // Avoid showing the same turf twice or more for improved performance.
continue
P.vis_contents += turf
observed_turfs += turf
P.calculate_dimensions()
// Shifts the portal's pixels in order to line up properly, as BYOND offsets the sprite when it holds multiple turfs inside `vis_contents`.
// This undos the shift that BYOND did.
/obj/effect/map_effect/portal/master/proc/apply_offset()
for(var/thing in portal_lines + src)
var/obj/effect/map_effect/portal/P = thing
P.pixel_x = WORLD_ICON_SIZE * P.portal_distance_x
P.pixel_y = WORLD_ICON_SIZE * P.portal_distance_y
// Allows portals to transfer emotes.
// Only portal masters do this to avoid flooding the other side with duplicate messages.
/obj/effect/map_effect/portal/master/see_emote(mob/M, text)
if(!counterpart)
return
var/turf/T = counterpart.get_focused_turf()
var/list/in_range = get_mobs_and_objs_in_view_fast(T, world.view, 0)
var/list/mobs_to_relay = in_range["mobs"]
for(var/thing in mobs_to_relay)
var/mob/mob = thing
var/rendered = "<span class='message'>[text]</span>"
mob.show_message(rendered)
..()
// Allows portals to transfer visible messages.
/obj/effect/map_effect/portal/master/show_message(msg, type, alt, alt_type)
if(!counterpart)
return
var/rendered = "<span class='message'>[msg]</span>"
var/turf/T = counterpart.get_focused_turf()
var/list/in_range = get_mobs_and_objs_in_view_fast(T, world.view, 0)
var/list/mobs_to_relay = in_range["mobs"]
for(var/thing in mobs_to_relay)
var/mob/mob = thing
mob.show_message(rendered)
..()
// Allows portals to transfer speech.
/obj/effect/map_effect/portal/master/hear_talk(mob/M, list/message_pieces, verb)
if(!counterpart)
return
var/turf/T = counterpart.get_focused_turf()
var/list/in_range = get_mobs_and_objs_in_view_fast(T, world.view, 0)
var/list/mobs_to_relay = in_range["mobs"]
for(var/thing in mobs_to_relay)
var/mob/mob = thing
var/message = mob.combine_message(message_pieces, verb, M)
var/name_used = M.GetVoice()
var/rendered = null
rendered = "<span class='game say'><span class='name'>[name_used]</span> [message]</span>"
mob.show_message(rendered, 2)
..()
// Returns the position that an atom that's hopefully on the other side of the portal would be if it were really there.
// Z levels not taken into account.
/obj/effect/map_effect/portal/master/proc/get_apparent_position(atom/A)
if(!counterpart)
return null
var/turf/true_turf = get_turf(A)
var/obj/effect/map_effect/portal/master/other_master = counterpart
var/in_vis_contents = FALSE
for(var/thing in other_master.portal_lines + other_master)
var/obj/effect/map_effect/portal/P = thing
if(P in true_turf.vis_locs)
in_vis_contents = TRUE
break
if(!in_vis_contents)
return null // Not in vision of the other portal.
var/turf/their_focus = counterpart.get_focused_turf()
var/turf/our_focus = get_focused_turf()
var/relative_x = (true_turf.x - our_focus.x)
relative_x += SIGN(relative_x)
var/relative_y = (true_turf.y - our_focus.y)
relative_y += SIGN(relative_y)
return new /datum/position(their_focus.x + relative_x, their_focus.y + relative_y, our_focus.z)
/obj/effect/map_effect/portal/master/side_a
name = "portal master A"
icon_state = "portal_side_a"
// color = "#00FF00"
/obj/effect/map_effect/portal/master/side_b
name = "portal master B"
icon_state = "portal_side_b"
// color = "#FF0000"
// Portal lines extend out from the sides of portal masters,
// They let portals be longer than 1x1.
// Both sides MUST be the same length, meaning if side A is 1x3, side B must also be 1x3.
/obj/effect/map_effect/portal/line
name = "portal line"
var/obj/effect/map_effect/portal/master/my_master = null
/obj/effect/map_effect/portal/line/Destroy()
if(my_master)
my_master.portal_lines -= src
my_master = null
return ..()
/obj/effect/map_effect/portal/line/side_a
name = "portal line A"
icon_state = "portal_line_side_a"
/obj/effect/map_effect/portal/line/side_b
name = "portal line B"
icon_state = "portal_line_side_b"

View File

@@ -136,10 +136,10 @@ HALOGEN COUNTER - Radcount on mobs
for(var/A in C.reagents.reagent_list) for(var/A in C.reagents.reagent_list)
var/datum/reagent/R = A var/datum/reagent/R = A
if(R.scannable) if(R.scannable)
reagentdata["[R.id]"] = "<span class='notice'>\t[round(C.reagents.get_reagent_amount(R.id), 1)]u [R.name]</span><br>" reagentdata["[R.id]"] = "<span class='notice'>\t[round(C.reagents.get_reagent_amount(R.id), 1)]u [R.name][(R.overdose && R.volume > R.overdose) ? " - <span class='danger'>Overdose</span>" : ""]</span><br>"
else else
unknown++ unknown++
unknownreagents["[R.id]"] = "<span class='notice'>\t[round(C.reagents.get_reagent_amount(R.id), 1)]u [R.name]</span><br>" unknownreagents["[R.id]"] = "<span class='notice'>\t[round(C.reagents.get_reagent_amount(R.id), 1)]u [R.name][(R.overdose && R.volume > R.overdose) ? " - <span class='danger'>Overdose</span>" : ""]</span><br>"
if(reagentdata.len) if(reagentdata.len)
dat += "<span class='notice'>Beneficial reagents detected in subject's blood:</span><br>" dat += "<span class='notice'>Beneficial reagents detected in subject's blood:</span><br>"
for(var/d in reagentdata) for(var/d in reagentdata)
@@ -156,14 +156,14 @@ HALOGEN COUNTER - Radcount on mobs
var/stomachreagentdata[0] var/stomachreagentdata[0]
var/stomachunknownreagents[0] var/stomachunknownreagents[0]
for(var/B in C.ingested.reagent_list) for(var/B in C.ingested.reagent_list)
var/datum/reagent/T = B var/datum/reagent/R = B
if(T.scannable) if(R.scannable)
stomachreagentdata["[T.id]"] = "<span class='notice'>\t[round(C.ingested.get_reagent_amount(T.id), 1)]u [T.name]</span><br>" stomachreagentdata["[R.id]"] = "<span class='notice'>\t[round(C.ingested.get_reagent_amount(R.id), 1)]u [R.name][(R.overdose && R.volume > R.overdose) ? " - <span class='danger'>Overdose</span>" : ""]</span><br>"
if (advscan == 0 || showadvscan == 0) if (advscan == 0 || showadvscan == 0)
dat += "<span class='notice'>[T.name] found in subject's stomach.</span><br>" dat += "<span class='notice'>[R.name] found in subject's stomach.</span><br>"
else else
++unknown ++unknown
stomachunknownreagents["[T.id]"] = "<span class='notice'>\t[round(C.ingested.get_reagent_amount(T.id), 1)]u [T.name]</span><br>" stomachunknownreagents["[R.id]"] = "<span class='notice'>\t[round(C.ingested.get_reagent_amount(R.id), 1)]u [R.name][(R.overdose && R.volume > R.overdose) ? " - <span class='danger'>Overdose</span>" : ""]</span><br>"
if(advscan >= 1 && showadvscan == 1) if(advscan >= 1 && showadvscan == 1)
dat += "<span class='notice'>Beneficial reagents detected in subject's stomach:</span><br>" dat += "<span class='notice'>Beneficial reagents detected in subject's stomach:</span><br>"
for(var/d in stomachreagentdata) for(var/d in stomachreagentdata)
@@ -180,14 +180,14 @@ HALOGEN COUNTER - Radcount on mobs
var/touchreagentdata[0] var/touchreagentdata[0]
var/touchunknownreagents[0] var/touchunknownreagents[0]
for(var/B in C.touching.reagent_list) for(var/B in C.touching.reagent_list)
var/datum/reagent/T = B var/datum/reagent/R = B
if(T.scannable) if(R.scannable)
touchreagentdata["[T.id]"] = "<span class='notice'>\t[round(C.touching.get_reagent_amount(T.id), 1)]u [T.name]</span><br>" touchreagentdata["[R.id]"] = "<span class='notice'>\t[round(C.touching.get_reagent_amount(R.id), 1)]u [R.name][(R.overdose && R.can_overdose_touch && R.volume > R.overdose) ? " - <span class='danger'>Overdose</span>" : ""]</span><br>"
if (advscan == 0 || showadvscan == 0) if (advscan == 0 || showadvscan == 0)
dat += "<span class='notice'>[T.name] found in subject's dermis.</span><br>" dat += "<span class='notice'>[R.name] found in subject's dermis.</span><br>"
else else
++unknown ++unknown
touchunknownreagents["[T.id]"] = "<span class='notice'>\t[round(C.ingested.get_reagent_amount(T.id), 1)]u [T.name]</span><br>" touchunknownreagents["[R.id]"] = "<span class='notice'>\t[round(C.ingested.get_reagent_amount(R.id), 1)]u [R.name][(R.overdose && R.can_overdose_touch && R.volume > R.overdose) ? " - <span class='danger'>Overdose</span>" : ""]</span><br>"
if(advscan >= 1 && showadvscan == 1) if(advscan >= 1 && showadvscan == 1)
dat += "<span class='notice'>Beneficial reagents detected in subject's dermis:</span><br>" dat += "<span class='notice'>Beneficial reagents detected in subject's dermis:</span><br>"
for(var/d in touchreagentdata) for(var/d in touchreagentdata)

View File

@@ -289,6 +289,16 @@
if(!teleport_checks(target,user)) if(!teleport_checks(target,user))
return //The checks proc can send them a message if it wants. return //The checks proc can send them a message if it wants.
if(istype(target, /mob/living))
var/mob/living/L = target
if(!L.stat)
if(L != user)
if(L.a_intent != I_HELP || L.has_AI())
to_chat(user, "<span class='notice'>[L] is resisting your attempt to teleport them with \the [src].</span>")
to_chat(L, "<span class='danger'> [user] is trying to teleport you with \the [src]!</span>")
if(!do_after(user, 30, L))
return
//Bzzt. //Bzzt.
ready = 0 ready = 0
power_source.use(charge_cost) power_source.use(charge_cost)

View File

@@ -29,3 +29,39 @@
R.verbs += /mob/living/proc/set_size R.verbs += /mob/living/proc/set_size
return 1 return 1
/obj/item/borg/upgrade/bellysizeupgrade
name = "robotic Hound process capacity upgrade Module"
desc = "Used to upgrade a hound belly capacity. This only affects total volume and such, you won't be able to support more than one patient. Usable once."
icon_state = "cyborg_upgrade2"
item_state = "cyborg_upgrade"
require_module = 1
/obj/item/borg/upgrade/bellysizeupgrade/action(var/mob/living/silicon/robot/R)
if(..()) return 0
if(!R.module || R.dogborg == FALSE)//can work
to_chat(R, "Upgrade mounting error! No suitable hardpoint detected!")
to_chat(usr, "There's no mounting point for the module! Try upgrading another model.")
return 0
var/obj/item/device/dogborg/sleeper/T = locate() in R.module
if(!T)
T = locate() in R.module.contents
if(!T)
T = locate() in R.module.modules
if(!T)
to_chat(usr, "<span class='warning'>This robot has had its processor removed!</span>")
return 0
if(T.upgraded_capacity)// == TRUE
to_chat(R, "Maximum capacity achieved for this hardpoint!")
to_chat(usr, "There's no room for another capacity upgrade!")
return 0
else
var/X = T.max_item_count*2
T.max_item_count = X //I couldn't do T = maxitem*2 for some reason.
to_chat(R, "Internal capacity doubled.")
to_chat(usr, "Internal capacity doubled.")
T.upgraded_capacity = TRUE
return 1

View File

@@ -425,6 +425,15 @@
return return
..() ..()
/obj/random/mech_toy
name = "Random Mech Toy"
desc = "This is a random mech toy."
icon = 'icons/obj/toy.dmi'
icon_state = "ripleytoy"
/obj/random/mech_toy/item_to_spawn()
return pick(typesof(/obj/item/toy/prize))
/obj/item/toy/prize/ripley /obj/item/toy/prize/ripley
name = "toy ripley" name = "toy ripley"
desc = "Mini-Mecha action figure! Collect them all! 1/11." desc = "Mini-Mecha action figure! Collect them all! 1/11."

View File

@@ -199,6 +199,16 @@
/obj/item/weapon/storage/box/empshells/large /obj/item/weapon/storage/box/empshells/large
starts_with = list(/obj/item/ammo_casing/a12g/emp = 16) starts_with = list(/obj/item/ammo_casing/a12g/emp = 16)
/obj/item/weapon/storage/box/flechetteshells
name = "box of shotgun flechettes"
desc = "It has a picture of a gun and several warning symbols on the front.<br>WARNING: Live ammunition. Misuse may result in serious injury or death."
icon_state = "lethalslug_box"
item_state_slots = list(slot_r_hand_str = "syringe_kit", slot_l_hand_str = "syringe_kit")
starts_with = list(/obj/item/ammo_casing/a12g/flechette = 8)
/obj/item/weapon/storage/box/flechetteshells/large
starts_with = list(/obj/item/ammo_casing/a12g/flechette = 16)
/obj/item/weapon/storage/box/sniperammo /obj/item/weapon/storage/box/sniperammo
name = "box of 14.5mm shells" name = "box of 14.5mm shells"
desc = "It has a picture of a gun and several warning symbols on the front.<br>WARNING: Live ammunition. Misuse may result in serious injury or death." desc = "It has a picture of a gun and several warning symbols on the front.<br>WARNING: Live ammunition. Misuse may result in serious injury or death."

View File

@@ -30,7 +30,7 @@
/obj/structure/mob_spawner/Destroy() /obj/structure/mob_spawner/Destroy()
STOP_PROCESSING(SSobj, src) STOP_PROCESSING(SSobj, src)
for(var/mob/living/L in spawned_mobs) for(var/mob/living/L in spawned_mobs)
L.source_spawner = null L.nest = null
spawned_mobs.Cut() spawned_mobs.Cut()
return ..() return ..()
@@ -57,7 +57,7 @@
if(!ispath(mob_path)) if(!ispath(mob_path))
return 0 return 0
var/mob/living/L = new mob_path(get_turf(src)) var/mob/living/L = new mob_path(get_turf(src))
L.source_spawner = src L.nest = src
spawned_mobs.Add(L) spawned_mobs.Add(L)
last_spawn = world.time last_spawn = world.time
if(total_spawns > 0) if(total_spawns > 0)

View File

@@ -33,7 +33,9 @@
prob(10);/mob/living/simple_mob/animal/passive/mouse, prob(10);/mob/living/simple_mob/animal/passive/mouse,
prob(10);/mob/living/simple_mob/animal/passive/yithian, prob(10);/mob/living/simple_mob/animal/passive/yithian,
prob(10);/mob/living/simple_mob/animal/passive/tindalos, prob(10);/mob/living/simple_mob/animal/passive/tindalos,
prob(10);/mob/living/simple_mob/animal/passive/pillbug,
prob(10);/mob/living/simple_mob/animal/passive/dog/tamaskan, prob(10);/mob/living/simple_mob/animal/passive/dog/tamaskan,
prob(10);/mob/living/simple_mob/animal/passive/dog/brittany,
prob(3);/mob/living/simple_mob/animal/passive/bird/parrot, prob(3);/mob/living/simple_mob/animal/passive/bird/parrot,
prob(1);/mob/living/simple_mob/animal/passive/crab) prob(1);/mob/living/simple_mob/animal/passive/crab)
@@ -69,10 +71,12 @@
/obj/random/mob/sif/item_to_spawn() /obj/random/mob/sif/item_to_spawn()
return pick(prob(30);/mob/living/simple_mob/animal/sif/diyaab, return pick(prob(30);/mob/living/simple_mob/animal/sif/diyaab,
prob(20);/mob/living/simple_mob/animal/passive/hare,
prob(15);/mob/living/simple_mob/animal/passive/crab, prob(15);/mob/living/simple_mob/animal/passive/crab,
prob(15);/mob/living/simple_mob/animal/passive/penguin, prob(15);/mob/living/simple_mob/animal/passive/penguin,
prob(15);/mob/living/simple_mob/animal/passive/mouse, prob(15);/mob/living/simple_mob/animal/passive/mouse,
prob(15);/mob/living/simple_mob/animal/passive/dog/tamaskan, prob(15);/mob/living/simple_mob/animal/passive/dog/tamaskan,
prob(10);/mob/living/simple_mob/animal/sif/siffet,
prob(2);/mob/living/simple_mob/animal/giant_spider/frost, prob(2);/mob/living/simple_mob/animal/giant_spider/frost,
prob(1);/mob/living/simple_mob/animal/space/goose, prob(1);/mob/living/simple_mob/animal/space/goose,
prob(20);/mob/living/simple_mob/animal/passive/crab) prob(20);/mob/living/simple_mob/animal/passive/crab)
@@ -88,6 +92,7 @@
/obj/random/mob/sif/peaceful/item_to_spawn() /obj/random/mob/sif/peaceful/item_to_spawn()
return pick(prob(30);/mob/living/simple_mob/animal/sif/diyaab, return pick(prob(30);/mob/living/simple_mob/animal/sif/diyaab,
prob(20);/mob/living/simple_mob/animal/passive/hare,
prob(15);/mob/living/simple_mob/animal/passive/crab, prob(15);/mob/living/simple_mob/animal/passive/crab,
prob(15);/mob/living/simple_mob/animal/passive/penguin, prob(15);/mob/living/simple_mob/animal/passive/penguin,
prob(15);/mob/living/simple_mob/animal/passive/mouse, prob(15);/mob/living/simple_mob/animal/passive/mouse,
@@ -102,6 +107,8 @@
/obj/random/mob/sif/hostile/item_to_spawn() /obj/random/mob/sif/hostile/item_to_spawn()
return pick(prob(22);/mob/living/simple_mob/animal/sif/savik, return pick(prob(22);/mob/living/simple_mob/animal/sif/savik,
prob(33);/mob/living/simple_mob/animal/giant_spider/frost, prob(33);/mob/living/simple_mob/animal/giant_spider/frost,
prob(20);/mob/living/simple_mob/animal/sif/frostfly,
prob(10);/mob/living/simple_mob/animal/sif/tymisian,
prob(45);/mob/living/simple_mob/animal/sif/shantak) prob(45);/mob/living/simple_mob/animal/sif/shantak)
/obj/random/mob/sif/kururak /obj/random/mob/sif/kururak
@@ -329,6 +336,12 @@
/mob/living/simple_mob/animal/sif/duck, /mob/living/simple_mob/animal/sif/duck,
/mob/living/simple_mob/animal/sif/duck /mob/living/simple_mob/animal/sif/duck
), ),
prob(15);list(
/mob/living/simple_mob/animal/passive/hare,
/mob/living/simple_mob/animal/passive/hare,
/mob/living/simple_mob/animal/passive/hare,
/mob/living/simple_mob/animal/passive/hare
),
prob(10);list( prob(10);list(
/mob/living/simple_mob/animal/sif/shantak/retaliate, /mob/living/simple_mob/animal/sif/shantak/retaliate,
/mob/living/simple_mob/animal/sif/shantak/retaliate, /mob/living/simple_mob/animal/sif/shantak/retaliate,

View File

@@ -12,7 +12,7 @@
var/vision_range = 7 // How far the targeting system will look for things to kill. Note that values higher than 7 are 'offscreen' and might be unsporting. var/vision_range = 7 // How far the targeting system will look for things to kill. Note that values higher than 7 are 'offscreen' and might be unsporting.
var/respect_alpha = TRUE // If true, mobs with a sufficently low alpha will be treated as invisible. var/respect_alpha = TRUE // If true, mobs with a sufficently low alpha will be treated as invisible.
var/alpha_vision_threshold = 127 // Targets with an alpha less or equal to this will be considered invisible. Requires above var to be true. var/alpha_vision_threshold = FAKE_INVIS_ALPHA_THRESHOLD // Targets with an alpha less or equal to this will be considered invisible. Requires above var to be true.
var/lose_target_time = 0 // world.time when a target was lost. var/lose_target_time = 0 // world.time when a target was lost.
var/lose_target_timeout = 5 SECONDS // How long until a mob 'times out' and stops trying to find the mob that disappeared. var/lose_target_timeout = 5 SECONDS // How long until a mob 'times out' and stops trying to find the mob that disappeared.

View File

@@ -183,12 +183,6 @@
ckeywhitelist = list("cockatricexl") ckeywhitelist = list("cockatricexl")
character_name = list("James Holder") character_name = list("James Holder")
/datum/gear/fluff/jasmine_implant
path = /obj/item/weapon/implanter/reagent_generator/jasmine
display_name = "Jasmine's Implant"
ckeywhitelist = list("cameron653")
character_name = list("Jasmine Lizden")
/datum/gear/fluff/diana_robe /datum/gear/fluff/diana_robe
path = /obj/item/clothing/suit/fluff/purp_robes path = /obj/item/clothing/suit/fluff/purp_robes
display_name = "Diana's Robes" display_name = "Diana's Robes"
@@ -310,11 +304,6 @@
allowed_roles = list("Explorer") allowed_roles = list("Explorer")
// G CKEYS // G CKEYS
/datum/gear/fluff/eldi_implant
path = /obj/item/weapon/implanter/reagent_generator/eldi
display_name = "Eldi's Implant"
ckeywhitelist = list("gowst")
character_name = list("Eldi Moljir")
// H CKEYS // H CKEYS
/datum/gear/fluff/lauren_medal /datum/gear/fluff/lauren_medal
@@ -335,12 +324,6 @@
ckeywhitelist = list("hottokeeki") ckeywhitelist = list("hottokeeki")
character_name = list("Belle Day") character_name = list("Belle Day")
/datum/gear/fluff/belle_implant
path = /obj/item/weapon/implanter/reagent_generator/belle
display_name = "Belle's Implant"
ckeywhitelist = list("hottokeeki")
character_name = list("Belle Day")
// I CKEYS // I CKEYS
/datum/gear/fluff/ruda_badge /datum/gear/fluff/ruda_badge
path = /obj/item/clothing/accessory/badge/holo/detective/ruda path = /obj/item/clothing/accessory/badge/holo/detective/ruda
@@ -553,12 +536,6 @@
ckeywhitelist = list("kiwidaninja") ckeywhitelist = list("kiwidaninja")
character_name = list("Chakat Taiga") character_name = list("Chakat Taiga")
/datum/gear/fluff/rischi_implant
path = /obj/item/weapon/implanter/reagent_generator/rischi
display_name = "Rischi's Implant"
ckeywhitelist = list("konabird")
character_name = list("Rischi")
/datum/gear/fluff/ashley_medal /datum/gear/fluff/ashley_medal
path = /obj/item/clothing/accessory/medal/nobel_science/fluff/ashley path = /obj/item/clothing/accessory/medal/nobel_science/fluff/ashley
display_name = "Ashley's Medal" display_name = "Ashley's Medal"
@@ -580,12 +557,6 @@
ckeywhitelist = list("luminescentring") ckeywhitelist = list("luminescentring")
character_name = list("Briana Moore") character_name = list("Briana Moore")
/datum/gear/fluff/savannah_implant
path = /obj/item/weapon/implanter/reagent_generator/savannah
display_name = "Savannah's Implant"
ckeywhitelist = list("lycanthorph")
character_name = list("Savannah Dixon")
// M CKEYS // M CKEYS
/datum/gear/fluff/phi_box /datum/gear/fluff/phi_box
path = /obj/item/weapon/storage/box/fluff/phi path = /obj/item/weapon/storage/box/fluff/phi
@@ -842,12 +813,6 @@
ckeywhitelist = list("silvertalismen") ckeywhitelist = list("silvertalismen")
character_name = list("Tasy Ruffles") character_name = list("Tasy Ruffles")
/datum/gear/fluff/evian_implant
path = /obj/item/weapon/implanter/reagent_generator/evian
display_name = "Evian's Implant"
ckeywhitelist = list("silvertalismen")
character_name = list("Evian")
/datum/gear/fluff/fortune_backpack /datum/gear/fluff/fortune_backpack
path = /obj/item/weapon/storage/backpack/satchel/fluff/swat43bag path = /obj/item/weapon/storage/backpack/satchel/fluff/swat43bag
display_name = "Fortune's Backpack" display_name = "Fortune's Backpack"
@@ -861,12 +826,6 @@
ckeywhitelist = list("stobarico") ckeywhitelist = list("stobarico")
character_name = list("Alexis Bloise") character_name = list("Alexis Bloise")
/datum/gear/fluff/roiz_implant
path = /obj/item/weapon/implanter/reagent_generator/roiz
display_name = "Roiz's Implant"
ckeywhitelist = list("spoopylizz")
character_name = list("Roiz Lizden")
/datum/gear/fluff/roiz_coat /datum/gear/fluff/roiz_coat
path = /obj/item/clothing/suit/storage/hooded/wintercoat/roiz path = /obj/item/clothing/suit/storage/hooded/wintercoat/roiz
display_name = "Roiz's Coat" display_name = "Roiz's Coat"
@@ -1020,12 +979,6 @@
ckeywhitelist = list("vorrarkul") ckeywhitelist = list("vorrarkul")
character_name = list("Theodora Lindt") character_name = list("Theodora Lindt")
/datum/gear/fluff/theodora_implant
path = /obj/item/weapon/implanter/reagent_generator/vorrarkul
display_name = "Theodora's Implant"
ckeywhitelist = list("vorrarkul")
character_name = list("Theodora Lindt")
/datum/gear/fluff/kaitlyn_plush /datum/gear/fluff/kaitlyn_plush
path = /obj/item/toy/plushie/mouse/fluff path = /obj/item/toy/plushie/mouse/fluff
display_name = "Kaitlyn's Mouse Plush" display_name = "Kaitlyn's Mouse Plush"
@@ -1102,12 +1055,6 @@
ckeywhitelist = list("wickedtemp") ckeywhitelist = list("wickedtemp")
character_name = list("Chakat Tempest Venosare") character_name = list("Chakat Tempest Venosare")
/datum/gear/fluff/tempest_implant
path = /obj/item/weapon/implanter/reagent_generator/tempest
display_name = "Tempest's Implant"
ckeywhitelist = list("wickedtemp")
character_name = list("Chakat Tempest Venosare")
// X CKEYS // X CKEYS
/datum/gear/fluff/penelope_box /datum/gear/fluff/penelope_box
path = /obj/item/weapon/storage/box/fluff/penelope path = /obj/item/weapon/storage/box/fluff/penelope

View File

@@ -583,6 +583,7 @@
var/obj/item/thing var/obj/item/thing
var/delete = 1 var/delete = 1
var/status = CI.container.check_contents() var/status = CI.container.check_contents()
if (status == 1)//If theres only one object in a container then we extract that if (status == 1)//If theres only one object in a container then we extract that
thing = locate(/obj/item) in CI.container thing = locate(/obj/item) in CI.container
delete = 0 delete = 0
@@ -596,6 +597,7 @@
qdel(CI) qdel(CI)
else else
CI.reset()//reset instead of deleting if the container is left inside CI.reset()//reset instead of deleting if the container is left inside
user.visible_message("<span class='notice'>\The [user] remove \the [thing] from \the [src].</span>")
/obj/machinery/appliance/proc/cook_mob(var/mob/living/victim, var/mob/user) /obj/machinery/appliance/proc/cook_mob(var/mob/living/victim, var/mob/user)
return return

View File

@@ -145,7 +145,7 @@
/obj/item/weapon/reagent_containers/cooking_container/oven /obj/item/weapon/reagent_containers/cooking_container/oven
name = "oven dish" name = "oven dish"
shortname = "shelf" shortname = "shelf"
desc = "Put ingredients in this; designed for use with an oven. Warranty void if used incorrectly." desc = "Put ingredients in this; designed for use with an oven. Warranty void if used incorrectly. Alt click to remove contents."
icon_state = "ovendish" icon_state = "ovendish"
max_space = 30 max_space = 30
max_reagents = 120 max_reagents = 120
@@ -162,11 +162,11 @@
/obj/item/weapon/reagent_containers/cooking_container/fryer /obj/item/weapon/reagent_containers/cooking_container/fryer
name = "fryer basket" name = "fryer basket"
shortname = "basket" shortname = "basket"
desc = "Put ingredients in this; designed for use with a deep fryer. Warranty void if used incorrectly." desc = "Put ingredients in this; designed for use with a deep fryer. Warranty void if used incorrectly. Alt click to remove contents."
icon_state = "basket" icon_state = "basket"
/obj/item/weapon/reagent_containers/cooking_container/grill /obj/item/weapon/reagent_containers/cooking_container/grill
name = "grill rack" name = "grill rack"
shortname = "rack" shortname = "rack"
desc = "Put ingredients 'in'/on this; designed for use with a grill. Warranty void if used incorrectly." desc = "Put ingredients 'in'/on this; designed for use with a grill. Warranty void if used incorrectly. Alt click to remove contents."
icon_state = "grillrack" icon_state = "grillrack"

View File

@@ -12,7 +12,7 @@
circuit = /obj/item/weapon/circuitboard/fryer circuit = /obj/item/weapon/circuitboard/fryer
appliancetype = FRYER appliancetype = FRYER
active_power_usage = 12 KILOWATTS active_power_usage = 12 KILOWATTS
heating_power = 12000 heating_power = 12 KILOWATTS
light_y = 15 light_y = 15
@@ -24,7 +24,7 @@
// Power used to maintain temperature once it's heated. // Power used to maintain temperature once it's heated.
// Going with 25% of the active power. This is a somewhat arbitrary value. // Going with 25% of the active power. This is a somewhat arbitrary value.
resistance = 60000 // Approx. 10 minutes to heat up. resistance = 10 KILOWATTS // Approx. 10 minutes to heat up.
max_contents = 2 max_contents = 2
container_type = /obj/item/weapon/reagent_containers/cooking_container/fryer container_type = /obj/item/weapon/reagent_containers/cooking_container/fryer

View File

@@ -9,10 +9,10 @@
can_burn_food = TRUE can_burn_food = TRUE
circuit = /obj/item/weapon/circuitboard/oven circuit = /obj/item/weapon/circuitboard/oven
active_power_usage = 6 KILOWATTS active_power_usage = 6 KILOWATTS
heating_power = 6000 heating_power = 6 KILOWATTS
//Based on a double deck electric convection oven //Based on a double deck electric convection oven
resistance = 30000 // Approx. 12 minutes to heat up. resistance = 12 KILOWATTS // Approx. 12 minutes to heat up.
idle_power_usage = 2 KILOWATTS idle_power_usage = 2 KILOWATTS
//uses ~30% power to stay warm //uses ~30% power to stay warm
optimal_power = 0.8 // Oven cooks .2 faster than the default speed. optimal_power = 0.8 // Oven cooks .2 faster than the default speed.
@@ -86,6 +86,7 @@
cooking = FALSE cooking = FALSE
playsound(src, 'sound/machines/hatch_open.ogg', 20, 1) playsound(src, 'sound/machines/hatch_open.ogg', 20, 1)
to_chat(user, "<span class='notice'>You [open? "close":"open"] the oven door</span>")
update_icon() update_icon()
/obj/machinery/appliance/cooker/oven/proc/manip(var/obj/item/I) /obj/machinery/appliance/cooker/oven/proc/manip(var/obj/item/I)

View File

@@ -20,27 +20,6 @@
) )
result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/sushi result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/sushi
/datum/recipe/chocroizegg
items = list(
/obj/item/weapon/reagent_containers/food/snacks/chocolatebar,
/obj/item/weapon/reagent_containers/food/snacks/egg/roiz
)
result = /obj/item/weapon/reagent_containers/food/snacks/chocolateegg/roiz
/datum/recipe/friedroizegg
reagents = list("sodiumchloride" = 1, "blackpepper" = 1)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/egg/roiz
)
result = /obj/item/weapon/reagent_containers/food/snacks/friedegg/roiz
/datum/recipe/boiledroizegg
reagents = list("water" = 5)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/egg/roiz
)
result = /obj/item/weapon/reagent_containers/food/snacks/boiledegg/roiz
/datum/recipe/lobster /datum/recipe/lobster
fruit = list("lemon" = 1, "cabbage" = 1) fruit = list("lemon" = 1, "cabbage" = 1)
items = list( items = list(

View File

@@ -325,7 +325,7 @@
for(var/mob/living/M in mobs_in_area(linkedholodeck)) for(var/mob/living/M in mobs_in_area(linkedholodeck))
if(M.mind) if(M.mind)
linkedholodeck.play_ambience(M) linkedholodeck.play_ambience(M, initial = TRUE)
linkedholodeck.sound_env = A.sound_env linkedholodeck.sound_env = A.sound_env

View File

@@ -55,6 +55,14 @@
var/emp_modifier // Added to the EMP strength, which is an inverse scale from 1 to 4, with 1 being the strongest EMP. 5 is a nullification. var/emp_modifier // Added to the EMP strength, which is an inverse scale from 1 to 4, with 1 being the strongest EMP. 5 is a nullification.
var/explosion_modifier // Added to the bomb strength, which is an inverse scale from 1 to 3, with 1 being gibstrength. 4 is a nullification. var/explosion_modifier // Added to the bomb strength, which is an inverse scale from 1 to 3, with 1 being gibstrength. 4 is a nullification.
// Note that these are combined with the mob's real armor values additatively. You can also omit specific armor types.
var/list/armor_percent = null // List of armor values to add to the holder when doing armor calculations. This is for percentage based armor. E.g. 50 = half damage.
var/list/armor_flat = null // Same as above but only for flat armor calculations. E.g. 5 = 5 less damage (this comes after percentage).
// Unlike armor, this is multiplicative. Two 50% protection modifiers will be combined into 75% protection (assuming no base protection on the mob).
var/heat_protection = null // Modifies how 'heat' protection is calculated, like wearing a firesuit. 1 = full protection.
var/cold_protection = null // Ditto, but for cold, like wearing a winter coat.
var/siemens_coefficient = null // Similar to above two vars but 0 = full protection, to be consistant with siemens numbers everywhere else.
var/vision_flags // Vision flags to add to the mob. SEE_MOB, SEE_OBJ, etc. var/vision_flags // Vision flags to add to the mob. SEE_MOB, SEE_OBJ, etc.
/datum/modifier/New(var/new_holder, var/new_origin) /datum/modifier/New(var/new_holder, var/new_origin)
@@ -186,10 +194,14 @@
// Checks if the mob has a modifier type. // Checks if the mob has a modifier type.
/mob/living/proc/has_modifier_of_type(var/modifier_type) /mob/living/proc/has_modifier_of_type(var/modifier_type)
return get_modifier_of_type(modifier_type) ? TRUE : FALSE
// Gets the first instance of a specific modifier type or subtype.
/mob/living/proc/get_modifier_of_type(var/modifier_type)
for(var/datum/modifier/M in modifiers) for(var/datum/modifier/M in modifiers)
if(istype(M, modifier_type)) if(istype(M, modifier_type))
return TRUE return M
return FALSE return null
// This displays the actual 'numbers' that a modifier is doing. Should only be shown in OOC contexts. // This displays the actual 'numbers' that a modifier is doing. Should only be shown in OOC contexts.
// When adding new effects, be sure to update this as well. // When adding new effects, be sure to update this as well.

View File

@@ -398,3 +398,32 @@ the artifact triggers the rage.
/datum/modifier/outline_test/tick() /datum/modifier/outline_test/tick()
animate(filter_instance, size = 3, time = 0.25 SECONDS) animate(filter_instance, size = 3, time = 0.25 SECONDS)
animate(size = 1, 0.25 SECONDS) animate(size = 1, 0.25 SECONDS)
// Acts as a psuedo-godmode, yet probably is more reliable than the actual var for it nowdays.
// Can't protect from instantly killing things like singulos.
/datum/modifier/invulnerable
name = "invulnerable"
desc = "You are almost immune to harm, for a little while at least."
stacks = MODIFIER_STACK_EXTEND
disable_duration_percent = 0
incoming_damage_percent = 0
// bleeding_rate_percent = 0
pain_immunity = TRUE
armor_percent = list("melee" = 2000, "bullet" = 2000, "laser" = 2000, "bomb" = 2000, "energy" = 2000, "bio" = 2000, "rad" = 2000)
heat_protection = 1.0
cold_protection = 1.0
siemens_coefficient = 0.0
// Reduces resistance to "elements".
// Note that most things that do give resistance gives 100% protection,
// and due to multiplicitive stacking, this modifier won't do anything to change that.
/datum/modifier/elemental_vulnerability
name = "elemental vulnerability"
desc = "You're more vulnerable to extreme temperatures and electricity."
stacks = MODIFIER_STACK_EXTEND
heat_protection = -0.5
cold_protection = -0.5
siemens_coefficient = 1.5

View File

@@ -120,6 +120,11 @@
// People covered in blood is also bad. // People covered in blood is also bad.
// Feel free to trim down if its too expensive CPU wise. // Feel free to trim down if its too expensive CPU wise.
if(isliving(thing))
var/mob/living/L = thing
if(L.alpha <= FAKE_INVIS_ALPHA_THRESHOLD) // Can't fear something you can't (easily) see.
continue
if(istype(thing, /mob/living/carbon/human)) if(istype(thing, /mob/living/carbon/human))
var/mob/living/carbon/human/H = thing var/mob/living/carbon/human/H = thing
var/self_multiplier = H == holder ? 2 : 1 var/self_multiplier = H == holder ? 2 : 1
@@ -207,8 +212,14 @@
if(istype(thing, /obj/structure/snowman/spider)) //Snow spiders are also spooky so people can be assholes with those too. if(istype(thing, /obj/structure/snowman/spider)) //Snow spiders are also spooky so people can be assholes with those too.
fear_amount += 1 fear_amount += 1
if(istype(thing, /mob/living/simple_mob/animal/giant_spider)) // Actual giant spiders are the scariest of them all. if(isliving(thing))
var/mob/living/simple_mob/animal/giant_spider/S = thing var/mob/living/L = thing
if(L.alpha <= FAKE_INVIS_ALPHA_THRESHOLD) // Can't fear something you can't (easily) see.
continue
if(istype(L, /mob/living/simple_mob/animal/giant_spider)) // Actual giant spiders are the scariest of them all.
var/mob/living/simple_mob/animal/giant_spider/S = L
if(S.stat == DEAD) // Dead giant spiders are less scary than alive ones. if(S.stat == DEAD) // Dead giant spiders are less scary than alive ones.
fear_amount += 4 fear_amount += 4
else else
@@ -425,8 +436,12 @@
if(istype(thing, /obj/item/clothing/head/collectable/slime)) // Some hats are spooky so people can be assholes with them. if(istype(thing, /obj/item/clothing/head/collectable/slime)) // Some hats are spooky so people can be assholes with them.
fear_amount += 1 fear_amount += 1
if(istype(thing, /mob/living/simple_mob/slime)) // An actual predatory specimen! if(isliving(thing))
var/mob/living/simple_mob/slime/S = thing var/mob/living/L = thing
if(L.alpha <= FAKE_INVIS_ALPHA_THRESHOLD) // Can't fear something you can't (easily) see.
continue
if(istype(L, /mob/living/simple_mob/slime)) // An actual predatory specimen!
var/mob/living/simple_mob/slime/S = L
if(S.stat == DEAD) // Dead slimes are somewhat less spook. if(S.stat == DEAD) // Dead slimes are somewhat less spook.
fear_amount += 4 fear_amount += 4
if(istype(S, /mob/living/simple_mob/slime/xenobio)) if(istype(S, /mob/living/simple_mob/slime/xenobio))
@@ -438,8 +453,8 @@
else else
fear_amount += 10 // It's huge and feral. fear_amount += 10 // It's huge and feral.
if(istype(thing, /mob/living/carbon/human)) if(istype(L, /mob/living/carbon/human))
var/mob/living/carbon/human/S = thing var/mob/living/carbon/human/S = L
if(istype(S.species, /datum/species/skrell)) //Skrell ARE slimey. if(istype(S.species, /datum/species/skrell)) //Skrell ARE slimey.
fear_amount += 1 fear_amount += 1
if(istype(S.species, /datum/species/shapeshifter/promethean)) if(istype(S.species, /datum/species/shapeshifter/promethean))
@@ -525,8 +540,12 @@
if(istype(thing, /obj/item/weapon/gun/launcher/syringe)) if(istype(thing, /obj/item/weapon/gun/launcher/syringe))
fear_amount += 6 fear_amount += 6
if(istype(thing, /mob/living/carbon/human)) if(isliving(thing))
var/mob/living/carbon/human/H = thing var/mob/living/L = thing
if(L.alpha <= FAKE_INVIS_ALPHA_THRESHOLD) // Can't fear something you can't (easily) see.
continue
if(istype(L, /mob/living/carbon/human))
var/mob/living/carbon/human/H = L
if(H.l_hand && istype(H.l_hand, /obj/item/weapon/reagent_containers/syringe) || H.r_hand && istype(H.r_hand, /obj/item/weapon/reagent_containers/syringe)) if(H.l_hand && istype(H.l_hand, /obj/item/weapon/reagent_containers/syringe) || H.r_hand && istype(H.r_hand, /obj/item/weapon/reagent_containers/syringe))
fear_amount += 10 fear_amount += 10

View File

@@ -241,20 +241,20 @@
M.Weaken(5) M.Weaken(5)
..() ..()
/mob/living/bot/mulebot/proc/runOver(var/mob/living/carbon/human/H) /mob/living/bot/mulebot/proc/runOver(var/mob/living/M)
if(istype(H)) // No safety checks - WILL run over lying humans. Stop ERPing in the maint! if(istype(M)) // At this point, MULEBot has somehow crossed over onto your tile with you still on it. CRRRNCH.
visible_message("<span class='warning'>[src] drives over [H]!</span>") visible_message("<span class='warning'>[src] drives over [M]!</span>")
playsound(src, 'sound/effects/splat.ogg', 50, 1) playsound(src, 'sound/effects/splat.ogg', 50, 1)
var/damage = rand(5, 7) var/damage = rand(5, 7)
H.apply_damage(2 * damage, BRUTE, BP_HEAD) M.apply_damage(2 * damage, BRUTE, BP_HEAD)
H.apply_damage(2 * damage, BRUTE, BP_TORSO) M.apply_damage(2 * damage, BRUTE, BP_TORSO)
H.apply_damage(0.5 * damage, BRUTE, BP_L_LEG) M.apply_damage(0.5 * damage, BRUTE, BP_L_LEG)
H.apply_damage(0.5 * damage, BRUTE, BP_R_LEG) M.apply_damage(0.5 * damage, BRUTE, BP_R_LEG)
H.apply_damage(0.5 * damage, BRUTE, BP_L_ARM) M.apply_damage(0.5 * damage, BRUTE, BP_L_ARM)
H.apply_damage(0.5 * damage, BRUTE, BP_R_ARM) M.apply_damage(0.5 * damage, BRUTE, BP_R_ARM)
blood_splatter(src, H, 1) blood_splatter(src, M, 1)
..() ..()
/mob/living/bot/mulebot/relaymove(var/mob/user, var/direction) /mob/living/bot/mulebot/relaymove(var/mob/user, var/direction)

View File

@@ -0,0 +1,5 @@
/mob/living/bot/mulebot/handle_micro_bump_helping() // Can't drive over micros or macros regardless of intent.
return 0
/mob/living/bot/mulebot/handle_micro_bump_other() // Can't drive over micros or macros regardless of intent.
return 0

View File

@@ -253,21 +253,15 @@
return return
// called when something steps onto a human // called when something steps onto a human
// this handles mulebots and vehicles // this handles mobs on fire - mulebot and vehicle code has been relocated to /mob/living/Crossed()
// and now mobs on fire
/mob/living/carbon/human/Crossed(var/atom/movable/AM) /mob/living/carbon/human/Crossed(var/atom/movable/AM)
if(AM.is_incorporeal()) if(AM.is_incorporeal())
return return
if(istype(AM, /mob/living/bot/mulebot))
var/mob/living/bot/mulebot/MB = AM
MB.runOver(src)
if(istype(AM, /obj/vehicle))
var/obj/vehicle/V = AM
V.RunOver(src)
spread_fire(AM) spread_fire(AM)
..() // call parent because we moved behavior to parent
// Get rank from ID, ID inside PDA, PDA, ID in wallet, etc. // Get rank from ID, ID inside PDA, PDA, ID in wallet, etc.
/mob/living/carbon/human/proc/get_authentification_rank(var/if_no_id = "No id", var/if_no_job = "No job") /mob/living/carbon/human/proc/get_authentification_rank(var/if_no_id = "No id", var/if_no_job = "No job")
var/obj/item/device/pda/pda = wear_id var/obj/item/device/pda/pda = wear_id

View File

@@ -133,6 +133,12 @@ emp_act
if(istype(C) && (C.body_parts_covered & def_zone.body_part)) // Is that body part being targeted covered? if(istype(C) && (C.body_parts_covered & def_zone.body_part)) // Is that body part being targeted covered?
siemens_coefficient *= C.siemens_coefficient siemens_coefficient *= C.siemens_coefficient
// Modifiers.
for(var/thing in modifiers)
var/datum/modifier/M = thing
if(!isnull(M.siemens_coefficient))
siemens_coefficient *= M.siemens_coefficient
return siemens_coefficient return siemens_coefficient
// Similar to above but is for the mob's overall protection, being the average of all slots. // Similar to above but is for the mob's overall protection, being the average of all slots.
@@ -150,11 +156,11 @@ emp_act
if(fire_stacks < 0) // Water makes you more conductive. if(fire_stacks < 0) // Water makes you more conductive.
siemens_value *= 1.5 siemens_value *= 1.5
return (siemens_value/max(total, 1)) return (siemens_value / max(total, 1))
// Returns a number between 0 to 1, with 1 being total protection. // Returns a number between 0 to 1, with 1 being total protection.
/mob/living/carbon/human/get_shock_protection() /mob/living/carbon/human/get_shock_protection()
return between(0, 1-get_siemens_coefficient_average(), 1) return min(1 - get_siemens_coefficient_average(), 1) // Don't go above 1, but negatives are fine.
// Returns a list of clothing that is currently covering def_zone. // Returns a list of clothing that is currently covering def_zone.
/mob/living/carbon/human/proc/get_clothing_list_organ(var/obj/item/organ/external/def_zone, var/type) /mob/living/carbon/human/proc/get_clothing_list_organ(var/obj/item/organ/external/def_zone, var/type)
@@ -173,6 +179,13 @@ emp_act
var/list/protective_gear = def_zone.get_covering_clothing() var/list/protective_gear = def_zone.get_covering_clothing()
for(var/obj/item/clothing/gear in protective_gear) for(var/obj/item/clothing/gear in protective_gear)
protection += gear.armor[type] protection += gear.armor[type]
for(var/thing in modifiers)
var/datum/modifier/M = thing
var/modifier_armor = LAZYACCESS(M.armor_percent, type)
if(modifier_armor)
protection += modifier_armor
return protection return protection
/mob/living/carbon/human/proc/getsoak_organ(var/obj/item/organ/external/def_zone, var/type) /mob/living/carbon/human/proc/getsoak_organ(var/obj/item/organ/external/def_zone, var/type)
@@ -182,6 +195,13 @@ emp_act
var/list/protective_gear = def_zone.get_covering_clothing() var/list/protective_gear = def_zone.get_covering_clothing()
for(var/obj/item/clothing/gear in protective_gear) for(var/obj/item/clothing/gear in protective_gear)
soaked += gear.armorsoak[type] soaked += gear.armorsoak[type]
for(var/thing in modifiers)
var/datum/modifier/M = thing
var/modifier_armor = LAZYACCESS(M.armor_flat, type)
if(modifier_armor)
soaked += modifier_armor
return soaked return soaked
// Checked in borer code // Checked in borer code

View File

@@ -836,7 +836,19 @@
/mob/living/carbon/human/get_heat_protection(temperature) //Temperature is the temperature you're being exposed to. /mob/living/carbon/human/get_heat_protection(temperature) //Temperature is the temperature you're being exposed to.
var/thermal_protection_flags = get_heat_protection_flags(temperature) var/thermal_protection_flags = get_heat_protection_flags(temperature)
return get_thermal_protection(thermal_protection_flags)
. = get_thermal_protection(thermal_protection_flags)
. = 1 - . // Invert from 1 = immunity to 0 = immunity.
// Doing it this way makes multiplicative stacking not get out of hand, so two modifiers that give 0.5 protection will be combined to 0.75 in the end.
for(var/thing in modifiers)
var/datum/modifier/M = thing
if(!isnull(M.heat_protection))
. *= 1 - M.heat_protection
// Code that calls this expects 1 = immunity so we need to invert again.
. = 1 - .
. = min(., 1.0)
/mob/living/carbon/human/get_cold_protection(temperature) /mob/living/carbon/human/get_cold_protection(temperature)
if(COLD_RESISTANCE in mutations) if(COLD_RESISTANCE in mutations)
@@ -844,7 +856,20 @@
temperature = max(temperature, 2.7) //There is an occasional bug where the temperature is miscalculated in ares with a small amount of gas on them, so this is necessary to ensure that that bug does not affect this calculation. Space's temperature is 2.7K and most suits that are intended to protect against any cold, protect down to 2.0K. temperature = max(temperature, 2.7) //There is an occasional bug where the temperature is miscalculated in ares with a small amount of gas on them, so this is necessary to ensure that that bug does not affect this calculation. Space's temperature is 2.7K and most suits that are intended to protect against any cold, protect down to 2.0K.
var/thermal_protection_flags = get_cold_protection_flags(temperature) var/thermal_protection_flags = get_cold_protection_flags(temperature)
return get_thermal_protection(thermal_protection_flags)
. = get_thermal_protection(thermal_protection_flags)
. = 1 - . // Invert from 1 = immunity to 0 = immunity.
// Doing it this way makes multiplicative stacking not get out of hand, so two modifiers that give 0.5 protection will be combined to 0.75 in the end.
for(var/thing in modifiers)
var/datum/modifier/M = thing
if(!isnull(M.cold_protection))
// Invert the modifier values so they align with the current working value.
. *= 1 - M.cold_protection
// Code that calls this expects 1 = immunity so we need to invert again.
. = 1 - .
. = min(., 1.0)
/mob/living/carbon/human/proc/get_thermal_protection(var/flags) /mob/living/carbon/human/proc/get_thermal_protection(var/flags)
.=0 .=0

View File

@@ -89,8 +89,16 @@
heat_discomfort_strings = list( heat_discomfort_strings = list(
"Your feathers prickle in the heat.", "Your feathers prickle in the heat.",
"You feel uncomfortably warm.", "You feel uncomfortably warm.",
"Your hands and feet feel hot as your body tries to regulate heat",
) )
cold_discomfort_level = 180 cold_discomfort_level = 180
cold_discomfort_strings = list(
"You feel a bit chilly.",
"You fluff up your feathers against the cold.",
"You move your arms closer to your body to shield yourself from the cold.",
"You press your ears against your head to conserve heat",
"You start to feel the cold on your skin",
)
minimum_breath_pressure = 12 //Smaller, so needs less air minimum_breath_pressure = 12 //Smaller, so needs less air

View File

@@ -146,6 +146,15 @@ YW change end */
H.verbs |= /mob/living/carbon/human/proc/succubus_drain_finalize H.verbs |= /mob/living/carbon/human/proc/succubus_drain_finalize
H.verbs |= /mob/living/carbon/human/proc/succubus_drain_lethal H.verbs |= /mob/living/carbon/human/proc/succubus_drain_lethal
/datum/trait/feeder
name = "Feeder"
desc = "Allows you to feed your prey using your own body."
cost = 0
/datum/trait/feeder/apply(var/datum/species/S,var/mob/living/carbon/human/H)
..(S,H)
H.verbs |= /mob/living/carbon/human/proc/slime_feed
/datum/trait/hard_vore /datum/trait/hard_vore
name = "Brutal Predation" name = "Brutal Predation"
desc = "Allows you to tear off limbs & tear out internal organs." desc = "Allows you to tear off limbs & tear out internal organs."

View File

@@ -10,6 +10,11 @@
if(istype(nest, /obj/structure/blob/factory)) if(istype(nest, /obj/structure/blob/factory))
var/obj/structure/blob/factory/F = nest var/obj/structure/blob/factory/F = nest
F.spores -= src F.spores -= src
//VOREStation Edit Start
if(istype(nest, /obj/structure/mob_spawner))
var/obj/structure/mob_spawner/S = nest
S.get_death_report(src)
//VOREStation Edit End
nest = null nest = null
for(var/s in owned_soul_links) for(var/s in owned_soul_links)

View File

@@ -96,7 +96,7 @@
if(world.time >= (lastareachange + 30 SECONDS)) // Every 30 seconds, we're going to run a 35% chance to play ambience. if(world.time >= (lastareachange + 30 SECONDS)) // Every 30 seconds, we're going to run a 35% chance to play ambience.
var/area/A = get_area(src) var/area/A = get_area(src)
if(A) if(A)
A.play_ambience(src) A.play_ambience(src, initial = FALSE)
/mob/living/proc/update_pulling() /mob/living/proc/update_pulling()
if(pulling) if(pulling)

View File

@@ -244,6 +244,19 @@ default behaviour is:
return TRUE return TRUE
return ..() return ..()
// Called when something steps onto us. This allows for mulebots and vehicles to run things over. <3
/mob/living/Crossed(var/atom/movable/AM) // Transplanting this from /mob/living/carbon/human/Crossed()
if(AM == src || AM.is_incorporeal()) // We're not going to run over ourselves or ghosts
return
if(istype(AM, /mob/living/bot/mulebot))
var/mob/living/bot/mulebot/MB = AM
MB.runOver(src)
if(istype(AM, /obj/vehicle))
var/obj/vehicle/V = AM
V.RunOver(src)
/mob/living/verb/succumb() /mob/living/verb/succumb()
set hidden = 1 set hidden = 1
if ((src.health < 0 && src.health > (5-src.getMaxHealth()))) // Health below Zero but above 5-away-from-death, as before, but variable if ((src.health < 0 && src.health > (5-src.getMaxHealth()))) // Health below Zero but above 5-away-from-death, as before, but variable

View File

@@ -3,7 +3,6 @@
/mob/living /mob/living
var/ooc_notes = null var/ooc_notes = null
var/obj/structure/mob_spawner/source_spawner = null
appearance_flags = TILE_BOUND|PIXEL_SCALE|KEEP_TOGETHER appearance_flags = TILE_BOUND|PIXEL_SCALE|KEEP_TOGETHER
var/hunger_rate = DEFAULT_HUNGER_FACTOR var/hunger_rate = DEFAULT_HUNGER_FACTOR

View File

@@ -40,6 +40,7 @@
"Fennec" = "pai-fen", "Fennec" = "pai-fen",
"Type Zero" = "pai-typezero", "Type Zero" = "pai-typezero",
"Raccoon" = "pai-raccoon", "Raccoon" = "pai-raccoon",
"Raptor" = "pai-raptor",
"Rat" = "rat", "Rat" = "rat",
"Panther" = "panther" "Panther" = "panther"
//VOREStation Addition End //VOREStation Addition End

View File

@@ -34,6 +34,8 @@
scan_type = "robot" scan_type = "robot"
else if(istype(M, /mob/living/carbon/human)) else if(istype(M, /mob/living/carbon/human))
scan_type = "prosthetics" scan_type = "prosthetics"
else if(istype(M, /obj/mecha))
scan_type = "mecha"
else else
to_chat(user, "<font color='red'>You can't analyze non-robotic things!</font>") to_chat(user, "<font color='red'>You can't analyze non-robotic things!</font>")
return return
@@ -95,5 +97,37 @@
if(!organ_found) if(!organ_found)
to_chat(user, "No prosthetics located.") to_chat(user, "No prosthetics located.")
if("mecha")
var/obj/mecha/Mecha = M
var/integrity = Mecha.health/initial(Mecha.health)*100
var/cell_charge = Mecha.get_charge()
var/tank_pressure = Mecha.internal_tank ? round(Mecha.internal_tank.return_pressure(),0.01) : "None"
var/tank_temperature = Mecha.internal_tank ? Mecha.internal_tank.return_temperature() : "Unknown"
var/cabin_pressure = round(Mecha.return_pressure(),0.01)
var/output = {"<span class='notice'>Analyzing Results for \the [Mecha]:</span><br>
<b>Chassis Integrity: </b> [integrity]%<br>
<b>Powercell charge: </b>[isnull(cell_charge)?"No powercell installed":"[Mecha.cell.percent()]%"]<br>
<b>Air source: </b>[Mecha.use_internal_tank?"Internal Airtank":"Environment"]<br>
<b>Airtank pressure: </b>[tank_pressure]kPa<br>
<b>Airtank temperature: </b>[tank_temperature]K|[tank_temperature - T0C]&deg;C<br>
<b>Cabin pressure: </b>[cabin_pressure>WARNING_HIGH_PRESSURE ? "<font color='red'>[cabin_pressure]</font>": cabin_pressure]kPa<br>
<b>Cabin temperature: </b> [Mecha.return_temperature()]K|[Mecha.return_temperature() - T0C]&deg;C<br>
<b>DNA Lock: </b> [Mecha.dna?"Mecha.dna":"Not Found"]<br>
"}
to_chat(user, output)
to_chat(user, "<hr>")
to_chat(user, "<span class='notice'>Internal Diagnostics:</span>")
for(var/slot in Mecha.internal_components)
var/obj/item/mecha_parts/component/MC = Mecha.internal_components[slot]
to_chat(user, "[MC?"[slot]: [MC] <span class='notice'>[round((MC.integrity / MC.max_integrity) * 100, 0.1)]%</span> integrity. [MC.get_efficiency() * 100] Operational capacity.":"<span class='warning'>[slot]: Component Not Found</span>"]")
to_chat(user, "<hr>")
to_chat(user, "<span class='notice'>General Statistics:</span>")
to_chat(user, "<span class='notice'>Movement Weight: [Mecha.get_step_delay()]</span><br>")
src.add_fingerprint(user) src.add_fingerprint(user)
return return

View File

@@ -30,6 +30,7 @@
var/synced = FALSE var/synced = FALSE
var/startdrain = 500 var/startdrain = 500
var/max_item_count = 1 var/max_item_count = 1
var/upgraded_capacity = FALSE
var/gulpsound = 'sound/vore/gulp.ogg' var/gulpsound = 'sound/vore/gulp.ogg'
var/datum/matter_synth/metal = null var/datum/matter_synth/metal = null
var/datum/matter_synth/glass = null var/datum/matter_synth/glass = null

View File

@@ -140,7 +140,18 @@
// Cold stuff. // Cold stuff.
/mob/living/simple_mob/get_cold_protection() /mob/living/simple_mob/get_cold_protection()
return cold_resist . = cold_resist
. = 1 - . // Invert from 1 = immunity to 0 = immunity.
// Doing it this way makes multiplicative stacking not get out of hand, so two modifiers that give 0.5 protection will be combined to 0.75 in the end.
for(var/thing in modifiers)
var/datum/modifier/M = thing
if(!isnull(M.cold_protection))
. *= 1 - M.cold_protection
// Code that calls this expects 1 = immunity so we need to invert again.
. = 1 - .
. = min(., 1.0)
// Fire stuff. Not really exciting at the moment. // Fire stuff. Not really exciting at the moment.
@@ -154,7 +165,18 @@
return return
/mob/living/simple_mob/get_heat_protection() /mob/living/simple_mob/get_heat_protection()
return heat_resist . = heat_resist
. = 1 - . // Invert from 1 = immunity to 0 = immunity.
// Doing it this way makes multiplicative stacking not get out of hand, so two modifiers that give 0.5 protection will be combined to 0.75 in the end.
for(var/thing in modifiers)
var/datum/modifier/M = thing
if(!isnull(M.heat_protection))
. *= 1 - M.heat_protection
// Code that calls this expects 1 = immunity so we need to invert again.
. = 1 - .
. = min(., 1.0)
// Electricity // Electricity
/mob/living/simple_mob/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0, var/def_zone = null) /mob/living/simple_mob/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0, var/def_zone = null)
@@ -170,7 +192,18 @@
s.start() s.start()
/mob/living/simple_mob/get_shock_protection() /mob/living/simple_mob/get_shock_protection()
return shock_resist . = shock_resist
. = 1 - . // Invert from 1 = immunity to 0 = immunity.
// Doing it this way makes multiplicative stacking not get out of hand, so two modifiers that give 0.5 protection will be combined to 0.75 in the end.
for(var/thing in modifiers)
var/datum/modifier/M = thing
if(!isnull(M.siemens_coefficient))
. *= M.siemens_coefficient
// Code that calls this expects 1 = immunity so we need to invert again.
. = 1 - .
. = min(., 1.0)
// Shot with taser/stunvolver // Shot with taser/stunvolver
/mob/living/simple_mob/stun_effect_act(var/stun_amount, var/agony_amount, var/def_zone, var/used_weapon=null) /mob/living/simple_mob/stun_effect_act(var/stun_amount, var/agony_amount, var/def_zone, var/used_weapon=null)
@@ -218,16 +251,28 @@
// Armor // Armor
/mob/living/simple_mob/getarmor(def_zone, attack_flag) /mob/living/simple_mob/getarmor(def_zone, attack_flag)
var/armorval = armor[attack_flag] var/armorval = armor[attack_flag]
if(!armorval) if(isnull(armorval))
return 0 armorval = 0
else
for(var/thing in modifiers)
var/datum/modifier/M = thing
var/modifier_armor = LAZYACCESS(M.armor_percent, attack_flag)
if(modifier_armor)
armorval += modifier_armor
return armorval return armorval
/mob/living/simple_mob/getsoak(def_zone, attack_flag) /mob/living/simple_mob/getsoak(def_zone, attack_flag)
var/armorval = armor_soak[attack_flag] var/armorval = armor_soak[attack_flag]
if(!armorval) if(isnull(armorval))
return 0 armorval = 0
else
for(var/thing in modifiers)
var/datum/modifier/M = thing
var/modifier_armor = LAZYACCESS(M.armor_flat, attack_flag)
if(modifier_armor)
armorval += modifier_armor
return armorval return armorval
// Lightning // Lightning

View File

@@ -10,6 +10,8 @@
maxHealth = 5 maxHealth = 5
health = 5 health = 5
melee_damage_lower = 1
melee_damage_upper = 3
movement_cooldown = 1.5 movement_cooldown = 1.5

View File

@@ -238,3 +238,13 @@
real_name = "Spice" //Intended to hold the name without altering it. real_name = "Spice" //Intended to hold the name without altering it.
gender = FEMALE gender = FEMALE
desc = "It's a tamaskan, the name Spice can be found on its collar." desc = "It's a tamaskan, the name Spice can be found on its collar."
// Brittany Spaniel
/mob/living/simple_mob/animal/passive/dog/brittany
name = "brittany"
real_name = "brittany"
desc = "It's a brittany spaniel."
icon_state = "brittany"
icon_living = "brittany"
icon_dead = "brittany_dead"

View File

@@ -169,3 +169,4 @@
holder.face_atom(A) holder.face_atom(A)
F.energy = max(0, F.energy - 1) // The AI will eventually flee. F.energy = max(0, F.energy - 1) // The AI will eventually flee.

View File

@@ -0,0 +1,68 @@
// Complete chumps but a little bit hardier than mice.
/datum/category_item/catalogue/fauna/hare
name = "Sivian Fauna - Ice Hare"
desc = "Classification: S Lepus petropellis\
<br><br>\
Hard-skinned, horned herbivores common on the glacial regions of Sif. \
The Ice Hare lives in colonies of up to thirty individuals dug beneath thick ice sheets for protection from many burrowing predators. \
Their diet consists of mostly moss and lichens, though this is supplemented with the consumption of hard mineral pebbles, which it swallows whole, \
which form the small, hard, 'ice-like' scales of the animal. \
The Ice Hare is almost completely harmless to sapients, with relatively blunt claws and a weak jaw. Its main forms of self-defense are its speed, \
and two sharp head spikes whose 'ear-like' appearance gave the species its common name."
value = CATALOGUER_REWARD_EASY
/mob/living/simple_mob/animal/passive/hare
name = "ice hare"
real_name = "ice hare"
desc = "A small horned herbivore with a tough 'ice-like' hide."
tt_desc = "S Lepus petropellis" //Sivian hare rockskin
catalogue_data = list(/datum/category_item/catalogue/fauna/hare)
icon_state = "hare"
icon_living = "hare"
icon_dead = "hare_dead"
icon_rest = "hare_rest"
maxHealth = 20
health = 20
armor = list(
"melee" = 30,
"bullet" = 5,
"laser" = 5,
"energy" = 0,
"bomb" = 10,
"bio" = 0,
"rad" = 0
)
armor_soak = list(
"melee" = 5,
"bullet" = 0,
"laser" = 0,
"energy" = 0,
"bomb" = 0,
"bio" = 0,
"rad" = 0
)
movement_cooldown = 2
mob_size = MOB_SMALL
pass_flags = PASSTABLE
layer = MOB_LAYER
density = 0
response_help = "pets"
response_disarm = "nudges"
response_harm = "kicks"
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
say_list_type = /datum/say_list/hare
/datum/say_list/hare
speak = list("Snrf...","Crk!")
emote_hear = list("crackles","sniffles")
emote_see = list("stomps the ground", "sniffs the air", "chews on something")

Some files were not shown because too many files have changed in this diff Show More