Planetary Meteors (#8422)
* Begins work on Planetary meteors * Work, clean meteor code. * Continues work. Meteors now handle their own movement and launching. * New meteor types, some added to waves. Large meteor type fully implemented. * Fix and adjust for comments.
@@ -9,6 +9,7 @@
|
||||
#define MAP_LEVEL_XENOARCH_EXEMPT 0x080 // Z-levels exempt from xenoarch digsite generation.
|
||||
#define MAP_LEVEL_PERSIST 0x100 // Z-levels where SSpersistence should persist between rounds
|
||||
#define MAP_LEVEL_MAPPABLE 0x200 // Z-levels where mapping units will work fully
|
||||
#define MAP_LEVEL_UNDERGROUND 0x400 // Z-levels that are subterranean.
|
||||
|
||||
// Misc map defines.
|
||||
#define SUBMAP_MAP_EDGE_PAD 15 // Automatically created submaps are forbidden from being this close to the main map's edge.
|
||||
@@ -41,7 +41,8 @@
|
||||
#define ARCHAEO_SYRINGE 41
|
||||
#define ARCHAEO_RING 42
|
||||
#define ARCHAEO_CLUB 43
|
||||
#define MAX_ARCHAEO 43
|
||||
#define ARCHAEO_METEOR 44
|
||||
#define MAX_ARCHAEO 44
|
||||
|
||||
#define DIGSITE_GARDEN 1
|
||||
#define DIGSITE_ANIMAL 2
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
//for normal meteor event
|
||||
/var/list/meteors_normal = list(
|
||||
/obj/effect/meteor/dust=3,
|
||||
/obj/effect/meteor/medium=8,
|
||||
/obj/effect/meteor/medium=5,
|
||||
/obj/effect/meteor/medium/spalling = 3,
|
||||
/obj/effect/meteor/big=3,
|
||||
/obj/effect/meteor/flaming=1,
|
||||
/obj/effect/meteor/irradiated=3
|
||||
@@ -17,7 +18,8 @@
|
||||
|
||||
//for threatening meteor event
|
||||
/var/list/meteors_threatening = list(
|
||||
/obj/effect/meteor/medium=5,
|
||||
/obj/effect/meteor/medium=3,
|
||||
/obj/effect/meteor/medium/spalling = 2,
|
||||
/obj/effect/meteor/big=10,
|
||||
/obj/effect/meteor/flaming=3,
|
||||
/obj/effect/meteor/irradiated=3,
|
||||
@@ -25,10 +27,12 @@
|
||||
|
||||
//for catastrophic meteor event
|
||||
/var/list/meteors_catastrophic = list(
|
||||
/obj/effect/meteor/medium=5,
|
||||
/obj/effect/meteor/medium=2,
|
||||
/obj/effect/meteor/medium/spalling = 3,
|
||||
/obj/effect/meteor/big=75,
|
||||
/obj/effect/meteor/flaming=10,
|
||||
/obj/effect/meteor/irradiated=10,
|
||||
/obj/effect/meteor/irradiated=8,
|
||||
/obj/effect/meteor/irradiated/super=2,
|
||||
/obj/effect/meteor/emp=10)
|
||||
|
||||
|
||||
@@ -38,7 +42,7 @@
|
||||
///////////////////////////////
|
||||
|
||||
/proc/spawn_meteors(var/number = 10, var/list/meteortypes, var/startSide, var/zlevel)
|
||||
log_debug("Spawning [number] meteors on the [dir2text(startSide)] of [zlevel]")
|
||||
log_debug("Spawning [number] meteors on the [dir2text(startSide)] of [zlevel].")
|
||||
for(var/i = 0; i < number; i++)
|
||||
spawn_meteor(meteortypes, startSide, zlevel)
|
||||
|
||||
@@ -46,19 +50,26 @@
|
||||
if(isnull(startSide))
|
||||
startSide = pick(cardinal)
|
||||
if(isnull(startLevel))
|
||||
startLevel = pick(using_map.station_levels - using_map.sealed_levels)
|
||||
startLevel = pick(using_map.station_levels - using_map.underground_levels)
|
||||
|
||||
var/turf/pickedstart = spaceDebrisStartLoc(startSide, startLevel)
|
||||
var/turf/pickedgoal = spaceDebrisFinishLoc(startSide, startLevel)
|
||||
|
||||
var/Me = pickweight(meteortypes)
|
||||
var/obj/effect/meteor/M = new Me(pickedstart)
|
||||
M.dest = pickedgoal
|
||||
spawn(0)
|
||||
walk_towards(M, M.dest, 1)
|
||||
|
||||
if(M.planetary && !pickedgoal.outdoors)
|
||||
var/list/Targ = check_trajectory(pickedgoal, pickedstart, PASSTABLE)
|
||||
if(LAZYLEN(Targ))
|
||||
var/turf/TargetTurf = get_step(get_turf(Targ[1]), get_dir(pickedgoal, pickedstart))
|
||||
if(get_dist(pickedstart, Targ[1]) < get_dist(pickedstart, pickedgoal))
|
||||
pickedgoal = TargetTurf
|
||||
|
||||
M.launch_to_turf(pickedgoal, 1)
|
||||
|
||||
return
|
||||
|
||||
/proc/spaceDebrisStartLoc(startSide, Z)
|
||||
/proc/spaceDebrisStartLoc(var/startSide, var/Z, var/planetary)
|
||||
var/starty
|
||||
var/startx
|
||||
switch(startSide)
|
||||
@@ -77,7 +88,7 @@
|
||||
var/turf/T = locate(startx, starty, Z)
|
||||
return T
|
||||
|
||||
/proc/spaceDebrisFinishLoc(startSide, Z)
|
||||
/proc/spaceDebrisFinishLoc(var/startSide, var/Z, var/planetary)
|
||||
var/endy
|
||||
var/endx
|
||||
switch(startSide)
|
||||
@@ -113,11 +124,21 @@
|
||||
anchored = TRUE
|
||||
var/hits = 4
|
||||
var/hitpwr = 2 //Level of ex_act to be called on hit.
|
||||
var/dest
|
||||
var/atom/dest
|
||||
var/atom/start
|
||||
var/startheight = 0
|
||||
pass_flags = PASSTABLE
|
||||
var/heavy = FALSE
|
||||
var/z_original
|
||||
|
||||
// Planetary meteors slope in, and impact only their target turf. They can be hard to see before impact, but have a shadow.
|
||||
var/planetary
|
||||
var/curheight = 0 // How "high" we are
|
||||
// They also have shadows.
|
||||
var/obj/effect/projectile_shadow/shadow
|
||||
|
||||
var/list/chunk_tech = list(TECH_MATERIAL = 5)
|
||||
|
||||
var/meteordrop = /obj/item/weapon/ore/iron
|
||||
var/dropamt = 2
|
||||
|
||||
@@ -129,6 +150,9 @@
|
||||
/obj/effect/meteor/Initialize()
|
||||
. = ..()
|
||||
z_original = z
|
||||
var/turf/T = get_turf(src)
|
||||
if(T.outdoors)
|
||||
planetary = TRUE
|
||||
GLOB.meteor_list += src
|
||||
SpinAnimation()
|
||||
|
||||
@@ -141,13 +165,22 @@
|
||||
|
||||
/obj/effect/meteor/Moved(atom/old_loc, direction, forced = FALSE)
|
||||
. = ..()
|
||||
|
||||
handle_unique_movement(old_loc, direction)
|
||||
|
||||
// Planetary roids only hit the turf they target, since they're, you know, in the air.
|
||||
if(!planetary)
|
||||
var/turf/T = get_turf(loc)
|
||||
ram_turf(T)
|
||||
|
||||
if(prob(10) && !istype(T, /turf/space)) //randomly takes a 'hit' from ramming
|
||||
get_hit()
|
||||
else if(shadow) // We are planetary, and have a shadow. So make it keep up.
|
||||
shadow.forceMove(get_turf(src))
|
||||
|
||||
/obj/effect/meteor/Destroy()
|
||||
if(shadow)
|
||||
QDEL_NULL(shadow)
|
||||
walk(src,FALSE) //this cancels the walk_towards() proc
|
||||
GLOB.meteor_list -= src
|
||||
return ..()
|
||||
@@ -155,6 +188,11 @@
|
||||
/obj/effect/meteor/Bump(atom/A)
|
||||
if(A)
|
||||
if(A.handle_meteor_impact(src)) // Used for special behaviour when getting hit specifically by a meteor, like a shield.
|
||||
|
||||
if(planetary)
|
||||
if(curheight > 1)
|
||||
forceMove(get_turf(A))
|
||||
else
|
||||
ram_turf(get_turf(A))
|
||||
get_hit()
|
||||
else
|
||||
@@ -163,6 +201,67 @@
|
||||
/obj/effect/meteor/CanPass(atom/movable/mover, turf/target)
|
||||
return istype(mover, /obj/effect/meteor) ? TRUE : ..()
|
||||
|
||||
/obj/effect/meteor/proc/launch_to_turf(var/target, var/delay = 0)
|
||||
dest = get_turf(target)
|
||||
start = get_turf(src)
|
||||
var/turf/Current = get_turf(src)
|
||||
var/turf/Target = get_turf(target)
|
||||
if(Current.outdoors)
|
||||
startheight = rand(5,15)
|
||||
|
||||
if(planetary && !Target.outdoors)
|
||||
startheight = rand(5, 20) // Random "height" of falling meteors. Angle of attack, changes visibility.
|
||||
|
||||
move_toward(Target, delay, TRUE) // Begin the movement loop.
|
||||
|
||||
/obj/effect/meteor/proc/move_toward(var/target, var/delay = 0, var/allow_recursion = FALSE)
|
||||
if(!target)
|
||||
return
|
||||
|
||||
var/turf/StartTurf = get_turf(src)
|
||||
var/turf/EndTurf = get_step(StartTurf, get_dir(StartTurf, target))
|
||||
|
||||
if(planetary)
|
||||
if(!shadow)
|
||||
shadow = new(get_turf(src))
|
||||
shadow.pixel_y = -20
|
||||
|
||||
if(loc == dest)
|
||||
die(TRUE)
|
||||
return
|
||||
|
||||
var/dist_percent = calc_distance_percent()
|
||||
if(!isnull(dist_percent))
|
||||
curheight = startheight * dist_percent
|
||||
src.pixel_y = (curheight * 32)
|
||||
|
||||
if(EndTurf) // Have we somehow reached the edge of a map without a teleport boundary?
|
||||
Move(EndTurf, delay)
|
||||
if(get_turf(src) == StartTurf) // If it doesn't move, IE, is blocked by something, take a hit.
|
||||
get_hit()
|
||||
|
||||
if(allow_recursion)
|
||||
if(!QDELETED(src))
|
||||
addtimer(CALLBACK(src, .proc/move_toward, target, delay, allow_recursion), delay)
|
||||
|
||||
else if(!QDELETED(src)) // Then delete ourselves if we haven't been deleted already.
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/effect/meteor/proc/calc_distance_percent()
|
||||
var/current_dest_distance
|
||||
var/max_dest_distance
|
||||
|
||||
if(!start)
|
||||
start = get_turf(src)
|
||||
|
||||
if(!dest)
|
||||
return 0
|
||||
|
||||
current_dest_distance = get_dist(get_turf(src), dest)
|
||||
max_dest_distance = get_dist(start, dest)
|
||||
return current_dest_distance / max_dest_distance
|
||||
|
||||
/obj/effect/meteor/proc/ram_turf(var/turf/T)
|
||||
//first bust whatever is in the turf
|
||||
for(var/atom/A in T)
|
||||
@@ -178,7 +277,6 @@
|
||||
var/turf/simulated/wall/W = T
|
||||
W.take_damage(wall_power) // Stronger walls can halt asteroids.
|
||||
|
||||
|
||||
//process getting 'hit' by colliding with a dense object
|
||||
//or randomly when ramming turfs
|
||||
/obj/effect/meteor/proc/get_hit()
|
||||
@@ -186,9 +284,15 @@
|
||||
if(hits <= 0)
|
||||
die(TRUE)
|
||||
|
||||
|
||||
// Meteor effects on traversal.
|
||||
/obj/effect/meteor/proc/handle_unique_movement(var/turf/oldloc, var/direction)
|
||||
return
|
||||
|
||||
/obj/effect/meteor/proc/die(var/explode = TRUE)
|
||||
make_debris()
|
||||
meteor_effect(explode)
|
||||
if(!QDELETED(src))
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/meteor/ex_act()
|
||||
@@ -213,6 +317,10 @@
|
||||
return
|
||||
|
||||
/obj/effect/meteor/proc/make_debris()
|
||||
if(prob(5 * dropamt))
|
||||
var/obj/item/meteor_chunk/MC = new(get_turf(src))
|
||||
MC.copy_meteor(src)
|
||||
MC.throw_at(dest, 5, 10)
|
||||
for(var/throws = dropamt, throws > 0, throws--)
|
||||
var/obj/item/O = new meteordrop(get_turf(src))
|
||||
O.throw_at(dest, 5, 10)
|
||||
@@ -244,17 +352,35 @@
|
||||
meteordrop = /obj/item/weapon/ore/glass
|
||||
wall_power = 50
|
||||
|
||||
chunk_tech = list(TECH_MATERIAL = 3)
|
||||
|
||||
// Medium-sized meteors aren't very special and can be stopped easily by r-walls.
|
||||
/obj/effect/meteor/medium
|
||||
name = "meteor"
|
||||
dropamt = 3
|
||||
wall_power = 200
|
||||
|
||||
chunk_tech = list(TECH_MATERIAL = 5)
|
||||
|
||||
/obj/effect/meteor/medium/meteor_effect(var/explode)
|
||||
..()
|
||||
if(explode)
|
||||
explosion(src.loc, 0, 1, 2, 3, 0)
|
||||
|
||||
/obj/effect/meteor/medium/spalling
|
||||
name = "spalling meteor"
|
||||
wall_power = 150
|
||||
|
||||
chunk_tech = list(TECH_MATERIAL = 5, TECH_COMBAT = 3)
|
||||
|
||||
/obj/effect/meteor/medium/spalling/handle_unique_movement(var/turf/oldloc, var/direction)
|
||||
var/turf/T = get_turf(src)
|
||||
if(prob(20))
|
||||
for(var/I = 1 to rand(2,5))
|
||||
var/obj/item/projectile/bullet/pellet/fragment/meteor/frag = new(T)
|
||||
var/turf/Targ = pick(orange(7,src))
|
||||
frag.launch_projectile_from_turf(Targ, BP_TORSO)
|
||||
|
||||
// Large-sized meteors generally pack the most punch, but are more concentrated towards the epicenter.
|
||||
/obj/effect/meteor/big
|
||||
name = "large meteor"
|
||||
@@ -264,11 +390,41 @@
|
||||
dropamt = 4
|
||||
wall_power = 400
|
||||
|
||||
chunk_tech = list(TECH_MATERIAL = 6)
|
||||
|
||||
/obj/effect/meteor/big/meteor_effect(var/explode)
|
||||
..()
|
||||
if(explode)
|
||||
explosion(src.loc, 1, 2, 3, 4, 0)
|
||||
|
||||
// Huge-sized meteors pack -the biggest- punch, leaving a clump of rock behind.
|
||||
/obj/effect/meteor/huge
|
||||
name = "massive meteor"
|
||||
icon_state = "large"
|
||||
hits = 10
|
||||
hitpwr = 0
|
||||
heavy = 1
|
||||
dropamt = 0
|
||||
wall_power = 800
|
||||
|
||||
var/spawned_terrain = FALSE
|
||||
|
||||
chunk_tech = list(TECH_MATERIAL = 7)
|
||||
|
||||
/obj/effect/meteor/huge/Initialize()
|
||||
. = ..()
|
||||
adjust_scale(2)
|
||||
|
||||
/obj/effect/meteor/huge/meteor_effect(var/explode)
|
||||
..()
|
||||
if(!spawned_terrain)
|
||||
spawned_terrain = TRUE
|
||||
var/dest_x = x - 2
|
||||
var/dest_y = y - 2
|
||||
var/dest_z = z
|
||||
spawn(0) // Needs to be asynchronous due to how spawning the maps functions.
|
||||
new /datum/random_map/meteor(null, dest_x, dest_y, dest_z)
|
||||
|
||||
// 'Flaming' meteors do less overall damage but are spread out more due to a larger but weaker explosion at the end.
|
||||
/obj/effect/meteor/flaming
|
||||
name = "flaming meteor"
|
||||
@@ -278,6 +434,8 @@
|
||||
meteordrop = /obj/item/weapon/ore/phoron
|
||||
wall_power = 100
|
||||
|
||||
chunk_tech = list(TECH_MATERIAL = 6, TECH_PHORON = 4)
|
||||
|
||||
/obj/effect/meteor/flaming/meteor_effect(var/explode)
|
||||
..()
|
||||
if(explode)
|
||||
@@ -291,6 +449,7 @@
|
||||
meteordrop = /obj/item/weapon/ore/uranium
|
||||
wall_power = 75
|
||||
|
||||
chunk_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 5)
|
||||
|
||||
/obj/effect/meteor/irradiated/meteor_effect(var/explode)
|
||||
..()
|
||||
@@ -299,6 +458,17 @@
|
||||
new /obj/effect/decal/cleanable/greenglow(get_turf(src))
|
||||
SSradiation.radiate(src, 50)
|
||||
|
||||
// A -supermatter- irradiated meteor.
|
||||
/obj/effect/meteor/irradiated/super
|
||||
name = "supermatteor"
|
||||
desc = "Act of god, or ejected core gone wrong, something terrible is going to happen."
|
||||
icon_state = "glowing_blue"
|
||||
|
||||
chunk_tech = list(TECH_MATERIAL = 7, TECH_ENGINEERING = 6)
|
||||
|
||||
meteordrop = /obj/item/stack/material/supermatter
|
||||
wall_power = 200
|
||||
|
||||
// This meteor fries toasters.
|
||||
/obj/effect/meteor/emp
|
||||
name = "conducting meteor"
|
||||
@@ -308,6 +478,8 @@
|
||||
dropamt = 3
|
||||
wall_power = 80
|
||||
|
||||
chunk_tech = list(TECH_MATERIAL = 6, TECH_POWER = 5)
|
||||
|
||||
/obj/effect/meteor/emp/meteor_effect(var/explode)
|
||||
..()
|
||||
// Best case scenario: Comparable to a low-yield EMP grenade.
|
||||
@@ -325,6 +497,8 @@
|
||||
meteordrop = /obj/item/weapon/ore/phoron
|
||||
wall_power = 150
|
||||
|
||||
chunk_tech = list(TECH_MATERIAL = 10, TECH_PHORON = 8)
|
||||
|
||||
/obj/effect/meteor/tunguska/meteor_effect(var/explode)
|
||||
..()
|
||||
if(explode)
|
||||
@@ -334,3 +508,56 @@
|
||||
..()
|
||||
if(prob(20))
|
||||
explosion(src.loc,2,4,6,8)
|
||||
|
||||
// Meat. It's a- it's- it has- It's a meatyor.
|
||||
|
||||
/obj/effect/meteor/meaty
|
||||
name = "meatyor"
|
||||
desc = "A horrific amalgam of compacted flesh. Your skin crawls looking at this."
|
||||
icon_state = "meat"
|
||||
|
||||
wall_power = 70
|
||||
hits = 3
|
||||
hitpwr = 1
|
||||
|
||||
meteordrop = /obj/item/weapon/reagent_containers/food/snacks/meat
|
||||
dropamt = 4
|
||||
|
||||
// Blob! By default, it spawns a blob weaker than the lethargic by grow-rate, but slightly hardier defense-wise. Like a barnacle, from space!
|
||||
/obj/effect/meteor/blobby
|
||||
name = "blobteor"
|
||||
desc = "A pulsing amalgam of gel. It writhes."
|
||||
icon_state = "blob"
|
||||
|
||||
wall_power = 120
|
||||
hits = 5
|
||||
hitpwr = 1
|
||||
|
||||
meteordrop = /obj/structure/blob/core/barnacle
|
||||
dropamt = 1
|
||||
|
||||
/*
|
||||
* Meteor core chunks.
|
||||
*/
|
||||
|
||||
/obj/item/meteor_chunk // It's not just a pebble.. it's a rock! From space!
|
||||
name = "meteoric iron"
|
||||
desc = "A meteor chunk. Cool."
|
||||
icon = 'icons/obj/meteor.dmi'
|
||||
icon_state = "small"
|
||||
w_class = ITEMSIZE_SMALL
|
||||
origin_tech = list(TECH_MATERIAL = 5)
|
||||
|
||||
/obj/item/meteor_chunk/proc/copy_meteor(var/obj/effect/meteor/Parent)
|
||||
if(!Parent)
|
||||
return FALSE
|
||||
|
||||
name = "[Parent.name]ite chunk" // The single case this doesn't presently work for meteors would be incredibly funny, "space dustite", and so I leave it.
|
||||
desc = "A recovered piece of a [Parent.name]."
|
||||
icon_state = Parent.icon_state
|
||||
|
||||
adjust_scale(0.7)
|
||||
return TRUE
|
||||
|
||||
/obj/item/meteor_chunk/ex_act() // Meteor tuff
|
||||
return
|
||||
|
||||
@@ -92,6 +92,9 @@ var/list/blob_cores = list()
|
||||
/obj/structure/blob/core/ectoplasmic_horror
|
||||
desired_blob_type = /datum/blob_type/ectoplasmic_horror
|
||||
|
||||
/obj/structure/blob/core/barnacle
|
||||
desired_blob_type = /datum/blob_type/barnacle
|
||||
|
||||
/obj/structure/blob/core/classic
|
||||
desired_blob_type = /datum/blob_type/classic
|
||||
|
||||
|
||||
40
code/modules/blob2/overmind/types/barnacle.dm
Normal file
@@ -0,0 +1,40 @@
|
||||
|
||||
/datum/blob_type/barnacle
|
||||
name = "barnacloid blob"
|
||||
desc = "A mass that seems densely wound around its core."
|
||||
ai_desc = "sedentary"
|
||||
effect_desc = "Will not create any nodes. Has slightly higher resistances."
|
||||
difficulty = BLOB_DIFFICULTY_EASY
|
||||
color = "#383838"
|
||||
complementary_color = "#c04761"
|
||||
can_build_nodes = FALSE
|
||||
spread_modifier = 0.1
|
||||
ai_aggressiveness = 0
|
||||
|
||||
brute_multiplier = 0.35
|
||||
burn_multiplier = 0.8
|
||||
|
||||
/datum/blob_type/barnacle/on_chunk_use(obj/item/weapon/blobcore_chunk/B, mob/living/user)
|
||||
var/turf/T = get_turf(B)
|
||||
|
||||
to_chat(user, "<span class='alien'>\The [B] produces a cauterizing ooze!</span>")
|
||||
|
||||
T.visible_message("<span class='alium'>\The [B] shudders at \the [user]'s touch, before disgorging a disgusting ooze.</span>", "<span class='notice'>A fleshy slop hits the ground.</span>", list(user))
|
||||
|
||||
for(var/turf/simulated/floor/F in view(2, T))
|
||||
spawn()
|
||||
var/obj/effect/vfx/water/splash = new(T)
|
||||
splash.create_reagents(15)
|
||||
splash.reagents.add_reagent("blood", 10,list("blood_colour" = color))
|
||||
splash.set_color()
|
||||
|
||||
splash.set_up(F, 2, 3)
|
||||
|
||||
var/obj/effect/decal/cleanable/chemcoating/blood = locate() in T
|
||||
if(!istype(blood))
|
||||
blood = new(T)
|
||||
blood.reagents.add_reagent("blood", 10,list("blood_colour" = color))
|
||||
blood.reagents.add_reagent("dermalaze", 5)
|
||||
blood.update_icon()
|
||||
|
||||
return
|
||||
@@ -20,7 +20,7 @@
|
||||
endWhen = worst_case_end()
|
||||
|
||||
/datum/event/meteor_wave/start()
|
||||
affecting_z -= global.using_map.sealed_levels // Space levels only please!
|
||||
affecting_z -= global.using_map.underground_levels // Surface or space levels only, please.
|
||||
..()
|
||||
|
||||
/datum/event/meteor_wave/announce()
|
||||
|
||||
@@ -70,6 +70,24 @@ var/list/mining_overlay_cache = list()
|
||||
clear_ore_effects()
|
||||
. = ..()
|
||||
|
||||
/turf/simulated/mineral/xenoarch
|
||||
name = "random digsite"
|
||||
|
||||
/turf/simulated/mineral/xenoarch/Initialize()
|
||||
. = ..()
|
||||
name = "rock"
|
||||
|
||||
make_digsite(rand(0,2))
|
||||
|
||||
/turf/simulated/mineral/ore
|
||||
name = "random ore"
|
||||
|
||||
/turf/simulated/mineral/ore/Initialize()
|
||||
. = ..()
|
||||
name = "rock"
|
||||
|
||||
make_ore(prob(30))
|
||||
|
||||
// Alternative rock wall sprites.
|
||||
/turf/simulated/mineral/light
|
||||
icon_state = "rock-light"
|
||||
@@ -102,6 +120,30 @@ var/list/mining_overlay_cache = list()
|
||||
sand_icon_state = "sand-icey" // to be replaced
|
||||
rock_icon_state = "rock-crystal-shiny"
|
||||
|
||||
/turf/simulated/mineral/moon
|
||||
icon_state = "rock-moon"
|
||||
rock_side_icon_state = "rock_side-moon"
|
||||
sand_icon_state = "moonsand_fine"
|
||||
rock_icon_state = "rock-moon"
|
||||
|
||||
/turf/simulated/mineral/moon/xenoarch
|
||||
name = "random thor digsite"
|
||||
|
||||
/turf/simulated/mineral/moon/xenoarch/Initialize()
|
||||
. = ..()
|
||||
name = "rock"
|
||||
|
||||
make_digsite(rand(0,2))
|
||||
|
||||
/turf/simulated/mineral/moon/ore
|
||||
name = "random thor ore"
|
||||
|
||||
/turf/simulated/mineral/moon/ore/Initialize()
|
||||
. = ..()
|
||||
name = "rock"
|
||||
|
||||
make_ore(prob(30))
|
||||
|
||||
/turf/simulated/mineral/ignore_mapgen
|
||||
ignore_mapgen = 1
|
||||
|
||||
@@ -143,6 +185,10 @@ var/list/mining_overlay_cache = list()
|
||||
icon_state = "sand-light-corner"
|
||||
sand_icon_state = "sand-light-corner"
|
||||
|
||||
/turf/simulated/mineral/floor/moon
|
||||
icon_state = "moonsand_fine"
|
||||
sand_icon_state = "moonsand_fine"
|
||||
|
||||
/turf/simulated/mineral/floor/ignore_mapgen
|
||||
ignore_mapgen = 1
|
||||
|
||||
@@ -195,7 +241,7 @@ var/list/mining_overlay_cache = list()
|
||||
/turf/simulated/mineral/Initialize()
|
||||
. = ..()
|
||||
if(prob(20))
|
||||
overlay_detail = "asteroid[rand(0,9)]"
|
||||
overlay_detail = "[sand_icon_state][rand(0,9)]"
|
||||
update_icon(1)
|
||||
if(density && mineral)
|
||||
. = INITIALIZE_HINT_LATELOAD
|
||||
@@ -256,6 +302,7 @@ var/list/mining_overlay_cache = list()
|
||||
add_overlay(get_cached_border(rock_side_icon_state,direction,'icons/turf/walls.dmi',rock_side_icon_state))
|
||||
|
||||
if(overlay_detail)
|
||||
if(overlay_detail in icon_states(icon))
|
||||
add_overlay('icons/turf/flooring/decals.dmi',overlay_detail)
|
||||
|
||||
if(update_neighbors)
|
||||
@@ -284,6 +331,7 @@ var/list/mining_overlay_cache = list()
|
||||
var/amount_to_give = rand(CEILING(resources[ore] / 2, 1), resources[ore]) // Should result in at least one piece of ore.
|
||||
for(var/i = 1 to amount_to_give)
|
||||
var/oretype = ore_types[ore]
|
||||
if(oretype)
|
||||
new oretype(src)
|
||||
resources = null
|
||||
|
||||
@@ -703,3 +751,42 @@ var/list/mining_overlay_cache = list()
|
||||
if(initialized)
|
||||
UpdateMineral()
|
||||
update_icon()
|
||||
|
||||
// The value of range is turf-radius.
|
||||
// digsite_type allows you to specify what type of digsite is spawned. code/modules/xenoarchaeology/finds/finds_defines.dm
|
||||
// allow_anomalies is the probability, if any, of spawning an artifact in a turf, in the range. Garden and Animal digsites overwrite this probability.
|
||||
/turf/simulated/mineral/proc/make_digsite(var/range = 0, var/digsite_type , var/allow_anomalies = 5)
|
||||
var/digsite = digsite_type ? digsite_type : get_random_digsite_type()
|
||||
|
||||
for(var/turf/simulated/mineral/T in range(range,src))
|
||||
if(LAZYLEN(T.finds))
|
||||
continue
|
||||
|
||||
if(isnull(T.geologic_data))
|
||||
T.geologic_data = new /datum/geosample(T)
|
||||
|
||||
if(isnull(T.finds) || isemptylist(T.finds))
|
||||
T.finds = list()
|
||||
if(prob(50))
|
||||
T.finds.Add(new /datum/find(digsite, rand(10, 190)))
|
||||
else if(prob(75))
|
||||
T.finds.Add(new /datum/find(digsite, rand(10, 90)))
|
||||
T.finds.Add(new /datum/find(digsite, rand(110, 190)))
|
||||
else
|
||||
T.finds.Add(new /datum/find(digsite, rand(10, 50)))
|
||||
T.finds.Add(new /datum/find(digsite, rand(60, 140)))
|
||||
T.finds.Add(new /datum/find(digsite, rand(150, 190)))
|
||||
|
||||
//sometimes a find will be close enough to the surface to show
|
||||
var/datum/find/F = T.finds[1]
|
||||
if(F.excavation_required <= F.view_range)
|
||||
T.archaeo_overlay = "overlay_archaeo[rand(1,3)]"
|
||||
T.update_icon()
|
||||
|
||||
if(!isnull(allow_anomalies) && prob(allow_anomalies))
|
||||
//have a chance for an artifact to spawn here, but not in animal or plant digsites
|
||||
if(isnull(T.artifact_find) && digsite != DIGSITE_GARDEN && digsite != DIGSITE_ANIMAL)
|
||||
T.artifact_find = new()
|
||||
|
||||
T.update_icon()
|
||||
|
||||
|
||||
@@ -104,3 +104,20 @@
|
||||
armor_penetration = 10
|
||||
range_step = 5 //controls damage falloff with distance. projectiles lose a "pellet" each time they travel this distance. Can be a non-integer.
|
||||
pellets = 1
|
||||
|
||||
/obj/item/projectile/bullet/pellet/fragment/meteor
|
||||
name = "meteor fragment"
|
||||
damage = 10
|
||||
armor_penetration = 30
|
||||
range_step = 6
|
||||
pellets = 2
|
||||
|
||||
no_attack_log = 1
|
||||
muzzle_type = null
|
||||
|
||||
/obj/item/projectile/bullet/pellet/fragment/meteor/small
|
||||
damage = 5
|
||||
|
||||
/obj/item/projectile/bullet/pellet/fragment/meteor/incendiary
|
||||
name = "molten meteor fragment"
|
||||
damage_type = SEARING
|
||||
|
||||
119
code/modules/random_map/meteor/meteor.dm
Normal file
@@ -0,0 +1,119 @@
|
||||
#define ME_HEART_TILE 0
|
||||
#define ME_CRUST_TILE 1
|
||||
#define ME_CARDINAL_TILE 2
|
||||
#define ME_EMPTY_TILE 3
|
||||
#define ME_CORE_TILE 7
|
||||
|
||||
/datum/random_map/meteor
|
||||
descriptor = "meteor"
|
||||
initial_wall_cell = 0
|
||||
limit_x = 5
|
||||
limit_y = 5
|
||||
preserve_map = 0
|
||||
|
||||
wall_type = /turf/simulated/mineral/moon
|
||||
floor_type = /turf/simulated/mineral/moon/ore
|
||||
|
||||
auto_apply = TRUE
|
||||
|
||||
var/core_type = /turf/simulated/mineral/moon/xenoarch
|
||||
|
||||
var/placement_explosion_dev = 1
|
||||
var/placement_explosion_heavy = 2
|
||||
var/placement_explosion_light = 6
|
||||
var/placement_explosion_flash = 4
|
||||
|
||||
var/applied = FALSE
|
||||
|
||||
/datum/random_map/meteor/New(var/seed, var/tx, var/ty, var/tz, var/tlx, var/tly, var/do_not_apply, var/do_not_announce)
|
||||
//Make sure there is a clear midpoint.
|
||||
if(limit_x % 2 == 0) limit_x++
|
||||
if(limit_y % 2 == 0) limit_y++
|
||||
..()
|
||||
|
||||
/datum/random_map/meteor/generate_map()
|
||||
|
||||
// No point calculating these 200 times.
|
||||
var/x_midpoint = n_ceil(limit_x / 2)
|
||||
var/y_midpoint = n_ceil(limit_y / 2)
|
||||
|
||||
// Draw walls/floors
|
||||
for(var/x = 1, x <= limit_x, x++)
|
||||
for(var/y = 1, y <= limit_y, y++)
|
||||
var/current_cell = get_map_cell(x,y)
|
||||
if(!current_cell)
|
||||
continue
|
||||
|
||||
var/on_x_bound = (x == 1 || x == limit_x)
|
||||
var/on_y_bound = (y == 1 || y == limit_x)
|
||||
var/draw_corners = (limit_x < 5 && limit_y < 5)
|
||||
if(on_x_bound || on_y_bound)
|
||||
// Draw the actual walls.
|
||||
if(draw_corners || (!on_x_bound || !on_y_bound))
|
||||
map[current_cell] = ME_CRUST_TILE
|
||||
//Don't draw the far corners on large pods.
|
||||
else
|
||||
map[current_cell] = ME_EMPTY_TILE
|
||||
else
|
||||
// Fill in the corners.
|
||||
if((x == 2 || x == (limit_x-1)) && (y == 2 || y == (limit_y-1)))
|
||||
map[current_cell] = ME_CRUST_TILE
|
||||
// Fill in EVERYTHING ELSE.
|
||||
else
|
||||
map[current_cell] = ME_HEART_TILE
|
||||
|
||||
// Draw the meteor core.
|
||||
var/current_cell = get_map_cell(x_midpoint,y_midpoint)
|
||||
if(current_cell)
|
||||
map[current_cell] = ME_CORE_TILE
|
||||
return 1
|
||||
|
||||
/datum/random_map/meteor/apply_to_map()
|
||||
if(!applied)
|
||||
applied = TRUE
|
||||
if(placement_explosion_dev || placement_explosion_heavy || placement_explosion_light || placement_explosion_flash)
|
||||
var/turf/T = locate((origin_x + n_ceil(limit_x / 2)-1), (origin_y + n_ceil(limit_y / 2)-1), origin_z)
|
||||
if(istype(T))
|
||||
explosion(T, placement_explosion_dev, placement_explosion_heavy, placement_explosion_light, placement_explosion_flash)
|
||||
sleep(15) // Let the explosion finish proccing before we ChangeTurf(), otherwise it might destroy our spawned objects.
|
||||
return ..()
|
||||
|
||||
/datum/random_map/meteor/get_appropriate_path(var/value)
|
||||
if(value == ME_HEART_TILE)
|
||||
return floor_type
|
||||
else if(value == ME_CRUST_TILE)
|
||||
return wall_type
|
||||
else if(value == ME_CORE_TILE)
|
||||
return core_type
|
||||
return null
|
||||
|
||||
// Meteors are circular. Get the direction this object is facing from the center of the pod.
|
||||
/datum/random_map/meteor/get_spawn_dir(var/x, var/y)
|
||||
var/x_midpoint = n_ceil(limit_x / 2)
|
||||
var/y_midpoint = n_ceil(limit_y / 2)
|
||||
if(x == x_midpoint && y == y_midpoint)
|
||||
return null
|
||||
var/turf/target = locate(origin_x+x-1, origin_y+y-1, origin_z)
|
||||
var/turf/middle = locate(origin_x+x_midpoint-1, origin_y+y_midpoint-1, origin_z)
|
||||
if(!istype(target) || !istype(middle))
|
||||
return null
|
||||
return get_dir(middle, target)
|
||||
|
||||
/datum/random_map/meteor/get_additional_spawns(var/value, var/turf/T, var/spawn_dir)
|
||||
// Splatter anything under us that survived the explosion.
|
||||
if(value != ME_EMPTY_TILE && T.contents.len)
|
||||
for(var/atom/movable/AM in T)
|
||||
if(AM.simulated && !istype(AM, /mob/observer))
|
||||
qdel(AM)
|
||||
|
||||
/datum/admins/proc/call_meteor()
|
||||
set category = "Fun"
|
||||
set desc = "Drop a meteor on your current location."
|
||||
set name = "Drop Large Meteor"
|
||||
|
||||
if(!check_rights(R_FUN)) return
|
||||
|
||||
if(alert("Are you SURE you wish to drop this meteor? It will cause a sizable explosion and gib anyone underneath it.",,"No","Yes") == "No")
|
||||
return
|
||||
|
||||
new /datum/random_map/meteor(null, usr.x-1, usr.y-1, usr.z)
|
||||
@@ -593,6 +593,21 @@
|
||||
new_item.name = pick("great-club","club","billyclub","mace","tenderizer","maul","bat")
|
||||
item_type = new_item.name
|
||||
|
||||
if(ARCHAEO_METEOR)
|
||||
// A rock! From space! But, a long time ago.
|
||||
apply_prefix = FALSE
|
||||
apply_image_decorations = FALSE
|
||||
apply_material_decorations = FALSE
|
||||
if(prob(30))
|
||||
if(prob(30))
|
||||
apply_prefix = TRUE
|
||||
if(prob(20))
|
||||
apply_image_decorations = TRUE
|
||||
|
||||
new_item = new /obj/item/meteor_chunk(src.loc)
|
||||
new_item.name = pick("meteorite", "chunk", "lump", "stone")
|
||||
item_type = new_item.name
|
||||
|
||||
if(istype(new_item, /obj/item/weapon/material))
|
||||
var/new_item_mat = pickweight(list(
|
||||
MAT_STEEL = 80,
|
||||
|
||||
@@ -24,7 +24,7 @@ var/global/list/finds_as_strings = list(
|
||||
switch(find_type)
|
||||
if(ARCHAEO_BOWL, ARCHAEO_URN, ARCHAEO_CUTLERY, ARCHAEO_STATUETTE, ARCHAEO_INSTRUMENT, ARCHAEO_HANDCUFFS, ARCHAEO_BEARTRAP, ARCHAEO_LIGHTER, ARCHAEO_BOX, ARCHAEO_GASTANK, ARCHAEO_PEN, ARCHAEO_UNKNOWN)
|
||||
return "mercury"
|
||||
if(ARCHAEO_COIN, ARCHAEO_KNIFE, ARCHAEO_TOOL, ARCHAEO_METAL, ARCHAEO_CLAYMORE, ARCHAEO_RODS, ARCHAEO_KATANA, ARCHAEO_LASER, ARCHAEO_GUN)
|
||||
if(ARCHAEO_COIN, ARCHAEO_KNIFE, ARCHAEO_TOOL, ARCHAEO_METAL, ARCHAEO_CLAYMORE, ARCHAEO_RODS, ARCHAEO_KATANA, ARCHAEO_LASER, ARCHAEO_GUN, ARCHAEO_METEOR)
|
||||
return "iron"
|
||||
if(ARCHAEO_CRYSTAL, ARCHAEO_SHARD, ARCHAEO_SOULSTONE)
|
||||
return "nitrogen"
|
||||
@@ -45,7 +45,8 @@ var/global/list/finds_as_strings = list(
|
||||
100;ARCHAEO_PLANT,
|
||||
25;ARCHAEO_SHELL,
|
||||
25;ARCHAEO_FOSSIL,
|
||||
5;ARCHAEO_BEARTRAP)
|
||||
5;ARCHAEO_BEARTRAP,
|
||||
1;ARCHAEO_METEOR)
|
||||
if(DIGSITE_ANIMAL)
|
||||
. = pick(
|
||||
100;ARCHAEO_FOSSIL,
|
||||
@@ -69,7 +70,8 @@ var/global/list/finds_as_strings = list(
|
||||
50;ARCHAEO_SHARD,
|
||||
50;ARCHAEO_RODS,
|
||||
25;ARCHAEO_METAL,
|
||||
5;ARCHAEO_ALIEN_BOAT)
|
||||
5;ARCHAEO_ALIEN_BOAT,
|
||||
1;ARCHAEO_METEOR)
|
||||
if(DIGSITE_TECHNICAL)
|
||||
. = pick(
|
||||
125;ARCHAEO_GASMASK,
|
||||
@@ -105,7 +107,8 @@ var/global/list/finds_as_strings = list(
|
||||
10;ARCHAEO_SHARD,
|
||||
10;ARCHAEO_RODS,
|
||||
10;ARCHAEO_METAL,
|
||||
10;ARCHAEO_GASMASK)
|
||||
10;ARCHAEO_GASMASK,
|
||||
10;ARCHAEO_METEOR)
|
||||
if(DIGSITE_WAR)
|
||||
. = pick(
|
||||
100;ARCHAEO_GUN,
|
||||
|
||||
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 8.0 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 63 KiB |
@@ -216,7 +216,7 @@
|
||||
/datum/map_z_level/cynosure/station/station_one
|
||||
z = Z_LEVEL_STATION_ONE
|
||||
name = "Underground"
|
||||
flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_SEALED
|
||||
flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_SEALED|MAP_LEVEL_UNDERGROUND
|
||||
base_turf = /turf/simulated/floor/outdoors/rocks/caves
|
||||
holomap_offset_x = SOUTHERN_CROSS_HOLOMAP_MARGIN_X - 40
|
||||
holomap_offset_y = SOUTHERN_CROSS_HOLOMAP_MARGIN_Y + SOUTHERN_CROSS_MAP_SIZE*0
|
||||
|
||||
@@ -32,6 +32,7 @@ var/list/all_maps = list()
|
||||
var/static/list/contact_levels = list() // Z-levels that can be contacted from the station, for eg announcements
|
||||
var/static/list/player_levels = list() // Z-levels a character can typically reach
|
||||
var/static/list/sealed_levels = list() // Z-levels that don't allow random transit at edge
|
||||
var/static/list/underground_levels = list() // Z-levels that are underground.
|
||||
var/static/list/xenoarch_exempt_levels = list() //Z-levels exempt from xenoarch finds and digsites spawning.
|
||||
var/static/list/persist_levels = list() // Z-levels where SSpersistence should persist between rounds. Defaults to station_levels if unset.
|
||||
var/static/list/secret_levels = list() // Z-levels that (non-admin) ghosts can't get to
|
||||
@@ -357,6 +358,7 @@ var/list/all_maps = list()
|
||||
if(flags & MAP_LEVEL_SEALED) map.sealed_levels += z
|
||||
if(flags & MAP_LEVEL_XENOARCH_EXEMPT) map.xenoarch_exempt_levels += z
|
||||
if(flags & MAP_LEVEL_PERSIST) map.persist_levels += z
|
||||
if(flags & MAP_LEVEL_UNDERGROUND) map.underground_levels += z
|
||||
if(flags & MAP_LEVEL_EMPTY)
|
||||
if(!map.empty_levels) map.empty_levels = list()
|
||||
map.empty_levels += z
|
||||
|
||||
@@ -1527,6 +1527,7 @@
|
||||
#include "code\modules\blob2\overmind\overmind.dm"
|
||||
#include "code\modules\blob2\overmind\powers.dm"
|
||||
#include "code\modules\blob2\overmind\types.dm"
|
||||
#include "code\modules\blob2\overmind\types\barnacle.dm"
|
||||
#include "code\modules\blob2\overmind\types\blazing_oil.dm"
|
||||
#include "code\modules\blob2\overmind\types\classic.dm"
|
||||
#include "code\modules\blob2\overmind\types\cryogenic_goo.dm"
|
||||
@@ -2899,6 +2900,7 @@
|
||||
#include "code\modules\random_map\drop\supply.dm"
|
||||
#include "code\modules\random_map\mazes\maze.dm"
|
||||
#include "code\modules\random_map\mazes\maze_cell.dm"
|
||||
#include "code\modules\random_map\meteor\meteor.dm"
|
||||
#include "code\modules\random_map\noise\desert.dm"
|
||||
#include "code\modules\random_map\noise\noise.dm"
|
||||
#include "code\modules\random_map\noise\ore.dm"
|
||||
|
||||