diff --git a/baystation12.dme b/baystation12.dme index 948493f636..1bb34a9363 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -1502,6 +1502,8 @@ #include "code\modules\random_map\automata\automata.dm" #include "code\modules\random_map\automata\caves.dm" #include "code\modules\random_map\building\building.dm" +#include "code\modules\random_map\drop\droppod.dm" +#include "code\modules\random_map\drop\droppod_doors.dm" #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" diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 6c18a0baa9..176c2cbb60 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -115,8 +115,10 @@ var/list/admin_verbs_fun = list( /client/proc/toggle_random_events, /client/proc/editappear, /client/proc/roll_dices, - /datum/admins/proc/call_supply_drop + /datum/admins/proc/call_supply_drop, + /datum/admins/proc/call_drop_pod ) + var/list/admin_verbs_spawn = list( /datum/admins/proc/spawn_fruit, /datum/admins/proc/spawn_custom_item, diff --git a/code/modules/random_map/drop/droppod.dm b/code/modules/random_map/drop/droppod.dm new file mode 100644 index 0000000000..c2018659b9 --- /dev/null +++ b/code/modules/random_map/drop/droppod.dm @@ -0,0 +1,245 @@ +#define SD_FLOOR_TILE 0 +#define SD_WALL_TILE 1 +#define SD_DOOR_TILE 2 +#define SD_EMPTY_TILE 3 +#define SD_SUPPLY_TILE 7 +var/global/list/supply_drop_random_loot_types = list( + "guns", + "seeds", + "materials", + "food", + "armour", + "medical", + "power", + "hydroponics", + "lasers", + "ballistics" + ) + +/datum/random_map/droppod + descriptor = "drop pod" + initial_wall_cell = 0 + limit_x = 3 + limit_y = 3 + preserve_map = 0 + + wall_type = /turf/simulated/wall/voxshuttle + floor_type = /turf/simulated/floor/engine + var/list/supplied_drop_types = list() + var/door_type = /obj/structure/droppod_door + var/drop_type = /mob/living/simple_animal/parrot + var/auto_open_doors + + var/placement_explosion_dev = 2 + var/placement_explosion_heavy = 4 + var/placement_explosion_light = 6 + var/placement_explosion_flash = 4 + +/datum/random_map/droppod/New(var/seed, var/tx, var/ty, var/tz, var/tlx, var/tly, var/do_not_apply, var/do_not_announce, var/supplied_drop, var/list/supplied_drops, var/automated) + + if(supplied_drop) + drop_type = supplied_drop + else if(islist(supplied_drops) && supplied_drops.len) + supplied_drop_types = supplied_drops + drop_type = "custom" + if(automated) + auto_open_doors = 1 + + //Make sure there is a clear midpoint. + if(limit_x % 2 == 0) limit_x++ + if(limit_y % 2 == 0) limit_y++ + ..() + +/datum/random_map/droppod/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/doors. + 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 access points in midpoint of each wall. + if(x == x_midpoint || y == y_midpoint) + map[current_cell] = SD_DOOR_TILE + // Draw the actual walls. + else if(draw_corners || (!on_x_bound || !on_y_bound)) + map[current_cell] = SD_WALL_TILE + //Don't draw the far corners on large pods. + else + map[current_cell] = SD_EMPTY_TILE + else + // Fill in the corners. + if((x == 2 || x == (limit_x-1)) && (y == 2 || y == (limit_y-1))) + map[current_cell] = SD_WALL_TILE + // Fill in EVERYTHING ELSE. + else + map[current_cell] = SD_FLOOR_TILE + + // Draw the drop contents. + var/current_cell = get_map_cell(x_midpoint,y_midpoint) + if(current_cell) + map[current_cell] = SD_SUPPLY_TILE + return 1 + +/datum/random_map/droppod/apply_to_map() + 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(5) // Let the explosion finish proccing before we ChangeTurf(), otherwise it might destroy our spawned objects. + sleep(-1) + return ..() + +/datum/random_map/droppod/get_appropriate_path(var/value) + if(value == SD_FLOOR_TILE || value == SD_SUPPLY_TILE) + return floor_type + else if(value == SD_WALL_TILE) + return wall_type + return null + +// Pods are circular. Get the direction this object is facing from the center of the pod. +/datum/random_map/droppod/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/droppod/get_additional_spawns(var/value, var/turf/T, var/spawn_dir) + + // Splatter anything under us that survived the explosion. + if(value != SD_EMPTY_TILE && T.contents.len) + for(var/atom/A in T) + if(!A.simulated || istype(A, /mob/dead)) + continue + if(istype(A, /mob/living)) + var/mob/living/M = A + M.gib() + else + qdel(A) + + // Also spawn doors and loot. + if(value == SD_DOOR_TILE) + var/obj/structure/S = new door_type(T, auto_open_doors) + S.set_dir(spawn_dir) + + else if(value == SD_SUPPLY_TILE) + get_spawned_drop(T) + +/datum/random_map/droppod/proc/get_spawned_drop(var/turf/T) + var/obj/structure/bed/chair/C = new(T) + C.set_light(3, l_color = "#CC0000") + var/mob/living/drop + // This proc expects a list of mobs to be passed to the spawner. + // Use the supply pod if you don't want to drop mobs. + // Mobs will not double up; if you want multiple mobs, you + // will need multiple drop tiles. + if(islist(supplied_drop_types) && supplied_drop_types.len) + while(supplied_drop_types.len) + drop = pick(supplied_drop_types) + supplied_drop_types -= drop + if(istype(drop)) + if(drop.buckled) + drop.buckled = null + drop.loc = T + drop.forceMove(T) + else if(ispath(drop_type)) + drop = new drop_type(T) + if(istype(drop)) + if(drop.buckled) + drop.buckled = null + drop.loc = T + drop.forceMove(T) + +/datum/admins/proc/call_drop_pod() + set category = "Fun" + set desc = "Call an immediate drop pod on your location." + set name = "Call Drop Pod" + + if(!check_rights(R_FUN)) return + + var/turf/holder_turf = locate(157,254,2) // This is in the admin jails, will need adjusting for other mobs. + if(!istype(holder_turf)) + usr << "Nowhere to put the mobs, aborting." + return + + var/client/selected_player + var/mob/living/spawned_mob + var/list/spawned_mobs = list() + + var/spawn_path = input("Select a mob type.", "Drop Pod Selection", null) as null|anything in typesof(/mob/living)-/mob/living + if(!spawn_path) + return + + if(alert("Do you wish the mob to have a player?",,"No","Yes") == "No") + var/spawn_count = input("How many mobs do you wish the pod to contain?", "Drop Pod Selection", null) as num + if(spawn_count <= 0) + return + for(var/i=0;iYou prime the explosive bolts. Better get clear!" + sleep(30) + deploy() + +/obj/structure/droppod_door/proc/deploy() + if(deployed) + return + + deployed = 1 + visible_message("The explosive bolts on \the [src] detonate, throwing it open!") + playsound(src.loc, 'sound/effects/bang.ogg', 50, 1, 5) + + // This is shit but it will do for the sake of testing. + for(var/obj/structure/droppod_door/D in range(5,src)) + if(D.deployed) + continue + D.deploy() + + // Overwrite turfs. + var/turf/origin = get_turf(src) + origin.ChangeTurf(/turf/simulated/floor/engine) + origin.set_light(0) // Forcing updates + var/turf/T = get_step(origin, src.dir) + T.ChangeTurf(/turf/simulated/floor/engine) + T.set_light(0) // Forcing updates + + // Destroy turf contents. + for(var/obj/O in origin) + if(!O.simulated) + continue + qdel(O) //crunch + for(var/obj/O in T) + if(!O.simulated) + continue + qdel(O) //crunch + + // Hurl the mobs away. + for(var/mob/living/M in T) + M.throw_at(get_edge_target_turf(T,src.dir),rand(0,3),50) + for(var/mob/living/M in origin) + M.throw_at(get_edge_target_turf(origin,src.dir),rand(0,3),50) + + // Create a decorative ramp bottom and flatten out our current ramp. + density = 0 + opacity = 0 + icon_state = "ramptop" + var/obj/structure/droppod_door/door_bottom = new(T) + door_bottom.deployed = 1 + door_bottom.density = 0 + door_bottom.opacity = 0 + door_bottom.dir = src.dir + door_bottom.icon_state = "rampbottom" \ No newline at end of file diff --git a/code/modules/random_map/drop/supply.dm b/code/modules/random_map/drop/supply.dm index e059696b9a..101f849205 100644 --- a/code/modules/random_map/drop/supply.dm +++ b/code/modules/random_map/drop/supply.dm @@ -1,134 +1,33 @@ -#define SD_FLOOR_TILE 0 -#define SD_WALL_TILE 1 -#define SD_DOOR_TILE 2 -#define SD_EMPTY_TILE 3 -#define SD_SUPPLY_TILE 7 -var/global/list/supply_drop_random_loot_types = list( - "guns", - "seeds", - "materials", - "food", - "armour", - "medical", - "power", - "hydroponics", - "lasers", - "ballistics" - ) - -/datum/random_map/supplydrop - descriptor = "small supply drop" - initial_wall_cell = 0 +/datum/random_map/droppod/supply + descriptor = "supply drop" limit_x = 5 limit_y = 5 - var/list/custom_loot_types = list() - var/loot_type - var/placement_explosion_dev = 3 - var/placement_explosion_heavy = 5 - var/placement_explosion_light = 7 - var/placement_explosion_flash = 5 + placement_explosion_dev = 3 + placement_explosion_heavy = 5 + placement_explosion_light = 7 + placement_explosion_flash = 5 -/datum/random_map/supplydrop/New(var/seed, var/tx, var/ty, var/tz, var/tlx, var/tly, var/do_not_apply, var/do_not_announce, var/list/supplied_drops, var/supplied_loot_type) - if(islist(supplied_drops) && supplied_drops.len) - custom_loot_types = supplied_drops - loot_type = "custom" - else if(supplied_loot_type) - loot_type = supplied_loot_type - ..(seed, tx, ty, tz, tlx, tly, do_not_apply, do_not_announce) +// UNLIKE THE DROP POD, this map deals ENTIRELY with strings and types. +// Drop type is a string representing a mode rather than an atom or path. +// supplied_drop_types is a list of types to spawn in the pod. +/datum/random_map/droppod/supply/get_spawned_drop(var/turf/T) -/datum/random_map/supplydrop/generate_map() + if(!drop_type) drop_type = pick(supply_drop_random_loot_types) - // 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/doors. - 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) - - if(on_x_bound || on_y_bound) - // Draw access points in midpoint of each wall. - if(x == x_midpoint || y == y_midpoint) - map[current_cell] = SD_DOOR_TILE - // Draw the actual walls. - else if(!on_x_bound || !on_y_bound) - map[current_cell] = SD_WALL_TILE - //Don't draw the far corners. - else - map[current_cell] = SD_EMPTY_TILE - else - // Fill in the corners. - if((x == 2 || x == (limit_x-1)) && (y == 2 || y == (limit_y-1))) - map[current_cell] = SD_WALL_TILE - // Fill in EVERYTHING ELSE. - else - map[current_cell] = SD_FLOOR_TILE - - // Draw the drop contents. - var/current_cell = get_map_cell(x_midpoint,y_midpoint) - if(current_cell) - map[current_cell] = SD_SUPPLY_TILE - return 1 - -/datum/random_map/supplydrop/apply_to_map() - 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/supplydrop/get_appropriate_path(var/value) - if(value == SD_FLOOR_TILE || value == SD_SUPPLY_TILE|| value == SD_DOOR_TILE) - return floor_type - else if(value == SD_WALL_TILE) - return wall_type - return null - -/datum/random_map/supplydrop/get_additional_spawns(var/value, var/turf/T) - - // Splatter anything under us that survived the explosion. - if(value != SD_EMPTY_TILE && T.contents.len) - for(var/atom/A in T) - if(!A.simulated || istype(A, /mob/dead)) - continue - if(istype(A, /mob/living)) - var/mob/living/M = A - M.gib() - else - qdel(A) - - // Also spawn doors and loot. - if(value == SD_DOOR_TILE) - var/obj/machinery/door/airlock/A = new(T) - A.id_tag = name - else if(value == SD_SUPPLY_TILE) - get_spawned_loot(T) - -/datum/random_map/supplydrop/proc/get_spawned_loot(var/turf/T) - - if(!loot_type) loot_type = pick(supply_drop_random_loot_types) - - if(loot_type == "custom") - if(custom_loot_types.len) + if(drop_type == "custom") + if(supplied_drop_types.len) var/obj/structure/largecrate/C = locate() in T - for(var/drop_type in custom_loot_types) + for(var/drop_type in supplied_drop_types) var/atom/movable/A = new drop_type(T) if(!istype(A, /mob)) if(!C) C = new(T) C.contents |= A return else - loot_type = pick(supply_drop_random_loot_types) + drop_type = pick(supply_drop_random_loot_types) - switch(loot_type) + switch(drop_type) if("lasers") var/obj/structure/largecrate/C = new(T) new /obj/item/weapon/gun/energy/laser(C) @@ -285,4 +184,4 @@ var/global/list/supply_drop_random_loot_types = list( if(choice == "No") return log_admin("[key_name(usr)] dropped supplies at ([usr.x],[usr.y],[usr.z])") - new /datum/random_map/supplydrop(null, usr.x-2, usr.y-2, usr.z, supplied_drops = chosen_loot_types, supplied_loot_type = chosen_loot_type) \ No newline at end of file + new /datum/random_map/droppod/supply(null, usr.x-2, usr.y-2, usr.z, supplied_drops = chosen_loot_types, supplied_drop = chosen_loot_type) \ No newline at end of file diff --git a/code/modules/random_map/random_map.dm b/code/modules/random_map/random_map.dm index acc2544330..3ecb7d7214 100644 --- a/code/modules/random_map/random_map.dm +++ b/code/modules/random_map/random_map.dm @@ -17,6 +17,7 @@ var/global/list/map_count = list() var/limit_x = 128 // Default x size. var/limit_y = 128 // Default y size. var/auto_apply = 1 + var/preserve_map = 1 // Turf paths. var/wall_type = /turf/simulated/wall @@ -38,7 +39,7 @@ var/global/list/map_count = list() else map_count[descriptor]++ name = "[descriptor] #[map_count[descriptor]]" - random_maps[name] = src + if(preserve_map) random_maps[name] = src // Get origins for applying the map later. set_origins(tx, ty, tz) @@ -168,9 +169,12 @@ var/global/list/map_count = list() var/newpath = get_appropriate_path(map[current_cell]) if(newpath) T.ChangeTurf(newpath) - get_additional_spawns(map[current_cell],T) + get_additional_spawns(map[current_cell],T,get_spawn_dir(x, y)) return T +/datum/random_map/proc/get_spawn_dir() + return 0 + /datum/random_map/proc/get_appropriate_path(var/value) switch(value) if(FLOOR_CHAR) diff --git a/icons/obj/structures.dmi b/icons/obj/structures.dmi index 9f44d1113a..30144f1fb0 100644 Binary files a/icons/obj/structures.dmi and b/icons/obj/structures.dmi differ