mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-10 18:32:03 +00:00
Soul Rambler Mini-Antag (#21465)
* soul rambler * Progress need to rebase * rambler finished * The Power of Parenthesis * A Few For Robo
This commit is contained in:
@@ -279,6 +279,8 @@
|
||||
|
||||
#define isninja(H) (H.mind && H.mind.GetRole(NINJA))
|
||||
|
||||
#define isrambler(H) (H.mind && H.mind.GetRole(RAMBLER))
|
||||
|
||||
#define isERT(H) (H.mind && H.mind.GetRole(RESPONDER))
|
||||
|
||||
//Banning someone from the Syndicate role bans them from all antagonist roles
|
||||
|
||||
@@ -32,3 +32,5 @@
|
||||
#define CIVILIAN_POSITIONS list("Head of Personnel", "Bartender", "Botanist", "Chef", "Janitor", "Librarian", "Internal Affairs Agent", "Chaplain", "Clown", "Mime", "Assistant")
|
||||
#define CARGO_POSITIONS list("Head of Personnel", "Quartermaster", "Cargo Technician", "Shaft Miner")
|
||||
#define SECURITY_POSITIONS list("Head of Security", "Warden", "Detective", "Security Officer")
|
||||
|
||||
#define ALWAYSTRUE 2
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
#define CLOCKWORK_GRAVEKEEPER "clockwork gravekeeper"
|
||||
#define GRINCH "The Grinch"
|
||||
#define CATBEAST "loose catbeast"
|
||||
#define RAMBLER "soul rambler"
|
||||
|
||||
#define GREET_DEFAULT "default"
|
||||
#define GREET_ROUNDSTART "roundstart"
|
||||
|
||||
@@ -305,22 +305,22 @@ var/MAX_EXPLOSION_RANGE = 14
|
||||
|
||||
// bitflags for clothing parts
|
||||
|
||||
#define FULL_TORSO UPPER_TORSO|LOWER_TORSO
|
||||
#define FACE EYES|MOUTH|BEARD
|
||||
#define FULL_TORSO (UPPER_TORSO|LOWER_TORSO)
|
||||
#define FACE (EYES|MOUTH|BEARD)
|
||||
#define BEARD 32768
|
||||
#define FULL_HEAD HEAD|EYES|MOUTH|EARS
|
||||
#define LEGS LEG_LEFT|LEG_RIGHT // 24
|
||||
#define FEET FOOT_LEFT|FOOT_RIGHT //96
|
||||
#define ARMS ARM_LEFT|ARM_RIGHT //384
|
||||
#define HANDS HAND_LEFT|HAND_RIGHT //1536
|
||||
#define FULL_BODY FULL_HEAD|HANDS|FULL_TORSO|ARMS|FEET|LEGS
|
||||
#define FULL_HEAD (HEAD|EYES|MOUTH|EARS)
|
||||
#define LEGS (LEG_LEFT|LEG_RIGHT) // 24
|
||||
#define FEET (FOOT_LEFT|FOOT_RIGHT) //96
|
||||
#define ARMS (ARM_LEFT|ARM_RIGHT) //384
|
||||
#define HANDS (HAND_LEFT|HAND_RIGHT) //1536
|
||||
#define FULL_BODY (FULL_HEAD|HANDS|FULL_TORSO|ARMS|FEET|LEGS)
|
||||
#define IGNORE_INV 16384 // Don't make stuff invisible
|
||||
|
||||
|
||||
// bitflags for invisibility
|
||||
|
||||
#define HIDEGLOVES HANDS
|
||||
#define HIDEJUMPSUIT ARMS|LEGS|FULL_TORSO
|
||||
#define HIDEJUMPSUIT (ARMS|LEGS|FULL_TORSO)
|
||||
#define HIDESHOES FEET
|
||||
#define HIDEMASK FACE
|
||||
#define HIDEEARS EARS
|
||||
@@ -328,7 +328,7 @@ var/MAX_EXPLOSION_RANGE = 14
|
||||
#define HIDEFACE FACE
|
||||
#define HIDEHEADHAIR EARS|HEAD
|
||||
#define HIDEBEARDHAIR BEARD
|
||||
#define HIDEHAIR HIDEHEADHAIR|HIDEBEARDHAIR
|
||||
#define HIDEHAIR (HIDEHEADHAIR|HIDEBEARDHAIR)
|
||||
#define HIDESUITSTORAGE LOWER_TORSO
|
||||
|
||||
// bitflags for the percentual amount of protection a piece of clothing which covers the body part offers.
|
||||
|
||||
@@ -290,6 +290,12 @@
|
||||
return key
|
||||
return null
|
||||
|
||||
//In an associative list, get only the elements and not the keys.
|
||||
/proc/get_list_of_elements(var/list/L)
|
||||
var/list/elements = list()
|
||||
for(var/key in L)
|
||||
elements += L[key]
|
||||
return elements
|
||||
|
||||
/proc/count_by_type(var/list/L, type)
|
||||
var/i = 0
|
||||
|
||||
@@ -228,6 +228,7 @@ datum/emergency_shuttle/proc/shuttle_phase(var/phase, var/casual = 1)
|
||||
world << sound('sound/AI/shuttledock.ogg')
|
||||
if(ticker)
|
||||
ticker.shuttledocked_time = world.time / 10
|
||||
ticker.mode.ShuttleDocked(1)
|
||||
/*
|
||||
if(universe.name == "Hell Rising")
|
||||
to_chat(world, "___________________________________________________________________")
|
||||
@@ -277,6 +278,9 @@ datum/emergency_shuttle/proc/shuttle_phase(var/phase, var/casual = 1)
|
||||
vote_preload()
|
||||
location = 2
|
||||
|
||||
if(ticker)
|
||||
ticker.mode.ShuttleDocked(2)
|
||||
|
||||
if(shuttle && istype(shuttle,/datum/shuttle/escape))
|
||||
var/datum/shuttle/escape/E = shuttle
|
||||
E.open_all_doors()
|
||||
|
||||
@@ -109,13 +109,17 @@
|
||||
var/mob/living/carbon/human/new_character = applicant
|
||||
|
||||
if (makeBody)
|
||||
new_character = makeBody(applicant)
|
||||
new_character.dna.ResetSE()
|
||||
new_character = generate_ruleset_body(applicant)
|
||||
|
||||
finish_setup(new_character, i)
|
||||
|
||||
applicants.Cut()
|
||||
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/proc/generate_ruleset_body(mob/applicant)
|
||||
var/mob/living/carbon/human/new_character = makeBody(applicant)
|
||||
new_character.dna.ResetSE()
|
||||
return new_character
|
||||
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/proc/finish_setup(var/mob/new_character, var/index)
|
||||
var/datum/role/new_role = new role_category
|
||||
new_role.AssignToRole(new_character.mind,1)
|
||||
@@ -448,6 +452,47 @@
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// //
|
||||
// RAMBLER (MIDROUND) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/rambler
|
||||
name = "Soul Rambler Migration"
|
||||
role_category = /datum/role/rambler
|
||||
enemy_jobs = list("Librarian","Detective", "Chaplain", "Internal Affairs Agent")
|
||||
required_enemies = list(0,0,1,1,2,2,3,3,3,4)
|
||||
required_candidates = 1
|
||||
weight = 1
|
||||
cost = 5
|
||||
requirements = list(5,5,15,15,25,25,55,55,55,75)
|
||||
logo = "rambler-logo"
|
||||
repeatable = FALSE //Listen, this psyche is not big enough for two metaphysical seekers.
|
||||
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/rambler/acceptable(var/population=0,var/threat=0)
|
||||
if(!mode.executed_rules)
|
||||
return FALSE
|
||||
//We have nothing to investigate!
|
||||
if(population>=20)
|
||||
return FALSE
|
||||
//We don't cotton to freaks in 20+pop
|
||||
return ..()
|
||||
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/rambler/ready(var/forced = 0)
|
||||
if (required_candidates > (dead_players.len + list_observers.len))
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/rambler/generate_ruleset_body(mob/applicant)
|
||||
var/mob/living/carbon/human/frankenstein/new_frank = new(pick(latejoin))
|
||||
var/datum/preferences/A = new()
|
||||
A.randomize_appearance_for(new_frank)
|
||||
new_frank.key = applicant.key
|
||||
new_frank.dna.ready_dna(new_frank)
|
||||
new_frank.setGender(pick(MALE, FEMALE))
|
||||
return new_frank
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// //
|
||||
// THE GRINCH (holidays) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -79,6 +79,8 @@ var/list/factions_with_hud_icons = list()
|
||||
for(var/datum/role/R in members)
|
||||
R.AnnounceObjectives()
|
||||
|
||||
/datum/faction/proc/ShuttleDocked(state)
|
||||
|
||||
/datum/faction/proc/HandleNewMind(var/datum/mind/M) //Used on faction creation
|
||||
for(var/datum/role/R in members)
|
||||
if(R.antag == M)
|
||||
|
||||
@@ -46,6 +46,12 @@
|
||||
var/RolesSuccess = CreateRoles()
|
||||
return FactionSuccess && RolesSuccess
|
||||
|
||||
//1 = station, 2 = centcomm
|
||||
/datum/gamemode/proc/ShuttleDocked(var/state)
|
||||
for(var/datum/faction/F in factions)
|
||||
F.ShuttleDocked(state)
|
||||
for(var/datum/role/R in orphaned_roles)
|
||||
R.ShuttleDocked(state)
|
||||
|
||||
/*===FACTION RELATED STUFF===*/
|
||||
|
||||
|
||||
2
code/datums/gamemode/objectives/freeform/rambler.dm
Normal file
2
code/datums/gamemode/objectives/freeform/rambler.dm
Normal file
@@ -0,0 +1,2 @@
|
||||
/datum/objective/freeform/ponder
|
||||
explanation_text = "You are just a simple seeker on a simple quest to determine: What Doth Life?"
|
||||
17
code/datums/gamemode/objectives/investigate.dm
Normal file
17
code/datums/gamemode/objectives/investigate.dm
Normal file
@@ -0,0 +1,17 @@
|
||||
/datum/objective/investigate
|
||||
explanation_text = "Bring peace to the spirits of the dead by identifying one dangerous killer."
|
||||
name = "Investigate Killing"
|
||||
|
||||
/datum/objective/investigate/IsFulfilled()
|
||||
if (..())
|
||||
return TRUE
|
||||
if(!owner.current)
|
||||
return FALSE
|
||||
var/mob/living/rambler = owner.current
|
||||
var/obj/item/clothing/mask/necklace/crystal/C = pick(rambler.search_contents_for(/obj/item/clothing/mask/necklace/crystal))
|
||||
if(!C || !C.suspect)
|
||||
return FALSE
|
||||
if(C.suspect.mind.antag_roles.len)
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
18
code/datums/gamemode/objectives/ramble.dm
Normal file
18
code/datums/gamemode/objectives/ramble.dm
Normal file
@@ -0,0 +1,18 @@
|
||||
/datum/objective/ramble
|
||||
explanation_text = "Escape to a different Z-level at the end. Life is optional, but you must remain intact."
|
||||
name = "Ramble Forth"
|
||||
|
||||
/datum/objective/ramble/IsFulfilled()
|
||||
if (..())
|
||||
return TRUE
|
||||
//Unlike an escape objective, we are okay with being dead, arrested, siliconed, MMI'd, etc.
|
||||
if(!owner.current)
|
||||
return FALSE
|
||||
var/turf/location = get_turf(owner.current.loc)
|
||||
if(!location)
|
||||
return FALSE
|
||||
|
||||
if(location.z == STATION_Z)
|
||||
return FALSE
|
||||
else
|
||||
return TRUE
|
||||
29
code/datums/gamemode/objectives/uphold_vows.dm
Normal file
29
code/datums/gamemode/objectives/uphold_vows.dm
Normal file
@@ -0,0 +1,29 @@
|
||||
/datum/objective/uphold_vow
|
||||
name = "Uphold Vow"
|
||||
explanation_text = "Keep your vow."
|
||||
var/datum/mind/target
|
||||
var/vow_text
|
||||
var/approved = TRUE
|
||||
|
||||
/datum/objective/uphold_vow/PostAppend()
|
||||
explanation_text = "Keep your vow, \"[vow_text]\" to [target]."
|
||||
return TRUE
|
||||
|
||||
/datum/objective/uphold_vow/IsFulfilled()
|
||||
return approved
|
||||
|
||||
/datum/objective/uphold_vow/proc/PollMind()
|
||||
if(!target)
|
||||
return TRUE //Default yes!
|
||||
var/approval
|
||||
approval = alert(target.current,"[owner.name] vowed to you: \"[vow_text]\". Was it upheld? No answer defaults as yes.","Vow","Yes","No")
|
||||
switch(approval)
|
||||
if("Yes")
|
||||
to_chat(target.current,"<span class='info'>Your vow feedback was noted.</span>")
|
||||
approved = TRUE
|
||||
if("No")
|
||||
to_chat(target.current,"<span class='info'>Your vow feedback was noted.</span>")
|
||||
approved = FALSE
|
||||
else
|
||||
to_chat(target.current,"<span class='warning'>You took too long to decide on your answer!</span>")
|
||||
approved = TRUE
|
||||
161
code/datums/gamemode/role/rambler.dm
Normal file
161
code/datums/gamemode/role/rambler.dm
Normal file
@@ -0,0 +1,161 @@
|
||||
/datum/role/rambler
|
||||
name = RAMBLER
|
||||
id = RAMBLER
|
||||
required_pref = ROLE_MINOR
|
||||
special_role = RAMBLER
|
||||
logo_state = "rambler-logo"
|
||||
wikiroute = ROLE_MINOR
|
||||
var/remaining_vows = 3
|
||||
|
||||
/datum/role/rambler/OnPostSetup()
|
||||
. =..()
|
||||
if(ishuman(antag.current))
|
||||
equip_rambler(antag.current)
|
||||
name_rambler(antag.current)
|
||||
|
||||
/datum/role/rambler/ForgeObjectives()
|
||||
AppendObjective(/datum/objective/investigate)
|
||||
if(prob(10)) //Since Ramblers generate extra objectives from vows, let's not clog up the list too often
|
||||
AppendObjective(/datum/objective/freeform/ponder)
|
||||
AppendObjective(/datum/objective/ramble)
|
||||
|
||||
/datum/role/rambler/ShuttleDocked(state)
|
||||
if(state == 1)
|
||||
for(var/datum/objective/uphold_vow/O in objectives.GetObjectives())
|
||||
O.PollMind()
|
||||
|
||||
/datum/role/rambler/Greet(var/greeting,var/custom)
|
||||
if(!greeting)
|
||||
return
|
||||
|
||||
var/icon/logo = icon('icons/logos.dmi', logo_state)
|
||||
switch(greeting)
|
||||
if (GREET_CUSTOM)
|
||||
to_chat(antag.current, "<img src='data:image/png;base64,[icon2base64(logo)]' style='position: relative; top: 10;'/> <span class='info'>[custom]</span>")
|
||||
else
|
||||
to_chat(antag.current, "<img src='data:image/png;base64,[icon2base64(logo)]' style='position: relative; top: 10;'/> <span class='info'><B>You are a Soul Rambler.</B><BR>You wander space, looking for the one who killed your closest friend. And, perhaps, seeking answers to less tangible questions about life. If you happen to help people along the way, so be it.</span>")
|
||||
|
||||
to_chat(antag.current, "<span class='warning'>You have no powers, except the power to blow minds. Your shakashuri can be used to pacify spirits, but you will otherwise need to rely on your weapons-grade philosophical insights.</span>")
|
||||
|
||||
/datum/role/rambler/can_wear(var/obj/item/clothing/C)
|
||||
if(istype(C,/obj/item/clothing/mask/breath))
|
||||
return ALWAYSTRUE
|
||||
if(C.body_parts_covered & FULL_TORSO)
|
||||
return FALSE //This previously had feedback but it would spam the user if they tried to quick equip
|
||||
else
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/item/device/instrument/recorder/shakashuri
|
||||
name = "shakashuri"
|
||||
desc = "Similar to other woodwinds, though it can be played only by a true rambler of souls."
|
||||
slot_flags = SLOT_BACK
|
||||
|
||||
/obj/item/device/instrument/recorder/shakashuri/attack_self(mob/user)
|
||||
if(!isrambler(user))
|
||||
to_chat(user,"<span class='warning'>Playing this would require 9 years of training!</span>")
|
||||
return
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/device/instrument/recorder/shakashuri/OnPlayed(mob/user,mob/M)
|
||||
if(user!=M && !M.reagents.has_reagent(CHILLWAX,1))
|
||||
M.reagents.add_reagent(CHILLWAX,0.3)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/quiche/frittata/New()
|
||||
..()
|
||||
name = "frittata"
|
||||
desc = "Now you have no need to eat balls for breakfast."
|
||||
reagents.add_reagent(DOCTORSDELIGHT,37)
|
||||
|
||||
/obj/item/clothing/mask/necklace/crystal
|
||||
name = "crystal necklace"
|
||||
desc = "Your final memento of a lost friend. Use it to decide on the killer."
|
||||
icon_state = "tooth-necklace"
|
||||
var/mob/living/suspect = null
|
||||
|
||||
/obj/item/clothing/mask/necklace/crystal/attack_self(mob/user)
|
||||
if(!isrambler(user))
|
||||
return
|
||||
var/mob/potential = input(user, "Choose your suspect, from those whose voices you've heard before.", "Soul Inspiration") as null|mob in get_list_of_elements(user.mind.heard_before)
|
||||
if(!isliving(potential))
|
||||
to_chat(user,"<span class='warning'>That is some kind of ghost or something!</span>")
|
||||
return
|
||||
if(potential == suspect)
|
||||
to_chat(user,"<span class='warning'>It is just as you suspected. The suspect is the suspicious suspect you have already suspected!</span>")
|
||||
return
|
||||
if(!potential.mind)
|
||||
to_chat(user,"<span class='warning'>To accuse the mindless? The scrawling of a madman!</span>")
|
||||
return
|
||||
if(potential == user)
|
||||
to_chat(user,"<span class='warning'>You already know the crime was arson!</span>")
|
||||
return
|
||||
to_chat(user,"<span class='info'>Your new suspect is [potential].</span>")
|
||||
suspect = potential
|
||||
|
||||
/obj/item/clothing/mask/necklace/crystal/examine(mob/user)
|
||||
..()
|
||||
if(isrambler(user))
|
||||
to_chat(user, "<span class='notice'>Your current suspect is [suspect ? suspect : "no one"].</span>")
|
||||
|
||||
/proc/equip_rambler(var/mob/living/carbon/human/frankenstein/H)
|
||||
var/mob/living/carbon/human/frankenstein/F
|
||||
//If we are a Frankenstein, continue. If we're human, frankensteinize. If not human, abort.
|
||||
if(!istype(H))
|
||||
if(ishuman(F))
|
||||
F = H.Frankensteinize()
|
||||
else
|
||||
return 0
|
||||
else
|
||||
F = H
|
||||
F.mutations += M_NO_BREATH
|
||||
F.dna.SetSEState(NOBREATHBLOCK,1)
|
||||
F.add_spell(new /spell/targeted/lockinvow)
|
||||
F.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel, slot_back)
|
||||
F.equip_or_collect(new /obj/item/clothing/mask/necklace/crystal, slot_wear_mask)
|
||||
F.equip_or_collect(new /obj/item/clothing/shoes/white, slot_shoes)
|
||||
F.put_in_hands(new /obj/item/device/instrument/recorder/shakashuri)
|
||||
F.equip_or_collect(new /obj/item/weapon/reagent_containers/food/snacks/quiche/frittata, slot_in_backpack)
|
||||
|
||||
/proc/name_rambler(var/mob/living/carbon/human/H)
|
||||
var/randomname = pick("Xavier","Renegade","Angel")
|
||||
spawn(0)
|
||||
var/newname = copytext(sanitize(input(H, "You are on a soul journey. Would you like to change your name to something else?", randomname, randomname) as null|text),1,MAX_NAME_LEN)
|
||||
|
||||
if (!newname)
|
||||
newname = randomname
|
||||
|
||||
H.fully_replace_character_name(H.real_name, newname)
|
||||
|
||||
/spell/targeted/lockinvow
|
||||
name = "Lock in Vow"
|
||||
desc = "Allows you to vow to another soul."
|
||||
abbreviation = "LV"
|
||||
charge_max = 100
|
||||
max_targets = 1
|
||||
spell_flags = WAIT_FOR_CLICK
|
||||
compatible_mobs = list(/mob/living)
|
||||
hud_state = "rambler-vow"
|
||||
|
||||
/spell/targeted/lockinvow/cast(list/targets, mob/user = user)
|
||||
..()
|
||||
var/datum/role/rambler/R = user.mind.GetRole(RAMBLER)
|
||||
if(!istype(R))
|
||||
return
|
||||
for(var/mob/living/target in targets)
|
||||
if(!target.mind)
|
||||
to_chat(user,"<span class='warning'>[target] has no mind!</span>")
|
||||
continue
|
||||
var/vow = copytext(sanitize(input(user, "Enter your vow. You have [R.remaining_vows] left.", "VOW LOCK IN") as null|text),1,MAX_MESSAGE_LEN)
|
||||
if(vow)
|
||||
user.say("[target], I vow [vow].")
|
||||
user.say("VOW LOCKED IN!")
|
||||
R.remaining_vows--
|
||||
if(!R.remaining_vows)
|
||||
for(var/spell/spell_to_remove in R.antag.current.spell_list)
|
||||
if(istype(spell_to_remove,/spell/targeted/lockinvow))
|
||||
R.antag.current.remove_spell(spell_to_remove)
|
||||
var/datum/objective/uphold_vow/O = new()
|
||||
O.target = target.mind
|
||||
O.vow_text = vow
|
||||
R.objectives.AddObjective(O,R.antag)
|
||||
@@ -464,6 +464,7 @@
|
||||
// USE THIS INSTEAD (global)
|
||||
/datum/role/proc/RoleTopic(href, href_list, var/datum/mind/M, var/admin_auth)
|
||||
|
||||
/datum/role/proc/ShuttleDocked(state)
|
||||
|
||||
/datum/role/proc/AnnounceObjectives()
|
||||
var/text = ""
|
||||
@@ -506,6 +507,10 @@
|
||||
D.spend_threat(refund_value)
|
||||
D.threat_log += "[worldtime2text()]: [name] cost [refund_value] after being undestroyed."
|
||||
|
||||
//Does the role have special clothign restrictions?
|
||||
/datum/role/proc/can_wear(var/obj/item/clothing/C)
|
||||
return TRUE
|
||||
|
||||
/////////////////////////////THESE ROLES SHOULD GET MOVED TO THEIR OWN FILES ONCE THEY'RE GETTING ELABORATED/////////////////////////
|
||||
|
||||
|
||||
|
||||
@@ -41,6 +41,9 @@
|
||||
user.set_machine(src)
|
||||
song.interact(user)
|
||||
|
||||
/obj/item/device/instrument/proc/OnPlayed(mob/user,mob/M)
|
||||
return
|
||||
|
||||
/obj/item/device/instrument/suicide_act(mob/user)
|
||||
user.visible_message("<span class='danger'>[user] begins trying to play Faerie's Aire and Death Waltz with \the [src]! It looks like \he's trying to commit suicide.</span>")
|
||||
playsound(loc, 'sound/effects/applause.ogg', 50, 1, -1)
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
// note is a number from 1-7 for A-G
|
||||
// acc is either "b", "n", or "#"
|
||||
// oct is 1-8 (or 9 for C)
|
||||
/datum/song/proc/playnote(note, acc as text, oct)
|
||||
/datum/song/proc/playnote(note, acc as text, oct, mob/user)
|
||||
// handle accidental -> B<>C of E<>F
|
||||
if(acc == "b" && (note == 3 || note == 6)) // C or F
|
||||
if(note == 3)
|
||||
@@ -64,6 +64,9 @@
|
||||
continue
|
||||
if(M.client.prefs.hear_instruments)
|
||||
M.playsound_local(source, soundfile, 100, falloff = 5)
|
||||
if(istype(instrumentObj,/obj/item/device/instrument))
|
||||
var/obj/item/device/instrument/INS = instrumentObj
|
||||
INS.OnPlayed(user,M)
|
||||
|
||||
/datum/song/proc/updateDialog(mob/user)
|
||||
instrumentObj.updateDialog() // assumes it's an object in world, override if otherwise
|
||||
@@ -113,7 +116,7 @@
|
||||
cur_acc[cur_note] = "#" // so shift is never required
|
||||
else
|
||||
cur_oct[cur_note] = text2num(ni)
|
||||
playnote(cur_note, cur_acc[cur_note], cur_oct[cur_note])
|
||||
playnote(cur_note, cur_acc[cur_note], cur_oct[cur_note],user)
|
||||
if(notes.len >= 2 && text2num(notes[2]))
|
||||
sleep(sanitize_tempo(tempo / text2num(notes[2])))
|
||||
else
|
||||
|
||||
@@ -147,11 +147,16 @@
|
||||
|
||||
//BS12: Species-restricted clothing check.
|
||||
/obj/item/clothing/mob_can_equip(mob/M, slot, disable_warning = 0, automatic = 0)
|
||||
|
||||
. = ..() //Default return value. If 1, item can be equipped. If 0, it can't be.
|
||||
if(!.)
|
||||
return //Default return value is 0 - don't check for species
|
||||
|
||||
switch(role_check(M))
|
||||
if(FALSE)
|
||||
return CANNOT_EQUIP
|
||||
if(ALWAYSTRUE)
|
||||
return CAN_EQUIP
|
||||
|
||||
if(species_restricted && istype(M,/mob/living/carbon/human) && (slot != slot_l_store && slot != slot_r_store))
|
||||
|
||||
var/wearable = null
|
||||
@@ -206,6 +211,19 @@
|
||||
|
||||
//return ..()
|
||||
|
||||
/obj/item/clothing/proc/role_check(mob/user)
|
||||
if(!user || !user.mind || !user.mind.antag_roles.len)
|
||||
return TRUE //No roles to check
|
||||
for(var/datum/role/R in get_list_of_elements(user.mind.antag_roles))
|
||||
switch(R.can_wear(src))
|
||||
if(ALWAYSTRUE)
|
||||
return ALWAYSTRUE
|
||||
if(FALSE)
|
||||
return FALSE
|
||||
if(TRUE)
|
||||
continue
|
||||
return TRUE //All roles true? Return true.
|
||||
|
||||
/obj/item/clothing/before_stripped(mob/wearer as mob, mob/stripper as mob, slot)
|
||||
..()
|
||||
if(slot == slot_w_uniform) //this will cause us to drop our belt, ID, and pockets!
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/obj/item/clothing/mask/necklace
|
||||
body_parts_covered = 0
|
||||
ignore_flip = TRUE
|
||||
|
||||
/obj/item/clothing/mask/necklace/xeno_claw
|
||||
name = "xeno necklace"
|
||||
|
||||
BIN
icons/logos.dmi
BIN
icons/logos.dmi
Binary file not shown.
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 25 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 103 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.6 KiB |
@@ -358,18 +358,22 @@
|
||||
#include "code\datums\gamemode\objectives\harvest.dm"
|
||||
#include "code\datums\gamemode\objectives\hijack.dm"
|
||||
#include "code\datums\gamemode\objectives\invade.dm"
|
||||
#include "code\datums\gamemode\objectives\investigate.dm"
|
||||
#include "code\datums\gamemode\objectives\massacre.dm"
|
||||
#include "code\datums\gamemode\objectives\minimize_casualties.dm"
|
||||
#include "code\datums\gamemode\objectives\nuclear.dm"
|
||||
#include "code\datums\gamemode\objectives\objective.dm"
|
||||
#include "code\datums\gamemode\objectives\ramble.dm"
|
||||
#include "code\datums\gamemode\objectives\sample.dm"
|
||||
#include "code\datums\gamemode\objectives\silence.dm"
|
||||
#include "code\datums\gamemode\objectives\spray_blood.dm"
|
||||
#include "code\datums\gamemode\objectives\summon_narsie.dm"
|
||||
#include "code\datums\gamemode\objectives\survive.dm"
|
||||
#include "code\datums\gamemode\objectives\survive_silicon.dm"
|
||||
#include "code\datums\gamemode\objectives\uphold_vows.dm"
|
||||
#include "code\datums\gamemode\objectives\freeform\changeling.dm"
|
||||
#include "code\datums\gamemode\objectives\freeform\christmas.dm"
|
||||
#include "code\datums\gamemode\objectives\freeform\rambler.dm"
|
||||
#include "code\datums\gamemode\objectives\freeform\syndicate.dm"
|
||||
#include "code\datums\gamemode\objectives\freeform\vampire.dm"
|
||||
#include "code\datums\gamemode\objectives\freeform\wizard.dm"
|
||||
@@ -395,6 +399,7 @@
|
||||
#include "code\datums\gamemode\role\grinch.dm"
|
||||
#include "code\datums\gamemode\role\legacy_cultist.dm"
|
||||
#include "code\datums\gamemode\role\ninja.dm"
|
||||
#include "code\datums\gamemode\role\rambler.dm"
|
||||
#include "code\datums\gamemode\role\rev.dm"
|
||||
#include "code\datums\gamemode\role\role.dm"
|
||||
#include "code\datums\gamemode\role\summonsurvivors.dm"
|
||||
|
||||
Reference in New Issue
Block a user