From 4ff02b5a8bf27a12aee810c86bbdf6684435ba00 Mon Sep 17 00:00:00 2001 From: kevinz000 <2003111+kevinz000@users.noreply.github.com> Date: Tue, 7 Aug 2018 04:43:35 -0700 Subject: [PATCH 1/2] Sliding Puzzle --- .../LavaRuins/lavaland_surface_puzzle.dmm | 47 +++ code/__DEFINES/admin.dm | 1 + code/_onclick/click.dm | 3 + code/controllers/subsystem/npcpool.dm | 2 +- code/datums/ruins/lavaland.dm | 7 + code/modules/admin/verbs/randomverbs.dm | 6 +- .../mining/lavaland/necropolis_chests.dm | 15 + .../modules/ruins/lavalandruin_code/puzzle.dm | 351 ++++++++++++++++++ icons/obj/lavaland/artefacts.dmi | Bin 24834 -> 25700 bytes icons/obj/puzzle.dmi | Bin 0 -> 956 bytes tgstation.dme | 1 + 11 files changed, 431 insertions(+), 2 deletions(-) create mode 100644 _maps/RandomRuins/LavaRuins/lavaland_surface_puzzle.dmm create mode 100644 code/modules/ruins/lavalandruin_code/puzzle.dm create mode 100644 icons/obj/puzzle.dmi diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_puzzle.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_puzzle.dmm new file mode 100644 index 0000000000..911ee904fe --- /dev/null +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_puzzle.dmm @@ -0,0 +1,47 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/template_noop, +/area/lavaland/surface/outdoors) +"b" = ( +/obj/effect/sliding_puzzle/lavaland, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) +"c" = ( +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) + +(1,1,1) = {" +a +a +a +a +a +"} +(2,1,1) = {" +a +c +c +c +a +"} +(3,1,1) = {" +a +c +b +c +a +"} +(4,1,1) = {" +a +c +c +c +a +"} +(5,1,1) = {" +a +a +a +a +a +"} diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm index 255464d406..d43addf25a 100644 --- a/code/__DEFINES/admin.dm +++ b/code/__DEFINES/admin.dm @@ -70,6 +70,7 @@ #define ADMIN_PUNISHMENT_FIREBALL "Fireball" #define ADMIN_PUNISHMENT_ROD "Immovable Rod" #define ADMIN_PUNISHMENT_SUPPLYPOD "Supply Pod" +#define ADMIN_PUNISHMENT_MAZING "Puzzle" #define AHELP_ACTIVE 1 #define AHELP_CLOSED 2 diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index f98de83c23..b79e303d26 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -72,6 +72,9 @@ if(check_click_intercept(params,A)) return + if(notransform) + return + var/list/modifiers = params2list(params) if(modifiers["shift"] && modifiers["middle"]) ShiftMiddleClickOn(A) diff --git a/code/controllers/subsystem/npcpool.dm b/code/controllers/subsystem/npcpool.dm index 67e31b6931..d93f1f2407 100644 --- a/code/controllers/subsystem/npcpool.dm +++ b/code/controllers/subsystem/npcpool.dm @@ -23,7 +23,7 @@ SUBSYSTEM_DEF(npcpool) var/mob/living/simple_animal/SA = currentrun[currentrun.len] --currentrun.len - if(!SA.ckey) + if(!SA.ckey && !SA.notransform) if(SA.stat != DEAD) SA.handle_automated_movement() if(SA.stat != DEAD) diff --git a/code/datums/ruins/lavaland.dm b/code/datums/ruins/lavaland.dm index af299aaee9..4006c13a2c 100644 --- a/code/datums/ruins/lavaland.dm +++ b/code/datums/ruins/lavaland.dm @@ -215,3 +215,10 @@ suffix = "lavaland_surface_random_ripley.dmm" allow_duplicates = FALSE cost = 5 + +/datum/map_template/ruin/lavaland/puzzle + name = "Ancient Puzzle" + id = "puzzle" + description = "Mystery to be solved." + suffix = "lavaland_surface_puzzle.dmm" + cost = 5 \ No newline at end of file diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 0184c4b34f..de30b69f97 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -1313,7 +1313,7 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits if(!check_rights(R_ADMIN)) return - var/list/punishment_list = list(ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_GIB, ADMIN_PUNISHMENT_BSA, ADMIN_PUNISHMENT_FIREBALL, ADMIN_PUNISHMENT_ROD, ADMIN_PUNISHMENT_SUPPLYPOD) + var/list/punishment_list = list(ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_GIB, ADMIN_PUNISHMENT_BSA, ADMIN_PUNISHMENT_FIREBALL, ADMIN_PUNISHMENT_ROD, ADMIN_PUNISHMENT_SUPPLYPOD, ADMIN_PUNISHMENT_MAZING) var/punishment = input("Choose a punishment", "DIVINE SMITING") as null|anything in punishment_list @@ -1359,6 +1359,10 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits if(iscarbon(target)) target.Stun(10)//takes 0.53 seconds for CentCom pod to land new /obj/effect/DPtarget(get_turf(target), delivery, POD_CENTCOM) + if(ADMIN_PUNISHMENT_MAZING) + if(!puzzle_imprison(target)) + to_chat(usr,"Imprisonment failed!") + return var/msg = "[key_name_admin(usr)] punished [key_name_admin(target)] with [punishment]." message_admins(msg) diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index 002efdbf8d..5345410005 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -1315,3 +1315,18 @@ for(var/t in RANGE_TURFS(1, T)) var/obj/effect/temp_visual/hierophant/blast/B = new(t, user, friendly_fire_check) B.damage = 15 //keeps monster damage boost due to lower damage + + +//Just some minor stuff +/obj/structure/closet/crate/necropolis/puzzle + name = "puzzling chest" + +/obj/structure/closet/crate/necropolis/puzzle/PopulateContents() + var/loot = rand(1,3) + switch(loot) + if(1) + new /obj/item/soulstone/anybody(src) + if(2) + new /obj/item/wisp_lantern(src) + if(3) + new /obj/item/prisoncube(src) \ No newline at end of file diff --git a/code/modules/ruins/lavalandruin_code/puzzle.dm b/code/modules/ruins/lavalandruin_code/puzzle.dm new file mode 100644 index 0000000000..05eedc3e79 --- /dev/null +++ b/code/modules/ruins/lavalandruin_code/puzzle.dm @@ -0,0 +1,351 @@ +/obj/effect/sliding_puzzle + name = "Sliding puzzle generator" + icon = 'icons/obj/items_and_weapons.dmi' //mapping + icon_state = "syndballoon" + invisibility = INVISIBILITY_ABSTRACT + anchored = TRUE + var/list/elements + var/floor_type = /turf/open/floor/vault + var/finished = FALSE + var/reward_type = /obj/item/reagent_containers/food/snacks/cookie + var/element_type = /obj/structure/puzzle_element + var/auto_setup = TRUE + var/empty_tile_id + +//Gets the turf where the tile with given id should be +/obj/effect/sliding_puzzle/proc/get_turf_for_id(id) + var/turf/center = get_turf(src) + switch(id) + if(1) + return get_step(center,NORTHWEST) + if(2) + return get_step(center,NORTH) + if(3) + return get_step(center,NORTHEAST) + if(4) + return get_step(center,WEST) + if(5) + return center + if(6) + return get_step(center,EAST) + if(7) + return get_step(center,SOUTHWEST) + if(8) + return get_step(center,SOUTH) + if(9) + return get_step(center,SOUTHEAST) + +/obj/effect/sliding_puzzle/Initialize(mapload) + ..() + return INITIALIZE_HINT_LATELOAD + +/obj/effect/sliding_puzzle/LateInitialize() + if(auto_setup) + setup() + +/obj/effect/sliding_puzzle/proc/check_setup_location() + for(var/id in 1 to 9) + var/turf/T = get_turf_for_id(id) + if(!T) + return FALSE + if(istype(T,/turf/closed/indestructible)) + return FALSE + return TRUE + + +/obj/effect/sliding_puzzle/proc/validate() + if(finished) + return + + if(elements.len < 8) //Someone broke it + qdel(src) + + //Check if everything is in place + for(var/id in 1 to 9) + var/target_turf = get_turf_for_id(id) + var/obj/structure/puzzle_element/E = locate() in target_turf + if(id == empty_tile_id && !E) // This location should be empty. + continue + if(!E || E.id != id) //wrong tile or no tile at all + return + //Ding ding + finish() + +/obj/effect/sliding_puzzle/Destroy() + if(LAZYLEN(elements)) + for(var/obj/structure/puzzle_element/E in elements) + E.source = null + elements.Cut() + return ..() + +#define COLLAPSE_DURATION 7 + +/obj/effect/sliding_puzzle/proc/finish() + finished = TRUE + for(var/mob/M in range(7,src)) + shake_camera(M, COLLAPSE_DURATION , 1) + for(var/obj/structure/puzzle_element/E in elements) + E.collapse() + + dispense_reward() + +/obj/effect/sliding_puzzle/proc/dispense_reward() + new reward_type(get_turf(src)) + +/obj/effect/sliding_puzzle/proc/is_solvable() + var/list/current_ordering = list() + for(var/obj/structure/puzzle_element/E in elements_in_order()) + current_ordering += E.id + + var/swap_tally = 0 + for(var/i in 1 to current_ordering.len) + var/checked_value = current_ordering[i] + for(var/j in i to current_ordering.len) + if(current_ordering[j] < checked_value) + swap_tally++ + + return swap_tally % 2 == 0 + +//swap two tiles in same row +/obj/effect/sliding_puzzle/proc/make_solvable() + var/first_tile_id = 1 + var/other_tile_id = 2 + if(empty_tile_id == 1 || empty_tile_id == 2) //Can't swap with empty one so just grab some in second row + first_tile_id = 4 + other_tile_id = 5 + + var/turf/T1 = get_turf_for_id(first_tile_id) + var/turf/T2 = get_turf_for_id(other_tile_id) + + var/obj/structure/puzzle_element/E1 = locate() in T1 + var/obj/structure/puzzle_element/E2 = locate() in T2 + + E1.forceMove(T2) + E2.forceMove(T1) + +/proc/cmp_xy_desc(atom/movable/A,atom/movable/B) + if(A.y > B.y) + return -1 + if(A.y < B.y) + return 1 + if(A.x > B.x) + return 1 + if(A.x < B.x) + return -1 + return 0 + +/obj/effect/sliding_puzzle/proc/elements_in_order() + return sortTim(elements,cmp=/proc/cmp_xy_desc) + +/obj/effect/sliding_puzzle/proc/get_base_icon() + var/icon/I = new('icons/obj/puzzle.dmi') + var/list/puzzles = icon_states(I) + var/puzzle_state = pick(puzzles) + var/icon/P = new('icons/obj/puzzle.dmi',puzzle_state) + return P + +/obj/effect/sliding_puzzle/proc/setup() + //First we slice the 96x96 icon into 32x32 pieces + var/list/puzzle_pieces = list() //id -> icon list + + var/width = 3 + var/height = 3 + var/list/left_ids = list() + var/tile_count = width * height + + //Generate per tile icons + for(var/id in 1 to tile_count) + var/y = width - round((id - 1) / width) + var/x = ((id - 1) % width) + 1 + + var/x_start = 1 + (x - 1) * world.icon_size + var/x_end = x_start + world.icon_size - 1 + var/y_start = 1 + ((y - 1) * world.icon_size) + var/y_end = y_start + world.icon_size - 1 + + var/icon/T = get_base_icon() + T.Crop(x_start,y_start,x_end,y_end) + puzzle_pieces["[id]"] = T + left_ids += id + + //Setup random empty tile + empty_tile_id = pick_n_take(left_ids) + var/turf/empty_tile_turf = get_turf_for_id(empty_tile_id) + empty_tile_turf.PlaceOnTop(floor_type,null,CHANGETURF_INHERIT_AIR) + var/mutable_appearance/MA = new(puzzle_pieces["[empty_tile_id]"]) + MA.layer = empty_tile_turf.layer + 0.1 + empty_tile_turf.add_overlay(MA) + + elements = list() + var/list/empty_spots = left_ids.Copy() + for(var/spot_id in empty_spots) + var/turf/T = get_turf_for_id(spot_id) + T = T.PlaceOnTop(floor_type,null,CHANGETURF_INHERIT_AIR) + var/obj/structure/puzzle_element/E = new element_type(T) + elements += E + var/chosen_id = pick_n_take(left_ids) + E.puzzle_icon = puzzle_pieces["[chosen_id]"] + E.source = src + E.id = chosen_id + E.set_puzzle_icon() + + if(!is_solvable()) + make_solvable() + +/obj/structure/puzzle_element + name = "mysterious pillar" + desc = "puzzling..." + icon = 'icons/obj/lavaland/artefacts.dmi' + icon_state = "puzzle_pillar" + anchored = FALSE + density = TRUE + var/id = 0 + var/obj/effect/sliding_puzzle/source + var/icon/puzzle_icon + +/obj/structure/puzzle_element/Move(nloc, dir) + if(!isturf(nloc) || moving_diagonally || get_dist(get_step(src,dir),get_turf(source)) > 1) + return 0 + else + return ..() + +/obj/structure/puzzle_element/proc/set_puzzle_icon() + cut_overlays() + if(puzzle_icon) + //Need to scale it down a bit to fit the static border + var/icon/C = new(puzzle_icon) + C.Scale(19,19) + var/mutable_appearance/puzzle_small = new(C) + puzzle_small.layer = layer + 0.1 + puzzle_small.pixel_x = 7 + puzzle_small.pixel_y = 7 + add_overlay(puzzle_small) + +/obj/structure/puzzle_element/Destroy() + if(source) + source.elements -= src + source.validate() + return ..() + +//Set the full image on the turf and delete yourself +/obj/structure/puzzle_element/proc/collapse() + var/turf/T = get_turf(src) + var/mutable_appearance/MA = new(puzzle_icon) + MA.layer = T.layer + 0.1 + T.add_overlay(MA) + //Some basic shaking animation + for(var/i in 1 to COLLAPSE_DURATION) + animate(src, pixel_x=rand(-5,5), pixel_y=rand(-2,2), time=1) + QDEL_IN(src,COLLAPSE_DURATION) + +/obj/structure/puzzle_element/Moved() + . = ..() + source.validate() + +//Admin abuse version so you can pick the icon before it sets up +/obj/effect/sliding_puzzle/admin + auto_setup = FALSE + var/icon/puzzle_icon + var/puzzle_state + +/obj/effect/sliding_puzzle/admin/get_base_icon() + var/icon/I = new(puzzle_icon,puzzle_state) + return I + +//Ruin version +/obj/effect/sliding_puzzle/lavaland + reward_type = /obj/structure/closet/crate/necropolis/puzzle + +/obj/effect/sliding_puzzle/lavaland/dispense_reward() + if(prob(25)) + //If it's not roaming somewhere else already. + var/mob/living/simple_animal/hostile/megafauna/bubblegum/B = locate() in GLOB.mob_list + if(!B) + reward_type = /mob/living/simple_animal/hostile/megafauna/bubblegum + return ..() + +//Prison cube version +/obj/effect/sliding_puzzle/prison + auto_setup = FALSE //This will be done by cube proc + var/mob/living/prisoner + element_type = /obj/structure/puzzle_element/prison + +/obj/effect/sliding_puzzle/prison/get_base_icon() + if(!prisoner) + CRASH("Prison cube without prisoner") + prisoner.setDir(SOUTH) + var/icon/I = getFlatIcon(prisoner) + I.Scale(96,96) + return I + +/obj/effect/sliding_puzzle/prison/Destroy() + if(prisoner) + to_chat(prisoner,"With the cube broken by force, you can feel your body falling apart.") + prisoner.death() + qdel(prisoner) + . = ..() + +/obj/effect/sliding_puzzle/prison/dispense_reward() + prisoner.forceMove(get_turf(src)) + prisoner.notransform = FALSE + prisoner = null + +//Some armor so it's harder to kill someone by mistake. +/obj/structure/puzzle_element/prison + armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 50, "bio" = 50, "rad" = 50, "fire" = 50, "acid" = 50) + +/obj/structure/puzzle_element/prison/relaymove(mob/user) + return + +/obj/item/prisoncube + name = "Prison Cube" + desc = "Dusty cube with humanoid imprint on it." + icon = 'icons/obj/lavaland/artefacts.dmi' + icon_state = "prison_cube" + +/obj/item/prisoncube/afterattack(atom/target, mob/user, proximity_flag, click_parameters) + . = ..() + if(!proximity_flag || !isliving(target)) + return + var/mob/living/victim = target + var/mob/living/carbon/carbon_victim = victim + //Handcuffed or unconcious + if(istype(carbon_victim) && carbon_victim.handcuffed || victim.stat != CONSCIOUS) + if(!puzzle_imprison(target)) + to_chat(user,"[src] does nothing.") + return + to_chat(user,"You trap [victim] in the prison cube!") + qdel(src) + else + to_chat(user,"[src] only accepts restrained or unconcious prisoners.") + +/proc/puzzle_imprison(mob/living/prisoner) + var/turf/T = get_turf(prisoner) + var/obj/effect/sliding_puzzle/prison/cube = new(T) + if(!cube.check_setup_location()) + qdel(cube) + return FALSE + + //First grab the prisoner and move them temporarily into the generator so they won't get thrown around. + prisoner.notransform = TRUE + prisoner.forceMove(cube) + to_chat(prisoner,"You're trapped by the prison cube! You will remain trapped until someone solves it.") + + //Clear the area from objects (and cube user) + var/list/things_to_throw = list() + for(var/atom/movable/AM in range(1,T)) + if(!AM.anchored) + things_to_throw += AM + + for(var/atom/movable/AM in things_to_throw) + var/throwtarget = get_edge_target_turf(T, get_dir(T, get_step_away(AM, T))) + AM.throw_at(throwtarget, 2, 3) + + //Create puzzle itself + cube.prisoner = prisoner + cube.setup() + + //Move them into random block + var/obj/structure/puzzle_element/E = pick(cube.elements) + prisoner.forceMove(E) + return TRUE \ No newline at end of file diff --git a/icons/obj/lavaland/artefacts.dmi b/icons/obj/lavaland/artefacts.dmi index 0530f7bb3b5cfc20ab6e6db632c62a427856a9da..7f11ba29d4192bc4a3bb58666fbdfaf9a2489867 100644 GIT binary patch delta 5044 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 ZJBgbi8{%$Q7!IO7#`{tswR{X_r& delta 4178 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 Y^V9D^FPU8v8zA6!-qgyZ%E%@5f5u;2OaK4? diff --git a/icons/obj/puzzle.dmi b/icons/obj/puzzle.dmi new file mode 100644 index 0000000000000000000000000000000000000000..f623142beb4d454ef02a7e93492f2a2c2b1dadbb GIT binary patch literal 956 zcmV;t14I0YP)V=-0C=2J zR&a84_w-Y6@%7{?OD!tS%+FJ>RWQ*r;NmRLOex6#axBfbI5Sc+(=$pSoZ^zil2jm5 zDYYUow;(4~iHkEOv#1y-V#vjrR+N~V3SlcNxca$(4F&*y-Wv;V@kJ>B00QJmL_t(o zg`Jq~(X1d0g<)&}>|m{6XRrh9zorW$fs=rH<;{;>l{}mT`P8|I`B*K?$|e@U=C#dg z7t<=`-XEW!9$CZ6_9Of5$EVjb`gg*|?CJ_|9P(7h;S~{Mb`*e-G12ys6a|FHqP2tbwrE{G66 z%DM{R+hYLQs!Dtu0W8qcuKlZr6N5+y5Xq$nK>!9w5(M}v5O5geAE<)MvP9qjp^sBk zz5qe)xFA={K#NxzB>!fh-ALZf1-$7c06@>eZsy+%Uv!%HA!{bQYAKucDo?&PrY;7> zWE(u`Ze1%`iG)=^6Zi7-Mv1N54*;gWo%hv=9MFAtMRD}dMqBo18m0cs_tMtcF=+5f zNQ0+-Yt<=9LidG@=A%u4vS0}ka0&<}1(v9J*Nl|_2V;S)62)}J4H!C7CK#~(F19YL z^5_5r`5v;%ds|mDDr{FRphD zsdl`Eu7RCT2`GsO{Zs=d%oSUwd-qlYr~(PB&HjEqL?Svxc>AIsJceyc~z<-_ap@%WDi@Wmtk;zxwF&lJlaLY6 Date: Tue, 7 Aug 2018 04:46:41 -0700 Subject: [PATCH 2/2] Update puzzle.dm --- code/modules/ruins/lavalandruin_code/puzzle.dm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/modules/ruins/lavalandruin_code/puzzle.dm b/code/modules/ruins/lavalandruin_code/puzzle.dm index 05eedc3e79..9e798507da 100644 --- a/code/modules/ruins/lavalandruin_code/puzzle.dm +++ b/code/modules/ruins/lavalandruin_code/puzzle.dm @@ -290,10 +290,10 @@ prisoner.notransform = FALSE prisoner = null -//Some armor so it's harder to kill someone by mistake. +//Some armor so it's harder to kill someone by mistake. EDITED - Hugboxed /obj/structure/puzzle_element/prison - armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 50, "bio" = 50, "rad" = 50, "fire" = 50, "acid" = 50) - + resistance_flags = INDESTRUCTIBLE | ACID_PROOF | FIRE_PROOF | LAVA_PROOF + /obj/structure/puzzle_element/prison/relaymove(mob/user) return @@ -348,4 +348,4 @@ //Move them into random block var/obj/structure/puzzle_element/E = pick(cube.elements) prisoner.forceMove(E) - return TRUE \ No newline at end of file + return TRUE