mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2026-01-02 05:23:31 +00:00
Merge branch 'master' into protean-rework
This commit is contained in:
5
modular_chomp/code/coalesce_ch.dm
Normal file
5
modular_chomp/code/coalesce_ch.dm
Normal file
@@ -0,0 +1,5 @@
|
||||
/proc/coalesce(...)
|
||||
for (var/arg in args)
|
||||
if (arg)
|
||||
return arg
|
||||
return null
|
||||
95
modular_chomp/code/datums/components/gargoyle.dm
Normal file
95
modular_chomp/code/datums/components/gargoyle.dm
Normal file
@@ -0,0 +1,95 @@
|
||||
/datum/component/gargoyle
|
||||
var/energy = 100
|
||||
var/transformed = FALSE
|
||||
var/paused = FALSE
|
||||
var/paused_loc
|
||||
var/cooldown
|
||||
|
||||
var/mob/living/carbon/human/gargoyle //easy reference
|
||||
var/obj/structure/gargoyle/statue //another easy ref
|
||||
|
||||
/datum/component/gargoyle/Initialize()
|
||||
if (!ishuman(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
gargoyle = parent
|
||||
gargoyle.verbs += /mob/living/carbon/human/proc/gargoyle_transformation
|
||||
gargoyle.verbs += /mob/living/carbon/human/proc/gargoyle_pause
|
||||
gargoyle.verbs += /mob/living/carbon/human/proc/gargoyle_checkenergy
|
||||
START_PROCESSING(SSprocessing, src)
|
||||
|
||||
/datum/component/gargoyle/process()
|
||||
if (!gargoyle)
|
||||
return
|
||||
if (paused && gargoyle.loc != paused_loc)
|
||||
unpause()
|
||||
if (energy > 0)
|
||||
if (!transformed && !paused)
|
||||
energy = max(0,energy-0.05)
|
||||
else if (!transformed && isturf(gargoyle.loc))
|
||||
gargoyle.gargoyle_transformation()
|
||||
if (transformed)
|
||||
if (!statue)
|
||||
transformed = FALSE
|
||||
statue.damage(-0.5)
|
||||
energy = min(energy+0.3, 100)
|
||||
|
||||
/datum/component/gargoyle/proc/unpause()
|
||||
if (!paused || transformed)
|
||||
paused = FALSE
|
||||
paused_loc = null
|
||||
UnregisterSignal(gargoyle, COMSIG_ATOM_ENTERING)
|
||||
return
|
||||
if (gargoyle?.loc != paused_loc)
|
||||
paused = FALSE
|
||||
paused_loc = null
|
||||
energy = max(energy - 5, 0)
|
||||
if (energy == 0)
|
||||
gargoyle.gargoyle_transformation()
|
||||
UnregisterSignal(gargoyle, COMSIG_ATOM_ENTERING)
|
||||
|
||||
//verbs or action buttons...?
|
||||
/mob/living/carbon/human/proc/gargoyle_transformation()
|
||||
set name = "Gargoyle - Petrification"
|
||||
set category = "Abilities"
|
||||
set desc = "Turn yourself into (or back from) being a gargoyle."
|
||||
|
||||
if (stat == DEAD)
|
||||
return
|
||||
|
||||
var/datum/component/gargoyle/comp = GetComponent(/datum/component/gargoyle)
|
||||
if (comp)
|
||||
if (comp.energy <= 0 && isturf(loc))
|
||||
to_chat(src, "<span class='danger'>You suddenly turn into a statue as you run out of energy!</span>")
|
||||
else if (comp.cooldown > world.time)
|
||||
var/time_to_wait = (comp.cooldown - world.time) / (1 SECONDS)
|
||||
to_chat(src, "<span class='warning'>You can't transform just yet again! Wait for another [round(time_to_wait,0.1)] seconds!</span>")
|
||||
return
|
||||
if (istype(loc, /obj/structure/gargoyle))
|
||||
var/obj/structure/gargoyle/statue = loc
|
||||
qdel(statue)
|
||||
else if (isturf(loc))
|
||||
new /obj/structure/gargoyle(loc, src)
|
||||
|
||||
/mob/living/carbon/human/proc/gargoyle_pause()
|
||||
set name = "Gargoyle - Pause"
|
||||
set category = "Abilities"
|
||||
set desc = "Pause your energy while standing still, so you don't use up any more, though you will lose a small amount upon moving again."
|
||||
|
||||
if (stat)
|
||||
return
|
||||
|
||||
var/datum/component/gargoyle/comp = GetComponent(/datum/component/gargoyle)
|
||||
if (comp && !comp.transformed && !comp.paused)
|
||||
comp.paused = TRUE
|
||||
comp.paused_loc = loc
|
||||
comp.RegisterSignal(src, COMSIG_ATOM_ENTERING, /datum/component/gargoyle/proc/unpause)
|
||||
to_chat(src, "<span class='notice'>You start conserving your energy.</span>")
|
||||
|
||||
/mob/living/carbon/human/proc/gargoyle_checkenergy()
|
||||
set name = "Gargoyle - Check Energy"
|
||||
set category = "Abilities"
|
||||
set desc = "Check how much energy you have remaining as a gargoyle."
|
||||
|
||||
var/datum/component/gargoyle/comp = GetComponent(/datum/component/gargoyle)
|
||||
if (comp)
|
||||
to_chat(src, "<span class='notice'>You have [round(comp.energy,0.01)] energy remaining. It is currently [comp.paused ? "stable" : (comp.transformed ? "increasing" : "decreasing")].</span>")
|
||||
@@ -0,0 +1,299 @@
|
||||
// Props
|
||||
/obj/structure/prop/desert_rock
|
||||
icon = 'modular_chomp/icons/obj/desert_planet/desert_rocks.dmi'
|
||||
desc = "Sandy and smooth from erosion."
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
|
||||
/obj/structure/prop/desert_rock/rock
|
||||
name = "desert rock"
|
||||
|
||||
/obj/structure/prop/desert_rock/rock/attack_hand(mob/living/user)
|
||||
if(user.is_incorporeal())
|
||||
return
|
||||
to_chat(user, "You push on the [src].")
|
||||
var/movedir = user.dir
|
||||
if(do_after(user, 3 SECONDS, src))
|
||||
step(src, movedir)
|
||||
|
||||
/obj/structure/prop/desert_rock/rock/New()
|
||||
..()
|
||||
icon_state = "desert_rock[rand(0,6)]"
|
||||
|
||||
/obj/structure/prop/desert_rock/pebble
|
||||
name = "sandy pebble"
|
||||
density = FALSE
|
||||
|
||||
/obj/structure/prop/desert_rock/pebble/Crossed(atom/movable/AM as mob|obj)
|
||||
if(AM.is_incorporeal())
|
||||
return
|
||||
if(istype(AM, /mob/living))
|
||||
var/mob/living/M = AM
|
||||
if(M.m_intent == "run" && prob(5))
|
||||
M.Weaken(2)
|
||||
to_chat(M, "You trip over the [src]!")
|
||||
|
||||
/obj/structure/prop/desert_rock/pebble/New()
|
||||
..()
|
||||
icon_state = "desert_pebble[rand(0,6)]"
|
||||
|
||||
/obj/structure/prop/desert_rock/anthill
|
||||
name = "ant hill"
|
||||
desc = "See how many ants you can spot."
|
||||
icon = 'modular_chomp/icons/obj/desert_planet/desert_plants.dmi'
|
||||
icon_state = "anthill0"
|
||||
|
||||
/obj/structure/prop/desert_rock/anthill/New()
|
||||
..()
|
||||
icon_state = "anthill[rand(0,2)]"
|
||||
|
||||
/obj/structure/prop/desert_planet64x64
|
||||
name = "large rock"
|
||||
desc = "Sandy and smooth from erosion."
|
||||
icon = 'modular_chomp/icons/obj/desert_planet/desert_props_64x64.dmi'
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
can_buckle = FALSE
|
||||
|
||||
/obj/structure/prop/desert_planet64x64/lrock
|
||||
icon_state = "lrock"
|
||||
|
||||
/obj/structure/prop/desert_planet64x64/lrock1
|
||||
icon_state = "lrock1"
|
||||
|
||||
/obj/structure/prop/desert_planet64x64/lrock2
|
||||
icon_state = "lrock2"
|
||||
|
||||
/obj/structure/prop/desert_planet64x64/lrock3
|
||||
icon_state = "lrock3"
|
||||
|
||||
/obj/structure/prop/desert_planet64x64/lrock4
|
||||
icon_state = "lrock4"
|
||||
|
||||
/obj/structure/prop/desert_planet64x64/lribs
|
||||
name = "ribs"
|
||||
desc = "Bleached white by baking sunlight."
|
||||
icon_state = "lribs"
|
||||
|
||||
/obj/structure/prop/desert_planet64x64/lribs1
|
||||
name = "ribs"
|
||||
desc = "Bleached white by baking sunlight."
|
||||
icon_state = "lribs1"
|
||||
|
||||
/obj/structure/prop/desert_planet64x64/lskull
|
||||
name = "skull"
|
||||
desc = "Bleached white by baking sunlight."
|
||||
icon_state = "lskull"
|
||||
|
||||
/obj/structure/prop/desert_planet64x64/lbone
|
||||
name = "bone"
|
||||
desc = "Bleached white by baking sunlight."
|
||||
icon_state = "lbone"
|
||||
|
||||
/obj/structure/prop/desert_planet64x64/palmuria
|
||||
name = "palm"
|
||||
desc = "Stout and bushy."
|
||||
icon_state = "palmuria"
|
||||
|
||||
/obj/structure/prop/desert_planet64x64/palmuria1
|
||||
name = "palm"
|
||||
desc = "Stout and bushy."
|
||||
icon_state = "palmuria1"
|
||||
|
||||
/obj/structure/prop/desert_planet160x160
|
||||
name = "desert large boulder"
|
||||
desc = "Sandy and smooth from erosion."
|
||||
icon = 'modular_chomp/icons/obj/desert_planet/desert_planet_160x160.dmi'
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
can_buckle = FALSE
|
||||
|
||||
/obj/structure/prop/desert_planet160x160/largeboulder
|
||||
icon_state = "large_boulder"
|
||||
|
||||
/obj/structure/prop/desert_planet160x160/tallboulder
|
||||
icon_state = "tall_boulder"
|
||||
|
||||
/obj/structure/prop/desert_planet160x160/boulder
|
||||
icon_state = "boulder"
|
||||
|
||||
/obj/structure/prop/desert_planet160x160/lcactus
|
||||
name = "cactus"
|
||||
desc = "Large and prickly."
|
||||
icon_state = "lcactus"
|
||||
|
||||
/obj/structure/prop/desert_planet160x160/lcactus1
|
||||
name = "cactus"
|
||||
desc = "Large and prickly."
|
||||
icon_state = "lcactus1"
|
||||
|
||||
/obj/structure/prop/desert_planet160x160/lcactus2
|
||||
name = "cactus"
|
||||
desc = "Large and prickly."
|
||||
icon_state = "lcactus2"
|
||||
|
||||
/obj/structure/prop/desert_planet160x160/lcactus3
|
||||
name = "cactus"
|
||||
desc = "Large and prickly."
|
||||
icon_state = "lcactus3"
|
||||
|
||||
// Flora
|
||||
/obj/structure/flora/desert_planet
|
||||
name = "desert plant"
|
||||
desc = "Probably a succulent."
|
||||
icon = 'modular_chomp/icons/obj/desert_planet/desert_plants.dmi'
|
||||
|
||||
/obj/structure/flora/desert_planet/potted_plant
|
||||
name = "potted plant"
|
||||
desc = "Colloquially known as a pot plant."
|
||||
icon_state = "potplant0"
|
||||
|
||||
/obj/structure/flora/desert_planet/potted_plant/New()
|
||||
..()
|
||||
icon_state = "potplant[rand(0,2)]"
|
||||
|
||||
/obj/structure/flora/desert_planet/thicket
|
||||
name = "thicket"
|
||||
desc = "Weedy growths."
|
||||
icon_state = "thicket0"
|
||||
|
||||
/obj/structure/flora/desert_planet/thicket/New()
|
||||
..()
|
||||
icon_state = "thicket[rand(0,6)]"
|
||||
|
||||
/obj/structure/flora/desert_planet/shrub
|
||||
name = "shrub"
|
||||
desc = "Dense and weedy."
|
||||
icon_state = "shrub0"
|
||||
|
||||
/obj/structure/flora/desert_planet/shrub/New()
|
||||
..()
|
||||
icon_state = "shrub[rand(0,5)]"
|
||||
|
||||
/obj/structure/flora/desert_planet/bush
|
||||
name = "bush"
|
||||
desc = "Denser and weedier."
|
||||
icon_state = "bush0"
|
||||
|
||||
/obj/structure/flora/desert_planet/bush/New()
|
||||
..()
|
||||
icon_state = "bush[rand(0,5)]"
|
||||
|
||||
/obj/structure/flora/desert_planet/barrelcacti
|
||||
name = "barrel cacti"
|
||||
desc = "Small, adorable, and begging for a hug."
|
||||
icon_state = "barrelcacti0"
|
||||
|
||||
/obj/structure/flora/desert_planet/barrelcacti/New()
|
||||
..()
|
||||
icon_state = "barrelcacti[rand(0,3)]"
|
||||
|
||||
/obj/structure/flora/desert_planet/palmy
|
||||
name = "yucca bush"
|
||||
desc = "Probably not actually a yucca."
|
||||
icon_state = "palmy0"
|
||||
|
||||
/obj/structure/flora/desert_planet/palmy/New()
|
||||
..()
|
||||
icon_state = "palmy[rand(0,2)]"
|
||||
|
||||
/obj/structure/flora/desert_planet/shrubber
|
||||
name = "thorny bush"
|
||||
desc = "Makes for great fur accessories."
|
||||
icon_state = "shrubber0"
|
||||
|
||||
/obj/structure/flora/desert_planet/shrubber/New()
|
||||
..()
|
||||
icon_state = "shrubber[rand(0,2)]"
|
||||
|
||||
/obj/structure/flora/desert_planet/lbarrelcacti
|
||||
name = "barrel cactus"
|
||||
desc = "Absolutely begging for pets."
|
||||
icon_state = "lbarrelcacti0"
|
||||
|
||||
/obj/structure/flora/desert_planet/lbarrelcacti/New()
|
||||
..()
|
||||
icon_state = "lbarrelcacti[rand(0,2)]"
|
||||
|
||||
// Trees
|
||||
/obj/structure/flora/tree/desert_planet
|
||||
name = "palm tree"
|
||||
desc = "Tall palm tree, makes for a good shade."
|
||||
icon = 'modular_chomp/icons/obj/desert_planet/desert_planet_160x160.dmi'
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
can_buckle = FALSE
|
||||
product = /obj/item/stack/material/log
|
||||
product_amount = 50
|
||||
health = 2000
|
||||
max_health = 2000
|
||||
//var/fruit
|
||||
|
||||
/obj/structure/flora/tree/desert_planet/palmtreeb
|
||||
icon_state = "palmtreeb"
|
||||
base_state = "palmr" // Necessary for stumps to work.
|
||||
|
||||
/obj/structure/flora/tree/desert_planet/palmtreeb1
|
||||
icon_state = "palmtreeb1"
|
||||
base_state = "palml"
|
||||
|
||||
/obj/structure/flora/tree/desert_planet/palmtree
|
||||
icon_state = "palmtree"
|
||||
base_state = "palmr"
|
||||
|
||||
/obj/structure/flora/tree/desert_planet/palmtree1
|
||||
icon_state = "palmtree1"
|
||||
base_state = "palml"
|
||||
|
||||
/obj/structure/flora/tree/desert_planet/mpalmtreeb
|
||||
icon_state = "mpalmtreeb"
|
||||
base_state = "palmr"
|
||||
|
||||
/obj/structure/flora/tree/desert_planet/mpalmtreeb1
|
||||
icon_state = "mpalmtreeb1"
|
||||
base_state = "palml"
|
||||
|
||||
/obj/structure/flora/tree/desert_planet/mpalmtree
|
||||
icon_state = "mpalmtree"
|
||||
base_state = "palml"
|
||||
|
||||
/obj/structure/flora/tree/desert_planet/mpalmtree1
|
||||
icon_state = "mpalmtree1"
|
||||
base_state = "palmr"
|
||||
|
||||
/obj/structure/flora/tree/desert_planet/spalmtree
|
||||
icon_state = "spalmtree"
|
||||
base_state = "palmls"
|
||||
|
||||
/obj/structure/flora/tree/desert_planet/spalmtree1
|
||||
icon_state = "spalmtree1"
|
||||
base_state = "palmrs"
|
||||
|
||||
/obj/structure/flora/tree/desert_planet/spalmtree3
|
||||
icon_state = "spalmtree3"
|
||||
base_state = "palmls"
|
||||
|
||||
/obj/structure/flora/tree/desert_planet/spalmtree4
|
||||
icon_state = "spalmtree4"
|
||||
base_state = "palmrs"
|
||||
|
||||
/obj/structure/flora/tree/desert_planet/desert_tree
|
||||
name = "barren tree"
|
||||
desc = "Completely barren."
|
||||
icon_state = "desert_tree"
|
||||
base_state = "desert"
|
||||
|
||||
/obj/structure/flora/tree/desert_planet/desert_tree1
|
||||
name = "gnarled tree"
|
||||
desc = "Twisted but living."
|
||||
icon_state = "desert_tree1"
|
||||
base_state = "desert"
|
||||
|
||||
/obj/structure/flora/tree/desert_planet/desert_tree3
|
||||
name = "hardy tree"
|
||||
desc = "Thriving despite the conditions."
|
||||
icon_state = "desert_tree3"
|
||||
base_state = "desert"
|
||||
product_amount = 100
|
||||
health = 4000
|
||||
max_health = 4000
|
||||
169
modular_chomp/code/game/objects/structures/gargoyle.dm
Normal file
169
modular_chomp/code/game/objects/structures/gargoyle.dm
Normal file
@@ -0,0 +1,169 @@
|
||||
/obj/structure/gargoyle
|
||||
name = "statue"
|
||||
desc = "A very lifelike carving."
|
||||
density = TRUE
|
||||
anchored = TRUE
|
||||
var/mob/living/carbon/human/gargoyle
|
||||
var/initial_sleep
|
||||
var/initial_blind
|
||||
var/initial_is_shifted
|
||||
var/initial_lying
|
||||
var/initial_lying_prev
|
||||
var/wagging
|
||||
var/flapping
|
||||
var/obj_integrity = 100
|
||||
var/original_int = 100
|
||||
var/max_integrity = 100
|
||||
var/stored_examine
|
||||
|
||||
/obj/structure/gargoyle/Initialize(mapload, var/mob/living/carbon/human/H)
|
||||
. = ..()
|
||||
if (isspace(loc) || isopenspace(loc))
|
||||
anchored = FALSE
|
||||
if (!istype(H) || !isturf(H.loc))
|
||||
return
|
||||
var/datum/component/gargoyle/comp = H.GetComponent(/datum/component/gargoyle)
|
||||
if (comp)
|
||||
comp.cooldown = world.time + (15 SECONDS)
|
||||
comp.statue = src
|
||||
comp.transformed = TRUE
|
||||
comp.paused = FALSE
|
||||
gargoyle = H
|
||||
|
||||
max_integrity = H.getMaxHealth() + 100
|
||||
obj_integrity = H.health + 100
|
||||
original_int = obj_integrity
|
||||
name = "statue of [H.name]"
|
||||
desc = "A very lifelike statue."
|
||||
stored_examine = H.examine()
|
||||
description_fluff = H.get_description_fluff()
|
||||
|
||||
if (H.buckled)
|
||||
H.buckled.unbuckle_mob(H, TRUE)
|
||||
icon = H.icon
|
||||
copy_overlays(H)
|
||||
color = list(rgb(77,77,77), rgb(150,150,150), rgb(28,28,28), rgb(0,0,0))
|
||||
initial_sleep = H.sleeping
|
||||
initial_blind = H.eye_blind
|
||||
initial_is_shifted = H.is_shifted
|
||||
transform = H.transform
|
||||
layer = H.layer
|
||||
pixel_x = H.pixel_x
|
||||
pixel_y = H.pixel_y
|
||||
dir = H.dir
|
||||
initial_lying = H.lying
|
||||
initial_lying_prev = H.lying_prev
|
||||
H.sdisabilities |= MUTE
|
||||
if (H.appearance_flags & PIXEL_SCALE)
|
||||
appearance_flags |= PIXEL_SCALE
|
||||
wagging = H.wagging
|
||||
H.transforming = TRUE
|
||||
flapping = H.flapping
|
||||
H.toggle_tail(FALSE, FALSE)
|
||||
H.toggle_wing(FALSE, FALSE)
|
||||
H.visible_message("<span class='warning'>[H]'s skin rapidly turns to stone!</span>", "<span class='warning'>Your skin abruptly hardens as you turn to stone!</span>")
|
||||
H.forceMove(src)
|
||||
H.SetBlinded(0)
|
||||
H.SetSleeping(0)
|
||||
H.status_flags |= GODMODE
|
||||
H.updatehealth()
|
||||
H.canmove = 0
|
||||
|
||||
/obj/structure/gargoyle/Destroy()
|
||||
unpetrify()
|
||||
. = ..()
|
||||
|
||||
/obj/structure/gargoyle/examine_icon()
|
||||
var/icon/examine_icon = ..()
|
||||
examine_icon.MapColors(rgb(77,77,77), rgb(150,150,150), rgb(28,28,28), rgb(0,0,0))
|
||||
return examine_icon
|
||||
|
||||
/obj/structure/gargoyle/get_description_info()
|
||||
if (gargoyle)
|
||||
if (isspace(loc) || isopenspace(loc))
|
||||
return
|
||||
return "It can be [anchored ? "un" : ""]anchored with a wrench."
|
||||
|
||||
/obj/structure/gargoyle/examine(mob/user)
|
||||
. = ..()
|
||||
if (gargoyle && stored_examine)
|
||||
. += "The statue seems to have a bit more to them..."
|
||||
. += stored_examine
|
||||
return
|
||||
|
||||
/obj/structure/gargoyle/proc/unpetrify()
|
||||
if (!gargoyle)
|
||||
return
|
||||
var/datum/component/gargoyle/comp = gargoyle.GetComponent(/datum/component/gargoyle)
|
||||
if (comp)
|
||||
comp.cooldown = world.time + (15 SECONDS)
|
||||
comp.statue = null
|
||||
comp.transformed = FALSE
|
||||
gargoyle.forceMove(loc)
|
||||
gargoyle.transform = transform
|
||||
gargoyle.pixel_x = pixel_x
|
||||
gargoyle.pixel_y = pixel_y
|
||||
gargoyle.is_shifted = initial_is_shifted
|
||||
gargoyle.dir = dir
|
||||
gargoyle.lying = initial_lying
|
||||
gargoyle.lying_prev = initial_lying_prev
|
||||
gargoyle.toggle_tail(wagging, FALSE)
|
||||
gargoyle.toggle_wing(flapping, FALSE)
|
||||
gargoyle.sdisabilities &= ~MUTE //why is there no ADD_TRAIT etc here that's actually ussssed
|
||||
gargoyle.status_flags &= ~GODMODE
|
||||
gargoyle.SetBlinded(initial_blind)
|
||||
gargoyle.SetSleeping(initial_sleep)
|
||||
gargoyle.transforming = FALSE
|
||||
gargoyle.canmove = 1
|
||||
gargoyle.update_canmove()
|
||||
var/hurtmessage = ""
|
||||
if (obj_integrity < original_int)
|
||||
var/f = (original_int - obj_integrity) / 10
|
||||
for (var/x in 1 to 10)
|
||||
gargoyle.adjustBruteLoss(f)
|
||||
hurtmessage = " <b>You feel your body take the damage that was dealt while being stone!</b>"
|
||||
gargoyle.updatehealth()
|
||||
alpha = 0
|
||||
gargoyle.visible_message("<span class='warning'>[gargoyle]'s skin rapidly softens, returning them to normal!</span>", "<span class='warning'>Your skin softens, freeing your movement once more![hurtmessage]</span>")
|
||||
|
||||
/obj/structure/gargoyle/return_air()
|
||||
return return_air_for_internal_lifeform()
|
||||
|
||||
/obj/structure/gargoyle/return_air_for_internal_lifeform(var/mob/living/lifeform)
|
||||
var/air_type = /datum/gas_mixture/belly_air
|
||||
if(istype(lifeform))
|
||||
air_type = lifeform.get_perfect_belly_air_type()
|
||||
var/air = new air_type(1000)
|
||||
return air
|
||||
|
||||
/obj/structure/gargoyle/proc/damage(var/damage)
|
||||
obj_integrity = min(obj_integrity-damage, max_integrity)
|
||||
if(obj_integrity <= 0)
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/gargoyle/take_damage(var/damage)
|
||||
damage(damage)
|
||||
|
||||
/obj/structure/gargoyle/attack_generic(var/mob/user, var/damage, var/attack_message = "hits")
|
||||
user.do_attack_animation(src)
|
||||
visible_message("<span class='danger'>[user] [attack_message] the [src]!</span>")
|
||||
damage(damage)
|
||||
|
||||
/obj/structure/gargoyle/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
if(W.is_wrench())
|
||||
if (isspace(loc) || isopenspace(loc))
|
||||
to_chat(user, "<span class='warning'>You can't anchor that here!</span>")
|
||||
anchored = FALSE
|
||||
return ..()
|
||||
playsound(src, W.usesound, 50, 1)
|
||||
if (do_after(user, (2 SECONDS) * W.toolspeed, target = src))
|
||||
to_chat("<span class='notice'>You [anchored ? "un" : ""]anchor the [src].</span>")
|
||||
anchored = !anchored
|
||||
else if (!(W.flags & NOBLUDGEON))
|
||||
user.setClickCooldown(user.get_attack_speed(W))
|
||||
if(W.damtype == BRUTE || W.damtype == BURN)
|
||||
user.do_attack_animation(src)
|
||||
playsound(src, W.hitsound, 50, 1)
|
||||
damage(W.force)
|
||||
else
|
||||
return ..()
|
||||
@@ -1,136 +1,257 @@
|
||||
/* Testing
|
||||
// Parent turf.
|
||||
/turf/simulated/floor/outdoors/desert_planet
|
||||
name = "sand"
|
||||
desc = "Salty and gritty."
|
||||
icon = 'modular_chomp/icons/turf/desert_tiles.dmi'
|
||||
icon_edge = 'modular_chomp/icons/turf/outdoors_edge.dmi'
|
||||
can_dig = FALSE
|
||||
|
||||
/turf/simulated/floor/outdoors/desert_planet/sand
|
||||
name = "sand"
|
||||
desc = "Sandy, taste salty and gritty."
|
||||
icon = 'modular_chomp/icons/turf/desert_planet.dmi'
|
||||
desc = "Salty and gritty."
|
||||
icon_state = "sand0"
|
||||
edge_blending_priority = 2
|
||||
turf_layers = list(/turf/simulated/floor/outdoors/rocks)
|
||||
initial_flooring = /decl/flooring/sand
|
||||
can_dig = false
|
||||
*/
|
||||
initial_flooring = /decl/flooring/desert_planet/sand
|
||||
|
||||
/turf/simulated/floor/outdoors/desert_planet/sand
|
||||
name = "sand"
|
||||
desc = "Salty and gritty."
|
||||
icon = 'modular_chomp/icons/turf/desert_planet.dmi'
|
||||
icon_state = "sand"
|
||||
edge_blending_priority = 3
|
||||
turf_layers = list(/turf/simulated/floor/outdoors/desert_planet/sand)
|
||||
// Necessary to get the edges to generate correctly since we use a random-ish icon_state. Inelegant to hard code, but this is a one-off case.
|
||||
/turf/simulated/floor/outdoors/desert_planet/sand/get_edge_icon_state()
|
||||
return "sand"
|
||||
|
||||
/* Testing
|
||||
/decl/flooring/outdoors/sand
|
||||
name = "sand"
|
||||
desc = "Salty and gritty."
|
||||
icon = 'modular_chomp/icons/turf/desert_planet.dmi'
|
||||
icon_base = "sand"
|
||||
footstep_sounds = list("human" = list(
|
||||
'sound/effects/footstep/asteroid1.ogg',
|
||||
'sound/effects/footstep/asteroid2.ogg',
|
||||
'sound/effects/footstep/asteroid3.ogg',
|
||||
'sound/effects/footstep/asteroid4.ogg',
|
||||
'sound/effects/footstep/asteroid5.ogg',
|
||||
'sound/effects/footstep/MedDirt1.ogg',
|
||||
'sound/effects/footstep/MedDirt2.ogg',
|
||||
'sound/effects/footstep/MedDirt3.ogg',
|
||||
'sound/effects/footstep/MedDirt4.ogg'))
|
||||
/turf/simulated/floor/outdoors/desert_planet/sand/Initialize(mapload)
|
||||
. = ..()
|
||||
icon_state = "sand[rand(0,2)]"
|
||||
|
||||
/turf/simulated/floor/outdoors/sand/Initialize(mapload)
|
||||
var/possiblesands = list(
|
||||
"ironsand1" = 50,
|
||||
"ironsand2" = 1,
|
||||
"ironsand3" = 1,
|
||||
"ironsand4" = 1,
|
||||
"ironsand5" = 1,
|
||||
"ironsand6" = 1,
|
||||
"ironsand7" = 1,
|
||||
"ironsand8" = 1,
|
||||
"ironsand9" = 1,
|
||||
"ironsand10" = 1,
|
||||
"ironsand11" = 1,
|
||||
"ironsand12" = 1,
|
||||
"ironsand13" = 1,
|
||||
"ironsand14" = 1,
|
||||
"ironsand15" = 1
|
||||
|
||||
)
|
||||
flooring_override = pickweight(possiblesands)
|
||||
return ..()
|
||||
|
||||
/turf/simulated/floor/water/hotspring
|
||||
name = "Hotsprings"
|
||||
desc = "A natural hotspring connecting to an aquifer. It seems the facility was built ontop of it."
|
||||
edge_blending_priority = -2
|
||||
movement_cost = 8
|
||||
depth = 2
|
||||
water_state = "water_shallow"
|
||||
outdoors = FALSE
|
||||
|
||||
/turf/simulated/floor/water/hotspring/Entered(atom/movable/AM, atom/oldloc)
|
||||
if(istype(AM, /mob/living))
|
||||
var/mob/living/L = AM
|
||||
L.update_water()
|
||||
if(L.check_submerged() <= 0)
|
||||
return
|
||||
if(!istype(oldloc, /turf/simulated/floor/water/hotspring))
|
||||
to_chat(L, "<span class='warning'>You feel an overwhelming wave of warmth from entering \the [src]!</span>")
|
||||
AM.water_act(5)
|
||||
..()
|
||||
|
||||
|
||||
*/
|
||||
/turf/simulated/floor/outdoors/desert_planet/sand/attackby(var/obj/item/W, var/mob/user)
|
||||
if(istype(W, /obj/item/weapon/shovel))
|
||||
to_chat(user, "<span class='notice'>You begin to remove \the [src] with your [W].</span>")
|
||||
if(do_after(user, 4 SECONDS * W.toolspeed))
|
||||
to_chat(user, "<span class='notice'>\The [src] has been dug up, and now lies in a pile nearby.</span>")
|
||||
icon_state = "sand_dug"
|
||||
new /obj/item/weapon/ore/glass (src)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You decide to not finish removing \the [src].</span>")
|
||||
else
|
||||
..()
|
||||
|
||||
/turf/simulated/floor/outdoors/desert_planet/deep_sand
|
||||
name = "sand"
|
||||
desc = "Salty and gritty."
|
||||
icon = 'modular_chomp/icons/turf/desert_planet.dmi'
|
||||
icon_state = "deep_sand"
|
||||
edge_blending_priority = 2
|
||||
turf_layers = list(/turf/simulated/floor/outdoors/desert_planet/sand)
|
||||
desc = "Really gets everywhere."
|
||||
icon_state = "deep_sand0"
|
||||
edge_blending_priority = 1
|
||||
movement_cost = 3
|
||||
initial_flooring = /decl/flooring/desert_planet/deep_sand
|
||||
|
||||
/turf/simulated/floor/outdoors/desert_planet/deep_sand/Initialize(mapload)
|
||||
. = ..()
|
||||
icon_state = "deep_sand[rand(0,2)]"
|
||||
|
||||
/turf/simulated/floor/outdoors/desert_planet/grass
|
||||
name = "grass"
|
||||
desc = "Lively green grass, soft to walk on."
|
||||
icon = 'modular_chomp/icons/turf/desert_planet.dmi'
|
||||
icon_state = "grass"
|
||||
edge_blending_priority = 6
|
||||
turf_layers = list(/turf/simulated/floor/outdoors/desert_planet/sand)
|
||||
edge_blending_priority = 5
|
||||
initial_flooring = /decl/flooring/desert_planet/grass
|
||||
|
||||
/turf/simulated/floor/outdoors/desert_planet/deep_grass
|
||||
name = "dense grass"
|
||||
desc = "Dense patch of grass, seems like a soft spot to lay on."
|
||||
icon = 'modular_chomp/icons/turf/desert_planet.dmi'
|
||||
icon_state = "deep_grass"
|
||||
edge_blending_priority = 7
|
||||
turf_layers = list(/turf/simulated/floor/outdoors/desert_planet/sand)
|
||||
edge_blending_priority = 6
|
||||
initial_flooring = /decl/flooring/desert_planet/deep_grass
|
||||
|
||||
/turf/simulated/floor/outdoors/desert_planet/gravel
|
||||
name = "gravel"
|
||||
desc = "Mix of dirt and sand, it crumbles in your hand."
|
||||
icon = 'modular_chomp/icons/turf/desert_planet.dmi'
|
||||
icon_state = "gravel"
|
||||
edge_blending_priority = 5
|
||||
turf_layers = list(/turf/simulated/floor/outdoors/desert_planet/sand)
|
||||
edge_blending_priority = 3
|
||||
initial_flooring = /decl/flooring/desert_planet/gravel
|
||||
|
||||
/turf/simulated/floor/outdoors/desert_planet/mud
|
||||
name = "mud"
|
||||
desc = "Squishy damp dirt, smells muddy."
|
||||
icon = 'modular_chomp/icons/turf/desert_planet.dmi'
|
||||
icon_state = "mud"
|
||||
edge_blending_priority = 4
|
||||
turf_layers = list(/turf/simulated/floor/outdoors/desert_planet/sand)
|
||||
initial_flooring = /decl/flooring/desert_planet/mud
|
||||
|
||||
// At last we've come full circle, a floor which is actually a wall.
|
||||
/turf/simulated/floor/outdoors/desert_planet/stonewall
|
||||
name = "sandstone"
|
||||
desc = "Rough sandstone."
|
||||
icon_state = "stonewall"
|
||||
density = TRUE
|
||||
opacity = TRUE
|
||||
edge_blending_priority = 7
|
||||
initial_flooring = /decl/flooring/desert_planet/stonewall
|
||||
turf_layers = list(/turf/simulated/floor/outdoors/rocks)
|
||||
var/last_act = 0
|
||||
|
||||
// Stolen from mineral turf code.
|
||||
/turf/simulated/floor/outdoors/desert_planet/stonewall/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(!user.IsAdvancedToolUser())
|
||||
to_chat(user, "<span class='warning'>You don't have the dexterity to do this!</span>")
|
||||
return
|
||||
|
||||
if(istype(W, /obj/item/weapon/pickaxe))
|
||||
if(!istype(user.loc, /turf))
|
||||
return
|
||||
|
||||
var/obj/item/weapon/pickaxe/P = W
|
||||
if(last_act + P.digspeed > world.time)//prevents message spam
|
||||
return
|
||||
last_act = world.time
|
||||
|
||||
playsound(user, P.drill_sound, 20, 1)
|
||||
to_chat(user, "<span class='notice'>You start [P.drill_verb].</span>")
|
||||
|
||||
if(do_after(user,P.digspeed))
|
||||
|
||||
to_chat(user, "<span class='notice'>You finish [P.drill_verb] \the [src].</span>")
|
||||
new /obj/item/stack/material/sandstone(src)
|
||||
density = FALSE
|
||||
opacity = FALSE
|
||||
demote() // Converts the turf to the next layer in turf_layers.
|
||||
..()
|
||||
|
||||
/turf/simulated/floor/outdoors/desert_planet/sandrock
|
||||
name = "sandstone tiles"
|
||||
desc = "Tightly joined in a mesmerizing lattice."
|
||||
icon_state = "sandrock"
|
||||
density = TRUE
|
||||
opacity = TRUE
|
||||
initial_flooring = /decl/flooring/desert_planet/sandrock
|
||||
|
||||
// Declarations (for initial_flooring)
|
||||
/decl/flooring/desert_planet // Yeah don't use this one, it's a parent just for setting icon.
|
||||
name = "desert stuff"
|
||||
desc = "If you see this, this turf is using the wrong decl."
|
||||
icon = 'modular_chomp/icons/turf/desert_tiles.dmi'
|
||||
icon_base = null
|
||||
|
||||
/decl/flooring/desert_planet/sand
|
||||
name = "sand"
|
||||
desc = "Salty and gritty."
|
||||
icon_base = "sand"
|
||||
has_base_range = 2
|
||||
|
||||
/decl/flooring/desert_planet/deep_sand
|
||||
name = "sand"
|
||||
desc = "Really gets everywhere."
|
||||
icon_base = "deep_sand"
|
||||
has_base_range = 2
|
||||
|
||||
/decl/flooring/desert_planet/grass
|
||||
name = "grass"
|
||||
desc = "Lively green grass, soft to walk on."
|
||||
icon_base = "grass"
|
||||
|
||||
/decl/flooring/desert_planet/deep_grass
|
||||
name = "dense grass"
|
||||
desc = "Dense patch of grass, seems like a soft spot to lay on."
|
||||
icon_base = "deep_grass"
|
||||
|
||||
/decl/flooring/desert_planet/gravel
|
||||
name = "gravel"
|
||||
desc = "Mix of dirt and sand, it crumbles in your hand."
|
||||
icon_base = "gravel"
|
||||
|
||||
/decl/flooring/desert_planet/mud
|
||||
name = "mud"
|
||||
desc = "Squishy damp dirt, smells muddy."
|
||||
icon_base = "mud"
|
||||
|
||||
/decl/flooring/desert_planet/stonewall
|
||||
name = "sandstone"
|
||||
desc = "Rough sandstone."
|
||||
icon_base = "stonewall"
|
||||
|
||||
/decl/flooring/desert_planet/sandrock
|
||||
name = "sandstone tiles"
|
||||
desc = "Tightly joined in a mesmerizing lattice."
|
||||
icon_base = "sandrock"
|
||||
flags = TURF_HAS_EDGES | TURF_HAS_CORNERS
|
||||
|
||||
/*
|
||||
/obj/effect/floor_decal/desert_planet/floor/sand0_edge
|
||||
name = "sand0_edge"
|
||||
icon = 'icons/turf/desert_planet.dmi'
|
||||
icon_state = "sand0_edge"
|
||||
|
||||
/obj/effect/floor_decal/desert_planet/floor/gravel_edge
|
||||
name = "gravel_edge"
|
||||
icon = 'icons/turf/desert_planet.dmi'
|
||||
icon_state = "gravel_edge"
|
||||
|
||||
/obj/effect/floor_decal/desert_planet/floor/mud_edge
|
||||
name = "mud_edge"
|
||||
icon = 'icons/turf/desert_planet.dmi'
|
||||
icon_state = "mud_edge"
|
||||
|
||||
/obj/effect/floor_decal/desert_planet/floor/grass_edge
|
||||
name = "grass_edge"
|
||||
icon = 'icons/turf/desert_planet.dmi'
|
||||
icon_state = "grass_edge"
|
||||
|
||||
/obj/effect/floor_decal/desert_planet/floor/deep_grass_edge
|
||||
name = "deep_grass_edge"
|
||||
icon = 'icons/turf/desert_planet.dmi'
|
||||
icon_state = "deep_grass_edge"
|
||||
*/
|
||||
|
||||
/* #No idea how water tiles work
|
||||
/turf/simulated/floor/outdoors/desert_planet/water
|
||||
name = "water"
|
||||
desc = "Clear cool water, looks potable."
|
||||
icon = 'modular_chomp/icons/turf/desert_planet.dmi'
|
||||
icon = 'icons/turf/desert_planet.dmi'
|
||||
icon_state = "water"
|
||||
edge_blending_priority = 8
|
||||
var/water_state = "water_shallow"
|
||||
var/under_state = "sand"
|
||||
can_be_plated = FALSE
|
||||
outdoors = OUTDOORS_YES
|
||||
flags = TURF_ACID_IMMUNE
|
||||
layer = WATER_FLOOR_LAYER
|
||||
can_dirty = FALSE // It's water
|
||||
var/depth = 1 // Higher numbers indicates deeper water.
|
||||
var/reagent_type = "water"
|
||||
edge_blending_priority = 2
|
||||
turf_layers = list(/turf/simulated/floor/outdoors/desert_planet/sand)
|
||||
|
||||
/turf/simulated/floor/outdoors/desert_planet/deep_water
|
||||
name = "deep water"
|
||||
desc = "deep enough you can't see the bottom of it."
|
||||
icon = 'modular_chomp/icons/turf/desert_planet.dmi'
|
||||
icon = 'icons/turf/desert_planet.dmi'
|
||||
icon_state = "deep_water"
|
||||
edge_blending_priority = 9
|
||||
var/water_state = "water_shallow"
|
||||
var/under_state = "sand"
|
||||
can_be_plated = FALSE
|
||||
outdoors = OUTDOORS_YES
|
||||
flags = TURF_ACID_IMMUNE
|
||||
layer = WATER_FLOOR_LAYER
|
||||
can_dirty = FALSE // It's water
|
||||
var/depth = 2 // Higher numbers indicates deeper water.
|
||||
var/reagent_type = "water"
|
||||
edge_blending_priority = 4
|
||||
turf_layers = list(/turf/simulated/floor/outdoors/desert_planet/sand)
|
||||
|
||||
//I want this for the water tiles
|
||||
/turf/simulated/floor/water
|
||||
name = "shallow water"
|
||||
desc = "A body of water. It seems shallow enough to walk through, if needed."
|
||||
icon = 'icons/turf/outdoors.dmi'
|
||||
icon_state = "seashallow" // So it shows up in the map editor as water.
|
||||
var/water_state = "water_shallow"
|
||||
var/under_state = "rock"
|
||||
edge_blending_priority = -1
|
||||
movement_cost = 4
|
||||
can_be_plated = FALSE
|
||||
outdoors = OUTDOORS_YES
|
||||
flags = TURF_ACID_IMMUNE
|
||||
|
||||
layer = WATER_FLOOR_LAYER
|
||||
|
||||
can_dirty = FALSE // It's water
|
||||
|
||||
var/depth = 1 // Higher numbers indicates deeper water.
|
||||
|
||||
var/reagent_type = "water"
|
||||
// var/datum/looping_sound/water/soundloop CHOMPEdit: Removing soundloop for now.
|
||||
*/
|
||||
|
||||
25
modular_chomp/code/modules/artifice/deadringer.dm
Normal file
25
modular_chomp/code/modules/artifice/deadringer.dm
Normal file
@@ -0,0 +1,25 @@
|
||||
/obj/item/weapon/deadringer/process()
|
||||
if(activated)
|
||||
if (ismob(src.loc))
|
||||
var/mob/living/carbon/human/H = src.loc
|
||||
watchowner = H
|
||||
if(H.getBruteLoss() > bruteloss_prev || H.getFireLoss() > fireloss_prev)
|
||||
deathprevent()
|
||||
activated = 0
|
||||
if(watchowner.isSynthetic())
|
||||
to_chat(watchowner, "<font color='blue'>You fade into nothingness! [src]'s screen blinks, being unable to copy your synthetic body!</font>")
|
||||
else
|
||||
to_chat(watchowner, "<font color='blue'>You fade into nothingness, leaving behind a fake body!</font>")
|
||||
icon_state = "deadringer_cd"
|
||||
timer = 5
|
||||
return
|
||||
if(timer > 0)
|
||||
timer--
|
||||
if(timer == 2)
|
||||
reveal()
|
||||
if(corpse)
|
||||
new /obj/effect/effect/smoke/chem(corpse.loc)
|
||||
qdel(corpse)
|
||||
if(timer == 0)
|
||||
icon_state = "deadringer"
|
||||
return
|
||||
6
modular_chomp/code/modules/clothing/clothing_icons.dm
Normal file
6
modular_chomp/code/modules/clothing/clothing_icons.dm
Normal file
@@ -0,0 +1,6 @@
|
||||
/obj/item/clothing/shoes/apply_blood(var/image/standing)
|
||||
if(blood_DNA && blood_sprite_state && ishuman(loc))
|
||||
var/mob/living/carbon/human/H = loc
|
||||
var/image/bloodsies = image(icon = H.digitigrade ? 'modular_chomp/icons/mob/human_races/masks/blood_digitigrade.dmi' : H.species.get_blood_mask(H), icon_state = blood_sprite_state)
|
||||
bloodsies.color = blood_color
|
||||
standing.add_overlay(bloodsies)
|
||||
@@ -0,0 +1,71 @@
|
||||
/obj/item/weapon/rig/ch/precursor
|
||||
name = "xenotech hardsuit control module"
|
||||
desc = "A purple hardsuit gleaming with energy and alien metals."
|
||||
suit_type = "precursor hardsuit"
|
||||
icon = 'modular_chomp/icons/obj/rig_modules_ch.dmi'
|
||||
icon_state = "precursor_rig"
|
||||
armor = list(melee = 50, bullet = 50, laser = 70, energy = 70, bomb = 60, bio = 100, rad = 80)
|
||||
var/block_chance = 15
|
||||
slowdown = 0
|
||||
|
||||
chest_type = /obj/item/clothing/suit/space/rig/ch/precursor
|
||||
helm_type = /obj/item/clothing/head/helmet/space/rig/ch/precursor
|
||||
glove_type = /obj/item/clothing/gloves/gauntlets/rig/ch/precursor
|
||||
boot_type = /obj/item/clothing/shoes/magboots/rig/ch/precursor
|
||||
|
||||
req_access = list()
|
||||
req_one_access = list()
|
||||
|
||||
/obj/item/clothing/suit/space/rig/ch/precursor
|
||||
name = "protective vest"
|
||||
icon = 'icons/obj/clothing/spacesuits_ch.dmi'
|
||||
desc = "Light weight but oddly protective plating."
|
||||
var/block_chance = 15
|
||||
|
||||
/obj/item/clothing/head/helmet/space/rig/ch/precursor
|
||||
name = "helmet"
|
||||
icon = 'icons/obj/clothing/hats_ch.dmi'
|
||||
desc = "A protective dome for your head."
|
||||
var/block_chance = 15
|
||||
|
||||
/obj/item/clothing/gloves/gauntlets/rig/ch/precursor
|
||||
name = "gloves"
|
||||
icon = 'icons/obj/clothing/gloves_ch.dmi'
|
||||
desc = "Gloves created with alien tech"
|
||||
var/block_chance = 15
|
||||
|
||||
/obj/item/clothing/shoes/magboots/rig/ch/precursor
|
||||
name = "boots"
|
||||
icon = 'icons/obj/clothing/shoes_ch.dmi'
|
||||
desc = "A pair of grabby boots"
|
||||
var/block_chance = 15
|
||||
|
||||
/obj/item/weapon/rig/ch/precursor/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
|
||||
if(prob(block_chance))
|
||||
user.visible_message("<span class='danger'>\The [src] completely absorbs [attack_text]!</span>")
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/clothing/suit/space/rig/ch/precursor/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
|
||||
if(prob(block_chance))
|
||||
user.visible_message("<span class='danger'>\The [src] completely absorbs [attack_text]!</span>")
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/clothing/head/helmet/space/rig/ch/precursor/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
|
||||
if(prob(block_chance))
|
||||
user.visible_message("<span class='danger'>\The [src] completely absorbs [attack_text]!</span>")
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/clothing/gloves/gauntlets/rig/ch/precursor/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
|
||||
if(prob(block_chance))
|
||||
user.visible_message("<span class='danger'>\The [src] completely absorbs [attack_text]!</span>")
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/clothing/shoes/magboots/rig/ch/precursor/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
|
||||
if(prob(block_chance))
|
||||
user.visible_message("<span class='danger'>\The [src] completely absorbs [attack_text]!</span>")
|
||||
return TRUE
|
||||
return FALSE
|
||||
@@ -1,3 +1,4 @@
|
||||
/obj/item/weapon/rig
|
||||
var/protean = 0
|
||||
var/obj/item/weapon/storage/backpack/rig_storage
|
||||
var/obj/item/weapon/storage/backpack/rig_storage
|
||||
permeability_coefficient = 0 //Protect the squishies, after all this shit should be waterproof.
|
||||
|
||||
@@ -3,3 +3,6 @@
|
||||
|
||||
/datum/trait/positive/linguist
|
||||
custom_only = FALSE
|
||||
|
||||
/datum/trait/positive/toxin_gut
|
||||
custom_only = FALSE
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
//This hivebots are meant to be high threats, and a tad more fitting of the alien places they tend to be in. Aka mini-bosses.
|
||||
|
||||
/mob/living/simple_mob/mechanical/hivebot/precusor
|
||||
name = "Precursor Hivebot"
|
||||
icon = 'modular_chomp/icons/mob/hivebot.dmi'
|
||||
icon_state = "precursorhive"
|
||||
icon_living = "precursorhive"
|
||||
attacktext = list("prodded")
|
||||
maxHealth = 5 LASERS_TO_KILL // 150 health
|
||||
health = 5 LASERS_TO_KILL
|
||||
movement_cooldown = 4
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 15
|
||||
|
||||
var/obj/item/shield_projector/shields = null
|
||||
|
||||
/mob/living/simple_mob/mechanical/hivebot/precusor/Initialize(mapload)
|
||||
shields = new /obj/item/shield_projector/rectangle/automatic/hivebot_drone(src)
|
||||
return ..()
|
||||
|
||||
|
||||
/mob/living/simple_mob/mechanical/hivebot/precusor/machinegun
|
||||
projectiletype = /obj/item/projectile/bullet/hivebot
|
||||
base_attack_cooldown = 0 // Extremly rapid fire with rather weak bullets.
|
||||
|
||||
/mob/living/simple_mob/mechanical/hivebot/precusor/laser
|
||||
projectiletype = /obj/item/projectile/beam/precursor
|
||||
projectile_dispersion = 5
|
||||
projectile_accuracy = -30
|
||||
|
||||
/mob/living/simple_mob/mechanical/hivebot/precusor/lobber
|
||||
projectiletype = /obj/item/projectile/arc/blue_energy/precusor
|
||||
|
||||
|
||||
/obj/item/projectile/arc/blue_energy/precusor
|
||||
name = "energy missile"
|
||||
icon_state = "force_missile"
|
||||
armor_penetration = 10
|
||||
damage = 50 // Mimics the precusor laser damage and armor peircing with a tad more damage because of the lobbying style.
|
||||
damage_type = BURN
|
||||
color = "#A020F0"
|
||||
|
||||
/obj/item/shield_projector/rectangle/automatic/hivebot_drone
|
||||
shield_health = 100
|
||||
max_shield_health = 100
|
||||
shield_regen_delay = 5 SECONDS
|
||||
shield_regen_amount = 20
|
||||
size_x = 3
|
||||
size_y = 3
|
||||
color = "#A020F0"
|
||||
high_color = "#A020F0"
|
||||
low_color = "#A020F0"
|
||||
@@ -0,0 +1,5 @@
|
||||
//Giving the tank hivebot class a new look,
|
||||
/mob/living/simple_mob/mechanical/hivebot/tank
|
||||
icon = 'modular_chomp/icons/mob/hivebot.dmi'
|
||||
icon_state = "blue"
|
||||
icon_living = "blue"
|
||||
@@ -1,8 +1,15 @@
|
||||
|
||||
/mob/living/simple_mob/mechanical/mecha/combat/gygax
|
||||
movement_cooldown = 1 //Because normal Gygaxes are tougher then ths boss version with 0 speed
|
||||
|
||||
/mob/living/simple_mob/mechanical/mecha/combat/gygax/dark/advanced
|
||||
movement_cooldown = 0 //Because AADG needs all the help it can get.
|
||||
|
||||
/mob/living/simple_mob/mechanical/mecha/combat/gygax/aerostat
|
||||
desc = "A Vir System Authority automated combat mech with an aged apperance."
|
||||
ai_holder_type = /datum/ai_holder/simple_mob/intentional/adv_dark_gygax
|
||||
say_list = /datum/say_list/gygax_aerostat
|
||||
|
||||
|
||||
/datum/say_list/gygax_aerostat
|
||||
speak = list("ALERT.","Hostile-ile-ile entities dee-twhoooo-wected.","Threat parameterszzzz- szzet.","Bring sub-sub-sub-systems uuuup to combat alert alpha-a-a.")
|
||||
emote_see = list("beeps menacingly","whirrs threateningly","scans its immediate vicinity")
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/mob/living/simple_mob/animal/passive/dog/stray
|
||||
name = "dog"
|
||||
desc = "The most standard dog you have ever seen, it even smells like one."
|
||||
tt_desc = "Canis lupus familiaris"
|
||||
//faction = "mexico" //They are from Mexico. //Amusing but this prompts aggression from crew-aligned mobs.
|
||||
|
||||
icon = 'modular_chomp/icons/turf/desert_tiles.dmi'
|
||||
icon_state = "dog"
|
||||
item_state = "dog"
|
||||
icon_living = "dog"
|
||||
icon_rest = "dog"
|
||||
icon_dead = "dog"
|
||||
|
||||
health = 50
|
||||
maxHealth = 50
|
||||
|
||||
mob_size = MOB_SMALL
|
||||
pass_flags = PASSTABLE
|
||||
can_pull_size = ITEMSIZE_TINY
|
||||
can_pull_mobs = MOB_PULL_NONE
|
||||
layer = MOB_LAYER
|
||||
density = 1
|
||||
movement_cooldown = 0.75 //roughly a bit faster than a person
|
||||
|
||||
response_help = "pets"
|
||||
response_disarm = "rolls aside"
|
||||
response_harm = "stomps"
|
||||
|
||||
melee_damage_lower = 5
|
||||
melee_damage_upper = 7
|
||||
attacktext = list("nips", "bumps", "scratches")
|
||||
|
||||
vore_taste = "wet dog"
|
||||
|
||||
min_oxy = 16 //Require atleast 16kPA oxygen
|
||||
minbodytemp = 223 //Below -50 Degrees Celcius
|
||||
maxbodytemp = 523 //Above 80 Degrees Celcius
|
||||
heat_damage_per_tick = 3
|
||||
cold_damage_per_tick = 3
|
||||
|
||||
meat_amount = 7
|
||||
holder_type = /obj/item/weapon/holder/armadillo
|
||||
ai_holder_type = /datum/ai_holder/simple_mob/armadillo
|
||||
|
||||
speak_emote = list("rumbles", "chirr?", "churr")
|
||||
|
||||
say_list_type = /datum/say_list/armadillo
|
||||
@@ -20,6 +20,13 @@
|
||||
adminbus_trash = TRUE //You know what, sure whatever. It's not like anyone's gonna be taking this bird on unga trips to be their gamer backpack, which kinda was the main reason for the trash eater restrictions in the first place anyway.
|
||||
faction = "neutral"
|
||||
say_list_type = /datum/say_list/swoopie
|
||||
var/static/list/crew_creatures = list( /mob/living/simple_mob/protean_blob,
|
||||
/mob/living/simple_mob/slime/promethean)
|
||||
|
||||
/mob/living/simple_mob/vore/aggressive/corrupthound/swoopie/IIsAlly(mob/living/L)
|
||||
. = ..()
|
||||
if(!.) // Outside the faction and not in friends, are they crew
|
||||
return L?.type in crew_creatures
|
||||
|
||||
/mob/living/simple_mob/vore/aggressive/corrupthound/swoopie/init_vore()
|
||||
if(!voremob_loaded)
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
// preferentially take digitigrade value from owner if available, THEN DNA.
|
||||
// this allows limbs to be set properly when being printed in the bioprinter without an owner
|
||||
// this also allows the preview mannequin to update properly because customisation topic calls don't call a DNA check
|
||||
var/check_digi = istype(src,/obj/item/organ/external/leg) || istype(src,/obj/item/organ/external/foot)
|
||||
if(owner)
|
||||
digitigrade = owner.digitigrade && (istype(src,/obj/item/organ/external/leg) || istype(src,/obj/item/organ/external/foot))
|
||||
digitigrade = check_digi && owner.digitigrade
|
||||
else if(dna)
|
||||
digitigrade = dna.digitigrade && (istype(src,/obj/item/organ/external/leg) || istype(src,/obj/item/organ/external/foot))
|
||||
digitigrade = check_digi && dna.digitigrade
|
||||
|
||||
var/gender = "m"
|
||||
var/skip_forced_icon = skip_robo_icon || (digi_prosthetic && digitigrade)
|
||||
@@ -56,13 +57,15 @@
|
||||
if((!istype(src,/obj/item/organ/external/head) && !(force_icon && !skip_forced_icon)) || (model && owner && owner.synth_markings))
|
||||
for(var/M in markings)
|
||||
var/datum/sprite_accessory/marking/mark_style = markings[M]["datum"]
|
||||
var/isdigitype = istype(mark_style,/datum/sprite_accessory/marking/digi)
|
||||
if(!(digitigrade ^ isdigitype)) //Equivalent to XNOR; this code will only run if either both digitigrade and isdigitype are true, or if both are false.
|
||||
var/icon/mark_s = new/icon("icon" = mark_style.icon, "icon_state" = "[mark_style.icon_state]-[organ_tag]")
|
||||
mark_s.Blend(markings[M]["color"], mark_style.color_blend_mode) // VOREStation edit
|
||||
add_overlay(mark_s) //So when it's not on your body, it has icons
|
||||
mob_icon.Blend(mark_s, ICON_OVERLAY) //So when it's on your body, it has icons
|
||||
icon_cache_key += "[M][markings[M]["color"]]"
|
||||
var/isdigitype = mark_style.digitigrade_acceptance
|
||||
if(check_digi)
|
||||
if (!(isdigitype & (digitigrade ? MARKING_DIGITIGRADE_ONLY : MARKING_NONDIGI_ONLY))) //checks flags based on which digitigrade type the limb is
|
||||
continue
|
||||
var/icon/mark_s = new/icon("icon" = digitigrade ? mark_style.digitigrade_icon : mark_style.icon, "icon_state" = "[mark_style.icon_state]-[organ_tag]")
|
||||
mark_s.Blend(markings[M]["color"], mark_style.color_blend_mode) // VOREStation edit
|
||||
add_overlay(mark_s) //So when it's not on your body, it has icons
|
||||
mob_icon.Blend(mark_s, ICON_OVERLAY) //So when it's on your body, it has icons
|
||||
icon_cache_key += "[M][markings[M]["color"]]"
|
||||
if(body_hair && islist(h_col) && h_col.len >= 3)
|
||||
var/cache_key = "[body_hair]-[icon_name]-[h_col[1]][h_col[2]][h_col[3]]"
|
||||
if(!limb_icon_cache[cache_key])
|
||||
|
||||
358
modular_chomp/code/modules/overmap/dynamic_sector.dm
Normal file
358
modular_chomp/code/modules/overmap/dynamic_sector.dm
Normal file
@@ -0,0 +1,358 @@
|
||||
// This is an attempt to make space POI's which load/unload on demand, so we can have 50 overmap POI's without
|
||||
// 50 z-levels (which may lead to OOM). No idea what forces I'm working with, so let's see how poorly this goes.
|
||||
// Map templates for this system are stored in space_pois.dm.
|
||||
|
||||
GLOBAL_VAR_INIT(dynamic_sector_master, null)
|
||||
// Also adjust find_z_levels() if you adjust increase dynamic levels, that part is hard-coded so you don't gloss over world.increment_max_z().
|
||||
#define MAX_DYNAMIC_LEVELS 3
|
||||
#define MAX_DYNAMIC_POI_DIMENSIONS 200 // Keep this an even number if using even world.maxx/maxy. This value MUST
|
||||
// a large enough static border to fit OM ships. A 30x30 ship means max dimensions must be 60 less than the z-level max
|
||||
// to keep a 30 turf border on each side of the load/unload area.
|
||||
|
||||
// The "master" object, which creates + stores + registers the actual z-levels used for dynamic POI's. Handles overmap
|
||||
// sanity checks, + procs, should not be directly accessible by players. Do not use in maps. Only 1 should exist currently.
|
||||
/obj/effect/overmap/visitable/dynamic
|
||||
name = "DO NOT USE IN MAPS"
|
||||
known = FALSE
|
||||
scannable = FALSE
|
||||
invisibility = 101
|
||||
in_space = TRUE
|
||||
scanner_desc = "You should not see this."
|
||||
var/generated_z = FALSE
|
||||
var/base_area = /area/space
|
||||
|
||||
// Initialized to match max dynamic levels.
|
||||
map_z = list(null,null,null)
|
||||
|
||||
// Overmap poi's CURRENTLY USING a z-level. Dynamic POI's get referenced here when loading in and removed when unloaded.
|
||||
// Length must match map_z length or bad things may happen.
|
||||
var/list/active_pois[MAX_DYNAMIC_LEVELS]
|
||||
|
||||
// Reference list of shuttle landmarks for each z-level. Used to register/unregister shuttle landmarks in POI's.
|
||||
var/list/shuttle_landmarks[MAX_DYNAMIC_LEVELS]
|
||||
var/list/all_children = list()
|
||||
|
||||
|
||||
// This handles generating and assigning z-levels. Overriding this proc means we don't need a hacky Initialize() override.
|
||||
// This means extra_z_levels won't do anything, which is intentional.
|
||||
/obj/effect/overmap/visitable/dynamic/find_z_levels()
|
||||
if(!generated_z && (GLOB.dynamic_sector_master == src)) // Ensure this only runs once per round.
|
||||
for(var/i = 1; i <= 3; i++) // Hard-coding limit because this is dangerous.
|
||||
world.increment_max_z()
|
||||
map_z[i] = world.maxz
|
||||
// Spawn shuttle_landmarks near the lower x border, aligned with the POI spawning turf. These move during POI generation.
|
||||
var/turf/T = locate(10, round(world.maxy/2), map_z[i])
|
||||
if(istype(T))
|
||||
var/list/spawn_directions = list() // Stores a landmark for each direction.
|
||||
for(var/direction in list("FORE", "PORT", "AFT", "STARBOARD"))
|
||||
var/obj/effect/shuttle_landmark/om_poi/S = new(T, "Subspace sector [i] - [direction]", "dynamic_sector_[i] - [direction]")
|
||||
spawn_directions[direction] = S
|
||||
shuttle_landmarks[i] = spawn_directions
|
||||
generated_z = TRUE
|
||||
|
||||
/obj/effect/overmap/visitable/dynamic/Initialize()
|
||||
if(!GLOB.dynamic_sector_master)
|
||||
GLOB.dynamic_sector_master = src
|
||||
. = ..()
|
||||
if(ispath(base_area))
|
||||
var/area/spehss = locate(base_area)
|
||||
if(!istype(spehss))
|
||||
CRASH("Dynamic POI generation couldn't locate area [base_area].")
|
||||
base_area = spehss
|
||||
create_children()
|
||||
|
||||
// Create POI objects for each overmap POI template, link to parent. Initialize() of children handles turf assignment
|
||||
/obj/effect/overmap/visitable/dynamic/proc/create_children()
|
||||
for(var/datum/map_template/dynamic_overmap/poi as anything in subtypesof(/datum/map_template/dynamic_overmap))
|
||||
if(!initial(poi.mappath) || !initial(poi.name) || (initial(poi.block_size) > MAX_DYNAMIC_POI_DIMENSIONS)) // Exclude templates without an actual map or are too big (or are not included in the mapping subsystem map_templates)
|
||||
continue
|
||||
var/obj/effect/overmap/visitable/dynamic/poi/P = new()
|
||||
P.my_template = SSmapping.map_templates[initial(poi.name)] // Link to the stored map datums.
|
||||
P.parent = src
|
||||
all_children.Add(P)
|
||||
P.seed_overmap()
|
||||
|
||||
// Randomly unload a child POI, if possible. Returns the index of the recovered level if successful, 0 if not.
|
||||
// Should only be called if active_pois[] is full.
|
||||
/obj/effect/overmap/visitable/dynamic/proc/cull_child(mob/user)
|
||||
var/random_index = rand(1,MAX_DYNAMIC_LEVELS)
|
||||
var/obj/effect/overmap/visitable/dynamic/poi/P
|
||||
|
||||
// User selection. Remains random if user cancels.
|
||||
if(user)
|
||||
P = tgui_input_list(user, "Would you like to choose which link to sever?", "Sever link", active_pois)
|
||||
if(P && istype(P) && src.is_empty(P.my_index))
|
||||
random_index = P.my_index
|
||||
P.destroy_poi(user)
|
||||
active_pois[random_index] = null
|
||||
return random_index
|
||||
else
|
||||
return 0
|
||||
|
||||
if(is_empty(random_index)) // If this z-level is empty, destroy the poi
|
||||
P = active_pois[random_index]
|
||||
P.destroy_poi(user)
|
||||
active_pois[random_index] = null // Should be set in destroy_poi but this lets us use the z-level again if anything goes horribly wrong.
|
||||
return random_index
|
||||
|
||||
for(var/i = 1, i <= MAX_DYNAMIC_LEVELS, i++) // Level was not empty, check remaining levels
|
||||
if(i == random_index)
|
||||
continue // Don't run this one again.
|
||||
if(is_empty(i))
|
||||
P = active_pois[i]
|
||||
P.destroy_poi(user)
|
||||
active_pois[i] = null
|
||||
return i
|
||||
return 0
|
||||
|
||||
/obj/effect/overmap/visitable/dynamic/proc/is_empty(var/index, var/mob/observer)
|
||||
if(!LAZYLEN(map_z))
|
||||
log_and_message_admins("CANARY: [src] tried to check is_empty, but map_z is `[map_z || "null"]`")
|
||||
return TRUE
|
||||
if(!index)
|
||||
index = 1
|
||||
testing("Checking if sector at [map_z[index]] has no players.")
|
||||
for(var/mob/M in global.player_list)
|
||||
if(M != observer && (M.z == map_z[index]))
|
||||
testing("There are people on it.")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
// You generally shouldn't destroy these.
|
||||
/obj/effect/overmap/visitable/dynamic/Destroy()
|
||||
for(var/child in all_children)
|
||||
qdel(child)
|
||||
return ..()
|
||||
|
||||
// These are the player-viewable/interactible POI's which tell the parent how to use its z-levels. Spawned by the parent.
|
||||
/obj/effect/overmap/visitable/dynamic/poi
|
||||
name = "bluespace static"
|
||||
unknown_name = "bluespace static"
|
||||
unknown_state = "poi"
|
||||
known = FALSE
|
||||
scannable = TRUE
|
||||
invisibility = 0
|
||||
in_space = TRUE
|
||||
map_z = list(null) // Override parent value
|
||||
active_pois = null
|
||||
var/obj/effect/overmap/visitable/dynamic/parent // The object which created us.
|
||||
var/datum/map_template/dynamic_overmap/my_template
|
||||
var/last_scanned = 0 // Timer to prevent spamming POI loading/unloading since that's probably exploitable.
|
||||
var/loaded = FALSE
|
||||
var/my_index = 0 // Tracks which z-level we're using in the parent. Corresponds to index in parent's active_pois[]
|
||||
|
||||
/obj/effect/overmap/visitable/dynamic/poi/Initialize()
|
||||
if(!global.using_map.use_overmap)
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
// Normally Initialize() would do this but I need it to call after Initialize(), therefore new proc.
|
||||
/obj/effect/overmap/visitable/dynamic/poi/proc/seed_overmap()
|
||||
start_x = start_x || rand(OVERMAP_EDGE, global.using_map.overmap_size - OVERMAP_EDGE)
|
||||
start_y = start_y || rand(OVERMAP_EDGE, global.using_map.overmap_size - OVERMAP_EDGE)
|
||||
|
||||
forceMove(locate(start_x, start_y, global.using_map.overmap_z))
|
||||
|
||||
for(var/obj/effect/overmap/visitable/dynamic/poi/P in loc.contents) // If we've spawned on another poi, we'll try again once.
|
||||
if(P == src)
|
||||
continue
|
||||
start_x = start_x || rand(OVERMAP_EDGE, global.using_map.overmap_size - OVERMAP_EDGE)
|
||||
start_y = start_y || rand(OVERMAP_EDGE, global.using_map.overmap_size - OVERMAP_EDGE)
|
||||
forceMove(locate(start_x, start_y, global.using_map.overmap_z))
|
||||
break
|
||||
|
||||
if(!docking_codes)
|
||||
docking_codes = "[ascii2text(rand(65,90))][ascii2text(rand(65,90))][ascii2text(rand(65,90))][ascii2text(rand(65,90))]"
|
||||
|
||||
if(known)
|
||||
plane = PLANE_LIGHTING_ABOVE
|
||||
for(var/obj/machinery/computer/ship/helm/H in global.machines)
|
||||
H.get_known_sectors()
|
||||
else
|
||||
real_appearance = image(icon, src, my_template.poi_icon)
|
||||
real_appearance.override = TRUE
|
||||
name = unknown_name
|
||||
icon_state = unknown_state
|
||||
color = null
|
||||
desc = "Scan this to find out more information."
|
||||
|
||||
// Grab scanner info from map template, allow the user to load/unload POI's.
|
||||
/obj/effect/overmap/visitable/dynamic/poi/get_scan_data(user)
|
||||
scanner_desc = my_template.scanner_desc
|
||||
if(!known)
|
||||
known = TRUE
|
||||
name = my_template.name
|
||||
icon_state = my_template.poi_icon
|
||||
color = my_template.poi_color
|
||||
desc = initial(desc)
|
||||
|
||||
if(loaded)
|
||||
var/confirm = alert(user, "Sever bluespace link? This location will become permanently inaccessible.", "Are you sure?", "No", "Yes")
|
||||
if(confirm == "Yes")
|
||||
if(is_empty(1)) // Dynamic POI's should only ever have 1 entry in map_z
|
||||
destroy_poi(user) // Delete POI from dynamic z-level
|
||||
else
|
||||
to_chat(user, "Unable to sever link. Location likely contains living realspace entities.")
|
||||
else
|
||||
var/confirm = alert(user, "Transient subspace anomaly detected. Tether object to realspace?", "Stabilize anomaly?", "Yes", "No")
|
||||
if(confirm == "Yes")
|
||||
create_poi(user) // Load POI to dynamic z-level
|
||||
|
||||
return ..()
|
||||
|
||||
// Loads POI template into a dynamic z-level
|
||||
/obj/effect/overmap/visitable/dynamic/poi/proc/create_poi(mob/user)
|
||||
if(!parent) // Ideally this should never happen.
|
||||
log_and_message_admins("Dynamic overmap POI attempted to generate without a parent z-level.")
|
||||
qdel(src)
|
||||
return
|
||||
if(!my_template) // Also shouldn't happen.
|
||||
log_and_message_admins("Dynamic overmap POI attempted to generate without a map template.")
|
||||
qdel(src)
|
||||
return
|
||||
if(loaded) // These may only be created once.
|
||||
return
|
||||
if(last_scanned + 10 SECONDS > world.time)
|
||||
to_chat(user, "\[REDACTED\] matrix is still recharging!")
|
||||
return
|
||||
last_scanned = world.time
|
||||
|
||||
for(var/i = 1, i <= MAX_DYNAMIC_LEVELS, i++)
|
||||
if(!parent.active_pois[i]) // We found an unused z-level
|
||||
my_index = i
|
||||
parent.active_pois[i] = src
|
||||
map_z[1] = parent.map_z[i]
|
||||
map_sectors["[parent.map_z[i]]"] = src // Pass ownership of z-level to child, probably hacky and terribad, also mandatory for using forceMove() on shuttle landmarks
|
||||
break // Terminate loop
|
||||
if(!my_index) // No z-levels available
|
||||
var/confirm = alert(user, "\[REDACTED\] matrix at capacity; a bluespace link must be permanently severed to stabilize this anomaly. Continue?", "Are you sure?", "No", "Yes")
|
||||
if(confirm == "Yes")
|
||||
my_index = parent.cull_child(user)
|
||||
if(my_index)
|
||||
parent.active_pois[my_index] = src
|
||||
map_z[1] = parent.map_z[my_index]
|
||||
map_sectors["[parent.map_z[my_index]]"] = src
|
||||
else // Something went wrong, ideally due to all relevant z-levels containing players.
|
||||
to_chat(user, "Unable to sever any bluespace link. All links likely contain living realspace entities.")
|
||||
return
|
||||
else
|
||||
return
|
||||
|
||||
var/turf/T = locate(round(world.maxx/2), round(world.maxy/2), map_z[1]) // Find center turf, or near center for even-dimension maps.
|
||||
if(!istype(T))
|
||||
log_debug("Dynamic overmap POI found [T] instead of a valid turf.")
|
||||
return
|
||||
|
||||
// Move the shuttle landmarks.
|
||||
var/list/landmark_directions = parent.shuttle_landmarks[my_index] // Each shuttle_landmarks entry is an associative list.
|
||||
var/obj/effect/shuttle_landmark/om_poi/S = landmark_directions["FORE"]
|
||||
S.forceMove(locate(T.x, min(world.maxy, T.y + round(src.my_template.block_size/2) + rand(10,20)), T.z)) // Above
|
||||
add_landmark(S) // This lets overmap shuttles find our newly assigned z-level.
|
||||
S = landmark_directions["AFT"]
|
||||
S.forceMove(locate(T.x, max(1, T.y - round(src.my_template.block_size/2) - rand(10,20)), T.z))// Below
|
||||
add_landmark(S)
|
||||
S = landmark_directions["PORT"]
|
||||
S.forceMove(locate(max(1, T.x - round(src.my_template.block_size/2) - rand(10,20)), T.y, T.z)) // Left
|
||||
add_landmark(S)
|
||||
S = landmark_directions["STARBOARD"]
|
||||
S.forceMove(locate(min(world.maxx, T.x + round(src.my_template.block_size/2) + rand(10,20)), T.y, T.z)) // Right
|
||||
add_landmark(S)
|
||||
|
||||
my_template.load(T, centered=TRUE)
|
||||
loaded = TRUE
|
||||
my_template.update_lighting(T)
|
||||
to_chat(user, "Stabilization tether successfully created.")
|
||||
if(my_template.active_icon)
|
||||
icon_state = my_template.active_icon
|
||||
|
||||
/obj/effect/overmap/visitable/dynamic/poi/proc/destroy_poi(mob/user)
|
||||
if(!loaded) // Ideally this should never happen.
|
||||
log_debug("Dynamic overmap POI tried to unload itself but is not loaded.")
|
||||
return
|
||||
if(!parent) // Also shouldn't happen.
|
||||
log_and_message_admins("Dynamic overmap POI attempted to unload without a parent z-level.")
|
||||
loaded = FALSE // Always make sure loaded = FALSE before using qdel(src) in this proc to prevent an infinite loop in Destroy().
|
||||
qdel(src)
|
||||
return
|
||||
if(!((my_index >= 1) && (my_index <= MAX_DYNAMIC_LEVELS))) // Make sure my_index is sane
|
||||
log_debug("Dynamic overmap POI attempted to unload with an invalid index.")
|
||||
loaded = FALSE
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
map_sectors["[parent.map_z[my_index]]"] = parent // Pass ownership back to parent.
|
||||
parent.active_pois[my_index] = null
|
||||
if(!LAZYLEN(map_z)) // If this is 0, how did we get this far?
|
||||
log_and_message_admins("Dynamic overmap POI attempted to unload without a linked z-level.")
|
||||
loaded = FALSE
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
to_chat(user, "Destabilization initiated...")
|
||||
log_debug("Dynamic overmap POI unloading initiated...")
|
||||
// Some math to return a block of block_size turfs (+ 1 to each dimension to account for even-size maps lacking a true center to safely do math with). Basically, start from center turf and subtract half of block_size for bottom left corner, add for top right corner.
|
||||
var/list/turfs_to_reset = block(locate(round(world.maxx/2 - my_template.block_size/2 - 1), round(world.maxy/2 - my_template.block_size/2 - 1), map_z[1]), locate(round(world.maxx/2 + my_template.block_size/2 + 1), round(world.maxy/2 + my_template.block_size/2 + 1), map_z[1]))
|
||||
var/deleted_atoms = 0
|
||||
if(turfs_to_reset.len)
|
||||
var/area/A = parent.base_area
|
||||
if(ispath(A))
|
||||
A = locate(A)
|
||||
if(!istype(A))
|
||||
CRASH("Dynamic POI unloading couldn't locate area [A], unload aborted.")
|
||||
|
||||
for(var/turf/T in turfs_to_reset)
|
||||
for(var/atom/movable/AM in T)
|
||||
if(istype(AM, /mob/observer))
|
||||
continue
|
||||
++deleted_atoms
|
||||
qdel(AM)
|
||||
ChangeArea(T, A)
|
||||
T = T.ChangeTurf(/turf/space)
|
||||
loaded = FALSE
|
||||
map_z = null
|
||||
icon_state = "ring_destroyed"
|
||||
log_debug("Dynamic POI unload complete, [deleted_atoms] atoms destroyed.")
|
||||
to_chat(user, "Subspace pocket collapse successful.")
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/overmap/visitable/dynamic/poi/Destroy()
|
||||
if(loaded)
|
||||
if(is_empty()) // If we're deleted while loaded but the z-level is occupied, relinquish ownership instead.
|
||||
destroy_poi()
|
||||
else
|
||||
if(parent && (parent.active_pois.len >= my_index) && (parent.map_z.len >= my_index) && (my_index > 0)) // Unless vars are turbofucked.
|
||||
map_sectors["[parent.map_z[my_index]]"] = parent
|
||||
parent.active_pois[my_index] = null
|
||||
if(parent)
|
||||
parent.all_children.Remove(src)
|
||||
return ..()
|
||||
|
||||
// This assigns map_sectors which we don't want for this subtype since we have other procs to handle it.
|
||||
/obj/effect/overmap/visitable/dynamic/poi/register_z_levels()
|
||||
return
|
||||
|
||||
// Make sure we reassign our z_level to the parent if one exists and somehow this gets called.
|
||||
/obj/effect/overmap/visitable/dynamic/poi/unregister_z_levels()
|
||||
if(parent && LAZYLEN(map_z))
|
||||
map_sectors["[map_z[1]]"] = parent
|
||||
map_z = null
|
||||
return ..()
|
||||
|
||||
// Hahah recursion
|
||||
/obj/effect/overmap/visitable/dynamic/poi/create_children()
|
||||
return
|
||||
|
||||
/obj/effect/overmap/visitable/dynamic/poi/cull_child()
|
||||
return
|
||||
|
||||
/obj/effect/shuttle_landmark/om_poi // Landmarks used in dynamic poi generation
|
||||
flags = SLANDMARK_FLAG_AUTOSET
|
||||
base_area = /area/space
|
||||
base_turf = /turf/space
|
||||
|
||||
/obj/effect/shuttle_landmark/om_poi/Initialize(mapload, var/new_name, var/new_tag)
|
||||
name = new_name
|
||||
landmark_tag = new_tag
|
||||
. = ..()
|
||||
|
||||
#undef MAX_DYNAMIC_LEVELS
|
||||
#undef MAX_DYNAMIC_POI_DIMENSIONS
|
||||
81
modular_chomp/code/modules/player_tips/player_tips_list.dm
Normal file
81
modular_chomp/code/modules/player_tips/player_tips_list.dm
Normal file
@@ -0,0 +1,81 @@
|
||||
/* List of player tips
|
||||
Weighted to emphasize more important over less.area
|
||||
Weights are not additive. You can have multiple prob(50) items.
|
||||
prob(50) makes it half as likely to appear and so forth.
|
||||
When editing the list, please try and keep similar probabilities near each other. High on top, low on bottom */
|
||||
|
||||
//argument determines if to pick a random tip or use a forced choice.
|
||||
/datum/player_tips/proc/pick_tip(var/isSpecific)
|
||||
var/choice = null
|
||||
if(!(isSpecific == "none" || isSpecific == "general" || isSpecific == "gameplay" || isSpecific == "roleplay" || isSpecific == "lore" ))
|
||||
choice = "none" //Making sure that wrong arguments still give tips.
|
||||
if(isSpecific == "none")
|
||||
choice = pick (
|
||||
prob(50); "general",
|
||||
prob(50); "gameplay",
|
||||
prob(25); "roleplay",
|
||||
prob(20); "lore"
|
||||
)
|
||||
else
|
||||
choice = isSpecific
|
||||
|
||||
switch(choice)
|
||||
if("general")
|
||||
var/info = "The following is a general tip to playing on CHOMPStation! You can disable them using the periodic tips toggle in the Global tab of character setup! \n"
|
||||
return pick(
|
||||
prob(60); "[info] Got a question about gameplay, roleplay or the setting? Press F1 to Mentorhelp!",
|
||||
prob(60); "[info] We have a wiki that is actively updated! Please check it out at https://wiki.chompstation13.net/index.php/Chomp_Station_Wiki for help!",
|
||||
prob(60); "[info] Unsure about rules? Press F1 and ask our admins for clarification - they are happy to help.",
|
||||
prob(30); "[info] Don't be afraid to approach your fellow players for advice! Learning things ICly can help build powerful bonds!",
|
||||
prob(30); "[info] Need some guideance making a character or with roleplay concepts? Our discord's tutoring channel is happy to help!",
|
||||
prob(30); "[info] Having difficulties getting started? Pressing F3 to speak and typing '; Hello! I'm a new hire. Could someone please give me a tour?' or as appropriate for your character is a good way to start! More help available at: https://wiki.chompstation13.net/index.php/The_Basics",
|
||||
prob(30); "[info] Want to try out a new department? Consider joining as an intern when it's well-staffed. Our players enjoy teaching eager students. You can approach such roleplay as simply getting taught the local technologies, procedures - you don't need to be 'fresh out of school' to justify it!",
|
||||
prob(30); "[info] Our discord is an excellent resource to stay up to date about changes and events! If wanting to separate your kink and real identities, Discord has a built in means to swap accounts within the client. It is OK to lurk!",
|
||||
prob(5); "[info] Got another tip for the list? Please let us know on Discord in the feedback forums!"
|
||||
)
|
||||
|
||||
|
||||
if("gameplay")
|
||||
var/info = "The following is a gameplay-focused tip to playing on CHOMPStation! You can disable them using the periodic tips toggle in the Global tab of character setup! \n"
|
||||
return pick(
|
||||
prob(50); "[info] To talk to your fellow coworkers, use ';'! You may append it by an exclamation mark, like ';!' to perform an audiable emote. ",
|
||||
prob(50); "[info] Lost on the map? You can find In-Character help by speaking on the Common Radio. You can do this by pressing F3 and typing ' ; ' before your message. Your fellow co-workers will likely help. If OOC help is preferred, press F1 for mentorhelp. ",
|
||||
prob(50); "[info] You may set your suit sensors by clicking on the icon in the bottom left corner, then right click the clothes that appear right above it. It is recommended to turn on suit sensors to 'TRACKING' before doing anything dangerous like mining, and to turn them off before digestion scenes as prey.",
|
||||
prob(35); "[info] It is never a bad idea to visit the medbay if you get injured - small burns and cuts can get infected and become harder to treat! If there is no medical staff, bathrooms and the bar often has a NanoMed on the wall while a medical station can be found on the first deck - with ointments to disinfect cuts and burns, bandages to treat bruises and encourage healing.",
|
||||
prob(25); "[info] Two control modes exist for SS13 - hotkey ON and hotkey OFF. You can swap between the two modes by pressing TAB. In hotkey mode, to chat you need to press T to say anything which creates a small talking bubble.",
|
||||
prob(25); "[info] Do you want to shift your character around, for instance to appear as if leaning on the wall? Press CTRL + SHIFT + arrow keys to do so! Moving resets this.",
|
||||
prob(25); "[info] Emergency Fire Doors seal breaches and keep active fires out. Please do not open them without good reason. SHIFT + CLICK them to get temperature and atmospheric pressure readings.",
|
||||
prob(25); "[info] The kitchen's Oven can fit multiple ingredients in one slot if you pull the baking tray out first. This is required for most recipes, and the Grille and Deep Frier work the same way!",
|
||||
prob(10); "[info] Not every hostile NPC you encounter while mining or exploring need to be defeated. Sometimes, it's better to avoid or run away from them.",
|
||||
prob(1); "[info] Stay robust, my friends.",
|
||||
prob(35); "[info] You can insert your I.D into your PDA. This frees up your belt from having to carry your PDA. Furthermore, by clicking and dragging the PDA to game screen, you can use it without holding it!",
|
||||
prob(35); "[info] Your vore-bellies have multiple add-ons! Muffling is excellent to ensure your prey does not accidentally inform everyone about their predicament, and jam suit sensors is a great courtesy to avoid medical being worried about your prey!"
|
||||
)
|
||||
|
||||
if("roleplay")
|
||||
var/info = "The following is a roleplay-focused tip to playing on CHOMPStation! You can disable them using the periodic tips toggle in the Global tab of character setup! \n"
|
||||
return pick(
|
||||
prob(50); "[info] Having difficulty finding scenes? The number one tip that people should take for finding scenes is to be active! Generally speaking, people are more likely to interact with you if you are moving about and doing things. Don't be afraid to talk to people, you're less likely to be approached if you're sat alone at a table silently. People that are looking for scenes generally like to see how you type and RP before they'll start working towards a scene with you.",
|
||||
prob(50); "[info] Please avoid a character that knows everything. Having only a small set of jobs you are capable of doing can help flesh out your character! It's OK for things to break and fail if nobody is around to fix it - you do not need to do others' jobs.",
|
||||
prob(25); "[info] Embrace the limits of your character's skillsets! Seeking out other players to help you with a more challenging task might build friendships, or even lead to a scene!",
|
||||
prob(25); "[info] Slowing down when meeting another player can help with finding roleplay! Your fellow player might be typing up a greeting or an emote, and if you run off you won't see it!",
|
||||
prob(25); "[info] It is a good idea to wait a few moments after using mechanics like lick, hug or headpat on another player. They might be typing up a response or wish to reciprocate, and if you run away you might miss out!",
|
||||
prob(25); "[info] Participating in an away mission and see something acting strange? Try emoting or talking to it before resorting to fighting. It may be a GM event!",
|
||||
prob(15); "[info] We are a medium roleplay server. This does not neccessarily mean 'serious' roleplay, levity and light-hearted RP is more than welcome! Please do not ignore people just because it is unlikely you will be able to scene.",
|
||||
prob(10); "[info] Sending faxes to central command, using the 'pray' verb or pressing F1 to ahelp are highly encouraged when exploring the gateway or overmap locations! Letting GMs know something fun is happening allows them to spice things up and make the world feel alive!",
|
||||
prob(40); "[info] Just because you see something doesn't mean your character has to. A courtesy 'missing' of contraband or scene details can go a long way towards preserving everyone's fun!",
|
||||
prob(25); "[info] It is always a good idea to communicate on your department's private channel (whose key you can learn by examining your headset) when responding to an emergency! This lets your coworkers know if they might be needed!",
|
||||
prob(25); "[info] While following the SOP is not mandatory, and you are free to break it (albeit, with potential in-character consequences), departments like security and medical do well to be familiar with them! https://wiki.chompstation13.net/index.php/Standard_Operating_Procedure",
|
||||
prob(25); "[info] Think a player is acting especially antagonistic? It might be better to Ahelp (with F1) rather than try to deal with it icly, staff can make sure it's all okay.",
|
||||
prob(20); "[info] See a minor infraction as Security with a minimal time punishment? Consider using your ticket printer to give a non obtrusive punishment."
|
||||
)
|
||||
|
||||
if("lore")
|
||||
var/info = "The following is tip for understanding the lore of CHOMPStation! You can disable them using the periodic tips toggle in the Global tab of character setup! \n"
|
||||
return pick(
|
||||
prob(25); "[info] Our lore is somewhat in line with other servers. But not Virgo's. They wrote themselves out of the timeline, lol. The year is 2564 (current year+541).",
|
||||
prob(75); "[info] You can find a short summary of our setting that everyone should know at https://wiki.chompstation13.net/index.php/Lore",
|
||||
prob(50); "[info] You are currently working in the Vir system on the NLS Southern Cross telecommunications and traffic control station. https://wiki.chompstation13.net/index.php/Vir",
|
||||
prob(50); "[info] The majority of employees live at the Northern Star asteroid colony orbiting a gas giant called Kara. It is also a central hub for visitors, logistics, and mining. This is the place the shuttle takes you at the end of the round. You may visit the mines via the exploration shuttles. https://wiki.chompstation13.net/index.php/NCS_Northern_Star",
|
||||
prob(10); "[info] Thaler is a universal monopoly money. It is backed and supported by Sol Central and its allies. While ubiquitous in frontier worlds, it has an unfavourable exchange rate with most currencies used by well-settled regions, limiting immigration to places such as Earth. https://wiki.chompstation13.net/index.php/Lore"
|
||||
)
|
||||
@@ -1,3 +1,19 @@
|
||||
/datum/design/item/mechfab/rigsuit/phase
|
||||
name = "hardsuit phase rifle"
|
||||
desc = "A compact phase rifle for a hardsuit."
|
||||
id = "rig_gun_phase"
|
||||
req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 4, TECH_MAGNET = 3, TECH_POWER = 4, TECH_COMBAT = 4)
|
||||
materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 1250)
|
||||
build_path = /obj/item/rig_module/mounted/phase
|
||||
|
||||
/datum/design/item/mechfab/rigsuit/defib
|
||||
name = "hardsuit defib unit"
|
||||
desc = "A rig mounted defib and jumper kit combo."
|
||||
id = "rig_defib"
|
||||
req_tech = list(TECH_BIO = 5, TECH_MAGNET = 2, TECH_POWER = 3)
|
||||
materials = list(DEFAULT_WALL_MATERIAL = 6000, "glass" = 2000)
|
||||
build_path = /obj/item/rig_module/device/defib
|
||||
|
||||
/datum/design/item/mecha/phoron_bore
|
||||
name = "PB-23 \"Phobos\" Phoron Bore"
|
||||
category = list("Exosuit Equipment")
|
||||
@@ -111,18 +127,11 @@
|
||||
time = 20
|
||||
materials = list(DEFAULT_WALL_MATERIAL = 15000, MAT_PHORON = 2000, MAT_GOLD = 2000, MAT_VERDANTIUM = 500)
|
||||
|
||||
/datum/design/item/mechfab/rigsuit/phase
|
||||
name = "hardsuit phase rifle"
|
||||
desc = "A compact phase rifle for a hardsuit."
|
||||
id = "rig_gun_phase"
|
||||
req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 4, TECH_MAGNET = 3, TECH_POWER = 4, TECH_COMBAT = 4)
|
||||
materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 1250)
|
||||
build_path = /obj/item/rig_module/mounted/phase
|
||||
|
||||
/datum/design/item/mechfab/rigsuit/defib
|
||||
name = "hardsuit defib unit"
|
||||
desc = "A rig mounted defib and jumper kit combo."
|
||||
id = "rig_defib"
|
||||
req_tech = list(TECH_BIO = 5, TECH_MAGNET = 2, TECH_POWER = 3)
|
||||
materials = list(DEFAULT_WALL_MATERIAL = 6000, "glass" = 2000)
|
||||
build_path = /obj/item/rig_module/device/defib
|
||||
/datum/design/item/mechfab/rigsuit/precursor
|
||||
name = "Xenotech Rig"
|
||||
desc = "A rig made of alien tech and materials."
|
||||
id = "rigmodule_precursor"
|
||||
time = 30
|
||||
req_tech = list(TECH_MATERIAL = 9, TECH_ENGINEERING = 6, TECH_PHORON = 5, TECH_MAGNET = 6, TECH_POWER = 6, TECH_ILLEGAL = 8, TECH_PRECURSOR = 3)
|
||||
materials = list(MAT_PLASTEEL = 12000, MAT_GOLD = 5000, MAT_GRAPHITE = 8000, MAT_OSMIUM = 3000, MAT_PLASTIC = 6000, MAT_VERDANTIUM = 7500, MAT_MORPHIUM = 20000)
|
||||
build_path = /obj/item/weapon/rig/ch/precursor
|
||||
|
||||
@@ -6,9 +6,8 @@
|
||||
// And optionally, this could be gated behind another preference, to prevent stunlock being abused.
|
||||
if((mob_always_swap || (a_intent == I_HELP || src.restrained()) && (target.a_intent == I_HELP || target.restrained())) && target.canmove && target.handle_micro_bump_helping(src))
|
||||
return
|
||||
else if(!(target.a_intent == I_HELP || target.restrained()) && target.handle_micro_bump_other(src))
|
||||
if(!(target.a_intent == I_HELP || target.restrained()))
|
||||
if(src.step_mechanics_pref && target.step_mechanics_pref)
|
||||
target.handle_micro_bump_other(src)
|
||||
else
|
||||
target.handle_micro_bump_other(src, 1)
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user