diff --git a/code/__DEFINES/contracts.dm b/code/__DEFINES/contracts.dm
index 629493cc603..e2f4aff4099 100644
--- a/code/__DEFINES/contracts.dm
+++ b/code/__DEFINES/contracts.dm
@@ -16,6 +16,7 @@
#define OBLIGATION_FOOD "food"
#define OBLIGATION_FIDDLE "fiddle"
+#define OBLIGATION_DANCEOFF "danceoff"
#define OBLIGATION_GREET "greet"
#define OBLIGATION_PRESENCEKNOWN "presenceknown"
#define OBLIGATION_SAYNAME "sayname"
diff --git a/code/game/gamemodes/devil/devilinfo.dm b/code/game/gamemodes/devil/devilinfo.dm
index 1876ce8bd96..9710c599e52 100644
--- a/code/game/gamemodes/devil/devilinfo.dm
+++ b/code/game/gamemodes/devil/devilinfo.dm
@@ -18,6 +18,7 @@ var/global/list/lawlorify = list (
LORE = list(
OBLIGATION_FOOD = "This devil seems to always offer its victims food before slaughtering them.",
OBLIGATION_FIDDLE = "This devil will never turn down a musical challenge.",
+ OBLIGATION_DANCEOFF = "This devil will never turn down a dance off.",
OBLIGATION_GREET = "This devil seems to only be able to converse with people it knows the name of.",
OBLIGATION_PRESENCEKNOWN = "This devil seems to be unable to attack from stealth.",
OBLIGATION_SAYNAME = "He will always chant his name upon killing someone.",
@@ -48,6 +49,7 @@ var/global/list/lawlorify = list (
LAW = list(
OBLIGATION_FOOD = "When not acting in self defense, you must always offer your victim food before harming them.",
OBLIGATION_FIDDLE = "When not in immediate danger, if you are challenged to a musical duel, you must accept it. You are not obligated to duel the same person twice.",
+ OBLIGATION_DANCEOFF = "When not in immediate danger, if you are challenged to a dance off, you must accept it. You are not obligated to face off with the same person twice.",
OBLIGATION_GREET = "You must always greet other people by their last name before talking with them.",
OBLIGATION_PRESENCEKNOWN = "You must always make your presence known before attacking.",
OBLIGATION_SAYNAME = "You must always say your true name after you kill someone.",
@@ -77,7 +79,7 @@ var/global/list/lawlorify = list (
)
)
-/datum/devilinfo/
+/datum/devilinfo
var/datum/mind/owner = null
var/obligation
var/ban
@@ -88,6 +90,16 @@ var/global/list/lawlorify = list (
var/reviveNumber = 0
var/form = BASIC_DEVIL
var/exists = 0
+ var/static/list/dont_remove_spells = list(
+ /obj/effect/proc_holder/spell/targeted/summon_contract,
+ /obj/effect/proc_holder/spell/targeted/conjure_item/violin,
+ /obj/effect/proc_holder/spell/targeted/summon_dancefloor)
+
+
+/datum/devilinfo/New()
+ ..()
+ dont_remove_spells = typecacheof(dont_remove_spells)
+
/proc/randomDevilInfo(name = randomDevilName())
var/datum/devilinfo/devil = new
@@ -128,7 +140,7 @@ var/global/list/lawlorify = list (
return preTitle + title + mainName + suffix
/proc/randomdevilobligation()
- return pick(OBLIGATION_FOOD, OBLIGATION_FIDDLE, OBLIGATION_GREET, OBLIGATION_PRESENCEKNOWN, OBLIGATION_SAYNAME, OBLIGATION_ANNOUNCEKILL, OBLIGATION_ANSWERTONAME)
+ return pick(OBLIGATION_FOOD, OBLIGATION_FIDDLE, OBLIGATION_DANCEOFF, OBLIGATION_GREET, OBLIGATION_PRESENCEKNOWN, OBLIGATION_SAYNAME, OBLIGATION_ANNOUNCEKILL, OBLIGATION_ANSWERTONAME)
/proc/randomdevilban()
return pick(BAN_HURTWOMAN, BAN_CHAPEL, BAN_HURTPRIEST, BAN_AVOIDWATER, BAN_STRIKEUNCONCIOUS, BAN_HURTLIZARD, BAN_HURTANIMAL)
@@ -289,7 +301,7 @@ var/global/list/lawlorify = list (
/datum/devilinfo/proc/remove_spells()
for(var/X in owner.spell_list)
var/obj/effect/proc_holder/spell/S = X
- if(!istype(S, /obj/effect/proc_holder/spell/targeted/summon_contract) && !istype(S, /obj/effect/proc_holder/spell/targeted/conjure_item/violin))
+ if(!is_type_in_typecache(S, dont_remove_spells))
owner.RemoveSpell(S)
/datum/devilinfo/proc/give_summon_contract()
@@ -302,8 +314,10 @@ var/global/list/lawlorify = list (
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/conjure_item/summon_pitchfork(null))
if(give_summon_contract)
give_summon_contract()
- if (obligation == OBLIGATION_FIDDLE)
+ if(obligation == OBLIGATION_FIDDLE)
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/conjure_item/violin(null))
+ if(obligation == OBLIGATION_DANCEOFF)
+ owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/summon_dancefloor(null))
/datum/devilinfo/proc/give_lizard_spells()
remove_spells()
diff --git a/code/game/objects/effects/effect_system/effects_smoke.dm b/code/game/objects/effects/effect_system/effects_smoke.dm
index d042a1107bf..badef2a1296 100644
--- a/code/game/objects/effects/effect_system/effects_smoke.dm
+++ b/code/game/objects/effects/effect_system/effects_smoke.dm
@@ -311,3 +311,14 @@
if(S.amount)
S.spread_smoke() //calling process right now so the smoke immediately attacks mobs.
+
+/////////////////////////////////////////////
+// Transparent smoke
+/////////////////////////////////////////////
+
+//Same as the base type, but the smoke produced is not opaque
+/datum/effect_system/smoke_spread/transparent
+ effect_type = /obj/effect/particle_effect/smoke/transparent
+
+/obj/effect/particle_effect/smoke/transparent
+ opaque = FALSE
diff --git a/code/game/turfs/simulated/floor/light_floor.dm b/code/game/turfs/simulated/floor/light_floor.dm
index da67666b25d..6e8abc7aae4 100644
--- a/code/game/turfs/simulated/floor/light_floor.dm
+++ b/code/game/turfs/simulated/floor/light_floor.dm
@@ -6,9 +6,10 @@
floor_tile = /obj/item/stack/tile/light
broken_states = list("light_broken")
var/on = 1
- var/state //0 = fine, 1 = flickering, 2 = breaking, 3 = broken
+ var/state = 0//0 = fine, 1 = flickering, 2 = breaking, 3 = broken
var/list/coloredlights = list("g", "r", "y", "b", "p", "w", "s","o","g")
var/currentcolor = 1
+ var/can_modify_colour = TRUE
/turf/open/floor/light/New()
@@ -42,6 +43,8 @@
..()
/turf/open/floor/light/attack_hand(mob/user)
+ if(!can_modify_colour)
+ return
if(!on)
on = 1
currentcolor = 1
@@ -67,3 +70,23 @@
user << "You replace the light bulb."
else
user << "The lightbulb seems fine, no need to replace it."
+
+
+//Cycles through all of the colours
+/turf/open/floor/light/colour_cycle
+ coloredlights = list("cycle_all")
+ can_modify_colour = FALSE
+
+
+
+//Two different "dancefloor" types so that you can have a checkered pattern
+// (also has a longer delay than colour_cycle between cycling colours)
+/turf/open/floor/light/colour_cycle/dancefloor_a
+ name = "dancefloor"
+ desc = "Funky floor."
+ coloredlights = list("dancefloor_A")
+
+/turf/open/floor/light/colour_cycle/dancefloor_b
+ name = "dancefloor"
+ desc = "Funky floor."
+ coloredlights = list("dancefloor_B")
diff --git a/code/modules/spells/spell_types/devil.dm b/code/modules/spells/spell_types/devil.dm
index ae1115dd883..8d06e7b3415 100644
--- a/code/modules/spells/spell_types/devil.dm
+++ b/code/modules/spells/spell_types/devil.dm
@@ -196,3 +196,56 @@
H.influenceSin()
H.Weaken(2)
H.Stun(2)
+
+
+/obj/effect/proc_holder/spell/targeted/summon_dancefloor
+ name = "Summon Dancefloor"
+ desc = "When what a Devil really needs is funk."
+ include_user = 1
+ range = -1
+ clothes_req = 0
+
+ school = "conjuration"
+ charge_max = 10
+ cooldown_min = 50 //5 seconds, so the smoke can't be spammed
+ action_icon_state = "funk"
+ action_background_icon_state = "bg_demon"
+
+ var/list/dancefloor_turfs
+ var/list/dancefloor_turfs_types
+ var/dancefloor_exists = FALSE
+ var/datum/effect_system/smoke_spread/transparent/dancefloor_devil/smoke
+
+
+/obj/effect/proc_holder/spell/targeted/summon_dancefloor/cast(list/targets, mob/user = usr)
+ LAZYINITLIST(dancefloor_turfs)
+ LAZYINITLIST(dancefloor_turfs_types)
+
+ if(!smoke)
+ smoke = new()
+ smoke.set_up(0, get_turf(user))
+ smoke.start()
+
+ if(dancefloor_exists)
+ dancefloor_exists = FALSE
+ for(var/i in 1 to dancefloor_turfs.len)
+ var/turf/T = dancefloor_turfs[i]
+ T.ChangeTurf(dancefloor_turfs_types[i])
+ else
+ dancefloor_exists = TRUE
+ var/i = 1
+ var/list/funky_turfs = RANGE_TURFS(1, user)
+ dancefloor_turfs.len = funky_turfs.len
+ dancefloor_turfs_types.len = funky_turfs.len
+ for(var/t in funky_turfs)
+ var/turf/T = t
+ dancefloor_turfs[i] = T
+ dancefloor_turfs_types[i] = T.type
+ T.ChangeTurf((i % 2 == 0) ? /turf/open/floor/light/colour_cycle/dancefloor_a : /turf/open/floor/light/colour_cycle/dancefloor_b)
+ i++
+
+/datum/effect_system/smoke_spread/transparent/dancefloor_devil
+ effect_type = /obj/effect/particle_effect/smoke/transparent/dancefloor_devil
+
+/obj/effect/particle_effect/smoke/transparent/dancefloor_devil
+ lifetime = 2
\ No newline at end of file
diff --git a/icons/mob/actions.dmi b/icons/mob/actions.dmi
index 9408e9847bf..c80fe727297 100644
Binary files a/icons/mob/actions.dmi and b/icons/mob/actions.dmi differ
diff --git a/icons/turf/floors.dmi b/icons/turf/floors.dmi
index 418c769d057..881e3f2dc3f 100644
Binary files a/icons/turf/floors.dmi and b/icons/turf/floors.dmi differ