Adds a cursed sword (and other haunted things) (#4931)

* adds cursed sword and 'haunted' object framework.

* fixes back.dmi conflicts

* adds cursed blade ghost pod

as well as fixing some ghost pod oddities

* fixes misc.dm conflicts

* adds cursed sword cave POI

* makes cursed sword use voice mob

as opposed to a brainmob
This commit is contained in:
BillyBangles
2018-03-19 14:49:33 -04:00
committed by Atermonera
parent d36e67d90d
commit 85e377f017
15 changed files with 146 additions and 16 deletions

View File

@@ -132,3 +132,9 @@
question = "A curious explorer has touched a mysterious rune. \
Would you like to play as the creature it summons?"
cutoff_number = 1
/datum/ghost_query/cursedblade
role_name = "Cursed Sword"
question = "A cursed blade has been discovered by a curious explorer. \
Would you like to play as the soul imprisoned within?"
cutoff_number = 1

View File

@@ -51,3 +51,40 @@
/obj/item/weapon/melee/umbrella/random/New()
color = "#"+get_random_colour()
..()
/obj/item/weapon/melee/cursedblade
name = "crystal blade"
desc = "The red crystal blade's polished surface glints in the light, giving off a faint glow."
icon_state = "soulblade"
slot_flags = SLOT_BELT | SLOT_BACK
force = 30
throwforce = 10
w_class = ITEMSIZE_NORMAL
sharp = 1
edge = 1
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
hitsound = 'sound/weapons/bladeslice.ogg'
can_speak = 1
var/list/voice_mobs = list() //The curse of the sword is that it has someone trapped inside.
/obj/item/weapon/melee/cursedblade/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
if(default_parry_check(user, attacker, damage_source) && prob(50))
user.visible_message("<span class='danger'>\The [user] parries [attack_text] with \the [src]!</span>")
playsound(user.loc, 'sound/weapons/punchmiss.ogg', 50, 1)
return 1
return 0
/obj/item/weapon/melee/cursedblade/proc/ghost_inhabit(var/mob/candidate)
if(!isobserver(candidate))
return
//Handle moving the ghost into the new shell.
announce_ghost_joinleave(candidate, 0, "They are occupying a cursed sword now.")
var/mob/living/voice/new_voice = new /mob/living/voice(src) //Make the voice mob the ghost is going to be.
new_voice.transfer_identity(candidate) //Now make the voice mob load from the ghost's active character in preferences.
new_voice.mind = candidate.mind //Transfer the mind, if any.
new_voice.ckey = candidate.ckey //Finally, bring the client over.
new_voice.name = "cursed sword" //Cursed swords shouldn't be known characters.
new_voice.real_name = "cursed sword"
voice_mobs.Add(new_voice)
listening_objects |= src

View File

@@ -13,6 +13,7 @@
var/armor_penetration = 0
var/show_messages
var/preserve_item = 0 //whether this object is preserved when its owner goes into cryo-storage, gateway, etc
var/can_speak = 0 //For MMIs and admin trickery. If an object has a brainmob in its contents, set this to 1 to allow it to speak.
var/show_examine = TRUE // Does this pop up on a mob when the mob is examined?

View File

@@ -10,12 +10,14 @@
var/needscharger //For drone pods that want their pod to turn into a charger.
// Call this to get a ghost volunteer.
/obj/structure/ghost_pod/proc/trigger()
/obj/structure/ghost_pod/proc/trigger(var/alert, var/adminalert)
if(!ghost_query_type)
return FALSE
if(busy)
return FALSE
visible_message(alert)
log_and_message_admins(adminalert)
busy = TRUE
var/datum/ghost_query/Q = new ghost_query_type()
var/list/winner = Q.query()
@@ -44,7 +46,7 @@
/obj/structure/ghost_pod/manual/attack_hand(var/mob/living/user)
if(!used)
if(confirm_before_open)
if(alert(user, "Are you sure you want to open \the [src]?", "Confirm", "No", "Yes") == "No")
if(alert(user, "Are you sure you want to touch \the [src]?", "Confirm", "No", "Yes") == "No")
return
trigger()

View File

@@ -13,9 +13,7 @@
needscharger = TRUE
/obj/structure/ghost_pod/manual/lost_drone/trigger()
..()
visible_message("<span class='notice'>\The [src] appears to be attempting to restart the robot contained inside.</span>")
log_and_message_admins("is attempting to open \a [src].")
..("<span class='notice'>\The [src] appears to be attempting to restart the robot contained inside.</span>", "is attempting to open \a [src].")
/obj/structure/ghost_pod/manual/lost_drone/create_occupant(var/mob/M)
density = FALSE
@@ -68,14 +66,13 @@
description_info = "This will summon some manner of creature through quite dubious means. The creature will be controlled by a player."
icon_state = "corgirune"
icon_state_opened = "corgirune-inert"
density = TRUE
density = FALSE
anchored = TRUE
ghost_query_type = /datum/ghost_query/corgi_rune
confirm_before_open = TRUE
/obj/structure/ghost_pod/manual/corgi/trigger()
..()
visible_message("<span class='warning'>\The [usr] places their hand on the rune!</span>")
log_and_message_admins("is attempting to summon a corgi.")
..("<span class='warning'>\The [usr] places their hand on the rune!</span>", "is attempting to summon a corgi.")
/obj/structure/ghost_pod/manual/corgi/create_occupant(var/mob/M)
density = FALSE
@@ -87,3 +84,28 @@
visible_message("<span class='warning'>With a bright flash of light, \the [src] disappears, and in its place stands a small corgi.</span>")
log_and_message_admins("successfully touched \a [src] and summoned a corgi.")
..()
/obj/structure/ghost_pod/manual/cursedblade
name = "abandoned blade"
desc = "A red crystal blade that someone jammed deep into a stone. If you try hard enough, you might be able to remove it."
icon_state = "soulblade-embedded"
icon_state_opened = "soulblade-released"
density = TRUE
anchored = TRUE
ghost_query_type = /datum/ghost_query/cursedblade
confirm_before_open = TRUE
/obj/structure/ghost_pod/manual/cursedblade/trigger()
..("<span class='warning'>\The [usr] attempts to pull out the sword!</span>", "is activating a cursed blade.")
/obj/structure/ghost_pod/manual/cursedblade/create_occupant(var/mob/M)
density = FALSE
var/obj/item/weapon/melee/cursedblade/R = new(get_turf(src))
to_chat(M, "<span class='notice'>You are a <b>Cursed Sword</b>, discovered by a hapless explorer. \
You were once an explorer yourself, when one day you discovered a strange sword made from a red crystal. As soon as you touched it,\
your body was reduced to ashes and your soul was cursed to remain trapped in the blade forever. \
Now it is up to you to decide whether you want to be a faithful companion, or a bitter prisoner of the blade.</span>")
R.ghost_inhabit(M)
visible_message("<span class='warning'>The blade shines brightly for a brief moment as [usr] pulls it out of the stone!</span>")
log_and_message_admins("successfully acquired a cursed sword.")
..()

View File

@@ -6,6 +6,7 @@
icon = 'icons/obj/assemblies.dmi'
icon_state = "mmi_empty"
w_class = ITEMSIZE_NORMAL
can_speak = 1
origin_tech = list(TECH_BIO = 3)
req_access = list(access_robotics)

View File

@@ -5,8 +5,8 @@
message = sanitize(message)
if(!(container && istype(container, /obj/item/device/mmi)))
return //No MMI, can't speak, bucko./N
if(!(container && container.can_speak))
return //Certain objects can speak, like MMIs. Most others cannot. -Q
else
var/datum/language/speaking = parse_language(message)
if(speaking)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View File

@@ -0,0 +1,55 @@
"a" = (/turf/template_noop,/area/template_noop)
"b" = (/turf/simulated/mineral,/area/submap/cave/swordcave)
"c" = (/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/cave/swordcave)
"d" = (/obj/machinery/crystal,/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/cave/swordcave)
"e" = (/turf/simulated/floor/water,/area/submap/cave/swordcave)
"f" = (/turf/simulated/floor/water/deep,/area/submap/cave/swordcave)
"g" = (/obj/structure/ghost_pod/manual/cursedblade,/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/cave/swordcave)
"h" = (/mob/living/simple_animal/hostile/faithless/cult,/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/cave/swordcave)
"i" = (/obj/item/device/gps/explorer,/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/cave/swordcave)
"j" = (/obj/structure/loot_pile/surface/bones,/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/cave/swordcave)
"k" = (/mob/living/simple_animal/hostile/scarybat/cult,/turf/simulated/mineral/floor/ignore_mapgen,/area/submap/cave/swordcave)
(1,1,1) = {"
aaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbaaaaaa
aaaaabbbbbbbbbbbcccdccccbbbbbbbbbbbbaaaaa
aaaabbbbbbcccccccccccccccccccccbbbbbbaaaa
aaabbbbbbcccccccccccccccccccccccdbbbbbaaa
aabbbbccccccceeeeeeeeeeeeeccccccccbbbbbaa
aabbbccccccceeeeeeeeeeeeeeeccccccccbbbbaa
aabbbcdcccceeeffffffffffffeeeccccccbbbbaa
aabbbccccceefeeeeeeefeeeeeeeeecccccbbbbaa
aabbbccccceefeeccceeeeeeeefffeeccccbbbaaa
aabbbcccceeffeecccccecccceefffeecccbbbaaa
aabbbcccceeffeeeccgcccchcceeffeecccbbbaaa
aabbbcccdeeffeeccijcdccccceefeeccdcbbbaaa
abbbccccceefffeeeccccccceeefeeccccccbbaaa
abbbcccccceefffeeeccccceeeffeeccccccbbbaa
abbbcdccccceefffeeeeeeeeffffeeccccccbbbaa
abbcccckcccceeffffeeeeefffffeeccccccbbbaa
abbcccccccccceeffffffffffffeeccccdccbbbaa
abbccccccccccceeffeeeeeefffeecccccccbbbaa
abbbccccdcccccceefeeeeeeeeeeckccccccbbbaa
abbbcccccccccccceeecccdceeecccccccccbbaaa
abbbcccccccccccccecccccccceccccdckccbbaaa
abbbcccccccccckcccccccccccccccccccccbbaaa
abbbbcccccckccccccccccccccckccccccccbbaaa
abbbbbcccccccccccccccckccccccccckcccbbaaa
aabbbbbccccccccccccccccccccccccccccbbbaaa
aabbbbbccccccccccccdccccccccccccccbbbbaaa
aabbbbbcccccdccccccccccccccccccccbbbbbaaa
aabbbbbccccccccccckccccccccdcccccbbbbaaaa
aabbbbbbbccccccccccccccccccccccccbbbbaaaa
aaabbbbbbbcccccccccccccccdccccccbbbbaaaaa
aaaabbbbbbcckcccccdcccccccccccccbbbbaaaaa
aaaaabbbbbcccccccccccccccccccccbbbbbaaaaa
aaaaabbbbbccccccccccccccccccccbbbbbaaaaaa
aaaaaabbbbbcccdccccccccccccccbbbbbaaaaaaa
aaaaaaabbbbbcccccccckccccckcbbbbbbaaaaaaa
aaaaaaabbbbbbcccccccccccccccbbbbbaaaaaaaa
aaaaaaabbbbbbbbbbbbccccccccccbbbaaaaaaaaa
aaaaaaaaabbbbbbbbbbbccccccccccbaaaaaaaaaa
aaaaaaaaaaabbbbbbbbbbccccccccccaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaacccdccccaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaccccccaaaaaaaaaaaa
"}

View File

@@ -27,6 +27,7 @@
#include "IceCave1A.dmm"
#include "IceCave1B.dmm"
#include "IceCave1C.dmm"
#include "SwordCave.dmm"
#include "SupplyDrop1.dmm"
#include "BlastMine1.dmm"
#endif
@@ -171,6 +172,11 @@
mappath = 'maps/submaps/surface_submaps/mountains/IceCave1C.dmm'
cost = 10
/datum/map_template/surface/mountains/normal/SwordCave
name = "Cursed Sword Cave"
desc = "An underground lake. The sword on the lake's island holds a terrible secret."
mappath = 'maps/submaps/surface_submaps/mountains/SwordCave.dmm'
/datum/map_template/surface/mountains/normal/supplydrop1
name = "Supply Drop 1"
desc = "A drop pod that landed deep within the mountains."

View File

@@ -76,13 +76,13 @@
name = "Ice Cave 1B"
/area/submap/cave/IceCave1C
name = "Ice Cave 1C"
name = "Mine Vault"
/area/submap/cave/swordcave
name = "Cursed Sword Cave"
/area/submap/cave/SupplyDrop1
name = "Supply Drop 1"
/area/submap/cave/BlastMine1
name = "Blast Mine 1"