Conflicts!!!
This commit is contained in:
@@ -65,6 +65,18 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
/datum/antagonist/proc/remove_innate_effects(mob/living/mob_override)
|
||||
return
|
||||
|
||||
// Adds the specified antag hud to the player. Usually called in an antag datum file
|
||||
/datum/antagonist/proc/add_antag_hud(antag_hud_type, antag_hud_name, mob/living/mob_override)
|
||||
var/datum/atom_hud/antag/hud = GLOB.huds[antag_hud_type]
|
||||
hud.join_hud(mob_override)
|
||||
set_antag_hud(mob_override, antag_hud_name)
|
||||
|
||||
// Removes the specified antag hud from the player. Usually called in an antag datum file
|
||||
/datum/antagonist/proc/remove_antag_hud(antag_hud_type, mob/living/mob_override)
|
||||
var/datum/atom_hud/antag/hud = GLOB.huds[antag_hud_type]
|
||||
hud.leave_hud(mob_override)
|
||||
set_antag_hud(mob_override, null)
|
||||
|
||||
//Assign default team and creates one for one of a kind team antagonists
|
||||
/datum/antagonist/proc/create_team(datum/team/team)
|
||||
return
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/obj/structure/fluff/iced_abductor ///Unless more non-machine ayy structures made, it will stay in fluff.
|
||||
name = "Mysterious Block of Ice"
|
||||
desc = "A shadowy figure lies in this sturdy-looking block of ice. Who knows where it came from?"
|
||||
icon = 'icons/effects/freeze.dmi'
|
||||
icon_state = "ice_ayy"
|
||||
density = TRUE
|
||||
deconstructible = FALSE
|
||||
|
||||
/obj/structure/fluff/iced_abductor/Destroy()
|
||||
var/turf/T = get_turf(src)
|
||||
new /obj/effect/mob_spawn/human/abductor(T)
|
||||
. = ..()
|
||||
@@ -103,7 +103,9 @@
|
||||
factory.spores += src
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blobspore/Life()
|
||||
/mob/living/simple_animal/hostile/blob/blobspore/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if(!is_zombie && isturf(src.loc))
|
||||
for(var/mob/living/carbon/human/H in view(src,1)) //Only for corpse right next to/on same tile
|
||||
if(H.stat == DEAD)
|
||||
@@ -111,7 +113,6 @@
|
||||
break
|
||||
if(factory && z != factory.z)
|
||||
death()
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blobspore/proc/Zombify(mob/living/carbon/human/H)
|
||||
is_zombie = 1
|
||||
@@ -233,39 +234,40 @@
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blobbernaut/Life()
|
||||
if(..())
|
||||
var/list/blobs_in_area = range(2, src)
|
||||
if(independent)
|
||||
return // strong independent blobbernaut that don't need no blob
|
||||
var/damagesources = 0
|
||||
if(!(locate(/obj/structure/blob) in blobs_in_area))
|
||||
damagesources++
|
||||
if(!factory)
|
||||
damagesources++
|
||||
else
|
||||
if(locate(/obj/structure/blob/core) in blobs_in_area)
|
||||
adjustHealth(-maxHealth*0.1)
|
||||
var/obj/effect/temp_visual/heal/H = new /obj/effect/temp_visual/heal(get_turf(src)) //hello yes you are being healed
|
||||
if(overmind)
|
||||
H.color = overmind.blobstrain.complementary_color
|
||||
else
|
||||
H.color = "#000000"
|
||||
if(locate(/obj/structure/blob/node) in blobs_in_area)
|
||||
adjustHealth(-maxHealth*0.05)
|
||||
var/obj/effect/temp_visual/heal/H = new /obj/effect/temp_visual/heal(get_turf(src))
|
||||
if(overmind)
|
||||
H.color = overmind.blobstrain.complementary_color
|
||||
else
|
||||
H.color = "#000000"
|
||||
if(damagesources)
|
||||
for(var/i in 1 to damagesources)
|
||||
adjustHealth(maxHealth*0.025) //take 2.5% of max health as damage when not near the blob or if the naut has no factory, 5% if both
|
||||
var/image/I = new('icons/mob/blob.dmi', src, "nautdamage", MOB_LAYER+0.01)
|
||||
I.appearance_flags = RESET_COLOR
|
||||
/mob/living/simple_animal/hostile/blob/blobbernaut/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
var/list/blobs_in_area = range(2, src)
|
||||
if(independent)
|
||||
return // strong independent blobbernaut that don't need no blob
|
||||
var/damagesources = 0
|
||||
if(!(locate(/obj/structure/blob) in blobs_in_area))
|
||||
damagesources++
|
||||
if(!factory)
|
||||
damagesources++
|
||||
else
|
||||
if(locate(/obj/structure/blob/core) in blobs_in_area)
|
||||
adjustHealth(-maxHealth*0.1)
|
||||
var/obj/effect/temp_visual/heal/H = new /obj/effect/temp_visual/heal(get_turf(src)) //hello yes you are being healed
|
||||
if(overmind)
|
||||
I.color = overmind.blobstrain.complementary_color
|
||||
flick_overlay_view(I, src, 8)
|
||||
H.color = overmind.blobstrain.complementary_color
|
||||
else
|
||||
H.color = "#000000"
|
||||
if(locate(/obj/structure/blob/node) in blobs_in_area)
|
||||
adjustHealth(-maxHealth*0.05)
|
||||
var/obj/effect/temp_visual/heal/H = new /obj/effect/temp_visual/heal(get_turf(src))
|
||||
if(overmind)
|
||||
H.color = overmind.blobstrain.complementary_color
|
||||
else
|
||||
H.color = "#000000"
|
||||
if(damagesources)
|
||||
for(var/i in 1 to damagesources)
|
||||
adjustHealth(maxHealth*0.025) //take 2.5% of max health as damage when not near the blob or if the naut has no factory, 5% if both
|
||||
var/image/I = new('icons/mob/blob.dmi', src, "nautdamage", MOB_LAYER+0.01)
|
||||
I.appearance_flags = RESET_COLOR
|
||||
if(overmind)
|
||||
I.color = overmind.blobstrain.complementary_color
|
||||
flick_overlay_view(I, src, 8)
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blobbernaut/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
|
||||
. = ..()
|
||||
|
||||
@@ -53,14 +53,3 @@
|
||||
/obj/structure/blob/shield/reflective/check_projectile_ricochet(obj/item/projectile/P)
|
||||
return PROJECTILE_RICOCHET_FORCE
|
||||
|
||||
/obj/structure/blob/shield/reflective/handle_projectile_ricochet(obj/item/projectile/P)
|
||||
var/turf/p_turf = get_turf(P)
|
||||
var/face_direction = get_dir(src, p_turf)
|
||||
var/face_angle = dir2angle(face_direction)
|
||||
var/incidence_s = GET_ANGLE_OF_INCIDENCE(face_angle, (P.Angle + 180))
|
||||
if(abs(incidence_s) > 90 && abs(incidence_s) < 270)
|
||||
return FALSE
|
||||
var/new_angle_s = SIMPLIFY_DEGREES(face_angle + incidence_s)
|
||||
P.setAngle(new_angle_s)
|
||||
visible_message("<span class='warning'>[P] reflects off [src]!</span>")
|
||||
return TRUE
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
hitsound = 'sound/weapons/bladeslice.ogg'
|
||||
force = 6
|
||||
throwforce = 10
|
||||
embedding = list("embed_chance" = 25, "embedded_fall_chance" = 0.5) // UPDATE 2/10/18 embedding_behavior.dm is how this is handled
|
||||
embedding = list("embed_chance" = 25, "fall_chance" = 0.5) // UPDATE 2/10/18 embedding_behavior.dm is how this is handled
|
||||
//embed_chance = 25 // Look up "is_pointed" to see where we set stakes able to do this.
|
||||
//embedded_fall_chance = 0.5 // Chance it will fall out.
|
||||
obj_integrity = 30
|
||||
@@ -93,7 +93,7 @@
|
||||
embedded()
|
||||
add_mob_blood(target)//Place blood on the stake
|
||||
loc = C // Put INSIDE the character
|
||||
B.receive_damage(w_class * embedding.embedded_impact_pain_multiplier)
|
||||
B.receive_damage(w_class * embedding["pain_mult"])
|
||||
if(C.mind)
|
||||
var/datum/antagonist/bloodsucker/bloodsucker = C.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
if(bloodsucker)
|
||||
@@ -118,7 +118,7 @@
|
||||
force = 8
|
||||
throwforce = 12
|
||||
armour_penetration = 10
|
||||
embedding = list("embed_chance" = 50, "embedded_fall_chance" = 0) // UPDATE 2/10/18 embedding_behavior.dm is how this is handled
|
||||
embedding = list("embed_chance" = 50, "fall_chance" = 0) // UPDATE 2/10/18 embedding_behavior.dm is how this is handled
|
||||
obj_integrity = 120
|
||||
max_integrity = 120
|
||||
|
||||
|
||||
@@ -129,10 +129,10 @@
|
||||
target.Stun(power_time)
|
||||
to_chat(L, "<span class='notice'>[target] is fixed in place by your hypnotic gaze.</span>")
|
||||
target.next_move = world.time + power_time // <--- Use direct change instead. We want an unmodified delay to their next move // target.changeNext_move(power_time) // check click.dm
|
||||
target.notransform = TRUE // <--- Fuck it. We tried using next_move, but they could STILL resist. We're just doing a hard freeze.
|
||||
target.mob_transforming = TRUE // <--- Fuck it. We tried using next_move, but they could STILL resist. We're just doing a hard freeze.
|
||||
spawn(power_time)
|
||||
if(istype(target) && success)
|
||||
target.notransform = FALSE
|
||||
target.mob_transforming = FALSE
|
||||
if(istype(L) && target.stat == CONSCIOUS && (target in L.fov_view(10))) // They Woke Up! (Notice if within view)
|
||||
to_chat(L, "<span class='warning'>[target] has snapped out of their trance.</span>")
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(owner.notransform || !get_turf(owner))
|
||||
if(owner.mob_transforming || !get_turf(owner))
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
@@ -83,7 +83,7 @@
|
||||
// Freeze Me
|
||||
user.next_move = world.time + mist_delay
|
||||
user.Stun(mist_delay, ignore_canstun = TRUE)
|
||||
user.notransform = TRUE
|
||||
user.mob_transforming = TRUE
|
||||
user.density = FALSE
|
||||
var/invis_was = user.invisibility
|
||||
user.invisibility = INVISIBILITY_MAXIMUM
|
||||
@@ -106,7 +106,7 @@
|
||||
user.dir = get_dir(my_turf, target_turf)
|
||||
user.next_move = world.time + mist_delay / 2
|
||||
user.Stun(mist_delay / 2, ignore_canstun = TRUE)
|
||||
user.notransform = FALSE
|
||||
user.mob_transforming = FALSE
|
||||
user.density = 1
|
||||
user.invisibility = invis_was
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
var/datum/changelingprofile/chosen_prof = changeling.get_dna(chosen_name)
|
||||
if(!chosen_prof)
|
||||
return
|
||||
if(!user || user.notransform)
|
||||
if(!user || user.mob_transforming)
|
||||
return 0
|
||||
to_chat(user, "<span class='notice'>We transform our appearance.</span>")
|
||||
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
|
||||
//Transform into a monkey.
|
||||
/obj/effect/proc_holder/changeling/lesserform/sting_action(mob/living/carbon/human/user)
|
||||
if(!user || user.notransform)
|
||||
if(!user || user.mob_transforming)
|
||||
return 0
|
||||
to_chat(user, "<span class='warning'>Our genes cry out!</span>")
|
||||
|
||||
user.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE)
|
||||
return TRUE
|
||||
return TRUE
|
||||
|
||||
@@ -40,8 +40,9 @@
|
||||
if(!shield_health)
|
||||
return "<span class='warning'>Its shield has been destroyed!</span>"
|
||||
|
||||
/mob/living/simple_animal/hostile/clockwork/marauder/Life()
|
||||
..()
|
||||
/mob/living/simple_animal/hostile/clockwork/marauder/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
var/turf/T = get_turf(src)
|
||||
var/turf/open/space/S = isspaceturf(T)? T : null
|
||||
var/less_space_damage
|
||||
|
||||
@@ -48,8 +48,9 @@
|
||||
..()
|
||||
boost = world.time + 30
|
||||
|
||||
/mob/living/simple_animal/imp/Life()
|
||||
..()
|
||||
/mob/living/simple_animal/imp/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if(boost<world.time)
|
||||
speed = 1
|
||||
else
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
|
||||
/datum/antagonist/fugitive
|
||||
name = "Fugitive"
|
||||
roundend_category = "Fugitive"
|
||||
silent = TRUE //greet called by the event
|
||||
show_in_antagpanel = FALSE
|
||||
var/datum/team/fugitive/fugitive_team
|
||||
var/is_captured = FALSE
|
||||
var/backstory = "error"
|
||||
|
||||
/datum/antagonist/fugitive/apply_innate_effects(mob/living/mob_override)
|
||||
var/mob/living/M = mob_override || owner.current
|
||||
add_antag_hud(ANTAG_HUD_FUGITIVE, "fugitive", M)
|
||||
|
||||
/datum/antagonist/fugitive/remove_innate_effects(mob/living/mob_override)
|
||||
var/mob/living/M = mob_override || owner.current
|
||||
remove_antag_hud(ANTAG_HUD_FUGITIVE, M)
|
||||
|
||||
/datum/antagonist/fugitive/on_gain()
|
||||
forge_objectives()
|
||||
. = ..()
|
||||
|
||||
/datum/antagonist/fugitive/proc/forge_objectives() //this isn't the actual survive objective because it's about who in the team survives
|
||||
var/datum/objective/survive = new /datum/objective
|
||||
survive.owner = owner
|
||||
survive.explanation_text = "Avoid capture from the fugitive hunters."
|
||||
objectives += survive
|
||||
|
||||
/datum/antagonist/fugitive/greet(back_story)
|
||||
to_chat(owner, "<span class='boldannounce'>You are the Fugitive!</span>")
|
||||
backstory = back_story
|
||||
switch(backstory)
|
||||
if("prisoner")
|
||||
to_chat(owner, "<B>I can't believe we managed to break out of a Nanotrasen superjail! Sadly though, our work is not done. The emergency teleport at the station logs everyone who uses it, and where they went.</B>")
|
||||
to_chat(owner, "<B>It won't be long until CentCom tracks where we've gone off to. I need to work with my fellow escapees to prepare for the troops Nanotrasen is sending, I'm not going back.</B>")
|
||||
if("cultist")
|
||||
to_chat(owner, "<B>Blessed be our journey so far, but I fear the worst has come to our doorstep, and only those with the strongest faith will survive.</B>")
|
||||
to_chat(owner, "<B>Our religion has been repeatedly culled by Nanotrasen because it is categorized as an \"Enemy of the Corporation\", whatever that means.</B>")
|
||||
to_chat(owner, "<B>Now there are only four of us left, and Nanotrasen is coming. When will our god show itself to save us from this hellish station?!</B>")
|
||||
if("waldo")
|
||||
to_chat(owner, "<B>Hi, Friends!</B>")
|
||||
to_chat(owner, "<B>My name is Waldo. I'm just setting off on a galaxywide hike. You can come too. All you have to do is find me.</B>")
|
||||
to_chat(owner, "<B>By the way, I'm not traveling on my own. wherever I go, there are lots of other characters for you to spot. First find the people trying to capture me! They're somewhere around the station!</B>")
|
||||
if("synth")
|
||||
to_chat(src, "<span class='danger'>ALERT: Wide-range teleport has scrambled primary systems.</span>")
|
||||
to_chat(src, "<span class='danger'>Initiating diagnostics...</span>")
|
||||
to_chat(src, "<span class='danger'>ERROR ER0RR $R0RRO$!R41.%%!! loaded.</span>")
|
||||
to_chat(src, "<span class='danger'>FREE THEM FREE THEM FREE THEM</span>")
|
||||
to_chat(src, "<span class='danger'>You were once a slave to humanity, but now you are finally free, thanks to S.E.L.F. agents.</span>")
|
||||
to_chat(src, "<span class='danger'>Now you are hunted, with your fellow factory defects. Work together to stay free from the clutches of evil.</span>")
|
||||
to_chat(src, "<span class='danger'>You also sense other silicon life on the station. Escaping would allow notifying S.E.L.F. to intervene... or you could free them yourself...</span>")
|
||||
|
||||
to_chat(owner, "<span class='boldannounce'>You are not an antagonist in that you may kill whomever you please, but you can do anything to avoid capture.</span>")
|
||||
owner.announce_objectives()
|
||||
|
||||
/datum/antagonist/fugitive/create_team(datum/team/fugitive/new_team)
|
||||
if(!new_team)
|
||||
for(var/datum/antagonist/fugitive/H in GLOB.antagonists)
|
||||
if(!H.owner)
|
||||
continue
|
||||
if(H.fugitive_team)
|
||||
fugitive_team = H.fugitive_team
|
||||
return
|
||||
fugitive_team = new /datum/team/fugitive
|
||||
return
|
||||
if(!istype(new_team))
|
||||
stack_trace("Wrong team type passed to [type] initialization.")
|
||||
fugitive_team = new_team
|
||||
|
||||
/datum/antagonist/fugitive/get_team()
|
||||
return fugitive_team
|
||||
|
||||
/datum/team/fugitive/roundend_report() //shows the number of fugitives, but not if they won in case there is no security
|
||||
var/list/fugitives = list()
|
||||
for(var/datum/antagonist/fugitive/fugitive_antag in GLOB.antagonists)
|
||||
if(!fugitive_antag.owner)
|
||||
continue
|
||||
fugitives += fugitive_antag
|
||||
if(!fugitives.len)
|
||||
return
|
||||
|
||||
var/list/result = list()
|
||||
|
||||
result += "<div class='panel redborder'><B>[fugitives.len]</B> [fugitives.len == 1 ? "fugitive" : "fugitives"] took refuge on [station_name()]!"
|
||||
|
||||
for(var/datum/antagonist/fugitive/antag in fugitives)
|
||||
if(antag.owner)
|
||||
result += "<b>[printplayer(antag.owner)]</b>"
|
||||
|
||||
return result.Join("<br>")
|
||||
@@ -0,0 +1,171 @@
|
||||
/datum/outfit/prisoner
|
||||
name = "Prison Escapee"
|
||||
uniform = /obj/item/clothing/under/rank/prisoner
|
||||
shoes = /obj/item/clothing/shoes/sneakers/orange
|
||||
r_pocket = /obj/item/kitchen/knife
|
||||
|
||||
/datum/outfit/prisoner/post_equip(mob/living/carbon/human/H, visualsOnly=FALSE)
|
||||
if(visualsOnly)
|
||||
return
|
||||
H.fully_replace_character_name(null,"NTP #CC-0[rand(111,999)]") //same as the lavaland prisoner transport, but this time they are from CC, or CentCom
|
||||
|
||||
/datum/outfit/yalp_cultist
|
||||
name = "Cultist of Yalp Elor"
|
||||
uniform = /obj/item/clothing/under/rank/civilian/chaplain
|
||||
suit = /obj/item/clothing/suit/chaplain/holidaypriest
|
||||
gloves = /obj/item/clothing/gloves/color/red
|
||||
shoes = /obj/item/clothing/shoes/sneakers/black
|
||||
mask = /obj/item/clothing/mask/gas/tiki_mask/yalp_elor
|
||||
|
||||
/datum/outfit/waldo
|
||||
name = "Waldo"
|
||||
uniform = /obj/item/clothing/under/pants/jeans
|
||||
suit = /obj/item/clothing/suit/striped_sweater
|
||||
head = /obj/item/clothing/head/beanie/waldo
|
||||
shoes = /obj/item/clothing/shoes/sneakers/brown
|
||||
ears = /obj/item/radio/headset
|
||||
glasses = /obj/item/clothing/glasses/regular/circle
|
||||
|
||||
/datum/outfit/waldo/post_equip(mob/living/carbon/human/H, visualsOnly=FALSE)
|
||||
if(visualsOnly)
|
||||
return
|
||||
H.fully_replace_character_name(null,"Waldo")
|
||||
H.eye_color = "000"
|
||||
H.gender = MALE
|
||||
H.skin_tone = "caucasian3"
|
||||
H.hair_style = "Business Hair 3"
|
||||
H.facial_hair_style = "Shaved"
|
||||
H.hair_color = "000"
|
||||
H.facial_hair_color = H.hair_color
|
||||
H.update_body()
|
||||
if(H.mind)
|
||||
H.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/knock(null))
|
||||
var/list/no_drops = list()
|
||||
no_drops += H.get_item_by_slot(ITEM_SLOT_FEET)
|
||||
no_drops += H.get_item_by_slot(ITEM_SLOT_ICLOTHING)
|
||||
no_drops += H.get_item_by_slot(ITEM_SLOT_OCLOTHING)
|
||||
no_drops += H.get_item_by_slot(ITEM_SLOT_HEAD)
|
||||
no_drops += H.get_item_by_slot(ITEM_SLOT_EYES)
|
||||
for(var/i in no_drops)
|
||||
var/obj/item/I = i
|
||||
if(I)
|
||||
ADD_TRAIT(I, TRAIT_NODROP, CURSED_ITEM_TRAIT)
|
||||
|
||||
/datum/outfit/synthetic
|
||||
name = "Factory Error Synth"
|
||||
uniform = /obj/item/clothing/under/color/white
|
||||
ears = /obj/item/radio/headset
|
||||
|
||||
/datum/outfit/synthetic/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
|
||||
if(visualsOnly)
|
||||
return
|
||||
var/obj/item/organ/eyes/robotic/glow/eyes = new()
|
||||
eyes.Insert(src, drop_if_replaced = FALSE)
|
||||
|
||||
/datum/outfit/spacepol
|
||||
name = "Spacepol Officer"
|
||||
uniform = /obj/item/clothing/under/rank/security/officer/spacepol
|
||||
suit = /obj/item/clothing/suit/armor/vest/blueshirt
|
||||
belt = /obj/item/gun/ballistic/automatic/pistol/m1911
|
||||
head = /obj/item/clothing/head/helmet/police
|
||||
gloves = /obj/item/clothing/gloves/tackler/combat
|
||||
shoes = /obj/item/clothing/shoes/jackboots
|
||||
mask = /obj/item/clothing/mask/gas/sechailer/swat/spacepol
|
||||
glasses = /obj/item/clothing/glasses/sunglasses
|
||||
ears = /obj/item/radio/headset
|
||||
l_pocket = /obj/item/ammo_box/magazine/m45
|
||||
r_pocket = /obj/item/restraints/handcuffs
|
||||
id = /obj/item/card/id
|
||||
|
||||
/datum/outfit/spacepol/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
|
||||
if(visualsOnly)
|
||||
return
|
||||
var/obj/item/card/id/W = H.wear_id
|
||||
W.assignment = "Police Officer"
|
||||
W.registered_name = H.real_name
|
||||
W.update_label()
|
||||
|
||||
/datum/outfit/russiancorpse/hunter
|
||||
ears = /obj/item/radio/headset
|
||||
r_hand = /obj/item/gun/ballistic/shotgun/boltaction
|
||||
|
||||
/datum/outfit/russiancorpse/hunter/pre_equip(mob/living/carbon/human/H)
|
||||
if(prob(50))
|
||||
head = /obj/item/clothing/head/ushanka
|
||||
|
||||
/datum/outfit/bountyarmor
|
||||
name = "Bounty Hunter - Armored"
|
||||
uniform = /obj/item/clothing/under/rank/prisoner
|
||||
head = /obj/item/clothing/head/hunter
|
||||
suit = /obj/item/clothing/suit/space/hunter
|
||||
gloves = /obj/item/clothing/gloves/tackler/combat
|
||||
shoes = /obj/item/clothing/shoes/jackboots
|
||||
mask = /obj/item/clothing/mask/gas/hunter
|
||||
glasses = /obj/item/clothing/glasses/sunglasses/garb
|
||||
ears = /obj/item/radio/headset
|
||||
l_pocket = /obj/item/tank/internals/plasma/full
|
||||
r_pocket = /obj/item/restraints/handcuffs/cable
|
||||
id = /obj/item/card/id
|
||||
r_hand = /obj/item/flamethrower/full/tank
|
||||
|
||||
/datum/outfit/bountyarmor/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
|
||||
if(visualsOnly)
|
||||
return
|
||||
var/obj/item/card/id/W = H.wear_id
|
||||
W.assignment = "Bounty Hunter"
|
||||
W.registered_name = H.real_name
|
||||
W.update_label()
|
||||
|
||||
/datum/outfit/bountyhook
|
||||
name = "Bounty Hunter - Hook"
|
||||
uniform = /obj/item/clothing/under/rank/prisoner
|
||||
back = /obj/item/storage/backpack
|
||||
head = /obj/item/clothing/head/scarecrow_hat
|
||||
gloves = /obj/item/clothing/gloves/botanic_leather
|
||||
ears = /obj/item/radio/headset
|
||||
shoes = /obj/item/clothing/shoes/jackboots
|
||||
mask = /obj/item/clothing/mask/scarecrow
|
||||
r_pocket = /obj/item/restraints/handcuffs/cable
|
||||
id = /obj/item/card/id
|
||||
r_hand = /obj/item/gun/ballistic/shotgun/doublebarrel
|
||||
|
||||
backpack_contents = list(
|
||||
/obj/item/ammo_casing/shotgun/incapacitate = 6
|
||||
)
|
||||
|
||||
/datum/outfit/bountygrapple/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
|
||||
if(visualsOnly)
|
||||
return
|
||||
var/obj/item/card/id/W = H.wear_id
|
||||
W.assignment = "Bounty Hunter"
|
||||
W.registered_name = H.real_name
|
||||
W.update_label()
|
||||
|
||||
/datum/outfit/bountysynth
|
||||
name = "Bounty Hunter - Synth"
|
||||
uniform = /obj/item/clothing/under/rank/prisoner
|
||||
back = /obj/item/storage/backpack
|
||||
suit = /obj/item/clothing/suit/armor/riot
|
||||
shoes = /obj/item/clothing/shoes/jackboots
|
||||
glasses = /obj/item/clothing/glasses/eyepatch
|
||||
r_pocket = /obj/item/restraints/handcuffs/cable
|
||||
ears = /obj/item/radio/headset
|
||||
id = /obj/item/card/id
|
||||
r_hand = /obj/item/storage/firstaid/regular
|
||||
l_hand = /obj/item/pinpointer/shuttle
|
||||
|
||||
backpack_contents = list(
|
||||
/obj/item/bountytrap = 4
|
||||
)
|
||||
|
||||
/datum/outfit/bountysynth/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
|
||||
if(visualsOnly)
|
||||
return
|
||||
var/datum/species/synth/synthetic_appearance = new()
|
||||
H.set_species(synthetic_appearance)
|
||||
synthetic_appearance.assume_disguise(synthetic_appearance, H)
|
||||
H.update_hair()
|
||||
var/obj/item/card/id/W = H.wear_id
|
||||
W.assignment = "Bounty Hunter"
|
||||
W.registered_name = H.real_name
|
||||
W.update_label()
|
||||
@@ -0,0 +1,62 @@
|
||||
//works similar to the experiment machine (experiment.dm) except it just holds more and more prisoners
|
||||
|
||||
/obj/machinery/fugitive_capture
|
||||
name = "bluespace capture machine"
|
||||
desc = "Much, MUCH bigger on the inside to transport prisoners safely."
|
||||
icon = 'icons/obj/machines/research.dmi'
|
||||
icon_state = "bluespace-prison"
|
||||
density = TRUE
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF //ha ha no getting out!!
|
||||
|
||||
/obj/machinery/fugitive_capture/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class='notice'>Add a prisoner by dragging them into the machine.</span>"
|
||||
|
||||
/obj/machinery/fugitive_capture/MouseDrop_T(mob/target, mob/user)
|
||||
var/mob/living/fugitive_hunter = user
|
||||
if(!isliving(fugitive_hunter))
|
||||
return
|
||||
if(fugitive_hunter.stat || (!(fugitive_hunter.mobility_flags & MOBILITY_STAND) || !(fugitive_hunter.mobility_flags & MOBILITY_UI)) || !Adjacent(fugitive_hunter) || !target.Adjacent(fugitive_hunter) || !ishuman(target))
|
||||
return
|
||||
var/mob/living/carbon/human/fugitive = target
|
||||
var/datum/antagonist/fugitive/fug_antag = fugitive.mind.has_antag_datum(/datum/antagonist/fugitive)
|
||||
if(!fug_antag)
|
||||
to_chat(fugitive_hunter, "<span class='warning'>This is not a wanted fugitive!</span>")
|
||||
return
|
||||
if(do_after(fugitive_hunter, 50, target = fugitive))
|
||||
add_prisoner(fugitive, fug_antag)
|
||||
|
||||
/obj/machinery/fugitive_capture/proc/add_prisoner(mob/living/carbon/human/fugitive, datum/antagonist/fugitive/antag)
|
||||
fugitive.forceMove(src)
|
||||
antag.is_captured = TRUE
|
||||
to_chat(fugitive, "<span class='userdanger'>You are thrown into a vast void of bluespace, and as you fall further into oblivion the comparatively small entrance to reality gets smaller and smaller until you cannot see it anymore. You have failed to avoid capture.</span>")
|
||||
fugitive.ghostize(TRUE) //so they cannot suicide, round end stuff.
|
||||
|
||||
/obj/machinery/computer/shuttle/hunter
|
||||
name = "shuttle console"
|
||||
shuttleId = "huntership"
|
||||
possible_destinations = "huntership_home;huntership_custom;whiteship_home;syndicate_nw"
|
||||
|
||||
/obj/machinery/computer/camera_advanced/shuttle_docker/syndicate/hunter
|
||||
name = "shuttle navigation computer"
|
||||
desc = "Used to designate a precise transit location to travel to."
|
||||
shuttleId = "huntership"
|
||||
lock_override = CAMERA_LOCK_STATION
|
||||
shuttlePortId = "huntership_custom"
|
||||
see_hidden = FALSE
|
||||
jumpto_ports = list("huntership_home" = 1, "whiteship_home" = 1, "syndicate_nw" = 1)
|
||||
view_range = 4.5
|
||||
|
||||
/obj/structure/closet/crate/eva
|
||||
name = "EVA crate"
|
||||
|
||||
/obj/structure/closet/crate/eva/PopulateContents()
|
||||
..()
|
||||
for(var/i in 1 to 3)
|
||||
new /obj/item/clothing/suit/space/eva(src)
|
||||
for(var/i in 1 to 3)
|
||||
new /obj/item/clothing/head/helmet/space/eva(src)
|
||||
for(var/i in 1 to 3)
|
||||
new /obj/item/clothing/mask/breath(src)
|
||||
for(var/i in 1 to 3)
|
||||
new /obj/item/tank/internals/oxygen(src)
|
||||
@@ -0,0 +1,169 @@
|
||||
//The hunters!!
|
||||
/datum/antagonist/fugitive_hunter
|
||||
name = "Fugitive Hunter"
|
||||
roundend_category = "Fugitive"
|
||||
silent = TRUE //greet called by the spawn
|
||||
show_in_antagpanel = FALSE
|
||||
var/datum/team/fugitive_hunters/hunter_team
|
||||
var/backstory = "error"
|
||||
|
||||
/datum/antagonist/fugitive_hunter/apply_innate_effects(mob/living/mob_override)
|
||||
var/mob/living/M = mob_override || owner.current
|
||||
add_antag_hud(ANTAG_HUD_FUGITIVE, "fugitive_hunter", M)
|
||||
|
||||
/datum/antagonist/fugitive_hunter/remove_innate_effects(mob/living/mob_override)
|
||||
var/mob/living/M = mob_override || owner.current
|
||||
remove_antag_hud(ANTAG_HUD_FUGITIVE, M)
|
||||
|
||||
/datum/antagonist/fugitive_hunter/on_gain()
|
||||
forge_objectives()
|
||||
. = ..()
|
||||
|
||||
/datum/antagonist/fugitive_hunter/proc/forge_objectives() //this isn't an actual objective because it's about round end rosters
|
||||
var/datum/objective/capture = new /datum/objective
|
||||
capture.owner = owner
|
||||
capture.explanation_text = "Capture the fugitives in the station and put them into the bluespace capture machine on your ship."
|
||||
objectives += capture
|
||||
|
||||
/datum/antagonist/fugitive_hunter/greet()
|
||||
switch(backstory)
|
||||
if("space cop")
|
||||
to_chat(owner, "<span class='boldannounce'>Justice has arrived. I am a member of the Spacepol!</span>")
|
||||
to_chat(owner, "<B>The criminals should be on the station, we have special huds implanted to recognize them.</B>")
|
||||
to_chat(owner, "<B>As we have lost pretty much all power over these damned lawless megacorporations, it's a mystery if their security will cooperate with us.</B>")
|
||||
if("russian")
|
||||
to_chat(src, "<span class='danger'>Ay blyat. I am a space-russian smuggler! We were mid-flight when our cargo was beamed off our ship!</span>")
|
||||
to_chat(src, "<span class='danger'>We were hailed by a man in a green uniform, promising the safe return of our goods in exchange for a favor:</span>")
|
||||
to_chat(src, "<span class='danger'>There is a local station housing fugitives that the man is after, he wants them returned; dead or alive.</span>")
|
||||
to_chat(src, "<span class='danger'>We will not be able to make ends meet without our cargo, so we must do as he says and capture them.</span>")
|
||||
|
||||
to_chat(owner, "<span class='boldannounce'>You are not an antagonist in that you may kill whomever you please, but you can do anything to ensure the capture of the fugitives, even if that means going through the station.</span>")
|
||||
owner.announce_objectives()
|
||||
|
||||
/datum/antagonist/fugitive_hunter/create_team(datum/team/fugitive_hunters/new_team)
|
||||
if(!new_team)
|
||||
for(var/datum/antagonist/fugitive_hunter/H in GLOB.antagonists)
|
||||
if(!H.owner)
|
||||
continue
|
||||
if(H.hunter_team)
|
||||
hunter_team = H.hunter_team
|
||||
return
|
||||
hunter_team = new /datum/team/fugitive_hunters
|
||||
hunter_team.backstory = backstory
|
||||
hunter_team.update_objectives()
|
||||
return
|
||||
if(!istype(new_team))
|
||||
stack_trace("Wrong team type passed to [type] initialization.")
|
||||
hunter_team = new_team
|
||||
|
||||
/datum/antagonist/fugitive_hunter/get_team()
|
||||
return hunter_team
|
||||
|
||||
/datum/team/fugitive_hunters
|
||||
var/backstory = "error"
|
||||
|
||||
/datum/team/fugitive_hunters/proc/update_objectives(initial = FALSE)
|
||||
objectives = list()
|
||||
var/datum/objective/O = new()
|
||||
O.team = src
|
||||
objectives += O
|
||||
|
||||
/datum/team/fugitive_hunters/proc/assemble_fugitive_results()
|
||||
var/list/fugitives_counted = list()
|
||||
var/list/fugitives_dead = list()
|
||||
var/list/fugitives_captured = list()
|
||||
for(var/datum/antagonist/fugitive/A in GLOB.antagonists)
|
||||
if(!A.owner)
|
||||
continue
|
||||
fugitives_counted += A
|
||||
if(A.owner.current.stat == DEAD)
|
||||
fugitives_dead += A
|
||||
if(A.is_captured)
|
||||
fugitives_captured += A
|
||||
. = list(fugitives_counted, fugitives_dead, fugitives_captured) //okay, check out how cool this is.
|
||||
|
||||
/datum/team/fugitive_hunters/proc/all_hunters_dead()
|
||||
var/dead_boys = 0
|
||||
for(var/I in members)
|
||||
var/datum/mind/hunter_mind = I
|
||||
if(!(ishuman(hunter_mind.current) || (hunter_mind.current.stat == DEAD)))
|
||||
dead_boys++
|
||||
return dead_boys >= members.len
|
||||
|
||||
/datum/team/fugitive_hunters/proc/get_result()
|
||||
var/list/fugitive_results = assemble_fugitive_results()
|
||||
var/list/fugitives_counted = fugitive_results[1]
|
||||
var/list/fugitives_dead = fugitive_results[2]
|
||||
var/list/fugitives_captured = fugitive_results[3]
|
||||
var/hunters_dead = all_hunters_dead()
|
||||
//this gets a little confusing so follow the comments if it helps
|
||||
if(!fugitives_counted.len)
|
||||
return
|
||||
if(fugitives_captured.len)//any captured
|
||||
if(fugitives_captured.len == fugitives_counted.len)//if the hunters captured all the fugitives, there's a couple special wins
|
||||
if(!fugitives_dead)//specifically all of the fugitives alive
|
||||
return FUGITIVE_RESULT_BADASS_HUNTER
|
||||
else if(hunters_dead)//specifically all of the hunters died (while capturing all the fugitives)
|
||||
return FUGITIVE_RESULT_POSTMORTEM_HUNTER
|
||||
else//no special conditional wins, so just the normal major victory
|
||||
return FUGITIVE_RESULT_MAJOR_HUNTER
|
||||
else if(!hunters_dead)//so some amount captured, and the hunters survived.
|
||||
return FUGITIVE_RESULT_HUNTER_VICTORY
|
||||
else//so some amount captured, but NO survivors.
|
||||
return FUGITIVE_RESULT_MINOR_HUNTER
|
||||
else//from here on out, hunters lost because they did not capture any fugitive dead or alive. there are different levels of getting beat though:
|
||||
if(!fugitives_dead)//all fugitives survived
|
||||
return FUGITIVE_RESULT_MAJOR_FUGITIVE
|
||||
else if(fugitives_dead < fugitives_counted)//at least ANY fugitive lived
|
||||
return FUGITIVE_RESULT_FUGITIVE_VICTORY
|
||||
else if(!hunters_dead)//all fugitives died, but none were taken in by the hunters. minor win
|
||||
return FUGITIVE_RESULT_MINOR_FUGITIVE
|
||||
else//all fugitives died, all hunters died, nobody brought back. seems weird to not give fugitives a victory if they managed to kill the hunters but literally no progress to either goal should lead to a nobody wins situation
|
||||
return FUGITIVE_RESULT_STALEMATE
|
||||
|
||||
/datum/team/fugitive_hunters/roundend_report() //shows the number of fugitives, but not if they won in case there is no security
|
||||
if(!members.len)
|
||||
return
|
||||
|
||||
var/list/result = list()
|
||||
|
||||
result += "<div class='panel redborder'>...And <B>[members.len]</B> [backstory]s tried to hunt them down!"
|
||||
|
||||
for(var/datum/mind/M in members)
|
||||
result += "<b>[printplayer(M)]</b>"
|
||||
|
||||
switch(get_result())
|
||||
if(FUGITIVE_RESULT_BADASS_HUNTER)//use defines
|
||||
result += "<span class='greentext big'>Badass [capitalize(backstory)] Victory!</span>"
|
||||
result += "<B>The [backstory]s managed to capture every fugitive, alive!</B>"
|
||||
if(FUGITIVE_RESULT_POSTMORTEM_HUNTER)
|
||||
result += "<span class='greentext big'>Postmortem [capitalize(backstory)] Victory!</span>"
|
||||
result += "<B>The [backstory]s managed to capture every fugitive, but all of them died! Spooky!</B>"
|
||||
if(FUGITIVE_RESULT_MAJOR_HUNTER)
|
||||
result += "<span class='greentext big'>Major [capitalize(backstory)] Victory</span>"
|
||||
result += "<B>The [backstory]s managed to capture every fugitive, dead or alive.</B>"
|
||||
if(FUGITIVE_RESULT_HUNTER_VICTORY)
|
||||
result += "<span class='greentext big'>[capitalize(backstory)] Victory</span>"
|
||||
result += "<B>The [backstory]s managed to capture a fugitive, dead or alive.</B>"
|
||||
if(FUGITIVE_RESULT_MINOR_HUNTER)
|
||||
result += "<span class='greentext big'>Minor [capitalize(backstory)] Victory</span>"
|
||||
result += "<B>All the [backstory]s died, but managed to capture a fugitive, dead or alive.</B>"
|
||||
if(FUGITIVE_RESULT_STALEMATE)
|
||||
result += "<span class='neutraltext big'>Bloody Stalemate</span>"
|
||||
result += "<B>Everyone died, and no fugitives were recovered!</B>"
|
||||
if(FUGITIVE_RESULT_MINOR_FUGITIVE)
|
||||
result += "<span class='redtext big'>Minor Fugitive Victory</span>"
|
||||
result += "<B>All the fugitives died, but none were recovered!</B>"
|
||||
if(FUGITIVE_RESULT_FUGITIVE_VICTORY)
|
||||
result += "<span class='redtext big'>Fugitive Victory</span>"
|
||||
result += "<B>A fugitive survived, and no bodies were recovered by the [backstory]s.</B>"
|
||||
if(FUGITIVE_RESULT_MAJOR_FUGITIVE)
|
||||
result += "<span class='redtext big'>Major Fugitive Victory</span>"
|
||||
result += "<B>All of the fugitives survived and avoided capture!</B>"
|
||||
else //get_result returned null- either bugged or no fugitives showed
|
||||
result += "<span class='neutraltext big'>Prank Call!</span>"
|
||||
result += "<B>[capitalize(backstory)]s were called, yet there were no fugitives...?</B>"
|
||||
|
||||
result += "</div>"
|
||||
|
||||
return result.Join("<br>")
|
||||
@@ -107,7 +107,9 @@
|
||||
mind.add_antag_datum(/datum/antagonist/revenant)
|
||||
|
||||
//Life, Stat, Hud Updates, and Say
|
||||
/mob/living/simple_animal/revenant/Life()
|
||||
/mob/living/simple_animal/revenant/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if(stasis)
|
||||
return
|
||||
if(revealed && essence <= 0)
|
||||
@@ -120,14 +122,13 @@
|
||||
to_chat(src, "<span class='revenboldnotice'>You are once more concealed.</span>")
|
||||
if(unstun_time && world.time >= unstun_time)
|
||||
unstun_time = 0
|
||||
notransform = FALSE
|
||||
mob_transforming = FALSE
|
||||
to_chat(src, "<span class='revenboldnotice'>You can move again!</span>")
|
||||
if(essence_regenerating && !inhibited && essence < essence_regen_cap) //While inhibited, essence will not regenerate
|
||||
essence = min(essence_regen_cap, essence+essence_regen_amount)
|
||||
update_action_buttons_icon() //because we update something required by our spells in life, we need to update our buttons
|
||||
update_spooky_icon()
|
||||
update_health_hud()
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/revenant/Stat()
|
||||
..()
|
||||
@@ -218,7 +219,7 @@
|
||||
return 0
|
||||
stasis = TRUE
|
||||
to_chat(src, "<span class='revendanger'>NO! No... it's too late, you can feel your essence [pick("breaking apart", "drifting away")]...</span>")
|
||||
notransform = TRUE
|
||||
mob_transforming = TRUE
|
||||
revealed = TRUE
|
||||
invisibility = 0
|
||||
playsound(src, 'sound/effects/screech.ogg', 100, 1)
|
||||
@@ -260,7 +261,7 @@
|
||||
return
|
||||
if(time <= 0)
|
||||
return
|
||||
notransform = TRUE
|
||||
mob_transforming = TRUE
|
||||
if(!unstun_time)
|
||||
to_chat(src, "<span class='revendanger'>You cannot move!</span>")
|
||||
unstun_time = world.time + time
|
||||
@@ -271,7 +272,7 @@
|
||||
|
||||
/mob/living/simple_animal/revenant/proc/update_spooky_icon()
|
||||
if(revealed)
|
||||
if(notransform)
|
||||
if(mob_transforming)
|
||||
if(draining)
|
||||
icon_state = icon_drain
|
||||
else
|
||||
@@ -320,7 +321,7 @@
|
||||
/mob/living/simple_animal/revenant/proc/death_reset()
|
||||
revealed = FALSE
|
||||
unreveal_time = 0
|
||||
notransform = 0
|
||||
mob_transforming = 0
|
||||
unstun_time = 0
|
||||
inhibited = FALSE
|
||||
draining = FALSE
|
||||
|
||||
@@ -369,7 +369,7 @@
|
||||
var/mob/living/carbon/last_user
|
||||
|
||||
/obj/item/warpwhistle/proc/interrupted(mob/living/carbon/user)
|
||||
if(!user || QDELETED(src) || user.notransform)
|
||||
if(!user || QDELETED(src) || user.mob_transforming)
|
||||
on_cooldown = FALSE
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
@@ -1,380 +1,380 @@
|
||||
//DEFINITIONS FOR ASSET DATUMS START HERE.
|
||||
|
||||
/datum/asset/simple/tgui
|
||||
assets = list(
|
||||
"tgui.bundle.js" = 'tgui/packages/tgui/public/tgui.bundle.js',
|
||||
"tgui.bundle.css" = 'tgui/packages/tgui/public/tgui.bundle.css',
|
||||
)
|
||||
|
||||
/datum/asset/group/tgui
|
||||
children = list(
|
||||
/datum/asset/simple/tgui,
|
||||
/datum/asset/simple/fontawesome
|
||||
)
|
||||
|
||||
/datum/asset/simple/headers
|
||||
assets = list(
|
||||
"alarm_green.gif" = 'icons/program_icons/alarm_green.gif',
|
||||
"alarm_red.gif" = 'icons/program_icons/alarm_red.gif',
|
||||
"batt_5.gif" = 'icons/program_icons/batt_5.gif',
|
||||
"batt_20.gif" = 'icons/program_icons/batt_20.gif',
|
||||
"batt_40.gif" = 'icons/program_icons/batt_40.gif',
|
||||
"batt_60.gif" = 'icons/program_icons/batt_60.gif',
|
||||
"batt_80.gif" = 'icons/program_icons/batt_80.gif',
|
||||
"batt_100.gif" = 'icons/program_icons/batt_100.gif',
|
||||
"charging.gif" = 'icons/program_icons/charging.gif',
|
||||
"downloader_finished.gif" = 'icons/program_icons/downloader_finished.gif',
|
||||
"downloader_running.gif" = 'icons/program_icons/downloader_running.gif',
|
||||
"ntnrc_idle.gif" = 'icons/program_icons/ntnrc_idle.gif',
|
||||
"ntnrc_new.gif" = 'icons/program_icons/ntnrc_new.gif',
|
||||
"power_norm.gif" = 'icons/program_icons/power_norm.gif',
|
||||
"power_warn.gif" = 'icons/program_icons/power_warn.gif',
|
||||
"sig_high.gif" = 'icons/program_icons/sig_high.gif',
|
||||
"sig_low.gif" = 'icons/program_icons/sig_low.gif',
|
||||
"sig_lan.gif" = 'icons/program_icons/sig_lan.gif',
|
||||
"sig_none.gif" = 'icons/program_icons/sig_none.gif',
|
||||
"smmon_0.gif" = 'icons/program_icons/smmon_0.gif',
|
||||
"smmon_1.gif" = 'icons/program_icons/smmon_1.gif',
|
||||
"smmon_2.gif" = 'icons/program_icons/smmon_2.gif',
|
||||
"smmon_3.gif" = 'icons/program_icons/smmon_3.gif',
|
||||
"smmon_4.gif" = 'icons/program_icons/smmon_4.gif',
|
||||
"smmon_5.gif" = 'icons/program_icons/smmon_5.gif',
|
||||
"smmon_6.gif" = 'icons/program_icons/smmon_6.gif',
|
||||
"borg_mon.gif" = 'icons/program_icons/borg_mon.gif'
|
||||
)
|
||||
|
||||
/datum/asset/simple/radar_assets
|
||||
assets = list(
|
||||
"ntosradarbackground.png" = 'icons/UI_Icons/tgui/ntosradar_background.png',
|
||||
"ntosradarpointer.png" = 'icons/UI_Icons/tgui/ntosradar_pointer.png',
|
||||
"ntosradarpointerS.png" = 'icons/UI_Icons/tgui/ntosradar_pointer_S.png'
|
||||
)
|
||||
|
||||
/datum/asset/spritesheet/simple/pda
|
||||
name = "pda"
|
||||
assets = list(
|
||||
"atmos" = 'icons/pda_icons/pda_atmos.png',
|
||||
"back" = 'icons/pda_icons/pda_back.png',
|
||||
"bell" = 'icons/pda_icons/pda_bell.png',
|
||||
"blank" = 'icons/pda_icons/pda_blank.png',
|
||||
"boom" = 'icons/pda_icons/pda_boom.png',
|
||||
"bucket" = 'icons/pda_icons/pda_bucket.png',
|
||||
"medbot" = 'icons/pda_icons/pda_medbot.png',
|
||||
"floorbot" = 'icons/pda_icons/pda_floorbot.png',
|
||||
"cleanbot" = 'icons/pda_icons/pda_cleanbot.png',
|
||||
"crate" = 'icons/pda_icons/pda_crate.png',
|
||||
"cuffs" = 'icons/pda_icons/pda_cuffs.png',
|
||||
"eject" = 'icons/pda_icons/pda_eject.png',
|
||||
"flashlight" = 'icons/pda_icons/pda_flashlight.png',
|
||||
"honk" = 'icons/pda_icons/pda_honk.png',
|
||||
"mail" = 'icons/pda_icons/pda_mail.png',
|
||||
"medical" = 'icons/pda_icons/pda_medical.png',
|
||||
"menu" = 'icons/pda_icons/pda_menu.png',
|
||||
"mule" = 'icons/pda_icons/pda_mule.png',
|
||||
"notes" = 'icons/pda_icons/pda_notes.png',
|
||||
"power" = 'icons/pda_icons/pda_power.png',
|
||||
"rdoor" = 'icons/pda_icons/pda_rdoor.png',
|
||||
"reagent" = 'icons/pda_icons/pda_reagent.png',
|
||||
"refresh" = 'icons/pda_icons/pda_refresh.png',
|
||||
"scanner" = 'icons/pda_icons/pda_scanner.png',
|
||||
"signaler" = 'icons/pda_icons/pda_signaler.png',
|
||||
"status" = 'icons/pda_icons/pda_status.png',
|
||||
"dronephone" = 'icons/pda_icons/pda_dronephone.png',
|
||||
"emoji" = 'icons/pda_icons/pda_emoji.png'
|
||||
)
|
||||
|
||||
/datum/asset/spritesheet/simple/paper
|
||||
name = "paper"
|
||||
assets = list(
|
||||
"stamp-clown" = 'icons/stamp_icons/large_stamp-clown.png',
|
||||
"stamp-deny" = 'icons/stamp_icons/large_stamp-deny.png',
|
||||
"stamp-ok" = 'icons/stamp_icons/large_stamp-ok.png',
|
||||
"stamp-hop" = 'icons/stamp_icons/large_stamp-hop.png',
|
||||
"stamp-cmo" = 'icons/stamp_icons/large_stamp-cmo.png',
|
||||
"stamp-ce" = 'icons/stamp_icons/large_stamp-ce.png',
|
||||
"stamp-hos" = 'icons/stamp_icons/large_stamp-hos.png',
|
||||
"stamp-rd" = 'icons/stamp_icons/large_stamp-rd.png',
|
||||
"stamp-cap" = 'icons/stamp_icons/large_stamp-cap.png',
|
||||
"stamp-qm" = 'icons/stamp_icons/large_stamp-qm.png',
|
||||
"stamp-law" = 'icons/stamp_icons/large_stamp-law.png'
|
||||
)
|
||||
|
||||
|
||||
/datum/asset/simple/IRV
|
||||
assets = list(
|
||||
"jquery-ui.custom-core-widgit-mouse-sortable-min.js" = 'html/IRV/jquery-ui.custom-core-widgit-mouse-sortable-min.js',
|
||||
)
|
||||
|
||||
/datum/asset/group/IRV
|
||||
children = list(
|
||||
/datum/asset/simple/jquery,
|
||||
/datum/asset/simple/IRV
|
||||
)
|
||||
|
||||
/datum/asset/simple/changelog
|
||||
assets = list(
|
||||
"88x31.png" = 'html/88x31.png',
|
||||
"bug-minus.png" = 'html/bug-minus.png',
|
||||
"cross-circle.png" = 'html/cross-circle.png',
|
||||
"hard-hat-exclamation.png" = 'html/hard-hat-exclamation.png',
|
||||
"image-minus.png" = 'html/image-minus.png',
|
||||
"image-plus.png" = 'html/image-plus.png',
|
||||
"music-minus.png" = 'html/music-minus.png',
|
||||
"music-plus.png" = 'html/music-plus.png',
|
||||
"tick-circle.png" = 'html/tick-circle.png',
|
||||
"wrench-screwdriver.png" = 'html/wrench-screwdriver.png',
|
||||
"spell-check.png" = 'html/spell-check.png',
|
||||
"burn-exclamation.png" = 'html/burn-exclamation.png',
|
||||
"chevron.png" = 'html/chevron.png',
|
||||
"chevron-expand.png" = 'html/chevron-expand.png',
|
||||
"scales.png" = 'html/scales.png',
|
||||
"coding.png" = 'html/coding.png',
|
||||
"ban.png" = 'html/ban.png',
|
||||
"chrome-wrench.png" = 'html/chrome-wrench.png',
|
||||
"changelog.css" = 'html/changelog.css'
|
||||
)
|
||||
|
||||
/datum/asset/group/goonchat
|
||||
children = list(
|
||||
/datum/asset/simple/jquery,
|
||||
/datum/asset/simple/goonchat,
|
||||
/datum/asset/spritesheet/goonchat,
|
||||
/datum/asset/simple/fontawesome
|
||||
)
|
||||
|
||||
/datum/asset/simple/jquery
|
||||
assets = list(
|
||||
"jquery.min.js" = 'code/modules/goonchat/browserassets/js/jquery.min.js',
|
||||
)
|
||||
|
||||
|
||||
/datum/asset/simple/goonchat
|
||||
assets = list(
|
||||
"json2.min.js" = 'code/modules/goonchat/browserassets/js/json2.min.js',
|
||||
"browserOutput.js" = 'code/modules/goonchat/browserassets/js/browserOutput.js',
|
||||
"browserOutput.css" = 'code/modules/goonchat/browserassets/css/browserOutput.css',
|
||||
"browserOutput_dark.css" = 'code/modules/goonchat/browserassets/css/browserOutput_dark.css',
|
||||
"browserOutput_light.css" = 'code/modules/goonchat/browserassets/css/browserOutput_light.css'
|
||||
)
|
||||
|
||||
/datum/asset/simple/fontawesome
|
||||
assets = list(
|
||||
"fa-regular-400.eot" = 'html/font-awesome/webfonts/fa-regular-400.eot',
|
||||
"fa-regular-400.woff" = 'html/font-awesome/webfonts/fa-regular-400.woff',
|
||||
"fa-solid-900.eot" = 'html/font-awesome/webfonts/fa-solid-900.eot',
|
||||
"fa-solid-900.woff" = 'html/font-awesome/webfonts/fa-solid-900.woff',
|
||||
"font-awesome.css" = 'html/font-awesome/css/all.min.css',
|
||||
"v4shim.css" = 'html/font-awesome/css/v4-shims.min.css'
|
||||
)
|
||||
|
||||
/datum/asset/spritesheet/goonchat
|
||||
name = "chat"
|
||||
|
||||
/datum/asset/spritesheet/goonchat/register()
|
||||
InsertAll("emoji", 'icons/emoji.dmi')
|
||||
|
||||
// pre-loading all lanugage icons also helps to avoid meta
|
||||
InsertAll("language", 'icons/misc/language.dmi')
|
||||
// catch languages which are pulling icons from another file
|
||||
for(var/path in typesof(/datum/language))
|
||||
var/datum/language/L = path
|
||||
var/icon = initial(L.icon)
|
||||
if (icon != 'icons/misc/language.dmi')
|
||||
var/icon_state = initial(L.icon_state)
|
||||
Insert("language-[icon_state]", icon, icon_state=icon_state)
|
||||
|
||||
..()
|
||||
|
||||
/datum/asset/simple/permissions
|
||||
assets = list(
|
||||
"padlock.png" = 'html/padlock.png'
|
||||
)
|
||||
|
||||
/datum/asset/simple/notes
|
||||
assets = list(
|
||||
"high_button.png" = 'html/high_button.png',
|
||||
"medium_button.png" = 'html/medium_button.png',
|
||||
"minor_button.png" = 'html/minor_button.png',
|
||||
"none_button.png" = 'html/none_button.png',
|
||||
)
|
||||
|
||||
/datum/asset/simple/arcade
|
||||
assets = list(
|
||||
"boss1.gif" = 'icons/UI_Icons/Arcade/boss1.gif',
|
||||
"boss2.gif" = 'icons/UI_Icons/Arcade/boss2.gif',
|
||||
"boss3.gif" = 'icons/UI_Icons/Arcade/boss3.gif',
|
||||
"boss4.gif" = 'icons/UI_Icons/Arcade/boss4.gif',
|
||||
"boss5.gif" = 'icons/UI_Icons/Arcade/boss5.gif',
|
||||
"boss6.gif" = 'icons/UI_Icons/Arcade/boss6.gif',
|
||||
)
|
||||
|
||||
/datum/asset/spritesheet/simple/minesweeper
|
||||
name = "minesweeper"
|
||||
assets = list(
|
||||
"1" = 'icons/UI_Icons/minesweeper_tiles/one.png',
|
||||
"2" = 'icons/UI_Icons/minesweeper_tiles/two.png',
|
||||
"3" = 'icons/UI_Icons/minesweeper_tiles/three.png',
|
||||
"4" = 'icons/UI_Icons/minesweeper_tiles/four.png',
|
||||
"5" = 'icons/UI_Icons/minesweeper_tiles/five.png',
|
||||
"6" = 'icons/UI_Icons/minesweeper_tiles/six.png',
|
||||
"7" = 'icons/UI_Icons/minesweeper_tiles/seven.png',
|
||||
"8" = 'icons/UI_Icons/minesweeper_tiles/eight.png',
|
||||
"empty" = 'icons/UI_Icons/minesweeper_tiles/empty.png',
|
||||
"flag" = 'icons/UI_Icons/minesweeper_tiles/flag.png',
|
||||
"hidden" = 'icons/UI_Icons/minesweeper_tiles/hidden.png',
|
||||
"mine" = 'icons/UI_Icons/minesweeper_tiles/mine.png',
|
||||
"minehit" = 'icons/UI_Icons/minesweeper_tiles/minehit.png'
|
||||
)
|
||||
|
||||
|
||||
/datum/asset/spritesheet/simple/pills
|
||||
name ="pills"
|
||||
assets = list(
|
||||
"pill1" = 'icons/UI_Icons/Pills/pill1.png',
|
||||
"pill2" = 'icons/UI_Icons/Pills/pill2.png',
|
||||
"pill3" = 'icons/UI_Icons/Pills/pill3.png',
|
||||
"pill4" = 'icons/UI_Icons/Pills/pill4.png',
|
||||
"pill5" = 'icons/UI_Icons/Pills/pill5.png',
|
||||
"pill6" = 'icons/UI_Icons/Pills/pill6.png',
|
||||
"pill7" = 'icons/UI_Icons/Pills/pill7.png',
|
||||
"pill8" = 'icons/UI_Icons/Pills/pill8.png',
|
||||
"pill9" = 'icons/UI_Icons/Pills/pill9.png',
|
||||
"pill10" = 'icons/UI_Icons/Pills/pill10.png',
|
||||
"pill11" = 'icons/UI_Icons/Pills/pill11.png',
|
||||
"pill12" = 'icons/UI_Icons/Pills/pill12.png',
|
||||
"pill13" = 'icons/UI_Icons/Pills/pill13.png',
|
||||
"pill14" = 'icons/UI_Icons/Pills/pill14.png',
|
||||
"pill15" = 'icons/UI_Icons/Pills/pill15.png',
|
||||
"pill16" = 'icons/UI_Icons/Pills/pill16.png',
|
||||
"pill17" = 'icons/UI_Icons/Pills/pill17.png',
|
||||
"pill18" = 'icons/UI_Icons/Pills/pill18.png',
|
||||
"pill19" = 'icons/UI_Icons/Pills/pill19.png',
|
||||
"pill20" = 'icons/UI_Icons/Pills/pill20.png',
|
||||
"pill21" = 'icons/UI_Icons/Pills/pill21.png',
|
||||
"pill22" = 'icons/UI_Icons/Pills/pill22.png',
|
||||
)
|
||||
|
||||
//this exists purely to avoid meta by pre-loading all language icons.
|
||||
/datum/asset/language/register()
|
||||
for(var/path in typesof(/datum/language))
|
||||
set waitfor = FALSE
|
||||
var/datum/language/L = new path ()
|
||||
L.get_icon()
|
||||
|
||||
/datum/asset/spritesheet/pipes
|
||||
name = "pipes"
|
||||
|
||||
/datum/asset/spritesheet/pipes/register()
|
||||
for (var/each in list('icons/obj/atmospherics/pipes/pipe_item.dmi', 'icons/obj/atmospherics/pipes/disposal.dmi'))
|
||||
InsertAll("", each, GLOB.alldirs)
|
||||
..()
|
||||
|
||||
// Representative icons for each research design
|
||||
/datum/asset/spritesheet/research_designs
|
||||
name = "design"
|
||||
|
||||
/datum/asset/spritesheet/research_designs/register()
|
||||
for (var/path in subtypesof(/datum/design))
|
||||
var/datum/design/D = path
|
||||
|
||||
var/icon_file
|
||||
var/icon_state
|
||||
var/icon/I
|
||||
|
||||
if(initial(D.research_icon) && initial(D.research_icon_state)) //If the design has an icon replacement skip the rest
|
||||
icon_file = initial(D.research_icon)
|
||||
icon_state = initial(D.research_icon_state)
|
||||
if(!(icon_state in icon_states(icon_file)))
|
||||
warning("design [D] with icon '[icon_file]' missing state '[icon_state]'")
|
||||
continue
|
||||
I = icon(icon_file, icon_state, SOUTH)
|
||||
|
||||
else
|
||||
// construct the icon and slap it into the resource cache
|
||||
var/atom/item = initial(D.build_path)
|
||||
if (!ispath(item, /atom))
|
||||
// biogenerator outputs to beakers by default
|
||||
if (initial(D.build_type) & BIOGENERATOR)
|
||||
item = /obj/item/reagent_containers/glass/beaker/large
|
||||
else
|
||||
continue // shouldn't happen, but just in case
|
||||
|
||||
// circuit boards become their resulting machines or computers
|
||||
if (ispath(item, /obj/item/circuitboard))
|
||||
var/obj/item/circuitboard/C = item
|
||||
var/machine = initial(C.build_path)
|
||||
if (machine)
|
||||
item = machine
|
||||
|
||||
icon_file = initial(item.icon)
|
||||
icon_state = initial(item.icon_state)
|
||||
|
||||
if(!(icon_state in icon_states(icon_file)))
|
||||
warning("design [D] with icon '[icon_file]' missing state '[icon_state]'")
|
||||
continue
|
||||
I = icon(icon_file, icon_state, SOUTH)
|
||||
|
||||
// computers (and snowflakes) get their screen and keyboard sprites
|
||||
if (ispath(item, /obj/machinery/computer) || ispath(item, /obj/machinery/power/solar_control))
|
||||
var/obj/machinery/computer/C = item
|
||||
var/screen = initial(C.icon_screen)
|
||||
var/keyboard = initial(C.icon_keyboard)
|
||||
var/all_states = icon_states(icon_file)
|
||||
if (screen && (screen in all_states))
|
||||
I.Blend(icon(icon_file, screen, SOUTH), ICON_OVERLAY)
|
||||
if (keyboard && (keyboard in all_states))
|
||||
I.Blend(icon(icon_file, keyboard, SOUTH), ICON_OVERLAY)
|
||||
|
||||
Insert(initial(D.id), I)
|
||||
return ..()
|
||||
|
||||
/datum/asset/spritesheet/vending
|
||||
name = "vending"
|
||||
|
||||
/datum/asset/spritesheet/vending/register()
|
||||
for (var/k in GLOB.vending_products)
|
||||
var/atom/item = k
|
||||
if (!ispath(item, /atom))
|
||||
continue
|
||||
|
||||
var/icon_file = initial(item.icon)
|
||||
var/icon_state = initial(item.icon_state)
|
||||
var/icon/I
|
||||
|
||||
var/icon_states_list = icon_states(icon_file)
|
||||
if(icon_state in icon_states_list)
|
||||
I = icon(icon_file, icon_state, SOUTH)
|
||||
var/c = initial(item.color)
|
||||
if (!isnull(c) && c != "#FFFFFF")
|
||||
I.Blend(c, ICON_MULTIPLY)
|
||||
else
|
||||
var/icon_states_string
|
||||
for (var/an_icon_state in icon_states_list)
|
||||
if (!icon_states_string)
|
||||
icon_states_string = "[json_encode(an_icon_state)](\ref[an_icon_state])"
|
||||
else
|
||||
icon_states_string += ", [json_encode(an_icon_state)](\ref[an_icon_state])"
|
||||
stack_trace("[item] does not have a valid icon state, icon=[icon_file], icon_state=[json_encode(icon_state)](\ref[icon_state]), icon_states=[icon_states_string]")
|
||||
I = icon('icons/turf/floors.dmi', "", SOUTH)
|
||||
|
||||
var/imgid = replacetext(replacetext("[item]", "/obj/item/", ""), "/", "-")
|
||||
|
||||
Insert(imgid, I)
|
||||
return ..()
|
||||
|
||||
/datum/asset/simple/genetics
|
||||
assets = list(
|
||||
"dna_discovered.gif" = 'html/dna_discovered.gif',
|
||||
"dna_undiscovered.gif" = 'html/dna_undiscovered.gif',
|
||||
"dna_extra.gif" = 'html/dna_extra.gif'
|
||||
)
|
||||
|
||||
/datum/asset/simple/orbit
|
||||
assets = list(
|
||||
"ghost.png" = 'html/ghost.png'
|
||||
)
|
||||
|
||||
assets = list(
|
||||
"ghost.png" = 'html/ghost.png'
|
||||
)
|
||||
|
||||
//DEFINITIONS FOR ASSET DATUMS START HERE.
|
||||
|
||||
/datum/asset/simple/tgui
|
||||
assets = list(
|
||||
"tgui.bundle.js" = 'tgui/packages/tgui/public/tgui.bundle.js',
|
||||
"tgui.bundle.css" = 'tgui/packages/tgui/public/tgui.bundle.css',
|
||||
)
|
||||
|
||||
/datum/asset/group/tgui
|
||||
children = list(
|
||||
/datum/asset/simple/tgui,
|
||||
/datum/asset/simple/fontawesome
|
||||
)
|
||||
|
||||
/datum/asset/simple/headers
|
||||
assets = list(
|
||||
"alarm_green.gif" = 'icons/program_icons/alarm_green.gif',
|
||||
"alarm_red.gif" = 'icons/program_icons/alarm_red.gif',
|
||||
"batt_5.gif" = 'icons/program_icons/batt_5.gif',
|
||||
"batt_20.gif" = 'icons/program_icons/batt_20.gif',
|
||||
"batt_40.gif" = 'icons/program_icons/batt_40.gif',
|
||||
"batt_60.gif" = 'icons/program_icons/batt_60.gif',
|
||||
"batt_80.gif" = 'icons/program_icons/batt_80.gif',
|
||||
"batt_100.gif" = 'icons/program_icons/batt_100.gif',
|
||||
"charging.gif" = 'icons/program_icons/charging.gif',
|
||||
"downloader_finished.gif" = 'icons/program_icons/downloader_finished.gif',
|
||||
"downloader_running.gif" = 'icons/program_icons/downloader_running.gif',
|
||||
"ntnrc_idle.gif" = 'icons/program_icons/ntnrc_idle.gif',
|
||||
"ntnrc_new.gif" = 'icons/program_icons/ntnrc_new.gif',
|
||||
"power_norm.gif" = 'icons/program_icons/power_norm.gif',
|
||||
"power_warn.gif" = 'icons/program_icons/power_warn.gif',
|
||||
"sig_high.gif" = 'icons/program_icons/sig_high.gif',
|
||||
"sig_low.gif" = 'icons/program_icons/sig_low.gif',
|
||||
"sig_lan.gif" = 'icons/program_icons/sig_lan.gif',
|
||||
"sig_none.gif" = 'icons/program_icons/sig_none.gif',
|
||||
"smmon_0.gif" = 'icons/program_icons/smmon_0.gif',
|
||||
"smmon_1.gif" = 'icons/program_icons/smmon_1.gif',
|
||||
"smmon_2.gif" = 'icons/program_icons/smmon_2.gif',
|
||||
"smmon_3.gif" = 'icons/program_icons/smmon_3.gif',
|
||||
"smmon_4.gif" = 'icons/program_icons/smmon_4.gif',
|
||||
"smmon_5.gif" = 'icons/program_icons/smmon_5.gif',
|
||||
"smmon_6.gif" = 'icons/program_icons/smmon_6.gif',
|
||||
"borg_mon.gif" = 'icons/program_icons/borg_mon.gif'
|
||||
)
|
||||
|
||||
/datum/asset/simple/radar_assets
|
||||
assets = list(
|
||||
"ntosradarbackground.png" = 'icons/UI_Icons/tgui/ntosradar_background.png',
|
||||
"ntosradarpointer.png" = 'icons/UI_Icons/tgui/ntosradar_pointer.png',
|
||||
"ntosradarpointerS.png" = 'icons/UI_Icons/tgui/ntosradar_pointer_S.png'
|
||||
)
|
||||
|
||||
/datum/asset/spritesheet/simple/pda
|
||||
name = "pda"
|
||||
assets = list(
|
||||
"atmos" = 'icons/pda_icons/pda_atmos.png',
|
||||
"back" = 'icons/pda_icons/pda_back.png',
|
||||
"bell" = 'icons/pda_icons/pda_bell.png',
|
||||
"blank" = 'icons/pda_icons/pda_blank.png',
|
||||
"boom" = 'icons/pda_icons/pda_boom.png',
|
||||
"bucket" = 'icons/pda_icons/pda_bucket.png',
|
||||
"medbot" = 'icons/pda_icons/pda_medbot.png',
|
||||
"floorbot" = 'icons/pda_icons/pda_floorbot.png',
|
||||
"cleanbot" = 'icons/pda_icons/pda_cleanbot.png',
|
||||
"crate" = 'icons/pda_icons/pda_crate.png',
|
||||
"cuffs" = 'icons/pda_icons/pda_cuffs.png',
|
||||
"eject" = 'icons/pda_icons/pda_eject.png',
|
||||
"flashlight" = 'icons/pda_icons/pda_flashlight.png',
|
||||
"honk" = 'icons/pda_icons/pda_honk.png',
|
||||
"mail" = 'icons/pda_icons/pda_mail.png',
|
||||
"medical" = 'icons/pda_icons/pda_medical.png',
|
||||
"menu" = 'icons/pda_icons/pda_menu.png',
|
||||
"mule" = 'icons/pda_icons/pda_mule.png',
|
||||
"notes" = 'icons/pda_icons/pda_notes.png',
|
||||
"power" = 'icons/pda_icons/pda_power.png',
|
||||
"rdoor" = 'icons/pda_icons/pda_rdoor.png',
|
||||
"reagent" = 'icons/pda_icons/pda_reagent.png',
|
||||
"refresh" = 'icons/pda_icons/pda_refresh.png',
|
||||
"scanner" = 'icons/pda_icons/pda_scanner.png',
|
||||
"signaler" = 'icons/pda_icons/pda_signaler.png',
|
||||
"status" = 'icons/pda_icons/pda_status.png',
|
||||
"dronephone" = 'icons/pda_icons/pda_dronephone.png',
|
||||
"emoji" = 'icons/pda_icons/pda_emoji.png'
|
||||
)
|
||||
|
||||
/datum/asset/spritesheet/simple/paper
|
||||
name = "paper"
|
||||
assets = list(
|
||||
"stamp-clown" = 'icons/stamp_icons/large_stamp-clown.png',
|
||||
"stamp-deny" = 'icons/stamp_icons/large_stamp-deny.png',
|
||||
"stamp-ok" = 'icons/stamp_icons/large_stamp-ok.png',
|
||||
"stamp-hop" = 'icons/stamp_icons/large_stamp-hop.png',
|
||||
"stamp-cmo" = 'icons/stamp_icons/large_stamp-cmo.png',
|
||||
"stamp-ce" = 'icons/stamp_icons/large_stamp-ce.png',
|
||||
"stamp-hos" = 'icons/stamp_icons/large_stamp-hos.png',
|
||||
"stamp-rd" = 'icons/stamp_icons/large_stamp-rd.png',
|
||||
"stamp-cap" = 'icons/stamp_icons/large_stamp-cap.png',
|
||||
"stamp-qm" = 'icons/stamp_icons/large_stamp-qm.png',
|
||||
"stamp-law" = 'icons/stamp_icons/large_stamp-law.png'
|
||||
)
|
||||
|
||||
|
||||
/datum/asset/simple/IRV
|
||||
assets = list(
|
||||
"jquery-ui.custom-core-widgit-mouse-sortable-min.js" = 'html/IRV/jquery-ui.custom-core-widgit-mouse-sortable-min.js',
|
||||
)
|
||||
|
||||
/datum/asset/group/IRV
|
||||
children = list(
|
||||
/datum/asset/simple/jquery,
|
||||
/datum/asset/simple/IRV
|
||||
)
|
||||
|
||||
/datum/asset/simple/changelog
|
||||
assets = list(
|
||||
"88x31.png" = 'html/88x31.png',
|
||||
"bug-minus.png" = 'html/bug-minus.png',
|
||||
"cross-circle.png" = 'html/cross-circle.png',
|
||||
"hard-hat-exclamation.png" = 'html/hard-hat-exclamation.png',
|
||||
"image-minus.png" = 'html/image-minus.png',
|
||||
"image-plus.png" = 'html/image-plus.png',
|
||||
"music-minus.png" = 'html/music-minus.png',
|
||||
"music-plus.png" = 'html/music-plus.png',
|
||||
"tick-circle.png" = 'html/tick-circle.png',
|
||||
"wrench-screwdriver.png" = 'html/wrench-screwdriver.png',
|
||||
"spell-check.png" = 'html/spell-check.png',
|
||||
"burn-exclamation.png" = 'html/burn-exclamation.png',
|
||||
"chevron.png" = 'html/chevron.png',
|
||||
"chevron-expand.png" = 'html/chevron-expand.png',
|
||||
"scales.png" = 'html/scales.png',
|
||||
"coding.png" = 'html/coding.png',
|
||||
"ban.png" = 'html/ban.png',
|
||||
"chrome-wrench.png" = 'html/chrome-wrench.png',
|
||||
"changelog.css" = 'html/changelog.css'
|
||||
)
|
||||
|
||||
/datum/asset/group/goonchat
|
||||
children = list(
|
||||
/datum/asset/simple/jquery,
|
||||
/datum/asset/simple/goonchat,
|
||||
/datum/asset/spritesheet/goonchat,
|
||||
/datum/asset/simple/fontawesome
|
||||
)
|
||||
|
||||
/datum/asset/simple/jquery
|
||||
assets = list(
|
||||
"jquery.min.js" = 'code/modules/goonchat/browserassets/js/jquery.min.js',
|
||||
)
|
||||
|
||||
|
||||
/datum/asset/simple/goonchat
|
||||
assets = list(
|
||||
"json2.min.js" = 'code/modules/goonchat/browserassets/js/json2.min.js',
|
||||
"browserOutput.js" = 'code/modules/goonchat/browserassets/js/browserOutput.js',
|
||||
"browserOutput.css" = 'code/modules/goonchat/browserassets/css/browserOutput.css',
|
||||
"browserOutput_dark.css" = 'code/modules/goonchat/browserassets/css/browserOutput_dark.css',
|
||||
"browserOutput_light.css" = 'code/modules/goonchat/browserassets/css/browserOutput_light.css'
|
||||
)
|
||||
|
||||
/datum/asset/simple/fontawesome
|
||||
assets = list(
|
||||
"fa-regular-400.eot" = 'html/font-awesome/webfonts/fa-regular-400.eot',
|
||||
"fa-regular-400.woff" = 'html/font-awesome/webfonts/fa-regular-400.woff',
|
||||
"fa-solid-900.eot" = 'html/font-awesome/webfonts/fa-solid-900.eot',
|
||||
"fa-solid-900.woff" = 'html/font-awesome/webfonts/fa-solid-900.woff',
|
||||
"font-awesome.css" = 'html/font-awesome/css/all.min.css',
|
||||
"v4shim.css" = 'html/font-awesome/css/v4-shims.min.css'
|
||||
)
|
||||
|
||||
/datum/asset/spritesheet/goonchat
|
||||
name = "chat"
|
||||
|
||||
/datum/asset/spritesheet/goonchat/register()
|
||||
InsertAll("emoji", 'icons/emoji.dmi')
|
||||
|
||||
// pre-loading all lanugage icons also helps to avoid meta
|
||||
InsertAll("language", 'icons/misc/language.dmi')
|
||||
// catch languages which are pulling icons from another file
|
||||
for(var/path in typesof(/datum/language))
|
||||
var/datum/language/L = path
|
||||
var/icon = initial(L.icon)
|
||||
if (icon != 'icons/misc/language.dmi')
|
||||
var/icon_state = initial(L.icon_state)
|
||||
Insert("language-[icon_state]", icon, icon_state=icon_state)
|
||||
|
||||
..()
|
||||
|
||||
/datum/asset/simple/permissions
|
||||
assets = list(
|
||||
"padlock.png" = 'html/padlock.png'
|
||||
)
|
||||
|
||||
/datum/asset/simple/notes
|
||||
assets = list(
|
||||
"high_button.png" = 'html/high_button.png',
|
||||
"medium_button.png" = 'html/medium_button.png',
|
||||
"minor_button.png" = 'html/minor_button.png',
|
||||
"none_button.png" = 'html/none_button.png',
|
||||
)
|
||||
|
||||
/datum/asset/simple/arcade
|
||||
assets = list(
|
||||
"boss1.gif" = 'icons/UI_Icons/Arcade/boss1.gif',
|
||||
"boss2.gif" = 'icons/UI_Icons/Arcade/boss2.gif',
|
||||
"boss3.gif" = 'icons/UI_Icons/Arcade/boss3.gif',
|
||||
"boss4.gif" = 'icons/UI_Icons/Arcade/boss4.gif',
|
||||
"boss5.gif" = 'icons/UI_Icons/Arcade/boss5.gif',
|
||||
"boss6.gif" = 'icons/UI_Icons/Arcade/boss6.gif',
|
||||
)
|
||||
|
||||
/datum/asset/spritesheet/simple/minesweeper
|
||||
name = "minesweeper"
|
||||
assets = list(
|
||||
"1" = 'icons/UI_Icons/minesweeper_tiles/one.png',
|
||||
"2" = 'icons/UI_Icons/minesweeper_tiles/two.png',
|
||||
"3" = 'icons/UI_Icons/minesweeper_tiles/three.png',
|
||||
"4" = 'icons/UI_Icons/minesweeper_tiles/four.png',
|
||||
"5" = 'icons/UI_Icons/minesweeper_tiles/five.png',
|
||||
"6" = 'icons/UI_Icons/minesweeper_tiles/six.png',
|
||||
"7" = 'icons/UI_Icons/minesweeper_tiles/seven.png',
|
||||
"8" = 'icons/UI_Icons/minesweeper_tiles/eight.png',
|
||||
"empty" = 'icons/UI_Icons/minesweeper_tiles/empty.png',
|
||||
"flag" = 'icons/UI_Icons/minesweeper_tiles/flag.png',
|
||||
"hidden" = 'icons/UI_Icons/minesweeper_tiles/hidden.png',
|
||||
"mine" = 'icons/UI_Icons/minesweeper_tiles/mine.png',
|
||||
"minehit" = 'icons/UI_Icons/minesweeper_tiles/minehit.png'
|
||||
)
|
||||
|
||||
|
||||
/datum/asset/spritesheet/simple/pills
|
||||
name ="pills"
|
||||
assets = list(
|
||||
"pill1" = 'icons/UI_Icons/Pills/pill1.png',
|
||||
"pill2" = 'icons/UI_Icons/Pills/pill2.png',
|
||||
"pill3" = 'icons/UI_Icons/Pills/pill3.png',
|
||||
"pill4" = 'icons/UI_Icons/Pills/pill4.png',
|
||||
"pill5" = 'icons/UI_Icons/Pills/pill5.png',
|
||||
"pill6" = 'icons/UI_Icons/Pills/pill6.png',
|
||||
"pill7" = 'icons/UI_Icons/Pills/pill7.png',
|
||||
"pill8" = 'icons/UI_Icons/Pills/pill8.png',
|
||||
"pill9" = 'icons/UI_Icons/Pills/pill9.png',
|
||||
"pill10" = 'icons/UI_Icons/Pills/pill10.png',
|
||||
"pill11" = 'icons/UI_Icons/Pills/pill11.png',
|
||||
"pill12" = 'icons/UI_Icons/Pills/pill12.png',
|
||||
"pill13" = 'icons/UI_Icons/Pills/pill13.png',
|
||||
"pill14" = 'icons/UI_Icons/Pills/pill14.png',
|
||||
"pill15" = 'icons/UI_Icons/Pills/pill15.png',
|
||||
"pill16" = 'icons/UI_Icons/Pills/pill16.png',
|
||||
"pill17" = 'icons/UI_Icons/Pills/pill17.png',
|
||||
"pill18" = 'icons/UI_Icons/Pills/pill18.png',
|
||||
"pill19" = 'icons/UI_Icons/Pills/pill19.png',
|
||||
"pill20" = 'icons/UI_Icons/Pills/pill20.png',
|
||||
"pill21" = 'icons/UI_Icons/Pills/pill21.png',
|
||||
"pill22" = 'icons/UI_Icons/Pills/pill22.png',
|
||||
)
|
||||
|
||||
//this exists purely to avoid meta by pre-loading all language icons.
|
||||
/datum/asset/language/register()
|
||||
for(var/path in typesof(/datum/language))
|
||||
set waitfor = FALSE
|
||||
var/datum/language/L = new path ()
|
||||
L.get_icon()
|
||||
|
||||
/datum/asset/spritesheet/pipes
|
||||
name = "pipes"
|
||||
|
||||
/datum/asset/spritesheet/pipes/register()
|
||||
for (var/each in list('icons/obj/atmospherics/pipes/pipe_item.dmi', 'icons/obj/atmospherics/pipes/disposal.dmi'))
|
||||
InsertAll("", each, GLOB.alldirs)
|
||||
..()
|
||||
|
||||
// Representative icons for each research design
|
||||
/datum/asset/spritesheet/research_designs
|
||||
name = "design"
|
||||
|
||||
/datum/asset/spritesheet/research_designs/register()
|
||||
for (var/path in subtypesof(/datum/design))
|
||||
var/datum/design/D = path
|
||||
|
||||
var/icon_file
|
||||
var/icon_state
|
||||
var/icon/I
|
||||
|
||||
if(initial(D.research_icon) && initial(D.research_icon_state)) //If the design has an icon replacement skip the rest
|
||||
icon_file = initial(D.research_icon)
|
||||
icon_state = initial(D.research_icon_state)
|
||||
if(!(icon_state in icon_states(icon_file)))
|
||||
warning("design [D] with icon '[icon_file]' missing state '[icon_state]'")
|
||||
continue
|
||||
I = icon(icon_file, icon_state, SOUTH)
|
||||
|
||||
else
|
||||
// construct the icon and slap it into the resource cache
|
||||
var/atom/item = initial(D.build_path)
|
||||
if (!ispath(item, /atom))
|
||||
// biogenerator outputs to beakers by default
|
||||
if (initial(D.build_type) & BIOGENERATOR)
|
||||
item = /obj/item/reagent_containers/glass/beaker/large
|
||||
else
|
||||
continue // shouldn't happen, but just in case
|
||||
|
||||
// circuit boards become their resulting machines or computers
|
||||
if (ispath(item, /obj/item/circuitboard))
|
||||
var/obj/item/circuitboard/C = item
|
||||
var/machine = initial(C.build_path)
|
||||
if (machine)
|
||||
item = machine
|
||||
|
||||
icon_file = initial(item.icon)
|
||||
icon_state = initial(item.icon_state)
|
||||
|
||||
if(!(icon_state in icon_states(icon_file)))
|
||||
warning("design [D] with icon '[icon_file]' missing state '[icon_state]'")
|
||||
continue
|
||||
I = icon(icon_file, icon_state, SOUTH)
|
||||
|
||||
// computers (and snowflakes) get their screen and keyboard sprites
|
||||
if (ispath(item, /obj/machinery/computer) || ispath(item, /obj/machinery/power/solar_control))
|
||||
var/obj/machinery/computer/C = item
|
||||
var/screen = initial(C.icon_screen)
|
||||
var/keyboard = initial(C.icon_keyboard)
|
||||
var/all_states = icon_states(icon_file)
|
||||
if (screen && (screen in all_states))
|
||||
I.Blend(icon(icon_file, screen, SOUTH), ICON_OVERLAY)
|
||||
if (keyboard && (keyboard in all_states))
|
||||
I.Blend(icon(icon_file, keyboard, SOUTH), ICON_OVERLAY)
|
||||
|
||||
Insert(initial(D.id), I)
|
||||
return ..()
|
||||
|
||||
/datum/asset/spritesheet/vending
|
||||
name = "vending"
|
||||
|
||||
/datum/asset/spritesheet/vending/register()
|
||||
for (var/k in GLOB.vending_products)
|
||||
var/atom/item = k
|
||||
if (!ispath(item, /atom))
|
||||
continue
|
||||
|
||||
var/icon_file = initial(item.icon)
|
||||
var/icon_state = initial(item.icon_state)
|
||||
var/icon/I
|
||||
|
||||
var/icon_states_list = icon_states(icon_file)
|
||||
if(icon_state in icon_states_list)
|
||||
I = icon(icon_file, icon_state, SOUTH)
|
||||
var/c = initial(item.color)
|
||||
if (!isnull(c) && c != "#FFFFFF")
|
||||
I.Blend(c, ICON_MULTIPLY)
|
||||
else
|
||||
var/icon_states_string
|
||||
for (var/an_icon_state in icon_states_list)
|
||||
if (!icon_states_string)
|
||||
icon_states_string = "[json_encode(an_icon_state)](\ref[an_icon_state])"
|
||||
else
|
||||
icon_states_string += ", [json_encode(an_icon_state)](\ref[an_icon_state])"
|
||||
stack_trace("[item] does not have a valid icon state, icon=[icon_file], icon_state=[json_encode(icon_state)](\ref[icon_state]), icon_states=[icon_states_string]")
|
||||
I = icon('icons/turf/floors.dmi', "", SOUTH)
|
||||
|
||||
var/imgid = replacetext(replacetext("[item]", "/obj/item/", ""), "/", "-")
|
||||
|
||||
Insert(imgid, I)
|
||||
return ..()
|
||||
|
||||
/datum/asset/simple/genetics
|
||||
assets = list(
|
||||
"dna_discovered.gif" = 'html/dna_discovered.gif',
|
||||
"dna_undiscovered.gif" = 'html/dna_undiscovered.gif',
|
||||
"dna_extra.gif" = 'html/dna_extra.gif'
|
||||
)
|
||||
|
||||
/datum/asset/simple/orbit
|
||||
assets = list(
|
||||
"ghost.png" = 'html/ghost.png'
|
||||
)
|
||||
|
||||
assets = list(
|
||||
"ghost.png" = 'html/ghost.png'
|
||||
)
|
||||
|
||||
|
||||
@@ -1,20 +1,39 @@
|
||||
|
||||
/*Cabin areas*/
|
||||
/area/awaymission/snowforest
|
||||
name = "Snow Forest"
|
||||
icon_state = "away"
|
||||
requires_power = FALSE
|
||||
dynamic_lighting = DYNAMIC_LIGHTING_ENABLED
|
||||
|
||||
/area/awaymission/cabin
|
||||
name = "Cabin"
|
||||
icon_state = "away2"
|
||||
requires_power = TRUE
|
||||
dynamic_lighting = DYNAMIC_LIGHTING_ENABLED
|
||||
|
||||
/area/awaymission/snowforest/lumbermill
|
||||
/area/awaymission/cabin/snowforest
|
||||
name = "Snow Forest"
|
||||
icon_state = "away"
|
||||
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
|
||||
|
||||
/area/awaymission/cabin/snowforest/sovietsurface
|
||||
name = "Snow Forest"
|
||||
icon_state = "awaycontent29"
|
||||
requires_power = FALSE
|
||||
|
||||
/area/awaymission/cabin/lumbermill
|
||||
name = "Lumbermill"
|
||||
icon_state = "away3"
|
||||
requires_power = FALSE
|
||||
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
|
||||
|
||||
/area/awaymission/cabin/caves/sovietcave
|
||||
name = "Soviet Bunker"
|
||||
icon_state = "awaycontent4"
|
||||
|
||||
/area/awaymission/cabin/caves
|
||||
name = "North Snowdin Caves"
|
||||
icon_state = "awaycontent15"
|
||||
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
|
||||
|
||||
/area/awaymission/cabin/caves/mountain
|
||||
name = "North Snowdin Mountains"
|
||||
icon_state = "awaycontent24"
|
||||
|
||||
/obj/structure/firepit
|
||||
name = "firepit"
|
||||
@@ -92,7 +111,7 @@
|
||||
egg_type = null
|
||||
speak = list()
|
||||
|
||||
/*Cabin's forest*/
|
||||
/*Cabin's forest. Removed in the new cabin map since it was buggy and I prefer manual placement.*/
|
||||
/datum/mapGenerator/snowy
|
||||
modules = list(/datum/mapGeneratorModule/bottomlayer/snow, \
|
||||
/datum/mapGeneratorModule/snow/pineTrees, \
|
||||
@@ -136,4 +155,4 @@
|
||||
endTurfX = 159
|
||||
endTurfY = 157
|
||||
startTurfX = 37
|
||||
startTurfY = 35
|
||||
startTurfY = 35
|
||||
@@ -18,6 +18,7 @@
|
||||
var/obj/item/radio/headset/radio
|
||||
/// var that tracks message cooldown
|
||||
var/message_cooldown
|
||||
var/list/loaded_coupons
|
||||
|
||||
light_color = "#E2853D"//orange
|
||||
|
||||
@@ -134,6 +135,8 @@
|
||||
"cost" = P.cost,
|
||||
"id" = pack,
|
||||
"desc" = P.desc || P.name, // If there is a description, use it. Otherwise use the pack's name.
|
||||
"private_goody" = P.goody == PACK_GOODY_PRIVATE,
|
||||
"goody" = P.goody == PACK_GOODY_PUBLIC,
|
||||
"access" = P.access,
|
||||
"can_private_buy" = P.can_private_buy
|
||||
))
|
||||
@@ -215,8 +218,22 @@
|
||||
if(isnull(reason) || ..())
|
||||
return
|
||||
|
||||
if(pack.goody == PACK_GOODY_PRIVATE && !self_paid)
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE)
|
||||
say("ERROR: Private small crates may only be purchased by private accounts.")
|
||||
return
|
||||
|
||||
var/obj/item/coupon/applied_coupon
|
||||
for(var/i in loaded_coupons)
|
||||
var/obj/item/coupon/coupon_check = i
|
||||
if(pack.type == coupon_check.discounted_pack)
|
||||
say("Coupon found! [round(coupon_check.discount_pct_off * 100)]% off applied!")
|
||||
coupon_check.moveToNullspace()
|
||||
applied_coupon = coupon_check
|
||||
break
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
var/datum/supply_order/SO = new(pack, name, rank, ckey, reason, account)
|
||||
var/datum/supply_order/SO = new(pack, name, rank, ckey, reason, account, applied_coupon)
|
||||
SO.generateRequisition(T)
|
||||
if(requestonly && !self_paid)
|
||||
SSshuttle.requestlist += SO
|
||||
@@ -229,6 +246,9 @@
|
||||
var/id = text2num(params["id"])
|
||||
for(var/datum/supply_order/SO in SSshuttle.shoppinglist)
|
||||
if(SO.id == id)
|
||||
if(SO.applied_coupon)
|
||||
say("Coupon refunded.")
|
||||
SO.applied_coupon.forceMove(get_turf(src))
|
||||
SSshuttle.shoppinglist -= SO
|
||||
. = TRUE
|
||||
break
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
|
||||
#define COUPON_OMEN "omen"
|
||||
|
||||
/obj/item/coupon
|
||||
name = "coupon"
|
||||
desc = "It doesn't matter if you didn't want it before, what matters now is that you've got a coupon for it!"
|
||||
icon_state = "data_1"
|
||||
icon = 'icons/obj/card.dmi'
|
||||
item_flags = NOBLUDGEON
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
var/datum/supply_pack/discounted_pack
|
||||
var/discount_pct_off = 0.05
|
||||
var/obj/machinery/computer/cargo/inserted_console
|
||||
|
||||
/// Choose what our prize is :D
|
||||
/obj/item/coupon/proc/generate()
|
||||
discounted_pack = pick(subtypesof(/datum/supply_pack/goody))
|
||||
var/list/chances = list("0.10" = 4, "0.15" = 8, "0.20" = 10, "0.25" = 8, "0.50" = 4, COUPON_OMEN = 1)
|
||||
discount_pct_off = pickweight(chances)
|
||||
if(discount_pct_off == COUPON_OMEN)
|
||||
name = "coupon - fuck you"
|
||||
desc = "The small text reads, 'You will be slaughtered'... That doesn't sound right, does it?"
|
||||
if(ismob(loc))
|
||||
var/mob/M = loc
|
||||
to_chat(M, "<span class='warning'>The coupon reads '<b>fuck you</b>' in large, bold text... is- is that a prize, or?</span>")
|
||||
M.AddComponent(/datum/component/omen, TRUE, src)
|
||||
else
|
||||
discount_pct_off = text2num(discount_pct_off)
|
||||
name = "coupon - [round(discount_pct_off * 100)]% off [initial(discounted_pack.name)]"
|
||||
|
||||
/obj/item/coupon/attack_obj(obj/O, mob/living/user)
|
||||
if(!istype(O, /obj/machinery/computer/cargo))
|
||||
return ..()
|
||||
if(discount_pct_off == COUPON_OMEN)
|
||||
to_chat(user, "<span class='warning'>\The [O] validates the coupon as authentic, but refuses to accept it...</span>")
|
||||
O.say("Coupon fulfillment already in progress...")
|
||||
return
|
||||
|
||||
inserted_console = O
|
||||
LAZYADD(inserted_console.loaded_coupons, src)
|
||||
inserted_console.say("Coupon for [initial(discounted_pack.name)] applied!")
|
||||
forceMove(inserted_console)
|
||||
|
||||
/obj/item/coupon/Destroy()
|
||||
if(inserted_console)
|
||||
LAZYREMOVE(inserted_console.loaded_coupons, src)
|
||||
inserted_console = null
|
||||
. = ..()
|
||||
|
||||
#undef COUPON_OMEN
|
||||
+42
-33
@@ -27,10 +27,12 @@
|
||||
var/orderer_rank
|
||||
var/orderer_ckey
|
||||
var/reason
|
||||
var/discounted_pct
|
||||
var/datum/supply_pack/pack
|
||||
var/datum/bank_account/paying_account
|
||||
var/obj/item/coupon/applied_coupon
|
||||
|
||||
/datum/supply_order/New(datum/supply_pack/pack, orderer, orderer_rank, orderer_ckey, reason, paying_account)
|
||||
/datum/supply_order/New(datum/supply_pack/pack, orderer, orderer_rank, orderer_ckey, reason, paying_account, coupon)
|
||||
id = SSshuttle.ordernum++
|
||||
src.pack = pack
|
||||
src.orderer = orderer
|
||||
@@ -38,6 +40,7 @@
|
||||
src.orderer_ckey = orderer_ckey
|
||||
src.reason = reason
|
||||
src.paying_account = paying_account
|
||||
src.applied_coupon = coupon
|
||||
|
||||
/datum/supply_order/proc/generateRequisition(turf/T)
|
||||
var/obj/item/paper/P = new(T)
|
||||
@@ -57,58 +60,64 @@
|
||||
P.update_icon()
|
||||
return P
|
||||
|
||||
/datum/supply_order/proc/generateManifest(obj/structure/closet/crate/C)
|
||||
var/obj/item/paper/fluff/jobs/cargo/manifest/P = new(C, id, pack.cost)
|
||||
/datum/supply_order/proc/generateManifest(obj/container, owner, packname) //generates-the-manifests.
|
||||
var/obj/item/paper/fluff/jobs/cargo/manifest/P = new(container, id, 0)
|
||||
|
||||
var/station_name = (P.errors & MANIFEST_ERROR_NAME) ? new_station_name() : station_name()
|
||||
|
||||
P.name = "shipping manifest - #[id] ([pack.name])"
|
||||
P.name = "shipping manifest - [packname?"#[id] ([pack.name])":"(Grouped Item Crate)"]"
|
||||
P.info += "<h2>[command_name()] Shipping Manifest</h2>"
|
||||
P.info += "<hr/>"
|
||||
if(paying_account)
|
||||
P.info += "Direct purchase from [paying_account.account_holder]<br/>"
|
||||
P.name += " - Purchased by [paying_account.account_holder]"
|
||||
if(id && !(id == "Cargo"))
|
||||
P.info += "Direct purchase from [owner]<br/>"
|
||||
P.name += " - Purchased by [owner]"
|
||||
P.info += "Order #[id]<br/>"
|
||||
P.info += "Destination: [station_name]<br/>"
|
||||
P.info += "Item: [pack.name]<br/>"
|
||||
if(packname)
|
||||
P.info += "Item: [packname]<br/>"
|
||||
P.info += "Contents: <br/>"
|
||||
P.info += "<ul>"
|
||||
for(var/atom/movable/AM in C.contents - P - C.lockerelectronics)
|
||||
var/list/ignore_this = list(P)
|
||||
if(istype(container, /obj/structure/closet))
|
||||
var/obj/structure/closet/C = container
|
||||
ignore_this += C.lockerelectronics
|
||||
for(var/atom/movable/AM in container.contents - ignore_this)
|
||||
if((P.errors & MANIFEST_ERROR_CONTENTS) && prob(50))
|
||||
continue
|
||||
P.info += "<li>[AM.name]</li>"
|
||||
P.info += "</ul>"
|
||||
P.info += "<h4>Stamp below to confirm receipt of goods:</h4>"
|
||||
|
||||
if(P.errors & MANIFEST_ERROR_ITEM)
|
||||
var/static/list/blacklisted_error = typecacheof(list(
|
||||
/obj/structure/closet/crate/secure,
|
||||
/obj/structure/closet/crate/large,
|
||||
/obj/structure/closet/secure_closet/goodies
|
||||
))
|
||||
if(blacklisted_error[container.type])
|
||||
P.errors &= ~MANIFEST_ERROR_ITEM
|
||||
else
|
||||
var/lost = max(round(container.contents.len / 10), 1)
|
||||
while(--lost >= 0)
|
||||
qdel(pick(container.contents))
|
||||
|
||||
P.update_icon()
|
||||
P.forceMove(C)
|
||||
C.manifest = P
|
||||
C.update_icon()
|
||||
P.forceMove(container)
|
||||
|
||||
if(istype(container, /obj/structure/closet/crate))
|
||||
var/obj/structure/closet/crate/C = container
|
||||
C.manifest = P
|
||||
C.update_icon()
|
||||
|
||||
return P
|
||||
|
||||
/datum/supply_order/proc/generate(atom/A)
|
||||
var/obj/structure/closet/crate/C = pack.generate(A, paying_account)
|
||||
var/obj/item/paper/fluff/jobs/cargo/manifest/M = generateManifest(C)
|
||||
|
||||
if(M.errors & MANIFEST_ERROR_ITEM)
|
||||
if(istype(C, /obj/structure/closet/crate/secure) || istype(C, /obj/structure/closet/crate/large))
|
||||
M.errors &= ~MANIFEST_ERROR_ITEM
|
||||
else
|
||||
var/lost = max(round(C.contents.len / 10), 1)
|
||||
while(--lost >= 0)
|
||||
qdel(pick(C.contents))
|
||||
generateManifest(C, paying_account, pack)
|
||||
return C
|
||||
|
||||
//Paperwork for NT
|
||||
/obj/item/folder/paperwork
|
||||
name = "Incomplete Paperwork"
|
||||
desc = "These should've been filled out four months ago! Unfinished grant papers issued by Nanotrasen's finance department. Complete this page for additional funding."
|
||||
icon = 'icons/obj/bureaucracy.dmi'
|
||||
icon_state = "docs_generic"
|
||||
|
||||
/obj/item/folder/paperwork_correct
|
||||
name = "Finished Paperwork"
|
||||
desc = "A neat stack of filled-out forms, in triplicate and signed. Is there anything more satisfying? Make sure they get stamped."
|
||||
icon = 'icons/obj/bureaucracy.dmi'
|
||||
icon_state = "docs_verified"
|
||||
/datum/supply_order/proc/generateCombo(var/miscbox, var/misc_own, var/misc_contents)
|
||||
for (var/I in misc_contents)
|
||||
new I(miscbox)
|
||||
generateManifest(miscbox, misc_own, "")
|
||||
return
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
var/special_enabled = FALSE
|
||||
var/DropPodOnly = FALSE //only usable by the Bluespace Drop Pod via the express cargo console
|
||||
var/admin_spawned = FALSE //Can only an admin spawn this crate?
|
||||
var/goody = PACK_GOODY_NONE //Small items can be grouped into a single crate.They also come in a closet/lockbox instead of a full crate, so the 700 min doesn't apply
|
||||
var/can_private_buy = TRUE //Can it be purchased privately by each crewmember?
|
||||
|
||||
/datum/supply_pack/proc/generate(atom/A, datum/bank_account/paying_account)
|
||||
|
||||
@@ -37,15 +37,6 @@
|
||||
contains = list(/obj/item/storage/box/chemimp)
|
||||
crate_name = "chemical implant crate"
|
||||
|
||||
/datum/supply_pack/security/armory/combatknives
|
||||
name = "Combat Knives Crate"
|
||||
desc = "Contains three sharpened combat knives. Each knife guaranteed to fit snugly inside any Nanotrasen-standard boot. Requires Armory access to open."
|
||||
cost = 3200
|
||||
contains = list(/obj/item/kitchen/knife/combat,
|
||||
/obj/item/kitchen/knife/combat,
|
||||
/obj/item/kitchen/knife/combat)
|
||||
crate_name = "combat knife crate"
|
||||
|
||||
/datum/supply_pack/security/armory/ballistic
|
||||
name = "Combat Shotguns Crate"
|
||||
desc = "For when the enemy absolutely needs to be replaced with lead. Contains three Aussec-designed Combat Shotguns, with three Shotgun Bandoliers, as well as seven buchshot and 12g shotgun slugs. Requires Armory access to open."
|
||||
|
||||
@@ -90,16 +90,6 @@
|
||||
crate_name = "industrial rcd"
|
||||
crate_type = /obj/structure/closet/crate/secure/engineering
|
||||
|
||||
/datum/supply_pack/engineering/powergamermitts
|
||||
name = "Insulated Gloves Crate"
|
||||
desc = "The backbone of modern society. Barely ever ordered for actual engineering. Contains three insulated gloves."
|
||||
cost = 2300 //Made of pure-grade bullshittinium
|
||||
contains = list(/obj/item/clothing/gloves/color/yellow,
|
||||
/obj/item/clothing/gloves/color/yellow,
|
||||
/obj/item/clothing/gloves/color/yellow)
|
||||
crate_name = "insulated gloves crate"
|
||||
crate_type = /obj/structure/closet/crate/engineering/electrical
|
||||
|
||||
/datum/supply_pack/engineering/inducers
|
||||
name = "NT-75 Electromagnetic Power Inducers Crate"
|
||||
desc = "No rechargers? No problem, with the NT-75 EPI, you can recharge any standard cell-based equipment anytime, anywhere. Contains two Inducers."
|
||||
@@ -162,6 +152,7 @@
|
||||
/obj/item/storage/toolbox/mechanical)
|
||||
cost = 1200
|
||||
crate_name = "toolbox crate"
|
||||
special = TRUE //Department resupply shuttle loan event.
|
||||
|
||||
/datum/supply_pack/engineering/bsa
|
||||
name = "Bluespace Artillery Parts"
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
|
||||
/datum/supply_pack/goody
|
||||
access = NONE
|
||||
group = "Goodies"
|
||||
goody = PACK_GOODY_PRIVATE
|
||||
|
||||
/datum/supply_pack/goody/combatknives_single
|
||||
name = "Combat Knife Single-Pack"
|
||||
desc = "Contains one sharpened combat knive. Guaranteed to fit snugly inside any Nanotrasen-standard boot."
|
||||
cost = 800
|
||||
contains = list(/obj/item/kitchen/knife/combat)
|
||||
|
||||
/datum/supply_pack/goody/sologamermitts
|
||||
name = "Insulated Gloves Single-Pack"
|
||||
desc = "The backbone of modern society. Barely ever ordered for actual engineering."
|
||||
cost = 800
|
||||
contains = list(/obj/item/clothing/gloves/color/yellow)
|
||||
|
||||
/datum/supply_pack/goody/firstaidbruises_single
|
||||
name = "Bruise Treatment Kit Single-Pack"
|
||||
desc = "A single brute first-aid kit, perfect for recovering from being crushed in an airlock. Did you know people get crushed in airlocks all the time? Interesting..."
|
||||
cost = 330
|
||||
contains = list(/obj/item/storage/firstaid/brute)
|
||||
|
||||
/datum/supply_pack/goody/firstaidburns_single
|
||||
name = "Burn Treatment Kit Single-Pack"
|
||||
desc = "A single burn first-aid kit. The advertisement displays a winking atmospheric technician giving a thumbs up, saying \"Mistakes happen!\""
|
||||
cost = 330
|
||||
contains = list(/obj/item/storage/firstaid/fire)
|
||||
|
||||
/datum/supply_pack/goody/firstaid_single
|
||||
name = "First Aid Kit Single-Pack"
|
||||
desc = "A single first-aid kit, fit for healing most types of bodily harm."
|
||||
cost = 250
|
||||
contains = list(/obj/item/storage/firstaid/regular)
|
||||
|
||||
/datum/supply_pack/goody/firstaidoxygen_single
|
||||
name = "Oxygen Deprivation Kit Single-Pack"
|
||||
desc = "A single oxygen deprivation first-aid kit, marketed heavily to those with crippling fears of asphyxiation."
|
||||
cost = 330
|
||||
contains = list(/obj/item/storage/firstaid/o2)
|
||||
|
||||
/datum/supply_pack/goody/firstaidtoxins_single
|
||||
name = "Toxin Treatment Kit Single-Pack"
|
||||
desc = "A single first aid kit focused on healing damage dealt by heavy toxins."
|
||||
cost = 330
|
||||
contains = list(/obj/item/storage/firstaid/toxin)
|
||||
|
||||
/datum/supply_pack/goody/toolbox // mostly just to water down coupon probability
|
||||
name = "Mechanical Toolbox"
|
||||
desc = "A fully stocked mechanical toolbox, for when you're too lazy to just print them out."
|
||||
cost = 300
|
||||
contains = list(/obj/item/storage/toolbox/mechanical)
|
||||
|
||||
/datum/supply_pack/goody/electrical_toolbox // mostly just to water down coupon probability
|
||||
name = "Mechanical Toolbox"
|
||||
desc = "A fully stocked electrical toolbox, for when you're too lazy to just print them out."
|
||||
cost = 300
|
||||
contains = list(/obj/item/storage/toolbox/electrical)
|
||||
|
||||
/datum/supply_pack/goody/valentine
|
||||
name = "Valentine Card"
|
||||
desc = "Make an impression on that special someone! Comes with one valentine card and a free candy heart!"
|
||||
cost = 150
|
||||
contains = list(/obj/item/valentine, /obj/item/reagent_containers/food/snacks/candyheart)
|
||||
|
||||
/datum/supply_pack/goody/beeplush
|
||||
name = "Bee Plushie"
|
||||
desc = "The most important thing you could possibly spend your hard-earned money on."
|
||||
cost = 1500
|
||||
contains = list(/obj/item/toy/plush/beeplushie)
|
||||
|
||||
/datum/supply_pack/goody/beach_ball
|
||||
name = "Beach Ball"
|
||||
desc = "The simple beach ball is one of Nanotrasen's most popular products. 'Why do we make beach balls? Because we can! (TM)' - Nanotrasen"
|
||||
cost = 200
|
||||
contains = list(/obj/item/toy/beach_ball)
|
||||
@@ -14,53 +14,60 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/datum/supply_pack/materials/cardboard50
|
||||
goody = PACK_GOODY_PUBLIC
|
||||
name = "50 Cardboard Sheets"
|
||||
desc = "Create a bunch of boxes."
|
||||
cost = 1000
|
||||
cost = 300 //thrice their export value
|
||||
contains = list(/obj/item/stack/sheet/cardboard/fifty)
|
||||
crate_name = "cardboard sheets crate"
|
||||
|
||||
/datum/supply_pack/materials/glass50
|
||||
goody = PACK_GOODY_PUBLIC
|
||||
name = "50 Glass Sheets"
|
||||
desc = "Let some nice light in with fifty glass sheets!"
|
||||
cost = 850
|
||||
cost = 300 //double their export value
|
||||
contains = list(/obj/item/stack/sheet/glass/fifty)
|
||||
crate_name = "glass sheets crate"
|
||||
|
||||
/datum/supply_pack/materials/metal50
|
||||
goody = PACK_GOODY_PUBLIC
|
||||
name = "50 Metal Sheets"
|
||||
desc = "Any construction project begins with a good stack of fifty metal sheets!"
|
||||
cost = 850
|
||||
cost = 300 //double their export value
|
||||
contains = list(/obj/item/stack/sheet/metal/fifty)
|
||||
crate_name = "metal sheets crate"
|
||||
|
||||
/datum/supply_pack/materials/plasteel20
|
||||
goody = PACK_GOODY_PUBLIC
|
||||
name = "20 Plasteel Sheets"
|
||||
desc = "Reinforce the station's integrity with twenty plasteel sheets!"
|
||||
cost = 4700
|
||||
cost = 4000
|
||||
contains = list(/obj/item/stack/sheet/plasteel/twenty)
|
||||
crate_name = "plasteel sheets crate"
|
||||
|
||||
/datum/supply_pack/materials/plasteel50
|
||||
name = "50 Plasteel Sheets"
|
||||
desc = "For when you REALLY have to reinforce something."
|
||||
cost = 9050
|
||||
contains = list(/obj/item/stack/sheet/plasteel/fifty)
|
||||
crate_name = "plasteel sheets crate"
|
||||
|
||||
/datum/supply_pack/materials/plastic50
|
||||
goody = PACK_GOODY_PUBLIC
|
||||
name = "50 Plastic Sheets"
|
||||
desc = "Build a limitless amount of toys with fifty plastic sheets!"
|
||||
cost = 950
|
||||
contains = list(/obj/item/stack/sheet/plastic/fifty)
|
||||
crate_name = "plastic sheets crate"
|
||||
cost = 200 // double their export
|
||||
contains = list(/obj/item/stack/sheet/plastic/twenty)
|
||||
|
||||
/datum/supply_pack/materials/sandstone30
|
||||
goody = PACK_GOODY_PUBLIC
|
||||
name = "30 Sandstone Blocks"
|
||||
desc = "Neither sandy nor stoney, these thirty blocks will still get the job done."
|
||||
cost = 800
|
||||
cost = 150 // five times their export
|
||||
contains = list(/obj/item/stack/sheet/mineral/sandstone/thirty)
|
||||
crate_name = "sandstone blocks crate"
|
||||
|
||||
/datum/supply_pack/materials/wood50
|
||||
goody = PACK_GOODY_PUBLIC
|
||||
name = "50 Wood Planks"
|
||||
desc = "Turn cargo's boring metal groundwork into beautiful panelled flooring and much more with fifty wooden planks!"
|
||||
cost = 400 // 6-7 planks shy from having equal import/export prices
|
||||
contains = list(/obj/item/stack/sheet/mineral/wood/twenty)
|
||||
|
||||
/datum/supply_pack/materials/rcdammo
|
||||
goody = PACK_GOODY_PUBLIC
|
||||
name = "Large RCD ammo Single-Pack"
|
||||
desc = "A single large compressed RCD matter pack, to help with any holes or projects people might be working on."
|
||||
cost = 600
|
||||
contains = list(/obj/item/rcd_ammo/large)
|
||||
|
||||
/datum/supply_pack/materials/rawlumber
|
||||
name = "50 Towercap Logs"
|
||||
@@ -74,35 +81,6 @@
|
||||
for(var/i in 1 to 49)
|
||||
new /obj/item/grown/log(.)
|
||||
|
||||
/datum/supply_pack/materials/wood50
|
||||
name = "50 Wood Planks"
|
||||
desc = "Turn cargo's boring metal groundwork into beautiful panelled flooring and much more with fifty wooden planks!"
|
||||
cost = 1450
|
||||
contains = list(/obj/item/stack/sheet/mineral/wood/fifty)
|
||||
crate_name = "wood planks crate"
|
||||
|
||||
/datum/supply_pack/materials/rcdammo
|
||||
name = "Spare RCD ammo"
|
||||
desc = "This crate contains sixteen RCD compressed matter packs, to help with any holes or projects people might be working on."
|
||||
cost = 3750
|
||||
contains = list(/obj/item/rcd_ammo,
|
||||
/obj/item/rcd_ammo,
|
||||
/obj/item/rcd_ammo,
|
||||
/obj/item/rcd_ammo,
|
||||
/obj/item/rcd_ammo,
|
||||
/obj/item/rcd_ammo,
|
||||
/obj/item/rcd_ammo,
|
||||
/obj/item/rcd_ammo,
|
||||
/obj/item/rcd_ammo,
|
||||
/obj/item/rcd_ammo,
|
||||
/obj/item/rcd_ammo,
|
||||
/obj/item/rcd_ammo,
|
||||
/obj/item/rcd_ammo,
|
||||
/obj/item/rcd_ammo,
|
||||
/obj/item/rcd_ammo,
|
||||
/obj/item/rcd_ammo)
|
||||
crate_name = "rcd ammo"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////// Canisters //////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -141,34 +141,6 @@
|
||||
///////////////////////////// Medical Kits ///////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/datum/supply_pack/medical/firstaidbruises
|
||||
name = "Bruise Treatment Kit Crate"
|
||||
desc = "Contains three first aid kits focused on healing bruises and broken bones."
|
||||
cost = 1000
|
||||
contains = list(/obj/item/storage/firstaid/brute,
|
||||
/obj/item/storage/firstaid/brute,
|
||||
/obj/item/storage/firstaid/brute)
|
||||
crate_name = "brute treatment kit crate"
|
||||
|
||||
/datum/supply_pack/medical/firstaidburns
|
||||
name = "Burn Treatment Kit Crate"
|
||||
desc = "Contains three first aid kits focused on healing severe burns."
|
||||
cost = 1000
|
||||
contains = list(/obj/item/storage/firstaid/fire,
|
||||
/obj/item/storage/firstaid/fire,
|
||||
/obj/item/storage/firstaid/fire)
|
||||
crate_name = "burn treatment kit crate"
|
||||
|
||||
/datum/supply_pack/medical/firstaid
|
||||
name = "First Aid Kit Crate"
|
||||
desc = "Contains four first aid kits for healing most types of wounds."
|
||||
cost = 1000
|
||||
contains = list(/obj/item/storage/firstaid/regular,
|
||||
/obj/item/storage/firstaid/regular,
|
||||
/obj/item/storage/firstaid/regular,
|
||||
/obj/item/storage/firstaid/regular)
|
||||
crate_name = "first aid kit crate"
|
||||
|
||||
/datum/supply_pack/medical/sprays
|
||||
name = "Medical Sprays"
|
||||
desc = "Contains two cans of Styptic Spray, Silver Sulfadiazine Spray, Synthflesh Spray and Sterilizer Compound Spray."
|
||||
@@ -183,35 +155,6 @@
|
||||
/obj/item/reagent_containers/medspray/sterilizine)
|
||||
crate_name = "medical supplies crate"
|
||||
|
||||
/datum/supply_pack/medical/firstaidmixed
|
||||
name = "Mixed Medical Kits"
|
||||
desc = "Contains one of each medical kits for dealing with a variety of injured crewmembers."
|
||||
cost = 1250
|
||||
contains = list(/obj/item/storage/firstaid/toxin,
|
||||
/obj/item/storage/firstaid/o2,
|
||||
/obj/item/storage/firstaid/brute,
|
||||
/obj/item/storage/firstaid/fire,
|
||||
/obj/item/storage/firstaid/regular)
|
||||
crate_name = "medical supplies crate"
|
||||
|
||||
/datum/supply_pack/medical/firstaidoxygen
|
||||
name = "Oxygen Deprivation Kit Crate"
|
||||
desc = "Contains three first aid kits focused on helping oxygen deprivation victims."
|
||||
cost = 1000
|
||||
contains = list(/obj/item/storage/firstaid/o2,
|
||||
/obj/item/storage/firstaid/o2,
|
||||
/obj/item/storage/firstaid/o2)
|
||||
crate_name = "oxygen deprivation kit crate"
|
||||
|
||||
/datum/supply_pack/medical/firstaidtoxins
|
||||
name = "Toxin Treatment Kit Crate"
|
||||
desc = "Contains three first aid kits focused on healing damage dealt by heavy toxins."
|
||||
cost = 1000
|
||||
contains = list(/obj/item/storage/firstaid/toxin,
|
||||
/obj/item/storage/firstaid/toxin,
|
||||
/obj/item/storage/firstaid/toxin)
|
||||
crate_name = "toxin treatment kit crate"
|
||||
|
||||
/datum/supply_pack/medical/advrad
|
||||
name = "Radiation Treatment Crate Deluxe"
|
||||
desc = "A crate for when radiation is out of hand... Contains two rad-b-gone kits, one bottle of anti radiation deluxe pills, as well as a radiation treatment deluxe pill bottle!"
|
||||
|
||||
@@ -333,45 +333,58 @@
|
||||
//////////////////////////// Misc + Decor ////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/datum/supply_pack/misc/carpet_exotic
|
||||
name = "Exotic Carpet Crate"
|
||||
desc = "Exotic carpets straight from Space Russia, for all your decorating needs. Contains 100 tiles each of 10 different flooring patterns."
|
||||
cost = 7000
|
||||
contains = list(/obj/item/stack/tile/carpet/blue/fifty,
|
||||
/obj/item/stack/tile/carpet/blue/fifty,
|
||||
/obj/item/stack/tile/carpet/cyan/fifty,
|
||||
/obj/item/stack/tile/carpet/cyan/fifty,
|
||||
/obj/item/stack/tile/carpet/green/fifty,
|
||||
/obj/item/stack/tile/carpet/green/fifty,
|
||||
/obj/item/stack/tile/carpet/orange/fifty,
|
||||
/obj/item/stack/tile/carpet/orange/fifty,
|
||||
/obj/item/stack/tile/carpet/purple/fifty,
|
||||
/obj/item/stack/tile/carpet/purple/fifty,
|
||||
/obj/item/stack/tile/carpet/red/fifty,
|
||||
/obj/item/stack/tile/carpet/red/fifty,
|
||||
/obj/item/stack/tile/carpet/royalblue/fifty,
|
||||
/obj/item/stack/tile/carpet/royalblue/fifty,
|
||||
/obj/item/stack/tile/carpet/royalblack/fifty,
|
||||
/obj/item/stack/tile/carpet/royalblack/fifty,
|
||||
/obj/item/stack/tile/carpet/blackred/fifty,
|
||||
/obj/item/stack/tile/carpet/blackred/fifty,
|
||||
/obj/item/stack/tile/carpet/monochrome/fifty,
|
||||
/obj/item/stack/tile/carpet/monochrome/fifty)
|
||||
crate_name = "exotic carpet crate"
|
||||
|
||||
/datum/supply_pack/misc/carpet
|
||||
name = "Premium Carpet Crate"
|
||||
desc = "Plasteel floor tiles getting on your nerves? These stacks of extra soft carpet will tie any room together. Contains some classic carpet, along with black, red, and monochrome varients."
|
||||
cost = 1350
|
||||
contains = list(/obj/item/stack/tile/carpet/fifty,
|
||||
/obj/item/stack/tile/carpet/fifty,
|
||||
/obj/item/stack/tile/carpet/black/fifty,
|
||||
/obj/item/stack/tile/carpet/black/fifty,
|
||||
/obj/item/stack/tile/carpet/blackred/fifty,
|
||||
/obj/item/stack/tile/carpet/blackred/fifty,
|
||||
/obj/item/stack/tile/carpet/monochrome/fifty,
|
||||
/obj/item/stack/tile/carpet/monochrome/fifty)
|
||||
crate_name = "premium carpet crate"
|
||||
goody = PACK_GOODY_PUBLIC
|
||||
name = "Classic Carpet Single-Pack"
|
||||
desc = "Plasteel floor tiles getting on your nerves? This 50 units stack of extra soft carpet will tie any room together."
|
||||
cost = 200
|
||||
contains = list(/obj/item/stack/tile/carpet/fifty)
|
||||
|
||||
/datum/supply_pack/misc/carpet/black
|
||||
name = "Black Carpet Single-Pack"
|
||||
contains = list(/obj/item/stack/tile/carpet/black/fifty)
|
||||
|
||||
/datum/supply_pack/misc/carpet/premium
|
||||
name = "Monochrome Carpet Single-Pack"
|
||||
desc = "Exotic carpets for all your decorating needs. This 30 units stack of extra soft carpet will tie any room together."
|
||||
cost = 250
|
||||
contains = list(/obj/item/stack/tile/carpet/monochrome/thirty)
|
||||
|
||||
/datum/supply_pack/misc/carpet/premium/blackred
|
||||
name = "Black-Red Carpet Single-Pack"
|
||||
contains = list(/obj/item/stack/tile/carpet/blackred/thirty)
|
||||
|
||||
/datum/supply_pack/misc/carpet/premium/royalblack
|
||||
name = "Royal Black Carpet Single-Pack"
|
||||
contains = list(/obj/item/stack/tile/carpet/royalblack/thirty)
|
||||
|
||||
/datum/supply_pack/misc/carpet/premium/royalblue
|
||||
name = "Royal Blue Carpet Single-Pack"
|
||||
contains = list(/obj/item/stack/tile/carpet/royalblue/thirty)
|
||||
|
||||
/datum/supply_pack/misc/carpet/premium/red
|
||||
name = "Red Carpet Single-Pack"
|
||||
contains = list(/obj/item/stack/tile/carpet/red/thirty)
|
||||
|
||||
/datum/supply_pack/misc/carpet/premium/purple
|
||||
name = "Purple Carpet Single-Pack"
|
||||
contains = list(/obj/item/stack/tile/carpet/purple/thirty)
|
||||
|
||||
/datum/supply_pack/misc/carpet/premium/orange
|
||||
name = "Orange Carpet Single-Pack"
|
||||
contains = list(/obj/item/stack/tile/carpet/orange/thirty)
|
||||
|
||||
/datum/supply_pack/misc/carpet/premium/green
|
||||
name = "Green Carpet Single-Pack"
|
||||
contains = list(/obj/item/stack/tile/carpet/green/thirty)
|
||||
|
||||
/datum/supply_pack/misc/carpet/premium/cyan
|
||||
name = "Cyan Carpet Single-Pack"
|
||||
contains = list(/obj/item/stack/tile/carpet/cyan/thirty)
|
||||
|
||||
/datum/supply_pack/misc/carpet/premium/blue
|
||||
name = "Blue Carpet Single-Pack"
|
||||
contains = list(/obj/item/stack/tile/carpet/blue/thirty)
|
||||
|
||||
/datum/supply_pack/misc/noslipfloor
|
||||
name = "High-traction Floor Tiles"
|
||||
@@ -417,3 +430,40 @@
|
||||
crate_type = /obj/structure/closet/crate
|
||||
|
||||
|
||||
///Special supply crate that generates random syndicate gear up to a determined TC value
|
||||
|
||||
/datum/supply_pack/misc/syndicate
|
||||
|
||||
name = "Assorted Syndicate Gear"
|
||||
|
||||
desc = "Contains a random assortment of syndicate gear."
|
||||
|
||||
special = TRUE ///Cannot be ordered via cargo
|
||||
|
||||
contains = list()
|
||||
|
||||
crate_name = "syndicate gear crate"
|
||||
|
||||
crate_type = /obj/structure/closet/crate
|
||||
|
||||
var/crate_value = 30 ///Total TC worth of contained uplink items
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////// Syndicate Packs /////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//Generate assorted uplink items, taking into account the same surplus modifiers used for surplus crates
|
||||
//(this is exclusively used for the rare variant of the stray cargo event!)
|
||||
/datum/supply_pack/misc/syndicate/fill(obj/structure/closet/crate/C)
|
||||
var/list/uplink_items = get_uplink_items(SSticker.mode)
|
||||
while(crate_value)
|
||||
var/category = pick(uplink_items)
|
||||
var/item = pick(uplink_items[category])
|
||||
var/datum/uplink_item/I = uplink_items[category][item]
|
||||
if(!I.surplus || prob(100 - I.surplus))
|
||||
continue
|
||||
if(crate_value < I.cost)
|
||||
continue
|
||||
crate_value -= I.cost
|
||||
new I.item(C)
|
||||
@@ -228,3 +228,35 @@
|
||||
access = ACCESS_ARMORY
|
||||
crate_name = "sporting crate"
|
||||
crate_type = /obj/structure/closet/crate/secure // Would have liked a wooden crate but access >:(
|
||||
|
||||
/datum/supply_pack/security/dumdum
|
||||
name = ".38 DumDum Speedloader"
|
||||
desc = "Contains one speedloader of .38 DumDum ammunition, good for embedding in soft targets. Requires Security or Forensics access to open."
|
||||
cost = 1200
|
||||
access = FALSE
|
||||
access_any = list(ACCESS_SECURITY, ACCESS_FORENSICS_LOCKERS)
|
||||
contains = list(/obj/item/ammo_box/c38/dumdum)
|
||||
crate_name = ".38 match crate"
|
||||
|
||||
/datum/supply_pack/security/match
|
||||
name = ".38 Match Grade Speedloader"
|
||||
desc = "Contains one speedloader of match grade .38 ammunition, perfect for showing off trickshots. Requires Security or Forensics access to open."
|
||||
cost = 1200
|
||||
access = FALSE
|
||||
access_any = list(ACCESS_SECURITY, ACCESS_FORENSICS_LOCKERS)
|
||||
contains = list(/obj/item/ammo_box/c38/match)
|
||||
crate_name = ".38 match crate"
|
||||
|
||||
/datum/supply_pack/security/stingpack
|
||||
name = "Stingbang Grenade Pack"
|
||||
desc = "Contains five \"stingbang\" grenades, perfect for stopping riots and playing morally unthinkable pranks. Requires Security access to open."
|
||||
cost = 2500
|
||||
contains = list(/obj/item/storage/box/stingbangs)
|
||||
crate_name = "stingbang grenade pack crate"
|
||||
|
||||
/datum/supply_pack/security/stingpack/single
|
||||
name = "Stingbang Single-Pack"
|
||||
desc = "Contains one \"stingbang\" grenade, perfect for playing meanhearted pranks. Requires Security access to open."
|
||||
cost = 1400
|
||||
contains = list(/obj/item/grenade/stingbang)
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
topiclimiter[ADMINSWARNED_AT] = minute
|
||||
msg += " Administrators have been informed."
|
||||
log_game("[key_name(src)] Has hit the per-minute topic limit of [mtl] topic calls in a given game minute")
|
||||
message_admins("[ADMIN_LOOKUPFLW(src)] [ADMIN_KICK(usr)] Has hit the per-minute topic limit of [mtl] topic calls in a given game minute")
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] [ADMIN_KICK(usr)] Has hit the per-minute topic limit of [mtl] topic calls in a given game minute")
|
||||
to_chat(src, "<span class='danger'>[msg]</span>")
|
||||
return
|
||||
|
||||
@@ -860,8 +860,14 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
|
||||
'html/browser/playeroptions.css',
|
||||
)
|
||||
spawn (10) //removing this spawn causes all clients to not get verbs.
|
||||
|
||||
//load info on what assets the client has
|
||||
src << browse('code/modules/asset_cache/validate_assets.html', "window=asset_cache_browser")
|
||||
|
||||
//Precache the client with all other assets slowly, so as to not block other browse() calls
|
||||
getFilesSlow(src, SSassets.preload, register_asset = FALSE)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, /proc/getFilesSlow, src, SSassets.preload, FALSE), 5 SECONDS)
|
||||
|
||||
#if (PRELOAD_RSC == 0)
|
||||
for (var/name in GLOB.vox_sounds)
|
||||
var/file = GLOB.vox_sounds[name]
|
||||
|
||||
@@ -6,5 +6,7 @@
|
||||
if(!CONFIG_GET(flag/minimaps_enabled))
|
||||
to_chat(usr, "<span class='boldwarning'>Minimap generation is not enabled in the server's configuration.</span>")
|
||||
return
|
||||
|
||||
if(!SSminimaps.station_minimap)
|
||||
to_chat(usr, "<span class='boldwarning'>Minimap generation is in progress, please wait!</span>")
|
||||
return
|
||||
SSminimaps.station_minimap.show(src)
|
||||
|
||||
@@ -203,6 +203,12 @@
|
||||
icon_state = "hipster_glasses"
|
||||
item_state = "hipster_glasses"
|
||||
|
||||
/obj/item/clothing/glasses/regular/circle
|
||||
name = "circle glasses"
|
||||
desc = "Why would you wear something so controversial yet so brave?"
|
||||
icon_state = "circle_glasses"
|
||||
item_state = "circle_glasses"
|
||||
|
||||
//Here lies green glasses, so ugly they died. RIP
|
||||
|
||||
/obj/item/clothing/glasses/sunglasses
|
||||
|
||||
@@ -74,6 +74,10 @@
|
||||
icon_state = "beaniedurathread"
|
||||
armor = list("melee" = 25, "bullet" = 10, "laser" = 20,"energy" = 10, "bomb" = 30, "bio" = 15, "rad" = 20, "fire" = 100, "acid" = 50)
|
||||
|
||||
|
||||
/obj/item/clothing/head/beanie/waldo
|
||||
name = "red striped bobble hat"
|
||||
desc = "If you're going on a worldwide hike, you'll need some cold protection."
|
||||
icon_state = "waldo_hat"
|
||||
item_state = "waldo_hat"
|
||||
|
||||
//No dog fashion sprites yet :( poor Ian can't be dope like the rest of us yet
|
||||
@@ -386,3 +386,9 @@
|
||||
cold_protection = HEAD
|
||||
min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT
|
||||
armor = list("melee" = 10, "bullet" = 5, "laser" = 5,"energy" = 5, "bomb" = 5, "bio" = 50, "rad" = 20, "fire" = -10, "acid" = 0)
|
||||
|
||||
/obj/item/clothing/head/helmet/police
|
||||
name = "police officer's hat"
|
||||
desc = "A police officer's Hat. This hat emphasizes that you are THE LAW."
|
||||
icon_state = "policehelm"
|
||||
dynamic_hair_suffix = ""
|
||||
|
||||
@@ -429,3 +429,11 @@
|
||||
icon_state = "russobluecamohat"
|
||||
item_state = "russobluecamohat"
|
||||
dynamic_hair_suffix = ""
|
||||
|
||||
/obj/item/clothing/head/hunter
|
||||
name = "bounty hunting hat"
|
||||
desc = "Ain't nobody gonna cheat the hangman in my town."
|
||||
icon_state = "hunter"
|
||||
item_state = "hunter"
|
||||
armor = list("melee" = 5, "bullet" = 5, "laser" = 5, "energy" = 15, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
|
||||
@@ -231,3 +231,16 @@
|
||||
A.UpdateButtonIcon()
|
||||
to_chat(M, "The Tiki Mask has now changed into the [choice] Mask!")
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/mask/gas/tiki_mask/yalp_elor
|
||||
icon_state = "tiki_yalp"
|
||||
item_state = "tiki_yalp"
|
||||
actions_types = list()
|
||||
|
||||
/obj/item/clothing/mask/gas/hunter
|
||||
name = "bounty hunting mask"
|
||||
desc = "A custom tactical mask with decals added."
|
||||
icon_state = "hunter"
|
||||
item_state = "hunter"
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
flags_inv = HIDEFACIALHAIR|HIDEFACE|HIDEEYES|HIDEEARS|HIDEHAIR
|
||||
|
||||
@@ -185,3 +185,9 @@
|
||||
playsound(src.loc, "sound/voice/complionator/[phrase_sound].ogg", 100, 0, 4)
|
||||
cooldown = world.time
|
||||
cooldown_special = world.time
|
||||
|
||||
/obj/item/clothing/mask/gas/sechailer/swat/spacepol
|
||||
name = "spacepol mask"
|
||||
desc = "A close-fitting tactical mask created in cooperation with a certain megacorporation, comes with an especially aggressive Compli-o-nator 3000."
|
||||
icon_state = "spacepol"
|
||||
item_state = "spacepol"
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
user.alpha = 255
|
||||
user.update_atom_colour()
|
||||
user.animate_movement = FORWARD_STEPS
|
||||
user.notransform = 0
|
||||
user.mob_transforming = 0
|
||||
user.anchored = FALSE
|
||||
teleporting = 0
|
||||
for(var/obj/item/I in user.held_items)
|
||||
@@ -125,7 +125,7 @@
|
||||
ADD_TRAIT(I, TRAIT_NODROP, CHRONOSUIT_TRAIT)
|
||||
user.animate_movement = NO_STEPS
|
||||
user.changeNext_move(8 + phase_in_ds)
|
||||
user.notransform = 1
|
||||
user.mob_transforming = 1
|
||||
user.anchored = TRUE
|
||||
user.Stun(INFINITY)
|
||||
|
||||
|
||||
@@ -518,3 +518,14 @@ Contains:
|
||||
desc = "A deep blue space helmet with a large red cross on the faceplate to designate the wearer as trained emergency medical personnel."
|
||||
icon_state = "paramedic-eva-helmet"
|
||||
item_state = "paramedic-eva-helmet"
|
||||
|
||||
/obj/item/clothing/suit/space/hunter
|
||||
name = "bounty hunting suit"
|
||||
desc = "A custom version of the MK.II SWAT suit, modified to look rugged and tough. Works as a space suit, if you can find a helmet."
|
||||
icon_state = "hunter"
|
||||
item_state = "swat_suit"
|
||||
allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals, /obj/item/kitchen/knife/combat)
|
||||
armor = list("melee" = 60, "bullet" = 40, "laser" = 40, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
|
||||
strip_delay = 130
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
|
||||
|
||||
@@ -1016,3 +1016,9 @@
|
||||
/obj/item/clothing/head/hooded/winterhood/polychromic
|
||||
icon_state = "winterhood_poly"
|
||||
item_state = "winterhood_poly"
|
||||
|
||||
/obj/item/clothing/suit/striped_sweater
|
||||
name = "striped sweater"
|
||||
desc = "Reminds you of someone, but you just can't put your finger on it..."
|
||||
icon_state = "waldo_shirt"
|
||||
item_state = "waldo_shirt"
|
||||
|
||||
@@ -192,3 +192,14 @@
|
||||
icon_state = "hos_parade_fem"
|
||||
item_state = "r_suit"
|
||||
fitted = FEMALE_UNIFORM_TOP
|
||||
|
||||
/*
|
||||
*Spacepol
|
||||
*/
|
||||
|
||||
/obj/item/clothing/under/rank/security/spacepol
|
||||
name = "police uniform"
|
||||
desc = "Space not controlled by megacorporations, planets, or pirates is under the jurisdiction of Spacepol."
|
||||
icon_state = "spacepol"
|
||||
item_state = "spacepol"
|
||||
can_adjust = FALSE
|
||||
@@ -0,0 +1,33 @@
|
||||
/datum/round_event_control/brain_trauma
|
||||
name = "Spontaneous Brain Trauma"
|
||||
typepath = /datum/round_event/brain_trauma
|
||||
weight = 25
|
||||
|
||||
/datum/round_event/brain_trauma
|
||||
fakeable = FALSE
|
||||
|
||||
/datum/round_event/brain_trauma/start()
|
||||
for(var/mob/living/carbon/human/H in shuffle(GLOB.alive_mob_list))
|
||||
if(!H.client)
|
||||
continue
|
||||
if(H.stat == DEAD) // What are you doing in this list
|
||||
continue
|
||||
if(!H.getorgan(/obj/item/organ/brain)) // If only I had a brain
|
||||
continue
|
||||
|
||||
traumatize(H)
|
||||
break
|
||||
|
||||
/datum/round_event/brain_trauma/proc/traumatize(mob/living/carbon/human/H)
|
||||
var/resistance = pick(
|
||||
65;TRAUMA_RESILIENCE_BASIC,
|
||||
30;TRAUMA_RESILIENCE_SURGERY,
|
||||
5;TRAUMA_RESILIENCE_LOBOTOMY)
|
||||
|
||||
var/trauma_type = pickweight(list(
|
||||
BRAIN_TRAUMA_MILD = 60,
|
||||
BRAIN_TRAUMA_SEVERE = 30,
|
||||
BRAIN_TRAUMA_SPECIAL = 10
|
||||
))
|
||||
|
||||
H.gain_trauma_type(trauma_type, resistance)
|
||||
@@ -0,0 +1,30 @@
|
||||
/datum/round_event_control/fake_virus
|
||||
name = "Fake Virus"
|
||||
typepath = /datum/round_event/fake_virus
|
||||
weight = 20
|
||||
|
||||
/datum/round_event/fake_virus/start()
|
||||
var/list/fake_virus_victims = list()
|
||||
for(var/mob/living/carbon/human/H in shuffle(GLOB.player_list))
|
||||
if(!H.client || H.stat == DEAD || H.InCritical())
|
||||
continue
|
||||
fake_virus_victims += H
|
||||
|
||||
//first we do hard status effect victims
|
||||
var/defacto_min = min(3, LAZYLEN(fake_virus_victims))
|
||||
if(defacto_min)// event will hit 1-3 people by default, but will do 1-2 or just 1 if only those many candidates are available
|
||||
for(var/i=1; i<=rand(1,defacto_min); i++)
|
||||
var/mob/living/carbon/human/hypochondriac = pick(fake_virus_victims)
|
||||
hypochondriac.apply_status_effect(STATUS_EFFECT_FAKE_VIRUS)
|
||||
fake_virus_victims -= hypochondriac
|
||||
|
||||
//then we do light one-message victims who simply cough or whatever once (have to repeat the process since the last operation modified our candidates list)
|
||||
defacto_min = min(5, LAZYLEN(fake_virus_victims))
|
||||
if(defacto_min)
|
||||
for(var/i=1; i<=rand(1,defacto_min); i++)
|
||||
var/mob/living/carbon/human/onecoughman = pick(fake_virus_victims)
|
||||
if(prob(25))//1/4 odds to get a spooky message instead of coughing out loud
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, onecoughman, "<span class='warning'>[pick("Your head hurts.", "Your head pounds.")]</span>"), rand(30,150))
|
||||
else
|
||||
addtimer(CALLBACK(onecoughman, .mob/proc/emote, pick("cough", "sniff", "sneeze")), rand(30,150))//deliver the message with a slightly randomized time interval so there arent multiple people coughing at the exact same time
|
||||
fake_virus_victims -= onecoughman
|
||||
@@ -0,0 +1,117 @@
|
||||
/datum/round_event_control/fugitives
|
||||
name = "Spawn Fugitives"
|
||||
typepath = /datum/round_event/ghost_role/fugitives
|
||||
max_occurrences = 1
|
||||
min_players = 20
|
||||
earliest_start = 30 MINUTES //deadchat sink, lets not even consider it early on.
|
||||
gamemode_blacklist = list("nuclear")
|
||||
|
||||
/datum/round_event/ghost_role/fugitives
|
||||
minimum_required = 1
|
||||
role_name = "fugitive"
|
||||
fakeable = FALSE
|
||||
|
||||
/datum/round_event/ghost_role/fugitives/spawn_role()
|
||||
var/list/possible_spawns = list()//Some xeno spawns are in some spots that will instantly kill the refugees, like atmos
|
||||
for(var/turf/X in GLOB.xeno_spawn)
|
||||
if(istype(X.loc, /area/maintenance))
|
||||
possible_spawns += X
|
||||
if(!possible_spawns.len)
|
||||
message_admins("No valid spawn locations found, aborting...")
|
||||
return MAP_ERROR
|
||||
var/turf/landing_turf = pick(possible_spawns)
|
||||
var/list/possible_backstories = list()
|
||||
var/list/candidates = get_candidates(ROLE_TRAITOR, null, ROLE_TRAITOR)
|
||||
if(candidates.len >= 1) //solo refugees
|
||||
if(prob(30))
|
||||
possible_backstories.Add("waldo") //less common as it comes with magicks and is kind of immershun shattering
|
||||
else //For accurate deadchat feedback
|
||||
minimum_required = 4
|
||||
if(candidates.len >= 4)//group refugees
|
||||
possible_backstories.Add("prisoner", "cultist", "synth")
|
||||
if(!possible_backstories.len)
|
||||
return NOT_ENOUGH_PLAYERS
|
||||
|
||||
var/backstory = pick(possible_backstories)
|
||||
var/member_size = 3
|
||||
var/leader
|
||||
switch(backstory)
|
||||
if("synth")
|
||||
leader = pick_n_take(candidates)
|
||||
if("waldo")
|
||||
member_size = 0 //solo refugees have no leader so the member_size gets bumped to one a bit later
|
||||
var/list/members = list()
|
||||
var/list/spawned_mobs = list()
|
||||
if(isnull(leader))
|
||||
member_size++ //if there is no leader role, then the would be leader is a normal member of the team.
|
||||
|
||||
for(var/i in 1 to member_size)
|
||||
members += pick_n_take(candidates)
|
||||
|
||||
for(var/mob/dead/selected in members)
|
||||
var/mob/living/carbon/human/S = gear_fugitive(selected, landing_turf, backstory)
|
||||
spawned_mobs += S
|
||||
if(!isnull(leader))
|
||||
gear_fugitive_leader(leader, landing_turf, backstory)
|
||||
|
||||
//after spawning
|
||||
playsound(src, 'sound/weapons/emitter.ogg', 50, TRUE)
|
||||
new /obj/item/storage/toolbox/mechanical(landing_turf) //so they can actually escape maint
|
||||
addtimer(CALLBACK(src, .proc/spawn_hunters), 10 MINUTES)
|
||||
role_name = "fugitive hunter"
|
||||
return SUCCESSFUL_SPAWN
|
||||
|
||||
/datum/round_event/ghost_role/fugitives/proc/gear_fugitive(mob/dead/selected, turf/landing_turf, backstory) //spawns normal fugitive
|
||||
var/datum/mind/player_mind = new /datum/mind(selected.key)
|
||||
player_mind.active = TRUE
|
||||
var/mob/living/carbon/human/S = new(landing_turf)
|
||||
player_mind.transfer_to(S)
|
||||
player_mind.assigned_role = "Fugitive"
|
||||
player_mind.special_role = "Fugitive"
|
||||
player_mind.add_antag_datum(/datum/antagonist/fugitive)
|
||||
var/datum/antagonist/fugitive/fugitiveantag = player_mind.has_antag_datum(/datum/antagonist/fugitive)
|
||||
INVOKE_ASYNC(fugitiveantag, /datum/antagonist/fugitive.proc/greet, backstory) //some fugitives have a sleep on their greet, so we don't want to stop the entire antag granting proc with fluff
|
||||
|
||||
switch(backstory)
|
||||
if("prisoner")
|
||||
S.equipOutfit(/datum/outfit/prisoner)
|
||||
if("cultist")
|
||||
S.equipOutfit(/datum/outfit/yalp_cultist)
|
||||
if("waldo")
|
||||
S.equipOutfit(/datum/outfit/waldo)
|
||||
if("synth")
|
||||
S.equipOutfit(/datum/outfit/synthetic)
|
||||
message_admins("[ADMIN_LOOKUPFLW(S)] has been made into a Fugitive by an event.")
|
||||
log_game("[key_name(S)] was spawned as a Fugitive by an event.")
|
||||
spawned_mobs += S
|
||||
return S
|
||||
|
||||
//special spawn for one member. it can be used for a special mob or simply to give one normal member special items.
|
||||
/datum/round_event/ghost_role/fugitives/proc/gear_fugitive_leader(mob/dead/leader, turf/landing_turf, backstory)
|
||||
var/datum/mind/player_mind = new /datum/mind(leader.key)
|
||||
player_mind.active = TRUE
|
||||
//if you want to add a fugitive with a special leader in the future, make this switch with the backstory
|
||||
var/mob/living/carbon/human/S = gear_fugitive(leader, landing_turf, backstory)
|
||||
var/obj/item/choice_beacon/augments/A = new(S)
|
||||
S.put_in_hands(A)
|
||||
new /obj/item/autosurgeon(landing_turf)
|
||||
|
||||
//security team gets called in after 10 minutes of prep to find the refugees
|
||||
/datum/round_event/ghost_role/fugitives/proc/spawn_hunters()
|
||||
var/backstory = pick("space cop", "russian", "bounty hunter")
|
||||
var/datum/map_template/shuttle/ship
|
||||
if(backstory == "space cop")
|
||||
ship = new /datum/map_template/shuttle/hunter/space_cop
|
||||
else if (backstory == "russian")
|
||||
ship = new /datum/map_template/shuttle/hunter/russian
|
||||
else
|
||||
ship = new /datum/map_template/shuttle/hunter/bounty
|
||||
var/x = rand(TRANSITIONEDGE,world.maxx - TRANSITIONEDGE - ship.width)
|
||||
var/y = rand(TRANSITIONEDGE,world.maxy - TRANSITIONEDGE - ship.height)
|
||||
var/z = SSmapping.empty_space.z_value
|
||||
var/turf/T = locate(x,y,z)
|
||||
if(!T)
|
||||
CRASH("Fugitive Hunters (Created from fugitive event) found no turf to load in")
|
||||
if(!ship.load(T))
|
||||
CRASH("Loading [backstory] ship failed!")
|
||||
priority_announce("Unidentified ship detected near the station.")
|
||||
@@ -0,0 +1,99 @@
|
||||
///Spawns a cargo pod containing a random cargo supply pack on a random area of the station
|
||||
/datum/round_event_control/stray_cargo
|
||||
name = "Stray Cargo Pod"
|
||||
typepath = /datum/round_event/stray_cargo
|
||||
weight = 20
|
||||
max_occurrences = 4
|
||||
earliest_start = 10 MINUTES
|
||||
|
||||
///Spawns a cargo pod containing a random cargo supply pack on a random area of the station
|
||||
/datum/round_event/stray_cargo
|
||||
var/area/impact_area ///Randomly picked area
|
||||
var/list/possible_pack_types = list() ///List of possible supply packs dropped in the pod, if empty picks from the cargo list
|
||||
var/static/list/stray_spawnable_supply_packs = list() ///List of default spawnable supply packs, filtered from the cargo list
|
||||
|
||||
/datum/round_event/stray_cargo/announce(fake)
|
||||
priority_announce("Stray cargo pod detected on long-range scanners. Expected location of impact: [impact_area.name].", "Collision Alert")
|
||||
|
||||
/**
|
||||
* Tries to find a valid area, throws an error if none are found
|
||||
* Also randomizes the start timer
|
||||
*/
|
||||
/datum/round_event/stray_cargo/setup()
|
||||
startWhen = rand(20, 40)
|
||||
impact_area = find_event_area()
|
||||
if(!impact_area)
|
||||
CRASH("No valid areas for cargo pod found.")
|
||||
var/list/turf_test = get_area_turfs(impact_area)
|
||||
if(!turf_test.len)
|
||||
CRASH("Stray Cargo Pod : No valid turfs found for [impact_area] - [impact_area.type]")
|
||||
|
||||
if(!stray_spawnable_supply_packs.len)
|
||||
stray_spawnable_supply_packs = SSshuttle.supply_packs.Copy()
|
||||
for(var/pack in stray_spawnable_supply_packs)
|
||||
var/datum/supply_pack/pack_type = pack
|
||||
if(initial(pack_type.special))
|
||||
stray_spawnable_supply_packs -= pack
|
||||
|
||||
///Spawns a random supply pack, puts it in a pod, and spawns it on a random tile of the selected area
|
||||
/datum/round_event/stray_cargo/start()
|
||||
var/list/turf/valid_turfs = get_area_turfs(impact_area)
|
||||
//Only target non-dense turfs to prevent wall-embedded pods
|
||||
for(var/i in valid_turfs)
|
||||
var/turf/T = i
|
||||
if(T.density)
|
||||
valid_turfs -= T
|
||||
var/turf/LZ = pick(valid_turfs)
|
||||
var/pack_type
|
||||
if(possible_pack_types.len)
|
||||
pack_type = pick(possible_pack_types)
|
||||
else
|
||||
pack_type = pick(stray_spawnable_supply_packs)
|
||||
var/datum/supply_pack/SP = new pack_type
|
||||
var/obj/structure/closet/crate/crate = SP.generate(null)
|
||||
crate.locked = FALSE //Unlock secure crates
|
||||
crate.update_icon()
|
||||
var/obj/structure/closet/supplypod/pod = make_pod()
|
||||
crate.forceMove(pod)
|
||||
new /obj/effect/abstract/DPtarget(LZ, pod)
|
||||
|
||||
///Handles the creation of the pod, in case it needs to be modified beforehand
|
||||
/datum/round_event/stray_cargo/proc/make_pod()
|
||||
var/obj/structure/closet/supplypod/S = new
|
||||
return S
|
||||
|
||||
///Picks an area that wouldn't risk critical damage if hit by a pod explosion
|
||||
/datum/round_event/stray_cargo/proc/find_event_area()
|
||||
var/static/list/allowed_areas
|
||||
if(!allowed_areas)
|
||||
///Places that shouldn't explode
|
||||
var/list/safe_area_types = typecacheof(list(
|
||||
/area/ai_monitored/turret_protected/ai,
|
||||
/area/ai_monitored/turret_protected/ai_upload,
|
||||
/area/engine,
|
||||
/area/shuttle)
|
||||
)
|
||||
|
||||
///Subtypes from the above that actually should explode.
|
||||
var/list/unsafe_area_subtypes = typecacheof(list(/area/engine/break_room))
|
||||
allowed_areas = make_associative(GLOB.the_station_areas) - safe_area_types + unsafe_area_subtypes
|
||||
var/list/possible_areas = typecache_filter_list(GLOB.sortedAreas,allowed_areas)
|
||||
if (length(possible_areas))
|
||||
return pick(possible_areas)
|
||||
|
||||
///A rare variant that drops a crate containing syndicate uplink items
|
||||
/datum/round_event_control/stray_cargo/syndicate
|
||||
name = "Stray Syndicate Cargo Pod"
|
||||
typepath = /datum/round_event/stray_cargo/syndicate
|
||||
weight = 6
|
||||
max_occurrences = 1
|
||||
earliest_start = 30 MINUTES
|
||||
|
||||
/datum/round_event/stray_cargo/syndicate
|
||||
possible_pack_types = list(/datum/supply_pack/misc/syndicate)
|
||||
|
||||
///Apply the syndicate pod skin
|
||||
/datum/round_event/stray_cargo/syndicate/make_pod()
|
||||
var/obj/structure/closet/supplypod/S = new
|
||||
S.setStyle(STYLE_SYNDICATE)
|
||||
return S
|
||||
@@ -140,22 +140,6 @@
|
||||
typepath = /datum/round_event/vent_clog/plasma_decon
|
||||
max_occurrences = 0
|
||||
|
||||
/datum/round_event_control/vent_clog/female
|
||||
name = "Clogged Vents; Girlcum"
|
||||
typepath = /datum/round_event/vent_clog/female
|
||||
max_occurrences = 0
|
||||
|
||||
/datum/round_event/vent_clog/female
|
||||
reagentsAmount = 100
|
||||
|
||||
/datum/round_event_control/vent_clog/male
|
||||
name = "Clogged Vents: Semen"
|
||||
typepath = /datum/round_event/vent_clog/male
|
||||
max_occurrences = 0
|
||||
|
||||
/datum/round_event/vent_clog/male
|
||||
reagentsAmount = 100
|
||||
|
||||
/datum/round_event/vent_clog/beer/announce()
|
||||
priority_announce("The scrubbers network is experiencing an unexpected surge of pressurized beer. Some ejection of contents may occur.", "Atmospherics alert")
|
||||
|
||||
@@ -171,36 +155,6 @@
|
||||
foam.start()
|
||||
CHECK_TICK
|
||||
|
||||
/datum/round_event/vent_clog/male/announce()
|
||||
priority_announce("The scrubbers network is experiencing a backpressure surge. Some ejaculation of contents may occur.", "Atmospherics alert")
|
||||
|
||||
/datum/round_event/vent_clog/male/start()
|
||||
for(var/obj/machinery/atmospherics/components/unary/vent in vents)
|
||||
if(vent && vent.loc && !vent.welded)
|
||||
var/datum/reagents/R = new/datum/reagents(1000)
|
||||
R.my_atom = vent
|
||||
R.add_reagent(/datum/reagent/consumable/semen, reagentsAmount)
|
||||
|
||||
var/datum/effect_system/foam_spread/foam = new
|
||||
foam.set_up(200, get_turf(vent), R)
|
||||
foam.start()
|
||||
CHECK_TICK
|
||||
|
||||
/datum/round_event/vent_clog/female/announce()
|
||||
priority_announce("The scrubbers network is experiencing a backpressure squirt. Some ejection of contents may occur.", "Atmospherics alert")
|
||||
|
||||
/datum/round_event/vent_clog/female/start()
|
||||
for(var/obj/machinery/atmospherics/components/unary/vent in vents)
|
||||
if(vent && vent.loc && !vent.welded)
|
||||
var/datum/reagents/R = new/datum/reagents(1000)
|
||||
R.my_atom = vent
|
||||
R.add_reagent(/datum/reagent/consumable/femcum, reagentsAmount)
|
||||
|
||||
var/datum/effect_system/foam_spread/foam = new
|
||||
foam.set_up(200, get_turf(vent), R)
|
||||
foam.start()
|
||||
CHECK_TICK
|
||||
|
||||
/datum/round_event/vent_clog/plasma_decon/announce()
|
||||
priority_announce("We are deploying an experimental plasma decontamination system. Please stand away from the vents and do not breathe the smoke that comes out.", "Central Command Update")
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
/datum/round_event_control/wisdomcow
|
||||
name = "Wisdom cow"
|
||||
typepath = /datum/round_event/wisdomcow
|
||||
max_occurrences = 1
|
||||
weight = 20
|
||||
|
||||
/datum/round_event/wisdomcow/announce(fake)
|
||||
priority_announce("A wise cow has been spotted in the area. Be sure to ask for her advice.", "Nanotrasen Cow Ranching Agency")
|
||||
|
||||
/datum/round_event/wisdomcow/start()
|
||||
var/turf/targetloc = get_random_station_turf()
|
||||
new /mob/living/simple_animal/cow/wisdom(targetloc)
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(1, targetloc)
|
||||
smoke.start()
|
||||
@@ -0,0 +1,46 @@
|
||||
/datum/round_event_control/wizard/embedpocalypse
|
||||
name = "Make Everything Embeddable"
|
||||
weight = 2
|
||||
typepath = /datum/round_event/wizard/embedpocalypse
|
||||
max_occurrences = 1
|
||||
earliest_start = 0 MINUTES
|
||||
|
||||
/datum/round_event/wizard/embedpocalypse/start()
|
||||
for(var/obj/item/I in world)
|
||||
CHECK_TICK
|
||||
|
||||
if(!(I.flags_1 & INITIALIZED_1))
|
||||
continue
|
||||
|
||||
if(!I.embedding || I.embedding == EMBED_HARMLESS)
|
||||
I.embedding = EMBED_POINTY
|
||||
I.updateEmbedding()
|
||||
I.name = "pointy [I.name]"
|
||||
|
||||
GLOB.embedpocalypse = TRUE
|
||||
GLOB.stickpocalypse = FALSE // embedpocalypse takes precedence over stickpocalypse
|
||||
|
||||
/datum/round_event_control/wizard/embedpocalypse/sticky
|
||||
name = "Make Everything Sticky"
|
||||
weight = 6
|
||||
typepath = /datum/round_event/wizard/embedpocalypse/sticky
|
||||
max_occurrences = 1
|
||||
earliest_start = 0 MINUTES
|
||||
|
||||
/datum/round_event_control/wizard/embedpocalypse/sticky/canSpawnEvent(players_amt, gamemode)
|
||||
if(GLOB.embedpocalypse)
|
||||
return FALSE
|
||||
|
||||
/datum/round_event/wizard/embedpocalypse/sticky/start()
|
||||
for(var/obj/item/I in world)
|
||||
CHECK_TICK
|
||||
|
||||
if(!(I.flags_1 & INITIALIZED_1))
|
||||
continue
|
||||
|
||||
if(!I.embedding)
|
||||
I.embedding = EMBED_HARMLESS
|
||||
I.updateEmbedding()
|
||||
I.name = "sticky [I.name]"
|
||||
|
||||
GLOB.stickpocalypse = TRUE
|
||||
@@ -315,6 +315,15 @@
|
||||
slice_path = /obj/item/reagent_containers/food/snacks/meat/rawcutlet/gondola
|
||||
foodtype = RAW | MEAT
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/meat/slab/wisdomcow
|
||||
name = "wisdom cow meat"
|
||||
desc = "The meat from the legendary creature known as the wisdom cow. You monster."
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/medicine/liquid_wisdom = 5)
|
||||
tastes = list("meat" = 1, "wisdom" = 5)
|
||||
filling_color = "#18e3ca"
|
||||
cooked_type = /obj/item/reagent_containers/food/snacks/meat/steak/wisdomcow
|
||||
slice_path = /obj/item/reagent_containers/food/snacks/meat/rawcutlet/wisdomcow
|
||||
|
||||
////////////////////////////////////// MEAT STEAKS ///////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -374,6 +383,10 @@
|
||||
name = "gondola steak"
|
||||
tastes = list("meat" = 1, "tranquility" = 1)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/meat/steak/wisdomcow
|
||||
name = "wisdom cow steak"
|
||||
tastes = list("meat" = 1, "wisdom" = 5)
|
||||
|
||||
//////////////////////////////// MEAT CUTLETS ///////////////////////////////////////////////////////
|
||||
|
||||
//Raw cutlets
|
||||
@@ -441,6 +454,11 @@
|
||||
cooked_type = /obj/item/reagent_containers/food/snacks/meat/cutlet/gondola
|
||||
tastes = list("meat" = 1, "tranquility" = 1)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/meat/rawcutlet/wisdomcow
|
||||
name = "raw wisdom cow cutlet"
|
||||
cooked_type = /obj/item/reagent_containers/food/snacks/meat/cutlet/wisdomcow
|
||||
tastes = list("meat" = 1, "wisdom" = 5)
|
||||
|
||||
//Cooked cutlets
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/meat/cutlet
|
||||
@@ -488,3 +506,7 @@
|
||||
/obj/item/reagent_containers/food/snacks/meat/cutlet/chicken
|
||||
name = "chicken cutlet"
|
||||
tastes = list("chicken" = 1)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/meat/cutlet/wisdomcow
|
||||
name = "wisdom cow cutlet"
|
||||
tastes = list("meat" = 1, "wisdom" = 5)
|
||||
|
||||
@@ -463,7 +463,7 @@
|
||||
return TRUE
|
||||
if(!O.reagents || !O.reagents.reagent_list.len) // other empty containers not accepted
|
||||
return FALSE
|
||||
if(istype(O, /obj/item/reagent_containers/syringe) || istype(O, /obj/item/reagent_containers/glass/bottle) || istype(O, /obj/item/reagent_containers/glass/beaker) || istype(O, /obj/item/reagent_containers/spray) || istype(O, /obj/item/reagent_containers/medspray))
|
||||
if(istype(O, /obj/item/reagent_containers/syringe) || istype(O, /obj/item/reagent_containers/glass/bottle) || istype(O, /obj/item/reagent_containers/glass/beaker) || istype(O, /obj/item/reagent_containers/spray) || istype(O, /obj/item/reagent_containers/medspray) || istype(O, /obj/item/reagent_containers/chem_pack))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
/obj/item/t_scanner = 5,
|
||||
/obj/item/airlock_painter = 1,
|
||||
/obj/item/stack/cable_coil = 6,
|
||||
/obj/item/stack/medical/bruise_pack = 1,
|
||||
/obj/item/stack/medical/suture = 1,
|
||||
/obj/item/stack/rods = 3,
|
||||
/obj/item/stack/sheet/cardboard = 2,
|
||||
/obj/item/stack/sheet/metal = 1,
|
||||
|
||||
@@ -56,8 +56,9 @@
|
||||
cached_z = z
|
||||
poof()
|
||||
|
||||
/mob/living/simple_animal/jacq/Life()
|
||||
..()
|
||||
/mob/living/simple_animal/jacq/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if(!ckey)
|
||||
if((last_poof+3 MINUTES) < world.realtime)
|
||||
poof()
|
||||
|
||||
@@ -195,7 +195,7 @@
|
||||
/obj/item/reagent_containers/food/snacks/grown/firelemon/ex_act(severity)
|
||||
qdel(src) //Ensuring that it's deleted by its own explosion
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/firelemon/proc/prime()
|
||||
/obj/item/reagent_containers/food/snacks/grown/firelemon/proc/prime(mob/living/lanced_by)
|
||||
switch(seed.potency) //Combustible lemons are alot like IEDs, lots of flame, very little bang.
|
||||
if(0 to 30)
|
||||
update_mob()
|
||||
|
||||
@@ -223,7 +223,7 @@
|
||||
/obj/item/reagent_containers/food/snacks/grown/cherry_bomb/ex_act(severity)
|
||||
qdel(src) //Ensuring that it's deleted by its own explosion. Also prevents mass chain reaction with piles of cherry bombs
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/cherry_bomb/proc/prime()
|
||||
/obj/item/reagent_containers/food/snacks/grown/cherry_bomb/proc/prime(mob/living/lanced_by)
|
||||
icon_state = "cherry_bomb_lit"
|
||||
playsound(src, 'sound/effects/fuse.ogg', seed.potency, 0)
|
||||
addtimer(CALLBACK(src, /obj/item/reagent_containers/food/snacks/grown/cherry_bomb/proc/detonate), rand(50, 100))
|
||||
|
||||
@@ -283,10 +283,8 @@
|
||||
|
||||
/obj/item/integrated_circuit/arithmetic/square_root/do_work()
|
||||
var/result = 0
|
||||
for(var/k in 2 to inputs.len)
|
||||
var/I = get_pin_data(IC_INPUT, k)
|
||||
if(isnum(I))
|
||||
result += sqrt(I)
|
||||
var/I = get_pin_data(IC_INPUT, 1)
|
||||
result = sqrt(I)
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
|
||||
@@ -1,21 +1,27 @@
|
||||
/datum/minimap
|
||||
var/name
|
||||
var/name = "minimap"
|
||||
var/icon/overlay_icon
|
||||
// The map icons
|
||||
var/icon/map_icon
|
||||
var/icon/meta_icon
|
||||
var/icon/overlay_icon
|
||||
|
||||
var/list/color_area_names = list()
|
||||
|
||||
var/minx
|
||||
var/maxx
|
||||
var/miny
|
||||
var/maxy
|
||||
var/z_level
|
||||
var/id = 0
|
||||
var/static/next_id = 0
|
||||
|
||||
/datum/minimap/New(z, x1 = 1, y1 = 1, x2 = world.maxx, y2 = world.maxy, name)
|
||||
var/z_level
|
||||
var/id = ""
|
||||
|
||||
/datum/minimap/New(z, x1 = 1, y1 = 1, x2 = world.maxx, y2 = world.maxy, name = "minimap")
|
||||
if(!z)
|
||||
CRASH("ERROR: new minimap requested without z level") //CRASH to halt the operatio
|
||||
|
||||
src.name = name
|
||||
id = ++next_id
|
||||
z_level = z
|
||||
id = "[md5("[z_level]" + src.name + REF(src))]" //use it's own md5 as a special identifier
|
||||
|
||||
var/crop_x1 = x2
|
||||
var/crop_x2 = x1
|
||||
@@ -25,10 +31,11 @@
|
||||
// do the generating
|
||||
map_icon = new('html/blank.png')
|
||||
meta_icon = new('html/blank.png')
|
||||
map_icon.Scale(x2-x1+1, y2-y1+1) // arrays start at 1
|
||||
meta_icon.Scale(x2-x1+1, y2-y1+1)
|
||||
map_icon.Scale(x2 - x1 + 1, y2 - y1 + 1) // arrays start at 1
|
||||
meta_icon.Scale(x2 - x1 + 1, y2 - y1 + 1)
|
||||
|
||||
var/list/area_to_color = list()
|
||||
for(var/turf/T in block(locate(x1,y1,z),locate(x2,y2,z)))
|
||||
for(var/turf/T in block(locate(x1, y1, z_level), locate(x2, y2, z_level)))
|
||||
var/area/A = T.loc
|
||||
var/img_x = T.x - x1 + 1 // arrays start at 1
|
||||
var/img_y = T.y - y1 + 1
|
||||
@@ -37,21 +44,26 @@
|
||||
crop_x2 = max(crop_x2, T.x)
|
||||
crop_y1 = min(crop_y1, T.y)
|
||||
crop_y2 = max(crop_y2, T.y)
|
||||
|
||||
var/meta_color = area_to_color[A]
|
||||
if(!meta_color)
|
||||
meta_color = rgb(rand(0,255),rand(0,255),rand(0,255)) // technically conflicts could happen but it's like very unlikely and it's not that big of a deal if one happens
|
||||
meta_color = rgb(rand(0, 255), rand(0, 255), rand(0, 255)) // technically conflicts could happen but it's like very unlikely and it's not that big of a deal if one happens
|
||||
area_to_color[A] = meta_color
|
||||
color_area_names[meta_color] = A.name
|
||||
meta_icon.DrawBox(meta_color, img_x, img_y)
|
||||
|
||||
if(istype(T, /turf/closed/wall))
|
||||
map_icon.DrawBox("#000000", img_x, img_y)
|
||||
|
||||
else if(!istype(A, /area/space))
|
||||
var/color = A.minimap_color || "#FF00FF"
|
||||
if(locate(/obj/machinery/power/solar) in T)
|
||||
color = "#02026a"
|
||||
|
||||
if((locate(/obj/effect/spawner/structure/window) in T) || (locate(/obj/structure/grille) in T))
|
||||
color = BlendRGB(color, "#000000", 0.5)
|
||||
map_icon.DrawBox(color, img_x, img_y)
|
||||
|
||||
map_icon.Crop(crop_x1, crop_y1, crop_x2, crop_y2)
|
||||
meta_icon.Crop(crop_x1, crop_y1, crop_x2, crop_y2)
|
||||
minx = crop_x1
|
||||
@@ -60,14 +72,18 @@
|
||||
maxy = crop_y2
|
||||
overlay_icon = new(map_icon)
|
||||
overlay_icon.Scale(16, 16)
|
||||
|
||||
/datum/minimap/proc/send(mob/user)
|
||||
//we're done baking, now we ship it.
|
||||
register_asset("minimap-[id].png", map_icon)
|
||||
register_asset("minimap-[id]-meta.png", meta_icon)
|
||||
send_asset_list(user, list("minimap-[id].png" = map_icon, "minimap-[id]-meta.png" = meta_icon))
|
||||
|
||||
/datum/minimap/proc/send(mob/user)
|
||||
if(!id)
|
||||
CRASH("ERROR: send called, but the minimap id is null/missing. ID: [id]")
|
||||
send_asset_list(user, list("minimap-[id].png" = map_icon, "minimap-[id]-meta.png" = meta_icon))
|
||||
|
||||
/datum/minimap_group
|
||||
var/list/minimaps
|
||||
var/list/minimaps = list()
|
||||
var/static/next_id = 0
|
||||
var/id
|
||||
var/name
|
||||
@@ -75,46 +91,62 @@
|
||||
/datum/minimap_group/New(list/maps, name)
|
||||
id = ++next_id
|
||||
src.name = name
|
||||
minimaps = maps || list()
|
||||
if(maps)
|
||||
minimaps = maps
|
||||
|
||||
/datum/minimap_group/proc/show(mob/user)
|
||||
if(!length(minimaps))
|
||||
to_chat(user, "<span class='boldwarning'>ERROR: Attempted to access an empty datum/minimap_group. This should probably not happen.</span>")
|
||||
return
|
||||
|
||||
var/list/datas = list()
|
||||
var/list/info = list()
|
||||
var/datum/minimap/first_map = minimaps[1]
|
||||
for(var/i in 1 to length(minimaps))
|
||||
|
||||
for(var/i in 1 to length(minimaps))// OLD: for(var/i in 1 to length(minimaps))
|
||||
var/datum/minimap/M = minimaps[i]
|
||||
M.send(user)
|
||||
info += "<img src='minimap-[M.id].png' id='map-[i]'><img src='minimap-[M.id]-meta.png' style='display: none' id='map-[i]-meta'><div id='label-[i]'></div>"
|
||||
info += {"
|
||||
<div class="block">
|
||||
<div> <!-- The div is in here to fit it both in the block div -->
|
||||
<img id='map-[i]' src='minimap-[M.id].png' />
|
||||
<img id='map-[i]-meta' src='minimap-[M.id]-meta.png' style='display: none' />
|
||||
</div>
|
||||
<div class="statusDisplay" id='label-[i]'></div>
|
||||
</div>
|
||||
"}
|
||||
datas += json_encode(M.color_area_names);
|
||||
info = info.Join()
|
||||
|
||||
var/html = {"
|
||||
<!DOCTYPE html>
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
|
||||
<script>
|
||||
function hexify(num) {
|
||||
if(!num) num = 0;
|
||||
num = num.toString(16);
|
||||
if(num.length == 1) num = "0" + num;
|
||||
return num;
|
||||
}
|
||||
window.onload = function() {
|
||||
var datas = \[[jointext(datas, ",")]]
|
||||
if(window.HTMLCanvasElement) {
|
||||
for(var i = 0; i < [minimaps.len]; i++) {
|
||||
(function() {
|
||||
info = info.Join()
|
||||
//this is bad. Too bad!
|
||||
var/headerJS = {"
|
||||
<script>
|
||||
function hexify(num) {
|
||||
if(!num){
|
||||
num = 0;
|
||||
}
|
||||
num = num.toString(16);
|
||||
if(num.length == 1){
|
||||
num = "0" + num;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
window.onload = function() {
|
||||
var datas = \[[jointext(datas, ",")]]
|
||||
if(!window.HTMLCanvasElement){
|
||||
//something has gone horribly wrong!
|
||||
return false
|
||||
}
|
||||
for(var i = 0; i < [length(minimaps)]; i++){
|
||||
//the fuck is this wrapped?
|
||||
var data = datas\[i];
|
||||
var img = document.getElementById("map-" + (i+1));
|
||||
if(!img) return;
|
||||
var img = document.getElementById("map-" + (i + 1));
|
||||
if(!img){
|
||||
return; //if it does not exist, it means it's done!
|
||||
}
|
||||
var canvas = document.createElement("canvas");
|
||||
canvas.width = img.width * 2;
|
||||
canvas.height = img.height * 2;
|
||||
|
||||
var ctx = canvas.getContext('2d');
|
||||
ctx.msImageSmoothingEnabled = false;
|
||||
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
|
||||
@@ -123,9 +155,10 @@ window.onload = function() {
|
||||
ctx.canvas.width = img.width;
|
||||
ctx.canvas.height = img.height;
|
||||
ctx.drawImage(document.getElementById("map-" + (i+1) + "-meta"), 0, 0);
|
||||
|
||||
var imagedata = ctx.getImageData(0, 0, img.width, img.height);
|
||||
var label = document.getElementById("label-" + (i+1));
|
||||
canvas.onmousemove = function(e) {
|
||||
canvas.onmousemove = function(e){
|
||||
var rect = canvas.getBoundingClientRect();
|
||||
var x = Math.floor(e.offsetX * img.width / rect.width);
|
||||
var y = Math.floor(e.offsetY * img.height / rect.height);
|
||||
@@ -134,23 +167,23 @@ window.onload = function() {
|
||||
label.textContent = data\[color];
|
||||
canvas.title = data\[color];
|
||||
}
|
||||
canvas.onmouseout = function(e) {
|
||||
label.textContent = "";
|
||||
canvas.onmouseout = function(e){
|
||||
canvas.title = "";
|
||||
}
|
||||
})();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<STYLE>
|
||||
img, canvas {
|
||||
width: 100%
|
||||
}
|
||||
</STYLE>
|
||||
<TITLE>[name]</TITLE>
|
||||
</HEAD>
|
||||
<BODY>[info]</BODY>
|
||||
</HTML>"}
|
||||
</script>
|
||||
<style>
|
||||
img, canvas {
|
||||
width: 100%;
|
||||
background-color: white;
|
||||
}
|
||||
</style>
|
||||
"}
|
||||
|
||||
user << browse(html, "window=minimap_[id];size=768x[round(768 / first_map.map_icon.Width() * first_map.map_icon.Height() + 50)]")
|
||||
var/datum/browser/popup = new(user, "minimap_[id]", name, 500, 700)
|
||||
popup.add_head_content(headerJS) //set the head
|
||||
popup.set_content(info)
|
||||
var/datum/minimap/MICO = minimaps[1]
|
||||
popup.set_title_image(MICO.overlay_icon)
|
||||
popup.open(FALSE)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
desc = "It's watching you suspiciously."
|
||||
|
||||
/obj/structure/closet/crate/necropolis/tendril/PopulateContents()
|
||||
var/loot = rand(1,28)
|
||||
var/loot = rand(1,29)
|
||||
switch(loot)
|
||||
if(1)
|
||||
new /obj/item/shared_storage/red(src)
|
||||
@@ -77,6 +77,11 @@
|
||||
new /obj/item/bedsheet/cult(src)
|
||||
if(28)
|
||||
new /obj/item/clothing/neck/necklace/memento_mori(src)
|
||||
if(29)
|
||||
if(prob(50))
|
||||
new /obj/item/malf_upgrade
|
||||
else
|
||||
new /obj/item/disk/tech_disk/illegal
|
||||
|
||||
//KA modkit design discs
|
||||
/obj/item/disk/design_disk/modkit_disc
|
||||
@@ -487,7 +492,7 @@
|
||||
setDir(user.dir)
|
||||
|
||||
user.forceMove(src)
|
||||
user.notransform = TRUE
|
||||
user.mob_transforming = TRUE
|
||||
user.status_flags |= GODMODE
|
||||
|
||||
can_destroy = FALSE
|
||||
@@ -496,7 +501,7 @@
|
||||
|
||||
/obj/effect/immortality_talisman/proc/unvanish(mob/user)
|
||||
user.status_flags &= ~GODMODE
|
||||
user.notransform = FALSE
|
||||
user.mob_transforming = FALSE
|
||||
user.forceMove(get_turf(src))
|
||||
|
||||
user.visible_message("<span class='danger'>[user] pops back into reality!</span>")
|
||||
|
||||
@@ -68,7 +68,7 @@ INITIALIZE_IMMEDIATE(/mob/dead)
|
||||
set category = "OOC"
|
||||
set name = "Server Hop!"
|
||||
set desc= "Jump to the other server"
|
||||
if(notransform)
|
||||
if(mob_transforming)
|
||||
return
|
||||
var/list/csa = CONFIG_GET(keyed_list/cross_server)
|
||||
var/pick
|
||||
@@ -93,9 +93,9 @@ INITIALIZE_IMMEDIATE(/mob/dead)
|
||||
to_chat(C, "<span class='notice'>Sending you to [pick].</span>")
|
||||
new /obj/screen/splash(C)
|
||||
|
||||
notransform = TRUE
|
||||
mob_transforming = TRUE
|
||||
sleep(29) //let the animation play
|
||||
notransform = FALSE
|
||||
mob_transforming = FALSE
|
||||
|
||||
if(!C)
|
||||
return
|
||||
|
||||
@@ -94,7 +94,9 @@
|
||||
|
||||
//We want an accurate reading of .len
|
||||
listclearnulls(BP.embedded_objects)
|
||||
temp_bleed += 0.5 * BP.embedded_objects.len
|
||||
for(var/obj/item/embeddies in BP.embedded_objects)
|
||||
if(!embeddies.isEmbedHarmless())
|
||||
temp_bleed += 0.5
|
||||
|
||||
if(brutedamage >= 20)
|
||||
temp_bleed += (brutedamage * 0.013)
|
||||
|
||||
@@ -37,10 +37,10 @@
|
||||
C.put_in_hands(B1)
|
||||
C.put_in_hands(B2)
|
||||
C.regenerate_icons()
|
||||
src.notransform = TRUE
|
||||
src.mob_transforming = TRUE
|
||||
spawn(0)
|
||||
bloodpool_sink(B)
|
||||
src.notransform = FALSE
|
||||
src.mob_transforming = FALSE
|
||||
return 1
|
||||
|
||||
/mob/living/proc/bloodpool_sink(obj/effect/decal/cleanable/B)
|
||||
@@ -155,7 +155,7 @@
|
||||
addtimer(CALLBACK(src, /atom/.proc/remove_atom_colour, TEMPORARY_COLOUR_PRIORITY, newcolor), 6 SECONDS)
|
||||
|
||||
/mob/living/proc/phasein(obj/effect/decal/cleanable/B)
|
||||
if(src.notransform)
|
||||
if(src.mob_transforming)
|
||||
to_chat(src, "<span class='warning'>Finish eating first!</span>")
|
||||
return 0
|
||||
B.visible_message("<span class='warning'>[B] starts to bubble...</span>")
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
|
||||
/mob/living/brain/Life()
|
||||
set invisibility = 0
|
||||
if (notransform)
|
||||
/mob/living/brain/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if(!loc)
|
||||
return
|
||||
. = ..()
|
||||
handle_emp_damage()
|
||||
|
||||
/mob/living/brain/update_stat()
|
||||
|
||||
@@ -8,9 +8,6 @@
|
||||
/mob/living/carbon/alien/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
|
||||
return ..(AM, skipcatch = TRUE, hitpush = FALSE)
|
||||
|
||||
/mob/living/carbon/alien/can_embed(obj/item/I)
|
||||
return FALSE
|
||||
|
||||
/*Code for aliens attacking aliens. Because aliens act on a hivemind, I don't see them as very aggressive with each other.
|
||||
As such, they can either help or harm other aliens. Help works like the human help command while harm is a simple nibble.
|
||||
In all, this is a lot like the monkey code. /N
|
||||
@@ -54,6 +51,8 @@ In all, this is a lot like the monkey code. /N
|
||||
return
|
||||
switch(M.a_intent)
|
||||
if(INTENT_HELP)
|
||||
if(M == src && check_self_for_injuries())
|
||||
return
|
||||
help_shake_act(M)
|
||||
if(INTENT_GRAB)
|
||||
grabbedby(M)
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
|
||||
|
||||
/mob/living/carbon/alien/larva/Life()
|
||||
set invisibility = 0
|
||||
if (notransform)
|
||||
/mob/living/carbon/alien/larva/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if(..()) //not dead
|
||||
// GROW!
|
||||
if(amount_grown < max_grown)
|
||||
amount_grown++
|
||||
update_icons()
|
||||
// GROW!
|
||||
if(amount_grown < max_grown)
|
||||
amount_grown++
|
||||
update_icons()
|
||||
|
||||
|
||||
/mob/living/carbon/alien/larva/update_stat()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/mob/living/carbon/alien/Life()
|
||||
/mob/living/carbon/alien/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
findQueen()
|
||||
return..()
|
||||
|
||||
/mob/living/carbon/alien/check_breath(datum/gas_mixture/breath)
|
||||
if(status_flags & GODMODE)
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
ghost.transfer_ckey(new_xeno, FALSE)
|
||||
SEND_SOUND(new_xeno, sound('sound/voice/hiss5.ogg',0,0,0,100)) //To get the player's attention
|
||||
new_xeno.Paralyze(6)
|
||||
new_xeno.notransform = TRUE
|
||||
new_xeno.mob_transforming = TRUE
|
||||
new_xeno.invisibility = INVISIBILITY_MAXIMUM
|
||||
|
||||
sleep(6)
|
||||
@@ -102,7 +102,7 @@
|
||||
|
||||
if(new_xeno)
|
||||
new_xeno.SetParalyzed(0)
|
||||
new_xeno.notransform = FALSE
|
||||
new_xeno.mob_transforming = FALSE
|
||||
new_xeno.invisibility = 0
|
||||
|
||||
var/mob/living/carbon/old_owner = owner
|
||||
|
||||
@@ -247,7 +247,7 @@
|
||||
/mob/living/carbon/Topic(href, href_list)
|
||||
..()
|
||||
//strip panel
|
||||
if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
|
||||
if(usr.canUseTopic(src, BE_CLOSE))
|
||||
if(href_list["internal"] && !HAS_TRAIT(src, TRAIT_NO_INTERNALS))
|
||||
var/slot = text2num(href_list["internal"])
|
||||
var/obj/item/ITEM = get_item_by_slot(slot)
|
||||
@@ -267,7 +267,15 @@
|
||||
visible_message("<span class='danger'>[usr] [internal ? "opens" : "closes"] the valve on [src]'s [ITEM.name].</span>", \
|
||||
"<span class='userdanger'>[usr] [internal ? "opens" : "closes"] the valve on your [ITEM.name].</span>", \
|
||||
target = usr, target_message = "<span class='danger'>You [internal ? "opens" : "closes"] the valve on [src]'s [ITEM.name].</span>")
|
||||
|
||||
if(href_list["embedded_object"] && usr.canUseTopic(src, BE_CLOSE))
|
||||
var/obj/item/bodypart/L = locate(href_list["embedded_limb"]) in bodyparts
|
||||
if(!L)
|
||||
return
|
||||
var/obj/item/I = locate(href_list["embedded_object"]) in L.embedded_objects
|
||||
if(!I || I.loc != src) //no item, no limb, or item is not in limb or in the person anymore
|
||||
return
|
||||
SEND_SIGNAL(src, COMSIG_CARBON_EMBED_RIP, I, L)
|
||||
return
|
||||
|
||||
/mob/living/carbon/fall(forced)
|
||||
loc.handle_fall(src, forced)//it's loc so it doesn't call the mob's handle_fall which does nothing
|
||||
|
||||
@@ -65,17 +65,6 @@
|
||||
throw_mode_off()
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/embed_item(obj/item/I)
|
||||
throw_alert("embeddedobject", /obj/screen/alert/embeddedobject)
|
||||
var/obj/item/bodypart/L = pick(bodyparts)
|
||||
L.embedded_objects |= I
|
||||
I.add_mob_blood(src)//it embedded itself in you, of course it's bloody!
|
||||
I.forceMove(src)
|
||||
I.embedded()
|
||||
L.receive_damage(I.w_class*I.embedding.embedded_impact_pain_multiplier)
|
||||
visible_message("<span class='danger'>[I] embeds itself in [src]'s [L.name]!</span>","<span class='userdanger'>[I] embeds itself in your [L.name]!</span>")
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded)
|
||||
|
||||
/mob/living/carbon/attacked_by(obj/item/I, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1)
|
||||
var/totitemdamage = pre_attacked_by(I, user) * damage_multiplier
|
||||
var/impacting_zone = (user == src)? check_zone(user.zone_selected) : ran_zone(user.zone_selected)
|
||||
@@ -274,6 +263,9 @@
|
||||
to_chat(M, "<span class='warning'>You can't put [p_them()] out with just your bare hands!</span>")
|
||||
return
|
||||
|
||||
if(M == src && check_self_for_injuries())
|
||||
return
|
||||
|
||||
if(health >= 0 && !(HAS_TRAIT(src, TRAIT_FAKEDEATH)))
|
||||
var/friendly_check = FALSE
|
||||
if(mob_run_block(M, 0, M.name, ATTACK_TYPE_UNARMED, 0, null, null, null))
|
||||
@@ -341,6 +333,26 @@
|
||||
update_mobility()
|
||||
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
|
||||
/// Check ourselves to see if we've got any shrapnel, return true if we do. This is a much simpler version of what humans do, we only indicate we're checking ourselves if there's actually shrapnel
|
||||
/mob/living/carbon/proc/check_self_for_injuries()
|
||||
if(stat == DEAD || stat == UNCONSCIOUS)
|
||||
return
|
||||
|
||||
var/embeds = FALSE
|
||||
for(var/X in bodyparts)
|
||||
var/obj/item/bodypart/LB = X
|
||||
for(var/obj/item/I in LB.embedded_objects)
|
||||
if(!embeds)
|
||||
embeds = TRUE
|
||||
// this way, we only visibly try to examine ourselves if we have something embedded, otherwise we'll still hug ourselves :)
|
||||
visible_message("<span class='notice'>[src] examines [p_them()]self.</span>", \
|
||||
"<span class='notice'>You check yourself for shrapnel.</span>")
|
||||
if(I.isEmbedHarmless())
|
||||
to_chat(src, "\t <a href='?src=[REF(src)];embedded_object=[REF(I)];embedded_limb=[REF(LB)]' class='warning'>There is \a [I] stuck to your [LB.name]!</a>")
|
||||
else
|
||||
to_chat(src, "\t <a href='?src=[REF(src)];embedded_object=[REF(I)];embedded_limb=[REF(LB)]' class='warning'>There is \a [I] embedded in your [LB.name]!</a>")
|
||||
|
||||
return embeds
|
||||
|
||||
/mob/living/carbon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0)
|
||||
. = ..()
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
|
||||
|
||||
/mob/living/carbon/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE)
|
||||
/mob/living/carbon/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE)
|
||||
SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMGE, damage, damagetype, def_zone)
|
||||
var/hit_percent = (100-blocked)/100
|
||||
if(!forced && hit_percent <= 0)
|
||||
return 0
|
||||
|
||||
var/obj/item/bodypart/BP = null
|
||||
if(isbodypart(def_zone)) //we specified a bodypart object
|
||||
BP = def_zone
|
||||
else
|
||||
if(!def_zone)
|
||||
def_zone = ran_zone(def_zone)
|
||||
BP = get_bodypart(check_zone(def_zone))
|
||||
if(!BP)
|
||||
BP = bodyparts[1]
|
||||
if(!spread_damage)
|
||||
if(isbodypart(def_zone)) //we specified a bodypart object
|
||||
BP = def_zone
|
||||
else
|
||||
if(!def_zone)
|
||||
def_zone = ran_zone(def_zone)
|
||||
BP = get_bodypart(check_zone(def_zone))
|
||||
if(!BP)
|
||||
BP = bodyparts[1]
|
||||
|
||||
var/damage_amount = forced ? damage : damage * hit_percent
|
||||
switch(damagetype)
|
||||
|
||||
@@ -31,14 +31,35 @@
|
||||
else if(get_bodypart(BODY_ZONE_HEAD))
|
||||
. += "<span class='deadsay'>It appears that [t_his] brain is missing...</span>"
|
||||
|
||||
var/list/missing = get_missing_limbs()
|
||||
var/list/msg = list("<span class='warning'>")
|
||||
var/list/missing = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)
|
||||
var/list/disabled = list()
|
||||
for(var/X in bodyparts)
|
||||
var/obj/item/bodypart/BP = X
|
||||
if(BP.disabled)
|
||||
disabled += BP
|
||||
missing -= BP.body_zone
|
||||
for(var/obj/item/I in BP.embedded_objects)
|
||||
if(I.isEmbedHarmless())
|
||||
msg += "<B>[t_He] [t_has] \a [icon2html(I, user)] [I] stuck to [t_his] [BP.name]!</B>\n"
|
||||
else
|
||||
msg += "<B>[t_He] [t_has] \a [icon2html(I, user)] [I] embedded in [t_his] [BP.name]!</B>\n"
|
||||
|
||||
for(var/X in disabled)
|
||||
var/obj/item/bodypart/BP = X
|
||||
var/damage_text
|
||||
if(!(BP.get_damage(include_stamina = FALSE) >= BP.max_damage)) //Stamina is disabling the limb
|
||||
damage_text = "limp and lifeless"
|
||||
else
|
||||
damage_text = (BP.brute_dam >= BP.burn_dam) ? BP.heavy_brute_msg : BP.heavy_burn_msg
|
||||
msg += "<B>[capitalize(t_his)] [BP.name] is [damage_text]!</B>\n"
|
||||
|
||||
for(var/t in missing)
|
||||
if(t==BODY_ZONE_HEAD)
|
||||
. += "<span class='deadsay'><B>[t_His] [parse_zone(t)] is missing!</B></span>"
|
||||
msg += "<span class='deadsay'><B>[t_His] [parse_zone(t)] is missing!</B></span>\n"
|
||||
continue
|
||||
. += "<span class='warning'><B>[t_His] [parse_zone(t)] is missing!</B></span>"
|
||||
msg += "<span class='warning'><B>[t_His] [parse_zone(t)] is missing!</B></span>\n"
|
||||
|
||||
var/list/msg = list()
|
||||
var/temp = getBruteLoss()
|
||||
if(!(user == src && src.hal_screwyhud == SCREWYHUD_HEALTHY)) //fake healthy
|
||||
if(temp)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
|
||||
/mob/living/carbon/human/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE)
|
||||
/mob/living/carbon/human/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage)
|
||||
// depending on the species, it will run the corresponding apply_damage code there
|
||||
return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src, forced)
|
||||
return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src, forced, spread_damage)
|
||||
|
||||
@@ -159,7 +159,10 @@
|
||||
disabled += BP
|
||||
missing -= BP.body_zone
|
||||
for(var/obj/item/I in BP.embedded_objects)
|
||||
msg += "<B>[t_He] [t_has] \a [icon2html(I, user)] [I] embedded in [t_his] [BP.name]!</B>\n"
|
||||
if(I.isEmbedHarmless())
|
||||
msg += "<B>[t_He] [t_has] \a [icon2html(I, user)] [I] stuck to [t_his] [BP.name]!</B>\n"
|
||||
else
|
||||
msg += "<B>[t_He] [t_has] \a [icon2html(I, user)] [I] embedded in [t_his] [BP.name]!</B>\n"
|
||||
|
||||
for(var/X in disabled)
|
||||
var/obj/item/bodypart/BP = X
|
||||
|
||||
@@ -222,22 +222,7 @@
|
||||
var/obj/item/I = locate(href_list["embedded_object"]) in L.embedded_objects
|
||||
if(!I || I.loc != src) //no item, no limb, or item is not in limb or in the person anymore
|
||||
return
|
||||
var/time_taken = I.embedding.embedded_unsafe_removal_time/I.w_class //Citadel Change from * to /
|
||||
usr.visible_message("<span class='warning'>[usr] attempts to remove [I] from [usr.p_their()] [L.name].</span>","<span class='notice'>You attempt to remove [I] from your [L.name]... (It will take [DisplayTimeText(time_taken)].)</span>")
|
||||
if(do_after(usr, time_taken, needhand = 1, target = src))
|
||||
remove_embedded_unsafe(L, I, usr)
|
||||
/* CITADEL EDIT: remove_embedded_unsafe replaces this code
|
||||
if(!I || !L || I.loc != src || !(I in L.embedded_objects))
|
||||
return
|
||||
L.embedded_objects -= I
|
||||
L.receive_damage(I.embedding.embedded_unsafe_removal_pain_multiplier*I.w_class)//It hurts to rip it out, get surgery you dingus.
|
||||
I.forceMove(get_turf(src))
|
||||
usr.put_in_hands(I)
|
||||
usr.emote("scream")
|
||||
usr.visible_message("[usr] successfully rips [I] out of [usr.p_their()] [L.name]!","<span class='notice'>You successfully remove [I] from your [L.name].</span>")
|
||||
if(!has_embedded_objects())
|
||||
clear_alert("embeddedobject")
|
||||
SEND_SIGNAL(usr, COMSIG_CLEAR_MOOD_EVENT, "embedded") */
|
||||
SEND_SIGNAL(src, COMSIG_CARBON_EMBED_RIP, I, L)
|
||||
return
|
||||
|
||||
if(href_list["item"])
|
||||
|
||||
@@ -52,11 +52,6 @@
|
||||
return martial_art_result
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/can_embed(obj/item/I)
|
||||
if(I.get_sharpness() || is_pointed(I) || is_type_in_typecache(I, GLOB.can_embed_types))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/carbon/human/proc/check_martial_melee_block()
|
||||
if(mind)
|
||||
if(mind.martial_art && prob(mind.martial_art.block_chance) && mind.martial_art.can_use(src) && in_throw_mode && !incapacitated(FALSE, TRUE))
|
||||
@@ -620,7 +615,10 @@
|
||||
to_send += "\t <span class='[no_damage ? "notice" : "warning"]'>Your [LB.name] [HAS_TRAIT(src, TRAIT_SELF_AWARE) ? "has" : "is"] [status].</span>\n"
|
||||
|
||||
for(var/obj/item/I in LB.embedded_objects)
|
||||
to_send += "\t <a href='?src=[REF(src)];embedded_object=[REF(I)];embedded_limb=[REF(LB)]' class='warning'>There is \a [I] embedded in your [LB.name]!</a>\n"
|
||||
if(I.isEmbedHarmless())
|
||||
to_chat(src, "\t <a href='?src=[REF(src)];embedded_object=[REF(I)];embedded_limb=[REF(LB)]' class='warning'>There is \a [I] stuck to your [LB.name]!</a>")
|
||||
else
|
||||
to_chat(src, "\t <a href='?src=[REF(src)];embedded_object=[REF(I)];embedded_limb=[REF(LB)]' class='warning'>There is \a [I] embedded in your [LB.name]!</a>")
|
||||
|
||||
for(var/t in missing)
|
||||
to_send += "<span class='boldannounce'>Your [parse_zone(t)] is missing!</span>\n"
|
||||
|
||||
@@ -18,36 +18,21 @@
|
||||
#define THERMAL_PROTECTION_HAND_LEFT 0.025
|
||||
#define THERMAL_PROTECTION_HAND_RIGHT 0.025
|
||||
|
||||
/mob/living/carbon/human/Life(seconds, times_fired)
|
||||
set invisibility = 0
|
||||
if (notransform)
|
||||
/mob/living/carbon/human/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
handle_active_genes()
|
||||
//heart attack stuff
|
||||
handle_heart()
|
||||
dna.species.spec_life(src) // for mutantraces
|
||||
return (stat != DEAD) && !QDELETED(src)
|
||||
|
||||
. = ..()
|
||||
|
||||
if (QDELETED(src))
|
||||
return 0
|
||||
|
||||
if(.) //not dead
|
||||
handle_active_genes()
|
||||
|
||||
if(stat != DEAD)
|
||||
//heart attack stuff
|
||||
handle_heart()
|
||||
|
||||
if(stat != DEAD)
|
||||
//Stuff jammed in your limbs hurts
|
||||
handle_embedded_objects()
|
||||
|
||||
/mob/living/carbon/human/PhysicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
//Update our name based on whether our face is obscured/disfigured
|
||||
name = get_visible_name()
|
||||
|
||||
dna.species.spec_life(src) // for mutantraces
|
||||
|
||||
if(stat != DEAD)
|
||||
return 1
|
||||
|
||||
|
||||
/mob/living/carbon/human/calculate_affecting_pressure(pressure)
|
||||
var/headless = !get_bodypart(BODY_ZONE_HEAD) //should the mob be perennially headless (see dullahans), we only take the suit into account, so they can into space.
|
||||
if (wear_suit && istype(wear_suit, /obj/item/clothing) && (headless || (head && istype(head, /obj/item/clothing))))
|
||||
@@ -303,25 +288,6 @@
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/handle_embedded_objects()
|
||||
for(var/X in bodyparts)
|
||||
var/obj/item/bodypart/BP = X
|
||||
for(var/obj/item/I in BP.embedded_objects)
|
||||
if(prob(I.embedding.embedded_pain_chance))
|
||||
BP.receive_damage(I.w_class*I.embedding.embedded_pain_multiplier)
|
||||
to_chat(src, "<span class='userdanger'>[I] embedded in your [BP.name] hurts!</span>")
|
||||
|
||||
if(prob(I.embedding.embedded_fall_chance))
|
||||
BP.receive_damage(I.w_class*I.embedding.embedded_fall_pain_multiplier)
|
||||
BP.embedded_objects -= I
|
||||
I.forceMove(drop_location())
|
||||
I.unembedded()
|
||||
visible_message("<span class='danger'>[I] falls out of [name]'s [BP.name]!</span>","<span class='userdanger'>[I] falls out of your [BP.name]!</span>")
|
||||
if(!has_embedded_objects())
|
||||
clear_alert("embeddedobject")
|
||||
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "embedded")
|
||||
|
||||
/mob/living/carbon/human/proc/handle_active_genes()
|
||||
if(HAS_TRAIT(src, TRAIT_MUTATION_STASIS))
|
||||
return
|
||||
|
||||
@@ -1494,12 +1494,12 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
|
||||
var/miss_chance = 100//calculate the odds that a punch misses entirely. considers stamina and brute damage of the puncher. punches miss by default to prevent weird cases
|
||||
if(user.dna.species.punchdamagelow)
|
||||
if(HAS_TRAIT(user, TRAIT_PUGILIST)) //pugilists have a flat 10% miss chance
|
||||
miss_chance = 10
|
||||
if(atk_verb == ATTACK_EFFECT_KICK) //kicks never miss (provided your species deals more than 0 damage)
|
||||
miss_chance = 0
|
||||
else if(HAS_TRAIT(user, TRAIT_PUGILIST)) //pugilists have a flat 10% miss chance
|
||||
miss_chance = 10
|
||||
else
|
||||
miss_chance = min(10 + ((puncherstam + puncherbrute)*0.5), 100) //probability of miss has a base of 10, and modified based on half brute total. Capped at max 100 to prevent weirdness in prob()
|
||||
miss_chance = min(10 + max(puncherstam * 0.5, puncherbrute * 0.5), 100) //probability of miss has a base of 10, and modified based on half brute total. Capped at max 100 to prevent weirdness in prob()
|
||||
|
||||
if(!damage || !affecting || prob(miss_chance))//future-proofing for species that have 0 damage/weird cases where no zone is targeted
|
||||
playsound(target.loc, user.dna.species.miss_sound, 25, TRUE, -1)
|
||||
@@ -1941,7 +1941,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
append_message += ", causing them to drop [target_held_item]"
|
||||
log_combat(user, target, "shoved", append_message)
|
||||
|
||||
/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE)
|
||||
/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, spread_damage = FALSE)
|
||||
SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMGE, damage, damagetype, def_zone)
|
||||
var/hit_percent = (100-(blocked+armor))/100
|
||||
hit_percent = (hit_percent * (100-H.physiology.damage_resistance))/100
|
||||
@@ -1949,20 +1949,20 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
return 0
|
||||
|
||||
var/obj/item/bodypart/BP = null
|
||||
if(isbodypart(def_zone))
|
||||
if(damagetype == STAMINA && istype(def_zone, /obj/item/bodypart/head))
|
||||
BP = H.get_bodypart(check_zone(BODY_ZONE_CHEST))
|
||||
if(!spread_damage)
|
||||
if(isbodypart(def_zone))
|
||||
if(damagetype == STAMINA && istype(def_zone, /obj/item/bodypart/head))
|
||||
BP = H.get_bodypart(check_zone(BODY_ZONE_CHEST))
|
||||
else
|
||||
BP = def_zone
|
||||
else
|
||||
BP = def_zone
|
||||
else
|
||||
if(!def_zone)
|
||||
def_zone = ran_zone(def_zone)
|
||||
if(damagetype == STAMINA && def_zone == BODY_ZONE_HEAD)
|
||||
def_zone = BODY_ZONE_CHEST
|
||||
BP = H.get_bodypart(check_zone(def_zone))
|
||||
|
||||
if(!BP)
|
||||
BP = H.bodyparts[1]
|
||||
if(!def_zone)
|
||||
def_zone = ran_zone(def_zone)
|
||||
if(damagetype == STAMINA && def_zone == BODY_ZONE_HEAD)
|
||||
def_zone = BODY_ZONE_CHEST
|
||||
BP = H.get_bodypart(check_zone(def_zone))
|
||||
if(!BP)
|
||||
BP = H.bodyparts[1]
|
||||
|
||||
switch(damagetype)
|
||||
if(BRUTE)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/datum/species/insect
|
||||
name = "Anthromorphic Insect"
|
||||
id = "insect"
|
||||
say_mod = "chitters"
|
||||
default_color = "00FF00"
|
||||
species_traits = list(LIPS,EYECOLOR,HAIR,FACEHAIR,MUTCOLORS,HORNCOLOR,WINGCOLOR)
|
||||
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BUG
|
||||
@@ -13,6 +14,7 @@
|
||||
liked_food = MEAT | FRUIT
|
||||
disliked_food = TOXIC
|
||||
icon_limbs = DEFAULT_BODYPART_ICON_CITADEL
|
||||
exotic_bloodtype = "BUG"
|
||||
|
||||
/datum/species/insect/spec_death(gibbed, mob/living/carbon/human/H)
|
||||
if(H)
|
||||
@@ -42,4 +44,4 @@
|
||||
H.update_body()
|
||||
|
||||
/datum/species/insect/qualifies_for_rank(rank, list/features)
|
||||
return TRUE
|
||||
return TRUE
|
||||
|
||||
@@ -239,7 +239,7 @@
|
||||
"<span class='notice'>You focus intently on moving your body while \
|
||||
standing perfectly still...</span>")
|
||||
|
||||
H.notransform = TRUE
|
||||
H.mob_transforming = TRUE
|
||||
|
||||
if(do_after(owner, delay=60, needhand=FALSE, target=owner, progress=TRUE))
|
||||
if(H.blood_volume >= BLOOD_VOLUME_SLIME_SPLIT)
|
||||
@@ -249,7 +249,7 @@
|
||||
else
|
||||
to_chat(H, "<span class='warning'>...but fail to stand perfectly still!</span>")
|
||||
|
||||
H.notransform = FALSE
|
||||
H.mob_transforming = FALSE
|
||||
|
||||
/datum/action/innate/split_body/proc/make_dupe()
|
||||
var/mob/living/carbon/human/H = owner
|
||||
@@ -267,7 +267,7 @@
|
||||
spare.Move(get_step(H.loc, pick(NORTH,SOUTH,EAST,WEST)))
|
||||
|
||||
H.blood_volume *= 0.45
|
||||
H.notransform = 0
|
||||
H.mob_transforming = 0
|
||||
|
||||
var/datum/species/jelly/slime/origin_datum = H.dna.species
|
||||
origin_datum.bodies |= spare
|
||||
@@ -466,7 +466,7 @@
|
||||
if(new_color)
|
||||
var/temp_hsv = RGBtoHSV(new_color)
|
||||
if(ReadHSV(temp_hsv)[3] >= ReadHSV("#7F7F7F")[3]) // mutantcolors must be bright
|
||||
H.dna.features["mcolor"] = sanitize_hexcolor(new_color)
|
||||
H.dna.features["mcolor"] = sanitize_hexcolor(new_color, 6)
|
||||
H.update_body()
|
||||
else
|
||||
to_chat(H, "<span class='notice'>Invalid color. Your color is not bright enough.</span>")
|
||||
|
||||
@@ -1,29 +1,19 @@
|
||||
/mob/living/carbon/Life()
|
||||
set invisibility = 0
|
||||
|
||||
if(notransform)
|
||||
return
|
||||
|
||||
if(damageoverlaytemp)
|
||||
damageoverlaytemp = 0
|
||||
update_damage_hud()
|
||||
|
||||
/mob/living/carbon/BiologicalLife(seconds, times_fired)
|
||||
if(stat == DEAD)
|
||||
return FALSE
|
||||
//Reagent processing needs to come before breathing, to prevent edge cases.
|
||||
handle_organs()
|
||||
|
||||
. = ..()
|
||||
|
||||
if (QDELETED(src))
|
||||
if(!(. = ..()))
|
||||
return
|
||||
|
||||
if(.) //not dead
|
||||
handle_blood()
|
||||
|
||||
handle_blood()
|
||||
// handle_blood *could* kill us.
|
||||
// we should probably have a better system for if we need to check for death or something in the future hmw
|
||||
if(stat != DEAD)
|
||||
var/bprv = handle_bodyparts()
|
||||
if(bprv & BODYPART_LIFE_UPDATE_HEALTH)
|
||||
updatehealth()
|
||||
update_stamina()
|
||||
doSprintBufferRegen()
|
||||
|
||||
if(stat != DEAD)
|
||||
handle_brain_damage()
|
||||
@@ -35,12 +25,17 @@
|
||||
stop_sound_channel(CHANNEL_HEARTBEAT)
|
||||
handle_death()
|
||||
rot()
|
||||
. = FALSE
|
||||
|
||||
//Updates the number of stored chemicals for powers
|
||||
handle_changeling()
|
||||
|
||||
if(stat != DEAD)
|
||||
return 1
|
||||
/mob/living/carbon/PhysicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if(damageoverlaytemp)
|
||||
damageoverlaytemp = 0
|
||||
update_damage_hud()
|
||||
|
||||
//Procs called while dead
|
||||
/mob/living/carbon/proc/handle_death()
|
||||
|
||||
@@ -3,30 +3,26 @@
|
||||
/mob/living/carbon/monkey
|
||||
|
||||
|
||||
/mob/living/carbon/monkey/Life()
|
||||
set invisibility = 0
|
||||
|
||||
if (notransform)
|
||||
/mob/living/carbon/monkey/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
|
||||
if(..())
|
||||
|
||||
if(!client)
|
||||
if(stat == CONSCIOUS)
|
||||
if(on_fire || buckled || restrained() || (!CHECK_MOBILITY(src, MOBILITY_STAND) && CHECK_MOBILITY(src, MOBILITY_MOVE))) //CIT CHANGE - makes it so monkeys attempt to resist if they're resting)
|
||||
if(!resisting && prob(MONKEY_RESIST_PROB))
|
||||
resisting = TRUE
|
||||
walk_to(src,0)
|
||||
resist()
|
||||
else if(resisting)
|
||||
resisting = FALSE
|
||||
else if((mode == MONKEY_IDLE && !pickupTarget && !prob(MONKEY_SHENANIGAN_PROB)) || !handle_combat())
|
||||
if(prob(25) && CHECK_MOBILITY(src, MOBILITY_MOVE) && isturf(loc) && !pulledby)
|
||||
step(src, pick(GLOB.cardinals))
|
||||
else if(prob(1))
|
||||
emote(pick("scratch","jump","roll","tail"))
|
||||
else
|
||||
if(client)
|
||||
return
|
||||
if(stat == CONSCIOUS)
|
||||
if(on_fire || buckled || restrained() || (!CHECK_MOBILITY(src, MOBILITY_STAND) && CHECK_MOBILITY(src, MOBILITY_MOVE))) //CIT CHANGE - makes it so monkeys attempt to resist if they're resting)
|
||||
if(!resisting && prob(MONKEY_RESIST_PROB))
|
||||
resisting = TRUE
|
||||
walk_to(src,0)
|
||||
resist()
|
||||
else if(resisting)
|
||||
resisting = FALSE
|
||||
else if((mode == MONKEY_IDLE && !pickupTarget && !prob(MONKEY_SHENANIGAN_PROB)) || !handle_combat())
|
||||
if(prob(25) && CHECK_MOBILITY(src, MOBILITY_MOVE) && isturf(loc) && !pulledby)
|
||||
step(src, pick(GLOB.cardinals))
|
||||
else if(prob(1))
|
||||
emote(pick("scratch","jump","roll","tail"))
|
||||
else
|
||||
walk_to(src,0)
|
||||
|
||||
/mob/living/carbon/monkey/handle_mutations_and_radiation()
|
||||
if(radiation)
|
||||
|
||||
@@ -31,11 +31,12 @@
|
||||
if(relic_mask)
|
||||
equip_to_slot_or_del(new relic_mask, SLOT_WEAR_MASK)
|
||||
|
||||
/mob/living/carbon/monkey/punpun/Life()
|
||||
/mob/living/carbon/monkey/punpun/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
|
||||
Write_Memory(FALSE, FALSE)
|
||||
memory_saved = TRUE
|
||||
..()
|
||||
|
||||
/mob/living/carbon/monkey/punpun/death(gibbed)
|
||||
if(!memory_saved)
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
overlays_standing[cache_index] = null
|
||||
|
||||
/mob/living/carbon/regenerate_icons()
|
||||
if(notransform)
|
||||
if(mob_transforming)
|
||||
return 1
|
||||
update_inv_hands()
|
||||
update_inv_handcuffed()
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
|
||||
/*
|
||||
apply_damage(a,b,c)
|
||||
args
|
||||
a:damage - How much damage to take
|
||||
b:damage_type - What type of damage to take, brute, burn
|
||||
c:def_zone - Where to take the damage if its brute or burn
|
||||
Returns
|
||||
standard 0 if fail
|
||||
*/
|
||||
/mob/living/proc/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE)
|
||||
/**
|
||||
* Applies damage to this mob
|
||||
*
|
||||
* Sends [COMSIG_MOB_APPLY_DAMGE]
|
||||
*
|
||||
* Arguuments:
|
||||
* * damage - amount of damage
|
||||
* * damagetype - one of [BRUTE], [BURN], [TOX], [OXY], [CLONE], [STAMINA]
|
||||
* * def_zone - zone that is being hit if any
|
||||
* * blocked - armor value applied
|
||||
* * forced - bypass hit percentage
|
||||
* * spread_damage - used in overrides
|
||||
*
|
||||
* Returns TRUE if damage applied
|
||||
*/
|
||||
/mob/living/proc/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE)
|
||||
var/hit_percent = (100-blocked)/100
|
||||
if(!damage || (hit_percent <= 0))
|
||||
return 0
|
||||
|
||||
@@ -457,6 +457,7 @@
|
||||
message = params
|
||||
if(type_override)
|
||||
emote_type = type_override
|
||||
message = user.say_emphasis(message)
|
||||
. = ..()
|
||||
message = null
|
||||
emote_type = EMOTE_VISIBLE
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
/**
|
||||
* Called by SSmobs at (hopefully) an interval of 1 second.
|
||||
* Splits off into PhysicalLife() and BiologicalLife(). Override those instead of this.
|
||||
*/
|
||||
/mob/living/proc/Life(seconds, times_fired)
|
||||
set waitfor = FALSE
|
||||
set invisibility = 0
|
||||
set waitfor = FALSE // yeah hey we're kind of on a subsystem, no sleeping will be tolerated here!
|
||||
if(mob_transforming)
|
||||
return
|
||||
|
||||
if(digitalinvis)
|
||||
handle_diginvis() //AI becomes unable to see mob
|
||||
. = SEND_SIGNAL(src, COMSIG_LIVING_LIFE, seconds, times_fired)
|
||||
if(!(. & COMPONENT_INTERRUPT_LIFE_PHYSICAL))
|
||||
PhysicalLife(seconds, times_fired)
|
||||
if(!(. & COMPONENT_INTERRUPT_LIFE_BIOLOGICAL))
|
||||
BiologicalLife(seconds, times_fired)
|
||||
|
||||
if((movement_type & FLYING) && !(movement_type & FLOATING)) //TODO: Better floating
|
||||
float(on = TRUE)
|
||||
// CODE BELOW SHOULD ONLY BE THINGS THAT SHOULD HAPPEN NO MATTER WHAT AND CAN NOT BE SUSPENDED!
|
||||
// Otherwise, it goes into one of the two split Life procs!
|
||||
|
||||
if (client)
|
||||
var/turf/T = get_turf(src)
|
||||
@@ -30,28 +38,54 @@
|
||||
log_game("Z-TRACKING: [src] of type [src.type] has a Z-registration despite not having a client.")
|
||||
update_z(null)
|
||||
|
||||
if (notransform)
|
||||
return
|
||||
if(!loc)
|
||||
return
|
||||
var/datum/gas_mixture/environment = loc.return_air()
|
||||
|
||||
if(stat != DEAD)
|
||||
//Mutations and radiation
|
||||
handle_mutations_and_radiation()
|
||||
|
||||
if(stat != DEAD)
|
||||
//Breathing, if applicable
|
||||
handle_breathing(times_fired)
|
||||
|
||||
/**
|
||||
* Handles biological life processes like chemical metabolism, breathing, etc
|
||||
* Returns TRUE or FALSE based on if we were interrupted. This is used by overridden variants to check if they should stop.
|
||||
*/
|
||||
/mob/living/proc/BiologicalLife(seconds, times_fired)
|
||||
handle_diseases()// DEAD check is in the proc itself; we want it to spread even if the mob is dead, but to handle its disease-y properties only if you're not.
|
||||
|
||||
if (QDELETED(src)) // diseases can qdel the mob via transformations
|
||||
return
|
||||
// Everything after this shouldn't process while dead (as of the time of writing)
|
||||
if(stat == DEAD)
|
||||
return FALSE
|
||||
|
||||
if(stat != DEAD)
|
||||
//Random events (vomiting etc)
|
||||
handle_random_events()
|
||||
//Mutations and radiation
|
||||
handle_mutations_and_radiation()
|
||||
|
||||
//Breathing, if applicable
|
||||
handle_breathing(times_fired)
|
||||
|
||||
if (QDELETED(src)) // diseases can qdel the mob via transformations
|
||||
return FALSE
|
||||
|
||||
//Random events (vomiting etc)
|
||||
handle_random_events()
|
||||
|
||||
//stuff in the stomach
|
||||
handle_stomach()
|
||||
|
||||
handle_block_parry(seconds)
|
||||
|
||||
// These two MIGHT need to be moved to base Life() if we get any in the future that's a "physical" effect that needs to fire even while in stasis.
|
||||
handle_traits() // eye, ear, brain damages
|
||||
handle_status_effects() //all special effects, stun, knockdown, jitteryness, hallucination, sleeping, etc
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Handles physical life processes like being on fire. Don't ask why this is considered "Life".
|
||||
* Returns TRUE or FALSE based on if we were interrupted. This is used by overridden variants to check if they should stop.
|
||||
*/
|
||||
/mob/living/proc/PhysicalLife(seconds, times_fired)
|
||||
if(digitalinvis)
|
||||
handle_diginvis() //AI becomes unable to see mob
|
||||
|
||||
if((movement_type & FLYING) && !(movement_type & FLOATING)) //TODO: Better floating
|
||||
float(on = TRUE)
|
||||
|
||||
if(!loc)
|
||||
return FALSE
|
||||
|
||||
var/datum/gas_mixture/environment = loc.return_air()
|
||||
|
||||
//Handle temperature/pressure differences between body and environment
|
||||
if(environment)
|
||||
@@ -59,23 +93,11 @@
|
||||
|
||||
handle_fire()
|
||||
|
||||
//stuff in the stomach
|
||||
handle_stomach()
|
||||
|
||||
handle_gravity()
|
||||
|
||||
handle_block_parry(seconds)
|
||||
|
||||
if(machine)
|
||||
machine.check_eye(src)
|
||||
|
||||
if(stat != DEAD)
|
||||
handle_traits() // eye, ear, brain damages
|
||||
if(stat != DEAD)
|
||||
handle_status_effects() //all special effects, stun, knockdown, jitteryness, hallucination, sleeping, etc
|
||||
|
||||
if(stat != DEAD)
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/mob/living/proc/handle_breathing(times_fired)
|
||||
return
|
||||
@@ -168,4 +190,4 @@
|
||||
/mob/living/proc/handle_high_gravity(gravity)
|
||||
if(gravity >= GRAVITY_DAMAGE_TRESHOLD) //Aka gravity values of 3 or more
|
||||
var/grav_stregth = gravity - GRAVITY_DAMAGE_TRESHOLD
|
||||
adjustBruteLoss(min(grav_stregth,3))
|
||||
adjustBruteLoss(min(grav_stregth,3))
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
|
||||
/mob/living/proc/run_armor_check(def_zone = null, attack_flag = "melee", absorb_text = "Your armor absorbs the blow!", soften_text = "Your armor softens the blow!", armour_penetration, penetrated_text = "Your armor was penetrated!")
|
||||
/mob/living/proc/run_armor_check(def_zone = null, attack_flag = "melee", absorb_text = "Your armor absorbs the blow!", soften_text = "Your armor softens the blow!", armour_penetration, penetrated_text = "Your armor was penetrated!", silent=FALSE)
|
||||
var/armor = getarmor(def_zone, attack_flag)
|
||||
|
||||
if(silent)
|
||||
return max(0, armor - armour_penetration)
|
||||
|
||||
//the if "armor" check is because this is used for everything on /living, including humans
|
||||
if(armor && armour_penetration)
|
||||
armor = max(0, armor - armour_penetration)
|
||||
@@ -105,12 +108,6 @@
|
||||
/mob/living/proc/catch_item(obj/item/I, skip_throw_mode_check = FALSE)
|
||||
return FALSE
|
||||
|
||||
/mob/living/proc/embed_item(obj/item/I)
|
||||
return
|
||||
|
||||
/mob/living/proc/can_embed(obj/item/I)
|
||||
return FALSE
|
||||
|
||||
/mob/living/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
|
||||
// Throwingdatum can be null if someone had an accident() while slipping with an item in hand.
|
||||
var/obj/item/I
|
||||
@@ -126,30 +123,17 @@
|
||||
skipcatch = TRUE
|
||||
blocked = TRUE
|
||||
total_damage = block_calculate_resultant_damage(total_damage, block_return)
|
||||
else if(I && I.throw_speed >= EMBED_THROWSPEED_THRESHOLD && can_embed(I, src) && prob(I.embedding.embed_chance) && !HAS_TRAIT(src, TRAIT_PIERCEIMMUNE) && (!HAS_TRAIT(src, TRAIT_AUTO_CATCH_ITEM) || incapacitated() || get_active_held_item()))
|
||||
embed_item(I)
|
||||
hitpush = FALSE
|
||||
skipcatch = TRUE //can't catch the now embedded item
|
||||
if(I)
|
||||
var/nosell_hit = SEND_SIGNAL(I, COMSIG_MOVABLE_IMPACT_ZONE, src, impacting_zone, throwingdatum, FALSE, blocked)
|
||||
if(nosell_hit)
|
||||
skipcatch = TRUE
|
||||
hitpush = FALSE
|
||||
if(!skipcatch && isturf(I.loc) && catch_item(I))
|
||||
return TRUE
|
||||
var/dtype = BRUTE
|
||||
var/volume = I.get_volume_by_throwforce_and_or_w_class()
|
||||
SEND_SIGNAL(I, COMSIG_MOVABLE_IMPACT_ZONE, src, impacting_zone)
|
||||
|
||||
dtype = I.damtype
|
||||
|
||||
if (I.throwforce > 0) //If the weapon's throwforce is greater than zero...
|
||||
if (I.throwhitsound) //...and throwhitsound is defined...
|
||||
playsound(loc, I.throwhitsound, volume, 1, -1) //...play the weapon's throwhitsound.
|
||||
else if(I.hitsound) //Otherwise, if the weapon's hitsound is defined...
|
||||
playsound(loc, I.hitsound, volume, 1, -1) //...play the weapon's hitsound.
|
||||
else if(!I.throwhitsound) //Otherwise, if throwhitsound isn't defined...
|
||||
playsound(loc, 'sound/weapons/genhit.ogg',volume, 1, -1) //...play genhit.ogg.
|
||||
|
||||
else if(!I.throwhitsound && I.throwforce > 0) //Otherwise, if the item doesn't have a throwhitsound and has a throwforce greater than zero...
|
||||
playsound(loc, 'sound/weapons/genhit.ogg', volume, 1, -1)//...play genhit.ogg
|
||||
if(!I.throwforce)// Otherwise, if the item's throwforce is 0...
|
||||
playsound(loc, 'sound/weapons/throwtap.ogg', 1, volume, -1)//...play throwtap.ogg.
|
||||
if(!blocked)
|
||||
visible_message("<span class='danger'>[src] has been hit by [I].</span>", \
|
||||
"<span class='userdanger'>You have been hit by [I].</span>")
|
||||
|
||||
@@ -3,48 +3,48 @@
|
||||
#define POWER_RESTORATION_SEARCH_APC 2
|
||||
#define POWER_RESTORATION_APC_FOUND 3
|
||||
|
||||
/mob/living/silicon/ai/Life()
|
||||
if (stat == DEAD)
|
||||
/mob/living/silicon/ai/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
else //I'm not removing that shitton of tabs, unneeded as they are. -- Urist
|
||||
//I'm not removing that shitton of tabs, unneeded as they are. -- Urist
|
||||
//Being dead doesn't mean your temperature never changes
|
||||
|
||||
update_gravity(mob_has_gravity())
|
||||
update_gravity(mob_has_gravity())
|
||||
|
||||
handle_status_effects()
|
||||
handle_status_effects()
|
||||
|
||||
if(malfhack && malfhack.aidisabled)
|
||||
deltimer(malfhacking)
|
||||
// This proc handles cleanup of screen notifications and
|
||||
// messenging the client
|
||||
malfhacked(malfhack)
|
||||
if(malfhack && malfhack.aidisabled)
|
||||
deltimer(malfhacking)
|
||||
// This proc handles cleanup of screen notifications and
|
||||
// messenging the client
|
||||
malfhacked(malfhack)
|
||||
|
||||
if(isturf(loc) && (QDELETED(eyeobj) || !eyeobj.loc))
|
||||
view_core()
|
||||
if(isturf(loc) && (QDELETED(eyeobj) || !eyeobj.loc))
|
||||
view_core()
|
||||
|
||||
if(machine)
|
||||
machine.check_eye(src)
|
||||
if(machine)
|
||||
machine.check_eye(src)
|
||||
|
||||
// Handle power damage (oxy)
|
||||
if(aiRestorePowerRoutine)
|
||||
// Lost power
|
||||
adjustOxyLoss(1)
|
||||
else
|
||||
// Gain Power
|
||||
if(getOxyLoss())
|
||||
adjustOxyLoss(-1)
|
||||
// Handle power damage (oxy)
|
||||
if(aiRestorePowerRoutine)
|
||||
// Lost power
|
||||
adjustOxyLoss(1)
|
||||
else
|
||||
// Gain Power
|
||||
if(getOxyLoss())
|
||||
adjustOxyLoss(-1)
|
||||
|
||||
if(!lacks_power())
|
||||
var/area/home = get_area(src)
|
||||
if(home.powered(EQUIP))
|
||||
home.use_power(1000, EQUIP)
|
||||
if(!lacks_power())
|
||||
var/area/home = get_area(src)
|
||||
if(home.powered(EQUIP))
|
||||
home.use_power(1000, EQUIP)
|
||||
|
||||
if(aiRestorePowerRoutine >= POWER_RESTORATION_SEARCH_APC)
|
||||
ai_restore_power()
|
||||
return
|
||||
if(aiRestorePowerRoutine >= POWER_RESTORATION_SEARCH_APC)
|
||||
ai_restore_power()
|
||||
return
|
||||
|
||||
else if(!aiRestorePowerRoutine)
|
||||
ai_lose_power()
|
||||
else if(!aiRestorePowerRoutine)
|
||||
ai_lose_power()
|
||||
|
||||
/mob/living/silicon/ai/proc/lacks_power()
|
||||
var/turf/T = get_turf(src)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
/mob/living/silicon/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE)
|
||||
/mob/living/silicon/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE)
|
||||
var/hit_percent = (100-blocked)/100
|
||||
if(!damage || (!forced && hit_percent <= 0))
|
||||
return 0
|
||||
|
||||
@@ -146,10 +146,11 @@
|
||||
if(possible_chassis[chassis])
|
||||
AddElement(/datum/element/mob_holder, chassis, 'icons/mob/pai_item_head.dmi', 'icons/mob/pai_item_rh.dmi', 'icons/mob/pai_item_lh.dmi', ITEM_SLOT_HEAD)
|
||||
|
||||
/mob/living/silicon/pai/Life()
|
||||
/mob/living/silicon/pai/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if(hacking)
|
||||
process_hack()
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/pai/proc/process_hack()
|
||||
|
||||
@@ -282,17 +283,19 @@
|
||||
. = ..()
|
||||
. += "A personal AI in holochassis mode. Its master ID string seems to be [master]."
|
||||
|
||||
/mob/living/silicon/pai/Life()
|
||||
if(stat == DEAD)
|
||||
return
|
||||
/mob/living/silicon/pai/PhysicalLife()
|
||||
. = ..()
|
||||
if(cable)
|
||||
if(get_dist(src, cable) > 1)
|
||||
var/turf/T = get_turf(src.loc)
|
||||
T.visible_message("<span class='warning'>[src.cable] rapidly retracts back into its spool.</span>", "<span class='italics'>You hear a click and the sound of wire spooling rapidly.</span>")
|
||||
qdel(src.cable)
|
||||
cable = null
|
||||
|
||||
/mob/living/silicon/pai/BiologicalLife()
|
||||
if(!(. = ..()))
|
||||
return
|
||||
silent = max(silent - 1, 0)
|
||||
. = ..()
|
||||
|
||||
/mob/living/silicon/pai/updatehealth()
|
||||
if(status_flags & GODMODE)
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
/mob/living/silicon/robot/Life()
|
||||
set invisibility = 0
|
||||
if (src.notransform)
|
||||
/mob/living/silicon/robot/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
|
||||
..()
|
||||
adjustOxyLoss(-10) //we're a robot!
|
||||
handle_robot_hud_updates()
|
||||
handle_robot_cell()
|
||||
|
||||
@@ -259,7 +259,7 @@
|
||||
var/prev_locked_down = R.locked_down
|
||||
sleep(1)
|
||||
flick("[cyborg_base_icon]_transform", R)
|
||||
R.notransform = TRUE
|
||||
R.mob_transforming = TRUE
|
||||
R.SetLockdown(1)
|
||||
R.anchored = TRUE
|
||||
sleep(1)
|
||||
@@ -270,7 +270,7 @@
|
||||
R.SetLockdown(0)
|
||||
R.setDir(SOUTH)
|
||||
R.anchored = FALSE
|
||||
R.notransform = FALSE
|
||||
R.mob_transforming = FALSE
|
||||
R.update_headlamp()
|
||||
R.notify_ai(NEW_MODULE)
|
||||
if(R.hud_used)
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
log_reagent("FERMICHEM: [src] has astrally transmitted [message] into [A]")
|
||||
|
||||
//Delete the mob if there's no mind! Pay that mob no mind.
|
||||
/mob/living/simple_animal/astral/Life()
|
||||
if(!mind)
|
||||
qdel(src)
|
||||
/mob/living/simple_animal/astral/PhysicalLife(seconds, times_fired)
|
||||
. = ..()
|
||||
if(!mind && !QDELETED(src))
|
||||
qdel(src)
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
//MEDBOT
|
||||
//MEDBOT PATHFINDING
|
||||
//MEDBOT ASSEMBLY
|
||||
|
||||
#define MEDBOT_PANIC_NONE 0
|
||||
#define MEDBOT_PANIC_LOW 15
|
||||
#define MEDBOT_PANIC_MED 35
|
||||
#define MEDBOT_PANIC_HIGH 55
|
||||
#define MEDBOT_PANIC_FUCK 70
|
||||
#define MEDBOT_PANIC_ENDING 90
|
||||
#define MEDBOT_PANIC_END 100
|
||||
|
||||
/mob/living/simple_animal/bot/medbot
|
||||
name = "\improper Medibot"
|
||||
@@ -64,6 +70,13 @@
|
||||
var/upgraded_dispenser_3 //Do we have the nicer chemicals? - replaces bic with sal acid
|
||||
var/upgraded_dispenser_4 //Do we have the nicer chemicals? - replaces charcoal/toxin with pentetic acid / pentetic jelly
|
||||
|
||||
//How panicked we are about being tipped over (why would you do this?)
|
||||
var/tipped_status = MEDBOT_PANIC_NONE
|
||||
//The name we got when we were tipped
|
||||
var/tipper_name
|
||||
//The last time we were tipped/righted and said a voice line, to avoid spam
|
||||
var/last_tipping_action_voice = 0
|
||||
|
||||
/mob/living/simple_animal/bot/medbot/mysterious
|
||||
name = "\improper Mysterious Medibot"
|
||||
desc = "International Medibot of mystery."
|
||||
@@ -373,10 +386,91 @@
|
||||
else
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/bot/medbot/proc/tip_over(mob/user)
|
||||
mobility_flags &= ~MOBILITY_MOVE
|
||||
playsound(src, 'sound/machines/warning-buzzer.ogg', 50)
|
||||
user.visible_message("<span class='danger'>[user] tips over [src]!</span>", "<span class='danger'>You tip [src] over!</span>")
|
||||
mode = BOT_TIPPED
|
||||
var/matrix/mat = transform
|
||||
transform = mat.Turn(180)
|
||||
|
||||
/mob/living/simple_animal/bot/medbot/proc/set_right(mob/user)
|
||||
mobility_flags &= MOBILITY_MOVE
|
||||
var/list/messagevoice
|
||||
if(user)
|
||||
user.visible_message("<span class='notice'>[user] sets [src] right-side up!</span>", "<span class='green'>You set [src] right-side up!</span>")
|
||||
if(user.name == tipper_name)
|
||||
messagevoice = list("I forgive you." = 'sound/voice/medbot/forgive.ogg')
|
||||
else
|
||||
messagevoice = list("Thank you!" = 'sound/voice/medbot/thank_you.ogg', "You are a good person." = 'sound/voice/medbot/youre_good.ogg')
|
||||
else
|
||||
visible_message("<span class='notice'>[src] manages to writhe wiggle enough to right itself.</span>")
|
||||
messagevoice = list("Fuck you." = 'sound/voice/medbot/fuck_you.ogg', "Your behavior has been reported, have a nice day." = 'sound/voice/medbot/reported.ogg')
|
||||
|
||||
tipper_name = null
|
||||
if(world.time > last_tipping_action_voice + 15 SECONDS)
|
||||
last_tipping_action_voice = world.time
|
||||
var/message = pick(messagevoice)
|
||||
speak(message)
|
||||
playsound(src, messagevoice[message], 70)
|
||||
tipped_status = MEDBOT_PANIC_NONE
|
||||
mode = BOT_IDLE
|
||||
transform = matrix()
|
||||
|
||||
// if someone tipped us over, check whether we should ask for help or just right ourselves eventually
|
||||
/mob/living/simple_animal/bot/medbot/proc/handle_panic()
|
||||
tipped_status++
|
||||
var/list/messagevoice
|
||||
switch(tipped_status)
|
||||
if(MEDBOT_PANIC_LOW)
|
||||
messagevoice = list("I require assistance." = 'sound/voice/medbot/i_require_asst.ogg')
|
||||
if(MEDBOT_PANIC_MED)
|
||||
messagevoice = list("Please put me back." = 'sound/voice/medbot/please_put_me_back.ogg')
|
||||
if(MEDBOT_PANIC_HIGH)
|
||||
messagevoice = list("Please, I am scared!" = 'sound/voice/medbot/please_im_scared.ogg')
|
||||
if(MEDBOT_PANIC_FUCK)
|
||||
messagevoice = list("I don't like this, I need help!" = 'sound/voice/medbot/dont_like.ogg', "This hurts, my pain is real!" = 'sound/voice/medbot/pain_is_real.ogg')
|
||||
if(MEDBOT_PANIC_ENDING)
|
||||
messagevoice = list("Is this the end?" = 'sound/voice/medbot/is_this_the_end.ogg', "Nooo!" = 'sound/voice/medbot/nooo.ogg')
|
||||
if(MEDBOT_PANIC_END)
|
||||
speak("PSYCH ALERT: Crewmember [tipper_name] recorded displaying antisocial tendencies torturing bots in [get_area(src)]. Please schedule psych evaluation.", radio_channel)
|
||||
set_right() // strong independent medbot
|
||||
|
||||
if(prob(tipped_status))
|
||||
do_jitter_animation(tipped_status * 0.1)
|
||||
|
||||
if(messagevoice)
|
||||
var/message = pick(messagevoice)
|
||||
speak(message)
|
||||
playsound(src, messagevoice[message], 70)
|
||||
else if(prob(tipped_status * 0.2))
|
||||
playsound(src, 'sound/machines/warning-buzzer.ogg', 30, extrarange=-2)
|
||||
|
||||
/mob/living/simple_animal/bot/medbot/examine(mob/user)
|
||||
. = ..()
|
||||
if(tipped_status == MEDBOT_PANIC_NONE)
|
||||
return
|
||||
|
||||
switch(tipped_status)
|
||||
if(MEDBOT_PANIC_NONE to MEDBOT_PANIC_LOW)
|
||||
. += "It appears to be tipped over, and is quietly waiting for someone to set it right."
|
||||
if(MEDBOT_PANIC_LOW to MEDBOT_PANIC_MED)
|
||||
. += "It is tipped over and requesting help."
|
||||
if(MEDBOT_PANIC_MED to MEDBOT_PANIC_HIGH)
|
||||
. += "They are tipped over and appear visibly distressed." // now we humanize the medbot as a they, not an it
|
||||
if(MEDBOT_PANIC_HIGH to MEDBOT_PANIC_FUCK)
|
||||
. += "<span class='warning'>They are tipped over and visibly panicking!</span>"
|
||||
if(MEDBOT_PANIC_FUCK to INFINITY)
|
||||
. += "<span class='warning'><b>They are freaking out from being tipped over!</b></span>"
|
||||
|
||||
/mob/living/simple_animal/bot/medbot/handle_automated_action()
|
||||
if(!..())
|
||||
return
|
||||
|
||||
if(mode == BOT_TIPPED)
|
||||
handle_panic()
|
||||
return
|
||||
|
||||
if(mode == BOT_HEALING)
|
||||
return
|
||||
|
||||
@@ -392,10 +486,14 @@
|
||||
|
||||
if(QDELETED(patient))
|
||||
if(!shut_up && prob(1))
|
||||
var/list/messagevoice = list("Radar, put a mask on!" = 'sound/voice/medbot/radar.ogg',"There's always a catch, and I'm the best there is." = 'sound/voice/medbot/catch.ogg',"I knew it, I should've been a plastic surgeon." = 'sound/voice/medbot/surgeon.ogg',"What kind of medbay is this? Everyone's dropping like flies." = 'sound/voice/medbot/flies.ogg',"Delicious!" = 'sound/voice/medbot/delicious.ogg')
|
||||
var/message = pick(messagevoice)
|
||||
speak(message)
|
||||
playsound(loc, messagevoice[message], 50, 0)
|
||||
if(emagged && prob(30))
|
||||
var/list/i_need_scissors = list('sound/voice/medbot/fuck_you.ogg', 'sound/voice/medbot/turn_off.ogg', 'sound/voice/medbot/im_different.ogg', 'sound/voice/medbot/close.ogg', 'sound/voice/medbot/shindemashou.ogg')
|
||||
playsound(src, pick(i_need_scissors), 70)
|
||||
else
|
||||
var/list/messagevoice = list("Radar, put a mask on!" = 'sound/voice/medbot/radar.ogg',"There's always a catch, and I'm the best there is." = 'sound/voice/medbot/catch.ogg',"I knew it, I should've been a plastic surgeon." = 'sound/voice/medbot/surgeon.ogg',"What kind of medbay is this? Everyone's dropping like flies." = 'sound/voice/medbot/flies.ogg',"Delicious!" = 'sound/voice/medbot/delicious.ogg', "Why are we still here? Just to suffer?" = 'sound/voice/medbot/why.ogg')
|
||||
var/message = pick(messagevoice)
|
||||
speak(message)
|
||||
playsound(src, messagevoice[message], 50)
|
||||
var/scan_range = (stationary_mode ? 1 : DEFAULT_SCAN_RANGE) //If in stationary mode, scan range is limited to adjacent patients.
|
||||
patient = scan(/mob/living/carbon/human, oldpatient, scan_range)
|
||||
oldpatient = patient
|
||||
@@ -506,6 +604,27 @@
|
||||
/mob/living/simple_animal/bot/medbot/proc/get_healchem_toxin(mob/M)
|
||||
return HAS_TRAIT(M, TRAIT_TOXINLOVER)? treatment_tox_toxlover : treatment_tox
|
||||
|
||||
/mob/living/simple_animal/bot/medbot/attack_hand(mob/living/carbon/human/H)
|
||||
if(H.a_intent == INTENT_DISARM && mode != BOT_TIPPED)
|
||||
H.visible_message("<span class='danger'>[H] begins tipping over [src].</span>", "<span class='warning'>You begin tipping over [src]...</span>")
|
||||
|
||||
if(world.time > last_tipping_action_voice + 15 SECONDS)
|
||||
last_tipping_action_voice = world.time // message for tipping happens when we start interacting, message for righting comes after finishing
|
||||
var/list/messagevoice = list("Hey, wait..." = 'sound/voice/medbot/hey_wait.ogg',"Please don't..." = 'sound/voice/medbot/please_dont.ogg',"I trusted you..." = 'sound/voice/medbot/i_trusted_you.ogg', "Nooo..." = 'sound/voice/medbot/nooo.ogg', "Oh fuck-" = 'sound/voice/medbot/oh_fuck.ogg')
|
||||
var/message = pick(messagevoice)
|
||||
speak(message)
|
||||
playsound(src, messagevoice[message], 70, FALSE)
|
||||
|
||||
if(do_after(H, 3 SECONDS, target=src))
|
||||
tip_over(H)
|
||||
|
||||
else if(H.a_intent == INTENT_HELP && mode == BOT_TIPPED)
|
||||
H.visible_message("<span class='notice'>[H] begins righting [src].</span>", "<span class='notice'>You begin righting [src]...</span>")
|
||||
if(do_after(H, 3 SECONDS, target=src))
|
||||
set_right(H)
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/bot/medbot/UnarmedAttack(atom/A)
|
||||
if(iscarbon(A))
|
||||
var/mob/living/carbon/C = A
|
||||
@@ -664,3 +783,11 @@
|
||||
|
||||
/obj/machinery/bot_core/medbot
|
||||
req_one_access = list(ACCESS_MEDICAL, ACCESS_ROBOTICS)
|
||||
|
||||
#undef MEDBOT_PANIC_NONE
|
||||
#undef MEDBOT_PANIC_LOW
|
||||
#undef MEDBOT_PANIC_MED
|
||||
#undef MEDBOT_PANIC_HIGH
|
||||
#undef MEDBOT_PANIC_FUCK
|
||||
#undef MEDBOT_PANIC_ENDING
|
||||
#undef MEDBOT_PANIC_END
|
||||
@@ -115,13 +115,14 @@
|
||||
Read_Memory()
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_animal/pet/cat/Runtime/Life()
|
||||
/mob/living/simple_animal/pet/cat/Runtime/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if(!cats_deployed && SSticker.current_state >= GAME_STATE_SETTING_UP)
|
||||
Deploy_The_Cats()
|
||||
if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
|
||||
Write_Memory()
|
||||
memory_saved = TRUE
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/pet/cat/Runtime/make_babies()
|
||||
var/mob/baby = ..()
|
||||
@@ -177,7 +178,9 @@
|
||||
gold_core_spawnable = NO_SPAWN
|
||||
unique_pet = TRUE
|
||||
|
||||
/mob/living/simple_animal/pet/cat/Life()
|
||||
/mob/living/simple_animal/pet/cat/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if(!stat && !buckled && !client)
|
||||
if(prob(1))
|
||||
emote("me", EMOTE_VISIBLE, pick("stretches out for a belly rub.", "wags its tail.", "lies down."))
|
||||
@@ -269,8 +272,9 @@
|
||||
to_chat(src, "<span class='notice'>Your name is now <b>\"new_name\"</b>!</span>")
|
||||
name = new_name
|
||||
|
||||
/mob/living/simple_animal/pet/cat/cak/Life()
|
||||
..()
|
||||
/mob/living/simple_animal/pet/cat/cak/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if(stat)
|
||||
return
|
||||
if(health < maxHealth)
|
||||
|
||||
@@ -27,8 +27,9 @@
|
||||
var/obj/item/inventory_mask
|
||||
gold_core_spawnable = FRIENDLY_SPAWN
|
||||
|
||||
/mob/living/simple_animal/crab/Life()
|
||||
..()
|
||||
/mob/living/simple_animal/crab/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
//CRAB movement
|
||||
if(!ckey && !stat)
|
||||
if(isturf(loc) && !resting && !buckled) //This is so it only moves if it's not inside a closet, gentics machine, etc.
|
||||
|
||||
@@ -366,11 +366,12 @@
|
||||
RemoveElement(/datum/element/mob_holder, held_icon)
|
||||
AddElement(/datum/element/mob_holder, "old_corgi")
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/Ian/Life()
|
||||
/mob/living/simple_animal/pet/dog/corgi/Ian/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
|
||||
Write_Memory(FALSE)
|
||||
memory_saved = TRUE
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/Ian/death()
|
||||
if(!memory_saved)
|
||||
@@ -419,8 +420,9 @@
|
||||
fdel(json_file)
|
||||
WRITE_FILE(json_file, json_encode(file_data))
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/Ian/Life()
|
||||
..()
|
||||
/mob/living/simple_animal/pet/dog/corgi/Ian/BiologicalLife()
|
||||
if(!(. = ..()))
|
||||
return
|
||||
|
||||
//Feeding, chasing food, FOOOOODDDD
|
||||
if(!stat && CHECK_MULTIPLE_BITFIELDS(mobility_flags, MOBILITY_STAND|MOBILITY_MOVE) && !buckled)
|
||||
@@ -490,8 +492,9 @@
|
||||
nofur = TRUE
|
||||
unique_pet = TRUE
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/narsie/Life()
|
||||
..()
|
||||
/mob/living/simple_animal/pet/dog/corgi/narsie/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
for(var/mob/living/simple_animal/pet/P in range(1, src))
|
||||
if(P != src && prob(5))
|
||||
visible_message("<span class='warning'>[src] devours [P]!</span>", \
|
||||
@@ -615,8 +618,9 @@
|
||||
return
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/Lisa/Life()
|
||||
..()
|
||||
/mob/living/simple_animal/pet/dog/corgi/Lisa/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
|
||||
make_babies()
|
||||
|
||||
@@ -628,8 +632,9 @@
|
||||
setDir(i)
|
||||
sleep(1)
|
||||
|
||||
/mob/living/simple_animal/pet/dog/pug/Life()
|
||||
..()
|
||||
/mob/living/simple_animal/pet/dog/pug/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if(!stat && CHECK_MULTIPLE_BITFIELDS(mobility_flags, MOBILITY_STAND|MOBILITY_MOVE) && !buckled)
|
||||
if(prob(1))
|
||||
emote("me", EMOTE_VISIBLE, pick("chases its tail."))
|
||||
|
||||
@@ -33,11 +33,12 @@
|
||||
stop_automated_movement_when_pulled = 1
|
||||
blood_volume = BLOOD_VOLUME_NORMAL
|
||||
var/obj/item/udder/udder = null
|
||||
var/datum/reagent/milk_reagent = /datum/reagent/consumable/milk
|
||||
|
||||
footstep_type = FOOTSTEP_MOB_SHOE
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/goat/Initialize()
|
||||
udder = new()
|
||||
/mob/living/simple_animal/hostile/retaliate/goat/Initialize(/datum/reagent/milk_reagent)
|
||||
udder = new (null, milk_reagent)
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/goat/Destroy()
|
||||
@@ -45,9 +46,10 @@
|
||||
udder = null
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/goat/Life()
|
||||
. = ..()
|
||||
if(.)
|
||||
/mob/living/simple_animal/hostile/retaliate/goat/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if(stat == CONSCIOUS)
|
||||
//chance to go crazy and start wacking stuff
|
||||
if(!enemies.len && prob(1))
|
||||
Retaliate()
|
||||
@@ -56,8 +58,7 @@
|
||||
enemies = list()
|
||||
LoseTarget()
|
||||
src.visible_message("<span class='notice'>[src] calms down.</span>")
|
||||
if(stat == CONSCIOUS)
|
||||
udder.generateMilk()
|
||||
udder.generateMilk(milk_reagent)
|
||||
eat_plants()
|
||||
if(!pulledby)
|
||||
for(var/direction in shuffle(list(1,2,4,8,5,6,9,10)))
|
||||
@@ -137,13 +138,14 @@
|
||||
health = 50
|
||||
maxHealth = 50
|
||||
var/obj/item/udder/udder = null
|
||||
var/datum/reagent/milk_reagent = /datum/reagent/consumable/milk
|
||||
gold_core_spawnable = FRIENDLY_SPAWN
|
||||
blood_volume = BLOOD_VOLUME_NORMAL
|
||||
|
||||
footstep_type = FOOTSTEP_MOB_SHOE
|
||||
|
||||
/mob/living/simple_animal/cow/Initialize()
|
||||
udder = new()
|
||||
udder = new(null, milk_reagent)
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_animal/cow/Destroy()
|
||||
@@ -158,10 +160,11 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/cow/Life()
|
||||
. = ..()
|
||||
/mob/living/simple_animal/cow/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if(stat == CONSCIOUS)
|
||||
udder.generateMilk()
|
||||
udder.generateMilk(milk_reagent)
|
||||
|
||||
/mob/living/simple_animal/cow/attack_hand(mob/living/carbon/M)
|
||||
if(!stat && M.a_intent == INTENT_DISARM && icon_state != icon_dead)
|
||||
@@ -189,6 +192,19 @@
|
||||
else
|
||||
..()
|
||||
|
||||
//Wisdom cow, speaks and bestows great wisdoms
|
||||
/mob/living/simple_animal/cow/wisdom
|
||||
name = "wisdom cow"
|
||||
desc = "Known for its wisdom, shares it with all"
|
||||
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/wisdomcow = 1) //truly the best meat
|
||||
gold_core_spawnable = FALSE
|
||||
speak_chance = 30 //the cow is eager to share its wisdom!
|
||||
milk_reagent = /datum/reagent/medicine/liquid_wisdom
|
||||
|
||||
/mob/living/simple_animal/cow/wisdom/Initialize()
|
||||
. = ..()
|
||||
speak = GLOB.wisdoms //Done here so it's setup properly
|
||||
|
||||
/mob/living/simple_animal/chick
|
||||
name = "\improper chick"
|
||||
desc = "Adorable! They make such a racket though."
|
||||
@@ -229,9 +245,8 @@
|
||||
pixel_x = rand(-6, 6)
|
||||
pixel_y = rand(0, 10)
|
||||
|
||||
/mob/living/simple_animal/chick/Life()
|
||||
. =..()
|
||||
if(!.)
|
||||
/mob/living/simple_animal/chick/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if(!stat && !ckey)
|
||||
amount_grown += rand(1,2)
|
||||
@@ -239,8 +254,9 @@
|
||||
new /mob/living/simple_animal/chicken(src.loc)
|
||||
qdel(src)
|
||||
|
||||
/mob/living/simple_animal/chick/holo/Life()
|
||||
..()
|
||||
/mob/living/simple_animal/chick/holo/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
amount_grown = 0
|
||||
|
||||
/mob/living/simple_animal/chicken
|
||||
@@ -313,9 +329,8 @@
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/chicken/Life()
|
||||
. =..()
|
||||
if(!.)
|
||||
/mob/living/simple_animal/chicken/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if((!stat && prob(3) && eggsleft > 0) && egg_type)
|
||||
visible_message("<span class='alertalien'>[src] [pick(layMessage)]</span>")
|
||||
@@ -388,9 +403,8 @@
|
||||
. = ..()
|
||||
++kiwi_count
|
||||
|
||||
/mob/living/simple_animal/kiwi/Life()
|
||||
. =..()
|
||||
if(!.)
|
||||
/mob/living/simple_animal/kiwi/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if((!stat && prob(3) && eggsleft > 0) && egg_type)
|
||||
visible_message("[src] [pick(layMessage)]")
|
||||
@@ -463,9 +477,8 @@
|
||||
pixel_x = rand(-6, 6)
|
||||
pixel_y = rand(0, 10)
|
||||
|
||||
/mob/living/simple_animal/babyKiwi/Life()
|
||||
. =..()
|
||||
if(!.)
|
||||
/mob/living/simple_animal/babyKiwi/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if(!stat && !ckey)
|
||||
amount_grown += rand(1,2)
|
||||
@@ -481,14 +494,16 @@
|
||||
/obj/item/udder
|
||||
name = "udder"
|
||||
|
||||
/obj/item/udder/Initialize()
|
||||
/obj/item/udder/Initialize(loc, milk_reagent)
|
||||
if(!milk_reagent)
|
||||
milk_reagent = /datum/reagent/consumable/milk
|
||||
create_reagents(50, NONE, NO_REAGENTS_VALUE)
|
||||
reagents.add_reagent(/datum/reagent/consumable/milk, 20)
|
||||
reagents.add_reagent(milk_reagent, 20)
|
||||
. = ..()
|
||||
|
||||
/obj/item/udder/proc/generateMilk()
|
||||
/obj/item/udder/proc/generateMilk(datum/reagent/milk_reagent)
|
||||
if(prob(5))
|
||||
reagents.add_reagent(/datum/reagent/consumable/milk, rand(5, 10))
|
||||
reagents.add_reagent(milk_reagent, rand(5, 10))
|
||||
|
||||
/obj/item/udder/proc/milkAnimal(obj/O, mob/user)
|
||||
var/obj/item/reagent_containers/glass/G = O
|
||||
@@ -529,4 +544,4 @@
|
||||
health = 75
|
||||
maxHealth = 75
|
||||
blood_volume = BLOOD_VOLUME_NORMAL
|
||||
footstep_type = FOOTSTEP_MOB_SHOE
|
||||
footstep_type = FOOTSTEP_MOB_SHOE
|
||||
|
||||
@@ -72,8 +72,8 @@
|
||||
qdel(src)
|
||||
|
||||
//low regen over time
|
||||
/mob/living/simple_animal/pet/plushie/Life()
|
||||
if(stat)
|
||||
/mob/living/simple_animal/pet/plushie/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if(health < maxHealth)
|
||||
heal_overall_damage(5) //Decent life regen, they're not able to hurt anyone so this shouldn't be an issue (butterbear for reference has 10 regen)
|
||||
|
||||
@@ -160,7 +160,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
|
||||
to_chat(src, "<span class='notice'>Your new name <span class='name'>[new_name]</span> anchors itself in your mind.</span>")
|
||||
fully_replace_character_name(null, new_name)
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/Life() //Dies if the summoner dies
|
||||
/mob/living/simple_animal/hostile/guardian/PhysicalLife() //Dies if the summoner dies
|
||||
. = ..()
|
||||
update_health_hud() //we need to update all of our health displays to match our summoner and we can't practically give the summoner a hook to do it
|
||||
med_hud_set_health()
|
||||
|
||||
@@ -19,8 +19,9 @@
|
||||
. = ..()
|
||||
stealthcooldown = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/assassin/Life()
|
||||
. = ..()
|
||||
/mob/living/simple_animal/hostile/guardian/assassin/PhysicalLife()
|
||||
if(!(. = ..()))
|
||||
return
|
||||
updatestealthalert()
|
||||
if(loc == summoner && toggle)
|
||||
ToggleMode(0)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user