Merge remote-tracking branch 'upstream/master'
This commit is contained in:
@@ -714,7 +714,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)
|
||||
|
||||
AI_Interact = !AI_Interact
|
||||
if(mob && IsAdminGhost(mob))
|
||||
mob.has_unlimited_silicon_privilege = AI_Interact
|
||||
mob.silicon_privileges = AI_Interact ? ALL : NONE
|
||||
|
||||
log_admin("[key_name(usr)] has [AI_Interact ? "activated" : "deactivated"] Admin AI Interact")
|
||||
message_admins("[key_name_admin(usr)] has [AI_Interact ? "activated" : "deactivated"] their AI interaction")
|
||||
|
||||
@@ -14,7 +14,8 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
var/list/objectives = list()
|
||||
var/antag_memory = ""//These will be removed with antag datum
|
||||
var/antag_moodlet //typepath of moodlet that the mob will gain with their status
|
||||
var/can_hijack = HIJACK_NEUTRAL //If these antags are alone on shuttle hijack happens.
|
||||
/// If above 0, this is the multiplier for the speed at which we hijack the shuttle. Do not directly read, use hijack_speed().
|
||||
var/hijack_speed = 0
|
||||
|
||||
//Antag panel properties
|
||||
var/show_in_antagpanel = TRUE //This will hide adding this antag type in antag panel, use only for internal subtypes that shouldn't be added directly but still show if possessed by mind
|
||||
@@ -229,6 +230,13 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
return
|
||||
antag_memory = new_memo
|
||||
|
||||
/// Gets how fast we can hijack the shuttle, return 0 for can not hijack. Defaults to hijack_speed var, override for custom stuff like buffing hijack speed for hijack objectives or something.
|
||||
/datum/antagonist/proc/hijack_speed()
|
||||
var/datum/objective/hijack/H = locate() in objectives
|
||||
if(!isnull(H?.hijack_speed_override))
|
||||
return H.hijack_speed_override
|
||||
return hijack_speed
|
||||
|
||||
//This one is created by admin tools for custom objectives
|
||||
/datum/antagonist/custom
|
||||
antagpanel_category = "Custom"
|
||||
|
||||
@@ -286,10 +286,10 @@
|
||||
var/mob/living/L = owner.current
|
||||
level_bloodcost = maxBloodVolume * 0.2
|
||||
//If the blood volume of the bloodsucker is lower than the cost to level up, return and inform the bloodsucker
|
||||
|
||||
|
||||
//TODO: Make this into a radial, or perhaps a tgui next UI
|
||||
// Purchase Power Prompt
|
||||
var/list/options = list()
|
||||
var/list/options = list()
|
||||
for(var/pickedpower in typesof(/datum/action/bloodsucker))
|
||||
var/datum/action/bloodsucker/power = pickedpower
|
||||
// If I don't own it, and I'm allowed to buy it.
|
||||
|
||||
@@ -170,7 +170,7 @@
|
||||
// Warn Feeder about Witnesses...
|
||||
var/was_unnoticed = TRUE
|
||||
for(var/mob/living/M in viewers(notice_range, owner))
|
||||
if(M != owner && M != target && iscarbon(M) && M.mind && !M.has_unlimited_silicon_privilege && !M.eye_blind && !M.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
|
||||
if(M != owner && M != target && iscarbon(M) && M.mind && !M.silicon_privileges && !M.eye_blind && !M.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
|
||||
was_unnoticed = FALSE
|
||||
break
|
||||
if(was_unnoticed)
|
||||
@@ -28,9 +28,9 @@
|
||||
to_chat(owner, "<span class='warning'>Your coffin has been destroyed!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
|
||||
/datum/action/bloodsucker/gohome/proc/flicker_lights(var/flicker_range, var/beat_volume)
|
||||
for(var/obj/machinery/light/L in view(flicker_range, get_turf(owner)))
|
||||
for(var/obj/machinery/light/L in view(flicker_range, get_turf(owner)))
|
||||
playsound(get_turf(owner), 'sound/effects/singlebeat.ogg', beat_volume, 1)
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
flicker_lights(4, 40)
|
||||
sleep(50)
|
||||
flicker_lights(4, 60)
|
||||
for(var/obj/machinery/light/L in view(6, get_turf(owner)))
|
||||
for(var/obj/machinery/light/L in view(6, get_turf(owner)))
|
||||
L.flicker(5)
|
||||
playsound(get_turf(owner), 'sound/effects/singlebeat.ogg', 60, 1)
|
||||
// ( STEP TWO: Lights OFF? )
|
||||
@@ -56,7 +56,7 @@
|
||||
if(!owner)
|
||||
return
|
||||
// SEEN?: (effects ONLY if there are witnesses! Otherwise you just POOF)
|
||||
|
||||
|
||||
var/am_seen = FALSE // Do Effects (seen by anyone)
|
||||
var/drop_item = FALSE // Drop Stuff (seen by non-vamp)
|
||||
if(isturf(owner.loc)) // Only check if I'm not in a Locker or something.
|
||||
@@ -65,7 +65,7 @@
|
||||
if(T && T.lighting_object && T.get_lumcount()>= 0.1)
|
||||
// B) Check for Viewers
|
||||
for(var/mob/living/M in viewers(get_turf(owner)))
|
||||
if(M != owner && isliving(M) && M.mind && !M.has_unlimited_silicon_privilege && !M.eye_blind) // M.client <--- add this in after testing!
|
||||
if(M != owner && isliving(M) && M.mind && !M.silicon_privileges && !M.eye_blind) // M.client <--- add this in after testing!
|
||||
am_seen = TRUE
|
||||
if (!M.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
|
||||
drop_item = TRUE
|
||||
@@ -95,12 +95,12 @@
|
||||
puff.effect_type = /obj/effect/particle_effect/smoke/vampsmoke
|
||||
puff.set_up(3, 0, get_turf(owner))
|
||||
puff.start()
|
||||
|
||||
|
||||
//STEP FIVE: Create animal at prev location
|
||||
var/mob/living/simple_animal/SA = pick(/mob/living/simple_animal/mouse,/mob/living/simple_animal/mouse,/mob/living/simple_animal/mouse, /mob/living/simple_animal/hostile/retaliate/bat) //prob(300) /mob/living/simple_animal/mouse,
|
||||
new SA (owner.loc)
|
||||
// TELEPORT: Move to Coffin & Close it!
|
||||
do_teleport(owner, bloodsuckerdatum.coffin, no_effects = TRUE, forced = TRUE, channel = TELEPORT_CHANNEL_QUANTUM)
|
||||
do_teleport(owner, bloodsuckerdatum.coffin, no_effects = TRUE, forced = TRUE, channel = TELEPORT_CHANNEL_QUANTUM)
|
||||
user.resting = TRUE
|
||||
user.Stun(30,1)
|
||||
// CLOSE LID: If fail, force me in.
|
||||
@@ -112,4 +112,4 @@
|
||||
bloodsuckerdatum.coffin.update_icon()
|
||||
// Lock Coffin
|
||||
bloodsuckerdatum.coffin.LockMe(owner)
|
||||
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
message_Trigger = ""//"Whom will you subvert to your will?"
|
||||
bloodsucker_can_buy = TRUE
|
||||
must_be_capacitated = TRUE
|
||||
var/list/hit //current hit, set while power is in use as we can't pass the list as an extra calling argument in registersignal.
|
||||
/// If set, uses this speed in deciseconds instead of world.tick_lag
|
||||
var/speed_override
|
||||
|
||||
/datum/action/bloodsucker/targeted/haste/CheckCanUse(display_error)
|
||||
. = ..()
|
||||
@@ -43,43 +46,46 @@
|
||||
return TRUE
|
||||
|
||||
/datum/action/bloodsucker/targeted/haste/FireTargetedPower(atom/A)
|
||||
// set waitfor = FALSE <---- DONT DO THIS!We WANT this power to hold up ClickWithPower(), so that we can unlock the power when it's done.
|
||||
// This is a non-async proc to make sure the power is "locked" until this finishes.
|
||||
hit = list()
|
||||
RegisterSignal(owner, COMSIG_MOVABLE_MOVED, .proc/on_move)
|
||||
var/mob/living/user = owner
|
||||
var/turf/T = isturf(A) ? A : get_turf(A)
|
||||
// Pulled? Not anymore.
|
||||
owner.pulledby = null
|
||||
// Step One: Heatseek toward Target's Turf
|
||||
walk_to(owner, T, 0, 0.01, 20) // NOTE: this runs in the background! to cancel it, you need to use walk(owner.current,0), or give them a new path.
|
||||
user.pulledby?.stop_pulling()
|
||||
// Go to target turf
|
||||
// DO NOT USE WALK TO.
|
||||
playsound(get_turf(owner), 'sound/weapons/punchmiss.ogg', 25, 1, -1)
|
||||
var/safety = 20
|
||||
while(get_turf(owner) != T && safety > 0 && !(isliving(target) && target.Adjacent(owner)))
|
||||
user.canmove = FALSE //Dont move while doing the thing, or itll break
|
||||
safety --
|
||||
// Did I get knocked down?
|
||||
if(owner && owner.incapacitated(ignore_restraints=TRUE, ignore_grab=TRUE))// owner.incapacitated())
|
||||
// We're gonna cancel. But am I on the ground? Spin me!
|
||||
if(user.resting)
|
||||
var/send_dir = get_dir(owner, T)
|
||||
new /datum/forced_movement(owner, get_ranged_target_turf(owner, send_dir, 1), 1, FALSE)
|
||||
owner.spin(10)
|
||||
var/safety = get_dist(user, T) * 3 + 1
|
||||
var/consequetive_failures = 0
|
||||
var/speed = isnull(speed_override)? world.tick_lag : speed_override
|
||||
while(--safety && (get_turf(user) != T))
|
||||
var/success = step_towards(user, T) //This does not try to go around obstacles.
|
||||
if(!success)
|
||||
success = step_to(user, T) //this does
|
||||
if(!success)
|
||||
if(++consequetive_failures >= 3) //if 3 steps don't work
|
||||
break //just stop
|
||||
else
|
||||
consequetive_failures = 0
|
||||
if(user.resting)
|
||||
user.setDir(turn(user.dir, 90)) //down? spin2win :^)
|
||||
if(user.incapacitated(ignore_restraints = TRUE, ignore_grab = TRUE)) //actually down? stop.
|
||||
break
|
||||
// Spin/Stun people we pass.
|
||||
//var/mob/living/newtarget = locate(/mob/living) in oview(1, owner)
|
||||
var/list/mob/living/foundtargets = list()
|
||||
for(var/mob/living/newtarget in oview(1, owner))
|
||||
if (newtarget && newtarget != target && !(newtarget in foundtargets))//!newtarget.IsKnockdown())
|
||||
if (rand(0, 5) < level_current)
|
||||
playsound(get_turf(newtarget), "sound/weapons/punch[rand(1,4)].ogg", 15, 1, -1)
|
||||
newtarget.Knockdown(10 + level_current * 5)
|
||||
if(newtarget.IsStun())
|
||||
newtarget.spin(10,1)
|
||||
if (rand(0,4))
|
||||
newtarget.drop_all_held_items()
|
||||
foundtargets += newtarget
|
||||
sleep(1)
|
||||
if(user)
|
||||
user.update_canmove() //Let the poor guy move again
|
||||
if(success) //don't sleep if we failed to move.
|
||||
sleep(speed)
|
||||
UnregisterSignal(owner, COMSIG_MOVABLE_MOVED)
|
||||
hit = null
|
||||
user.update_canmove()
|
||||
|
||||
/datum/action/bloodsucker/targeted/haste/DeactivatePower(mob/living/user = owner, mob/living/target)
|
||||
..() // activate = FALSE
|
||||
user.update_canmove()
|
||||
|
||||
/datum/action/bloodsucker/targeted/haste/proc/on_move()
|
||||
for(var/mob/living/L in dview(1, get_turf(owner)))
|
||||
if(!hit[L] && (L != owner))
|
||||
hit[L] = TRUE
|
||||
playsound(L, "sound/weapons/punch[rand(1,4)].ogg", 15, 1, -1)
|
||||
L.Knockdown(10 + level_current * 5, override_hardstun = 0.1)
|
||||
L.spin(10, 1)
|
||||
@@ -54,8 +54,8 @@
|
||||
REMOVE_TRAIT(user, TRAIT_VIRUSIMMUNE, "bloodsucker")
|
||||
var/obj/item/organ/heart/vampheart/H = user.getorganslot(ORGAN_SLOT_HEART)
|
||||
var/obj/item/organ/eyes/vassal/bloodsucker/E = user.getorganslot(ORGAN_SLOT_EYES)
|
||||
E.flash_protect = 0
|
||||
|
||||
E.flash_protect = 0
|
||||
|
||||
// WE ARE ALIVE! //
|
||||
bloodsuckerdatum.poweron_masquerade = TRUE
|
||||
while(bloodsuckerdatum && ContinueActive(user))
|
||||
@@ -5,7 +5,6 @@
|
||||
var/special_role = ROLE_BROTHER
|
||||
var/datum/team/brother_team/team
|
||||
antag_moodlet = /datum/mood_event/focused
|
||||
can_hijack = HIJACK_HIJACKER
|
||||
|
||||
/datum/antagonist/brother/create_team(datum/team/brother_team/new_team)
|
||||
if(!new_team)
|
||||
|
||||
@@ -120,7 +120,7 @@
|
||||
hierophant_network.Grant(current)
|
||||
current.throw_alert("clockinfo", /obj/screen/alert/clockwork/infodump)
|
||||
var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar
|
||||
if(G.active && ishuman(current))
|
||||
if(G && G.active && ishuman(current))
|
||||
current.add_overlay(mutable_appearance('icons/effects/genetics.dmi', "servitude", -MUTATIONS_LAYER))
|
||||
|
||||
/datum/antagonist/clockcult/remove_innate_effects(mob/living/mob_override)
|
||||
@@ -174,9 +174,12 @@
|
||||
log_admin("[key_name(admin)] has made [new_owner.current] into a servant of Ratvar.")
|
||||
|
||||
/datum/antagonist/clockcult/admin_remove(mob/user)
|
||||
remove_servant_of_ratvar(owner.current, TRUE)
|
||||
message_admins("[key_name_admin(user)] has removed clockwork servant status from [owner.current].")
|
||||
log_admin("[key_name(user)] has removed clockwork servant status from [owner.current].")
|
||||
var/mob/target = owner.current
|
||||
if(!target)
|
||||
return
|
||||
remove_servant_of_ratvar(target, TRUE)
|
||||
message_admins("[key_name_admin(user)] has removed clockwork servant status from [target].")
|
||||
log_admin("[key_name(user)] has removed clockwork servant status from [target].")
|
||||
|
||||
/datum/antagonist/clockcult/get_admin_commands()
|
||||
. = ..()
|
||||
|
||||
@@ -5,49 +5,49 @@ is currently following.
|
||||
*/
|
||||
|
||||
GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
new /datum/disease_ability/action/cough,
|
||||
new /datum/disease_ability/action/sneeze,
|
||||
new /datum/disease_ability/action/infect,
|
||||
new /datum/disease_ability/symptom/mild/cough,
|
||||
new /datum/disease_ability/symptom/mild/sneeze,
|
||||
new /datum/disease_ability/symptom/medium/shedding,
|
||||
new /datum/disease_ability/symptom/medium/beard,
|
||||
new /datum/disease_ability/symptom/medium/hallucigen,
|
||||
new /datum/disease_ability/symptom/medium/choking,
|
||||
new /datum/disease_ability/symptom/medium/confusion,
|
||||
new /datum/disease_ability/symptom/medium/vomit,
|
||||
new /datum/disease_ability/symptom/medium/voice_change,
|
||||
new /datum/disease_ability/symptom/medium/visionloss,
|
||||
new /datum/disease_ability/symptom/medium/deafness,
|
||||
new /datum/disease_ability/symptom/powerful/narcolepsy,
|
||||
new /datum/disease_ability/symptom/medium/fever,
|
||||
new /datum/disease_ability/symptom/medium/shivering,
|
||||
new /datum/disease_ability/symptom/medium/headache,
|
||||
new /datum/disease_ability/symptom/medium/nano_boost,
|
||||
new /datum/disease_ability/symptom/medium/nano_destroy,
|
||||
new /datum/disease_ability/symptom/medium/viraladaptation,
|
||||
new /datum/disease_ability/symptom/medium/viralevolution,
|
||||
new /datum/disease_ability/symptom/medium/vitiligo,
|
||||
new /datum/disease_ability/symptom/medium/revitiligo,
|
||||
new /datum/disease_ability/symptom/medium/itching,
|
||||
new /datum/disease_ability/symptom/medium/heal/weight_loss,
|
||||
new /datum/disease_ability/symptom/medium/heal/sensory_restoration,
|
||||
new /datum/disease_ability/symptom/medium/heal/mind_restoration,
|
||||
new /datum/disease_ability/symptom/powerful/fire,
|
||||
new /datum/disease_ability/symptom/powerful/flesh_eating,
|
||||
// new /datum/disease_ability/symptom/powerful/genetic_mutation,
|
||||
new /datum/disease_ability/symptom/powerful/inorganic_adaptation,
|
||||
new /datum/disease_ability/symptom/powerful/heal/starlight,
|
||||
new /datum/disease_ability/symptom/powerful/heal/oxygen,
|
||||
new /datum/disease_ability/symptom/powerful/heal/chem,
|
||||
new /datum/disease_ability/symptom/powerful/heal/metabolism,
|
||||
new /datum/disease_ability/symptom/powerful/heal/dark,
|
||||
new /datum/disease_ability/symptom/powerful/heal/water,
|
||||
new /datum/disease_ability/symptom/powerful/heal/plasma,
|
||||
new /datum/disease_ability/symptom/powerful/heal/radiation,
|
||||
new /datum/disease_ability/symptom/powerful/heal/coma,
|
||||
new /datum/disease_ability/symptom/powerful/youth
|
||||
))
|
||||
new /datum/disease_ability/action/cough,
|
||||
new /datum/disease_ability/action/sneeze,
|
||||
new /datum/disease_ability/action/infect,
|
||||
new /datum/disease_ability/symptom/mild/cough,
|
||||
new /datum/disease_ability/symptom/mild/sneeze,
|
||||
new /datum/disease_ability/symptom/medium/shedding,
|
||||
new /datum/disease_ability/symptom/medium/beard,
|
||||
new /datum/disease_ability/symptom/medium/hallucigen,
|
||||
new /datum/disease_ability/symptom/medium/choking,
|
||||
new /datum/disease_ability/symptom/medium/confusion,
|
||||
new /datum/disease_ability/symptom/medium/vomit,
|
||||
new /datum/disease_ability/symptom/medium/voice_change,
|
||||
new /datum/disease_ability/symptom/medium/visionloss,
|
||||
new /datum/disease_ability/symptom/medium/deafness,
|
||||
new /datum/disease_ability/symptom/powerful/narcolepsy,
|
||||
new /datum/disease_ability/symptom/medium/fever,
|
||||
new /datum/disease_ability/symptom/medium/shivering,
|
||||
new /datum/disease_ability/symptom/medium/headache,
|
||||
new /datum/disease_ability/symptom/medium/nano_boost,
|
||||
new /datum/disease_ability/symptom/medium/nano_destroy,
|
||||
new /datum/disease_ability/symptom/medium/viraladaptation,
|
||||
new /datum/disease_ability/symptom/medium/viralevolution,
|
||||
new /datum/disease_ability/symptom/medium/disfiguration,
|
||||
new /datum/disease_ability/symptom/medium/polyvitiligo,
|
||||
new /datum/disease_ability/symptom/medium/itching,
|
||||
new /datum/disease_ability/symptom/medium/heal/weight_loss,
|
||||
new /datum/disease_ability/symptom/medium/heal/sensory_restoration,
|
||||
new /datum/disease_ability/symptom/medium/heal/mind_restoration,
|
||||
new /datum/disease_ability/symptom/powerful/fire,
|
||||
new /datum/disease_ability/symptom/powerful/flesh_eating,
|
||||
new /datum/disease_ability/symptom/powerful/genetic_mutation,
|
||||
new /datum/disease_ability/symptom/powerful/inorganic_adaptation,
|
||||
new /datum/disease_ability/symptom/powerful/heal/starlight,
|
||||
new /datum/disease_ability/symptom/powerful/heal/oxygen,
|
||||
new /datum/disease_ability/symptom/powerful/heal/chem,
|
||||
new /datum/disease_ability/symptom/powerful/heal/metabolism,
|
||||
new /datum/disease_ability/symptom/powerful/heal/dark,
|
||||
new /datum/disease_ability/symptom/powerful/heal/water,
|
||||
new /datum/disease_ability/symptom/powerful/heal/plasma,
|
||||
new /datum/disease_ability/symptom/powerful/heal/radiation,
|
||||
new /datum/disease_ability/symptom/powerful/heal/coma,
|
||||
new /datum/disease_ability/symptom/powerful/youth
|
||||
))
|
||||
|
||||
/datum/disease_ability
|
||||
var/name
|
||||
@@ -57,7 +57,7 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
var/short_desc = ""
|
||||
var/long_desc = ""
|
||||
var/stat_block = ""
|
||||
var/threshold_block = list()
|
||||
var/threshold_block = ""
|
||||
var/category = ""
|
||||
|
||||
var/list/symptoms
|
||||
@@ -76,7 +76,7 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
resistance += initial(S.resistance)
|
||||
stage_speed += initial(S.stage_speed)
|
||||
transmittable += initial(S.transmittable)
|
||||
threshold_block += initial(S.threshold_desc)
|
||||
threshold_block += "<br><br>[initial(S.threshold_desc)]"
|
||||
stat_block = "Resistance: [resistance]<br>Stealth: [stealth]<br>Stage Speed: [stage_speed]<br>Transmissibility: [transmittable]<br><br>"
|
||||
if(symptoms.len == 1) //lazy boy's dream
|
||||
name = initial(S.name)
|
||||
@@ -106,10 +106,8 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
for(var/T in symptoms)
|
||||
var/datum/symptom/S = new T()
|
||||
SD.symptoms += S
|
||||
S.OnAdd(SD)
|
||||
if(SD.processing)
|
||||
if(S.Start(SD))
|
||||
S.next_activation = world.time + rand(S.symptom_delay_min * 10, S.symptom_delay_max * 10)
|
||||
S.Start(SD)
|
||||
SD.Refresh()
|
||||
for(var/T in actions)
|
||||
var/datum/action/A = new T()
|
||||
@@ -136,7 +134,6 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
var/datum/symptom/S = locate(T) in SD.symptoms
|
||||
if(S)
|
||||
SD.symptoms -= S
|
||||
S.OnRemove(SD)
|
||||
if(SD.processing)
|
||||
S.End(SD)
|
||||
qdel(S)
|
||||
@@ -296,7 +293,6 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
cost = 8
|
||||
category = "Symptom (Strong+)"
|
||||
|
||||
|
||||
/******MILD******/
|
||||
|
||||
/datum/disease_ability/symptom/mild/cough
|
||||
@@ -377,11 +373,11 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
/datum/disease_ability/symptom/medium/viralevolution
|
||||
symptoms = list(/datum/symptom/viralevolution)
|
||||
|
||||
/datum/disease_ability/symptom/medium/vitiligo
|
||||
symptoms = list(/datum/symptom/vitiligo)
|
||||
/datum/disease_ability/symptom/medium/polyvitiligo
|
||||
symptoms = list(/datum/symptom/polyvitiligo)
|
||||
|
||||
/datum/disease_ability/symptom/medium/revitiligo
|
||||
symptoms = list(/datum/symptom/revitiligo)
|
||||
/datum/disease_ability/symptom/medium/disfiguration
|
||||
symptoms = list(/datum/symptom/disfiguration)
|
||||
|
||||
/datum/disease_ability/symptom/medium/itching
|
||||
symptoms = list(/datum/symptom/itching)
|
||||
@@ -409,11 +405,9 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
/datum/disease_ability/symptom/powerful/flesh_eating
|
||||
symptoms = list(/datum/symptom/flesh_eating)
|
||||
|
||||
/*
|
||||
/datum/disease_ability/symptom/powerful/genetic_mutation
|
||||
symptoms = list(/datum/symptom/genetic_mutation)
|
||||
cost = 8
|
||||
*/
|
||||
|
||||
/datum/disease_ability/symptom/powerful/inorganic_adaptation
|
||||
symptoms = list(/datum/symptom/inorganic_adaptation)
|
||||
@@ -457,4 +451,4 @@ GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
/datum/disease_ability/symptom/powerful/heal/coma
|
||||
symptoms = list(/datum/symptom/heal/coma)
|
||||
short_desc = "Cause victims to fall into a healing coma when hurt."
|
||||
long_desc = "Cause victims to fall into a healing coma when hurt."
|
||||
long_desc = "Cause victims to fall into a healing coma when hurt."
|
||||
@@ -12,7 +12,6 @@
|
||||
var/list/name_source
|
||||
show_in_antagpanel = FALSE
|
||||
antag_moodlet = /datum/mood_event/focused
|
||||
can_hijack = HIJACK_PREVENT
|
||||
|
||||
/datum/antagonist/ert/on_gain()
|
||||
update_name()
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
var/obj/item/claymore/highlander/sword
|
||||
show_in_antagpanel = FALSE
|
||||
show_name_in_check_antagonists = TRUE
|
||||
can_hijack = HIJACK_HIJACKER
|
||||
hijack_speed = 2 //if you kill everyone and actually haev a hand to hijack with, you win??
|
||||
|
||||
/datum/antagonist/highlander/apply_innate_effects(mob/living/mob_override)
|
||||
var/mob/living/L = owner.current || mob_override
|
||||
|
||||
@@ -8,11 +8,6 @@
|
||||
var/give_objectives = TRUE
|
||||
var/give_equipment = TRUE
|
||||
|
||||
/datum/antagonist/ninja/New()
|
||||
if(helping_station)
|
||||
can_hijack = HIJACK_PREVENT
|
||||
. = ..()
|
||||
|
||||
/datum/antagonist/ninja/apply_innate_effects(mob/living/mob_override)
|
||||
var/mob/living/M = mob_override || owner.current
|
||||
update_ninja_icons_added(M)
|
||||
@@ -135,8 +130,6 @@
|
||||
adj = "objectiveless"
|
||||
else
|
||||
return
|
||||
if(helping_station)
|
||||
can_hijack = HIJACK_PREVENT
|
||||
new_owner.assigned_role = ROLE_NINJA
|
||||
new_owner.special_role = ROLE_NINJA
|
||||
new_owner.add_antag_datum(src)
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
var/always_new_team = FALSE //If not assigned a team by default ops will try to join existing ones, set this to TRUE to always create new team.
|
||||
var/send_to_spawnpoint = TRUE //Should the user be moved to default spawnpoint.
|
||||
var/nukeop_outfit = /datum/outfit/syndicate
|
||||
can_hijack = HIJACK_HIJACKER //Alternative way to wipe out the station.
|
||||
|
||||
/datum/antagonist/nukeop/proc/update_synd_icons_added(mob/living/M)
|
||||
var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS]
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
show_in_antagpanel = FALSE
|
||||
var/datum/objective/mission
|
||||
var/datum/team/ert/ert_team
|
||||
can_hijack = HIJACK_PREVENT
|
||||
|
||||
/datum/antagonist/official/greet()
|
||||
to_chat(owner, "<B><font size=3 color=red>You are a CentCom Official.</font></B>")
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
var/should_give_codewords = TRUE
|
||||
var/should_equip = TRUE
|
||||
var/traitor_kind = TRAITOR_HUMAN //Set on initial assignment
|
||||
can_hijack = HIJACK_HIJACKER
|
||||
hijack_speed = 0.5 //10 seconds per hijack stage by default
|
||||
|
||||
/datum/antagonist/traitor/on_gain()
|
||||
if(owner.current && isAI(owner.current))
|
||||
@@ -60,6 +60,7 @@
|
||||
message = GLOB.syndicate_code_response_regex.Replace(message, "<span class='red'>$1</span>")
|
||||
hearing_args[HEARING_RAW_MESSAGE] = message
|
||||
|
||||
// needs to be refactored to base /datum/antagonist sometime..
|
||||
/datum/antagonist/traitor/proc/add_objective(datum/objective/O)
|
||||
objectives += O
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
name = "Wishgranter Avatar"
|
||||
show_in_antagpanel = FALSE
|
||||
show_name_in_check_antagonists = TRUE
|
||||
can_hijack = HIJACK_HIJACKER
|
||||
|
||||
/datum/antagonist/wishgranter/proc/forge_objectives()
|
||||
var/datum/objective/hijack/hijack = new
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
var/move_to_lair = TRUE
|
||||
var/outfit_type = /datum/outfit/wizard
|
||||
var/wiz_age = WIZARD_AGE_MIN /* Wizards by nature cannot be too young. */
|
||||
can_hijack = HIJACK_HIJACKER
|
||||
|
||||
/datum/antagonist/wizard/on_gain()
|
||||
register()
|
||||
|
||||
@@ -229,7 +229,7 @@
|
||||
. += "<span class='notice'>Alt-click to [locked ? "unlock" : "lock"] the interface.</span>"
|
||||
|
||||
/obj/machinery/airalarm/ui_status(mob/user)
|
||||
if(user.has_unlimited_silicon_privilege && aidisabled)
|
||||
if(hasSiliconAccessInArea(user) && aidisabled)
|
||||
to_chat(user, "AI control has been disabled.")
|
||||
else if(!shorted)
|
||||
return ..()
|
||||
@@ -245,7 +245,7 @@
|
||||
/obj/machinery/airalarm/ui_data(mob/user)
|
||||
var/data = list(
|
||||
"locked" = locked,
|
||||
"siliconUser" = user.has_unlimited_silicon_privilege || hasSiliconAccessInArea(user),
|
||||
"siliconUser" = hasSiliconAccessInArea(user),
|
||||
"emagged" = (obj_flags & EMAGGED ? 1 : 0),
|
||||
"danger_level" = danger_level,
|
||||
)
|
||||
@@ -288,7 +288,7 @@
|
||||
"danger_level" = cur_tlv.get_danger_level(environment.gases[gas_id] * partial_pressure)
|
||||
))
|
||||
|
||||
if(!locked || user.has_unlimited_silicon_privilege || hasSiliconAccessInArea(user))
|
||||
if(!locked || hasSiliconAccessInArea(user, PRIVILEDGES_SILICON|PRIVILEDGES_DRONE))
|
||||
data["vents"] = list()
|
||||
for(var/id_tag in A.air_vent_names)
|
||||
var/long_name = A.air_vent_names[id_tag]
|
||||
@@ -368,12 +368,14 @@
|
||||
/obj/machinery/airalarm/ui_act(action, params)
|
||||
if(..() || buildstage != 2)
|
||||
return
|
||||
if((locked && !usr.has_unlimited_silicon_privilege && !hasSiliconAccessInArea(usr)) || (usr.has_unlimited_silicon_privilege && aidisabled))
|
||||
var/silicon_access = hasSiliconAccessInArea(usr)
|
||||
var/bot_priviledges = silicon_access || (usr.silicon_privileges & PRIVILEDGES_DRONE)
|
||||
if((locked && !bot_priviledges) || (silicon_access && aidisabled))
|
||||
return
|
||||
var/device_id = params["id_tag"]
|
||||
switch(action)
|
||||
if("lock")
|
||||
if(usr.has_unlimited_silicon_privilege && !wires.is_cut(WIRE_IDSCAN))
|
||||
if(bot_priviledges && !wires.is_cut(WIRE_IDSCAN))
|
||||
locked = !locked
|
||||
. = TRUE
|
||||
if("power", "toggle_filter", "widenet", "scrubbing")
|
||||
|
||||
@@ -24,13 +24,13 @@
|
||||
export_types = list(/obj/structure/ore_box)
|
||||
|
||||
/datum/export/large/crate/wood
|
||||
cost = 140 //
|
||||
cost = 140
|
||||
unit_name = "wooden crate"
|
||||
export_types = list(/obj/structure/closet/crate/wooden)
|
||||
exclude_types = list()
|
||||
|
||||
/datum/export/large/barrel
|
||||
cost = 500 //150 to make meaning proffit of 350
|
||||
cost = 300 //double the wooden cost of a coffin.
|
||||
unit_name = "wooden barrel"
|
||||
export_types = list(/obj/structure/fermenting_barrel)
|
||||
|
||||
@@ -40,19 +40,11 @@
|
||||
export_types = list(/obj/structure/closet/crate/coffin)
|
||||
|
||||
/datum/export/large/reagent_dispenser
|
||||
cost = 100 // +0-400 depending on amount of reagents left
|
||||
var/contents_cost = 400
|
||||
|
||||
/datum/export/large/reagent_dispenser/get_cost(obj/O)
|
||||
var/obj/structure/reagent_dispensers/D = O
|
||||
var/ratio = D.reagents.total_volume / D.reagents.maximum_volume
|
||||
|
||||
return ..() + round(contents_cost * ratio)
|
||||
cost = 100
|
||||
|
||||
/datum/export/large/reagent_dispenser/water
|
||||
unit_name = "watertank"
|
||||
export_types = list(/obj/structure/reagent_dispensers/watertank)
|
||||
contents_cost = 200
|
||||
|
||||
/datum/export/large/reagent_dispenser/fuel
|
||||
unit_name = "fueltank"
|
||||
@@ -60,7 +52,6 @@
|
||||
|
||||
/datum/export/large/reagent_dispenser/beer
|
||||
unit_name = "beer keg"
|
||||
contents_cost = 700
|
||||
export_types = list(/obj/structure/reagent_dispensers/beerkeg)
|
||||
|
||||
/datum/export/large/pipedispenser
|
||||
|
||||
@@ -65,11 +65,6 @@
|
||||
material_id = MAT_TITANIUM
|
||||
message = "cm3 of titanium"
|
||||
|
||||
/datum/export/material/plastitanium
|
||||
cost = 165 // plasma + titanium costs
|
||||
material_id = MAT_TITANIUM // code can only check for one material_id; plastitanium is half plasma, half titanium
|
||||
message = "cm3 of plastitanium"
|
||||
|
||||
/datum/export/material/plastic
|
||||
cost = 5
|
||||
material_id = MAT_PLASTIC
|
||||
|
||||
@@ -67,6 +67,16 @@
|
||||
message = "of plasteel"
|
||||
export_types = list(/obj/item/stack/sheet/plasteel)
|
||||
|
||||
/datum/export/material/plastitanium
|
||||
cost = 165 // plasma + titanium costs
|
||||
export_types = list(/obj/item/stack/sheet/mineral/plastitanium)
|
||||
message = "of plastitanium"
|
||||
|
||||
/datum/export/material/plastitanium_glass
|
||||
cost = 168 // plasma + titanium + glass costs
|
||||
export_types = list(/obj/item/stack/sheet/plastitaniumglass)
|
||||
message = "of plastitanium glass"
|
||||
|
||||
// 1 glass + 0.5 metal, cost is rounded up.
|
||||
/datum/export/stack/rglass
|
||||
cost = 6
|
||||
|
||||
@@ -199,6 +199,31 @@
|
||||
unit_name = "advanced shotgun shell"
|
||||
export_types = list(/obj/item/ammo_casing/shotgun/dragonsbreath, /obj/item/ammo_casing/shotgun/meteorslug, /obj/item/ammo_casing/shotgun/pulseslug, /obj/item/ammo_casing/shotgun/frag12, /obj/item/ammo_casing/shotgun/ion, /obj/item/ammo_casing/shotgun/laserslug)
|
||||
|
||||
/////////////////////////
|
||||
//Bow and Arrows/////////
|
||||
/////////////////////////
|
||||
|
||||
/datum/export/weapon/bows
|
||||
cost = 450
|
||||
unit_name = "bow"
|
||||
export_types = list(/obj/item/gun/ballistic/bow)
|
||||
|
||||
/datum/export/weapon/arrows
|
||||
cost = 150
|
||||
unit_name = "arrow"
|
||||
export_types = list(/obj/item/ammo_casing/caseless/arrow, /obj/item/ammo_casing/caseless/arrow/bone, /obj/item/ammo_casing/caseless/arrow/ashen)
|
||||
|
||||
/datum/export/weapon/bow_teaching
|
||||
cost = 500
|
||||
unit_name = "stone tablets"
|
||||
export_types = list(/obj/item/book/granter/crafting_recipe/bone_bow)
|
||||
|
||||
/datum/export/weapon/quiver
|
||||
cost = 100
|
||||
unit_name = "quiver"
|
||||
export_types = list(/obj/item/storage/belt/quiver)
|
||||
|
||||
|
||||
/////////////////////////
|
||||
//The Traitor Sell Outs//
|
||||
/////////////////////////
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
var/canBeacon = beacon && (isturf(beacon.loc) || ismob(beacon.loc))//is the beacon in a valid location?
|
||||
var/list/data = list()
|
||||
data["locked"] = locked//swipe an ID to unlock
|
||||
data["siliconUser"] = user.has_unlimited_silicon_privilege
|
||||
data["siliconUser"] = hasSiliconAccessInArea(user)
|
||||
data["beaconzone"] = beacon ? get_area(beacon) : ""//where is the beacon located? outputs in the tgui
|
||||
data["usingBeacon"] = usingBeacon //is the mode set to deliver to the beacon or the cargobay?
|
||||
data["canBeacon"] = !usingBeacon || canBeacon //is the mode set to beacon delivery, and is the beacon in a valid location?
|
||||
@@ -183,6 +183,7 @@
|
||||
LZ = pick(empty_turfs)
|
||||
if (SO.pack.cost <= SSshuttle.points && LZ)//we need to call the cost check again because of the CHECK_TICK call
|
||||
SSshuttle.points -= SO.pack.cost
|
||||
SSblackbox.record_feedback("nested tally", "cargo_imports", 1, list("[SO.pack.cost]", "[SO.pack.name]"))
|
||||
new /obj/effect/abstract/DPtarget(LZ, podType, SO)
|
||||
. = TRUE
|
||||
update_icon()
|
||||
@@ -196,6 +197,7 @@
|
||||
CHECK_TICK
|
||||
if(empty_turfs && empty_turfs.len)
|
||||
SSshuttle.points -= SO.pack.cost * (0.72*MAX_EMAG_ROCKETS)
|
||||
SSblackbox.record_feedback("nested tally", "cargo_imports", MAX_EMAG_ROCKETS, list("[SO.pack.cost * 0.72]", "[SO.pack.name]"))
|
||||
SO.generateRequisition(get_turf(src))
|
||||
for(var/i in 1 to MAX_EMAG_ROCKETS)
|
||||
var/LZ = pick(empty_turfs)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
var/name = "Crate"
|
||||
var/group = ""
|
||||
var/hidden = FALSE //Aka emag only
|
||||
var/contraband = FALSE //Hacking the console with a multitool
|
||||
var/contraband = FALSE //Requires a hacked console UNLESS DropPodOnly = TRUE, in which case it requires an emag
|
||||
var/cost = 700 // Minimum cost, or infinite points are possible.
|
||||
var/access = FALSE //What access does the Crate itself need?
|
||||
var/access_any = FALSE //Do we care about access?
|
||||
|
||||
@@ -178,7 +178,7 @@
|
||||
/datum/supply_pack/security/armory/russian
|
||||
name = "Russian Surplus Crate"
|
||||
desc = "Hello Comrade, we have the most modern russian military equipment the black market can offer, for the right price of course. Sadly we couldnt remove the lock so it requires Armory access to open."
|
||||
cost = 5000
|
||||
cost = 7500
|
||||
contraband = TRUE
|
||||
contains = list(/obj/item/reagent_containers/food/snacks/rationpack,
|
||||
/obj/item/ammo_box/a762,
|
||||
@@ -192,12 +192,11 @@
|
||||
/obj/item/clothing/mask/russian_balaclava,
|
||||
/obj/item/clothing/head/helmet/rus_ushanka,
|
||||
/obj/item/clothing/suit/armor/vest/russian_coat,
|
||||
/obj/item/gun/ballistic/shotgun/boltaction,
|
||||
/obj/item/gun/ballistic/shotgun/boltaction)
|
||||
crate_name = "surplus military crate"
|
||||
|
||||
/datum/supply_pack/security/armory/russian/fill(obj/structure/closet/crate/C)
|
||||
for(var/i in 1 to 10)
|
||||
for(var/i in 1 to 5)
|
||||
var/item = pick(contains)
|
||||
new item(C)
|
||||
|
||||
@@ -218,7 +217,7 @@
|
||||
crate_name = "swat crate"
|
||||
|
||||
/datum/supply_pack/security/armory/swattasers //Lesser AEG tbh
|
||||
name = "SWAT tatical tasers Crate"
|
||||
name = "SWAT tactical tasers Crate"
|
||||
desc = "Contains two tactical energy gun, these guns are able to tase, disable and lethal as well as hold a seclight. Requires Armory access to open."
|
||||
cost = 7000
|
||||
contains = list(/obj/item/gun/energy/e_gun/stun,
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
/obj/item/toy/cards/deck/syndicate,
|
||||
/obj/item/reagent_containers/food/drinks/bottle/absinthe,
|
||||
/obj/item/clothing/under/syndicate/tacticool,
|
||||
/obj/item/clothing/under/syndicate/skirt,
|
||||
/obj/item/clothing/under/syndicate,
|
||||
/obj/item/suppressor,
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_syndicate,
|
||||
|
||||
@@ -130,7 +130,7 @@
|
||||
|
||||
/datum/supply_pack/emergency/bomb
|
||||
name = "Explosive Emergency Crate"
|
||||
desc = "Science gone bonkers? Beeping behind the airlock? Buy now and be the hero the station des... I mean needs! (Time not included.)"
|
||||
desc = "Science gone bonkers? Beeping behind the airlock? Buy now and become the hero the station des... I mean needs! Time not included, but a full bomb suit and hood, as well as a mask and defusal kit are! Non-Nuclear ordnances only."
|
||||
cost = 1500
|
||||
contains = list(/obj/item/clothing/head/bomb_hood,
|
||||
/obj/item/clothing/suit/bomb_suit,
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
/obj/item/clothing/mask/gas,
|
||||
/obj/item/clothing/suit/space/hardsuit/medical)
|
||||
crate_name = "medical hardsuit"
|
||||
crate_type = /obj/structure/closet/crate/secure/medical
|
||||
|
||||
/datum/supply_pack/medical/supplies
|
||||
name = "Medical Supplies Crate"
|
||||
@@ -125,7 +126,7 @@
|
||||
/obj/item/reagent_containers/medspray/synthflesh,
|
||||
/obj/item/reagent_containers/medspray/sterilizine)
|
||||
crate_name = "medco surgery tools"
|
||||
crate_type = /obj/structure/closet/crate/medical
|
||||
crate_type = /obj/structure/closet/crate/secure/medical
|
||||
|
||||
/datum/supply_pack/medical/surgery
|
||||
name = "Surgical Supplies Crate"
|
||||
|
||||
@@ -193,6 +193,7 @@
|
||||
/obj/item/reagent_containers/food/snacks/meat/slab/bear,
|
||||
/obj/item/reagent_containers/food/snacks/meat/slab/xeno,
|
||||
/obj/item/reagent_containers/food/snacks/meat/slab/spider,
|
||||
/obj/item/reagent_containers/food/snacks/meat/rawcrab,
|
||||
/obj/item/reagent_containers/food/snacks/meat/rawbacon,
|
||||
/obj/item/reagent_containers/food/snacks/spiderleg,
|
||||
/obj/item/reagent_containers/food/snacks/carpmeat,
|
||||
@@ -327,7 +328,7 @@
|
||||
|
||||
/datum/supply_pack/organic/seeds
|
||||
name = "Seeds Crate"
|
||||
desc = "Big things have small beginnings. Contains thirteen different seeds."
|
||||
desc = "Big things have small beginnings. Contains fourteen different seeds."
|
||||
cost = 1250
|
||||
contains = list(/obj/item/seeds/chili,
|
||||
/obj/item/seeds/berry,
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
|
||||
/datum/supply_pack/science/glasswork
|
||||
name = "Glass Blower Kit Crate"
|
||||
desc = "Learn and make glassworks of usefull things for a profit! Contains glassworking tools and blowing rods. Glass not included."
|
||||
desc = "Learn and make glassworks of useful things for a profit! Contains glassworking tools and blowing rods. Glass not included."
|
||||
cost = 1000
|
||||
contains = list(/obj/item/glasswork/glasskit,
|
||||
/obj/item/glasswork/glasskit,
|
||||
@@ -111,9 +111,9 @@
|
||||
/datum/supply_pack/science/nuke_b_gone
|
||||
name = "Nuke Defusal Kit"
|
||||
desc = "Contains set of tools to defuse a nuke."
|
||||
cost = 7500 //Usefull for traitors/nukies that fucked up
|
||||
cost = 7500 //Useful for traitors/nukies that fucked up
|
||||
dangerous = TRUE
|
||||
DropPodOnly = TRUE
|
||||
hidden = TRUE
|
||||
contains = list(/obj/item/nuke_core_container/nt,
|
||||
/obj/item/screwdriver/nuke/nt,
|
||||
/obj/item/paper/guides/nt/nuke_instructions)
|
||||
@@ -194,7 +194,7 @@
|
||||
/datum/supply_pack/science/supermater
|
||||
name = "Supermatter Extraction Tools Crate"
|
||||
desc = "Contains a set of tools to extract a sliver of supermatter. Consult your CE today!"
|
||||
cost = 7500 //Usefull for traitors that fucked up
|
||||
cost = 7500 //Useful for traitors that fucked up
|
||||
hidden = TRUE
|
||||
contains = list(/obj/item/nuke_core_container/supermatter,
|
||||
/obj/item/scalpel/supermatter,
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
desc = "An old russian Minutemen crate, comes with a full russian outfit, a mosin and a stripper clip."
|
||||
contraband = TRUE
|
||||
access = FALSE
|
||||
cost = 5500 //
|
||||
cost = 6500 //
|
||||
contains = list(/obj/item/clothing/suit/armor/navyblue/russian,
|
||||
/obj/item/clothing/shoes/combat,
|
||||
/obj/item/clothing/head/ushanka,
|
||||
|
||||
@@ -737,13 +737,13 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
|
||||
message_admins("<span class='adminnotice'>Proxy Detection: [key_name_admin(src)] IP intel rated [res.intel*100]% likely to be a Proxy/VPN.</span>")
|
||||
ip_intel = res.intel
|
||||
|
||||
/client/Click(atom/object, atom/location, control, params)
|
||||
/client/Click(atom/object, atom/location, control, params, ignore_spam = FALSE)
|
||||
var/ab = FALSE
|
||||
var/list/L = params2list(params)
|
||||
if (object && object == middragatom && L["left"])
|
||||
ab = max(0, 5 SECONDS-(world.time-middragtime)*0.1)
|
||||
var/mcl = CONFIG_GET(number/minute_click_limit)
|
||||
if (!holder && mcl)
|
||||
if (!holder && !ignore_spam && mcl)
|
||||
var/minute = round(world.time, 600)
|
||||
if (!clicklimiter)
|
||||
clicklimiter = new(LIMITER_SIZE)
|
||||
@@ -768,7 +768,7 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
|
||||
return
|
||||
|
||||
var/scl = CONFIG_GET(number/second_click_limit)
|
||||
if (!holder && scl)
|
||||
if (!holder && !ignore_spam && scl)
|
||||
var/second = round(world.time, 10)
|
||||
if (!clicklimiter)
|
||||
clicklimiter = new(LIMITER_SIZE)
|
||||
|
||||
@@ -53,7 +53,8 @@
|
||||
H.adjust_blurriness(1)
|
||||
H.visible_message("<span class='warning'>[H] is creamed by [src]!</span>", "<span class='userdanger'>You've been creamed by [src]!</span>")
|
||||
playsound(H, "desceration", 50, TRUE)
|
||||
reagents.trans_to(H,15) //Cream pie combat
|
||||
if(!H.is_mouth_covered())
|
||||
reagents.trans_to(H,15) //Cream pie combat
|
||||
if(!H.creamed) // one layer at a time
|
||||
H.add_overlay(creamoverlay)
|
||||
H.creamed = TRUE
|
||||
|
||||
@@ -319,7 +319,7 @@
|
||||
/obj/machinery/icecream_vat/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker)
|
||||
if(beaker)
|
||||
beaker.forceMove(drop_location())
|
||||
if(user && Adjacent(user) && !issiliconoradminghost(user))
|
||||
if(user && Adjacent(user) && user.can_hold_items())
|
||||
user.put_in_hands(beaker)
|
||||
if(new_beaker)
|
||||
beaker = new_beaker
|
||||
|
||||
@@ -122,13 +122,10 @@
|
||||
to_chat(usr, "<span class='warning'>Error: Insufficient credits for [prize.equipment_name] on [I]!</span>")
|
||||
flick(icon_deny, src)
|
||||
else
|
||||
if (I.mining_points -= prize.cost)
|
||||
to_chat(usr, "<span class='notice'>[src] clanks to life briefly before vending [prize.equipment_name]!</span>")
|
||||
new prize.equipment_path(src.loc)
|
||||
SSblackbox.record_feedback("nested tally", "mining_equipment_bought", 1, list("[type]", "[prize.equipment_path]"))
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>Error: Transaction failure, please try again later!</span>")
|
||||
flick(icon_deny, src)
|
||||
I.mining_points -= prize.cost
|
||||
to_chat(usr, "<span class='notice'>[src] clanks to life briefly before vending [prize.equipment_name]!</span>")
|
||||
new prize.equipment_path(src.loc)
|
||||
SSblackbox.record_feedback("nested tally", "mining_equipment_bought", 1, list("[type]", "[prize.equipment_path]"))
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>Error: An ID with a registered account is required!</span>")
|
||||
flick(icon_deny, src)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
var/preferred_form = null
|
||||
|
||||
if(IsAdminGhost(src))
|
||||
has_unlimited_silicon_privilege = 1
|
||||
silicon_privileges = ALL
|
||||
|
||||
if(client.prefs.unlock_content)
|
||||
preferred_form = client.prefs.ghost_form
|
||||
|
||||
@@ -834,12 +834,31 @@
|
||||
update_inv_handcuffed()
|
||||
update_hud_handcuffed()
|
||||
|
||||
/mob/living/carbon/proc/can_defib()
|
||||
var/tlimit = DEFIB_TIME_LIMIT * 10
|
||||
var/obj/item/organ/heart = getorgan(/obj/item/organ/heart)
|
||||
if(suiciding || hellbound || HAS_TRAIT(src, TRAIT_HUSK))
|
||||
return
|
||||
if((world.time - timeofdeath) > tlimit)
|
||||
return
|
||||
if((getBruteLoss() >= MAX_REVIVE_BRUTE_DAMAGE) || (getFireLoss() >= MAX_REVIVE_FIRE_DAMAGE))
|
||||
return
|
||||
if(!heart || (heart.organ_flags & ORGAN_FAILING))
|
||||
return
|
||||
var/obj/item/organ/brain/BR = getorgan(/obj/item/organ/brain)
|
||||
if(QDELETED(BR) || BR.brain_death || (BR.organ_flags & ORGAN_FAILING) || suiciding)
|
||||
return
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/fully_heal(admin_revive = FALSE)
|
||||
if(reagents)
|
||||
reagents.clear_reagents()
|
||||
var/obj/item/organ/brain/B = getorgan(/obj/item/organ/brain)
|
||||
if(B)
|
||||
B.brain_death = FALSE
|
||||
for(var/O in internal_organs)
|
||||
var/obj/item/organ/organ = O
|
||||
organ.setOrganDamage(0)
|
||||
for(var/thing in diseases)
|
||||
var/datum/disease/D = thing
|
||||
if(D.severity != DISEASE_SEVERITY_POSITIVE)
|
||||
@@ -852,7 +871,8 @@
|
||||
qdel(R)
|
||||
update_handcuffed()
|
||||
if(reagents)
|
||||
reagents.addiction_list = list()
|
||||
for(var/addi in reagents.addiction_list)
|
||||
reagents.remove_addiction(addi)
|
||||
cure_all_traumas(TRAUMA_RESILIENCE_MAGIC)
|
||||
..()
|
||||
// heal ears after healing traits, since ears check TRAIT_DEAF trait
|
||||
@@ -987,3 +1007,6 @@
|
||||
return TRUE
|
||||
if(isclothing(wear_mask) && (wear_mask.clothing_flags & SCAN_REAGENTS))
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/can_hold_items()
|
||||
return TRUE
|
||||
|
||||
@@ -803,7 +803,7 @@
|
||||
hud_used.staminas?.update_icon_state()
|
||||
hud_used.staminabuffer?.update_icon_state()
|
||||
|
||||
/mob/living/carbon/human/fully_heal(admin_revive = 0)
|
||||
/mob/living/carbon/human/fully_heal(admin_revive = FALSE)
|
||||
if(admin_revive)
|
||||
regenerate_limbs()
|
||||
regenerate_organs()
|
||||
@@ -823,9 +823,6 @@
|
||||
. += dna.species.check_weakness(weapon, attacker)
|
||||
|
||||
/mob/living/carbon/human/is_literate()
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/human/can_hold_items()
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/human/update_gravity(has_gravity,override = 0)
|
||||
@@ -834,7 +831,7 @@
|
||||
..()
|
||||
|
||||
/mob/living/carbon/human/vomit(lost_nutrition = 10, blood = 0, stun = 1, distance = 0, message = 1, toxic = 0)
|
||||
if(blood && (NOBLOOD in dna.species.species_traits))
|
||||
if(blood && dna?.species && (NOBLOOD in dna.species.species_traits))
|
||||
if(message)
|
||||
visible_message("<span class='warning'>[src] dry heaves!</span>", \
|
||||
"<span class='userdanger'>You try to throw up, but there's nothing in your stomach!</span>")
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/checkarmor(obj/item/bodypart/def_zone, d_type)
|
||||
if(!d_type)
|
||||
if(!d_type || !def_zone)
|
||||
return 0
|
||||
var/protection = 0
|
||||
var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform, back, gloves, shoes, belt, s_store, glasses, ears, wear_id, wear_neck) //Everything but pockets. Pockets are l_store and r_store. (if pockets were allowed, putting something armored, gloves or hats for example, would double up on the armor)
|
||||
|
||||
@@ -135,7 +135,7 @@
|
||||
RegisterSignal(owner, COMSIG_CLICK_SHIFT, .proc/examinate_check)
|
||||
RegisterSignal(src, COMSIG_ATOM_HEARER_IN_VIEW, .proc/include_owner)
|
||||
RegisterSignal(owner, COMSIG_LIVING_REGENERATE_LIMBS, .proc/unlist_head)
|
||||
RegisterSignal(owner, COMSIG_LIVING_FULLY_HEAL, .proc/retrieve_head)
|
||||
RegisterSignal(owner, COMSIG_LIVING_REVIVE, .proc/retrieve_head)
|
||||
|
||||
/obj/item/dullahan_relay/proc/examinate_check(atom/source, mob/user)
|
||||
if(user.client.eye == src)
|
||||
@@ -148,8 +148,9 @@
|
||||
/obj/item/dullahan_relay/proc/unlist_head(datum/source, noheal = FALSE, list/excluded_limbs)
|
||||
excluded_limbs |= BODY_ZONE_HEAD // So we don't gib when regenerating limbs.
|
||||
|
||||
/obj/item/dullahan_relay/proc/retrieve_head(datum/source, admin_revive = FALSE)
|
||||
if(admin_revive) //retrieving the owner's head for ahealing purposes.
|
||||
//Retrieving the owner's head for better ahealing.
|
||||
/obj/item/dullahan_relay/proc/retrieve_head(datum/source, full_heal, admin_revive)
|
||||
if(admin_revive)
|
||||
var/obj/item/bodypart/head/H = loc
|
||||
var/turf/T = get_turf(owner)
|
||||
if(H && istype(H) && T && !(H in owner.GetAllContents()))
|
||||
|
||||
@@ -71,14 +71,42 @@
|
||||
if(/obj/item/projectile/energy/florayield)
|
||||
H.nutrition = min(H.nutrition+30, NUTRITION_LEVEL_FULL)
|
||||
|
||||
|
||||
/datum/species/pod/pseudo_weak
|
||||
name = "Anthromorphic Plant"
|
||||
id = "podweak"
|
||||
limbs_id = "pod"
|
||||
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,MUTCOLORS)
|
||||
mutant_bodyparts = list("mam_tail", "mam_ears", "mam_body_markings", "mam_snouts", "taur", "legs")
|
||||
default_features = list("mcolor" = "FFF","mcolor2" = "FFF","mcolor3" = "FFF", "mam_snouts" = "Husky", "mam_tail" = "Husky", "mam_ears" = "Husky", "mam_body_markings" = "Husky", "taur" = "None", "legs" = "Normal Legs")
|
||||
limbs_id = "pod"
|
||||
light_nutrition_gain_factor = 7.5
|
||||
light_bruteheal = 0.2
|
||||
light_burnheal = 0.2
|
||||
light_toxheal = 0.7
|
||||
|
||||
/datum/species/pod/pseudo_weak/spec_death(gibbed, mob/living/carbon/human/H)
|
||||
if(H)
|
||||
stop_wagging_tail(H)
|
||||
|
||||
/datum/species/pod/pseudo_weak/spec_stun(mob/living/carbon/human/H,amount)
|
||||
if(H)
|
||||
stop_wagging_tail(H)
|
||||
. = ..()
|
||||
|
||||
/datum/species/pod/pseudo_weak/can_wag_tail(mob/living/carbon/human/H)
|
||||
return ("mam_tail" in mutant_bodyparts) || ("mam_waggingtail" in mutant_bodyparts)
|
||||
|
||||
/datum/species/pod/pseudo_weak/is_wagging_tail(mob/living/carbon/human/H)
|
||||
return ("mam_waggingtail" in mutant_bodyparts)
|
||||
|
||||
/datum/species/pod/pseudo_weak/start_wagging_tail(mob/living/carbon/human/H)
|
||||
if("mam_tail" in mutant_bodyparts)
|
||||
mutant_bodyparts -= "mam_tail"
|
||||
mutant_bodyparts |= "mam_waggingtail"
|
||||
H.update_body()
|
||||
|
||||
/datum/species/pod/pseudo_weak/stop_wagging_tail(mob/living/carbon/human/H)
|
||||
if("mam_waggingtail" in mutant_bodyparts)
|
||||
mutant_bodyparts -= "mam_waggingtail"
|
||||
mutant_bodyparts |= "mam_tail"
|
||||
H.update_body()
|
||||
|
||||
@@ -213,6 +213,16 @@
|
||||
PDA.f_lum = 0
|
||||
PDA.update_icon()
|
||||
visible_message("<span class='danger'>The light in [PDA] shorts out!</span>")
|
||||
else if(istype(O, /obj/item/gun))
|
||||
var/obj/item/gun/weapon = O
|
||||
if(weapon.gun_light)
|
||||
var/obj/item/flashlight/seclite/light = weapon.gun_light
|
||||
light.forceMove(get_turf(weapon))
|
||||
light.burn()
|
||||
weapon.gun_light = null
|
||||
weapon.update_gunlight()
|
||||
QDEL_NULL(weapon.alight)
|
||||
visible_message("<span class='danger'>[light] on [O] flickers out and disintegrates!</span>")
|
||||
else
|
||||
visible_message("<span class='danger'>[O] is disintegrated by [src]!</span>")
|
||||
O.burn()
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
put_in_hands(I)
|
||||
update_inv_hands()
|
||||
if(SLOT_IN_BACKPACK)
|
||||
if(!SEND_SIGNAL(back, COMSIG_TRY_STORAGE_INSERT, I, src, TRUE))
|
||||
if(!back || !SEND_SIGNAL(back, COMSIG_TRY_STORAGE_INSERT, I, src, TRUE))
|
||||
not_handled = TRUE
|
||||
else
|
||||
not_handled = TRUE
|
||||
|
||||
@@ -357,8 +357,8 @@
|
||||
if(istype(loc, /obj/structure/closet/crate/coffin)|| istype(loc, /obj/structure/closet/body_bag) || istype(loc, /obj/structure/bodycontainer))
|
||||
return
|
||||
|
||||
// No decay if formaldehyde in corpse or when the corpse is charred
|
||||
if(reagents.has_reagent(/datum/reagent/toxin/formaldehyde, 1) || HAS_TRAIT(src, TRAIT_HUSK))
|
||||
// No decay if formaldehyde/preservahyde in corpse or when the corpse is charred
|
||||
if(reagents.has_reagent(/datum/reagent/toxin/formaldehyde, 1) || HAS_TRAIT(src, TRAIT_HUSK) || reagents.has_reagent(/datum/reagent/preservahyde, 1))
|
||||
return
|
||||
|
||||
// Also no decay if corpse chilled or not organic/undead
|
||||
@@ -397,7 +397,7 @@
|
||||
if(O)
|
||||
O.on_life()
|
||||
else
|
||||
if(reagents.has_reagent(/datum/reagent/toxin/formaldehyde, 1)) // No organ decay if the body contains formaldehyde.
|
||||
if(reagents.has_reagent(/datum/reagent/toxin/formaldehyde, 1) || reagents.has_reagent(/datum/reagent/preservahyde, 1)) // No organ decay if the body contains formaldehyde. Or preservahyde.
|
||||
return
|
||||
for(var/V in internal_organs)
|
||||
var/obj/item/organ/O = V
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
/mob/living/proc/spawn_gibs(with_bodyparts, atom/loc_override)
|
||||
var/location = loc_override ? loc_override.drop_location() : drop_location()
|
||||
if((MOB_ROBOTIC) in (mob_biotypes))
|
||||
if(mob_biotypes & MOB_ROBOTIC)
|
||||
new /obj/effect/gibspawner/robot(location, src, get_static_viruses())
|
||||
else
|
||||
new /obj/effect/gibspawner/generic(location, src, get_static_viruses())
|
||||
|
||||
@@ -482,7 +482,8 @@
|
||||
med_hud_set_status()
|
||||
|
||||
//proc used to ressuscitate a mob
|
||||
/mob/living/proc/revive(full_heal = 0, admin_revive = 0)
|
||||
/mob/living/proc/revive(full_heal = FALSE, admin_revive = FALSE)
|
||||
SEND_SIGNAL(src, COMSIG_LIVING_REVIVE, full_heal, admin_revive)
|
||||
if(full_heal)
|
||||
fully_heal(admin_revive)
|
||||
if(stat == DEAD && can_be_revived()) //in some cases you can't revive (e.g. no brain)
|
||||
@@ -528,11 +529,6 @@
|
||||
fire_stacks = 0
|
||||
confused = 0
|
||||
update_canmove()
|
||||
var/datum/component/mood/mood = GetComponent(/datum/component/mood)
|
||||
if (mood)
|
||||
QDEL_LIST_ASSOC_VAL(mood.mood_events)
|
||||
mood.sanity = SANITY_GREAT
|
||||
mood.update_mood()
|
||||
//Heal all organs
|
||||
if(iscarbon(src))
|
||||
var/mob/living/carbon/C = src
|
||||
@@ -540,8 +536,6 @@
|
||||
for(var/organ in C.internal_organs)
|
||||
var/obj/item/organ/O = organ
|
||||
O.setOrganDamage(0)
|
||||
SEND_SIGNAL(src, COMSIG_LIVING_FULLY_HEAL, admin_revive)
|
||||
|
||||
|
||||
//proc called by revive(), to check if we can actually ressuscitate the mob (we don't want to revive him and have him instantly die again)
|
||||
/mob/living/proc/can_be_revived()
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
name = "pAI"
|
||||
icon = 'icons/mob/pai.dmi'
|
||||
icon_state = "repairbot"
|
||||
mouse_opacity = MOUSE_OPACITY_OPAQUE
|
||||
density = FALSE
|
||||
pass_flags = PASSTABLE | PASSMOB
|
||||
mob_size = MOB_SIZE_TINY
|
||||
@@ -11,6 +10,7 @@
|
||||
health = 500
|
||||
maxHealth = 500
|
||||
layer = BELOW_MOB_LAYER
|
||||
silicon_privileges = PRIVILEDGES_PAI
|
||||
var/datum/element/mob_holder/current_mob_holder //because only a few of their chassis can be actually held.
|
||||
|
||||
var/network = "ss13"
|
||||
@@ -74,7 +74,7 @@
|
||||
var/emitteroverloadcd = 100
|
||||
|
||||
var/radio_short = FALSE
|
||||
var/radio_short_cooldown = 5 MINUTES
|
||||
var/radio_short_cooldown = 3 MINUTES
|
||||
var/radio_short_timerid
|
||||
|
||||
canmove = FALSE
|
||||
|
||||
@@ -56,7 +56,8 @@
|
||||
if(P.stun)
|
||||
fold_in(force = TRUE)
|
||||
visible_message("<span class='warning'>The electrically-charged projectile disrupts [src]'s holomatrix, forcing [src] to fold in!</span>")
|
||||
return ..()
|
||||
. = ..()
|
||||
return BULLET_ACT_FORCE_PIERCE
|
||||
|
||||
/mob/living/silicon/pai/stripPanelUnequip(obj/item/what, mob/who, where) //prevents stripping
|
||||
to_chat(src, "<span class='warning'>Your holochassis stutters and warps intensely as you attempt to interact with the object, forcing you to cease lest the field fail.</span>")
|
||||
|
||||
@@ -596,8 +596,8 @@
|
||||
|
||||
/obj/item/robot_module/peacekeeper/do_transform_animation()
|
||||
..()
|
||||
to_chat(loc, "<span class='userdanger'>Under ASIMOV/CREWSIMOV, you are an enforcer of the PEACE and preventer of HUMAN/CREW HARM. \
|
||||
You are not a security module and you are expected to follow orders and prevent harm above all else. Space law means nothing to you.</span>")
|
||||
to_chat(loc, "<span class='userdanger'>Under ASIMOV/CREWSIMOV, you are an enforcer of the PEACE. \
|
||||
You are not a security module and you are expected to follow orders to the best of your abilities without causing harm. Space law means nothing to you.</span>")
|
||||
|
||||
/obj/item/robot_module/peacekeeper/be_transformed_to(obj/item/robot_module/old_module)
|
||||
var/mob/living/silicon/robot/R = loc
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/mob/living/silicon
|
||||
gender = NEUTER
|
||||
has_unlimited_silicon_privilege = 1
|
||||
silicon_privileges = PRIVILEDGES_SILICON
|
||||
verb_say = "states"
|
||||
verb_ask = "queries"
|
||||
verb_exclaim = "declares"
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
maxbodytemp = INFINITY
|
||||
minbodytemp = 0
|
||||
blood_volume = 0
|
||||
has_unlimited_silicon_privilege = 1
|
||||
silicon_privileges = PRIVILEDGES_BOT
|
||||
sentience_type = SENTIENCE_ARTIFICIAL
|
||||
status_flags = NONE //no default canpush
|
||||
verb_say = "states"
|
||||
@@ -194,10 +194,12 @@
|
||||
if(locked) //First emag application unlocks the bot's interface. Apply a screwdriver to use the emag again.
|
||||
locked = FALSE
|
||||
emagged = 1
|
||||
to_chat(user, "<span class='notice'>You bypass [src]'s controls.</span>")
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>You bypass [src]'s controls.</span>")
|
||||
return TRUE
|
||||
if(!open)
|
||||
to_chat(user, "<span class='warning'>You need to open maintenance panel first!</span>")
|
||||
if(user)
|
||||
to_chat(user, "<span class='warning'>You need to open maintenance panel first!</span>")
|
||||
return
|
||||
emagged = 2
|
||||
remote_disabled = 1 //Manually emagging the bot locks out the AI built in panel.
|
||||
@@ -205,7 +207,8 @@
|
||||
bot_reset()
|
||||
turn_on() //The bot automatically turns on when emagged, unless recently hit with EMP.
|
||||
to_chat(src, "<span class='userdanger'>(#$*#$^^( OVERRIDE DETECTED</span>")
|
||||
log_combat(user, src, "emagged")
|
||||
if(user)
|
||||
log_combat(user, src, "emagged")
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/bot/examine(mob/user)
|
||||
|
||||
@@ -123,7 +123,8 @@
|
||||
emagged = TRUE
|
||||
if(!open)
|
||||
locked = !locked
|
||||
to_chat(user, "<span class='notice'>You [locked ? "lock" : "unlock"] [src]'s controls!</span>")
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>You [locked ? "lock" : "unlock"] [src]'s controls!</span>")
|
||||
flick("mulebot-emagged", src)
|
||||
playsound(src, "sparks", 100, FALSE)
|
||||
|
||||
@@ -180,7 +181,7 @@
|
||||
var/list/data = list()
|
||||
data["on"] = on
|
||||
data["locked"] = locked
|
||||
data["siliconUser"] = user.has_unlimited_silicon_privilege
|
||||
data["siliconUser"] = hasSiliconAccessInArea(usr)
|
||||
data["mode"] = mode ? mode_name[mode] : "Ready"
|
||||
data["modeStatus"] = ""
|
||||
switch(mode)
|
||||
@@ -205,11 +206,12 @@
|
||||
return data
|
||||
|
||||
/mob/living/simple_animal/bot/mulebot/ui_act(action, params)
|
||||
if(..() || (locked && !usr.has_unlimited_silicon_privilege))
|
||||
var/silicon_access = hasSiliconAccessInArea(usr)
|
||||
if(..() || (locked && silicon_access))
|
||||
return
|
||||
switch(action)
|
||||
if("lock")
|
||||
if(usr.has_unlimited_silicon_privilege)
|
||||
if(silicon_access)
|
||||
locked = !locked
|
||||
. = TRUE
|
||||
if("power")
|
||||
@@ -766,4 +768,3 @@
|
||||
|
||||
/obj/machinery/bot_core/mulebot
|
||||
req_access = list(ACCESS_CARGO)
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
bubble_icon = "machine"
|
||||
initial_language_holder = /datum/language_holder/drone
|
||||
mob_size = MOB_SIZE_SMALL
|
||||
has_unlimited_silicon_privilege = 1
|
||||
silicon_privileges = PRIVILEDGES_DRONE
|
||||
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
|
||||
hud_possible = list(DIAG_STAT_HUD, DIAG_HUD, ANTAG_HUD)
|
||||
unique_name = TRUE
|
||||
|
||||
91
code/modules/mob/living/simple_animal/hostile/sharks.dm
Normal file
91
code/modules/mob/living/simple_animal/hostile/sharks.dm
Normal file
@@ -0,0 +1,91 @@
|
||||
//shameless copies of carps.
|
||||
|
||||
/mob/living/simple_animal/hostile/shark
|
||||
name = "Space Shark"
|
||||
desc = "The best terror of the seas, next to the kraken."
|
||||
icon_state = "shark"
|
||||
icon_living = "shark"
|
||||
icon = 'icons/mob/sharks.dmi'
|
||||
icon_dead = "shark_dead"
|
||||
icon_gib = "carp_gib"
|
||||
environment_smash = 0
|
||||
speak_chance = 0
|
||||
turns_per_move = 3
|
||||
butcher_results = list(/obj/item/reagent_containers/food/snacks/carpmeat = 3)
|
||||
response_help = "pets"
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "hits"
|
||||
speed = 0
|
||||
maxHealth = 75
|
||||
health = 75
|
||||
harm_intent_damage = 18
|
||||
melee_damage_lower = 18
|
||||
melee_damage_upper = 18
|
||||
attacktext = "maims"
|
||||
attack_sound = 'sound/weapons/bite.ogg'
|
||||
gold_core_spawnable = 1
|
||||
//Space shark aren't affected by cold.
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
minbodytemp = 0
|
||||
maxbodytemp = 1500
|
||||
|
||||
faction = list("shark")
|
||||
|
||||
/mob/living/simple_animal/hostile/shark/Process_Spacemove(var/movement_dir = 0)
|
||||
return 1 //No drifting in space for space sharks....either!
|
||||
|
||||
/mob/living/simple_animal/hostile/shark/FindTarget()
|
||||
. = ..()
|
||||
if(.)
|
||||
emote("me", 1, "growls at [.]!")
|
||||
|
||||
/mob/living/simple_animal/hostile/shark/AttackingTarget()
|
||||
. =..()
|
||||
var/mob/living/carbon/L = .
|
||||
if(istype(L))
|
||||
if(prob(25))
|
||||
L.Knockdown(20)
|
||||
L.visible_message("<span class='danger'>\the [src] knocks down \the [L]!</span>")
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/shark/laser
|
||||
name = "Laser-Shark"
|
||||
desc = "NOW we've jumped the shark."
|
||||
icon_state = "lasershark"
|
||||
icon_living = "lasershark"
|
||||
icon_dead = "lasershark_dead"
|
||||
icon_gib = "carp_gib"
|
||||
ranged = 1
|
||||
retreat_distance = 3
|
||||
minimum_distance = 0 //Between shots they can and will close in to nash
|
||||
projectiletype = /obj/item/projectile/beam/laser/heavylaser
|
||||
projectilesound = 'sound/weapons/lasercannonfire.ogg'
|
||||
maxHealth = 50
|
||||
health = 50
|
||||
|
||||
/mob/living/simple_animal/hostile/shark/kawaii
|
||||
name = "Kawaii Shark"
|
||||
desc = "Senpai~ Notice me.."
|
||||
icon_state = "kawaiishark"
|
||||
icon_living = "kawaiishark"
|
||||
icon_dead = "kawaiishark_dead"
|
||||
speak = list("Oh Senpai","Notice me senpai!","Oh my...","Kawaii~")
|
||||
speak_emote = list("lovingly says","says")
|
||||
speak_chance = 2
|
||||
turns_per_move = 3
|
||||
butcher_results = list(/mob/living/simple_animal/butterfly = 3)
|
||||
maxHealth = 50
|
||||
health = 50
|
||||
maxbodytemp = INFINITY
|
||||
|
||||
harm_intent_damage = 0
|
||||
melee_damage_lower = 0
|
||||
melee_damage_upper = 0
|
||||
attacktext = "violently hugs"
|
||||
vision_range = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/shark/kawaii/death()
|
||||
say("Senpai, you noticed~!")
|
||||
LoseAggro()
|
||||
..()
|
||||
walk(src, 0)
|
||||
@@ -126,7 +126,7 @@
|
||||
// This loop will, at most, loop twice.
|
||||
for(var/atom/check in check_list)
|
||||
for(var/mob/living/M in viewers(world.view + 1, check) - src)
|
||||
if(M.client && CanAttack(M) && !M.has_unlimited_silicon_privilege)
|
||||
if(M.client && CanAttack(M) && !M.silicon_privileges)
|
||||
if(!M.eye_blind)
|
||||
return M
|
||||
for(var/obj/mecha/M in view(world.view + 1, check)) //assuming if you can see them they can see you
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
var/digitalinvis = 0 //Are they ivisible to the AI?
|
||||
var/image/digitaldisguise = null //what does the AI see instead of them?
|
||||
|
||||
var/has_unlimited_silicon_privilege = 0 // Can they interact with station electronics
|
||||
var/silicon_privileges = NONE // Can they interact with station electronics
|
||||
|
||||
var/obj/control_object //Used by admins to possess objects. All mobs should have this var
|
||||
var/atom/movable/remote_control //Calls relaymove() to whatever it is
|
||||
|
||||
@@ -406,8 +406,8 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
|
||||
return
|
||||
return TRUE
|
||||
|
||||
/atom/proc/hasSiliconAccessInArea(mob/user)
|
||||
return user && (issilicon(user) || (user.siliconaccesstoggle && (get_area(src) in user.siliconaccessareas)))
|
||||
/atom/proc/hasSiliconAccessInArea(mob/user, flags = PRIVILEDGES_SILICON)
|
||||
return user.silicon_privileges & (flags) || (user.siliconaccesstoggle && (get_area(src) in user.siliconaccessareas))
|
||||
|
||||
/mob/proc/toggleSiliconAccessArea(area/area)
|
||||
if (area in siliconaccessareas)
|
||||
@@ -555,4 +555,4 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
|
||||
|
||||
//Can the mob see reagents inside of containers?
|
||||
/mob/proc/can_see_reagents()
|
||||
return stat == DEAD || has_unlimited_silicon_privilege //Dead guys and silicons can always see reagents
|
||||
return stat == DEAD || silicon_privileges //Dead guys and silicons can always see reagents
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
return "Default Implementation"
|
||||
|
||||
/datum/proc/oui_canuse(mob/user)
|
||||
if(isobserver(user) && !user.has_unlimited_silicon_privilege)
|
||||
if(isobserver(user) && !user.silicon_privileges)
|
||||
return FALSE
|
||||
return oui_canview(user)
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
return ..()
|
||||
|
||||
/obj/machinery/oui_canview(mob/user)
|
||||
if(user.has_unlimited_silicon_privilege || hasSiliconAccessInArea(user))
|
||||
if(hasSiliconAccessInArea(user, ALL))
|
||||
return TRUE
|
||||
if(!can_interact(user))
|
||||
return FALSE
|
||||
|
||||
422
code/modules/pool/pool_controller.dm
Normal file
422
code/modules/pool/pool_controller.dm
Normal file
@@ -0,0 +1,422 @@
|
||||
#define POOL_NO_OVERDOSE_MEDICINE_MAX 5 //max units of no-overdose medicine to allow mobs to have through duplication
|
||||
|
||||
//Originally stolen from paradise. Credits to tigercat2000.
|
||||
//Modified a lot by Kokojo and Tortellini Tony for hippiestation.
|
||||
//Heavily refactored by tgstation
|
||||
/obj/machinery/pool
|
||||
icon = 'icons/obj/machines/pool.dmi'
|
||||
anchored = TRUE
|
||||
resistance_flags = INDESTRUCTIBLE
|
||||
|
||||
/obj/machinery/pool/controller
|
||||
name = "\improper Pool Controller"
|
||||
desc = "An advanced substance generation and fluid tank management system that can refill the contents of a pool to a completely different substance in minutes."
|
||||
icon_state = "poolc_3"
|
||||
density = TRUE
|
||||
use_power = TRUE
|
||||
idle_power_usage = 75
|
||||
/// How far it scans for pool objects
|
||||
var/scan_range = 6
|
||||
/// Is pool mist currently on?
|
||||
var/mist_state = FALSE
|
||||
/// Linked mist effects
|
||||
var/list/obj/effect/mist/linked_mist = list()
|
||||
/// Pool turfs
|
||||
var/list/turf/open/pool/linked_turfs = list()
|
||||
/// All mobs in pool
|
||||
var/list/mob/living/mobs_in_pool = list()
|
||||
/// Is the pool bloody?
|
||||
var/bloody = 0
|
||||
/// Last time we process_reagents()'d
|
||||
var/last_reagent_process = 0
|
||||
/// Maximum amount we will take from a beaker
|
||||
var/max_beaker_transfer = 100
|
||||
/// Minimum amount of a reagent for it to work on us
|
||||
var/min_reagent_amount = 10
|
||||
/// ADMINBUS ONLY - WHETHER OR NOT WE HAVE NOREACT ;)
|
||||
var/noreact_reagents = FALSE
|
||||
/// how fast in deciseconds between reagent processes
|
||||
var/reagent_tick_interval = 5
|
||||
/// Can we use unsafe temperatures
|
||||
var/temperature_unlocked = FALSE
|
||||
/// See __DEFINES/pool.dm, temperature defines
|
||||
var/temperature = POOL_NORMAL
|
||||
/// Whether or not the pool can be drained
|
||||
var/drainable = FALSE
|
||||
// Whether or not the pool is drained
|
||||
var/drained = FALSE
|
||||
/// Pool drain
|
||||
var/obj/machinery/pool/drain/linked_drain
|
||||
/// Pool filter
|
||||
var/obj/machinery/pool/filter/linked_filter
|
||||
/// Next world.time you can interact with settings
|
||||
var/interact_delay = 0
|
||||
/// Airlock style shocks
|
||||
var/shocked = FALSE
|
||||
/// Old reagent color, used to determine if update_color needs to reset colors.
|
||||
var/old_rcolor
|
||||
/// Just to prevent spam
|
||||
var/draining = FALSE
|
||||
/// Reagent blacklisting
|
||||
var/respect_reagent_blacklist = TRUE
|
||||
|
||||
/obj/machinery/pool/controller/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class='boldnotice'>Alt click to drain reagents.</span>"
|
||||
|
||||
/obj/machinery/pool/controller/Initialize()
|
||||
. = ..()
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
create_reagents(1000)
|
||||
if(noreact_reagents)
|
||||
reagents.reagents_holder_flags |= NO_REACT
|
||||
wires = new /datum/wires/poolcontroller(src)
|
||||
scan_things()
|
||||
|
||||
/obj/machinery/pool/controller/Destroy()
|
||||
STOP_PROCESSING(SSprocessing, src)
|
||||
linked_drain = null
|
||||
linked_filter = null
|
||||
linked_turfs.Cut()
|
||||
mobs_in_pool.Cut()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/pool/controller/proc/scan_things()
|
||||
var/list/cached = range(scan_range, src)
|
||||
for(var/turf/open/pool/W in cached)
|
||||
linked_turfs += W
|
||||
W.controller = src
|
||||
for(var/obj/machinery/pool/drain/pooldrain in cached)
|
||||
linked_drain = pooldrain
|
||||
linked_drain.controller = src
|
||||
break
|
||||
for(var/obj/machinery/pool/filter/F in cached)
|
||||
linked_filter = F
|
||||
linked_filter.controller = src
|
||||
break
|
||||
|
||||
/obj/machinery/pool/controller/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(!(obj_flags & EMAGGED)) //If it is not already emagged, emag it.
|
||||
to_chat(user, "<span class='warning'>You disable the [src]'s safety features.</span>")
|
||||
do_sparks(5, TRUE, src)
|
||||
obj_flags |= EMAGGED
|
||||
temperature_unlocked = TRUE
|
||||
drainable = TRUE
|
||||
log_game("[key_name(user)] emagged [src]")
|
||||
message_admins("[key_name_admin(user)] emagged [src]")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The interface on [src] is already too damaged to short it again.</span>")
|
||||
return
|
||||
|
||||
/obj/machinery/pool/controller/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!isliving(user) || !user.Adjacent(src) || !user.CanReach(src) || user.IsStun() || user.IsKnockdown() || user.incapacitated())
|
||||
return FALSE
|
||||
visible_message("<span class='boldwarning'>[user] starts to drain [src]!</span>")
|
||||
draining = TRUE
|
||||
if(!do_after(user, 50, target = src))
|
||||
draining = FALSE
|
||||
return TRUE
|
||||
reagents.remove_all(INFINITY)
|
||||
visible_message("<span class='boldnotice'>[user] drains [src].</span>")
|
||||
say("Reagents cleared.")
|
||||
update_color()
|
||||
draining = FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/pool/controller/attackby(obj/item/W, mob/user)
|
||||
if(shocked && !(stat & NOPOWER))
|
||||
shock(user,50)
|
||||
if(stat & (BROKEN))
|
||||
return
|
||||
if(istype(W,/obj/item/reagent_containers))
|
||||
if(W.reagents.total_volume) //check if there's reagent
|
||||
user.visible_message("<span class='boldwarning'>[user] is feeding [src] some chemicals from [W].</span>")
|
||||
if(do_after(user, 50, target = src))
|
||||
for(var/datum/reagent/R in W.reagents.reagent_list)
|
||||
if(R.type in GLOB.blacklisted_pool_reagents)
|
||||
to_chat(user, "[src] cannot accept [R.name].")
|
||||
return
|
||||
if(R.reagent_state == SOLID)
|
||||
to_chat(user, "The pool cannot accept reagents in solid form!.")
|
||||
return
|
||||
reagents.clear_reagents()
|
||||
// This also reacts them. No nitroglycerin deathpools, sorry gamers :(
|
||||
W.reagents.trans_to(reagents, max_beaker_transfer)
|
||||
user.visible_message("<span class='notice'>[src] makes a slurping noise.</span>", "<span class='notice'>All of the contents of [W] are quickly suctioned out by the machine!</span")
|
||||
updateUsrDialog()
|
||||
var/list/reagent_names = list()
|
||||
var/list/rejected = list()
|
||||
for(var/datum/reagent/R in reagents.reagent_list)
|
||||
if((R.volume >= min_reagent_amount) && (!respect_reagent_blacklist || R.can_synth))
|
||||
reagent_names += R.name
|
||||
else
|
||||
reagents.remove_reagent(R.type, INFINITY)
|
||||
rejected += R.name
|
||||
if(length(reagent_names))
|
||||
reagent_names = english_list(reagent_names)
|
||||
var/msg = "POOL: [key_name(user)] has changed [src]'s chems to [reagent_names]"
|
||||
log_game(msg)
|
||||
message_admins(msg)
|
||||
if(length(rejected))
|
||||
rejected = english_list(rejected)
|
||||
to_chat(user, "<span class='warning'>[src] rejects the following chemicals as they do not have at least [min_reagent_amount] units of volume: [rejected]</span>")
|
||||
update_color()
|
||||
else
|
||||
to_chat(user, "<span class='notice'>[src] beeps unpleasantly as it rejects the beaker. Why are you trying to feed it an empty beaker?</span>")
|
||||
return
|
||||
else if(panel_open && is_wire_tool(W))
|
||||
wires.interact(user)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/pool/controller/screwdriver_act(mob/living/user, obj/item/W)
|
||||
. = ..()
|
||||
if(.)
|
||||
return TRUE
|
||||
cut_overlays()
|
||||
panel_open = !panel_open
|
||||
to_chat(user, "You [panel_open ? "open" : "close"] the maintenance panel.")
|
||||
W.play_tool_sound(src)
|
||||
if(panel_open)
|
||||
add_overlay("wires")
|
||||
return TRUE
|
||||
|
||||
//procs
|
||||
/obj/machinery/pool/controller/proc/shock(mob/user, prb)
|
||||
if(stat & (BROKEN|NOPOWER)) // unpowered, no shock
|
||||
return FALSE
|
||||
if(!prob(prb))
|
||||
return FALSE
|
||||
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
|
||||
s.set_up(5, 1, src)
|
||||
s.start()
|
||||
if(electrocute_mob(user, get_area(src), src, 0.7))
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/pool/controller/proc/process_reagents()
|
||||
if(last_reagent_process > world.time + reagent_tick_interval)
|
||||
return
|
||||
if(!length(reagents.reagent_list))
|
||||
return
|
||||
for(var/turf/open/pool/W in linked_turfs)
|
||||
for(var/mob/living/carbon/human/swimee in W)
|
||||
for(var/datum/reagent/R in reagents.reagent_list)
|
||||
if(R.reagent_state == SOLID)
|
||||
R.reagent_state = LIQUID
|
||||
if(!swimee.reagents.has_reagent(POOL_NO_OVERDOSE_MEDICINE_MAX))
|
||||
swimee.reagents.add_reagent(R.type, 0.5) //osmosis
|
||||
reagents.reaction(swimee, VAPOR, 0.03) //3 percent. Need to find a way to prevent this from stacking chems at some point like the above.
|
||||
for(var/obj/objects in W)
|
||||
if(W.reagents)
|
||||
W.reagents.reaction(objects, VAPOR, 1)
|
||||
last_reagent_process = world.time
|
||||
|
||||
/obj/machinery/pool/controller/process()
|
||||
updateUsrDialog()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
if(drained)
|
||||
return
|
||||
process_pool()
|
||||
process_reagents()
|
||||
|
||||
/obj/machinery/pool/controller/proc/process_pool()
|
||||
if(drained)
|
||||
return
|
||||
for(var/mob/living/M in mobs_in_pool)
|
||||
switch(temperature) //Apply different effects based on what the temperature is set to.
|
||||
if(POOL_SCALDING) //Scalding
|
||||
M.adjust_bodytemperature(50,0,500)
|
||||
if(POOL_WARM) //Warm
|
||||
M.adjust_bodytemperature(20,0,360) //Heats up mobs till the termometer shows up
|
||||
//Normal temp does nothing, because it's just room temperature water.
|
||||
if(POOL_COOL)
|
||||
M.adjust_bodytemperature(-20,250) //Cools mobs till the termometer shows up
|
||||
if(POOL_FRIGID) //Freezing
|
||||
M.adjust_bodytemperature(-60) //cool mob at -35k per cycle, less would not affect the mob enough.
|
||||
if(M.bodytemperature <= 50 && !M.stat)
|
||||
M.apply_status_effect(/datum/status_effect/freon)
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/drownee = M
|
||||
if(!drownee || drownee.stat == DEAD)
|
||||
return
|
||||
if(drownee.resting && !drownee.internal)
|
||||
if(drownee.stat != CONSCIOUS)
|
||||
drownee.adjustOxyLoss(9)
|
||||
else
|
||||
drownee.adjustOxyLoss(4)
|
||||
if(prob(35))
|
||||
to_chat(drownee, "<span class='danger'>You're drowning!</span>")
|
||||
|
||||
/obj/machinery/pool/controller/proc/set_bloody(state)
|
||||
if(bloody == state)
|
||||
return
|
||||
bloody = state
|
||||
update_color()
|
||||
|
||||
/obj/machinery/pool/controller/proc/update_color()
|
||||
if(drained)
|
||||
return
|
||||
var/rcolor
|
||||
if(reagents.reagent_list.len)
|
||||
rcolor = mix_color_from_reagents(reagents.reagent_list)
|
||||
if(rcolor == old_rcolor)
|
||||
return // small performance upgrade hopefully?
|
||||
old_rcolor = rcolor
|
||||
for(var/X in linked_turfs)
|
||||
var/turf/open/pool/color1 = X
|
||||
if(bloody)
|
||||
if(rcolor)
|
||||
var/thecolor = BlendRGB(rgb(150, 20, 20), rcolor, 0.5)
|
||||
color1.watereffect.add_atom_colour(thecolor, FIXED_COLOUR_PRIORITY)
|
||||
color1.watertop.add_atom_colour(thecolor, FIXED_COLOUR_PRIORITY)
|
||||
else
|
||||
var/thecolor = rgb(150, 20, 20)
|
||||
color1.watereffect.add_atom_colour(thecolor, FIXED_COLOUR_PRIORITY)
|
||||
color1.watertop.add_atom_colour(thecolor, FIXED_COLOUR_PRIORITY)
|
||||
else if(!bloody && rcolor)
|
||||
color1.watereffect.add_atom_colour(rcolor, FIXED_COLOUR_PRIORITY)
|
||||
color1.watertop.add_atom_colour(rcolor, FIXED_COLOUR_PRIORITY)
|
||||
else
|
||||
color1.watereffect.remove_atom_colour(FIXED_COLOUR_PRIORITY)
|
||||
color1.watertop.remove_atom_colour(FIXED_COLOUR_PRIORITY)
|
||||
|
||||
/obj/machinery/pool/controller/proc/update_temp()
|
||||
if(mist_state)
|
||||
if(temperature < POOL_SCALDING)
|
||||
mist_off()
|
||||
else
|
||||
if(temperature == POOL_SCALDING)
|
||||
mist_on()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/pool/controller/update_icon()
|
||||
. = ..()
|
||||
icon_state = "poolc_[temperature]"
|
||||
|
||||
/obj/machinery/pool/controller/proc/CanUpTemp(mob/user)
|
||||
if(temperature == POOL_WARM && (temperature_unlocked || issilicon(user) || IsAdminGhost(user)) || temperature < POOL_WARM)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/pool/controller/proc/CanDownTemp(mob/user)
|
||||
if(temperature == POOL_COOL && (temperature_unlocked || issilicon(user) || IsAdminGhost(user)) || temperature > POOL_COOL)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/pool/controller/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(interact_delay > world.time)
|
||||
return
|
||||
if(href_list["IncreaseTemp"])
|
||||
if(CanUpTemp(usr))
|
||||
visible_message("<span class='warning'>[usr] presses a button on [src].</span>")
|
||||
temperature++
|
||||
update_temp()
|
||||
var/msg = "POOL: [key_name(usr)] increased [src]'s pool temperature at [COORD(src)] to [temperature]"
|
||||
log_game(msg)
|
||||
message_admins(msg)
|
||||
interact_delay = world.time + 15
|
||||
if(href_list["DecreaseTemp"])
|
||||
if(CanDownTemp(usr))
|
||||
visible_message("<span class='warning'>[usr] presses a button on [src].</span>")
|
||||
temperature--
|
||||
update_temp()
|
||||
var/msg = "POOL: [key_name(usr)] decreased [src]'s pool temperature at [COORD(src)] to [temperature]"
|
||||
log_game(msg)
|
||||
message_admins(msg)
|
||||
interact_delay = world.time + 15
|
||||
if(href_list["Activate Drain"])
|
||||
if((drainable || issilicon(usr) || IsAdminGhost(usr)) && !linked_drain.active)
|
||||
var/msg = "POOL: [key_name(usr)] activated [src]'s pool drain in [linked_drain.filling? "FILLING" : "DRAINING"] mode at [COORD(src)]"
|
||||
log_game(msg)
|
||||
message_admins(msg)
|
||||
visible_message("<span class='warning'>[usr] presses a button on [src].</span>")
|
||||
mist_off()
|
||||
interact_delay = world.time + 60
|
||||
linked_drain.active = TRUE
|
||||
linked_drain.cycles_left = 75
|
||||
if(!linked_drain.filling)
|
||||
new /obj/effect/whirlpool(linked_drain.loc)
|
||||
temperature = POOL_NORMAL
|
||||
else
|
||||
new /obj/effect/waterspout(linked_drain.loc)
|
||||
temperature = POOL_NORMAL
|
||||
update_temp()
|
||||
bloody = FALSE
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/pool/controller/proc/temp2text()
|
||||
switch(temperature)
|
||||
if(POOL_FRIGID)
|
||||
return "<span class='boldwarning'>Frigid</span>"
|
||||
if(POOL_COOL)
|
||||
return "<span class='boldnotice'>Cool</span>"
|
||||
if(POOL_NORMAL)
|
||||
return "<span class='notice'>Normal</span>"
|
||||
if(POOL_WARM)
|
||||
return "<span class='boldnotice'>Warm</span>"
|
||||
if(POOL_SCALDING)
|
||||
return "<span class='boldwarning'>Scalding</span>"
|
||||
else
|
||||
return "Outside of possible range."
|
||||
|
||||
/obj/machinery/pool/controller/ui_interact(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(shocked && !(stat & NOPOWER))
|
||||
shock(user,50)
|
||||
if(panel_open && !isAI(user))
|
||||
return wires.interact(user)
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
var/datum/browser/popup = new(user, "Pool Controller", name, 300, 450)
|
||||
var/dat = ""
|
||||
if(interact_delay > world.time)
|
||||
dat += "<span class='notice'>[round((interact_delay - world.time)/10, 0.1)] seconds left until [src] can operate again.</span><BR>"
|
||||
dat += text({"
|
||||
<h3>Temperature</h3>
|
||||
<div class='statusDisplay'>
|
||||
<B>Current temperature:</B> [temp2text()]<BR>
|
||||
[CanUpTemp(user) ? "<a href='?src=\ref[src];IncreaseTemp=1'>Increase Temperature</a><br>" : "<span class='linkOff'>Increase Temperature</span><br>"]
|
||||
[CanDownTemp(user) ? "<a href='?src=\ref[src];DecreaseTemp=1'>Decrease Temperature</a><br>" : "<span class='linkOff'>Decrease Temperature</span><br>"]
|
||||
</div>
|
||||
<h3>Drain</h3>
|
||||
<div class='statusDisplay'>
|
||||
<B>Drain status:</B> [(issilicon(user) || IsAdminGhost(user) || drainable) ? "<span class='bad'>Enabled</span>" : "<span class='good'>Disabled</span>"]
|
||||
<br><b>Pool status:</b> "})
|
||||
if(!drained)
|
||||
dat += "<span class='good'>Full</span><BR>"
|
||||
else
|
||||
dat += "<span class='bad'>Drained</span><BR>"
|
||||
if((issilicon(user) || IsAdminGhost(user) || drainable) && !linked_drain.active)
|
||||
dat += "<a href='?src=\ref[src];Activate Drain=1'>[drained ? "Fill" : "Drain"] Pool</a><br>"
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/pool/controller/proc/reset(wire)
|
||||
switch(wire)
|
||||
if(WIRE_SHOCK)
|
||||
if(!wires.is_cut(wire))
|
||||
shocked = FALSE
|
||||
|
||||
/obj/machinery/pool/controller/proc/mist_on() //Spawn /obj/effect/mist (from the shower) on all linked pool tiles
|
||||
if(mist_state)
|
||||
return
|
||||
mist_state = TRUE
|
||||
for(var/X in linked_turfs)
|
||||
var/turf/open/pool/W = X
|
||||
if(W.filled)
|
||||
var/M = new /obj/effect/mist(W)
|
||||
linked_mist += M
|
||||
|
||||
/obj/machinery/pool/controller/proc/mist_off() //Delete all /obj/effect/mist from all linked pool tiles.
|
||||
for(var/M in linked_mist)
|
||||
qdel(M)
|
||||
mist_state = FALSE
|
||||
160
code/modules/pool/pool_drain.dm
Normal file
160
code/modules/pool/pool_drain.dm
Normal file
@@ -0,0 +1,160 @@
|
||||
/obj/machinery/pool/drain
|
||||
name = "drain"
|
||||
icon_state = "drain"
|
||||
desc = "A suction system to remove the contents of the pool, and sometimes small objects. Do not insert fingers."
|
||||
anchored = TRUE
|
||||
/// Active/on?
|
||||
var/active = FALSE
|
||||
/// Filling or draining
|
||||
var/filling = FALSE
|
||||
/// Drain item suction range
|
||||
var/item_suction_range = 2
|
||||
/// Fill mode knock away range
|
||||
var/fill_push_range = 6
|
||||
/// Drain mode suction range
|
||||
var/drain_suck_range = 6
|
||||
/// Parent controller
|
||||
var/obj/machinery/pool/controller/controller
|
||||
/// Cycles left for fill/drain while active
|
||||
var/cycles_left = 0
|
||||
/// Mobs we are swirling around
|
||||
var/list/whirling_mobs
|
||||
/// Suck in once per x ticks
|
||||
var/suck_in_once_per = 3
|
||||
|
||||
var/cooldown
|
||||
|
||||
/obj/machinery/pool/drain/Initialize()
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
whirling_mobs = list()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/pool/drain/Destroy()
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
controller.linked_drain = null
|
||||
controller = null
|
||||
whirling_mobs = null
|
||||
return ..()
|
||||
|
||||
/obj/machinery/pool/drain/proc/is_in_our_pool(atom/A)
|
||||
. = FALSE
|
||||
if(istype(A.loc, /turf/open/pool))
|
||||
var/turf/open/pool/P = A.loc
|
||||
if(P.controller == controller)
|
||||
. = TRUE
|
||||
|
||||
// This should probably start using move force sometime in the future but I'm lazy.
|
||||
/obj/machinery/pool/drain/process()
|
||||
if(!filling)
|
||||
for(var/obj/item/I in range(min(item_suction_range, 10), src))
|
||||
if(!I.anchored && (I.w_class <= WEIGHT_CLASS_SMALL))
|
||||
step_towards(I, src)
|
||||
if((I.w_class <= WEIGHT_CLASS_TINY) && (get_dist(I, src) == 0))
|
||||
I.forceMove(controller.linked_filter)
|
||||
if(active)
|
||||
if(filling)
|
||||
if(cycles_left-- > 0)
|
||||
playsound(src, 'sound/effects/fillingwatter.ogg', 100, TRUE)
|
||||
for(var/obj/O in orange(min(fill_push_range, 10), src))
|
||||
if(!O.anchored && is_in_our_pool(O))
|
||||
step_away(O, src)
|
||||
for(var/mob/M in orange(min(fill_push_range, 10), src)) //compiler fastpath apparently?
|
||||
if(!M.anchored && isliving(M) && is_in_our_pool(M))
|
||||
step_away(M, src)
|
||||
else
|
||||
for(var/turf/open/pool/P in controller.linked_turfs)
|
||||
P.filled = TRUE
|
||||
P.update_icon()
|
||||
for(var/obj/effect/waterspout/S in range(1, src))
|
||||
qdel(S)
|
||||
controller.drained = FALSE
|
||||
if(controller.bloody < 1000)
|
||||
controller.bloody /= 2
|
||||
else
|
||||
controller.bloody /= 4
|
||||
controller.update_color()
|
||||
filling = FALSE
|
||||
active = FALSE
|
||||
else
|
||||
if(cycles_left-- > 0)
|
||||
playsound(src, 'sound/effects/pooldrain.ogg', 100, TRUE)
|
||||
playsound(src, "water_wade", 60, TRUE)
|
||||
for(var/obj/O in orange(min(drain_suck_range, 10), src))
|
||||
if(!O.anchored && is_in_our_pool(O))
|
||||
step_towards(O, src)
|
||||
for(var/mob/M in orange(min(drain_suck_range, 10), src))
|
||||
if(isliving(M) && !M.anchored && is_in_our_pool(M))
|
||||
if(!(cycles_left % suck_in_once_per))
|
||||
step_towards(M, src)
|
||||
whirl_mob(M)
|
||||
if(ishuman(M) && (get_dist(M, src) <= 1))
|
||||
var/mob/living/carbon/human/H = M
|
||||
playsound(src, pick('sound/misc/crack.ogg','sound/misc/crunch.ogg'), 50, TRUE)
|
||||
if(H.lying) //down for any reason
|
||||
H.adjustBruteLoss(2)
|
||||
to_chat(H, "<span class='danger'>You're caught in the drain!</span>")
|
||||
else
|
||||
H.apply_damage(2.5, BRUTE, pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)) //drain should only target the legs
|
||||
to_chat(H, "<span class='danger'>Your legs are caught in the drain!</span>")
|
||||
else
|
||||
for(var/turf/open/pool/P in controller.linked_turfs)
|
||||
P.filled = FALSE
|
||||
P.update_icon()
|
||||
for(var/obj/effect/whirlpool/W in range(1, src))
|
||||
qdel(W)
|
||||
controller.drained = TRUE
|
||||
controller.mist_off()
|
||||
active = FALSE
|
||||
filling = TRUE
|
||||
|
||||
/// dangerous proc don't fuck with, admins
|
||||
/obj/machinery/pool/drain/proc/whirl_mob(mob/living/L, duration = 8, delay = 1)
|
||||
set waitfor = FALSE
|
||||
if(whirling_mobs[L])
|
||||
return
|
||||
whirling_mobs[L] = TRUE
|
||||
for(var/i in 1 to min(duration, 100))
|
||||
L.setDir(turn(L.dir, 90))
|
||||
sleep(delay)
|
||||
if(QDELETED(L))
|
||||
break
|
||||
if(QDELETED(src))
|
||||
return
|
||||
whirling_mobs -= L
|
||||
|
||||
/obj/machinery/pool/filter
|
||||
name = "Filter"
|
||||
icon_state = "filter"
|
||||
desc = "The part of the pool where all the IDs, ATV keys, and pens, and other dangerous things get trapped."
|
||||
var/obj/machinery/pool/controller/controller
|
||||
|
||||
/obj/machinery/pool/filter/Destroy()
|
||||
controller.linked_filter = null
|
||||
controller = null
|
||||
return ..()
|
||||
|
||||
/obj/machinery/pool/filter/emag_act(mob/living/user)
|
||||
. = ..()
|
||||
if(!(obj_flags & EMAGGED))
|
||||
to_chat(user, "<span class='warning'>You disable the [src]'s shark filter! Run!</span>")
|
||||
obj_flags |= EMAGGED
|
||||
do_sparks(5, TRUE, src)
|
||||
icon_state = "filter_b"
|
||||
addtimer(CALLBACK(src, /obj/machinery/pool/filter/proc/spawn_shark), 50)
|
||||
var/msg = "[key_name(user)] emagged the pool filter and spawned a shark"
|
||||
log_game(msg)
|
||||
message_admins(msg)
|
||||
|
||||
/obj/machinery/pool/filter/proc/spawn_shark()
|
||||
if(prob(50))
|
||||
new /mob/living/simple_animal/hostile/shark(loc)
|
||||
else
|
||||
if(prob(50))
|
||||
new /mob/living/simple_animal/hostile/shark/kawaii(loc)
|
||||
else
|
||||
new /mob/living/simple_animal/hostile/shark/laser(loc)
|
||||
|
||||
/obj/machinery/pool/filter/attack_hand(mob/user)
|
||||
to_chat(user, "You search the filter.")
|
||||
for(var/obj/O in contents)
|
||||
O.forceMove(loc)
|
||||
29
code/modules/pool/pool_effects.dm
Normal file
29
code/modules/pool/pool_effects.dm
Normal file
@@ -0,0 +1,29 @@
|
||||
/obj/effect/splash
|
||||
name = "splash"
|
||||
desc = "Wataaa!."
|
||||
icon = 'icons/turf/pool.dmi'
|
||||
icon_state = "splash"
|
||||
layer = ABOVE_ALL_MOB_LAYER
|
||||
|
||||
/obj/effect/whirlpool
|
||||
name = "Whirlpool"
|
||||
icon = 'icons/effects/96x96.dmi'
|
||||
icon_state = "whirlpool"
|
||||
layer = 5
|
||||
anchored = TRUE
|
||||
mouse_opacity = 0
|
||||
pixel_x = -32
|
||||
pixel_y = -32
|
||||
alpha = 90
|
||||
|
||||
/obj/effect/waterspout
|
||||
name = "Waterspout"
|
||||
icon = 'icons/effects/96x96.dmi'
|
||||
icon_state = "waterspout"
|
||||
color = "#3399AA"
|
||||
layer = 5
|
||||
anchored = TRUE
|
||||
mouse_opacity = 0
|
||||
pixel_x = -32
|
||||
pixel_y = -32
|
||||
alpha = 120
|
||||
191
code/modules/pool/pool_main.dm
Normal file
191
code/modules/pool/pool_main.dm
Normal file
@@ -0,0 +1,191 @@
|
||||
/turf/open/pool
|
||||
icon = 'icons/turf/pool.dmi'
|
||||
name = "poolwater"
|
||||
desc = "You're safer here than in the deep."
|
||||
icon_state = "pool_tile"
|
||||
heat_capacity = INFINITY
|
||||
var/filled = TRUE
|
||||
var/next_splash = 0
|
||||
var/obj/machinery/pool/controller/controller
|
||||
var/obj/effect/overlay/water/watereffect
|
||||
var/obj/effect/overlay/water/top/watertop
|
||||
|
||||
/turf/open/pool/Initialize(mapload)
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
/turf/open/pool/Destroy()
|
||||
if(controller)
|
||||
controller.linked_turfs -= src
|
||||
controller = null
|
||||
QDEL_NULL(watereffect)
|
||||
QDEL_NULL(watertop)
|
||||
return ..()
|
||||
|
||||
/turf/open/pool/update_icon()
|
||||
. = ..()
|
||||
if(!filled)
|
||||
name = "drained pool"
|
||||
desc = "No diving!"
|
||||
QDEL_NULL(watereffect)
|
||||
QDEL_NULL(watertop)
|
||||
else
|
||||
name = "poolwater"
|
||||
desc = "You're safer here than in the deep."
|
||||
watereffect = new /obj/effect/overlay/water(src)
|
||||
watertop = new /obj/effect/overlay/water/top(src)
|
||||
|
||||
/obj/effect/overlay/water
|
||||
name = "water"
|
||||
icon = 'icons/turf/pool.dmi'
|
||||
icon_state = "bottom"
|
||||
density = FALSE
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
layer = ABOVE_MOB_LAYER
|
||||
anchored = TRUE
|
||||
resistance_flags = INDESTRUCTIBLE
|
||||
|
||||
/obj/effect/overlay/water/top
|
||||
icon_state = "top"
|
||||
layer = BELOW_MOB_LAYER
|
||||
|
||||
// Mousedrop hook to normal turfs to get out of pools.
|
||||
/turf/open/MouseDrop_T(atom/from, mob/user)
|
||||
// I could make this /open/floor and not have the !istype but ehh - kev
|
||||
if(isliving(from) && HAS_TRAIT(from, TRAIT_SWIMMING) && isliving(user) && ((user == from) || user.CanReach(from)) && !user.IsStun() && !user.IsKnockdown() && !user.incapacitated() && !istype(src, /turf/open/pool))
|
||||
var/mob/living/L = from
|
||||
//The element only exists if you're on water and a living mob, so let's skip those checks.
|
||||
var/pre_msg
|
||||
var/post_msg
|
||||
if(user == from)
|
||||
pre_msg = "<span class='notice'>[L] is getting out of the pool.</span>"
|
||||
post_msg = "<span class='notice'>[L] gets out of the pool.</span>"
|
||||
else
|
||||
pre_msg = "<span class='notice'>[L] is being pulled out of the pool by [user].</span>"
|
||||
post_msg = "<span class='notice'>[user] pulls [L] out of the pool.</span>"
|
||||
L.visible_message(pre_msg)
|
||||
if(do_mob(user, L, 20))
|
||||
L.visible_message(post_msg)
|
||||
L.forceMove(src)
|
||||
else
|
||||
return ..()
|
||||
|
||||
// Exit check
|
||||
/turf/open/pool/Exit(atom/movable/AM, atom/newloc)
|
||||
if(!AM.has_gravity(src))
|
||||
return ..()
|
||||
if(isliving(AM) || isstructure(AM))
|
||||
if(AM.throwing)
|
||||
return ..() //WHEEEEEEEEEEE
|
||||
if(istype(AM, /obj/structure) && isliving(AM.pulledby))
|
||||
return ..() //people pulling stuff out of pool
|
||||
if(!ishuman(AM))
|
||||
return ..() //human weak, monkey (and anyone else) ook ook eek eek strong
|
||||
if(isliving(AM) && (locate(/obj/structure/pool/ladder) in src))
|
||||
return ..() //climbing out
|
||||
return istype(newloc, /turf/open/pool)
|
||||
return ..()
|
||||
|
||||
// Exited logic
|
||||
/turf/open/pool/Exited(atom/A, atom/newLoc)
|
||||
. = ..()
|
||||
if(isliving(A))
|
||||
var/turf/open/pool/P = newLoc
|
||||
if(!istype(P) || (P.controller != controller))
|
||||
controller?.mobs_in_pool -= A
|
||||
|
||||
// Entered logic
|
||||
/turf/open/pool/Entered(atom/movable/AM, atom/oldloc)
|
||||
if(istype(AM, /obj/effect/decal/cleanable))
|
||||
var/obj/effect/decal/cleanable/C = AM
|
||||
if(prob(C.bloodiness))
|
||||
controller.set_bloody(TRUE)
|
||||
QDEL_IN(AM, 25)
|
||||
animate(AM, alpha = 10, time = 20)
|
||||
return ..()
|
||||
if(!AM.has_gravity(src))
|
||||
return ..()
|
||||
if(isliving(AM))
|
||||
var/mob/living/victim = AM
|
||||
if(!HAS_TRAIT(victim, TRAIT_SWIMMING)) //poor guy not swimming time to dunk them!
|
||||
victim.AddElement(/datum/element/swimming)
|
||||
controller.mobs_in_pool += victim
|
||||
if(locate(/obj/structure/pool/ladder) in src) //safe climbing
|
||||
return
|
||||
if(iscarbon(AM)) //FUN TIME!
|
||||
var/mob/living/carbon/H = victim
|
||||
if(filled)
|
||||
if (H.wear_mask && H.wear_mask.flags_cover & MASKCOVERSMOUTH)
|
||||
H.visible_message("<span class='danger'>[H] falls in the water!</span>",
|
||||
"<span class='userdanger'>You fall in the water!</span>")
|
||||
playsound(src, 'sound/effects/splash.ogg', 60, TRUE, 1)
|
||||
H.Knockdown(20)
|
||||
return
|
||||
else
|
||||
H.Knockdown(60)
|
||||
H.adjustOxyLoss(5)
|
||||
H.emote("cough")
|
||||
H.visible_message("<span class='danger'>[H] falls in and takes a drink!</span>",
|
||||
"<span class='userdanger'>You fall in and swallow some water!</span>")
|
||||
playsound(src, 'sound/effects/splash.ogg', 60, TRUE, 1)
|
||||
else if(!H.head || !(H.head.armor.getRating("melee") > 20))
|
||||
if(prob(75))
|
||||
H.visible_message("<span class='danger'>[H] falls in the drained pool!</span>",
|
||||
"<span class='userdanger'>You fall in the drained pool!</span>")
|
||||
H.adjustBruteLoss(7)
|
||||
H.Knockdown(80)
|
||||
playsound(src, 'sound/effects/woodhit.ogg', 60, TRUE, 1)
|
||||
else
|
||||
H.visible_message("<span class='danger'>[H] falls in the drained pool, and cracks his skull!</span>",
|
||||
"<span class='userdanger'>You fall in the drained pool, and crack your skull!</span>")
|
||||
H.apply_damage(15, BRUTE, "head")
|
||||
H.Knockdown(200) // This should hurt. And it does.
|
||||
playsound(src, 'sound/effects/woodhit.ogg', 60, TRUE, 1)
|
||||
playsound(src, 'sound/misc/crack.ogg', 100, TRUE)
|
||||
else
|
||||
H.visible_message("<span class='danger'>[H] falls in the drained pool, but had an helmet!</span>",
|
||||
"<span class='userdanger'>You fall in the drained pool, but you had an helmet!</span>")
|
||||
H.Knockdown(40)
|
||||
playsound(src, 'sound/effects/woodhit.ogg', 60, TRUE, 1)
|
||||
else if(filled)
|
||||
victim.adjustStaminaLoss(1)
|
||||
playsound(src, "water_wade", 20, TRUE)
|
||||
return ..()
|
||||
|
||||
/turf/open/pool/MouseDrop_T(atom/from, mob/user)
|
||||
. = ..()
|
||||
if(!isliving(from))
|
||||
return
|
||||
var/mob/living/victim = from
|
||||
if(user.stat || user.lying || !Adjacent(user) || !from.Adjacent(user) || !iscarbon(user) || !victim.has_gravity(src) || HAS_TRAIT(victim, TRAIT_SWIMMING))
|
||||
return
|
||||
var/victimname = victim == user? "themselves" : "[victim]"
|
||||
var/starttext = victim == user? "[user] is descending into [src]." : "[user] is lowering [victim] into [src]."
|
||||
user.visible_message("<span class='notice'>[starttext]</span>")
|
||||
if(do_mob(user, victim, 20))
|
||||
user.visible_message("<span class='notice'>[user] lowers [victimname] into [src].</span>")
|
||||
victim.AddElement(/datum/element/swimming) //make sure they have it so they don't fall/whatever
|
||||
victim.forceMove(src)
|
||||
|
||||
/turf/open/pool/attackby(obj/item/W, mob/living/user)
|
||||
if(istype(W, /obj/item/mop) && filled)
|
||||
W.reagents.add_reagent("water", 5)
|
||||
to_chat(user, "<span class='notice'>You wet [W] in [src].</span>")
|
||||
playsound(loc, 'sound/effects/slosh.ogg', 25, TRUE)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/turf/open/pool/attack_hand(mob/living/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if((user.loc != src) && !user.IsStun() && !user.IsKnockdown() && !user.incapacitated() && Adjacent(user) && HAS_TRAIT(user, TRAIT_SWIMMING) && filled && (next_splash < world.time))
|
||||
playsound(src, 'sound/effects/watersplash.ogg', 8, TRUE, 1)
|
||||
next_splash = world.time + 25
|
||||
var/obj/effect/splash/S = new(src)
|
||||
animate(S, alpha = 0, time = 8)
|
||||
QDEL_IN(S, 10)
|
||||
for(var/mob/living/carbon/human/H in src)
|
||||
if(!H.wear_mask && (H.stat == CONSCIOUS))
|
||||
H.emote("cough")
|
||||
H.adjustStaminaLoss(4)
|
||||
32
code/modules/pool/pool_noodles.dm
Normal file
32
code/modules/pool/pool_noodles.dm
Normal file
@@ -0,0 +1,32 @@
|
||||
//Pool noodles
|
||||
|
||||
/obj/item/toy/poolnoodle
|
||||
icon = 'icons/obj/toy.dmi'
|
||||
icon_state = "noodle"
|
||||
name = "pool noodle"
|
||||
desc = "A strange, bulky, bendable toy that can annoy people."
|
||||
force = 0
|
||||
color = "#000000"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
throwforce = 1
|
||||
throw_speed = 10 //weeee
|
||||
hitsound = 'sound/weapons/tap.ogg'
|
||||
attack_verb = list("flogged", "poked", "jabbed", "slapped", "annoyed")
|
||||
lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/items_righthand.dmi'
|
||||
|
||||
/obj/item/toy/poolnoodle/attack(target as mob, mob/living/user as mob)
|
||||
. = ..()
|
||||
user.spin(prob(20)? 16 : 8, 1)
|
||||
|
||||
/obj/item/toy/poolnoodle/red
|
||||
item_state = "noodlered"
|
||||
color = "#ff4c4c"
|
||||
|
||||
/obj/item/toy/poolnoodle/blue
|
||||
item_state = "noodleblue"
|
||||
color = "#3232ff"
|
||||
|
||||
/obj/item/toy/poolnoodle/yellow
|
||||
item_state = "noodleyellow"
|
||||
color = "#ffff66"
|
||||
159
code/modules/pool/pool_structures.dm
Normal file
159
code/modules/pool/pool_structures.dm
Normal file
@@ -0,0 +1,159 @@
|
||||
/obj/structure/pool
|
||||
name = "pool"
|
||||
icon = 'icons/obj/machines/pool.dmi'
|
||||
anchored = TRUE
|
||||
resistance_flags = UNACIDABLE|INDESTRUCTIBLE
|
||||
|
||||
/obj/structure/pool/ladder
|
||||
name = "Ladder"
|
||||
icon_state = "ladder"
|
||||
desc = "Are you getting in or are you getting out?."
|
||||
layer = ABOVE_MOB_LAYER
|
||||
dir = EAST
|
||||
|
||||
/obj/structure/pool/ladder/attack_hand(mob/living/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(!HAS_TRAIT(user, TRAIT_SWIMMING))
|
||||
if(user.CanReach(src))
|
||||
user.AddElement(/datum/element/swimming)
|
||||
user.forceMove(get_step(src, dir))
|
||||
else
|
||||
if(user.loc == loc)
|
||||
user.forceMove(get_step(src, turn(dir, 180))) //If this moves them out the element cleans up after itself.
|
||||
|
||||
/obj/structure/pool/Rboard
|
||||
name = "JumpBoard"
|
||||
density = FALSE
|
||||
icon_state = "boardright"
|
||||
desc = "The less-loved portion of the jumping board."
|
||||
dir = EAST
|
||||
|
||||
/obj/structure/pool/Lboard
|
||||
name = "JumpBoard"
|
||||
icon_state = "boardleft"
|
||||
desc = "Get on there to jump!"
|
||||
layer = FLY_LAYER
|
||||
dir = WEST
|
||||
var/jumping = FALSE
|
||||
var/timer
|
||||
|
||||
/obj/structure/pool/Lboard/proc/backswim()
|
||||
if(jumping)
|
||||
for(var/mob/living/jumpee in loc) //hackzors.
|
||||
playsound(jumpee, 'sound/effects/splash.ogg', 60, TRUE, 1)
|
||||
if(!HAS_TRAIT(jumpee, TRAIT_SWIMMING))
|
||||
jumpee.AddElement(/datum/element/swimming)
|
||||
jumpee.Stun(2)
|
||||
|
||||
/obj/structure/pool/Lboard/proc/reset_position(mob/user, initial_layer, initial_px, initial_py)
|
||||
user.layer = initial_layer
|
||||
user.pixel_x = initial_px
|
||||
user.pixel_y = initial_py
|
||||
|
||||
/obj/structure/pool/Lboard/attack_hand(mob/living/user)
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/jumper = user
|
||||
if(jumping)
|
||||
to_chat(user, "<span class='notice'>Someone else is already making a jump!</span>")
|
||||
return
|
||||
var/turf/T = get_turf(src)
|
||||
if(HAS_TRAIT(user, TRAIT_SWIMMING))
|
||||
return
|
||||
else
|
||||
if(Adjacent(jumper))
|
||||
jumper.visible_message("<span class='notice'>[user] climbs up \the [src]!</span>", \
|
||||
"<span class='notice'>You climb up \the [src] and prepares to jump!</span>")
|
||||
jumper.Stun(40)
|
||||
jumping = TRUE
|
||||
var/original_layer = jumper.layer
|
||||
var/original_px = jumper.pixel_x
|
||||
var/original_py = jumper.pixel_y
|
||||
jumper.layer = RIPPLE_LAYER
|
||||
jumper.pixel_x = 3
|
||||
jumper.pixel_y = 7
|
||||
jumper.dir = WEST
|
||||
jumper.AddElement(/datum/element/swimming)
|
||||
sleep(1)
|
||||
jumper.forceMove(T)
|
||||
addtimer(CALLBACK(src, .proc/dive, jumper, original_layer, original_px, original_py), 10)
|
||||
|
||||
/obj/structure/pool/Lboard/proc/dive(mob/living/carbon/jumper, original_layer, original_px, original_py)
|
||||
switch(rand(1, 100))
|
||||
if(1 to 20)
|
||||
jumper.visible_message("<span class='notice'>[jumper] goes for a small dive!</span>", \
|
||||
"<span class='notice'>You go for a small dive.</span>")
|
||||
sleep(15)
|
||||
backswim()
|
||||
var/atom/throw_target = get_edge_target_turf(src, dir)
|
||||
jumper.throw_at(throw_target, 1, 1, callback = CALLBACK(src, .proc/on_finish_jump, jumper))
|
||||
|
||||
if(21 to 40)
|
||||
jumper.visible_message("<span class='notice'>[jumper] goes for a dive!</span>", \
|
||||
"<span class='notice'>You're going for a dive!</span>")
|
||||
sleep(20)
|
||||
backswim()
|
||||
var/atom/throw_target = get_edge_target_turf(src, dir)
|
||||
jumper.throw_at(throw_target, 2, 1, callback = CALLBACK(src, .proc/on_finish_jump, jumper))
|
||||
|
||||
if(41 to 60)
|
||||
jumper.visible_message("<span class='notice'>[jumper] goes for a long dive! Stay far away!</span>", \
|
||||
"<span class='notice'>You're going for a long dive!!</span>")
|
||||
sleep(25)
|
||||
backswim()
|
||||
var/atom/throw_target = get_edge_target_turf(src, dir)
|
||||
jumper.throw_at(throw_target, 3, 1, callback = CALLBACK(src, .proc/on_finish_jump, jumper))
|
||||
|
||||
if(61 to 80)
|
||||
jumper.visible_message("<span class='notice'>[jumper] goes for an awesome dive! Don't stand in [jumper.p_their()] way!</span>", \
|
||||
"<span class='notice'>You feel like this dive will be awesome</span>")
|
||||
sleep(30)
|
||||
backswim()
|
||||
var/atom/throw_target = get_edge_target_turf(src, dir)
|
||||
jumper.throw_at(throw_target, 4, 1, callback = CALLBACK(src, .proc/on_finish_jump, jumper))
|
||||
if(81 to 91)
|
||||
sleep(20)
|
||||
backswim()
|
||||
jumper.visible_message("<span class='danger'>[jumper] misses [jumper.p_their()] step!</span>", \
|
||||
"<span class='userdanger'>You misstep!</span>")
|
||||
var/atom/throw_target = get_edge_target_turf(src, dir)
|
||||
jumper.throw_at(throw_target, 0, 1, callback = CALLBACK(src, .proc/on_finish_jump, jumper))
|
||||
jumper.Knockdown(100)
|
||||
jumper.adjustBruteLoss(10)
|
||||
|
||||
if(91 to 100)
|
||||
jumper.visible_message("<span class='notice'>[jumper] is preparing for the legendary dive! Can [jumper.p_they()] make it?</span>", \
|
||||
"<span class='userdanger'>You start preparing for a legendary dive!</span>")
|
||||
jumper.SpinAnimation(7,1)
|
||||
|
||||
sleep(30)
|
||||
if(prob(75))
|
||||
backswim()
|
||||
jumper.visible_message("<span class='notice'>[jumper] fails!</span>", \
|
||||
"<span class='userdanger'>You can't quite do it!</span>")
|
||||
var/atom/throw_target = get_edge_target_turf(src, dir)
|
||||
jumper.throw_at(throw_target, 1, 1, callback = CALLBACK(src, .proc/on_finish_jump, jumper))
|
||||
else
|
||||
jumper.fire_stacks = min(1,jumper.fire_stacks + 1)
|
||||
jumper.IgniteMob()
|
||||
sleep(5)
|
||||
backswim()
|
||||
jumper.visible_message("<span class='danger'>[jumper] bursts into flames of pure awesomness!</span>", \
|
||||
"<span class='userdanger'>No one can stop you now!</span>")
|
||||
var/atom/throw_target = get_edge_target_turf(src, dir)
|
||||
jumper.throw_at(throw_target, 6, 1, callback = CALLBACK(src, .proc/on_finish_jump, jumper))
|
||||
addtimer(CALLBACK(src, .proc/togglejumping), 35)
|
||||
reset_position(jumper, original_layer, original_px, original_py)
|
||||
|
||||
/obj/structure/pool/Lboard/proc/togglejumping()
|
||||
jumping = FALSE
|
||||
|
||||
/obj/structure/pool/Lboard/proc/on_finish_jump(mob/living/victim)
|
||||
if(istype(victim.loc, /turf/open/pool))
|
||||
var/turf/open/pool/P = victim.loc
|
||||
if(!P.filled) //you dun fucked up now
|
||||
to_chat(victim, "<span class='warning'>That was stupid of you..</span>")
|
||||
victim.visible_message("<span class='danger'>[victim] smashes into the ground!</span>")
|
||||
victim.apply_damage(50)
|
||||
victim.Knockdown(200)
|
||||
59
code/modules/pool/pool_wires.dm
Normal file
59
code/modules/pool/pool_wires.dm
Normal file
@@ -0,0 +1,59 @@
|
||||
#define POOL_WIRE_DRAIN "drain"
|
||||
#define POOL_WIRE_TEMP "temp"
|
||||
|
||||
|
||||
/datum/wires/poolcontroller
|
||||
holder_type = /obj/machinery/pool/controller
|
||||
proper_name = "Pool"
|
||||
|
||||
/datum/wires/poolcontroller/New(atom/holder)
|
||||
wires = list(
|
||||
POOL_WIRE_DRAIN, WIRE_SHOCK, WIRE_ZAP, POOL_WIRE_TEMP
|
||||
)
|
||||
add_duds(3)
|
||||
..()
|
||||
|
||||
/datum/wires/poolcontroller/interactable(mob/user)
|
||||
var/obj/machinery/pool/controller/P = holder
|
||||
if(P.panel_open)
|
||||
return TRUE
|
||||
|
||||
/datum/wires/poolcontroller/get_status()
|
||||
var/obj/machinery/pool/controller/P = holder
|
||||
var/list/status = list()
|
||||
status += "The blue light is [P.drainable ? "on" : "off"]."
|
||||
status += "The red light is [P.temperature_unlocked ? "on" : "off"]."
|
||||
status += "The yellow light is [P.shocked ? "on" : "off"]."
|
||||
return status
|
||||
|
||||
/datum/wires/poolcontroller/on_pulse(wire)
|
||||
var/obj/machinery/pool/controller/P = holder
|
||||
switch(wire)
|
||||
if(POOL_WIRE_DRAIN)
|
||||
P.drainable = FALSE
|
||||
if(POOL_WIRE_TEMP)
|
||||
P.temperature_unlocked = FALSE
|
||||
if(WIRE_SHOCK)
|
||||
P.shocked = !P.shocked
|
||||
addtimer(CALLBACK(P, /obj/machinery/autolathe.proc/reset, wire), 60)
|
||||
|
||||
/datum/wires/poolcontroller/on_cut(wire, mend)
|
||||
var/obj/machinery/pool/controller/P = holder
|
||||
switch(wire)
|
||||
if(POOL_WIRE_DRAIN)
|
||||
if(mend)
|
||||
P.drainable = FALSE
|
||||
else
|
||||
P.drainable = TRUE
|
||||
if(POOL_WIRE_TEMP)
|
||||
if(mend)
|
||||
P.temperature_unlocked = FALSE
|
||||
else
|
||||
P.temperature_unlocked = TRUE
|
||||
if(WIRE_ZAP)
|
||||
P.shock(usr, 50)
|
||||
if(WIRE_SHOCK)
|
||||
if(mend)
|
||||
P.stat &= ~NOPOWER
|
||||
else
|
||||
P.stat |= NOPOWER
|
||||
@@ -846,7 +846,7 @@
|
||||
return
|
||||
|
||||
/obj/machinery/power/apc/oui_canview(mob/user)
|
||||
if(user.has_unlimited_silicon_privilege || area.hasSiliconAccessInArea(user))
|
||||
if(area.hasSiliconAccessInArea(user)) //some APCs are mapped outside their assigned area, so this is required.
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
@@ -864,7 +864,7 @@
|
||||
if (H && !H.stealthmode && H.toggled)
|
||||
abilitiesavail = TRUE
|
||||
var/list/data = list(
|
||||
"locked" = locked && !(integration_cog && is_servant_of_ratvar(user)) && !area.hasSiliconAccessInArea(user),
|
||||
"locked" = locked && !(integration_cog && is_servant_of_ratvar(user)) && !area.hasSiliconAccessInArea(user, PRIVILEDGES_SILICON|PRIVILEDGES_DRONE),
|
||||
"lock_nightshift" = nightshift_requires_auth,
|
||||
"failTime" = failure_timer,
|
||||
"isOperating" = operating,
|
||||
@@ -874,7 +874,7 @@
|
||||
"chargingStatus" = charging,
|
||||
"totalLoad" = DisplayPower(lastused_total),
|
||||
"coverLocked" = coverlocked,
|
||||
"siliconUser" = user.has_unlimited_silicon_privilege || user.using_power_flow_console() || area.hasSiliconAccessInArea(user),
|
||||
"siliconUser" = user.using_power_flow_console() || area.hasSiliconAccessInArea(user),
|
||||
"malfStatus" = get_malf_status(user),
|
||||
"emergencyLights" = !emergency_lights,
|
||||
"nightshiftLights" = nightshift_lights,
|
||||
@@ -951,7 +951,7 @@
|
||||
return TRUE
|
||||
if (user == hijacker || (area.hasSiliconAccessInArea(user) && !aidisabled))
|
||||
return TRUE
|
||||
if(user.has_unlimited_silicon_privilege)
|
||||
if(user.silicon_privileges & PRIVILEDGES_SILICON)
|
||||
var/mob/living/silicon/ai/AI = user
|
||||
var/mob/living/silicon/robot/robot = user
|
||||
if (src.aidisabled || malfhack && istype(malfai) && ((istype(AI) && (malfai!=AI && malfai != AI.parent)) || (istype(robot) && (robot in malfai.connected_robots))))
|
||||
@@ -985,7 +985,7 @@
|
||||
if (action == "hijack" && can_use(usr, 1)) //don't need auth for hijack button
|
||||
hijack(usr)
|
||||
return
|
||||
var/authorized = (!locked || usr.has_unlimited_silicon_privilege || area.hasSiliconAccessInArea(usr) || (integration_cog && (is_servant_of_ratvar(usr))))
|
||||
var/authorized = (!locked || area.hasSiliconAccessInArea(usr, PRIVILEDGES_SILICON|PRIVILEDGES_DRONE) || (integration_cog && (is_servant_of_ratvar(usr))))
|
||||
if((action == "toggle_nightshift") && (!nightshift_requires_auth || authorized))
|
||||
toggle_nightshift_lights()
|
||||
return TRUE
|
||||
@@ -993,7 +993,7 @@
|
||||
return
|
||||
switch(action)
|
||||
if("lock")
|
||||
if(usr.has_unlimited_silicon_privilege || area.hasSiliconAccessInArea(usr))
|
||||
if(area.hasSiliconAccessInArea(usr))
|
||||
if((obj_flags & EMAGGED) || (stat & (BROKEN|MAINT)))
|
||||
to_chat(usr, "The APC does not respond to the command.")
|
||||
else
|
||||
@@ -1027,7 +1027,7 @@
|
||||
update()
|
||||
return TRUE
|
||||
if("overload")
|
||||
if(usr.has_unlimited_silicon_privilege || area.hasSiliconAccessInArea(usr))
|
||||
if(area.hasSiliconAccessInArea(usr))
|
||||
overload_lighting()
|
||||
return TRUE
|
||||
if("hack")
|
||||
|
||||
@@ -357,16 +357,10 @@
|
||||
maxcharge = 12000
|
||||
chargerate = 600
|
||||
|
||||
/obj/item/stock_parts/cell/magnetic/empty
|
||||
start_charged = FALSE
|
||||
|
||||
/obj/item/stock_parts/cell/magnetic/pistol
|
||||
name = "magpistol power supply"
|
||||
maxcharge = 6000
|
||||
|
||||
/obj/item/stock_parts/cell/magnetic/pistol/empty
|
||||
start_charged = FALSE
|
||||
|
||||
/obj/item/stock_parts/cell/toymagburst
|
||||
name = "toy mag burst rifle power supply"
|
||||
maxcharge = 4000
|
||||
|
||||
@@ -24,7 +24,16 @@
|
||||
|
||||
/obj/machinery/power/solar/Initialize(mapload, obj/item/solar_assembly/S)
|
||||
. = ..()
|
||||
Make(S)
|
||||
if(!S)
|
||||
assembly = new /obj/item/solar_assembly
|
||||
assembly.glass_type = new /obj/item/stack/sheet/glass(null, 2)
|
||||
assembly.anchored = TRUE
|
||||
else
|
||||
S.moveToNullspace()
|
||||
assembly = S
|
||||
assembly.glass_type.on_solar_construction(src)
|
||||
obj_integrity = max_integrity
|
||||
update_icon()
|
||||
connect_to_network()
|
||||
|
||||
/obj/machinery/power/solar/Destroy()
|
||||
@@ -45,17 +54,6 @@
|
||||
control.connected_panels.Remove(src)
|
||||
control = null
|
||||
|
||||
/obj/machinery/power/solar/proc/Make(obj/item/solar_assembly/S)
|
||||
if(!S)
|
||||
S = new /obj/item/solar_assembly
|
||||
S.glass_type = new /obj/item/stack/sheet/glass(null, 2)
|
||||
S.anchored = TRUE
|
||||
else
|
||||
S.moveToNullspace()
|
||||
S.glass_type.on_solar_construction(src)
|
||||
obj_integrity = max_integrity
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/power/solar/crowbar_act(mob/user, obj/item/I)
|
||||
playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
|
||||
user.visible_message("[user] begins to take the glass off [src].", "<span class='notice'>You begin to take the glass off [src]...</span>")
|
||||
@@ -201,7 +199,7 @@
|
||||
new shard(Tsec)
|
||||
new shard(Tsec)
|
||||
else if(glass_type)
|
||||
forceMove(glass_type, Tsec)
|
||||
glass_type.forceMove(Tsec)
|
||||
glass_type = null
|
||||
|
||||
/obj/item/solar_assembly/attackby(obj/item/W, mob/user, params)
|
||||
@@ -226,7 +224,8 @@
|
||||
var/obj/item/stack/sheet/G = S.change_stack(null, 2)
|
||||
if(G)
|
||||
glass_type = G
|
||||
playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
|
||||
G.moveToNullspace()
|
||||
playsound(loc, 'sound/machines/click.ogg', 50, 1)
|
||||
user.visible_message("[user] places the glass on the solar assembly.", "<span class='notice'>You place the glass on the solar assembly.</span>")
|
||||
if(tracker)
|
||||
new /obj/machinery/power/tracker(get_turf(src), src)
|
||||
|
||||
@@ -346,6 +346,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
|
||||
// Pass all the gas related code an empty gas container
|
||||
removed = new()
|
||||
|
||||
damage = min(damage_archived + (DAMAGE_HARDCAP * explosion_point),damage) // hardcap any direct damage taken before doing atmos damage
|
||||
damage_archived = damage
|
||||
if(!removed || !removed.total_moles() || isspaceturf(T)) //we're in space or there is no gas to process
|
||||
if(takes_damage)
|
||||
|
||||
@@ -20,7 +20,15 @@
|
||||
|
||||
/obj/machinery/power/tracker/Initialize(mapload, obj/item/solar_assembly/S)
|
||||
. = ..()
|
||||
Make(S)
|
||||
if(!S)
|
||||
assembly = new /obj/item/solar_assembly
|
||||
assembly.glass_type = new /obj/item/stack/sheet/glass(null, 2)
|
||||
assembly.tracker = TRUE
|
||||
assembly.anchored = TRUE
|
||||
else
|
||||
S.moveToNullspace()
|
||||
assembly = S
|
||||
update_icon()
|
||||
connect_to_network()
|
||||
|
||||
/obj/machinery/power/tracker/Destroy()
|
||||
@@ -41,16 +49,6 @@
|
||||
control.connected_tracker = null
|
||||
control = null
|
||||
|
||||
/obj/machinery/power/tracker/proc/Make(obj/item/solar_assembly/S)
|
||||
if(!S)
|
||||
S = new /obj/item/solar_assembly
|
||||
S.glass_type = new /obj/item/stack/sheet/glass(null, 2)
|
||||
S.tracker = TRUE
|
||||
S.anchored = TRUE
|
||||
else
|
||||
S.moveToNullspace()
|
||||
update_icon()
|
||||
|
||||
//updates the tracker icon and the facing angle for the control computer
|
||||
/obj/machinery/power/tracker/proc/set_angle(angle)
|
||||
sun_angle = angle
|
||||
|
||||
@@ -5,4 +5,22 @@
|
||||
caliber = "arrow"
|
||||
icon_state = "arrow"
|
||||
throwforce = 3 //good luck hitting someone with the pointy end of the arrow
|
||||
throw_speed = 3
|
||||
throw_speed = 3
|
||||
|
||||
/obj/item/ammo_casing/caseless/arrow/ashen
|
||||
name = "ashen arrow"
|
||||
desc = "Fire harderned wooden arrow."
|
||||
icon_state = "asharrow"
|
||||
projectile_type = /obj/item/projectile/bullet/reusable/arrow/ashen
|
||||
|
||||
/obj/item/ammo_casing/caseless/arrow/bone
|
||||
name = "bone arrow"
|
||||
desc = "Arrow made of bone and sinew. The tip is sharp enough to pierce into a goliath plate."
|
||||
icon_state = "bonearrow"
|
||||
projectile_type = /obj/item/projectile/bullet/reusable/arrow/bone
|
||||
|
||||
/obj/item/ammo_casing/caseless/arrow/bronze
|
||||
name = "bronze arrow"
|
||||
desc = "Bronze tipped arrow."
|
||||
icon_state = "bronzearrow"
|
||||
projectile_type = /obj/item/projectile/bullet/reusable/arrow/bronze
|
||||
|
||||
@@ -50,4 +50,19 @@
|
||||
icon_state = "bow_[get_ammo() ? (chambered ? "firing" : "loaded") : "unloaded"]"
|
||||
|
||||
/obj/item/gun/ballistic/bow/can_shoot()
|
||||
return chambered
|
||||
return chambered
|
||||
|
||||
/obj/item/gun/ballistic/bow/ashen
|
||||
name = "bone bow"
|
||||
desc = "Some sort of primitive projectile weapon made of bone and sinew. Used to fire arrows."
|
||||
icon_state = "ashenbow"
|
||||
item_state = "ashenbow"
|
||||
force = 8
|
||||
|
||||
/obj/item/gun/ballistic/bow/pipe
|
||||
name = "pipe bow"
|
||||
desc = "Some sort of pipe made projectile weapon made of a silk string and lots of bending. Used to fire arrows."
|
||||
icon_state = "pipebow"
|
||||
item_state = "pipebow"
|
||||
inaccuracy_modifier = 1.1 //Made of pipe and in a rush
|
||||
force = 0
|
||||
@@ -61,7 +61,6 @@
|
||||
/obj/item/gun/ballistic/automatic/magrifle/nopin
|
||||
pin = null
|
||||
spawnwithmagazine = FALSE
|
||||
cell_type = /obj/item/stock_parts/cell/magnetic/empty
|
||||
|
||||
/obj/item/gun/ballistic/automatic/magrifle/hyperburst
|
||||
name = "\improper Hyper-Burst Rifle"
|
||||
@@ -100,4 +99,3 @@
|
||||
/obj/item/gun/ballistic/automatic/magrifle/pistol/nopin
|
||||
pin = null
|
||||
spawnwithmagazine = FALSE
|
||||
cell_type = /obj/item/stock_parts/cell/magnetic/pistol/empty
|
||||
|
||||
@@ -67,7 +67,8 @@
|
||||
/obj/item/gun/energy/Destroy()
|
||||
if(flags_1 & INITIALIZED_1)
|
||||
QDEL_NULL(cell)
|
||||
QDEL_LIST(ammo_type)
|
||||
if(!(flags_1 & HOLOGRAM_1)) //holodeck stuff.
|
||||
QDEL_LIST(ammo_type)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
/obj/item/gun/energy/laser/practice
|
||||
name = "practice laser gun"
|
||||
icon_state = "laser-p"
|
||||
desc = "A modified version of the basic laser gun, this one fires less concentrated energy bolts designed for target practice."
|
||||
ammo_type = list(/obj/item/ammo_casing/energy/laser/practice)
|
||||
clumsy_check = 0
|
||||
|
||||
@@ -52,7 +52,6 @@
|
||||
var/hitscan = FALSE //Whether this is hitscan. If it is, speed is basically ignored.
|
||||
var/list/beam_segments //assoc list of datum/point or datum/point/vector, start = end. Used for hitscan effect generation.
|
||||
var/datum/point/beam_index
|
||||
var/turf/hitscan_last //last turf touched during hitscanning.
|
||||
var/tracer_type
|
||||
var/muzzle_type
|
||||
var/impact_type
|
||||
@@ -492,8 +491,6 @@
|
||||
process_homing()
|
||||
var/forcemoved = FALSE
|
||||
for(var/i in 1 to SSprojectiles.global_iterations_per_move)
|
||||
if(QDELETED(src))
|
||||
return
|
||||
trajectory.increment(trajectory_multiplier)
|
||||
var/turf/T = trajectory.return_turf()
|
||||
if(!istype(T))
|
||||
@@ -506,14 +503,16 @@
|
||||
forceMove(T)
|
||||
trajectory_ignore_forcemove = FALSE
|
||||
after_z_change(old, loc)
|
||||
forcemoved = TRUE
|
||||
if(QDELETED(src))
|
||||
return
|
||||
if(!hitscanning)
|
||||
pixel_x = trajectory.return_px()
|
||||
pixel_y = trajectory.return_py()
|
||||
forcemoved = TRUE
|
||||
hitscan_last = loc
|
||||
else if(T != loc)
|
||||
step_towards(src, T)
|
||||
hitscan_last = loc
|
||||
if(QDELETED(src))
|
||||
return
|
||||
if(!hitscanning && !forcemoved)
|
||||
pixel_x = trajectory.return_px() - trajectory.mpx * trajectory_multiplier * SSprojectiles.global_iterations_per_move
|
||||
pixel_y = trajectory.return_py() - trajectory.mpy * trajectory_multiplier * SSprojectiles.global_iterations_per_move
|
||||
|
||||
@@ -7,10 +7,11 @@
|
||||
var/zap_range = 3
|
||||
var/power = 10000
|
||||
|
||||
/obj/item/projectile/energy/tesla/fire(setAngle)
|
||||
if(firer)
|
||||
chain = firer.Beam(src, icon_state = "lightning[rand(1, 12)]", time = INFINITY, maxdistance = INFINITY)
|
||||
..()
|
||||
/obj/item/projectile/energy/tesla/fire(setAngle, atom/direct_target)
|
||||
var/atom/source = fired_from || firer
|
||||
if(source)
|
||||
chain = source.Beam(src, icon_state = "lightning[rand(1, 12)]", time = INFINITY, maxdistance = INFINITY)
|
||||
return ..()
|
||||
|
||||
/obj/item/projectile/energy/tesla/on_hit(atom/target)
|
||||
. = ..()
|
||||
|
||||
@@ -3,4 +3,23 @@
|
||||
desc = "Woosh!"
|
||||
damage = 15
|
||||
icon_state = "arrow"
|
||||
ammo_type = /obj/item/ammo_casing/caseless/arrow
|
||||
ammo_type = /obj/item/ammo_casing/caseless/arrow
|
||||
|
||||
/obj/item/projectile/bullet/reusable/arrow/ashen
|
||||
name = "ashen arrow"
|
||||
desc = "Fire harderned arrow."
|
||||
damage = 25
|
||||
ammo_type = /obj/item/ammo_casing/caseless/arrow/ashen
|
||||
|
||||
/obj/item/projectile/bullet/reusable/arrow/bone //AP for ashwalkers
|
||||
name = "bone arrow"
|
||||
desc = "Arrow made of bone and sinew."
|
||||
damage = 35
|
||||
armour_penetration = 40
|
||||
ammo_type = /obj/item/ammo_casing/caseless/arrow/bone
|
||||
|
||||
/obj/item/projectile/bullet/reusable/arrow/bronze //Just some AP shots
|
||||
name = "bronze arrow"
|
||||
desc = "Bronze tipped arrow."
|
||||
armour_penetration = 10
|
||||
ammo_type = /obj/item/ammo_casing/caseless/arrow/bronze
|
||||
|
||||
@@ -43,4 +43,34 @@
|
||||
explosion(target, 0, 1, 2, 4)
|
||||
else
|
||||
explosion(target, 0, 0, 2, 4)
|
||||
return BULLET_ACT_HIT
|
||||
return BULLET_ACT_HIT
|
||||
|
||||
/obj/item/projectile/bullet/a84mm_br
|
||||
name ="\improper HE missile"
|
||||
desc = "Boom."
|
||||
icon_state = "missile"
|
||||
damage = 30
|
||||
ricochets_max = 0 //it's a MISSILE
|
||||
var/sturdy = list(
|
||||
/turf/closed,
|
||||
/obj/mecha,
|
||||
/obj/machinery/door/,
|
||||
/obj/machinery/door/poddoor/shutters
|
||||
)
|
||||
|
||||
/obj/item/broken_missile
|
||||
name = "\improper broken missile"
|
||||
desc = "A missile that did not detonate. The tail has snapped and it is in no way fit to be used again."
|
||||
icon = 'icons/obj/projectiles.dmi'
|
||||
icon_state = "missile_broken"
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
|
||||
|
||||
/obj/item/projectile/bullet/a84mm_br/on_hit(atom/target, blocked=0)
|
||||
..()
|
||||
for(var/i in sturdy)
|
||||
if(istype(target, i))
|
||||
explosion(target, 0, 1, 1, 2)
|
||||
return BULLET_ACT_HIT
|
||||
//if(istype(target, /turf/closed) || ismecha(target))
|
||||
new /obj/item/broken_missile(get_turf(src), 1)
|
||||
@@ -77,6 +77,8 @@
|
||||
|
||||
/datum/reagents/Destroy()
|
||||
. = ..()
|
||||
//We're about to delete all reagents, so lets cleanup
|
||||
addiction_list.Cut()
|
||||
var/list/cached_reagents = reagent_list
|
||||
for(var/reagent in cached_reagents)
|
||||
var/datum/reagent/R = reagent
|
||||
@@ -332,9 +334,7 @@
|
||||
if(R.addiction_stage3_end to R.addiction_stage4_end)
|
||||
need_mob_update += R.addiction_act_stage4(C)
|
||||
if(R.addiction_stage4_end to INFINITY)
|
||||
to_chat(C, "<span class='notice'>You feel like you've gotten over your need for [R.name].</span>")
|
||||
SEND_SIGNAL(C, COMSIG_CLEAR_MOOD_EVENT, "[R.type]_addiction")
|
||||
cached_addictions.Remove(R)
|
||||
remove_addiction(R)
|
||||
else
|
||||
SEND_SIGNAL(C, COMSIG_CLEAR_MOOD_EVENT, "[R.type]_overdose")
|
||||
addiction_tick++
|
||||
@@ -344,6 +344,12 @@
|
||||
C.update_stamina()
|
||||
update_total()
|
||||
|
||||
/datum/reagents/proc/remove_addiction(datum/reagent/R)
|
||||
to_chat(my_atom, "<span class='notice'>You feel like you've gotten over your need for [R.name].</span>")
|
||||
SEND_SIGNAL(my_atom, COMSIG_CLEAR_MOOD_EVENT, "[R.type]_overdose")
|
||||
addiction_list.Remove(R)
|
||||
qdel(R)
|
||||
|
||||
//Signals that metabolization has stopped, triggering the end of trait-based effects
|
||||
/datum/reagents/proc/end_metabolization(mob/living/carbon/C, keep_liverless = TRUE)
|
||||
var/list/cached_reagents = reagent_list
|
||||
@@ -762,6 +768,8 @@
|
||||
R.metabolizing = FALSE
|
||||
R.on_mob_end_metabolize(M)
|
||||
R.on_mob_delete(M)
|
||||
//Clear from relevant lists
|
||||
addiction_list -= R
|
||||
qdel(R)
|
||||
reagent_list -= R
|
||||
update_total()
|
||||
|
||||
@@ -408,7 +408,7 @@
|
||||
if(beaker)
|
||||
var/obj/item/reagent_containers/B = beaker
|
||||
B.forceMove(drop_location())
|
||||
if(user && Adjacent(user) && !issiliconoradminghost(user))
|
||||
if(user && Adjacent(user) && user.can_hold_items())
|
||||
user.put_in_hands(B)
|
||||
if(new_beaker)
|
||||
beaker = new_beaker
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
/obj/machinery/chem_heater/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker)
|
||||
if(beaker)
|
||||
beaker.forceMove(drop_location())
|
||||
if(user && Adjacent(user) && !issiliconoradminghost(user))
|
||||
if(user && Adjacent(user) && user.can_hold_items())
|
||||
user.put_in_hands(beaker)
|
||||
if(new_beaker)
|
||||
beaker = new_beaker
|
||||
|
||||
@@ -129,7 +129,7 @@
|
||||
if(beaker)
|
||||
var/obj/item/reagent_containers/B = beaker
|
||||
B.forceMove(drop_location())
|
||||
if(user && Adjacent(user) && !issiliconoradminghost(user))
|
||||
if(user && Adjacent(user) && user.can_hold_items())
|
||||
user.put_in_hands(B)
|
||||
if(new_beaker)
|
||||
beaker = new_beaker
|
||||
@@ -139,7 +139,7 @@
|
||||
if(bottle)
|
||||
var/obj/item/storage/pill_bottle/B = bottle
|
||||
B.forceMove(drop_location())
|
||||
if(user && Adjacent(user) && !issiliconoradminghost(user))
|
||||
if(user && Adjacent(user) && user.can_hold_items())
|
||||
user.put_in_hands(B)
|
||||
else
|
||||
adjust_item_drop_location(B)
|
||||
|
||||
@@ -192,7 +192,7 @@
|
||||
update_icon()
|
||||
var/turf/source_turf = get_turf(src)
|
||||
log_virus("A culture bottle was printed for the virus [A.admin_details()] at [loc_name(source_turf)] by [key_name(usr)]")
|
||||
|
||||
|
||||
. = TRUE
|
||||
if("create_vaccine_bottle")
|
||||
wait = TRUE
|
||||
@@ -202,9 +202,9 @@
|
||||
var/obj/item/reagent_containers/glass/bottle/B = new(drop_location())
|
||||
B.name = "[D.name] vaccine bottle"
|
||||
B.reagents.add_reagent(/datum/reagent/vaccine, 15, list(id))
|
||||
|
||||
|
||||
update_icon()
|
||||
|
||||
|
||||
. = TRUE
|
||||
|
||||
/obj/machinery/computer/pandemic/attackby(obj/item/I, mob/user, params)
|
||||
@@ -229,7 +229,7 @@
|
||||
|
||||
/obj/machinery/computer/pandemic/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker)
|
||||
if(beaker)
|
||||
if(user && Adjacent(user) && !issiliconoradminghost(user))
|
||||
if(user && Adjacent(user) && user.can_hold_items())
|
||||
if(!user.put_in_hands(beaker))
|
||||
beaker.forceMove(drop_location())
|
||||
if(new_beaker)
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
/obj/machinery/reagentgrinder/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker)
|
||||
if(beaker)
|
||||
beaker.forceMove(drop_location())
|
||||
if(user && Adjacent(user) && !issiliconoradminghost(user))
|
||||
if(user && Adjacent(user) && user.can_hold_items())
|
||||
user.put_in_hands(beaker)
|
||||
if(new_beaker)
|
||||
beaker = new_beaker
|
||||
|
||||
@@ -1482,14 +1482,14 @@ datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M)
|
||||
|
||||
/datum/reagent/medicine/polypyr //This is intended to be an ingredient in advanced chems.
|
||||
name = "Polypyrylium Oligomers"
|
||||
description = "A<EFBFBD>purple mixture of short polyelectrolyte chains not easily synthesized in the laboratory. It is valued as an intermediate in the synthesis of the cutting edge pharmaceuticals."
|
||||
description = "A purple mixture of short polyelectrolyte chains not easily synthesized in the laboratory. It is valued as an intermediate in the synthesis of the cutting edge pharmaceuticals."
|
||||
reagent_state = SOLID
|
||||
color = "#9423FF"
|
||||
metabolization_rate = 0.25 * REAGENTS_METABOLISM
|
||||
overdose_threshold = 50
|
||||
taste_description = "numbing bitterness"
|
||||
|
||||
/datum/reagent/medicine/polypyr/on_mob_life(mob/living/carbon/M) //I w<EFBFBD>nted a collection of small positive effects, this is as hard to obtain as coniine after all.
|
||||
/datum/reagent/medicine/polypyr/on_mob_life(mob/living/carbon/M) //I wanted a collection of small positive effects, this is as hard to obtain as coniine after all.
|
||||
M.adjustOrganLoss(ORGAN_SLOT_LUNGS, -0.25)
|
||||
M.adjustBruteLoss(-0.35, 0)
|
||||
if(prob(50))
|
||||
@@ -1511,4 +1511,3 @@ datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M)
|
||||
M.adjustOrganLoss(ORGAN_SLOT_LUNGS, 0.5)
|
||||
..()
|
||||
. = 1
|
||||
|
||||
|
||||
@@ -93,8 +93,6 @@
|
||||
taste_description = "something spicy"
|
||||
pH = 6.85
|
||||
|
||||
|
||||
|
||||
/datum/reagent/blood/on_merge(list/mix_data)
|
||||
if(data && mix_data)
|
||||
if(data["blood_DNA"] != mix_data["blood_DNA"])
|
||||
@@ -131,16 +129,10 @@
|
||||
/datum/reagent/blood/synthetics
|
||||
data = list("donor"=null,"viruses"=null,"blood_DNA"="REPLICATED", "bloodcolor" = BLOOD_COLOR_SYNTHETIC, "blood_type"="SY","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
|
||||
name = "Synthetic Blood"
|
||||
description = "A synthetically produced imitation of blood."
|
||||
taste_description = "oily"
|
||||
color = BLOOD_COLOR_SYNTHETIC // rgb: 11, 7, 48
|
||||
|
||||
/datum/reagent/blood/lizard
|
||||
data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_LIZARD, "blood_type"="L","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
|
||||
name = "Lizard Blood"
|
||||
taste_description = "spicy"
|
||||
color = BLOOD_COLOR_LIZARD // rgb: 11, 7, 48
|
||||
pH = 6.85
|
||||
|
||||
/datum/reagent/blood/jellyblood
|
||||
data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_SLIME, "blood_type"="GEL","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
|
||||
name = "Slime Jelly Blood"
|
||||
@@ -150,29 +142,6 @@
|
||||
taste_mult = 1.3
|
||||
pH = 4
|
||||
|
||||
/datum/reagent/blood/xenomorph
|
||||
data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_XENO, "blood_type"="X*","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
|
||||
name = "Xenomorph Blood"
|
||||
taste_description = "acidic heresy"
|
||||
color = BLOOD_COLOR_XENO // greenish yellow ooze
|
||||
shot_glass_icon_state = "shotglassgreen"
|
||||
pH = 2.5
|
||||
|
||||
/datum/reagent/blood/oil
|
||||
data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_OIL, "blood_type"="HF","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
|
||||
name = "Hydraulic Blood"
|
||||
taste_description = "burnt oil"
|
||||
color = BLOOD_COLOR_OIL // dark, y'know, expected batman colors.
|
||||
pH = 9.75
|
||||
|
||||
/datum/reagent/blood/insect
|
||||
data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_BUG, "blood_type"="BUG","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
|
||||
name = "Insectoid Blood"
|
||||
taste_description = "waxy"
|
||||
color = BLOOD_COLOR_BUG // Bug colored, I guess.
|
||||
pH = 7.25
|
||||
|
||||
|
||||
/datum/reagent/blood/jellyblood/on_mob_life(mob/living/carbon/M)
|
||||
if(prob(10))
|
||||
if(M.dna?.species?.exotic_bloodtype != "GEL")
|
||||
@@ -2139,3 +2108,10 @@
|
||||
to_chat(M, "<span class='userlove'>You feel like playing with your [G.name]!</span>")
|
||||
|
||||
..()
|
||||
|
||||
/datum/reagent/preservahyde
|
||||
name = "Preservahyde"
|
||||
description = "A powerful preservation agent, utilizing the preservative effects of formaldehyde with significantly less of the histamine."
|
||||
reagent_state = LIQUID
|
||||
color = "#f7685e"
|
||||
metabolization_rate = REAGENTS_METABOLISM * 0.25
|
||||
|
||||
@@ -504,7 +504,7 @@
|
||||
toxpwr = 0
|
||||
|
||||
/datum/reagent/toxin/itching_powder/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
|
||||
if(method == TOUCH || method == VAPOR)
|
||||
if((method == TOUCH || method == VAPOR) && M.reagents)
|
||||
M.reagents.add_reagent(/datum/reagent/toxin/itching_powder, reac_volume)
|
||||
|
||||
/datum/reagent/toxin/itching_powder/on_mob_life(mob/living/carbon/M)
|
||||
|
||||
@@ -47,6 +47,12 @@
|
||||
results = list(/datum/reagent/consumable/sodiumchloride = 3)
|
||||
required_reagents = list(/datum/reagent/water = 1, /datum/reagent/sodium = 1, /datum/reagent/chlorine = 1)
|
||||
|
||||
/datum/chemical_reaction/preservahyde
|
||||
name = "Preservahyde"
|
||||
id = "preservahyde"
|
||||
results = list(/datum/reagent/preservahyde = 3)
|
||||
required_reagents = list(/datum/reagent/water = 1, /datum/reagent/toxin/formaldehyde = 1, /datum/reagent/bromine = 1)
|
||||
|
||||
/datum/chemical_reaction/plasmasolidification
|
||||
name = "Solid Plasma"
|
||||
id = "solidplasma"
|
||||
@@ -228,7 +234,6 @@
|
||||
var/level_max = 2
|
||||
|
||||
/datum/chemical_reaction/mix_virus/on_reaction(datum/reagents/holder, multiplier)
|
||||
|
||||
var/datum/reagent/blood/B = locate(/datum/reagent/blood) in holder.reagent_list
|
||||
if(B && B.data)
|
||||
var/datum/disease/advance/D = locate(/datum/disease/advance) in B.data["viruses"]
|
||||
@@ -236,94 +241,131 @@
|
||||
for(var/i in 1 to min(multiplier, 5))
|
||||
D.Evolve(level_min, level_max)
|
||||
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_2
|
||||
/datum/chemical_reaction/mix_virus/synth
|
||||
id = "mixvirus_synth"
|
||||
required_catalysts = list(/datum/reagent/blood/synthetics = 1)
|
||||
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_2
|
||||
name = "Mix Virus 2"
|
||||
id = "mixvirus2"
|
||||
required_reagents = list(/datum/reagent/toxin/mutagen = 1)
|
||||
level_min = 2
|
||||
level_max = 4
|
||||
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_3
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_2/synth
|
||||
id = "mixvirus2_synth"
|
||||
required_catalysts = list(/datum/reagent/blood/synthetics = 1)
|
||||
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_3
|
||||
name = "Mix Virus 3"
|
||||
id = "mixvirus3"
|
||||
required_reagents = list(/datum/reagent/toxin/plasma = 1)
|
||||
level_min = 4
|
||||
level_max = 6
|
||||
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_4
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_3/synth
|
||||
id = "mixvirus3_synth"
|
||||
required_catalysts = list(/datum/reagent/blood/synthetics = 1)
|
||||
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_4
|
||||
name = "Mix Virus 4"
|
||||
id = "mixvirus4"
|
||||
required_reagents = list(/datum/reagent/uranium = 1)
|
||||
level_min = 5
|
||||
level_max = 6
|
||||
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_5
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_4/synth
|
||||
id = "mixvirus4_synth"
|
||||
required_catalysts = list(/datum/reagent/blood/synthetics = 1)
|
||||
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_5
|
||||
name = "Mix Virus 5"
|
||||
id = "mixvirus5"
|
||||
required_reagents = list(/datum/reagent/toxin/mutagen/mutagenvirusfood = 1)
|
||||
level_min = 3
|
||||
level_max = 3
|
||||
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_6
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_5/synth
|
||||
id = "mixvirus5_synth"
|
||||
required_catalysts = list(/datum/reagent/blood/synthetics = 1)
|
||||
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_6
|
||||
name = "Mix Virus 6"
|
||||
id = "mixvirus6"
|
||||
required_reagents = list(/datum/reagent/toxin/mutagen/mutagenvirusfood/sugar = 1)
|
||||
level_min = 4
|
||||
level_max = 4
|
||||
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_7
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_6/synth
|
||||
id = "mixvirus6_synth"
|
||||
required_catalysts = list(/datum/reagent/blood/synthetics = 1)
|
||||
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_7
|
||||
name = "Mix Virus 7"
|
||||
id = "mixvirus7"
|
||||
required_reagents = list(/datum/reagent/toxin/plasma/plasmavirusfood/weak = 1)
|
||||
level_min = 5
|
||||
level_max = 5
|
||||
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_8
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_7/synth
|
||||
id = "mixvirus7_synth"
|
||||
required_catalysts = list(/datum/reagent/blood/synthetics = 1)
|
||||
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_8
|
||||
name = "Mix Virus 8"
|
||||
id = "mixvirus8"
|
||||
required_reagents = list(/datum/reagent/toxin/plasma/plasmavirusfood = 1)
|
||||
level_min = 6
|
||||
level_max = 6
|
||||
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_9
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_8/synth
|
||||
id = "mixvirus8_synth"
|
||||
required_catalysts = list(/datum/reagent/blood/synthetics = 1)
|
||||
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_9
|
||||
name = "Mix Virus 9"
|
||||
id = "mixvirus9"
|
||||
required_reagents = list(/datum/reagent/medicine/synaptizine/synaptizinevirusfood = 1)
|
||||
level_min = 1
|
||||
level_max = 1
|
||||
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_10
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_9/synth
|
||||
id = "mixvirus9_synth"
|
||||
required_catalysts = list(/datum/reagent/blood/synthetics = 1)
|
||||
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_10
|
||||
name = "Mix Virus 10"
|
||||
id = "mixvirus10"
|
||||
required_reagents = list(/datum/reagent/uranium/uraniumvirusfood = 1)
|
||||
level_min = 6
|
||||
level_max = 7
|
||||
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_11
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_10/synth
|
||||
id = "mixvirus10_synth"
|
||||
required_catalysts = list(/datum/reagent/blood/synthetics = 1)
|
||||
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_11
|
||||
name = "Mix Virus 11"
|
||||
id = "mixvirus11"
|
||||
required_reagents = list(/datum/reagent/uranium/uraniumvirusfood/unstable = 1)
|
||||
level_min = 7
|
||||
level_max = 7
|
||||
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_12
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_11/synth
|
||||
id = "mixvirus11_synth"
|
||||
required_catalysts = list(/datum/reagent/blood/synthetics = 1)
|
||||
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_12
|
||||
name = "Mix Virus 12"
|
||||
id = "mixvirus12"
|
||||
required_reagents = list(/datum/reagent/uranium/uraniumvirusfood/stable = 1)
|
||||
level_min = 8
|
||||
level_max = 8
|
||||
|
||||
/datum/chemical_reaction/mix_virus/mix_virus_12/synth
|
||||
id = "mixvirus12_synth"
|
||||
required_catalysts = list(/datum/reagent/blood/synthetics = 1)
|
||||
|
||||
/datum/chemical_reaction/mix_virus/rem_virus
|
||||
name = "Devolve Virus"
|
||||
id = "remvirus"
|
||||
@@ -338,6 +380,10 @@
|
||||
for(var/i in 1 to min(multiplier, 5))
|
||||
D.Devolve()
|
||||
|
||||
/datum/chemical_reaction/mix_virus/rem_virus/synth
|
||||
id = "remvirus_synth"
|
||||
required_catalysts = list(/datum/reagent/blood/synthetics = 1)
|
||||
|
||||
/datum/chemical_reaction/mix_virus/neuter_virus
|
||||
name = "Neuter Virus"
|
||||
id = "neutervirus"
|
||||
@@ -352,6 +398,10 @@
|
||||
for(var/i in 1 to min(multiplier, 5))
|
||||
D.Neuter()
|
||||
|
||||
/datum/chemical_reaction/mix_virus/neuter_virus/synth
|
||||
id = "neutervirus_synth"
|
||||
required_catalysts = list(/datum/reagent/blood/synthetics = 1)
|
||||
|
||||
////////////////////////////////// foam and foam precursor ///////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ GLOBAL_LIST_INIT(food_reagents, build_reagents_to_food()) //reagentid = related
|
||||
|
||||
/obj/item/paper/secretrecipe
|
||||
name = "old recipe"
|
||||
var/recipe_id = "secretsauce"
|
||||
var/recipe_id = /datum/reagent/consumable/secretsauce
|
||||
|
||||
/obj/item/paper/secretrecipe/examine(mob/user) //Extra secret
|
||||
if(isobserver(user))
|
||||
|
||||
@@ -431,4 +431,4 @@
|
||||
/obj/item/reagent_containers/glass/bottle/hexacamphor
|
||||
name = "Hexacamphor bottle"
|
||||
desc = "A bottle of strong anaphrodisiac. Reduces libido."
|
||||
list_reagents = list(/datum/reagent/drug/anaphrodisiacplus = 30)
|
||||
list_reagents = list(/datum/reagent/drug/anaphrodisiacplus = 30)
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
ignore_flags = 1 //so you can medipen through hardsuits
|
||||
reagent_flags = DRAWABLE
|
||||
flags_1 = null
|
||||
list_reagents = list(/datum/reagent/medicine/epinephrine = 10, /datum/reagent/toxin/formaldehyde = 3)
|
||||
list_reagents = list(/datum/reagent/medicine/epinephrine = 10, /datum/reagent/preservahyde = 3)
|
||||
|
||||
/obj/item/reagent_containers/hypospray/medipen/suicide_act(mob/living/carbon/user)
|
||||
user.visible_message("<span class='suicide'>[user] begins to choke on \the [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
SEND_SIGNAL(A, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_MEDIUM)
|
||||
return
|
||||
|
||||
/obj/item/reagent_containers/rag/pre_altattackby(mob/living/M, mob/living/user, params)
|
||||
/obj/item/reagent_containers/rag/alt_pre_attack(mob/living/M, mob/living/user, params)
|
||||
if(istype(M) && user.a_intent == INTENT_HELP)
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
if(M.on_fire)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
///////////////////////////////////
|
||||
|
||||
/datum/design/milk
|
||||
name = "10 Milk"
|
||||
name = "10u Milk"
|
||||
id = "milk"
|
||||
build_type = BIOGENERATOR
|
||||
materials = list(MAT_BIOMASS = 20)
|
||||
@@ -11,7 +11,7 @@
|
||||
category = list("initial","Food")
|
||||
|
||||
/datum/design/cream
|
||||
name = "10 Cream"
|
||||
name = "10u Cream"
|
||||
id = "cream"
|
||||
build_type = BIOGENERATOR
|
||||
materials = list(MAT_BIOMASS = 30)
|
||||
@@ -123,6 +123,22 @@
|
||||
build_path = /obj/item/reagent_containers/glass/bottle/killer/pestkiller
|
||||
category = list("initial","Botany Chemicals")
|
||||
|
||||
/datum/design/ammonia
|
||||
name = "10u Ammonia"
|
||||
id = "ammonia_biogen"
|
||||
build_type = BIOGENERATOR
|
||||
materials = list(MAT_BIOMASS = 25)
|
||||
make_reagents = list(/datum/reagent/ammonia = 10)
|
||||
category = list("initial","Botany Chemicals")
|
||||
|
||||
/datum/design/saltpetre
|
||||
name = "10u Saltpetre"
|
||||
id = "saltpetre_biogen"
|
||||
build_type = BIOGENERATOR
|
||||
materials = list(MAT_BIOMASS = 75)
|
||||
make_reagents = list(/datum/reagent/saltpetre = 10)
|
||||
category = list("initial","Botany Chemicals")
|
||||
|
||||
/datum/design/botany_bottle
|
||||
name = "Empty Bottle"
|
||||
id = "botany_bottle"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user