mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-07-13 08:04:22 +01:00
Merge branch 'master' into upstream-merge-5335
This commit is contained in:
@@ -659,11 +659,13 @@ var/list/admin_verbs_event_manager = list(
|
||||
set desc = "Cause an explosion of varying strength at your location."
|
||||
|
||||
var/turf/epicenter = mob.loc
|
||||
var/list/choices = list("Small Bomb", "Medium Bomb", "Big Bomb", "Custom Bomb")
|
||||
var/list/choices = list("Small Bomb", "Medium Bomb", "Big Bomb", "Custom Bomb", "Cancel")
|
||||
var/choice = input("What size explosion would you like to produce?") in choices
|
||||
switch(choice)
|
||||
if(null)
|
||||
return 0
|
||||
if("Cancel")
|
||||
return 0
|
||||
if("Small Bomb")
|
||||
explosion(epicenter, 1, 2, 3, 3)
|
||||
if("Medium Bomb")
|
||||
|
||||
@@ -637,7 +637,7 @@
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
var/datum/planet/planet = input(usr, "Which planet do you want to modify the weather on?", "Change Weather") in planet_controller.planets
|
||||
var/datum/planet/planet = input(usr, "Which planet do you want to modify the weather on?", "Change Weather") in SSplanets.planets
|
||||
var/datum/weather/new_weather = input(usr, "What weather do you want to change to?", "Change Weather") as null|anything in planet.weather_holder.allowed_weather_types
|
||||
if(new_weather)
|
||||
planet.weather_holder.change_weather(new_weather)
|
||||
@@ -653,7 +653,7 @@
|
||||
if(!check_rights(R_DEBUG))
|
||||
return
|
||||
|
||||
var/datum/planet/planet = input(usr, "Which planet do you want to modify time on?", "Change Time") in planet_controller.planets
|
||||
var/datum/planet/planet = input(usr, "Which planet do you want to modify time on?", "Change Time") in SSplanets.planets
|
||||
|
||||
var/datum/time/current_time_datum = planet.current_time
|
||||
var/new_hour = input(usr, "What hour do you want to change to?", "Change Time", text2num(current_time_datum.show_time("hh"))) as null|num
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
//Minimum limit is 18
|
||||
/datum/category_item/player_setup_item/get_min_age()
|
||||
var/min_age = 18
|
||||
var/datum/species/S = all_species[pref.species ? pref.species : "Human"]
|
||||
if(!is_FBP() && S.min_age > 18)
|
||||
min_age = S.min_age
|
||||
return min_age
|
||||
@@ -51,17 +51,6 @@
|
||||
kill()
|
||||
return
|
||||
|
||||
/** Checks if any living humans are in a given area! */
|
||||
/datum/event/atmos_leak/proc/is_area_occupied(var/area/myarea)
|
||||
// Testing suggests looping over human_mob_list is quicker than looping over area contents
|
||||
for(var/mob/living/carbon/human/H in human_mob_list)
|
||||
if(H.stat >= DEAD) //Conditions for exclusion here, like if disconnected people start blocking it.
|
||||
continue
|
||||
var/area/A = get_area(H)
|
||||
if(A == myarea) //The loc of a turf is the area it is in.
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/event/atmos_leak/announce()
|
||||
command_announcement.Announce("Warning, hazardous [gas_data.name[gas_type]] gas leak detected in \the [target_area], evacuate the area and contain the damage!", "Hazard Alert")
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
/datum/event/escaped_slimes/start()
|
||||
var/list/vents = list()
|
||||
for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in machines)
|
||||
if(temp_vent.network && temp_vent.loc.z in using_map.station_levels) //borrowed from spiders event, but it works. Distribute the slimes only in rooms with vents
|
||||
if(temp_vent.network && temp_vent.loc.z in using_map.station_levels && !is_area_occupied(temp_vent.loc.loc)) //borrowed from spiders event, but it works. Distribute the slimes only in rooms with vents
|
||||
vents += temp_vent
|
||||
|
||||
while((spawncount > 0) && vents.len)
|
||||
|
||||
@@ -6,9 +6,8 @@
|
||||
endWhen = rand(15, 60)
|
||||
// Setup which levels we will disrupt gravit on.
|
||||
zLevels = using_map.station_levels.Copy()
|
||||
if (planet_controller)
|
||||
for(var/datum/planet/P in planet_controller.planets)
|
||||
zLevels -= P.expected_z_levels
|
||||
for(var/datum/planet/P in SSplanets.planets)
|
||||
zLevels -= P.expected_z_levels
|
||||
|
||||
/datum/event/gravity/announce()
|
||||
command_announcement.Announce("Feedback surge detected in mass-distributions systems. Artificial gravity has been disabled whilst the system \
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
new /obj/structure/meteorite(current)
|
||||
|
||||
var/datum/planet/impacted
|
||||
for(var/datum/planet/P in planet_controller.planets)
|
||||
for(var/datum/planet/P in SSplanets.planets)
|
||||
if(current.z in P.expected_z_levels)
|
||||
impacted = P
|
||||
break
|
||||
|
||||
@@ -25,3 +25,7 @@
|
||||
|
||||
/mob/living/carbon/human/protean/New(var/new_loc)
|
||||
..(new_loc, "Protean")
|
||||
|
||||
|
||||
/mob/living/carbon/human/alraune/New(var/new_loc)
|
||||
..(new_loc, "Alraune")
|
||||
|
||||
@@ -0,0 +1,336 @@
|
||||
/datum/species/alraune
|
||||
name = SPECIES_ALRAUNE
|
||||
name_plural = "Alraunes"
|
||||
unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/punch, /datum/unarmed_attack/bite)
|
||||
num_alternate_languages = 2
|
||||
language = LANGUAGE_ROOTLOCAL
|
||||
slowdown = 1 //slow, they're plants. Not as slow as full diona.
|
||||
total_health = 100 //standard
|
||||
brute_mod = 1 //nothing special
|
||||
burn_mod = 1.5 //plants don't like fire
|
||||
metabolic_rate = 0.75 // slow metabolism
|
||||
item_slowdown_mod = 0.25 //while they start slow, they don't get much slower
|
||||
bloodloss_rate = 0.1 //While they do bleed, they bleed out VERY slowly
|
||||
min_age = 18
|
||||
max_age = 250
|
||||
health_hud_intensity = 1.5
|
||||
|
||||
body_temperature = T20C
|
||||
breath_type = "carbon_dioxide"
|
||||
poison_type = "phoron"
|
||||
exhale_type = "oxygen"
|
||||
|
||||
// Heat and cold resistances are 20 degrees broader on the level 1 range, level 2 is default, level 3 is much weaker, halfway between L2 and normal L3.
|
||||
// Essentially, they can tolerate a broader range of comfortable temperatures, but suffer more at extremes.
|
||||
cold_level_1 = 240 //Default 260 - Lower is better
|
||||
cold_level_2 = 200 //Default 200
|
||||
cold_level_3 = 160 //Default 120
|
||||
cold_discomfort_level = 260 //they start feeling uncomfortable around the point where humans take damage
|
||||
|
||||
heat_level_1 = 380 //Default 360 - Higher is better
|
||||
heat_level_2 = 400 //Default 400
|
||||
heat_level_3 = 700 //Default 1000
|
||||
heat_discomfort_level = 360
|
||||
|
||||
breath_cold_level_1 = 240 //They don't have lungs, they breathe through their skin
|
||||
breath_cold_level_2 = 180 //sadly for them, their breath tolerance is no better than anyone else's.
|
||||
breath_cold_level_3 = 140 //mainly 'cause breath tolerance is more generous than body temp tolerance.
|
||||
|
||||
breath_heat_level_1 = 400 //slightly better heat tolerance in air though. Slightly.
|
||||
breath_heat_level_2 = 450
|
||||
breath_heat_level_3 = 800 //lower incineration threshold though
|
||||
|
||||
spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED // whitelist only while WIP
|
||||
flags = NO_SCAN | IS_PLANT | NO_MINOR_CUT
|
||||
appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR
|
||||
|
||||
inherent_verbs = list(
|
||||
/mob/living/carbon/human/proc/succubus_drain,
|
||||
/mob/living/carbon/human/proc/succubus_drain_finalize,
|
||||
/mob/living/carbon/human/proc/succubus_drain_lethal,
|
||||
/mob/living/carbon/human/proc/bloodsuck) //Give them the voremodes related to wrapping people in vines and sapping their fluids
|
||||
|
||||
color_mult = 1
|
||||
icobase = 'icons/mob/human_races/r_human_vr.dmi'
|
||||
deform = 'icons/mob/human_races/r_def_human_vr.dmi'
|
||||
flesh_color = "#9ee02c"
|
||||
blood_color = "#edf4d0" //sap!
|
||||
base_color = "#1a5600"
|
||||
|
||||
blurb = "Alraunes are a rare sight in space. Their bodies are reminiscent of that of plants, and yet they share many\
|
||||
traits with other humanoid beings.\
|
||||
\
|
||||
Most Alraunes are not interested in traversing space, their heavy preference for natural environments and general\
|
||||
disinterest in things outside it keeps them as a species at a rather primal stage.\
|
||||
\
|
||||
However, after their discovery by the angels of Sanctum, many alraunes succumbed to their curiosity, and took the offer\
|
||||
to learn of the world and venture out, whether it's to Sanctum, or elsewhere in the galaxy."
|
||||
|
||||
has_limbs = list(
|
||||
BP_TORSO = list("path" = /obj/item/organ/external/chest),
|
||||
BP_GROIN = list("path" = /obj/item/organ/external/groin),
|
||||
BP_HEAD = list("path" = /obj/item/organ/external/head),
|
||||
BP_L_ARM = list("path" = /obj/item/organ/external/arm),
|
||||
BP_R_ARM = list("path" = /obj/item/organ/external/arm/right),
|
||||
BP_L_LEG = list("path" = /obj/item/organ/external/leg),
|
||||
BP_R_LEG = list("path" = /obj/item/organ/external/leg/right),
|
||||
BP_L_HAND = list("path" = /obj/item/organ/external/hand),
|
||||
BP_R_HAND = list("path" = /obj/item/organ/external/hand/right),
|
||||
BP_L_FOOT = list("path" = /obj/item/organ/external/foot),
|
||||
BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right)
|
||||
)
|
||||
|
||||
// limited organs, 'cause they're simple
|
||||
has_organ = list(
|
||||
O_LIVER = /obj/item/organ/internal/liver/alraune,
|
||||
O_KIDNEYS = /obj/item/organ/internal/kidneys/alraune,
|
||||
O_BRAIN = /obj/item/organ/internal/brain/alraune,
|
||||
O_EYES = /obj/item/organ/internal/eyes/alraune,
|
||||
)
|
||||
|
||||
/datum/species/alraune/can_breathe_water()
|
||||
return TRUE //eh, why not? Aquatic plants are a thing.
|
||||
|
||||
|
||||
/datum/species/alraune/handle_environment_special(var/mob/living/carbon/human/H)
|
||||
if(H.inStasisNow()) // if they're in stasis, they won't need this stuff.
|
||||
return
|
||||
|
||||
//setting these here 'cause ugh the defines for life are in the wrong place to compile properly
|
||||
//set them back to HUMAN_MAX_OXYLOSS if we move the life defines to the defines folder at any point
|
||||
var/ALRAUNE_MAX_OXYLOSS = 1 //Defines how much oxyloss humans can get per tick. A tile with no air at all (such as space) applies this value, otherwise it's a percentage of it.
|
||||
var/ALRAUNE_CRIT_MAX_OXYLOSS = ( 2.0 / 6) //The amount of damage you'll get when in critical condition. We want this to be a 5 minute deal = 300s. There are 50HP to get through, so (1/6)*last_tick_duration per second. Breaths however only happen every 4 ticks. last_tick_duration = ~2.0 on average
|
||||
|
||||
//They don't have lungs so breathe() will just return. Instead, they breathe through their skin.
|
||||
//This is mostly normal breath code with some tweaks that apply to their particular biology.
|
||||
|
||||
var/datum/gas_mixture/breath = null
|
||||
var/fullysealed = FALSE //if they're wearing a fully sealed suit, their internals take priority.
|
||||
var/environmentalair = FALSE //if no sealed suit, internals take priority in low pressure environements
|
||||
|
||||
if(H.wear_suit && (H.wear_suit.item_flags & STOPPRESSUREDAMAGE) && H.head && (H.head.item_flags & STOPPRESSUREDAMAGE))
|
||||
fullysealed = TRUE
|
||||
else // find out if local gas mixture is enough to override use of internals
|
||||
var/datum/gas_mixture/environment = H.loc.return_air()
|
||||
var/envpressure = environment.return_pressure()
|
||||
if(envpressure >= hazard_low_pressure)
|
||||
environmentalair = TRUE
|
||||
|
||||
if(fullysealed || !environmentalair)
|
||||
breath = H.get_breath_from_internal()
|
||||
|
||||
if(!breath) //No breath from internals so let's try to get air from our location
|
||||
// cut-down version of get_breath_from_environment - notably, gas masks provide no benefit
|
||||
var/datum/gas_mixture/environment2
|
||||
if(H.loc)
|
||||
environment2 = H.loc.return_air_for_internal_lifeform(H)
|
||||
|
||||
if(environment2)
|
||||
breath = environment2.remove_volume(BREATH_VOLUME)
|
||||
H.handle_chemical_smoke(environment2) //handle chemical smoke while we're at it
|
||||
|
||||
// NOW a crude copypasta of handle_breath. Leaving some things out that don't apply to plants.
|
||||
if(H.does_not_breathe)
|
||||
H.failed_last_breath = 0
|
||||
H.adjustOxyLoss(-5)
|
||||
return // if somehow they don't breathe, abort breathing.
|
||||
|
||||
if(!breath || (breath.total_moles == 0))
|
||||
H.failed_last_breath = 1
|
||||
if(H.health > config.health_threshold_crit)
|
||||
H.adjustOxyLoss(ALRAUNE_MAX_OXYLOSS)
|
||||
else
|
||||
H.adjustOxyLoss(ALRAUNE_CRIT_MAX_OXYLOSS)
|
||||
|
||||
H.oxygen_alert = max(H.oxygen_alert, 1)
|
||||
|
||||
return // skip air processing if there's no air
|
||||
|
||||
// now into the good stuff
|
||||
|
||||
//var/safe_pressure_min = species.minimum_breath_pressure // Minimum safe partial pressure of breathable gas in kPa
|
||||
//just replace safe_pressure_min with minimum_breath_pressure, no need to declare a new var
|
||||
|
||||
var/safe_exhaled_max = 10
|
||||
var/safe_toxins_max = 0.2
|
||||
var/SA_para_min = 1
|
||||
var/SA_sleep_min = 5
|
||||
var/inhaled_gas_used = 0
|
||||
|
||||
var/breath_pressure = (breath.total_moles*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME
|
||||
|
||||
var/inhaling
|
||||
var/poison
|
||||
var/exhaling
|
||||
|
||||
var/failed_inhale = 0
|
||||
var/failed_exhale = 0
|
||||
|
||||
inhaling = breath.gas[breath_type]
|
||||
poison = breath.gas[poison_type]
|
||||
exhaling = breath.gas[exhale_type]
|
||||
|
||||
var/inhale_pp = (inhaling/breath.total_moles)*breath_pressure
|
||||
var/toxins_pp = (poison/breath.total_moles)*breath_pressure
|
||||
var/exhaled_pp = (exhaling/breath.total_moles)*breath_pressure
|
||||
|
||||
// Not enough to breathe
|
||||
if((inhale_pp + exhaled_pp) < minimum_breath_pressure) //they can breathe either oxygen OR CO2
|
||||
if(prob(20))
|
||||
spawn(0) H.emote("gasp")
|
||||
|
||||
var/ratio = (inhale_pp + exhaled_pp)/minimum_breath_pressure
|
||||
// Don't fuck them up too fast (space only does HUMAN_MAX_OXYLOSS (1) after all!)
|
||||
H.adjustOxyLoss(max(ALRAUNE_MAX_OXYLOSS*(1-ratio), 0))
|
||||
failed_inhale = 1
|
||||
|
||||
H.oxygen_alert = max(H.oxygen_alert, 1)
|
||||
else
|
||||
// We're in safe limits
|
||||
H.oxygen_alert = 0
|
||||
|
||||
inhaled_gas_used = inhaling/6
|
||||
breath.adjust_gas(breath_type, -inhaled_gas_used, update = 0) //update afterwards
|
||||
breath.adjust_gas_temp(exhale_type, inhaled_gas_used, H.bodytemperature, update = 0) //update afterwards
|
||||
|
||||
//Now we handle CO2.
|
||||
if(inhale_pp > safe_exhaled_max * 0.7) // For a human, this would be too much exhaled gas in the air. But plants don't care.
|
||||
H.co2_alert = 1 // Give them the alert on the HUD. They'll be aware when the good stuff is present.
|
||||
|
||||
else
|
||||
H.co2_alert = 0
|
||||
|
||||
//do the CO2 buff stuff here
|
||||
|
||||
var/co2buff = 0
|
||||
if(inhaling)
|
||||
co2buff = (Clamp(inhale_pp, 0, minimum_breath_pressure))/minimum_breath_pressure //returns a value between 0 and 1.
|
||||
|
||||
var/light_amount = fullysealed ? H.getlightlevel() : H.getlightlevel()/5 // if they're covered, they're not going to get much light on them.
|
||||
|
||||
if(co2buff && !H.toxloss && light_amount >= 0.1) //if there's enough light and CO2 and you're not poisoned, heal. Note if you're wearing a sealed suit your heal rate will suck.
|
||||
H.adjustBruteLoss(-(light_amount * co2buff * 2)) //at a full partial pressure of CO2 and full light, you'll only heal half as fast as diona.
|
||||
H.adjustFireLoss(-(light_amount * co2buff)) //this won't let you tank environmental damage from fire. MAYBE cold until your body temp drops.
|
||||
|
||||
if(H.nutrition < (200 + 400*co2buff)) //if no CO2, a fully lit tile gives them 1/tick up to 200. With CO2, potentially up to 600.
|
||||
H.nutrition += (light_amount*(1+co2buff*5))
|
||||
|
||||
// Too much poison in the air.
|
||||
if(toxins_pp > safe_toxins_max)
|
||||
var/ratio = (poison/safe_toxins_max) * 10
|
||||
if(H.reagents)
|
||||
H.reagents.add_reagent("toxin", Clamp(ratio, MIN_TOXIN_DAMAGE, MAX_TOXIN_DAMAGE))
|
||||
breath.adjust_gas(poison_type, -poison/6, update = 0) //update after
|
||||
H.phoron_alert = max(H.phoron_alert, 1)
|
||||
else
|
||||
H.phoron_alert = 0
|
||||
|
||||
// If there's some other shit in the air lets deal with it here.
|
||||
if(breath.gas["sleeping_agent"])
|
||||
var/SA_pp = (breath.gas["sleeping_agent"] / breath.total_moles) * breath_pressure
|
||||
|
||||
// Enough to make us paralysed for a bit
|
||||
if(SA_pp > SA_para_min)
|
||||
|
||||
// 3 gives them one second to wake up and run away a bit!
|
||||
H.Paralyse(3)
|
||||
|
||||
// Enough to make us sleep as well
|
||||
if(SA_pp > SA_sleep_min)
|
||||
H.Sleeping(5)
|
||||
|
||||
// There is sleeping gas in their lungs, but only a little, so give them a bit of a warning
|
||||
else if(SA_pp > 0.15)
|
||||
if(prob(20))
|
||||
spawn(0) H.emote(pick("giggle", "laugh"))
|
||||
breath.adjust_gas("sleeping_agent", -breath.gas["sleeping_agent"]/6, update = 0) //update after
|
||||
|
||||
// Were we able to breathe?
|
||||
if (failed_inhale || failed_exhale)
|
||||
H.failed_last_breath = 1
|
||||
else
|
||||
H.failed_last_breath = 0
|
||||
H.adjustOxyLoss(-5)
|
||||
|
||||
|
||||
// Hot air hurts :(
|
||||
if((breath.temperature < breath_cold_level_1 || breath.temperature > breath_heat_level_1) && !(COLD_RESISTANCE in H.mutations))
|
||||
|
||||
if(breath.temperature <= breath_cold_level_1)
|
||||
if(prob(20))
|
||||
to_chat(H, "<span class='danger'>You feel icicles forming on your skin!</span>")
|
||||
else if(breath.temperature >= breath_heat_level_1)
|
||||
if(prob(20))
|
||||
to_chat(H, "<span class='danger'>You feel yourself smouldering in the heat!</span>")
|
||||
|
||||
var/bodypart = pick(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND,BP_TORSO,BP_GROIN,BP_HEAD)
|
||||
if(breath.temperature >= breath_heat_level_1)
|
||||
if(breath.temperature < breath_heat_level_2)
|
||||
H.apply_damage(HEAT_GAS_DAMAGE_LEVEL_1, BURN, bodypart, used_weapon = "Excessive Heat")
|
||||
H.fire_alert = max(H.fire_alert, 2)
|
||||
else if(breath.temperature < breath_heat_level_3)
|
||||
H.apply_damage(HEAT_GAS_DAMAGE_LEVEL_2, BURN, bodypart, used_weapon = "Excessive Heat")
|
||||
H.fire_alert = max(H.fire_alert, 2)
|
||||
else
|
||||
H.apply_damage(HEAT_GAS_DAMAGE_LEVEL_3, BURN, bodypart, used_weapon = "Excessive Heat")
|
||||
H.fire_alert = max(H.fire_alert, 2)
|
||||
|
||||
else if(breath.temperature <= breath_cold_level_1)
|
||||
if(breath.temperature > breath_cold_level_2)
|
||||
H.apply_damage(COLD_GAS_DAMAGE_LEVEL_1, BURN, bodypart, used_weapon = "Excessive Cold")
|
||||
H.fire_alert = max(H.fire_alert, 1)
|
||||
else if(breath.temperature > breath_cold_level_3)
|
||||
H.apply_damage(COLD_GAS_DAMAGE_LEVEL_2, BURN, bodypart, used_weapon = "Excessive Cold")
|
||||
H.fire_alert = max(H.fire_alert, 1)
|
||||
else
|
||||
H.apply_damage(COLD_GAS_DAMAGE_LEVEL_3, BURN, bodypart, used_weapon = "Excessive Cold")
|
||||
H.fire_alert = max(H.fire_alert, 1)
|
||||
|
||||
|
||||
//breathing in hot/cold air also heats/cools you a bit
|
||||
var/temp_adj = breath.temperature - H.bodytemperature
|
||||
if (temp_adj < 0)
|
||||
temp_adj /= (BODYTEMP_COLD_DIVISOR * 5) //don't raise temperature as much as if we were directly exposed
|
||||
else
|
||||
temp_adj /= (BODYTEMP_HEAT_DIVISOR * 5) //don't raise temperature as much as if we were directly exposed
|
||||
|
||||
var/relative_density = breath.total_moles / (MOLES_CELLSTANDARD * BREATH_PERCENTAGE)
|
||||
temp_adj *= relative_density
|
||||
|
||||
if (temp_adj > BODYTEMP_HEATING_MAX) temp_adj = BODYTEMP_HEATING_MAX
|
||||
if (temp_adj < BODYTEMP_COOLING_MAX) temp_adj = BODYTEMP_COOLING_MAX
|
||||
//world << "Breath: [breath.temperature], [src]: [bodytemperature], Adjusting: [temp_adj]"
|
||||
H.bodytemperature += temp_adj
|
||||
|
||||
else if(breath.temperature >= heat_discomfort_level)
|
||||
get_environment_discomfort(src,"heat")
|
||||
else if(breath.temperature <= cold_discomfort_level)
|
||||
get_environment_discomfort(src,"cold")
|
||||
|
||||
breath.update_values()
|
||||
return 1
|
||||
|
||||
/obj/item/organ/internal/brain/alraune
|
||||
icon = 'icons/mob/species/alraune/organs.dmi'
|
||||
icon_state = "neurostroma"
|
||||
name = "neuro-stroma"
|
||||
desc = "A knot of fibrous plant matter."
|
||||
parent_organ = BP_TORSO // brains in their core
|
||||
|
||||
/obj/item/organ/internal/eyes/alraune
|
||||
icon = 'icons/mob/species/alraune/organs.dmi'
|
||||
icon_state = "photoreceptors"
|
||||
name = "photoreceptors"
|
||||
desc = "Bulbous and fleshy plant matter."
|
||||
|
||||
/obj/item/organ/internal/kidneys/alraune
|
||||
icon = 'icons/mob/species/alraune/organs.dmi'
|
||||
icon_state = "rhyzofilter"
|
||||
name = "rhyzofilter"
|
||||
desc = "A tangle of root nodules."
|
||||
|
||||
/obj/item/organ/internal/liver/alraune
|
||||
icon = 'icons/mob/species/alraune/organs.dmi'
|
||||
icon_state = "phytoextractor"
|
||||
name = "phytoextractor"
|
||||
desc = "A bulbous gourd-like structure."
|
||||
@@ -1,10 +1,11 @@
|
||||
/mob/living/carbon/proc/ingest(var/datum/reagents/from, var/datum/reagents/target, var/amount = 1, var/multiplier = 1, var/copy = 0) //we kind of 'sneak' a proc in here for ingesting stuff so we can play with it.
|
||||
/* VOREStation Removal - Synths should be able to taste because... reasons
|
||||
if(ishuman(src))
|
||||
var/mob/living/carbon/human/H = src
|
||||
var/braintype = H.get_FBP_type()
|
||||
if(braintype == FBP_DRONE || braintype == FBP_POSI)
|
||||
return from.trans_to_holder(target,amount,multiplier,copy) //skip the taste, complete transfer
|
||||
|
||||
*/
|
||||
if(last_taste_time + 50 < world.time)
|
||||
var/datum/reagents/temp = new(amount) //temporary holder used to analyse what gets transfered.
|
||||
from.trans_to_holder(temp, amount, multiplier, 1)
|
||||
|
||||
@@ -693,6 +693,9 @@ var/list/ai_verbs_default = list(
|
||||
card.grab_ai(src, user)
|
||||
|
||||
else if(istype(W, /obj/item/weapon/wrench))
|
||||
if(user == controlling_drone)
|
||||
to_chat(user, "<span class='notice'>The drone's subsystems resist your efforts to tamper with your bolts.</span>")
|
||||
return
|
||||
if(anchored)
|
||||
playsound(src, W.usesound, 50, 1)
|
||||
user.visible_message("<font color='blue'>\The [user] starts to unbolt \the [src] from the plating...</font>")
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
if(stat == DEAD)
|
||||
return
|
||||
|
||||
if(controlling_drone)
|
||||
controlling_drone.release_ai_control("<b>WARNING: Primary control loop failure.</b> Session terminated.")
|
||||
. = ..(gibbed)
|
||||
|
||||
if(src.eyeobj)
|
||||
src.eyeobj.setLoc(get_turf(src))
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
if (src.stat!=CONSCIOUS)
|
||||
src.cameraFollow = null
|
||||
src.reset_view(null)
|
||||
if(controlling_drone)
|
||||
controlling_drone.release_ai_control("<b>WARNING: Primary control loop failure.</b> Session terminated.")
|
||||
|
||||
src.updatehealth()
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ var/list/mob_hat_cache = list()
|
||||
return mob_hat_cache[key]
|
||||
|
||||
/mob/living/silicon/robot/drone
|
||||
name = "drone"
|
||||
name = "maintenance drone"
|
||||
real_name = "drone"
|
||||
icon = 'icons/mob/robots.dmi'
|
||||
icon_state = "repairbot"
|
||||
@@ -57,6 +57,8 @@ var/list/mob_hat_cache = list()
|
||||
var/obj/item/hat
|
||||
var/hat_x_offset = 0
|
||||
var/hat_y_offset = -13
|
||||
var/serial_number = 0
|
||||
var/name_override = 0
|
||||
|
||||
holder_type = /obj/item/weapon/holder/drone
|
||||
|
||||
@@ -71,6 +73,7 @@ var/list/mob_hat_cache = list()
|
||||
return FALSE
|
||||
|
||||
/mob/living/silicon/robot/drone/construction
|
||||
name = "construction drone"
|
||||
icon_state = "constructiondrone"
|
||||
law_type = /datum/ai_laws/construction_drone
|
||||
module_type = /obj/item/weapon/robot_module/drone/construction
|
||||
@@ -95,6 +98,7 @@ var/list/mob_hat_cache = list()
|
||||
remove_language("Robot Talk")
|
||||
add_language("Robot Talk", 0)
|
||||
add_language("Drone Talk", 1)
|
||||
serial_number = rand(0,999)
|
||||
|
||||
//They are unable to be upgraded, so let's give them a bit of a better battery.
|
||||
cell.maxcharge = 10000
|
||||
@@ -127,14 +131,22 @@ var/list/mob_hat_cache = list()
|
||||
name = real_name
|
||||
|
||||
/mob/living/silicon/robot/drone/updatename()
|
||||
real_name = "maintenance drone ([rand(100,999)])"
|
||||
if(name_override)
|
||||
return
|
||||
if(controlling_ai)
|
||||
real_name = "remote drone ([controlling_ai])"
|
||||
else
|
||||
real_name = "[initial(name)] ([serial_number])"
|
||||
name = real_name
|
||||
|
||||
/mob/living/silicon/robot/drone/updateicon()
|
||||
|
||||
overlays.Cut()
|
||||
if(stat == 0)
|
||||
overlays += "eyes-[icon_state]"
|
||||
if(controlling_ai)
|
||||
overlays += "eyes-[icon_state]-ai"
|
||||
else
|
||||
overlays += "eyes-[icon_state]"
|
||||
else
|
||||
overlays -= "eyes"
|
||||
if(hat) // Let the drones wear hats.
|
||||
@@ -213,15 +225,18 @@ var/list/mob_hat_cache = list()
|
||||
return
|
||||
|
||||
if(emagged)
|
||||
to_chat(user, "<span class='danger'>\The [user] attempts to load subversive software into you, but your hacked subroutines ignore the attempt.</span>")
|
||||
to_chat(src, "<span class='danger'>\The [user] attempts to load subversive software into you, but your hacked subroutines ignore the attempt.</span>")
|
||||
to_chat(user, "<span class='danger'>You attempt to subvert [src], but the sequencer has no effect.</span>")
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='danger'>You swipe the sequencer across [src]'s interface and watch its eyes flicker.</span>")
|
||||
to_chat(user, "<span class='danger'>You feel a sudden burst of malware loaded into your execute-as-root buffer. Your tiny brain methodically parses, loads and executes the script.</span>")
|
||||
|
||||
message_admins("[key_name_admin(user)] emagged drone [key_name_admin(src)]. Laws overridden.")
|
||||
log_game("[key_name(user)] emagged drone [key_name(src)]. Laws overridden.")
|
||||
if(controlling_ai)
|
||||
to_chat(src, "<span class='danger'>\The [user] loads some kind of subversive software into the remote drone, corrupting its lawset but luckily sparing yours.</span>")
|
||||
else
|
||||
to_chat(src, "<span class='danger'>You feel a sudden burst of malware loaded into your execute-as-root buffer. Your tiny brain methodically parses, loads and executes the script.</span>")
|
||||
|
||||
log_game("[key_name(user)] emagged drone [key_name(src)][controlling_ai ? " but AI [key_name(controlling_ai)] is in remote control" : " Laws overridden"].")
|
||||
var/time = time2text(world.realtime,"hh:mm:ss")
|
||||
lawchanges.Add("[time] <B>:</B> [user.name]([user.key]) emagged [name]([key])")
|
||||
|
||||
@@ -234,9 +249,10 @@ var/list/mob_hat_cache = list()
|
||||
var/datum/gender/TU = gender_datums[user.get_visible_gender()]
|
||||
set_zeroth_law("Only [user.real_name] and people [TU.he] designate[TU.s] as being such are operatives.")
|
||||
|
||||
src << "<b>Obey these laws:</b>"
|
||||
laws.show_laws(src)
|
||||
src << "<span class='danger'>ALERT: [user.real_name] [TU.is] your new master. Obey your new laws and [TU.his] commands.</span>"
|
||||
if(!controlling_ai)
|
||||
to_chat(src, "<b>Obey these laws:</b>")
|
||||
laws.show_laws(src)
|
||||
to_chat(src, "<span class='danger'>ALERT: [user.real_name] is your new master. Obey your new laws and \his commands.</span>")
|
||||
return 1
|
||||
|
||||
//DRONE LIFE/DEATH
|
||||
@@ -262,26 +278,41 @@ var/list/mob_hat_cache = list()
|
||||
return
|
||||
..()
|
||||
|
||||
/mob/living/silicon/robot/drone/death(gibbed)
|
||||
if(controlling_ai)
|
||||
release_ai_control("<b>WARNING: remote system failure.</b> Connection timed out.")
|
||||
. = ..(gibbed)
|
||||
|
||||
//DRONE MOVEMENT.
|
||||
/mob/living/silicon/robot/drone/Process_Spaceslipping(var/prob_slip)
|
||||
return 0
|
||||
|
||||
//CONSOLE PROCS
|
||||
/mob/living/silicon/robot/drone/proc/law_resync()
|
||||
|
||||
if(controlling_ai)
|
||||
to_chat(src, "<span class='warning'>Someone issues a remote law reset order for this unit, but you disregard it.</span>")
|
||||
return
|
||||
|
||||
if(stat != 2)
|
||||
if(emagged)
|
||||
src << "<span class='danger'>You feel something attempting to modify your programming, but your hacked subroutines are unaffected.</span>"
|
||||
to_chat(src, "<span class='danger'>You feel something attempting to modify your programming, but your hacked subroutines are unaffected.</span>")
|
||||
else
|
||||
src << "<span class='danger'>A reset-to-factory directive packet filters through your data connection, and you obediently modify your programming to suit it.</span>"
|
||||
to_chat(src, "<span class='danger'>A reset-to-factory directive packet filters through your data connection, and you obediently modify your programming to suit it.</span>")
|
||||
full_law_reset()
|
||||
show_laws()
|
||||
|
||||
/mob/living/silicon/robot/drone/proc/shut_down()
|
||||
|
||||
if(controlling_ai && mind.special_role)
|
||||
to_chat(src, "<span class='warning'>Someone issued a remote kill order for this unit, but you disregard it.</span>")
|
||||
return
|
||||
|
||||
if(stat != 2)
|
||||
if(emagged)
|
||||
src << "<span class='danger'>You feel a system kill order percolate through your tiny brain, but it doesn't seem like a good idea to you.</span>"
|
||||
to_chat(src, "<span class='danger'>You feel a system kill order percolate through [controlling_ai ? "the drones" : "your"] tiny brain, but it doesn't seem like a good idea to [controlling_ai ? "it" : "you"].</span>")
|
||||
else
|
||||
src << "<span class='danger'>You feel a system kill order percolate through your tiny brain, and you obediently destroy yourself.</span>"
|
||||
to_chat(src, "<span class='danger'>You feel a system kill order percolate through [controlling_ai ? "the drones" : "your"] tiny brain, and [controlling_ai ? "it" : "you"] obediently destroy[controlling_ai ? "s itself" : " yourself"].</span>")
|
||||
death()
|
||||
|
||||
/mob/living/silicon/robot/drone/proc/full_law_reset()
|
||||
@@ -290,6 +321,21 @@ var/list/mob_hat_cache = list()
|
||||
clear_ion_laws(1)
|
||||
laws = new law_type
|
||||
|
||||
/mob/living/silicon/robot/drone/show_laws(var/everyone = 0)
|
||||
if(!controlling_ai)
|
||||
return..()
|
||||
to_chat(src, "<b>Obey these laws:</b>")
|
||||
controlling_ai.laws_sanity_check()
|
||||
controlling_ai.laws.show_laws(src)
|
||||
|
||||
/mob/living/silicon/robot/drone/robot_checklaws()
|
||||
set category = "Silicon Commands"
|
||||
set name = "State Laws"
|
||||
|
||||
if(!controlling_ai)
|
||||
return ..()
|
||||
controlling_ai.subsystem_law_manager()
|
||||
|
||||
//Reboot procs.
|
||||
|
||||
/mob/living/silicon/robot/drone/proc/request_player()
|
||||
@@ -347,14 +393,6 @@ var/list/mob_hat_cache = list()
|
||||
..()
|
||||
flavor_text = "It's a bulky construction drone stamped with a Sol Central glyph."
|
||||
|
||||
/mob/living/silicon/robot/drone/construction/updatename()
|
||||
real_name = "construction drone ([rand(100,999)])"
|
||||
name = real_name
|
||||
|
||||
/mob/living/silicon/robot/drone/mining/init()
|
||||
..()
|
||||
flavor_text = "It's a bulky mining drone stamped with a Grayson logo."
|
||||
|
||||
/mob/living/silicon/robot/drone/mining/updatename()
|
||||
real_name = "mining drone ([rand(100,999)])"
|
||||
name = real_name
|
||||
|
||||
@@ -75,20 +75,22 @@
|
||||
if(!produce_drones || !config.allow_drone_spawn || count_drones() >= config.max_maint_drones)
|
||||
return
|
||||
|
||||
if(!player || !istype(player.mob,/mob/observer/dead))
|
||||
if(player && !istype(player.mob,/mob/observer/dead))
|
||||
return
|
||||
|
||||
announce_ghost_joinleave(player, 0, "They have taken control over a maintenance drone.")
|
||||
visible_message("\The [src] churns and grinds as it lurches into motion, disgorging a shiny new drone after a few moments.")
|
||||
flick("h_lathe_leave",src)
|
||||
drone_progress = 0
|
||||
|
||||
time_last_drone = world.time
|
||||
if(player.mob && player.mob.mind) player.mob.mind.reset()
|
||||
var/mob/living/silicon/robot/drone/new_drone = new drone_type(get_turf(src))
|
||||
new_drone.transfer_personality(player)
|
||||
new_drone.master_fabricator = src
|
||||
|
||||
drone_progress = 0
|
||||
var/mob/living/silicon/robot/drone/new_drone = new drone_type(get_turf(src))
|
||||
if(player)
|
||||
announce_ghost_joinleave(player, 0, "They have taken control over a maintenance drone.")
|
||||
if(player.mob && player.mob.mind) player.mob.mind.reset()
|
||||
new_drone.transfer_personality(player)
|
||||
|
||||
return new_drone
|
||||
|
||||
/mob/observer/dead/verb/join_as_drone()
|
||||
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
/mob/living/silicon/ai
|
||||
var/mob/living/silicon/robot/drone/controlling_drone
|
||||
|
||||
/mob/living/silicon/robot/drone
|
||||
var/mob/living/silicon/ai/controlling_ai
|
||||
|
||||
/mob/living/silicon/robot/drone/attack_ai(var/mob/living/silicon/ai/user)
|
||||
|
||||
if(!istype(user) || controlling_ai || !config.allow_drone_spawn || !config.allow_ai_drones)
|
||||
return
|
||||
|
||||
if(client || key)
|
||||
to_chat(user, "<span class='warning'>You cannot take control of an autonomous, active drone.</span>")
|
||||
return
|
||||
|
||||
if(health < -35 || emagged)
|
||||
to_chat(user, "<span class='notice'><b>WARNING:</b> connection timed out.</span>")
|
||||
return
|
||||
|
||||
user.controlling_drone = src
|
||||
user.teleop = src
|
||||
radio.channels = user.aiRadio.keyslot2.channels
|
||||
controlling_ai = user
|
||||
verbs += /mob/living/silicon/robot/drone/proc/release_ai_control_verb
|
||||
local_transmit = FALSE
|
||||
languages = controlling_ai.languages.Copy()
|
||||
speech_synthesizer_langs = controlling_ai.speech_synthesizer_langs.Copy()
|
||||
stat = CONSCIOUS
|
||||
if(user.mind)
|
||||
user.mind.transfer_to(src)
|
||||
else
|
||||
key = user.key
|
||||
updatename()
|
||||
to_chat(src, "<span class='notice'><b>You have shunted your primary control loop into \a [initial(name)].</b> Use the <b>Release Control</b> verb to return to your core.</span>")
|
||||
|
||||
/obj/machinery/drone_fabricator/attack_ai(var/mob/living/silicon/ai/user as mob)
|
||||
|
||||
if(!istype(user) || user.controlling_drone || !config.allow_drone_spawn || !config.allow_ai_drones)
|
||||
return
|
||||
|
||||
if(stat & NOPOWER)
|
||||
to_chat(user, "<span class='warning'>\The [src] is unpowered.</span>")
|
||||
return
|
||||
|
||||
if(!produce_drones)
|
||||
to_chat(user, "<span class='warning'>\The [src] is disabled.</span>")
|
||||
return
|
||||
|
||||
if(drone_progress < 100)
|
||||
to_chat(user, "<span class='warning'>\The [src] is not ready to produce a new drone.</span>")
|
||||
return
|
||||
|
||||
if(count_drones() >= config.max_maint_drones)
|
||||
to_chat(user, "<span class='warning'>The drone control subsystems are tasked to capacity; they cannot support any more drones.</span>")
|
||||
return
|
||||
|
||||
var/mob/living/silicon/robot/drone/new_drone = create_drone()
|
||||
user.controlling_drone = new_drone
|
||||
user.teleop = new_drone
|
||||
new_drone.radio.channels = user.aiRadio.keyslot2.channels
|
||||
new_drone.controlling_ai = user
|
||||
new_drone.verbs += /mob/living/silicon/robot/drone/proc/release_ai_control_verb
|
||||
new_drone.local_transmit = FALSE
|
||||
new_drone.languages = new_drone.controlling_ai.languages.Copy()
|
||||
new_drone.speech_synthesizer_langs = new_drone.controlling_ai.speech_synthesizer_langs.Copy()
|
||||
|
||||
if(user.mind)
|
||||
user.mind.transfer_to(new_drone)
|
||||
else
|
||||
new_drone.key = user.key
|
||||
new_drone.updatename()
|
||||
|
||||
to_chat(new_drone, "<span class='notice'><b>You have shunted your primary control loop into \a [initial(new_drone.name)].</b> Use the <b>Release Control</b> verb to return to your core.</span>")
|
||||
|
||||
/mob/living/silicon/robot/drone/proc/release_ai_control_verb()
|
||||
set name = "Release Control"
|
||||
set desc = "Release control of a remote drone."
|
||||
set category = "Silicon Commands"
|
||||
|
||||
release_ai_control("Remote session terminated.")
|
||||
|
||||
/mob/living/silicon/robot/drone/proc/release_ai_control(var/message = "Connection terminated.")
|
||||
|
||||
if(controlling_ai)
|
||||
if(mind)
|
||||
mind.transfer_to(controlling_ai)
|
||||
else
|
||||
controlling_ai.key = key
|
||||
to_chat(controlling_ai, "<span class='notice'>[message]</span>")
|
||||
controlling_ai.controlling_drone = null
|
||||
controlling_ai.teleop = null
|
||||
controlling_ai = null
|
||||
|
||||
radio.channels = module.channels
|
||||
verbs -= /mob/living/silicon/robot/drone/proc/release_ai_control_verb
|
||||
languages = initial(languages)
|
||||
speech_synthesizer_langs = initial(speech_synthesizer_langs)
|
||||
remove_language("Robot Talk")
|
||||
add_language("Robot Talk", 0)
|
||||
add_language("Drone Talk", 1)
|
||||
local_transmit = TRUE
|
||||
full_law_reset()
|
||||
updatename()
|
||||
death()
|
||||
@@ -114,6 +114,8 @@
|
||||
var/obj/structure/closet/crate/C = new(get_turf(src))
|
||||
// Put loot in crate
|
||||
for(var/obj/O in src)
|
||||
if(isbelly(O)) //VOREStation edit
|
||||
continue
|
||||
O.forceMove(C)
|
||||
..()
|
||||
|
||||
@@ -146,6 +148,8 @@ var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/ca
|
||||
/mob/living/simple_animal/hostile/mimic/copy/death()
|
||||
|
||||
for(var/atom/movable/M in src)
|
||||
if(isbelly(M)) //VOREStation edit
|
||||
continue
|
||||
M.forceMove(get_turf(src))
|
||||
..()
|
||||
|
||||
|
||||
@@ -451,7 +451,7 @@
|
||||
if(!silent)
|
||||
if(planetary)
|
||||
visible_message("<span class='danger'><font size='3'>\A [src] falls out of the sky and crashes into \the [landing]!</font></span>", \
|
||||
"<span class='danger'><font size='3'> You fall out of the skiy and crash into \the [landing]!</font></span>", \
|
||||
"<span class='danger'><font size='3'> You fall out of the sky and crash into \the [landing]!</font></span>", \
|
||||
"You hear something slam into \the [landing].")
|
||||
var/turf/T = get_turf(landing)
|
||||
explosion(T, 0, 1, 2)
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
// Now sync the organ's eye_colour list.
|
||||
update_colour()
|
||||
// Finally, update the eye icon on the mob.
|
||||
owner.update_eyes()
|
||||
owner.regenerate_icons()
|
||||
|
||||
/obj/item/organ/internal/eyes/replaced(var/mob/living/carbon/human/target)
|
||||
|
||||
|
||||
@@ -1105,6 +1105,8 @@ Note that amputating the affected organ does in fact remove the infection from t
|
||||
R = basic_robolimb
|
||||
if(R)
|
||||
force_icon = R.icon
|
||||
brute_mod *= R.robo_brute_mod
|
||||
burn_mod *= R.robo_burn_mod
|
||||
if(R.lifelike)
|
||||
robotic = ORGAN_LIFELIKE
|
||||
name = "[initial(name)]"
|
||||
|
||||
@@ -4,13 +4,13 @@ var/global/list/limb_icon_cache = list()
|
||||
return
|
||||
|
||||
/obj/item/organ/external/proc/compile_icon()
|
||||
overlays.Cut()
|
||||
cut_overlays()
|
||||
// This is a kludge, only one icon has more than one generation of children though.
|
||||
for(var/obj/item/organ/external/organ in contents)
|
||||
if(organ.children && organ.children.len)
|
||||
for(var/obj/item/organ/external/child in organ.children)
|
||||
overlays += child.mob_icon
|
||||
overlays += organ.mob_icon
|
||||
add_overlay(organ.mob_icon)
|
||||
|
||||
/obj/item/organ/external/proc/sync_colour_to_human(var/mob/living/carbon/human/human)
|
||||
s_tone = null
|
||||
@@ -94,7 +94,7 @@ var/global/list/limb_icon_cache = list()
|
||||
mob_icon.Blend(mark_s, ICON_OVERLAY) //So when it's on your body, it has icons
|
||||
icon_cache_key += "[M][markings[M]["color"]]"
|
||||
|
||||
overlays |= get_hair_icon()
|
||||
add_overlay(get_hair_icon())
|
||||
|
||||
return mob_icon
|
||||
|
||||
@@ -107,7 +107,7 @@ var/global/list/limb_icon_cache = list()
|
||||
var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s")
|
||||
if(facial_hair_style.do_colouration)
|
||||
facial_s.Blend(rgb(owner.r_facial, owner.g_facial, owner.b_facial), ICON_MULTIPLY) // VOREStation edit
|
||||
add_overlay(facial_s)
|
||||
res.add_overlay(facial_s)
|
||||
|
||||
//Head hair
|
||||
if(owner.h_style && !(owner.head && (owner.head.flags_inv & BLOCKHEADHAIR)))
|
||||
@@ -122,7 +122,7 @@ var/global/list/limb_icon_cache = list()
|
||||
if(hair_style.do_colouration && islist(h_col) && h_col.len >= 3)
|
||||
hair_s.Blend(rgb(h_col[1], h_col[2], h_col[3]), ICON_MULTIPLY)
|
||||
hair_s.Blend(hair_s_add, ICON_ADD)
|
||||
res.overlays |= hair_s
|
||||
res.add_overlay(hair_s)
|
||||
|
||||
return res
|
||||
|
||||
@@ -164,7 +164,7 @@ var/global/list/limb_icon_cache = list()
|
||||
var/datum/sprite_accessory/marking/mark_style = markings[M]["datum"]
|
||||
var/icon/mark_s = new/icon("icon" = mark_style.icon, "icon_state" = "[mark_style.icon_state]-[organ_tag]")
|
||||
mark_s.Blend(markings[M]["color"], mark_style.color_blend_mode) // VOREStation edit
|
||||
overlays |= mark_s //So when it's not on your body, it has icons
|
||||
add_overlay(mark_s) //So when it's not on your body, it has icons
|
||||
mob_icon.Blend(mark_s, ICON_OVERLAY) //So when it's on your body, it has icons
|
||||
icon_cache_key += "[M][markings[M]["color"]]"
|
||||
|
||||
@@ -280,7 +280,7 @@ var/list/robot_hud_colours = list("#CFCFCF","#AFAFAF","#8F8F8F","#6F6F6F","#4F4F
|
||||
var/b = 0.11 * R.health_hud_intensity
|
||||
temp.color = list(r, r, r, g, g, g, b, b, b)
|
||||
hud_damage_image = image(null)
|
||||
hud_damage_image.overlays += temp
|
||||
hud_damage_image.add_overlay(temp)
|
||||
|
||||
// Calculate the required color index.
|
||||
var/dam_state = min(1,((brute_dam+burn_dam)/max_damage))
|
||||
|
||||
@@ -49,6 +49,9 @@ var/const/standard_monitor_styles = "blank=ipc_blank;\
|
||||
var/suggested_species = "Human" //If it should make the torso a species
|
||||
var/speech_bubble_appearance = "synthetic" // What icon_state to use for speech bubbles when talking. Check talk.dmi for all the icons.
|
||||
|
||||
var/robo_brute_mod = 1 // Multiplier for incoming brute damage.
|
||||
var/robo_burn_mod = 1 // As above for burn.
|
||||
|
||||
/datum/robolimb/unbranded_monitor
|
||||
company = "Unbranded Monitor"
|
||||
desc = "A generic unbranded interpretation of a popular prosthetic head model. It looks rudimentary and cheaply constructed."
|
||||
@@ -214,6 +217,8 @@ var/const/standard_monitor_styles = "blank=ipc_blank;\
|
||||
skin_tone = 1
|
||||
blood_color = "#CCCCCC"
|
||||
speech_bubble_appearance = "normal"
|
||||
//robo_brute_mod = 1.1 //VOREStation Edit
|
||||
//robo_burn_mod = 1.1 //VOREStation Edit
|
||||
|
||||
/datum/robolimb/wardtakahashi
|
||||
company = "Ward-Takahashi"
|
||||
|
||||
@@ -30,9 +30,10 @@
|
||||
current_time = current_time.make_random_time()
|
||||
update_sun()
|
||||
|
||||
/datum/planet/proc/process(amount)
|
||||
/datum/planet/proc/process(last_fire)
|
||||
if(current_time)
|
||||
current_time = current_time.add_seconds(amount)
|
||||
var/difference = world.time - last_fire
|
||||
current_time = current_time.add_seconds(difference SECONDS)
|
||||
update_weather() // We update this first, because some weather types decease the brightness of the sun.
|
||||
if(sun_last_process <= world.time - sun_process_interval)
|
||||
update_sun()
|
||||
|
||||
@@ -184,7 +184,8 @@ datum/weather/sif
|
||||
)
|
||||
|
||||
/datum/weather/sif/snow/process_effects()
|
||||
for(var/turf/simulated/floor/outdoors/snow/S in outdoor_turfs)
|
||||
..()
|
||||
for(var/turf/simulated/floor/outdoors/snow/S in SSplanets.new_outdoor_turfs) //This didn't make any sense before SSplanets, either
|
||||
if(S.z in holder.our_planet.expected_z_levels)
|
||||
for(var/dir_checked in cardinal)
|
||||
var/turf/simulated/floor/T = get_step(S, dir_checked)
|
||||
@@ -207,7 +208,8 @@ datum/weather/sif
|
||||
)
|
||||
|
||||
/datum/weather/sif/blizzard/process_effects()
|
||||
for(var/turf/simulated/floor/outdoors/snow/S in outdoor_turfs)
|
||||
..()
|
||||
for(var/turf/simulated/floor/outdoors/snow/S in SSplanets.new_outdoor_turfs) //This didn't make any sense before SSplanets, either
|
||||
if(S.z in holder.our_planet.expected_z_levels)
|
||||
for(var/dir_checked in cardinal)
|
||||
var/turf/simulated/floor/T = get_step(S, dir_checked)
|
||||
@@ -219,6 +221,8 @@ datum/weather/sif
|
||||
name = "rain"
|
||||
icon_state = "rain"
|
||||
light_modifier = 0.5
|
||||
effect_message = "<span class='warning'>Rain falls on you.</span>"
|
||||
|
||||
transition_chances = list(
|
||||
WEATHER_OVERCAST = 25,
|
||||
WEATHER_LIGHT_SNOW = 10,
|
||||
@@ -228,6 +232,7 @@ datum/weather/sif
|
||||
)
|
||||
|
||||
/datum/weather/sif/rain/process_effects()
|
||||
..()
|
||||
for(var/mob/living/L in living_mob_list)
|
||||
if(L.z in holder.our_planet.expected_z_levels)
|
||||
var/turf/T = get_turf(L)
|
||||
@@ -238,16 +243,19 @@ datum/weather/sif
|
||||
if(istype(L.get_active_hand(), /obj/item/weapon/melee/umbrella))
|
||||
var/obj/item/weapon/melee/umbrella/U = L.get_active_hand()
|
||||
if(U.open)
|
||||
to_chat(L, "<span class='notice'>Rain patters softly onto your umbrella</span>")
|
||||
if(show_message)
|
||||
to_chat(L, "<span class='notice'>Rain patters softly onto your umbrella</span>")
|
||||
continue
|
||||
else if(istype(L.get_inactive_hand(), /obj/item/weapon/melee/umbrella))
|
||||
var/obj/item/weapon/melee/umbrella/U = L.get_inactive_hand()
|
||||
if(U.open)
|
||||
to_chat(L, "<span class='notice'>Rain patters softly onto your umbrella</span>")
|
||||
if(show_message)
|
||||
to_chat(L, "<span class='notice'>Rain patters softly onto your umbrella</span>")
|
||||
continue
|
||||
|
||||
L.water_act(1)
|
||||
to_chat(L, "<span class='warning'>Rain falls on you.</span>")
|
||||
if(show_message)
|
||||
to_chat(L, effect_message)
|
||||
|
||||
/datum/weather/sif/storm
|
||||
name = "storm"
|
||||
@@ -256,6 +264,8 @@ datum/weather/sif
|
||||
temp_low = 233.15 // -40c
|
||||
light_modifier = 0.3
|
||||
flight_failure_modifier = 10
|
||||
|
||||
|
||||
transition_chances = list(
|
||||
WEATHER_RAIN = 45,
|
||||
WEATHER_STORM = 40,
|
||||
@@ -264,6 +274,7 @@ datum/weather/sif
|
||||
)
|
||||
|
||||
/datum/weather/sif/storm/process_effects()
|
||||
..()
|
||||
for(var/mob/living/L in living_mob_list)
|
||||
if(L.z in holder.our_planet.expected_z_levels)
|
||||
var/turf/T = get_turf(L)
|
||||
@@ -294,6 +305,10 @@ datum/weather/sif
|
||||
temp_low = 243.15 // -30c
|
||||
light_modifier = 0.3
|
||||
flight_failure_modifier = 15
|
||||
timer_low_bound = 2
|
||||
timer_high_bound = 5
|
||||
effect_message = "<span class='warning'>The hail smacks into you!</span>"
|
||||
|
||||
transition_chances = list(
|
||||
WEATHER_RAIN = 45,
|
||||
WEATHER_STORM = 40,
|
||||
@@ -302,6 +317,7 @@ datum/weather/sif
|
||||
)
|
||||
|
||||
/datum/weather/sif/hail/process_effects()
|
||||
..()
|
||||
for(var/mob/living/carbon/human/H in living_mob_list)
|
||||
if(H.z in holder.our_planet.expected_z_levels)
|
||||
var/turf/T = get_turf(H)
|
||||
@@ -309,15 +325,18 @@ datum/weather/sif
|
||||
continue // They're indoors, so no need to pelt them with ice.
|
||||
|
||||
// If they have an open umbrella, it'll guard from rain
|
||||
// Message plays every time the umbrella gets stolen, just so they're especially aware of what's happening
|
||||
if(istype(H.get_active_hand(), /obj/item/weapon/melee/umbrella))
|
||||
var/obj/item/weapon/melee/umbrella/U = H.get_active_hand()
|
||||
if(U.open)
|
||||
to_chat(H, "<span class='notice'>Hail patters gently onto your umbrella.</span>")
|
||||
if(show_message)
|
||||
to_chat(H, "<span class='notice'>Hail patters gently onto your umbrella.</span>")
|
||||
continue
|
||||
else if(istype(H.get_inactive_hand(), /obj/item/weapon/melee/umbrella))
|
||||
var/obj/item/weapon/melee/umbrella/U = H.get_inactive_hand()
|
||||
if(U.open)
|
||||
to_chat(H, "<span class='notice'>Hail patters gently onto your umbrella.</span>")
|
||||
if(show_message)
|
||||
to_chat(H, "<span class='notice'>Hail patters gently onto your umbrella.</span>")
|
||||
continue
|
||||
|
||||
var/target_zone = pick(BP_ALL)
|
||||
@@ -330,8 +349,9 @@ datum/weather/sif
|
||||
if(amount_soaked >= 10)
|
||||
continue // No need to apply damage.
|
||||
|
||||
H.apply_damage(rand(5, 10), BRUTE, target_zone, amount_blocked, amount_soaked, used_weapon = "hail")
|
||||
to_chat(H, "<span class='warning'>The hail smacks into you!</span>")
|
||||
H.apply_damage(rand(1, 3), BRUTE, target_zone, amount_blocked, amount_soaked, used_weapon = "hail")
|
||||
if(show_message)
|
||||
to_chat(H, effect_message)
|
||||
|
||||
/datum/weather/sif/blood_moon
|
||||
name = "blood moon"
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
if(current_weather)
|
||||
old_light_modifier = current_weather.light_modifier // We store the old one, so we can determine if recalculating the sun is needed.
|
||||
current_weather = allowed_weather_types[new_weather]
|
||||
next_weather_shift = world.time + rand(20, 30) MINUTES
|
||||
next_weather_shift = world.time + rand(current_weather.timer_low_bound, current_weather.timer_high_bound) MINUTES
|
||||
|
||||
update_icon_effects()
|
||||
update_temperature()
|
||||
@@ -66,8 +66,20 @@
|
||||
var/flight_failure_modifier = 0 // Some types of weather make flying harder, and therefore make crashes more likely.
|
||||
var/transition_chances = list() // Assoc list
|
||||
var/datum/weather_holder/holder = null
|
||||
var/timer_low_bound = 5 // How long this weather must run before it tries to change, in minutes
|
||||
var/timer_high_bound = 10 // How long this weather can run before it tries to change, in minutes
|
||||
|
||||
var/effect_message = null // Should be a string, this is what is shown to a mob caught in the weather
|
||||
var/last_message = 0 // Keeps track of when the weather last tells EVERY player it's hitting them
|
||||
var/message_delay = 10 SECONDS // Delay in between weather hit messages
|
||||
var/show_message = FALSE // Is set to TRUE and plays the messsage every [message_delay]
|
||||
|
||||
/datum/weather/proc/process_effects()
|
||||
show_message = FALSE // Need to reset the show_message var, just in case
|
||||
if(effect_message) // Only bother with the code below if we actually need to display something
|
||||
if(world.time >= last_message + message_delay)
|
||||
last_message = world.time // Reset the timer
|
||||
show_message = TRUE // Tell the rest of the process that we need to make a message
|
||||
return
|
||||
|
||||
// All this does is hold the weather icon.
|
||||
|
||||
@@ -909,9 +909,9 @@
|
||||
|
||||
cup_icon_state = "cup_coffee"
|
||||
cup_name = "cup of coffee"
|
||||
cup_desc = "Don't drop it, or you'll send scalding liquid and porcelain shards everywhere."
|
||||
cup_desc = "Don't drop it, or you'll send scalding liquid and ceramic shards everywhere."
|
||||
|
||||
glass_name = "cup of coffee"
|
||||
glass_name = "coffee"
|
||||
glass_desc = "Don't drop it, or you'll send scalding liquid and glass shards everywhere."
|
||||
|
||||
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
desc = "..."
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "watertank"
|
||||
plane = TURF_PLANE
|
||||
layer = TABLE_LAYER // Above catwalks, hopefully below other things
|
||||
layer = TABLE_LAYER
|
||||
density = 1
|
||||
anchored = 0
|
||||
pressure_resistance = 2*ONE_ATMOSPHERE
|
||||
|
||||
@@ -88,16 +88,58 @@
|
||||
do_colouration = 1
|
||||
color_blend_mode = ICON_MULTIPLY
|
||||
|
||||
/datum/sprite_accessory/ears/curly_bug
|
||||
name = "curly antennae, colorable"
|
||||
desc = ""
|
||||
icon_state = "curly_bug"
|
||||
do_colouration = 1
|
||||
color_blend_mode = ICON_MULTIPLY
|
||||
|
||||
/datum/sprite_accessory/ears/dual_robot
|
||||
name = "synth antennae, colorable"
|
||||
desc = ""
|
||||
icon_state = "dual_robot_antennae"
|
||||
do_colouration = 1
|
||||
color_blend_mode = ICON_MULTIPLY
|
||||
|
||||
/datum/sprite_accessory/ears/right_robot
|
||||
name = "right synth, colorable"
|
||||
desc = ""
|
||||
icon_state = "right_robot_antennae"
|
||||
do_colouration = 1
|
||||
color_blend_mode = ICON_MULTIPLY
|
||||
|
||||
/datum/sprite_accessory/ears/left_robot
|
||||
name = "left synth, colorable"
|
||||
desc = ""
|
||||
icon_state = "left_robot_antennae"
|
||||
do_colouration = 1
|
||||
color_blend_mode = ICON_MULTIPLY
|
||||
|
||||
/datum/sprite_accessory/ears/oni_h1
|
||||
name = "oni horns"
|
||||
desc = ""
|
||||
icon_state = "oni-h1"
|
||||
|
||||
/datum/sprite_accessory/ears/oni_h1_c
|
||||
name = "oni horns, colorable"
|
||||
desc = ""
|
||||
icon_state = "oni-h1_c"
|
||||
do_colouration = 1
|
||||
color_blend_mode = ICON_MULTIPLY
|
||||
|
||||
/datum/sprite_accessory/ears/demon_horns1
|
||||
name = "demon horns"
|
||||
desc = ""
|
||||
icon_state = "demon-horns1"
|
||||
|
||||
/datum/sprite_accessory/ears/demon_horns1_c
|
||||
name = "demon horns, colorable"
|
||||
desc = ""
|
||||
icon_state = "demon-horns1_c"
|
||||
do_colouration = 1
|
||||
color_blend_mode = ICON_MULTIPLY
|
||||
|
||||
/datum/sprite_accessory/ears/demon_horns2
|
||||
name = "demon horns, colorable(outward)"
|
||||
desc = ""
|
||||
@@ -105,6 +147,13 @@
|
||||
do_colouration = 1
|
||||
color_blend_mode = ICON_MULTIPLY
|
||||
|
||||
/datum/sprite_accessory/ears/dragon_horns
|
||||
name = "dragon horns, colorable"
|
||||
desc = ""
|
||||
icon_state = "dragon-horns"
|
||||
do_colouration = 1
|
||||
color_blend_mode = ICON_MULTIPLY
|
||||
|
||||
/datum/sprite_accessory/ears/foxears
|
||||
name = "highlander zorren ears"
|
||||
desc = ""
|
||||
@@ -413,6 +462,7 @@
|
||||
desc = ""
|
||||
icon_state = "spider-legs"
|
||||
color_blend_mode = ICON_MULTIPLY
|
||||
|
||||
/datum/sprite_accessory/wing/moth
|
||||
name = "moth wings"
|
||||
desc = ""
|
||||
@@ -682,12 +732,14 @@
|
||||
icon_state = "fantail"
|
||||
do_colouration = 1
|
||||
color_blend_mode = ICON_MULTIPLY
|
||||
|
||||
/datum/sprite_accessory/tail/wagtail
|
||||
name = "avian wagtail, colorable"
|
||||
desc = ""
|
||||
icon_state = "wagtail"
|
||||
do_colouration = 1
|
||||
color_blend_mode = ICON_MULTIPLY
|
||||
|
||||
/datum/sprite_accessory/tail/crossfox
|
||||
name = "cross fox"
|
||||
desc = ""
|
||||
|
||||
@@ -578,6 +578,11 @@
|
||||
if(!(content in src) || !istype(target))
|
||||
return
|
||||
content.forceMove(target)
|
||||
if(isitem(content))
|
||||
var/obj/item/I = content
|
||||
if(I.gurgled && (target.mode_flags & DM_FLAG_ITEMWEAK))
|
||||
I.decontaminate()
|
||||
I.gurgle_contaminate(target.contents, target.cont_flavor)
|
||||
items_preserved -= content
|
||||
if(!silent && target.vore_sound && !recent_sound)
|
||||
var/soundfile = vore_sounds[target.vore_sound]
|
||||
|
||||
@@ -217,6 +217,13 @@
|
||||
/obj/item/clothing/gloves/fluff/morsleeves,
|
||||
/obj/item/clothing/under/fluff/morunder)
|
||||
|
||||
// Mewchild: Phi Vietsi
|
||||
/obj/item/weapon/storage/box/fluff/vietsi
|
||||
name = "Phi's Personal Items"
|
||||
desc = "A small box containing Phi's small things"
|
||||
has_items = list(
|
||||
/obj/item/clothing/accessory/medal/bronze_heart,
|
||||
/obj/item/clothing/gloves/ring/seal/signet/fluff/vietsi)
|
||||
|
||||
/*
|
||||
Swimsuits, for general use, to avoid arriving to work with your swimsuit.
|
||||
|
||||
@@ -1680,9 +1680,10 @@ Departamental Swimsuits, for general use
|
||||
|
||||
//Mewchild: Phi Vietsi
|
||||
/obj/item/clothing/gloves/ring/seal/signet/fluff/vietsi
|
||||
name = "signet ring"
|
||||
desc = "A signet ring carved from the bones of something long extinct, as a ward against bad luck."
|
||||
|
||||
name = "Phi Vietsi's Bone Signet Ring"
|
||||
desc = "A signet ring belonging to Phi Vietsi, carved from the bones of something long extinct, as a ward against bad luck."
|
||||
var/signet_name = "Phi Vietsi"
|
||||
|
||||
icon = 'icons/vore/custom_clothes_vr.dmi'
|
||||
icon_state = "vietsi_ring"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user