Merge remote-tracking branch 'citadel/master' into eldritch_affairs

This commit is contained in:
kevinz000
2020-03-27 21:32:40 -07:00
917 changed files with 182662 additions and 22716 deletions
+2 -2
View File
@@ -9,9 +9,9 @@
/world/IsBanned(key,address,computer_id,type,real_bans_only=FALSE)
var/static/key_cache = list()
if(!real_bans_only)
if(key_cache[key])
if(key_cache[key] >= REALTIMEOFDAY)
return list("reason"="concurrent connection attempts", "desc"="You are attempting to connect too fast. Try again.")
key_cache[key] = 1
key_cache[key] = REALTIMEOFDAY+10 //this shouldn't runtime, but if it does, expiry attempts will cover it to ensure genuine connection attemps wont get trapped in limbo
if (!key || !address || !computer_id)
if(real_bans_only)
+2 -4
View File
@@ -194,7 +194,7 @@
body += "<A href='?_src_=holder;[HrefToken()];tdomeadmin=[REF(M)]'>Thunderdome Admin</A> | "
body += "<A href='?_src_=holder;[HrefToken()];tdomeobserve=[REF(M)]'>Thunderdome Observer</A> | "
body += "<A href='?_src_=holder;[HrefToken()];makementor=[M.ckey]'>Make mentor</A> | "
body += "<A href='?_src_=holder;[HrefToken()];removementor=[M.ckey]'>Remove mentor</A>"
body += "<A href='?_src_=holder;[HrefToken()];removementor=[M.ckey]'>Remove mentor</A> | "
body += "<A href='?_src_=holder;[HrefToken()];makeeligible=[REF(M)]'>Allow reentering round</A>"
body += "<br>"
body += "</body></html>"
@@ -639,15 +639,13 @@
var/almcam = CONFIG_GET(flag/allow_ai_multicam)
CONFIG_SET(flag/allow_ai_multicam, !almcam)
if (almcam)
to_chat(world, "<B>The AI no longer has multicam.</B>")
for(var/i in GLOB.ai_list)
var/mob/living/silicon/ai/aiPlayer = i
if(aiPlayer.multicam_on)
aiPlayer.end_multicam()
else
to_chat(world, "<B>The AI now has multicam.</B>")
log_admin("[key_name(usr)] toggled AI multicam.")
world.update_status()
to_chat(GLOB.ai_list | GLOB.admins, "<B>The AI [almcam ? "no longer" : "now"] has multicam.</B>")
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Multicam", "[!almcam ? "Disabled" : "Enabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/admins/proc/toggleaban()
+5 -1
View File
@@ -40,7 +40,11 @@
H.dna.features["insect_wings"] = pick(GLOB.insect_wings_list)
H.dna.features["deco_wings"] = pick(GLOB.deco_wings_list)
H.dna.features["insect_fluff"] = pick(GLOB.insect_fluffs_list)
H.dna.features["flavor_text"] = "" //Oh no.
H.dna.features["body_model"] = H.gender
H.update_body()
SEND_SIGNAL(H, COMSIG_HUMAN_ON_RANDOMIZE)
H.update_body(TRUE)
H.update_hair()
H.update_body_parts()
+1 -1
View File
@@ -55,7 +55,7 @@
var/question = "Would you like to be [group_name]?"
var/list/candidates = pollCandidatesForMobs(question, ROLE_PAI, null, FALSE, 100, bodies)
while(LAZYLEN(candidates) && LAZYLEN(bodies))
var/mob/dead/observer/C = pick_n_take(candidates)
var/mob/C = pick_n_take(candidates)
var/mob/living/body = pick_n_take(bodies)
to_chat(body, "Your mob has been taken over by a ghost!")
+2 -2
View File
@@ -415,8 +415,8 @@
H.fully_replace_character_name(H.real_name,newname)
H.update_mutant_bodyparts()
if(animetype == "Yes")
var/seifuku = pick(typesof(/obj/item/clothing/under/schoolgirl))
var/obj/item/clothing/under/schoolgirl/I = new seifuku
var/seifuku = pick(typesof(/obj/item/clothing/under/costume/schoolgirl))
var/obj/item/clothing/under/costume/schoolgirl/I = new seifuku
var/olduniform = H.w_uniform
H.temporarilyRemoveItemFromInventory(H.w_uniform, TRUE, FALSE)
H.equip_to_slot_or_del(I, SLOT_W_UNIFORM)
+2 -2
View File
@@ -1732,7 +1732,7 @@
var/mob/M = locate(href_list["makeeligible"])
if(!ismob(M))
to_chat(usr, "this can only be used on instances of type /mob.")
var/datum/element/ghost_role_eligibility/eli = SSdcs.GetElement(/datum/element/ghost_role_eligibility)
var/datum/element/ghost_role_eligibility/eli = SSdcs.GetElement(list(/datum/element/ghost_role_eligibility))
if(M.ckey in eli.timeouts)
eli.timeouts -= M.ckey
@@ -1880,7 +1880,7 @@
if(ishuman(L))
var/mob/living/carbon/human/observer = L
observer.equip_to_slot_or_del(new /obj/item/clothing/under/suit_jacket(observer), SLOT_W_UNIFORM)
observer.equip_to_slot_or_del(new /obj/item/clothing/under/suit/black(observer), SLOT_W_UNIFORM)
observer.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/black(observer), SLOT_SHOES)
L.Unconscious(100)
sleep(5)
@@ -220,4 +220,17 @@
/proc/_instantiate_at(thing, location)
new thing(location)
/// Locating turfs
/proc/_turf_in_offset(s = usr, x = 0, y = 0, z = 0)
var/turf/T = get_turf(s)
return locate(clamp(T.x + x, 1, world.maxx), clamp(T.y + y, 1, world.maxy), clamp(T.z + z, 1, world.maxz))
/proc/_random_turf_in_range(s = usr, r = 7)
return _turf_in_offset(s, rand(-r, r), rand(-r, r))
/proc/_random_turf_in_view(s = usr, r = 7)
var/list/v = view(s, r)
. = list()
for(var/turf/T in v)
. += T
return pick(.)
+3 -3
View File
@@ -1315,15 +1315,15 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
var/obj/item/reagent_containers/food/snacks/pie/cream/nostun/creamy = new(get_turf(target))
creamy.splat(target)
if (ADMIN_PUNISHMENT_CUSTOM_PIE)
var/obj/item/reagent_containers/food/snacks/pie/cream/nostun/A = new(get_turf(target))
var/obj/item/reagent_containers/food/snacks/pie/cream/nostun/A = new()
if(!A.reagents)
var/amount = input(usr, "Specify the reagent size of [A]", "Set Reagent Size", 50) as num
var/amount = input(usr, "Specify the reagent size of [A]", "Set Reagent Size", 50) as num|null
if(amount)
A.create_reagents(amount)
if(A.reagents)
var/chosen_id = choose_reagent_id(usr)
if(chosen_id)
var/amount = input(usr, "Choose the amount to add.", "Choose the amount.", A.reagents.maximum_volume) as num
var/amount = input(usr, "Choose the amount to add.", "Choose the amount.", A.reagents.maximum_volume) as num|null
if(amount)
A.reagents.add_reagent(chosen_id, amount)
A.splat(target)
@@ -22,6 +22,7 @@ GLOBAL_LIST_EMPTY(antagonists)
var/antagpanel_category = "Uncategorized" //Antagpanel will display these together, REQUIRED
var/show_name_in_check_antagonists = FALSE //Will append antagonist name in admin listings - use for categories that share more than one antag type
var/list/blacklisted_quirks = list(/datum/quirk/nonviolent,/datum/quirk/mute) // Quirks that will be removed upon gaining this antag. Pacifist and mute are default.
var/threat = 0 // Amount of threat this antag poses, for dynamic mode
/datum/antagonist/New()
GLOB.antagonists += src
@@ -75,6 +76,7 @@ GLOBAL_LIST_EMPTY(antagonists)
remove_blacklisted_quirks()
if(is_banned(owner.current) && replace_banned)
replace_banned_player()
SEND_SIGNAL(owner.current, COMSIG_MOB_ANTAG_ON_GAIN, src)
/datum/antagonist/proc/is_banned(mob/M)
if(!M)
@@ -84,9 +86,9 @@ GLOBAL_LIST_EMPTY(antagonists)
/datum/antagonist/proc/replace_banned_player()
set waitfor = FALSE
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [name]?", "[name]", null, job_rank, 50, owner.current)
var/list/mob/candidates = pollCandidatesForMob("Do you want to play as a [name]?", "[name]", null, job_rank, 50, owner.current)
if(LAZYLEN(candidates))
var/mob/dead/observer/C = pick(candidates)
var/mob/C = pick(candidates)
to_chat(owner, "Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!")
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(owner.current)]) to replace a jobbaned player.")
owner.current.ghostize(0)
@@ -237,6 +239,10 @@ GLOBAL_LIST_EMPTY(antagonists)
return H.hijack_speed_override
return hijack_speed
/// Gets our threat level. Defaults to threat var, override for custom stuff like different traitor goals having different threats.
/datum/antagonist/proc/threat()
return threat
//This one is created by admin tools for custom objectives
/datum/antagonist/custom
antagpanel_category = "Custom"
@@ -248,7 +248,7 @@
if(used || QDELETED(src))
return
used = TRUE
var/mob/dead/observer/C = pick(candidates)
var/mob/C = pick(candidates)
spawn_antag(C.client, get_turf(src), initial(demon_type.name),user.mind)
to_chat(user, shatter_msg)
to_chat(user, veil_msg)
@@ -6,6 +6,7 @@
antagpanel_category = "Abductor"
job_rank = ROLE_ABDUCTOR
show_in_antagpanel = FALSE //should only show subtypes
threat = 5
var/datum/team/abductor_team/team
var/sub_role
var/outfit
@@ -61,7 +61,7 @@
/obj/machinery/abductor/experiment/proc/dissection_icon(mob/living/carbon/human/H)
var/icon/photo = null
var/g = (H.gender == FEMALE) ? "f" : "m"
var/g = (H.dna.features["body_model"] == FEMALE) ? "f" : "m"
if(H.dna.species.use_skintones)
photo = icon("icon" = 'icons/mob/human.dmi', "icon_state" = "[H.skin_tone]_[g]")
else
+2 -2
View File
@@ -3,7 +3,7 @@
roundend_category = "blobs"
antagpanel_category = "Blob"
job_rank = ROLE_BLOB
threat = 20
var/datum/action/innate/blobpop/pop_action
var/starting_points_human_blob = 60
var/point_rate_human_blob = 2
@@ -63,4 +63,4 @@
if(owner && owner.current)
var/mob/camera/blob/B = owner.current
if(istype(B))
. += "(Progress: [B.blobs_legit.len]/[B.blobwincount])"
. += "(Progress: [B.blobs_legit.len]/[B.blobwincount])"
@@ -75,6 +75,7 @@
desc = "A floating, fragile spore."
icon_state = "blobpod"
icon_living = "blobpod"
threat = 0.2
health = 30
maxHealth = 30
verb_say = "psychically pulses"
@@ -47,7 +47,7 @@
icon_state = "blob_glow"
flags_1 = CHECK_RICOCHET_1
point_return = 8
max_integrity = 50
max_integrity = 100
brute_resist = 1
explosion_block = 2
+12 -11
View File
@@ -71,7 +71,7 @@
var/list/nodes = list()
for(var/i in 1 to GLOB.blob_nodes.len)
var/obj/structure/blob/node/B = GLOB.blob_nodes[i]
nodes["Blob Node #[i] ([B.overmind ? "[B.overmind.blobstrain.name]":"No Strain"])"] = B
nodes["Blob Node #[i] ([get_area_name(B)])"] = B
var/node_name = input(src, "Choose a node to jump to.", "Node Jump") in nodes
var/obj/structure/blob/node/chosen_node = nodes[node_name]
if(chosen_node)
@@ -120,13 +120,13 @@
/mob/camera/blob/proc/create_shield(turf/T)
var/obj/structure/blob/shield/S = locate(/obj/structure/blob/shield) in T
if(S)
if(!can_buy(15))
if(!can_buy(BLOB_REFLECTOR_COST))
return
if(S.obj_integrity < S.max_integrity * 0.5)
add_points(BLOB_REFLECTOR_COST)
to_chat(src, "<span class='warning'>This shield blob is too damaged to be modified properly!</span>")
return
to_chat(src, "<span class='warning'>You secrete a reflective ooze over the shield blob, allowing it to reflect projectiles at the cost of reduced intregrity.</span>")
to_chat(src, "<span class='warning'>You secrete a reflective ooze over the shield blob, allowing it to reflect projectiles at the cost of reduced integrity.</span>")
S.change_to(/obj/structure/blob/shield/reflective, src)
else
createSpecial(15, /obj/structure/blob/shield, 0, 0, T)
@@ -169,7 +169,7 @@
B.naut = TRUE //temporary placeholder to prevent creation of more than one per factory.
to_chat(src, "<span class='notice'>You attempt to produce a blobbernaut.</span>")
var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as a [blobstrain.name] blobbernaut?", ROLE_BLOB, null, ROLE_BLOB, 50) //players must answer rapidly
var/list/mob/candidates = pollGhostCandidates("Do you want to play as a [blobstrain.name] blobbernaut?", ROLE_BLOB, null, ROLE_BLOB, 50) //players must answer rapidly
if(LAZYLEN(candidates)) //if we got at least one candidate, they're a blobbernaut now.
B.max_integrity = initial(B.max_integrity) * 0.25 //factories that produced a blobbernaut have much lower health
B.obj_integrity = min(B.obj_integrity, B.max_integrity)
@@ -247,8 +247,8 @@
/mob/camera/blob/verb/expand_blob_power()
set category = "Blob"
set name = "Expand/Attack Blob (4)"
set desc = "Attempts to create a new blob in this tile. If the tile isn't clear, instead attacks it, damaging mobs and objects."
set name = "Expand/Attack Blob ([BLOB_SPREAD_COST])"
set desc = "Attempts to create a new blob in this tile. If the tile isn't clear, instead attacks it, damaging mobs and objects and refunding [BLOB_ATTACK_REFUND] points."
var/turf/T = get_turf(src)
expand_blob(T)
@@ -261,7 +261,7 @@
if(!possibleblobs.len)
to_chat(src, "<span class='warning'>There is no blob adjacent to the target tile!</span>")
return
if(can_buy(4))
if(can_buy(BLOB_SPREAD_COST))
var/attacksuccess = FALSE
for(var/mob/living/L in T)
if(ROLE_BLOB in L.faction) //no friendly/dead fire
@@ -271,11 +271,11 @@
blobstrain.attack_living(L)
var/obj/structure/blob/B = locate() in T
if(B)
if(attacksuccess) //if we successfully attacked a turf with a blob on it, don't refund shit
if(attacksuccess) //if we successfully attacked a turf with a blob on it, only give an attack refund
B.blob_attack_animation(T, src)
else
to_chat(src, "<span class='warning'>There is a blob there!</span>")
add_points(4) //otherwise, refund all of the cost
add_points(BLOB_SPREAD_COST) //otherwise, refund all of the cost
else
var/list/cardinalblobs = list()
var/list/diagonalblobs = list()
@@ -288,14 +288,15 @@
var/obj/structure/blob/OB
if(cardinalblobs.len)
OB = pick(cardinalblobs)
OB.expand(T, src)
if(!OB.expand(T, src))
add_points(BLOB_ATTACK_REFUND) //assume it's attacked SOMETHING, possibly a structure
else
OB = pick(diagonalblobs)
if(attacksuccess)
OB.blob_attack_animation(T, src)
playsound(OB, 'sound/effects/splat.ogg', 50, 1)
else
add_points(4) //if we're attacking diagonally and didn't hit anything, refund
add_points(BLOB_SPREAD_COST) //if we're attacking diagonally and didn't hit anything, refund
if(attacksuccess)
last_attack = world.time + CLICK_CD_MELEE
else
@@ -27,7 +27,7 @@
INVOKE_ASYNC(B, /obj/effect/mine/pickup/bloodbath/.proc/mineEffect, H) //could use moving out from the mine
for(var/mob/living/carbon/human/P in GLOB.player_list)
if(P == H)
if(P == H || HAS_TRAIT(P, TRAIT_NO_MIDROUND_ANTAG))
continue
to_chat(P, "<span class='userdanger'>You have an overwhelming desire to kill [H]. [H.p_theyve(TRUE)] been marked red! Whoever [H.p_they()] [H.p_were()], friend or foe, go kill [H.p_them()]!</span>")
P.put_in_hands(new /obj/item/kitchen/knife/butcher(P), TRUE)
@@ -43,7 +43,7 @@
// EXPLANATION
/datum/objective/bloodsucker/lair/update_explanation_text()
explanation_text = "Create a lair by claiming a coffin, and protect it until the end of the shift"// Make sure to keep it safe!"
explanation_text = "Create a lair by claiming a coffin, and protect it until the end of the shift."// Make sure to keep it safe!"
// WIN CONDITIONS?
/datum/objective/bloodsucker/lair/check_completion()
@@ -228,7 +228,7 @@
if (SC && SC.lastgen > 0 && SC.connected_panels.len > 0 && SC.connected_tracker)
return FALSE
return TRUE
*/
*/
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -250,15 +250,15 @@
// WIN CONDITIONS?
/datum/objective/bloodsucker/heartthief/check_completion()
// -Must have a body.
if (!owner.current)
if(!owner.current)
return FALSE
// Taken from /steal in objective.dm
var/list/all_items = owner.current.GetAllContents() // Includes items inside other items.
var/itemcount = FALSE
for(var/obj/I in all_items) //Check for items
if(I == /obj/item/organ/heart)
itemcount ++
if (itemcount >= target_amount) // Got the right amount?
if(istype(I, /obj/item/organ/heart/))
itemcount++
if(itemcount >= target_amount) // Got the right amount?
return TRUE
return FALSE
@@ -6,7 +6,7 @@
roundend_category = "bloodsuckers"
antagpanel_category = "Bloodsucker"
job_rank = ROLE_BLOODSUCKER
threat = 5
// NAME
var/vampname // My Dracula name
var/vamptitle // My Dracula title
@@ -91,10 +91,8 @@
// Refill with Blood
owner.current.blood_volume = max(owner.current.blood_volume,BLOOD_VOLUME_SAFE)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/datum/antagonist/bloodsucker/threat()
return threat+3*vamplevel
/datum/antagonist/bloodsucker/proc/SelectFirstName()
@@ -185,10 +183,10 @@
BuyPower(new /datum/action/bloodsucker/veil)
// Traits
for(var/T in defaultTraits)
ADD_TRAIT(owner.current, T, "bloodsucker")
ADD_TRAIT(owner.current, T, BLOODSUCKER_TRAIT)
if(HAS_TRAIT(owner.current, TRAIT_TOXINLOVER)) //No slime bonuses here, no thank you
had_toxlover = TRUE
REMOVE_TRAIT(owner.current, TRAIT_TOXINLOVER, "species")
REMOVE_TRAIT(owner.current, TRAIT_TOXINLOVER, SPECIES_TRAIT)
// Traits: Species
if(ishuman(owner.current))
var/mob/living/carbon/human/H = owner.current
@@ -235,9 +233,9 @@
// owner.RemoveSpell(power)
// Traits
for(var/T in defaultTraits)
REMOVE_TRAIT(owner.current, T, "bloodsucker")
REMOVE_TRAIT(owner.current, T, BLOODSUCKER_TRAIT)
if(had_toxlover == TRUE)
ADD_TRAIT(owner.current, TRAIT_TOXINLOVER, "species")
ADD_TRAIT(owner.current, TRAIT_TOXINLOVER, SPECIES_TRAIT)
// Traits: Species
if(ishuman(owner.current))
@@ -387,7 +385,7 @@
add_objective(heartthief_objective)
/*
else
// Solars Objective, doesnt work due to TG updates.
var/datum/objective/bloodsucker/solars/solars_objective = new
solars_objective.owner = owner
@@ -13,7 +13,10 @@
var/list/datum/objective/objectives_given = list() // For removal if needed.
var/datum/martial_art/my_kungfu // Hunters know a lil kung fu.
var/bad_dude = FALSE // Every first hunter spawned is a SHIT LORD.
threat = -3
/datum/antagonist/vamphunter/threat()
return bad_dude ? -threat : threat
/datum/antagonist/vamphunter/on_gain()
@@ -19,6 +19,7 @@
var/datum/antagonist/bloodsucker/master // Who made me?
var/list/datum/action/powers = list()// Purchased powers
var/list/datum/objective/objectives_given = list() // For removal if needed.
threat = 1
/datum/antagonist/vassal/can_be_owned(datum/mind/new_owner)
// If we weren't created by a bloodsucker, then we cannot be a vassal (assigned from antag panel)
@@ -90,6 +90,7 @@
user.dropItemToGround(src, TRUE) //user.drop_item() // "drop item" doesn't seem to exist anymore. New proc is user.dropItemToGround() but it doesn't seem like it's needed now?
var/obj/item/bodypart/B = C.get_bodypart("chest") // This was all taken from hitby() in human_defense.dm
B.embedded_objects |= src
embedded()
add_mob_blood(target)//Place blood on the stake
loc = C // Put INSIDE the character
B.receive_damage(w_class * embedding.embedded_impact_pain_multiplier)
@@ -95,7 +95,7 @@
H.dna.features = random_features(H.dna.species?.id)
// Apply Appearance
H.update_body() // Outfit and underware, also body.
H.update_body(TRUE) // Outfit and underwear, also body and privates.
//H.update_mutant_bodyparts() // Lizard tails etc
H.update_hair()
H.update_body_parts()
@@ -140,7 +140,7 @@
ADD_TRAIT(H, TRAIT_DISFIGURED, "husk") // NOTE: We are ASSUMING husk. // H.status_flags |= DISFIGURED // Restore "Unknown" disfigurement
H.dna.features = prev_features
// Apply Appearance
H.update_body() // Outfit and underware, also body.
H.update_body(TRUE) // Outfit and underwear, also body and privates.
H.update_hair()
H.update_body_parts() // Body itself, maybe skin color?
cast_effect() // POOF
@@ -5,6 +5,7 @@
var/special_role = ROLE_BROTHER
var/datum/team/brother_team/team
antag_moodlet = /datum/mood_event/focused
threat = 3
/datum/antagonist/brother/create_team(datum/team/brother_team/new_team)
if(!new_team)
@@ -8,6 +8,7 @@
antagpanel_category = "Changeling"
job_rank = ROLE_CHANGELING
antag_moodlet = /datum/mood_event/focused
threat = 10
var/you_are_greet = TRUE
var/give_objectives = TRUE
@@ -13,17 +13,14 @@
var/mob/living/carbon/human/H = user //SHOULD always be human, because req_human = 1
if(!istype(H)) // req_human could be done in can_sting stuff.
return
var/datum/mutation/human/HM = GLOB.mutations_list[CHAMELEON]
if(HM in H.dna.mutations)
HM.force_lose(H)
if(H.dna.get_mutation(CHAMELEON))
H.dna.remove_mutation(CHAMELEON)
else
HM.force_give(H)
H.dna.add_mutation(CHAMELEON)
return TRUE
/obj/effect/proc_holder/changeling/chameleon_skin/on_refund(mob/user)
action.Remove(user)
if(user.has_dna())
var/mob/living/carbon/C = user
var/datum/mutation/human/HM = GLOB.mutations_list[CHAMELEON]
if(HM in C.dna.mutations)
HM.force_lose(C)
C.dna.remove_mutation(CHAMELEON)
@@ -358,9 +358,9 @@
break
if(!L.client || L.client.is_afk())
set waitfor = FALSE
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [L.name], an inactive clock cultist?", ROLE_SERVANT_OF_RATVAR, null, ROLE_SERVANT_OF_RATVAR, 50, L)
var/list/mob/candidates = pollCandidatesForMob("Do you want to play as a [L.name], an inactive clock cultist?", ROLE_SERVANT_OF_RATVAR, null, ROLE_SERVANT_OF_RATVAR, 50, L)
if(LAZYLEN(candidates))
var/mob/dead/observer/C = pick(candidates)
var/mob/C = pick(candidates)
to_chat(L, "<span class='userdanger'>Your physical form has been taken over by another soul due to your inactivity! Ahelp if you wish to regain your form!</span>")
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(L)]) to replace an inactive clock cultist.")
L.ghostize(0)
@@ -6,6 +6,7 @@
unique_name = 1
minbodytemp = 0
unsuitable_atmos_damage = 0
threat = 1
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) //Robotic
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
healable = FALSE
@@ -9,6 +9,7 @@
desc = "The stalwart apparition of a soldier, blazing with crimson flames. It's armed with a gladius and shield."
icon_state = "clockwork_marauder"
mob_biotypes = MOB_HUMANOID
threat = 3
health = 120
maxHealth = 120
force_threshold = 8
@@ -138,11 +138,11 @@
quickbind_desc = "Applies handcuffs to a struck target."
//Vanguard: Provides twenty seconds of greatly increased stamina and stun immunity. At the end of the twenty seconds, 25% of all stuns absorbed are applied to the invoker.
//Vanguard: Provides twenty seconds of greatly increased stamina regeneration and stun immunity. At the end of the twenty seconds, 25% of all stuns absorbed aswell as 50% of healed stamloss are applied to the invoker.
/datum/clockwork_scripture/vanguard
descname = "Self Stun Immunity"
name = "Vanguard"
desc = "Provides twenty seconds of greatly increased stamina and stun immunity. At the end of the twenty seconds, the invoker is knocked down for the equivalent of 25% of all stuns they absorbed. \
desc = "Provides twenty seconds of greatly increased stamina regeneration and stun immunity. At the end of the twenty seconds, the invoker is knocked down for the equivalent of 25% of all stuns they absorbed aswell as incurring 50% of the stamina regenerated as stamina loss \
Excessive absorption will cause unconsciousness."
invocations = list("Shield me...", "...from darkness!")
channel_time = 30
@@ -152,7 +152,7 @@
primary_component = VANGUARD_COGWHEEL
sort_priority = 7
quickbind = TRUE
quickbind_desc = "Allows you to temporarily have quickly regenerating stamina and absorb stuns. All stuns absorbed will affect you when disabled."
quickbind_desc = "Allows you to temporarily have quickly regenerating stamina and absorb stuns. Part of the stuns absorbed and staminaloss healed will affect you when disabled."
/datum/clockwork_scripture/vanguard/check_special_requirements()
if(!GLOB.ratvar_awakens && islist(invoker.stun_absorption) && invoker.stun_absorption["vanguard"] && invoker.stun_absorption["vanguard"]["end_time"] > world.time)
@@ -6,6 +6,7 @@
job_rank = ROLE_SERVANT_OF_RATVAR
antag_moodlet = /datum/mood_event/cult
var/datum/action/innate/hierophant/hierophant_network = new
threat = 3
var/datum/team/clockcult/clock_team
var/make_team = TRUE //This should be only false for tutorial scarabs
var/neutered = FALSE //can not use round ending, gibbing, converting, or similar things with unmatched round impact
+1
View File
@@ -5,6 +5,7 @@
roundend_category = "cultists"
antagpanel_category = "Cult"
antag_moodlet = /datum/mood_event/cult
threat = 3
var/datum/action/innate/cult/comm/communion = new
var/datum/action/innate/cult/mastervote/vote = new
var/datum/action/innate/cult/blood_magic/magic = new
+2 -2
View File
@@ -575,9 +575,9 @@ structure_check() searches for nearby cultist structures required for the invoca
mob_to_revive.grab_ghost()
if(!mob_to_revive.client || mob_to_revive.client.is_afk())
set waitfor = FALSE
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [mob_to_revive.name], an inactive blood cultist?", ROLE_CULTIST, null, ROLE_CULTIST, 50, mob_to_revive)
var/list/mob/candidates = pollCandidatesForMob("Do you want to play as a [mob_to_revive.name], an inactive blood cultist?", ROLE_CULTIST, null, ROLE_CULTIST, 50, mob_to_revive)
if(LAZYLEN(candidates))
var/mob/dead/observer/C = pick(candidates)
var/mob/C = pick(candidates)
to_chat(mob_to_revive.mind, "Your physical form has been taken over by another soul due to your inactivity! Ahelp if you wish to regain your form.")
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(mob_to_revive)]) to replace an AFK player.")
mob_to_revive.ghostize(0)
+9 -6
View File
@@ -91,6 +91,7 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
job_rank = ROLE_DEVIL
//Don't delete upon mind destruction, otherwise soul re-selling will break.
delete_on_mind_deletion = FALSE
threat = 5
var/obligation
var/ban
var/bane
@@ -112,6 +113,9 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
/obj/effect/proc_holder/spell/targeted/summon_dancefloor))
var/ascendable = FALSE
/datum/antagonist/devil/threat()
return threat + form * 10
/datum/antagonist/devil/can_be_owned(datum/mind/new_owner)
. = ..()
return . && (ishuman(new_owner.current) || iscyborg(new_owner.current))
@@ -120,7 +124,6 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
. = ..()
.["Toggle ascendable"] = CALLBACK(src,.proc/admin_toggle_ascendable)
/datum/antagonist/devil/proc/admin_toggle_ascendable(mob/admin)
ascendable = !ascendable
message_admins("[key_name_admin(admin)] set [owner.current] devil ascendable to [ascendable]")
@@ -244,7 +247,7 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
H.undershirt = "Nude"
H.socks = "Nude"
H.dna.features["mcolor"] = "511" //A deep red
H.regenerate_icons()
H.update_body(TRUE)
else //Did the devil get hit by a staff of transmutation?
owner.current.color = "#501010"
give_appropriate_spells()
@@ -414,11 +417,11 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
if(BANISH_FUNERAL_GARB)
if(ishuman(body))
var/mob/living/carbon/human/H = body
if(H.w_uniform && istype(H.w_uniform, /obj/item/clothing/under/burial))
if(H.w_uniform && istype(H.w_uniform, /obj/item/clothing/under/misc/burial))
return 1
return 0
else
for(var/obj/item/clothing/under/burial/B in range(0,body))
for(var/obj/item/clothing/under/misc/burial/B in range(0,body))
if(B.loc == get_turf(B)) //Make sure it's not in someone's inventory or something.
return 1
return 0
@@ -456,7 +459,7 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
return -1
currentMob.change_mob_type( /mob/living/carbon/human, targetturf, null, 1)
var/mob/living/carbon/human/H = owner.current
H.equip_to_slot_or_del(new /obj/item/clothing/under/lawyer/black(H), SLOT_W_UNIFORM)
H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/civilian/lawyer/black(H), SLOT_W_UNIFORM)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/laceup(H), SLOT_SHOES)
H.equip_to_slot_or_del(new /obj/item/storage/briefcase(H), SLOT_HANDS)
H.equip_to_slot_or_del(new /obj/item/pen(H), SLOT_L_STORE)
@@ -466,7 +469,7 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
H.undershirt = "Nude"
H.socks = "Nude"
H.dna.features["mcolor"] = "511"
H.regenerate_icons()
H.update_body(TRUE)
if(SOULVALUE >= TRUE_THRESHOLD) //Yes, BOTH this and the above if statement are to run if soulpower is high enough.
var/mob/living/carbon/true_devil/A = new /mob/living/carbon/true_devil(targetturf)
A.faction |= "hell"
+13 -13
View File
@@ -8,19 +8,19 @@
var/obj/item/clothing/under/U = H.w_uniform
var/static/list/whiteness = list (
/obj/item/clothing/under/color/white = 2,
/obj/item/clothing/under/rank/bartender = 1,
/obj/item/clothing/under/rank/chef = 1,
/obj/item/clothing/under/rank/chief_engineer = 1,
/obj/item/clothing/under/rank/scientist = 1,
/obj/item/clothing/under/rank/chemist = 1,
/obj/item/clothing/under/rank/chief_medical_officer = 1,
/obj/item/clothing/under/rank/geneticist = 1,
/obj/item/clothing/under/rank/virologist = 1,
/obj/item/clothing/under/rank/nursesuit = 1,
/obj/item/clothing/under/rank/medical = 1,
/obj/item/clothing/under/rank/det = 1,
/obj/item/clothing/under/suit_jacket/white = 0.5,
/obj/item/clothing/under/burial = 1
/obj/item/clothing/under/rank/civilian/bartender = 1,
/obj/item/clothing/under/rank/civilian/chef = 1,
/obj/item/clothing/under/rank/engineering/chief_engineer = 1,
/obj/item/clothing/under/rank/rnd/scientist = 1,
/obj/item/clothing/under/rank/medical/chemist = 1,
/obj/item/clothing/under/rank/medical/chief_medical_officer = 1,
/obj/item/clothing/under/rank/medical/geneticist = 1,
/obj/item/clothing/under/rank/medical/virologist = 1,
/obj/item/clothing/under/rank/medical/doctor/nurse = 1,
/obj/item/clothing/under/rank/medical/doctor = 1,
/obj/item/clothing/under/rank/security/detective = 1,
/obj/item/clothing/under/suit/white = 0.5,
/obj/item/clothing/under/misc/burial = 1
)
if(U && whiteness[U.type])
src.visible_message("<span class='warning'>[src] seems to have been harmed by the purity of [attacker]'s clothes.</span>", "<span class='notice'>Unsullied white clothing is disrupting your form.</span>")
+2 -1
View File
@@ -62,6 +62,7 @@
name = "Imp"
antagpanel_category = "Devil"
show_in_roundend = FALSE
threat = 10
/datum/antagonist/imp/on_gain()
. = ..()
@@ -71,4 +72,4 @@
var/datum/objective/newobjective = new
newobjective.explanation_text = "Try to get a promotion to a higher devilic rank."
newobjective.owner = owner
objectives += newobjective
objectives += newobjective
@@ -14,6 +14,13 @@
var/static/list/sins = list(SIN_ACEDIA,SIN_GLUTTONY,SIN_GREED,SIN_SLOTH,SIN_WRATH,SIN_ENVY,SIN_PRIDE)
/datum/antagonist/sintouched/threat()
switch(sin)
if(SIN_GLUTTONY,SIN_ENVY)
return 1
else
return 0
/datum/antagonist/sintouched/New()
. = ..()
sin = pick(sins)
@@ -80,4 +87,4 @@
#undef SIN_GREED
#undef SIN_PRIDE
#undef SIN_SLOTH
#undef SIN_WRATH
#undef SIN_WRATH
@@ -59,7 +59,7 @@ new /datum/disease_ability/symptom/powerful/youth
var/stat_block = ""
var/threshold_block = ""
var/category = ""
var/malefit = 0 // used for threat calculation
var/list/symptoms
var/list/actions
@@ -282,6 +282,7 @@ new /datum/disease_ability/symptom/powerful/youth
/datum/disease_ability/symptom/medium/heal
cost = 5
malefit = -1
category = "Symptom (+)"
/datum/disease_ability/symptom/powerful
@@ -291,6 +292,7 @@ new /datum/disease_ability/symptom/powerful/youth
/datum/disease_ability/symptom/powerful/heal
cost = 8
malefit = -1
category = "Symptom (Strong+)"
/******MILD******/
@@ -319,50 +321,61 @@ new /datum/disease_ability/symptom/powerful/youth
/datum/disease_ability/symptom/medium/hallucigen
symptoms = list(/datum/symptom/hallucigen)
malefit = 1
short_desc = "Cause victims to hallucinate."
long_desc = "Cause victims to hallucinate. Decreases stats, especially resistance."
/datum/disease_ability/symptom/medium/choking
symptoms = list(/datum/symptom/choking)
malefit = 1
short_desc = "Cause victims to choke."
long_desc = "Cause victims to choke, threatening asphyxiation. Decreases stats, especially transmissibility."
/datum/disease_ability/symptom/medium/confusion
symptoms = list(/datum/symptom/confusion)
malefit = 1
short_desc = "Cause victims to become confused."
long_desc = "Cause victims to become confused intermittently."
/datum/disease_ability/symptom/medium/vomit
symptoms = list(/datum/symptom/vomit)
malefit = 1
short_desc = "Cause victims to vomit."
long_desc = "Cause victims to vomit. Slightly increases transmissibility. Vomiting also also causes the victims to lose nutrition and removes some toxin damage."
/datum/disease_ability/symptom/medium/voice_change
symptoms = list(/datum/symptom/voice_change)
malefit = 1
short_desc = "Change the voice of victims."
long_desc = "Change the voice of victims, causing confusion in communications."
/datum/disease_ability/symptom/medium/visionloss
symptoms = list(/datum/symptom/visionloss)
malefit = 1
short_desc = "Damage the eyes of victims, eventually causing blindness."
long_desc = "Damage the eyes of victims, eventually causing blindness. Decreases all stats."
/datum/disease_ability/symptom/medium/deafness
malefit = 1
symptoms = list(/datum/symptom/deafness)
/datum/disease_ability/symptom/medium/fever
malefit = 1
symptoms = list(/datum/symptom/fever)
/datum/disease_ability/symptom/medium/shivering
malefit = 1
symptoms = list(/datum/symptom/shivering)
/datum/disease_ability/symptom/medium/headache
symptoms = list(/datum/symptom/headache)
/datum/disease_ability/symptom/medium/nano_boost
malefit = -1
symptoms = list(/datum/symptom/nano_boost)
/datum/disease_ability/symptom/medium/nano_destroy
malefit = 1
symptoms = list(/datum/symptom/nano_destroy)
/datum/disease_ability/symptom/medium/viraladaptation
@@ -374,18 +387,22 @@ new /datum/disease_ability/symptom/powerful/youth
symptoms = list(/datum/symptom/viralevolution)
/datum/disease_ability/symptom/medium/polyvitiligo
malefit = 1
symptoms = list(/datum/symptom/polyvitiligo)
/datum/disease_ability/symptom/medium/disfiguration
malefit = 1
symptoms = list(/datum/symptom/disfiguration)
/datum/disease_ability/symptom/medium/itching
symptoms = list(/datum/symptom/itching)
malefit = 1
short_desc = "Cause victims to itch."
long_desc = "Cause victims to itch, increasing all stats except stealth."
/datum/disease_ability/symptom/medium/heal/weight_loss
symptoms = list(/datum/symptom/weight_loss)
malefit = 1
short_desc = "Cause victims to lose weight."
long_desc = "Cause victims to lose weight, and make it almost impossible for them to gain nutrition from food. Reduced nutrition allows your infection to spread more easily from hosts, especially by sneezing."
@@ -400,12 +417,15 @@ new /datum/disease_ability/symptom/powerful/youth
/******POWERFUL******/
/datum/disease_ability/symptom/powerful/fire
malefit = 1
symptoms = list(/datum/symptom/fire)
/datum/disease_ability/symptom/powerful/flesh_eating
malefit = 1
symptoms = list(/datum/symptom/flesh_eating)
/datum/disease_ability/symptom/powerful/genetic_mutation
malefit = 1
symptoms = list(/datum/symptom/genetic_mutation)
cost = 8
@@ -413,6 +433,7 @@ new /datum/disease_ability/symptom/powerful/youth
symptoms = list(/datum/symptom/inorganic_adaptation)
/datum/disease_ability/symptom/powerful/narcolepsy
malefit = 1
symptoms = list(/datum/symptom/narcolepsy)
/datum/disease_ability/symptom/powerful/youth
@@ -451,4 +472,4 @@ new /datum/disease_ability/symptom/powerful/youth
/datum/disease_ability/symptom/powerful/heal/coma
symptoms = list(/datum/symptom/heal/coma)
short_desc = "Cause victims to fall into a healing coma when hurt."
long_desc = "Cause victims to fall into a healing coma when hurt."
long_desc = "Cause victims to fall into a healing coma when hurt."
@@ -17,6 +17,14 @@
. = ..()
/datum/antagonist/disease/threat()
var/mob/camera/disease/D = owner.current
var/final_threat = 0
for(var/V in D.purchased_abilities)
var/datum/disease_ability/A = V
final_threat += (A.cost/8)*A.malefit
return final_threat*D.hosts
/datum/antagonist/disease/greet()
to_chat(owner.current, "<span class='notice'>You are the [owner.special_role]!</span>")
to_chat(owner.current, "<span class='notice'>Infect members of the crew to gain adaptation points, and spread your infection further.</span>")
+1
View File
@@ -10,6 +10,7 @@
var/datum/outfit/outfit = /datum/outfit/ert/security
var/role = "Security Officer"
var/list/name_source
threat = -5
show_in_antagpanel = FALSE
antag_moodlet = /datum/mood_event/focused
@@ -2,6 +2,7 @@
name = "Emergency Assistant"
show_name_in_check_antagonists = TRUE
show_in_antagpanel = FALSE
threat = -1
var/mission = "Assist the station."
var/datum/outfit/outfit = /datum/outfit/ert/greybois
@@ -45,7 +45,7 @@
qdel(I)
for(var/obj/item/I in H.held_items)
qdel(I)
H.equip_to_slot_or_del(new /obj/item/clothing/under/kilt/highlander(H), SLOT_W_UNIFORM)
H.equip_to_slot_or_del(new /obj/item/clothing/under/costume/kilt/highlander(H), SLOT_W_UNIFORM)
H.equip_to_slot_or_del(new /obj/item/radio/headset/heads/captain(H), SLOT_EARS)
H.equip_to_slot_or_del(new /obj/item/clothing/head/beret/highlander(H), SLOT_HEAD)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(H), SLOT_SHOES)
@@ -73,4 +73,4 @@
antiwelder.name = "compulsion of honor"
antiwelder.desc = "You are unable to hold anything in this hand until you're the last one left!"
antiwelder.icon_state = "bloodhand_right"
H.put_in_hands(antiwelder)
H.put_in_hands(antiwelder)
@@ -8,6 +8,7 @@
job_rank = ROLE_MONKEY
roundend_category = "monkeys"
antagpanel_category = "Monkey"
threat = 3
var/datum/team/monkey/monkey_team
var/monkey_only = TRUE
@@ -81,6 +82,7 @@
/datum/antagonist/monkey/leader
name = "Monkey Leader"
threat = 5
monkey_only = FALSE
/datum/antagonist/monkey/leader/admin_add(datum/mind/new_owner,mob/admin)
@@ -2,5 +2,6 @@
name = "Morph"
show_name_in_check_antagonists = TRUE
show_in_antagpanel = FALSE
threat = 2
//It does nothing! (Besides tracking)
//It does nothing! (Besides tracking)
@@ -1,4 +1,5 @@
/datum/antagonist/nightmare
name = "Nightmare"
show_in_antagpanel = FALSE
show_name_in_check_antagonists = TRUE
show_name_in_check_antagonists = TRUE
threat = 5
+3
View File
@@ -8,6 +8,9 @@
var/give_objectives = TRUE
var/give_equipment = TRUE
/datum/antagonist/ninja/threat()
return helping_station ? -8 : 8
/datum/antagonist/ninja/apply_innate_effects(mob/living/mob_override)
var/mob/living/M = mob_override || owner.current
update_ninja_icons_added(M)
@@ -3,6 +3,7 @@
name = "Clown Operative"
roundend_category = "clown operatives"
antagpanel_category = "ClownOp"
threat = 7
nukeop_outfit = /datum/outfit/syndicate/clownop
/datum/antagonist/nukeop/clownop/on_gain()
@@ -31,6 +31,7 @@
var/interior = ""
var/proper_bomb = TRUE //Please
var/obj/effect/countdown/nuclearbomb/countdown
var/nuclear_cooldown //used to stop global spam.
/obj/machinery/nuclearbomb/Initialize()
. = ..()
@@ -73,16 +74,15 @@
/obj/machinery/nuclearbomb/syndicate/get_cinematic_type(off_station)
var/datum/game_mode/nuclear/NM = SSticker.mode
switch(off_station)
if(0)
if(FALSE)
if(istype(NM) && !NM.nuke_team.syndies_escaped())
return CINEMATIC_ANNIHILATION
else
return CINEMATIC_NUKE_WIN
if(1)
if(NUKE_MISS_STATION)
return CINEMATIC_NUKE_MISS
if(2)
else
return CINEMATIC_NUKE_FAR
return CINEMATIC_NUKE_FAR
/obj/machinery/nuclearbomb/proc/disk_check(obj/item/disk/nuclear/D)
if(D.fake)
@@ -386,14 +386,14 @@
if("anchor")
if(auth && yes_code)
playsound(src, 'sound/machines/nuke/general_beep.ogg', 50, FALSE)
set_anchor()
set_anchor(usr)
else
playsound(src, 'sound/machines/nuke/angry_beep.ogg', 50, FALSE)
/obj/machinery/nuclearbomb/proc/set_anchor()
if(isinspace() && !anchored)
to_chat(usr, "<span class='warning'>There is nothing to anchor to!</span>")
/obj/machinery/nuclearbomb/proc/set_anchor(mob/user)
if((istype(get_area(src), /area/space) || isinspace()) && !anchored)
to_chat(user, "<span class='warning'>This is not a suitable platform for anchoring [src]!</span>")
else
anchored = !anchored
@@ -416,12 +416,16 @@
return
timing = !timing
if(timing)
if(nuclear_cooldown > world.time)
to_chat(usr, "<span class='danger'>[src]'s timer protocols are currently on cooldown, please stand by.</span>")
return
previous_level = get_security_level()
detonation_timer = world.time + (timer_set * 10)
for(var/obj/item/pinpointer/nuke/syndicate/S in GLOB.pinpointer_list)
S.switch_mode_to(TRACK_INFILTRATOR)
countdown.start()
set_security_level("delta")
nuclear_cooldown = world.time + 15 SECONDS
if(GLOB.war_declared)
var/area/A = get_area(src)
@@ -475,20 +479,14 @@
GLOB.enter_allowed = FALSE
var/off_station = 0
var/off_station = FALSE
var/turf/bomb_location = get_turf(src)
var/area/A = get_area(bomb_location)
if(bomb_location && is_station_level(bomb_location.z))
if(istype(A, /area/space))
off_station = NUKE_NEAR_MISS
if((bomb_location.x < (128-NUKERANGE)) || (bomb_location.x > (128+NUKERANGE)) || (bomb_location.y < (128-NUKERANGE)) || (bomb_location.y > (128+NUKERANGE)))
off_station = NUKE_NEAR_MISS
if(!bomb_location || !is_station_level(bomb_location.z))
off_station = NUKE_MISS_STATION
else if(bomb_location.onSyndieBase())
off_station = NUKE_SYNDICATE_BASE
else
off_station = NUKE_MISS_STATION
if(off_station < 2)
if(!off_station)
SSshuttle.registerHostileEnvironment(src)
SSshuttle.lockdown = TRUE
@@ -502,7 +500,7 @@
INVOKE_ASYNC(GLOBAL_PROC,.proc/KillEveryoneOnZLevel, z)
/obj/machinery/nuclearbomb/proc/get_cinematic_type(off_station)
if(off_station < 2)
if(!off_station)
return CINEMATIC_SELFDESTRUCT
else
return CINEMATIC_SELFDESTRUCT_MISS
@@ -583,7 +581,7 @@
This is here to make the tiles around the station mininuke change when it's armed.
*/
/obj/machinery/nuclearbomb/selfdestruct/set_anchor()
/obj/machinery/nuclearbomb/selfdestruct/set_anchor(mob/user)
return
/obj/machinery/nuclearbomb/selfdestruct/set_active()
@@ -4,6 +4,7 @@
antagpanel_category = "NukeOp"
job_rank = ROLE_OPERATIVE
antag_moodlet = /datum/mood_event/focused
threat = 10
var/datum/team/nuclear/nuke_team
var/always_new_team = FALSE //If not assigned a team by default ops will try to join existing ones, set this to TRUE to always create new team.
var/send_to_spawnpoint = TRUE //Should the user be moved to default spawnpoint.
@@ -10,6 +10,7 @@
roundend_category = "syndicate mutineers"
antagpanel_category = "Syndicate Mutineers"
job_rank = ROLE_TRAITOR // simply use the traitor preference & jobban settings
threat = 5
var/datum/team/overthrow/team
var/static/list/possible_useful_items
+2 -1
View File
@@ -3,6 +3,7 @@
job_rank = ROLE_TRAITOR
roundend_category = "space pirates"
antagpanel_category = "Pirate"
threat = 5
var/datum/team/pirate/crew
/datum/antagonist/pirate/greet()
@@ -104,4 +105,4 @@
else
parts += "<span class='redtext big'>The pirate crew has failed.</span>"
return "<div class='panel redborder'>[parts.Join("<br>")]</div>"
return "<div class='panel redborder'>[parts.Join("<br>")]</div>"
@@ -397,7 +397,7 @@
inert = TRUE
visible_message("<span class='revenwarning'>[src] settles down and seems lifeless.</span>")
return
var/mob/dead/observer/C = pick(candidates)
var/mob/C = pick(candidates)
C.transfer_ckey(revenant.key, FALSE)
if(!revenant.key)
qdel(revenant)
@@ -2,6 +2,7 @@
name = "Revenant"
show_in_antagpanel = FALSE
show_name_in_check_antagonists = TRUE
threat = 5
/datum/antagonist/revenant/greet()
owner.announce_objectives()
@@ -7,6 +7,7 @@
antagpanel_category = "Revolution"
job_rank = ROLE_REV
antag_moodlet = /datum/mood_event/revolution
threat = 2
var/hud_type = "rev"
var/datum/team/revolution/rev_team
@@ -148,6 +149,7 @@
/datum/antagonist/rev/head
name = "Head Revolutionary"
hud_type = "rev_head"
threat = 8
var/remove_clumsy = FALSE
var/give_flash = FALSE
var/give_hud = TRUE
@@ -3,6 +3,7 @@
show_name_in_check_antagonists = TRUE
var/objective_verb = "Kill"
var/datum/mind/summoner
threat = 10
job_rank = ROLE_ALIEN
show_in_antagpanel = FALSE
@@ -28,4 +29,4 @@
/datum/antagonist/slaughter/laughter
name = "Laughter demon"
objective_verb = "Hug and Tickle"
objective_verb = "Hug and Tickle"
@@ -3,6 +3,7 @@
show_in_antagpanel = FALSE
show_name_in_check_antagonists = TRUE
blacklisted_quirks = list(/datum/quirk/nonviolent) // mutes are allowed
threat = 1
var/greet_message = ""
/datum/antagonist/survivalist/proc/forge_objectives()
@@ -70,6 +70,7 @@
icon_living = "swarmer"
icon_dead = "swarmer_unactivated"
icon_gib = null
threat = 0.5
wander = 0
harm_intent_damage = 5
minbodytemp = 0
@@ -5,6 +5,7 @@
max_occurrences = 0
earliest_start = 30 MINUTES
min_players = 15
gamemode_blacklist = list("dynamic")
/datum/round_event/spawn_swarmer
@@ -120,7 +120,7 @@
/datum/antagonist/traitor/internal_affairs/reinstate_escape_objective()
..()
var/objtype = traitor_kind == TRAITOR_HUMAN ? /datum/objective/escape : /datum/objective/survive
var/objtype = !istype(traitor_kind,TRAITOR_AI) ? /datum/objective/escape : /datum/objective/survive
var/datum/objective/escape_objective = new objtype
escape_objective.owner = owner
add_objective(escape_objective)
@@ -215,20 +215,12 @@
kill_objective.target = target_mind
kill_objective.update_explanation_text()
add_objective(kill_objective)
//Optional traitor objective
if(prob(PROB_ACTUAL_TRAITOR))
employer = "The Syndicate"
owner.special_role = TRAITOR_AGENT_ROLE
special_role = TRAITOR_AGENT_ROLE
syndicate = TRUE
forge_single_objective()
return
/datum/antagonist/traitor/internal_affairs/forge_traitor_objectives()
forge_iaa_objectives()
var/objtype = traitor_kind == TRAITOR_HUMAN ? /datum/objective/escape : /datum/objective/survive
var/objtype = !istype(traitor_kind,TRAITOR_AI) ? /datum/objective/escape : /datum/objective/survive
var/datum/objective/escape_objective = new objtype
escape_objective.owner = owner
add_objective(escape_objective)
@@ -0,0 +1,69 @@
/datum/traitor_class/ai // this one is special, so has no weight
name = "Malfunctioning AI"
threat = 20
/datum/traitor_class/ai/forge_objectives(datum/antagonist/traitor/T)
var/objective_count = 0
if(prob(30))
objective_count += forge_single_objective()
for(var/i = objective_count, i < CONFIG_GET(number/traitor_objectives_amount), i++)
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = T.owner
kill_objective.find_target()
T.add_objective(kill_objective)
var/datum/objective/survive/exist/exist_objective = new
exist_objective.owner = T.owner
T.add_objective(exist_objective)
/datum/traitor_class/ai/forge_single_objective(datum/antagonist/traitor/T)
.=1
var/special_pick = rand(1,4)
switch(special_pick)
if(1)
var/datum/objective/block/block_objective = new
block_objective.owner = T.owner
T.add_objective(block_objective)
if(2)
var/datum/objective/purge/purge_objective = new
purge_objective.owner = T.owner
T.add_objective(purge_objective)
if(3)
var/datum/objective/robot_army/robot_objective = new
robot_objective.owner = T.owner
T.add_objective(robot_objective)
if(4) //Protect and strand a target
var/datum/objective/protect/yandere_one = new
yandere_one.owner = T.owner
T.add_objective(yandere_one)
yandere_one.find_target()
var/datum/objective/maroon/yandere_two = new
yandere_two.owner = T.owner
yandere_two.target = yandere_one.target
yandere_two.update_explanation_text() // normally called in find_target()
T.add_objective(yandere_two)
.=2
/datum/traitor_class/ai/on_removal(datum/antagonist/traitor/T)
var/mob/living/silicon/ai/A = T.owner.current
A.set_zeroth_law("")
A.verbs -= /mob/living/silicon/ai/proc/choose_modules
A.malf_picker.remove_malf_verbs(A)
qdel(A.malf_picker)
/datum/traitor_class/ai/apply_innate_effects(mob/living/M)
var/mob/living/silicon/ai/A = M
A.hack_software = TRUE
/datum/traitor_class/ai/remove_innate_effects(mob/living/M)
var/mob/living/silicon/ai/A = M
A.hack_software = FALSE
/datum/traitor_class/ai/finalize_traitor(datum/antagonist/traitor/T)
T.add_law_zero()
T.owner.current.playsound_local(get_turf(T.owner.current), 'sound/ambience/antag/malf.ogg', 100, FALSE, pressure_affected = FALSE)
T.owner.current.grant_language(/datum/language/codespeak)
return FALSE
@@ -0,0 +1,37 @@
/datum/traitor_class/human/assassin
name = "Donk Co Operative"
employer = "Donk Corporation"
weight = 0
chaos = 1
threat = 2
/datum/traitor_class/human/assassin/forge_single_objective(datum/antagonist/traitor/T)
.=1
var/permakill_prob = 20
var/is_dynamic = FALSE
var/datum/game_mode/dynamic/mode
if(istype(SSticker.mode,/datum/game_mode/dynamic))
mode = SSticker.mode
is_dynamic = TRUE
permakill_prob = max(0,mode.threat_level-50)
var/list/active_ais = active_ais()
if(active_ais.len && prob(100/GLOB.joined_player_list.len))
var/datum/objective/destroy/destroy_objective = new
destroy_objective.owner = T.owner
destroy_objective.find_target()
T.add_objective(destroy_objective)
else if(prob(30) || (is_dynamic && (mode.storyteller.flags & NO_ASSASSIN)))
var/datum/objective/maroon/maroon_objective = new
maroon_objective.owner = T.owner
maroon_objective.find_target()
T.add_objective(maroon_objective)
else if(prob(permakill_prob))
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = T.owner
kill_objective.find_target()
T.add_objective(kill_objective)
else
var/datum/objective/assassinate/once/kill_objective = new
kill_objective.owner = T.owner
kill_objective.find_target()
T.add_objective(kill_objective)
@@ -0,0 +1,12 @@
/datum/traitor_class/human/freeform
name = "Waffle Co Agent"
employer = "Waffle Company"
weight = 16
chaos = 0
/datum/traitor_class/human/freeform/forge_objectives(datum/antagonist/traitor/T)
var/datum/objective/escape/O = new
O.explanation_text = "You have no explicit goals! While we don't approve of mindless slaughter, you may antagonize nanotrasen any way you wish! Make sure to escape alive and not in custody, though!"
O.owner = T.owner
T.add_objective(O)
return
@@ -0,0 +1,18 @@
/datum/traitor_class/human/hijack
name = "Gorlex Marauder"
employer = "The Gorlex Marauders"
weight = 3
chaos = 5
threat = 3
uplink_filters = list(/datum/uplink_item/stealthy_weapons/romerol_kit)
/datum/traitor_class/human/hijack/forge_objectives(datum/antagonist/traitor/T)
var/datum/objective/hijack/O = new
O.explanation_text = "The Gorlex Marauders are letting you do what you want, with one condition: the shuttle must be hijacked by hacking its navigational protocols through the control console (alt click emergency shuttle console)."
O.owner = T.owner
T.add_objective(O)
return
/datum/traitor_class/human/hijack/finalize_traitor(datum/antagonist/traitor/T)
T.hijack_speed=1
return TRUE
@@ -0,0 +1,82 @@
/datum/traitor_class/human
name = "Syndicate Agent"
chaos = 0
/datum/traitor_class/human/forge_objectives(datum/antagonist/traitor/T)
var/objective_count = 0 //Hijacking counts towards number of objectives
if(!SSticker.mode.exchange_blue && SSticker.mode.traitors.len >= 8) //Set up an exchange if there are enough traitors
if(!SSticker.mode.exchange_red)
SSticker.mode.exchange_red = T.owner
else
SSticker.mode.exchange_blue = T.owner
T.assign_exchange_role(SSticker.mode.exchange_red)
T.assign_exchange_role(SSticker.mode.exchange_blue)
objective_count += 1 //Exchange counts towards number of objectives
var/toa = CONFIG_GET(number/traitor_objectives_amount)
for(var/i = objective_count, i < toa, i++)
forge_single_objective(T)
if(!(locate(/datum/objective/escape) in T.objectives))
var/datum/objective/escape/escape_objective = new
escape_objective.owner = T.owner
T.add_objective(escape_objective)
return
/datum/traitor_class/human/forge_single_objective(datum/antagonist/traitor/T)
.=1
var/assassin_prob = 50
var/is_dynamic = FALSE
var/datum/game_mode/dynamic/mode
if(istype(SSticker.mode,/datum/game_mode/dynamic))
mode = SSticker.mode
is_dynamic = TRUE
assassin_prob = max(0,mode.threat_level-20)
if(prob(assassin_prob))
if(is_dynamic)
var/threat_spent = CONFIG_GET(number/dynamic_assassinate_cost)
mode.spend_threat(threat_spent)
mode.log_threat("[T.owner.name] spent [threat_spent] on an assassination target.")
var/list/active_ais = active_ais()
if(active_ais.len && prob(100/GLOB.joined_player_list.len))
var/datum/objective/destroy/destroy_objective = new
destroy_objective.owner = T.owner
destroy_objective.find_target()
T.add_objective(destroy_objective)
else if(prob(30) || (is_dynamic && (mode.storyteller.flags & NO_ASSASSIN)))
var/datum/objective/maroon/maroon_objective = new
maroon_objective.owner = T.owner
maroon_objective.find_target()
T.add_objective(maroon_objective)
else if(prob(max(0,assassin_prob-20)))
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = T.owner
kill_objective.find_target()
T.add_objective(kill_objective)
else
var/datum/objective/assassinate/once/kill_objective = new
kill_objective.owner = T.owner
kill_objective.find_target()
T.add_objective(kill_objective)
else
if(prob(15) && !(locate(/datum/objective/download) in T.objectives) && !(T.owner.assigned_role in list("Research Director", "Scientist", "Roboticist")))
var/datum/objective/download/download_objective = new
download_objective.owner = T.owner
download_objective.gen_amount_goal()
T.add_objective(download_objective)
else if(prob(40)) // cum. not counting download: 40%.
var/datum/objective/steal/steal_objective = new
steal_objective.owner = T.owner
steal_objective.find_target()
T.add_objective(steal_objective)
else if(prob(100/3)) // cum. not counting download: 20%.
var/datum/objective/sabotage/sabotage_objective = new
sabotage_objective.owner = T.owner
sabotage_objective.find_target()
T.add_objective(sabotage_objective)
else // cum. not counting download: 40%
var/datum/objective/flavor/traitor/flavor_objective = new
flavor_objective.owner = T.owner
flavor_objective.forge_objective()
T.add_objective(flavor_objective)
/datum/traitor_class/human/greet(datum/antagonist/traitor/T)
to_chat(T.owner.current, "<B><font size=2 color=red>You are under contract with [employer]. They have given you your objectives.</font></B>")
@@ -0,0 +1,14 @@
/datum/traitor_class/human/martyr
name = "Tiger Cooperator"
employer = "The Tiger Cooperative"
weight = 2
chaos = 5
threat = 5
uplink_filters = list(/datum/uplink_item/stealthy_weapons/romerol_kit,/datum/uplink_item/bundles_TC/contract_kit)
/datum/traitor_class/human/martyr/forge_objectives(datum/antagonist/traitor/T)
var/datum/objective/martyr/O = new
O.explanation_text = "The tiger cooperative have given you free reign. You may do as you wish, as long as you die a glorious death!"
O.owner = T.owner
T.add_objective(O)
return
@@ -0,0 +1,40 @@
/datum/traitor_class/human/subterfuge
name = "MI13 Operative"
employer = "MI13"
weight = 20
chaos = -5
/datum/traitor_class/human/subterfuge/forge_single_objective(datum/antagonist/traitor/T)
.=1
var/assassin_prob = 30
var/datum/game_mode/dynamic/mode
if(istype(SSticker.mode,/datum/game_mode/dynamic))
mode = SSticker.mode
assassin_prob = max(0,mode.threat_level-40)
if(prob(assassin_prob))
if(prob(assassin_prob))
var/datum/objective/assassinate/once/kill_objective = new
kill_objective.owner = T.owner
kill_objective.find_target()
T.add_objective(kill_objective)
else
var/datum/objective/maroon/maroon_objective = new
maroon_objective.owner = T.owner
maroon_objective.find_target()
T.add_objective(maroon_objective)
else
if(prob(15) && !(locate(/datum/objective/download) in T.objectives) && !(T.owner.assigned_role in list("Research Director", "Scientist", "Roboticist")))
var/datum/objective/download/download_objective = new
download_objective.owner = T.owner
download_objective.gen_amount_goal()
T.add_objective(download_objective)
else if(prob(70)) // cum. not counting download: 40%.
var/datum/objective/steal/steal_objective = new
steal_objective.owner = T.owner
steal_objective.find_target()
T.add_objective(steal_objective)
else
var/datum/objective/sabotage/sabotage_objective = new
sabotage_objective.owner = T.owner
sabotage_objective.find_target()
T.add_objective(sabotage_objective)
@@ -0,0 +1,40 @@
GLOBAL_LIST_EMPTY(traitor_classes)
/datum/traitor_class
var/name = "Bad Coders Ltd."
var/employer = "The Syndicate"
var/weight = 0
var/chaos = 0
var/threat = 0
var/TC = 20
var/list/uplink_filters
/datum/traitor_class/New()
..()
if(src.type in GLOB.traitor_classes)
qdel(src)
else
GLOB.traitor_classes += src.type
GLOB.traitor_classes[src.type] = src
/datum/traitor_class/proc/forge_objectives(datum/antagonist/traitor/T)
// Like the old forge_human_objectives. Makes all the objectives for this traitor class.
/datum/traitor_class/proc/forge_single_objective(datum/antagonist/traitor/T)
// As forge_single_objective.
/datum/traitor_class/proc/on_removal(datum/antagonist/traitor/T)
// What this does to the antag datum on removal. Called before proper removal, obviously.
/datum/traitor_class/proc/apply_innate_effects(mob/living/M)
// What innate effects it should have. See: AI.
/datum/traitor_class/proc/remove_innate_effects(mob/living/M)
// Cleaning up the innate effects.
/datum/traitor_class/proc/greet(datum/antagonist/traitor/T)
// Message upon creation. Not necessary, but can be useful.
/datum/traitor_class/proc/finalize_traitor(datum/antagonist/traitor/T)
// Finalization. Return TRUE if should play standard traitor sound/equip, return FALSE if both are special case
return TRUE
+51 -227
View File
@@ -1,6 +1,3 @@
#define TRAITOR_HUMAN "human"
#define TRAITOR_AI "AI"
/datum/antagonist/traitor
name = "Traitor"
roundend_category = "traitors"
@@ -12,43 +9,48 @@
var/give_objectives = TRUE
var/should_give_codewords = TRUE
var/should_equip = TRUE
var/traitor_kind = TRAITOR_HUMAN //Set on initial assignment
var/datum/traitor_class/traitor_kind
var/datum/contractor_hub/contractor_hub
hijack_speed = 0.5 //10 seconds per hijack stage by default
threat = 5
/datum/antagonist/traitor/New()
..()
if(!GLOB.traitor_classes.len)//Only need to fill the list when it's needed.
for(var/I in subtypesof(/datum/traitor_class))
new I
/datum/antagonist/traitor/proc/set_traitor_kind(var/kind)
traitor_kind = GLOB.traitor_classes[kind]
/datum/antagonist/traitor/on_gain()
if(owner.current && isAI(owner.current))
traitor_kind = TRAITOR_AI
set_traitor_kind(TRAITOR_AI)
else
var/chaos_weight = 0
if(istype(SSticker.mode,/datum/game_mode/dynamic))
var/datum/game_mode/dynamic/mode = SSticker.mode
chaos_weight = (mode.threat - 50)/50
var/list/weights = list()
for(var/C in GLOB.traitor_classes)
var/datum/traitor_class/class = GLOB.traitor_classes[C]
var/weight = LOGISTIC_FUNCTION(1.5*class.weight,chaos_weight,class.chaos,0)
weights[C] = weight
var/choice = pickweightAllowZero(weights)
if(!choice)
choice = GLOB.traitor_classes[TRAITOR_HUMAN]
set_traitor_kind(pickweightAllowZero(weights))
traitor_kind.weight *= 0.8 // less likely this round
SSticker.mode.traitors += owner
owner.special_role = special_role
if(give_objectives)
forge_traitor_objectives()
traitor_kind.forge_objectives(src)
finalize_traitor()
..()
/datum/antagonist/traitor/apply_innate_effects()
if(owner.assigned_role == "Clown")
var/mob/living/carbon/human/traitor_mob = owner.current
if(traitor_mob && istype(traitor_mob))
if(!silent)
to_chat(traitor_mob, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.")
traitor_mob.dna.remove_mutation(CLOWNMUT)
/datum/antagonist/traitor/remove_innate_effects()
if(owner.assigned_role == "Clown")
var/mob/living/carbon/human/traitor_mob = owner.current
if(traitor_mob && istype(traitor_mob))
traitor_mob.dna.add_mutation(CLOWNMUT)
/datum/antagonist/traitor/on_removal()
//Remove malf powers.
if(traitor_kind == TRAITOR_AI && owner.current && isAI(owner.current))
var/mob/living/silicon/ai/A = owner.current
A.set_zeroth_law("")
A.verbs -= /mob/living/silicon/ai/proc/choose_modules
A.malf_picker.remove_malf_verbs(A)
qdel(A.malf_picker)
traitor_kind.on_removal(src)
SSticker.mode.traitors -= owner
if(!silent && owner.current)
to_chat(owner.current,"<span class='userdanger'> You are no longer the [special_role]! </span>")
@@ -69,192 +71,11 @@
objectives -= O
/datum/antagonist/traitor/proc/forge_traitor_objectives()
switch(traitor_kind)
if(TRAITOR_AI)
forge_ai_objectives()
else
forge_human_objectives()
/datum/antagonist/traitor/proc/forge_human_objectives()
var/is_hijacker = FALSE
var/datum/game_mode/dynamic/mode
var/is_dynamic = FALSE
var/hijack_prob = 0
if(istype(SSticker.mode,/datum/game_mode/dynamic))
mode = SSticker.mode
is_dynamic = TRUE
if(mode.threat >= CONFIG_GET(number/dynamic_hijack_cost))
hijack_prob = CLAMP(mode.threat_level-50,0,20)
if(GLOB.joined_player_list.len>=GLOB.dynamic_high_pop_limit)
is_hijacker = (prob(hijack_prob) && mode.threat_level > CONFIG_GET(number/dynamic_hijack_high_population_requirement))
else
var/indice_pop = min(10,round(GLOB.joined_player_list.len/mode.pop_per_requirement)+1)
is_hijacker = (prob(hijack_prob) && (mode.threat_level >= CONFIG_GET(number_list/dynamic_hijack_requirements)[indice_pop]))
if(mode.storyteller.flags & NO_ASSASSIN)
is_hijacker = FALSE
else if (GLOB.joined_player_list.len >= 30) // Less murderboning on lowpop thanks
hijack_prob = 10
is_hijacker = prob(10)
var/martyr_chance = prob(hijack_prob*2)
var/objective_count = is_hijacker //Hijacking counts towards number of objectives
if(!SSticker.mode.exchange_blue && SSticker.mode.traitors.len >= 8) //Set up an exchange if there are enough traitors
if(!SSticker.mode.exchange_red)
SSticker.mode.exchange_red = owner
else
SSticker.mode.exchange_blue = owner
assign_exchange_role(SSticker.mode.exchange_red)
assign_exchange_role(SSticker.mode.exchange_blue)
objective_count += 1 //Exchange counts towards number of objectives
var/toa = CONFIG_GET(number/traitor_objectives_amount)
for(var/i = objective_count, i < toa, i++)
forge_single_objective()
if(is_hijacker && objective_count <= toa) //Don't assign hijack if it would exceed the number of objectives set in config.traitor_objectives_amount
if (!(locate(/datum/objective/hijack) in objectives))
var/datum/objective/hijack/hijack_objective = new
hijack_objective.owner = owner
add_objective(hijack_objective)
if(is_dynamic)
var/threat_spent = CONFIG_GET(number/dynamic_hijack_cost)
mode.spend_threat(threat_spent)
mode.log_threat("[owner.name] spent [threat_spent] on hijack.")
return
var/martyr_compatibility = 1 //You can't succeed in stealing if you're dead.
for(var/datum/objective/O in objectives)
if(!O.martyr_compatible)
martyr_compatibility = 0
break
if(martyr_compatibility && martyr_chance)
var/datum/objective/martyr/martyr_objective = new
martyr_objective.owner = owner
add_objective(martyr_objective)
if(is_dynamic)
var/threat_spent = CONFIG_GET(number/dynamic_hijack_cost)
mode.spend_threat(threat_spent)
mode.log_threat("[owner.name] spent [threat_spent] on glorious death.")
return
else
if(!(locate(/datum/objective/escape) in objectives))
var/datum/objective/escape/escape_objective = new
escape_objective.owner = owner
add_objective(escape_objective)
return
/datum/antagonist/traitor/proc/forge_ai_objectives()
var/objective_count = 0
if(prob(30))
objective_count += forge_single_objective()
for(var/i = objective_count, i < CONFIG_GET(number/traitor_objectives_amount), i++)
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = owner
kill_objective.find_target()
add_objective(kill_objective)
var/datum/objective/survive/exist/exist_objective = new
exist_objective.owner = owner
add_objective(exist_objective)
/datum/antagonist/traitor/proc/forge_single_objective()
switch(traitor_kind)
if(TRAITOR_AI)
return forge_single_AI_objective()
else
return forge_single_human_objective()
/datum/antagonist/traitor/proc/forge_single_human_objective() //Returns how many objectives are added
.=1
var/assassin_prob = 50
var/is_dynamic = FALSE
var/datum/game_mode/dynamic/mode
if(istype(SSticker.mode,/datum/game_mode/dynamic))
mode = SSticker.mode
is_dynamic = TRUE
assassin_prob = max(0,mode.threat_level-20)
if(prob(assassin_prob))
if(is_dynamic)
var/threat_spent = CONFIG_GET(number/dynamic_assassinate_cost)
mode.spend_threat(threat_spent)
mode.log_threat("[owner.name] spent [threat_spent] on an assassination target.")
var/list/active_ais = active_ais()
if(active_ais.len && prob(100/GLOB.joined_player_list.len))
var/datum/objective/destroy/destroy_objective = new
destroy_objective.owner = owner
destroy_objective.find_target()
add_objective(destroy_objective)
else if(prob(30) || (is_dynamic && (mode.storyteller.flags & NO_ASSASSIN)))
var/datum/objective/maroon/maroon_objective = new
maroon_objective.owner = owner
maroon_objective.find_target()
add_objective(maroon_objective)
else if(prob(max(0,assassin_prob-20)))
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = owner
kill_objective.find_target()
add_objective(kill_objective)
else
var/datum/objective/assassinate/once/kill_objective = new
kill_objective.owner = owner
kill_objective.find_target()
add_objective(kill_objective)
else
if(prob(15) && !(locate(/datum/objective/download) in objectives) && !(owner.assigned_role in list("Research Director", "Scientist", "Roboticist")))
var/datum/objective/download/download_objective = new
download_objective.owner = owner
download_objective.gen_amount_goal()
add_objective(download_objective)
else if(prob(40)) // cum. not counting download: 40%.
var/datum/objective/steal/steal_objective = new
steal_objective.owner = owner
steal_objective.find_target()
add_objective(steal_objective)
else if(prob(100/3)) // cum. not counting download: 20%.
var/datum/objective/sabotage/sabotage_objective = new
sabotage_objective.owner = owner
sabotage_objective.find_target()
add_objective(sabotage_objective)
else // cum. not counting download: 40%
var/datum/objective/flavor/traitor/flavor_objective = new
flavor_objective.owner = owner
flavor_objective.forge_objective()
add_objective(flavor_objective)
/datum/antagonist/traitor/proc/forge_single_AI_objective()
.=1
var/special_pick = rand(1,4)
switch(special_pick)
if(1)
var/datum/objective/block/block_objective = new
block_objective.owner = owner
add_objective(block_objective)
if(2)
var/datum/objective/purge/purge_objective = new
purge_objective.owner = owner
add_objective(purge_objective)
if(3)
var/datum/objective/robot_army/robot_objective = new
robot_objective.owner = owner
add_objective(robot_objective)
if(4) //Protect and strand a target
var/datum/objective/protect/yandere_one = new
yandere_one.owner = owner
add_objective(yandere_one)
yandere_one.find_target()
var/datum/objective/maroon/yandere_two = new
yandere_two.owner = owner
yandere_two.target = yandere_one.target
yandere_two.update_explanation_text() // normally called in find_target()
add_objective(yandere_two)
.=2
traitor_kind.forge_objectives(src)
/datum/antagonist/traitor/greet()
to_chat(owner.current, "<B><font size=3 color=red>You are the [owner.special_role].</font></B>")
traitor_kind.greet(src)
owner.announce_objectives()
if(should_give_codewords)
give_codewords()
@@ -270,32 +91,33 @@
set_antag_hud(owner.current, null)
/datum/antagonist/traitor/proc/finalize_traitor()
switch(traitor_kind)
if(TRAITOR_AI)
add_law_zero()
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/malf.ogg', 100, FALSE, pressure_affected = FALSE)
owner.current.grant_language(/datum/language/codespeak)
if(TRAITOR_HUMAN)
if(should_equip)
equip(silent)
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/tatoralert.ogg', 100, FALSE, pressure_affected = FALSE)
if(traitor_kind.finalize_traitor(src))
if(should_equip)
equip(silent)
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/tatoralert.ogg', 100, FALSE, pressure_affected = FALSE)
/datum/antagonist/traitor/apply_innate_effects(mob/living/mob_override)
. = ..()
update_traitor_icons_added()
var/mob/M = mob_override || owner.current
if(isAI(M) && traitor_kind == TRAITOR_AI)
var/mob/living/silicon/ai/A = M
A.hack_software = TRUE
traitor_kind.apply_innate_effects(M)
if(owner.assigned_role == "Clown")
var/mob/living/carbon/human/H = M
if(istype(H))
if(!silent)
to_chat(H, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.")
H.dna.remove_mutation(CLOWNMUT)
RegisterSignal(M, COMSIG_MOVABLE_HEAR, .proc/handle_hearing)
/datum/antagonist/traitor/remove_innate_effects(mob/living/mob_override)
. = ..()
update_traitor_icons_removed()
var/mob/M = mob_override || owner.current
if(isAI(M) && traitor_kind == TRAITOR_AI)
var/mob/living/silicon/ai/A = M
A.hack_software = FALSE
traitor_kind.remove_innate_effects(M)
if(owner.assigned_role == "Clown")
var/mob/living/carbon/human/H = M
if(istype(H))
H.dna.add_mutation(CLOWNMUT)
UnregisterSignal(M, COMSIG_MOVABLE_HEAR)
/datum/antagonist/traitor/proc/give_codewords()
@@ -326,8 +148,7 @@
killer.add_malf_picker()
/datum/antagonist/traitor/proc/equip(var/silent = FALSE)
if(traitor_kind == TRAITOR_HUMAN)
owner.equip_traitor(employer, silent, src)
owner.equip_traitor(traitor_kind, silent, src)
/datum/antagonist/traitor/proc/assign_exchange_role()
//set faction
@@ -469,3 +290,6 @@
/datum/antagonist/traitor/is_gamemode_hero()
return SSticker.mode.name == "traitor"
/datum/antagonist/traitor/threat()
return threat+traitor_kind.threat
@@ -127,7 +127,7 @@
. = ..()
if (.)
to_chat(user, "<span class='notice'>The uplink vibrates quietly, connecting to nearby agents...</span>")
var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the Contractor Support Unit for [user.real_name]?", ROLE_PAI, null, FALSE, 100, POLL_IGNORE_CONTRACTOR_SUPPORT)
var/list/mob/candidates = pollGhostCandidates("Do you want to play as the Contractor Support Unit for [user.real_name]?", ROLE_PAI, null, FALSE, 100, POLL_IGNORE_CONTRACTOR_SUPPORT)
if(LAZYLEN(candidates))
var/mob/dead/observer/C = pick(candidates)
spawn_contractor_partner(user, C.key)
@@ -224,4 +224,4 @@
/obj/item/storage/box/contractor/fulton_extraction/PopulateContents()
new /obj/item/extraction_pack(src)
new /obj/item/fulton_core(src)
new /obj/item/fulton_core(src)
@@ -2,6 +2,7 @@
name = "Wishgranter Avatar"
show_in_antagpanel = FALSE
show_name_in_check_antagonists = TRUE
threat = 20
/datum/antagonist/wishgranter/proc/forge_objectives()
var/datum/objective/hijack/hijack = new
@@ -24,5 +25,5 @@
return
H.dna.add_mutation(HULK)
H.dna.add_mutation(XRAY)
H.dna.add_mutation(COLDRES)
H.dna.add_mutation(TK)
H.dna.add_mutation(SPACEMUT)
H.dna.add_mutation(TK)
@@ -230,7 +230,7 @@
var/hat = pick(/obj/item/clothing/head/helmet/roman, /obj/item/clothing/head/helmet/roman/legionnaire)
H.equip_to_slot_or_del(new hat(H), SLOT_HEAD)
H.equip_to_slot_or_del(new /obj/item/clothing/under/roman(H), SLOT_W_UNIFORM)
H.equip_to_slot_or_del(new /obj/item/clothing/under/costume/roman(H), SLOT_W_UNIFORM)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/roman(H), SLOT_SHOES)
H.put_in_hands(new /obj/item/shield/riot/roman(H), TRUE)
H.put_in_hands(new /obj/item/claymore(H), TRUE)
@@ -11,7 +11,6 @@
var/buy_word = "Learn"
var/limit //used to prevent a spellbook_entry from being bought more than X times with one wizard spellbook
var/list/no_coexistance_typecache //Used so you can't have specific spells together
var/dynamic_cost = 0 // How much threat the spell costs to purchase for dynamic.
var/dynamic_requirement = 0 // How high the threat level needs to be for purchasing in dynamic.
/datum/spellbook_entry/New()
@@ -31,10 +30,6 @@
for(var/spell in user.mind.spell_list)
if(is_type_in_typecache(spell, no_coexistance_typecache))
return 0
if(dynamic_cost>0 && istype(SSticker.mode,/datum/game_mode/dynamic))
var/datum/game_mode/dynamic/mode = SSticker.mode
if(mode.threat < dynamic_cost)
return 0
return 1
/datum/spellbook_entry/proc/Buy(mob/living/carbon/human/user,obj/item/spellbook/book) //return 1 on success
@@ -70,10 +65,6 @@
SSblackbox.record_feedback("nested tally", "wizard_spell_improved", 1, list("[name]", "[aspell.spell_level]"))
return 1
//No same spell found - just learn it
if(dynamic_cost > 0 && istype(SSticker.mode,/datum/game_mode/dynamic))
var/datum/game_mode/dynamic/mode = SSticker.mode
mode.spend_threat(dynamic_cost)
mode.log_threat("Wizard spent [dynamic_cost] on [name].")
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
user.mind.AddSpell(S)
to_chat(user, "<span class='notice'>You have learned [S.name].</span>")
@@ -97,10 +88,6 @@
if(!S)
S = new spell_type()
var/spell_levels = 0
if(dynamic_cost > 0 && istype(SSticker.mode,/datum/game_mode/dynamic))
var/datum/game_mode/dynamic/mode = SSticker.mode
mode.refund_threat(dynamic_cost)
mode.log_threat("Wizard refunded [dynamic_cost] on [name].")
for(var/obj/effect/proc_holder/spell/aspell in user.mind.spell_list)
if(initial(S.name) == initial(aspell.name))
spell_levels = aspell.spell_level
@@ -308,7 +295,6 @@
desc = "An artefact that spits bolts of coruscating energy which cause the target's very form to reshape itself."
item_path = /obj/item/gun/magic/staff/change
dynamic_requirement = 60
dynamic_cost = 20
/datum/spellbook_entry/item/staffanimation
name = "Staff of Animation"
@@ -375,6 +361,7 @@
desc = "A collection of wands that allow for a wide variety of utility. Wands have a limited number of charges, so be conservative in use. Comes in a handy belt."
item_path = /obj/item/storage/belt/wands/full
category = "Defensive"
dynamic_requirement = 60
/datum/spellbook_entry/item/armor
name = "Mastercrafted Armor Set"
@@ -394,7 +381,6 @@
item_path = /obj/item/antag_spawner/contract
category = "Assistance"
dynamic_requirement = 50
dynamic_cost = 10
/datum/spellbook_entry/item/plasmafist
name = "Plasma Fist"
@@ -422,10 +408,6 @@
category = "Assistance"
dynamic_requirement = 60
/datum/spellbook_entry/item/bloodbottle/New()
..()
dynamic_cost = CONFIG_GET(keyed_list/dynamic_cost)["slaughter_demon"]
/datum/spellbook_entry/item/hugbottle
name = "Bottle of Tickles"
desc = "A bottle of magically infused fun, the smell of which will \
@@ -441,10 +423,6 @@
category = "Assistance"
dynamic_requirement = 40
/datum/spellbook_entry/item/hugbottle/New()
..()
dynamic_cost = CONFIG_GET(keyed_list/dynamic_cost)["slaughter_demon"]/3
/datum/spellbook_entry/item/mjolnir
name = "Mjolnir"
desc = "A mighty hammer on loan from Thor, God of Thunder. It crackles with barely contained power."
@@ -520,7 +498,6 @@
/datum/spellbook_entry/summon/guns
name = "Summon Guns"
desc = "Nothing could possibly go wrong with arming a crew of lunatics just itching for an excuse to kill you. Just be careful not to stand still too long!"
dynamic_cost = 10
dynamic_requirement = 60
/datum/spellbook_entry/summon/guns/IsAvailible()
@@ -534,17 +511,11 @@
active = 1
playsound(get_turf(user), 'sound/magic/castsummon.ogg', 50, 1)
to_chat(user, "<span class='notice'>You have cast summon guns!</span>")
if(istype(SSticker.mode,/datum/game_mode/dynamic))
var/datum/game_mode/dynamic/mode = SSticker.mode
var/threat_spent = dynamic_cost
mode.spend_threat(threat_spent)
mode.log_threat("Wizard spent [threat_spent] on summon guns.")
return 1
/datum/spellbook_entry/summon/magic
name = "Summon Magic"
desc = "Share the wonders of magic with the crew and show them why they aren't to be trusted with it at the same time."
dynamic_cost = 10
dynamic_requirement = 60
/datum/spellbook_entry/summon/magic/IsAvailible()
@@ -558,17 +529,11 @@
active = 1
playsound(get_turf(user), 'sound/magic/castsummon.ogg', 50, 1)
to_chat(user, "<span class='notice'>You have cast summon magic!</span>")
if(istype(SSticker.mode,/datum/game_mode/dynamic))
var/datum/game_mode/dynamic/mode = SSticker.mode
var/threat_spent = dynamic_cost
mode.spend_threat(threat_spent)
mode.log_threat("Wizard spent [threat_spent] on summon magic.")
return 1
/datum/spellbook_entry/summon/events
name = "Summon Events"
desc = "Give Murphy's law a little push and replace all events with special wizard ones that will confound and confuse everyone. Multiple castings increase the rate of these events."
dynamic_cost = 20
dynamic_requirement = 60
var/times = 0
@@ -580,11 +545,6 @@
/datum/spellbook_entry/summon/events/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
summonevents()
if(istype(SSticker.mode,/datum/game_mode/dynamic) && times == 0)
var/datum/game_mode/dynamic/mode = SSticker.mode
var/threat_spent = dynamic_cost
mode.spend_threat(threat_spent)
mode.log_threat("Wizard spent [threat_spent] on summon events.")
times++
playsound(get_turf(user), 'sound/magic/castsummon.ogg', 50, 1)
to_chat(user, "<span class='notice'>You have cast summon events.</span>")
@@ -4,6 +4,7 @@
antagpanel_category = "Wizard"
job_rank = ROLE_WIZARD
antag_moodlet = /datum/mood_event/focused
threat = 30
var/give_objectives = TRUE
var/strip = TRUE //strip before equipping
var/allow_rename = TRUE
+2 -1
View File
@@ -13,6 +13,7 @@
job_rank = ROLE_ALIEN
show_in_antagpanel = FALSE
var/datum/team/xeno/xeno_team
threat = 3
/datum/antagonist/xeno/create_team(datum/team/xeno/new_team)
if(!new_team)
@@ -34,4 +35,4 @@
/mob/living/carbon/alien/mind_initialize()
..()
if(!mind.has_antag_datum(/datum/antagonist/xeno))
mind.add_antag_datum(/datum/antagonist/xeno)
mind.add_antag_datum(/datum/antagonist/xeno)
+2 -2
View File
@@ -103,10 +103,10 @@
bombassembly.setDir(dir)
bombassembly.Move()
/obj/item/onetankbomb/dropped()
/obj/item/onetankbomb/dropped(mob/user)
. = ..()
if(bombassembly)
bombassembly.dropped()
bombassembly.dropped(user)
+2 -2
View File
@@ -83,9 +83,9 @@
/obj/item/assembly_holder/dropped(mob/user)
. = ..()
if(a_left)
a_left.dropped()
a_left.dropped(user)
if(a_right)
a_right.dropped()
a_right.dropped(user)
/obj/item/assembly_holder/attack_hand()//Perhapse this should be a holder_pickup proc instead, can add if needbe I guess
. = ..()
+3 -8
View File
@@ -20,13 +20,8 @@
/obj/item/assembly/infra/ComponentInitialize()
. = ..()
AddComponent(
/datum/component/simple_rotation,
ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_FLIP | ROTATION_VERBS,
null,
null,
CALLBACK(src,.proc/after_rotation)
)
var/static/rotation_flags = ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_FLIP | ROTATION_VERBS
AddComponent(/datum/component/simple_rotation, rotation_flags, after_rotation=CALLBACK(src,.proc/after_rotation))
/obj/item/assembly/infra/proc/after_rotation()
refreshBeam()
@@ -74,7 +69,7 @@
holder.update_icon()
return
/obj/item/assembly/infra/dropped()
/obj/item/assembly/infra/dropped(mob/user)
. = ..()
if(holder)
holder_movement() //sync the dir of the device as well if it's contained in a TTV or an assembly holder
@@ -266,6 +266,7 @@
M.equipOutfit(ctf_gear)
M.dna.species.punchdamagehigh = 25
M.dna.species.punchdamagelow = 25
M.AddElement(/datum/element/ghost_role_eligibility)
spawned_mobs += M
/obj/machinery/capture_the_flag/Topic(href, href_list)
@@ -379,7 +380,7 @@
force = 75
mag_type = /obj/item/ammo_box/magazine/m50/ctf
/obj/item/gun/ballistic/automatic/pistol/deagle/ctf/dropped()
/obj/item/gun/ballistic/automatic/pistol/deagle/ctf/dropped(mob/user)
. = ..()
addtimer(CALLBACK(GLOBAL_PROC, /proc/ctf_floor_vanish, src), 1)
@@ -402,14 +403,14 @@
desc = "This looks like it could really hurt in melee."
force = 50
/obj/item/gun/ballistic/automatic/laser/ctf/dropped()
/obj/item/gun/ballistic/automatic/laser/ctf/dropped(mob/user)
. = ..()
addtimer(CALLBACK(GLOBAL_PROC, /proc/ctf_floor_vanish, src), 1)
/obj/item/ammo_box/magazine/recharge/ctf
ammo_type = /obj/item/ammo_casing/caseless/laser/ctf
/obj/item/ammo_box/magazine/recharge/ctf/dropped()
/obj/item/ammo_box/magazine/recharge/ctf/dropped(mob/user)
. = ..()
addtimer(CALLBACK(GLOBAL_PROC, /proc/ctf_floor_vanish, src), 1)
@@ -475,7 +476,7 @@
return TRUE
return ..()
/obj/item/claymore/ctf/dropped()
/obj/item/claymore/ctf/dropped(mob/user)
. = ..()
addtimer(CALLBACK(GLOBAL_PROC, /proc/ctf_floor_vanish, src), 1)
+7 -7
View File
@@ -208,7 +208,7 @@
else
H.skin_tone = random_skin_tone()
H.update_hair()
H.update_body()
H.update_body() //update_genitals arg FALSE because these don't quite require/have them most times.
if(outfit)
var/static/list/slots = list("uniform", "r_hand", "l_hand", "suit", "shoes", "gloves", "ears", "glasses", "mask", "head", "belt", "r_pocket", "l_pocket", "back", "id", "neck", "backpack_contents", "suit_store")
for(var/slot in slots)
@@ -411,7 +411,7 @@
/datum/outfit/spacebartender
name = "Space Bartender"
uniform = /obj/item/clothing/under/rank/bartender
uniform = /obj/item/clothing/under/rank/civilian/bartender
back = /obj/item/storage/backpack
shoes = /obj/item/clothing/shoes/sneakers/black
suit = /obj/item/clothing/suit/armor/vest
@@ -467,7 +467,7 @@
/datum/outfit/nanotrasenbridgeofficercorpse
name = "Bridge Officer Corpse"
ears = /obj/item/radio/headset/heads/hop
uniform = /obj/item/clothing/under/rank/centcom_officer
uniform = /obj/item/clothing/under/rank/centcom/officer
suit = /obj/item/clothing/suit/armor/bulletproof
shoes = /obj/item/clothing/shoes/sneakers/black
glasses = /obj/item/clothing/glasses/sunglasses
@@ -482,7 +482,7 @@
/datum/outfit/nanotrasencommandercorpse
name = "Nanotrasen Private Security Commander"
uniform = /obj/item/clothing/under/rank/centcom_commander
uniform = /obj/item/clothing/under/rank/centcom/commander
suit = /obj/item/clothing/suit/armor/bulletproof
ears = /obj/item/radio/headset/heads/captain
glasses = /obj/item/clothing/glasses/eyepatch
@@ -502,7 +502,7 @@
/datum/outfit/nanotrasensoldiercorpse
name = "NT Private Security Officer Corpse"
uniform = /obj/item/clothing/under/rank/security
uniform = /obj/item/clothing/under/rank/security/officer
suit = /obj/item/clothing/suit/armor/vest
shoes = /obj/item/clothing/shoes/combat
gloves = /obj/item/clothing/gloves/combat
@@ -602,7 +602,7 @@
/datum/outfit/cryobartender
name = "Cryogenic Bartender"
uniform = /obj/item/clothing/under/rank/bartender
uniform = /obj/item/clothing/under/rank/civilian/bartender
back = /obj/item/storage/backpack
shoes = /obj/item/clothing/shoes/sneakers/black
suit = /obj/item/clothing/suit/armor/vest
@@ -639,7 +639,7 @@
/datum/outfit/lavaknight
name = "Cydonian Knight"
uniform = /obj/item/clothing/under/assistantformal
uniform = /obj/item/clothing/under/misc/assistantformal
mask = /obj/item/clothing/mask/breath
shoes = /obj/item/clothing/shoes/sneakers/black
r_pocket = /obj/item/melee/transforming/energy/sword/cx
@@ -127,10 +127,10 @@
if(!current_wizard)
return
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as Wizard Academy Defender?", ROLE_WIZARD, null, ROLE_WIZARD, 50, current_wizard)
var/list/mob/candidates = pollCandidatesForMob("Do you want to play as Wizard Academy Defender?", ROLE_WIZARD, null, ROLE_WIZARD, 50, current_wizard)
if(LAZYLEN(candidates))
var/mob/dead/observer/C = pick(candidates)
var/mob/C = pick(candidates)
message_admins("[ADMIN_LOOKUPFLW(C)] was spawned as Wizard Academy Defender")
current_wizard.ghostize() // on the off chance braindead defender gets back in
C.transfer_ckey(current_wizard, FALSE)
@@ -269,9 +269,9 @@
A.setup_master(user)
servant_mind.transfer_to(H)
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [user.real_name] Servant?", ROLE_WIZARD, null, ROLE_WIZARD, 50, H)
var/list/mob/candidates = pollCandidatesForMob("Do you want to play as [user.real_name] Servant?", ROLE_WIZARD, null, ROLE_WIZARD, 50, H)
if(LAZYLEN(candidates))
var/mob/dead/observer/C = pick(candidates)
var/mob/C = pick(candidates)
message_admins("[ADMIN_LOOKUPFLW(C)] was spawned as Dice Servant")
C.transfer_ckey(H, FALSE)
@@ -299,7 +299,7 @@
/datum/outfit/butler
name = "Butler"
uniform = /obj/item/clothing/under/suit_jacket/really_black
uniform = /obj/item/clothing/under/suit/black_really
shoes = /obj/item/clothing/shoes/laceup
head = /obj/item/clothing/head/bowler
glasses = /obj/item/clothing/glasses/monocle
@@ -94,7 +94,7 @@
to_chat(user, "<B>Your wish is granted, but at a terrible cost...</B>")
to_chat(user, "The Wish Granter punishes you for your selfishness, claiming your soul and warping your body to match the darkness in your heart.")
user.dna.add_mutation(LASEREYES)
user.dna.add_mutation(COLDRES)
user.dna.add_mutation(SPACEMUT)
user.dna.add_mutation(XRAY)
user.set_species(/datum/species/shadow)
if("Wealth")
+6 -6
View File
@@ -582,18 +582,18 @@ datum/export/gear/glasses //glasses are not worth selling
cost = 10
unit_name = "fancy clothing"
k_elasticity = 1/90 //These will be what sells
export_types = list(/obj/item/clothing/under/scratch, /obj/item/clothing/under/sl_suit, /obj/item/clothing/under/rank/vice, /obj/item/clothing/under/suit_jacket, \
/obj/item/clothing/under/burial, /obj/item/clothing/under/skirt/black, /obj/item/clothing/under/captainparade, /obj/item/clothing/under/hosparademale, \
/obj/item/clothing/under/hosparadefem, /obj/item/clothing/under/assistantformal, /obj/item/clothing/under/stripeddress, /obj/item/clothing/under/redeveninggown, \
/obj/item/clothing/under/plaid_skirt, /obj/item/clothing/under/geisha, /obj/item/clothing/under/trek, /obj/item/clothing/under/rank)
export_types = list(/obj/item/clothing/under/suit/white_on_white, /obj/item/clothing/under/suit/sl, /obj/item/clothing/under/misc/vice_officer, /obj/item/clothing/under/suit/black, \
/obj/item/clothing/under/misc/burial, /obj/item/clothing/under/dress/skirt, /obj/item/clothing/under/rank/captain/parade, /obj/item/clothing/under/rank/security/head_of_security/parade, \
/obj/item/clothing/under/rank/security/head_of_security/parade/female, /obj/item/clothing/under/misc/assistantformal, /obj/item/clothing/under/dress/striped, /obj/item/clothing/under/dress/redeveninggown, \
/obj/item/clothing/under/dress/skirt/plaid, /obj/item/clothing/under/costume/geisha, /obj/item/clothing/under/trek, /obj/item/clothing/under/rank)
include_subtypes = TRUE
/datum/export/gear/armored_jumpsuit
cost = 15
unit_name = "armored_jumpsuit"
k_elasticity = 1/90 //These will be what sells
export_types = list(/obj/item/clothing/under/durathread, /obj/item/clothing/under/rank/security, /obj/item/clothing/under/plasmaman, /obj/item/clothing/under/syndicate, \
/obj/item/clothing/under/rank/det, /obj/item/clothing/under/rank/head_of_security, /obj/item/clothing/under/rank/security/spacepol)
export_types = list(/obj/item/clothing/under/misc/durathread, /obj/item/clothing/under/rank/security/officer, /obj/item/clothing/under/plasmaman, /obj/item/clothing/under/syndicate, \
/obj/item/clothing/under/rank/security/detective, /obj/item/clothing/under/rank/security/head_of_security, /obj/item/clothing/under/rank/security/officer/spacepol)
exclude_types = list(/obj/item/clothing/under/syndicate/tacticool, /obj/item/clothing/under/syndicate/tacticool/skirt)
include_subtypes = TRUE
+1 -1
View File
@@ -211,7 +211,7 @@
/datum/export/weapon/arrows
cost = 150
unit_name = "arrow"
export_types = list(/obj/item/ammo_casing/caseless/arrow, /obj/item/ammo_casing/caseless/arrow/bone, /obj/item/ammo_casing/caseless/arrow/ashen)
export_types = list(/obj/item/ammo_casing/caseless/arrow, /obj/item/ammo_casing/caseless/arrow/bone, /obj/item/ammo_casing/caseless/arrow/ash)
/datum/export/weapon/bow_teaching
cost = 500
+1 -1
View File
@@ -188,7 +188,7 @@
/obj/item/clothing/shoes/russian,
/obj/item/clothing/gloves/combat,
/obj/item/clothing/under/syndicate/rus_army,
/obj/item/clothing/under/soviet,
/obj/item/clothing/under/costume/soviet,
/obj/item/clothing/mask/russian_balaclava,
/obj/item/clothing/head/helmet/rus_ushanka,
/obj/item/clothing/suit/armor/vest/russian_coat,
+13 -13
View File
@@ -219,14 +219,14 @@
name = "Formalwear Crate"
desc = "You're gonna like the way you look, I guaranteed it. Contains an asston of fancy clothing."
cost = 4750 //Lots of fancy clothing that can be sold back!
contains = list(/obj/item/clothing/under/blacktango,
/obj/item/clothing/under/assistantformal,
/obj/item/clothing/under/assistantformal,
/obj/item/clothing/under/lawyer/bluesuit,
contains = list(/obj/item/clothing/under/dress/blacktango,
/obj/item/clothing/under/misc/assistantformal,
/obj/item/clothing/under/misc/assistantformal,
/obj/item/clothing/under/rank/civilian/lawyer/bluesuit,
/obj/item/clothing/suit/toggle/lawyer,
/obj/item/clothing/under/lawyer/purpsuit,
/obj/item/clothing/under/rank/civilian/lawyer/purpsuit,
/obj/item/clothing/suit/toggle/lawyer/purple,
/obj/item/clothing/under/lawyer/blacksuit,
/obj/item/clothing/under/suit/black,
/obj/item/clothing/suit/toggle/lawyer/black,
/obj/item/clothing/accessory/waistcoat,
/obj/item/clothing/neck/tie/blue,
@@ -240,11 +240,11 @@
/obj/item/clothing/shoes/laceup,
/obj/item/clothing/shoes/laceup,
/obj/item/clothing/shoes/laceup,
/obj/item/clothing/under/suit_jacket/charcoal,
/obj/item/clothing/under/suit_jacket/navy,
/obj/item/clothing/under/suit_jacket/burgundy,
/obj/item/clothing/under/suit_jacket/checkered,
/obj/item/clothing/under/suit_jacket/tan,
/obj/item/clothing/under/suit/charcoal,
/obj/item/clothing/under/suit/navy,
/obj/item/clothing/under/suit/burgundy,
/obj/item/clothing/under/suit/checkered,
/obj/item/clothing/under/suit/tan,
/obj/item/lipstick/random)
crate_name = "formalwear crate"
crate_type = /obj/structure/closet/crate/wooden
@@ -277,9 +277,9 @@
contains = list(/obj/item/storage/backpack/clown,
/obj/item/clothing/shoes/clown_shoes,
/obj/item/clothing/mask/gas/clown_hat,
/obj/item/clothing/under/rank/clown,
/obj/item/clothing/under/rank/civilian/clown,
/obj/item/bikehorn,
/obj/item/clothing/under/rank/mime,
/obj/item/clothing/under/rank/civilian/mime,
/obj/item/clothing/shoes/sneakers/black,
/obj/item/clothing/gloves/color/white,
/obj/item/clothing/mask/gas/mime,
+21 -42
View File
@@ -89,32 +89,17 @@
/datum/supply_pack/misc/paper_work
name = "Freelance Paper work"
desc = "The Nanotrasen Primary Bureaucratic Database Intelligence (PDBI) reports that the station has not completed its funding and grant paperwork this solar cycle. In order to gain further funding, your station is required to fill out (20) ten of these forms or no additional capital will be disbursed. We have sent you ten copies of the following form and we expect every one to be up to Nanotrasen Standards." // Disbursement. It's not a typo, look it up.
cost = 700 // Net of 0 credits but makes (120 x 20 = 2400)
desc = "The Nanotrasen Primary Bureaucratic Database Intelligence (PDBI) reports that the station has not completed its funding and grant paperwork this solar cycle. In order to gain further funding, your station is required to fill out (10) ten of these forms or no additional capital will be disbursed. We have sent you ten copies of the following form and we expect every one to be up to Nanotrasen Standards." // Disbursement. It's not a typo, look it up.
cost = 700 // Net of 0 credits but makes (120 x 10 = 1200)
contains = list(/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/folder/paperwork,
/obj/item/pen/fountain
)
crate_name = "Paperwork"
/datum/supply_pack/misc/paper_work/generate()
. = ..()
for(var/i in 1 to 9)
new /obj/item/folder/paperwork(.)
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////// Entertainment ///////////////////////////////
//////////////////////////////////////////////////////////////////////////////
@@ -123,16 +108,14 @@
name = "Bedsheet Crate (R)"
desc = "Snuggle up in some sweet sheets with this assorted bedsheet crate. Each set comes with eight random bedsheets for your slumbering pleasure!"
cost = 2000
contains = list(/obj/item/bedsheet/random,
/obj/item/bedsheet/random,
/obj/item/bedsheet/random,
/obj/item/bedsheet/random,
/obj/item/bedsheet/random,
/obj/item/bedsheet/random,
/obj/item/bedsheet/random,
/obj/item/bedsheet/random) //I'm lazy, and I copy paste stuff.
contains = list(/obj/item/bedsheet/random)
crate_name = "random bedsheet crate"
/datum/supply_pack/misc/randombedsheets/generate()
. = ..()
for(var/i in 1 to 7)
new /obj/item/bedsheet/random(.)
/datum/supply_pack/misc/coloredsheets
name = "Bedsheet Crate (C)"
desc = "Give your night life a splash of color with this crate filled with bedsheets! Contains a total of nine different-colored sheets."
@@ -208,13 +191,14 @@
name = "Dueling Pistols"
desc = "Resolve all your quarrels with some nonlethal fun."
cost = 2000
contains = list(/obj/item/storage/lockbox/dueling/hugbox/stamina,
/obj/item/storage/lockbox/dueling/hugbox/stamina,
/obj/item/storage/lockbox/dueling/hugbox/stamina,
/obj/item/storage/lockbox/dueling/hugbox/stamina,
/obj/item/storage/lockbox/dueling/hugbox/stamina)
contains = list(/obj/item/storage/lockbox/dueling/hugbox/stamina)
crate_name = "dueling pistols"
/datum/supply_pack/misc/dueling_stam/generate()
. = ..()
for(var/i in 1 to 3)
new /obj/item/storage/lockbox/dueling/hugbox/stamina(.)
/datum/supply_pack/misc/dueling_lethal
name = "Lethal Dueling Pistols"
desc = "Settle your differences the true spaceman way."
@@ -240,12 +224,7 @@
cost = 12000
var/num_contained = 3
contains = list(/obj/item/ammo_box/a357,
/obj/item/ammo_box/a357,
/obj/item/ammo_box/a357,
/obj/item/ammo_box/magazine/pistolm9mm,
/obj/item/ammo_box/magazine/pistolm9mm,
/obj/item/ammo_box/magazine/pistolm9mm,
/obj/item/ammo_box/magazine/m45/kitchengun,
/obj/item/ammo_box/magazine/m45/kitchengun)
crate_name = "crate"
@@ -295,7 +274,7 @@
name = "Funeral Supplies"
desc = "Mourn your dead properly buy sending them off with love filled notes, clean clothes, and a proper ceremony. Contains two candle packs, funeral garb, flowers, a paperbin , and crayons to help aid in religious rituals. Coffin included."
cost = 1200
contains = list(/obj/item/clothing/under/burial,
contains = list(/obj/item/clothing/under/misc/burial,
/obj/item/storage/fancy/candle_box,
/obj/item/storage/fancy/candle_box,
/obj/item/reagent_containers/food/snacks/grown/harebell,
@@ -440,8 +419,8 @@
/obj/item/dildo/custom,
/obj/item/vending_refill/kink,
/obj/item/vending_refill/kink,
/obj/item/clothing/under/maid,
/obj/item/clothing/under/maid,
/obj/item/clothing/under/costume/maid,
/obj/item/clothing/under/costume/maid,
/obj/item/electropack/shockcollar,
/obj/item/electropack/shockcollar,
/obj/item/restraints/handcuffs/fake/kinky,
+1 -1
View File
@@ -380,7 +380,7 @@
/obj/item/reagent_containers/food/drinks/bottle/cognac,
/obj/item/storage/fancy/cigarettes/cigars/havana,
/obj/item/clothing/gloves/color/white,
/obj/item/clothing/under/rank/curator,
/obj/item/clothing/under/rank/civilian/curator,
/obj/item/gun/ballistic/shotgun/lethal)
access = ACCESS_ARMORY
crate_name = "sporting crate"
+4 -4
View File
@@ -139,16 +139,16 @@
name = "Security Clothing Crate"
desc = "Contains appropriate outfits for the station's private security force. Contains outfits for the Warden, Head of Security, and two Security Officers. Each outfit comes with a rank-appropriate jumpsuit, suit, and beret. Requires Security access to open."
cost = 3250
contains = list(/obj/item/clothing/under/rank/security/navyblue,
/obj/item/clothing/under/rank/security/navyblue,
contains = list(/obj/item/clothing/under/rank/security/officer/formal,
/obj/item/clothing/under/rank/security/officer/formal,
/obj/item/clothing/suit/armor/navyblue,
/obj/item/clothing/suit/armor/navyblue,
/obj/item/clothing/head/beret/sec/navyofficer,
/obj/item/clothing/head/beret/sec/navyofficer,
/obj/item/clothing/under/rank/warden/navyblue,
/obj/item/clothing/under/rank/security/warden/formal,
/obj/item/clothing/suit/armor/vest/warden/navyblue,
/obj/item/clothing/head/beret/sec/navywarden,
/obj/item/clothing/under/rank/head_of_security/navyblue,
/obj/item/clothing/under/rank/security/head_of_security/formal,
/obj/item/clothing/suit/armor/hos/navyblue,
/obj/item/clothing/head/beret/sec/navyhos)
crate_name = "security clothing crate"
+7
View File
@@ -703,3 +703,10 @@ GLOBAL_LIST_EMPTY(asset_datums)
Insert(initial(D.id), I)
return ..()
/datum/asset/simple/genetics
assets = list(
"dna_discovered.gif" = 'html/dna_discovered.gif',
"dna_undiscovered.gif" = 'html/dna_undiscovered.gif',
"dna_extra.gif" = 'html/dna_extra.gif'
)
-8
View File
@@ -223,7 +223,6 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
new /datum/admins(localhost_rank, ckey, 1, 1)
//preferences datum - also holds some persistent data for the client (because we may as well keep these datums to a minimum)
prefs = GLOB.preferences_datums[ckey]
prefs_vr = GLOB.vore_preferences_datums[ckey] //CITADEL EDIT bypassing a failing hook
if(prefs)
prefs.parent = src
@@ -231,13 +230,6 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
prefs = new /datum/preferences(src)
GLOB.preferences_datums[ckey] = prefs
if(prefs_vr) //CITADEL EDIT bypassing a failing hook START
prefs_vr.client = src
else
prefs_vr = new/datum/vore_preferences(src)
GLOB.vore_preferences_datums[ckey] = prefs_vr
//CITADEL EDIT bypassing a failing hook END
prefs.last_ip = address //these are gonna be used for banning
prefs.last_id = computer_id //these are gonna be used for banning
fps = prefs.clientfps
+113 -107
View File
@@ -121,50 +121,35 @@ GLOBAL_LIST_EMPTY(preferences_datums)
"taur" = "None",
"genitals_use_skintone" = FALSE,
"has_cock" = FALSE,
"cock_shape" = "Human",
"cock_length" = 6,
"cock_shape" = DEF_COCK_SHAPE,
"cock_length" = COCK_SIZE_DEF,
"cock_diameter_ratio" = COCK_DIAMETER_RATIO_DEF,
"cock_color" = "fff",
"has_sheath" = FALSE,
"sheath_color" = "fff",
"has_balls" = FALSE,
"balls_internal" = FALSE,
"balls_color" = "fff",
"balls_amount" = 2,
"balls_sack_size" = BALLS_SACK_SIZE_DEF,
"balls_shape" = "Single",
"balls_shape" = DEF_BALLS_SHAPE,
"balls_size" = BALLS_SIZE_DEF,
"balls_cum_rate" = CUM_RATE,
"balls_cum_mult" = CUM_RATE_MULT,
"balls_efficiency" = CUM_EFFICIENCY,
"has_ovi" = FALSE,
"ovi_shape" = "knotted",
"ovi_length" = 6,
"ovi_color" = "fff",
"has_eggsack" = FALSE,
"eggsack_internal" = TRUE,
"eggsack_color" = "fff",
"eggsack_size" = BALLS_SACK_SIZE_DEF,
"eggsack_egg_color" = "fff",
"eggsack_egg_size" = EGG_GIRTH_DEF,
"has_breasts" = FALSE,
"breasts_color" = "fff",
"breasts_size" = "C",
"breasts_shape" = "Pair",
"breasts_size" = BREASTS_SIZE_DEF,
"breasts_shape" = DEF_BREASTS_SHAPE,
"breasts_producing" = FALSE,
"has_vag" = FALSE,
"vag_shape" = "Human",
"vag_shape" = DEF_VAGINA_SHAPE,
"vag_color" = "fff",
"vag_clits" = 1,
"vag_clit_diam" = 0.25,
"has_womb" = FALSE,
"womb_cum_rate" = CUM_RATE,
"womb_cum_mult" = CUM_RATE_MULT,
"womb_efficiency" = CUM_EFFICIENCY,
"balls_visibility" = GEN_VISIBLE_NO_UNDIES,
"breasts_visibility"= GEN_VISIBLE_NO_UNDIES,
"cock_visibility" = GEN_VISIBLE_NO_UNDIES,
"vag_visibility" = GEN_VISIBLE_NO_UNDIES,
"ipc_screen" = "Sunburst",
"ipc_antenna" = "None",
"flavor_text" = "",
"meat_type" = "Mammalian"
"meat_type" = "Mammalian",
"body_model" = MALE
)
var/list/custom_names = list()
@@ -200,11 +185,22 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/sprint_spacebar = FALSE
var/sprint_toggle = FALSE
var/hud_toggle_flash = TRUE
var/hud_toggle_color = "#ffffff"
var/list/exp = list()
var/list/menuoptions
var/action_buttons_screen_locs = list()
//bad stuff
var/digestable = FALSE
var/devourable = FALSE
var/feeding = FALSE
var/lickable = FALSE
var/list/belly_prefs = list()
var/vore_taste = "nothing in particular"
//backgrounds
var/mutable_appearance/character_background
var/icon/bgstate = "steel"
@@ -349,6 +345,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "[TextPreview(features["flavor_text"])]...<BR>"
dat += "<h2>Body</h2>"
dat += "<b>Gender:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=gender'>[gender == MALE ? "Male" : (gender == FEMALE ? "Female" : (gender == PLURAL ? "Non-binary" : "Object"))]</a><BR>"
if(gender != NEUTER && pref_species.sexes)
dat += "<b>Body Model:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=body_model'>[features["body_model"] == MALE ? "Masculine" : "Feminine"]</a><BR>"
dat += "<b>Species:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=species;task=input'>[pref_species.name]</a><BR>"
dat += "<b>Custom Species Name:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=custom_species;task=input'>[custom_species ? custom_species : "None"]</a><BR>"
dat += "<b>Random Body:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=all;task=random'>Randomize!</A><BR>"
@@ -421,7 +419,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "</td>"
mutant_category = 0
if("tail_lizard" in pref_species.default_features)
if(pref_species.mutant_bodyparts["tail_lizard"])
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -434,7 +432,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "</td>"
mutant_category = 0
if("mam_tail" in pref_species.default_features)
if(pref_species.mutant_bodyparts["mam_tail"])
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -446,7 +444,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(mutant_category >= MAX_MUTANT_ROWS)
dat += "</td>"
mutant_category = 0
if("tail_human" in pref_species.default_features)
if(pref_species.mutant_bodyparts["tail_human"])
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -459,7 +457,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "</td>"
mutant_category = 0
if("meat_type" in pref_species.default_features)
if(pref_species.mutant_bodyparts["meat_type"])
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -471,7 +469,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(mutant_category >= MAX_MUTANT_ROWS)
dat += "</td>"
mutant_category = 0
if("snout" in pref_species.default_features)
if(pref_species.mutant_bodyparts["snout"])
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -483,7 +481,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(mutant_category >= MAX_MUTANT_ROWS)
dat += "</td>"
mutant_category = 0
if("horns" in pref_species.default_features)
if(pref_species.mutant_bodyparts["horns"])
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -496,7 +494,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
mutant_category++
if(mutant_category >= MAX_MUTANT_ROWS)
dat += "</td>"
if("frills" in pref_species.default_features)
if(pref_species.mutant_bodyparts["frills"])
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -509,7 +507,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "</td>"
mutant_category = 0
if("spines" in pref_species.default_features)
if(pref_species.mutant_bodyparts["spines"])
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -522,7 +520,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "</td>"
mutant_category = 0
if("body_markings" in pref_species.default_features)
if(pref_species.mutant_bodyparts["body_markings"])
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -534,7 +532,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(mutant_category >= MAX_MUTANT_ROWS)
dat += "</td>"
mutant_category = 0
if("mam_body_markings" in pref_species.default_features)
if(pref_species.mutant_bodyparts["mam_body_markings"])
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -546,7 +544,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(mutant_category >= MAX_MUTANT_ROWS)
dat += "</td>"
if("mam_ears" in pref_species.default_features)
if(pref_species.mutant_bodyparts["mam_ears"])
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -559,7 +557,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "</td>"
mutant_category = 0
if("ears" in pref_species.default_features)
if(pref_species.mutant_bodyparts["ears"])
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -572,7 +570,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "</td>"
mutant_category = 0
if("mam_snouts" in pref_species.default_features)
if(pref_species.mutant_bodyparts["mam_snouts"])
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -584,7 +582,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(mutant_category >= MAX_MUTANT_ROWS)
dat += "</td>"
mutant_category = 0
if("legs" in pref_species.default_features)
if(pref_species.mutant_bodyparts["legs"])
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -596,7 +594,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(mutant_category >= MAX_MUTANT_ROWS)
dat += "</td>"
mutant_category = 0
if("deco_wings" in pref_species.default_features)
if(pref_species.mutant_bodyparts["deco_wings"])
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -605,7 +603,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<a style='display:block;width:100px' href='?_src_=prefs;preference=deco_wings;task=input'>[features["deco_wings"]]</a>"
dat += "<span style='border:1px solid #161616; background-color: #[wing_color];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=wings_color;task=input'>Change</a><BR>"
if("insect_wings" in pref_species.default_features)
if(pref_species.mutant_bodyparts["insect_wings"])
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -617,7 +615,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(mutant_category >= MAX_MUTANT_ROWS)
dat += "</td>"
mutant_category = 0
if("insect_fluff" in pref_species.default_features)
if(pref_species.mutant_bodyparts["insect_fluff"])
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -628,7 +626,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(mutant_category >= MAX_MUTANT_ROWS)
dat += "</td>"
mutant_category = 0
if("taur" in pref_species.default_features)
if(pref_species.mutant_bodyparts["taur"])
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -636,7 +634,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<a style='display:block;width:100px' href='?_src_=prefs;preference=taur;task=input'>[features["taur"]]</a>"
if("insect_markings" in pref_species.default_features)
if(pref_species.mutant_bodyparts["insect_markings"])
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -653,7 +651,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(mutant_category >= MAX_MUTANT_ROWS)
dat += "</td>"
mutant_category = 0
if("wings" in pref_species.mutant_bodyparts && GLOB.r_wings_list.len >1)
if(pref_species.mutant_bodyparts["wings"] && GLOB.r_wings_list.len >1)
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -665,7 +663,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(mutant_category >= MAX_MUTANT_ROWS)
dat += "</td>"
mutant_category = 0
if("xenohead" in pref_species.default_features)
if(pref_species.mutant_bodyparts["xenohead"])
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -677,7 +675,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(mutant_category >= MAX_MUTANT_ROWS)
dat += "</td>"
mutant_category = 0
if("xenotail" in pref_species.default_features)
if(pref_species.mutant_bodyparts["xenotail"])
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -689,7 +687,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(mutant_category >= MAX_MUTANT_ROWS)
dat += "</td>"
mutant_category = 0
if("xenodorsal" in pref_species.default_features)
if(pref_species.mutant_bodyparts["xenodorsal"])
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -701,7 +699,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(mutant_category >= MAX_MUTANT_ROWS)
dat += "</td>"
mutant_category = 0
if("ipc_screen" in pref_species.default_features)
if(pref_species.mutant_bodyparts["ipc_screen"])
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -713,7 +711,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(mutant_category >= MAX_MUTANT_ROWS)
dat += "</td>"
mutant_category = 0
if("ipc_antenna" in pref_species.default_features)
if(pref_species.mutant_bodyparts["ipc_antenna"])
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -766,6 +764,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<span style='border: 1px solid #161616; background-color: #[features["cock_color"]];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=cock_color;task=input'>Change</a><br>"
dat += "<b>Penis Shape:</b> <a style='display:block;width:120px' href='?_src_=prefs;preference=cock_shape;task=input'>[features["cock_shape"]]</a>"
dat += "<b>Penis Length:</b> <a style='display:block;width:120px' href='?_src_=prefs;preference=cock_length;task=input'>[features["cock_length"]] inch(es)</a>"
dat += "<b>Penis Visibility:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=cock_visibility;task=input'>[features["cock_visibility"]]</a>"
dat += "<b>Has Testicles:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=has_balls'>[features["has_balls"] == TRUE ? "Yes" : "No"]</a>"
if(features["has_balls"])
if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE)
@@ -774,7 +773,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
else
dat += "<b>Testicles Color:</b></a><BR>"
dat += "<span style='border: 1px solid #161616; background-color: #[features["balls_color"]];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=balls_color;task=input'>Change</a><br>"
dat += "<b>Testicles showing:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=balls_shape;task=input'>[features["balls_shape"]]</a>"
dat += "<b>Testicles Visibility:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=balls_visibility;task=input'>[features["balls_visibility"]]</a>"
dat += APPEARANCE_CATEGORY_COLUMN
dat += "<h3>Vagina</h3>"
dat += "<a style='display:block;width:50px' href='?_src_=prefs;preference=has_vag'>[features["has_vag"] == TRUE ? "Yes" : "No"]</a>"
@@ -786,6 +785,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
else
dat += "<b>Vagina Color:</b></a><BR>"
dat += "<span style='border: 1px solid #161616; background-color: #[features["vag_color"]];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=vag_color;task=input'>Change</a><br>"
dat += "<b>Vagina Visibility:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=vag_visibility;task=input'>[features["vag_visibility"]]</a>"
dat += "<b>Has Womb:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=has_womb'>[features["has_womb"] == TRUE ? "Yes" : "No"]</a>"
dat += "</td>"
dat += APPEARANCE_CATEGORY_COLUMN
@@ -799,7 +799,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<b>Color:</b></a><BR>"
dat += "<span style='border: 1px solid #161616; background-color: #[features["breasts_color"]];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=breasts_color;task=input'>Change</a><br>"
dat += "<b>Cup Size:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=breasts_size;task=input'>[features["breasts_size"]]</a>"
dat += "<b>Breast Shape:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=breasts_shape;task=input'>[features["breasts_shape"]]</a>"
dat += "<b>Breasts Shape:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=breasts_shape;task=input'>[features["breasts_shape"]]</a>"
dat += "<b>Breasts Visibility:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=breasts_visibility;task=input'>[features["breasts_visibility"]]</a>"
dat += "<b>Lactates:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=breasts_producing'>[features["breasts_producing"] == TRUE ? "Yes" : "No"]</a>"
dat += "</td>"
dat += "</td>"
@@ -905,6 +906,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<b>Fit Viewport:</b> <a href='?_src_=prefs;preference=auto_fit_viewport'>[auto_fit_viewport ? "Auto" : "Manual"]</a><br>"
dat += "<b>Sprint Key:</b> <a href='?_src_=prefs;preference=sprint_key'>[sprint_spacebar ? "Space" : "Shift"]</a><br>"
dat += "<b>Toggle Sprint:</b> <a href='?_src_=prefs;preference=sprint_toggle'>[sprint_toggle ? "Enabled" : "Disabled"]</a><br>"
dat += "<b>HUD Button Flashes:</b> <a href='?_src_=prefs;preference=hud_toggle_flash'>[hud_toggle_flash ? "Enabled" : "Disabled"]</a><br>"
dat += "<b>HUD Button Flash Color:</b> <span style='border: 1px solid #161616; background-color: [hud_toggle_color];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=hud_toggle_color;task=input'>Change</a><br>"
if (CONFIG_GET(flag/maprotation) && CONFIG_GET(flag/tgstyle_maprotation))
var/p_map = preferred_map
@@ -1483,7 +1486,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
age = max(min( round(text2num(new_age)), AGE_MAX),AGE_MIN)
if("flavor_text")
var/msg = stripped_multiline_input(usr, "Set the flavor text in your 'examine' verb. This can also be used for OOC notes and preferences!", "Flavor Text", features["flavor_text"], MAX_FAVOR_LEN, TRUE)
var/msg = stripped_multiline_input(usr, "Set the flavor text in your 'examine' verb. This can also be used for OOC notes and preferences!", "Flavor Text", features["flavor_text"], MAX_FLAVOR_LEN, TRUE)
if(!isnull(msg))
features["flavor_text"] = html_decode(msg)
@@ -1566,14 +1569,14 @@ GLOBAL_LIST_EMPTY(preferences_datums)
pref_species = new newtype()
//let's ensure that no weird shit happens on species swapping.
custom_species = null
if(!("body_markings" in pref_species.default_features))
if(!pref_species.mutant_bodyparts["body_markings"])
features["body_markings"] = "None"
if(!("mam_body_markings" in pref_species.default_features))
if(!pref_species.mutant_bodyparts["mam_body_markings"])
features["mam_body_markings"] = "None"
if("mam_body_markings" in pref_species.default_features)
if(pref_species.mutant_bodyparts["mam_body_markings"])
if(features["mam_body_markings"] == "None")
features["mam_body_markings"] = "Plain"
if("tail_lizard" in pref_species.default_features)
if(pref_species.mutant_bodyparts["tail_lizard"])
features["tail_lizard"] = "Smooth"
if(pref_species.id == "felinid")
features["mam_tail"] = "Cat"
@@ -1916,6 +1919,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
new_dors = input(user, "Choose your character's dorsal tube type:", "Character Preference") as null|anything in GLOB.xeno_dorsal_list
if(new_dors)
features["xenodorsal"] = new_dors
//Genital code
if("cock_color")
var/new_cockcolor = input(user, "Penis color:", "Character Preference") as color|null
@@ -1929,9 +1933,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
if("cock_length")
var/new_length = input(user, "Penis length in inches:\n([COCK_SIZE_MIN]-[COCK_SIZE_MAX])", "Character Preference") as num|null
var/min_D = CONFIG_GET(number/penis_min_inches_prefs)
var/max_D = CONFIG_GET(number/penis_max_inches_prefs)
var/new_length = input(user, "Penis length in inches:\n([min_D]-[max_D])", "Character Preference") as num|null
if(new_length)
features["cock_length"] = max(min( round(text2num(new_length)), COCK_SIZE_MAX),COCK_SIZE_MIN)
features["cock_length"] = CLAMP(round(new_length), min_D, max_D)
if("cock_shape")
var/new_shape
@@ -1939,8 +1945,13 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(new_shape)
features["cock_shape"] = new_shape
if("cock_visibility")
var/n_vis = input(user, "Penis Visibility", "Character Preference") as null|anything in CONFIG_GET(keyed_list/safe_visibility_toggles)
if(n_vis)
features["cock_visibility"] = n_vis
if("balls_color")
var/new_ballscolor = input(user, "Testicle Color:", "Character Preference") as color|null
var/new_ballscolor = input(user, "Testicles Color:", "Character Preference") as color|null
if(new_ballscolor)
var/temp_hsv = RGBtoHSV(new_ballscolor)
if(new_ballscolor == "#000000")
@@ -1950,31 +1961,13 @@ GLOBAL_LIST_EMPTY(preferences_datums)
else
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
if("balls_shape")
var/new_shape
new_shape = input(user, "Testicle Type:", "Character Preference") as null|anything in GLOB.balls_shapes_list
if(new_shape)
features["balls_shape"] = new_shape
if("egg_size")
var/new_size
var/list/egg_sizes = list(1,2,3)
new_size = input(user, "Egg Diameter(inches):", "Egg Size") as null|anything in egg_sizes
if(new_size)
features["eggsack_egg_size"] = new_size
if("egg_color")
var/new_egg_color = input(user, "Egg Color:", "Character Preference") as color|null
if(new_egg_color)
var/temp_hsv = RGBtoHSV(new_egg_color)
if(ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3])
features["eggsack_egg_color"] = sanitize_hexcolor(new_egg_color)
else
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
if("balls_visibility")
var/n_vis = input(user, "Testicles Visibility", "Character Preference") as null|anything in CONFIG_GET(keyed_list/safe_visibility_toggles)
if(n_vis)
features["balls_visibility"] = n_vis
if("breasts_size")
var/new_size
new_size = input(user, "Breast Size", "Character Preference") as null|anything in GLOB.breasts_size_list
var/new_size = input(user, "Breast Size", "Character Preference") as null|anything in CONFIG_GET(keyed_list/breasts_cups_prefs)
if(new_size)
features["breasts_size"] = new_size
@@ -1995,6 +1988,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
else
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
if("breasts_visibility")
var/n_vis = input(user, "Breasts Visibility", "Character Preference") as null|anything in CONFIG_GET(keyed_list/safe_visibility_toggles)
if(n_vis)
features["breasts_visibility"] = n_vis
if("vag_shape")
var/new_shape
new_shape = input(user, "Vagina Type", "Character Preference") as null|anything in GLOB.vagina_shapes_list
@@ -2012,6 +2010,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
else
to_chat(user,"<span class='danger'>Invalid color. Your color is not bright enough.</span>")
if("vag_visibility")
var/n_vis = input(user, "Vagina Visibility", "Character Preference") as null|anything in CONFIG_GET(keyed_list/safe_visibility_toggles)
if(n_vis)
features["vag_visibility"] = n_vis
if("ooccolor")
var/new_ooccolor = input(user, "Choose your OOC colour:", "Game Preference",ooccolor) as color|null
if(new_ooccolor)
@@ -2092,6 +2095,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(pickedPDASkin)
pda_skin = pickedPDASkin
if("hud_toggle_color")
var/new_toggle_color = input(user, "Choose your HUD toggle flash color:", "Game Preference",hud_toggle_color) as color|null
if(new_toggle_color)
hud_toggle_color = new_toggle_color
else
switch(href_list["preference"])
//CITADEL PREFERENCES EDIT - I can't figure out how to modularize these, so they have to go here. :c -Pooj
@@ -2105,14 +2113,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
features["has_balls"] = FALSE
if("has_balls")
features["has_balls"] = !features["has_balls"]
if("has_ovi")
features["has_ovi"] = !features["has_ovi"]
if("has_eggsack")
features["has_eggsack"] = !features["has_eggsack"]
if("balls_internal")
features["balls_internal"] = !features["balls_internal"]
if("eggsack_internal")
features["eggsack_internal"] = !features["eggsack_internal"]
if("has_breasts")
features["has_breasts"] = !features["has_breasts"]
if(features["has_breasts"] == FALSE)
@@ -2153,16 +2153,25 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(unlock_content)
toggles ^= MEMBER_PUBLIC
if("gender")
var/chosengender = input(user, "Select your character's gender.", "Gender Selection", gender) in list(MALE,FEMALE,"nonbinary","object")
var/chosengender = input(user, "Select your character's gender.", "Gender Selection", gender) as null|anything in list(MALE,FEMALE,"nonbinary","object")
if(!chosengender)
return
switch(chosengender)
if("nonbinary")
chosengender = PLURAL
features["body_model"] = pick(MALE, FEMALE)
if("object")
chosengender = NEUTER
features["body_model"] = MALE
else
features["body_model"] = chosengender
gender = chosengender
facial_hair_style = random_facial_hair_style(gender)
hair_style = random_hair_style(gender)
if("body_model")
features["body_model"] = features["body_model"] == MALE ? FEMALE : MALE
if("hotkeys")
hotkeys = !hotkeys
if(hotkeys)
@@ -2294,6 +2303,10 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("sprint_toggle")
sprint_toggle = !sprint_toggle
if("hud_toggle_flash")
hud_toggle_flash = !hud_toggle_flash
if("save")
save_preferences()
save_character()
@@ -2301,16 +2314,12 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("load")
load_preferences()
load_character()
if(parent && parent.prefs_vr)
attempt_vr(parent.prefs_vr,"load_vore","")
if("changeslot")
if(!load_character(text2num(href_list["num"])))
random_character()
real_name = random_unique_name(gender)
save_character()
if(parent && parent.prefs_vr)
attempt_vr(parent.prefs_vr,"load_vore","")
if("tab")
if (href_list["tab"])
@@ -2409,17 +2418,10 @@ GLOBAL_LIST_EMPTY(preferences_datums)
character.dna.nameless = character.nameless
character.dna.custom_species = character.custom_species
if("tail_lizard" in pref_species.default_features)
character.dna.species.mutant_bodyparts |= "tail_lizard"
if("mam_tail" in pref_species.default_features)
character.dna.species.mutant_bodyparts |= "mam_tail"
if("xenotail" in pref_species.default_features)
character.dna.species.mutant_bodyparts |= "xenotail"
if("meat_type" in pref_species.default_features)
if(pref_species.mutant_bodyparts["meat_type"])
character.type_of_meat = GLOB.meat_types[features["meat_type"]]
if(("legs" in character.dna.species.mutant_bodyparts) && (character.dna.features["legs"] == "Digitigrade" || character.dna.features["legs"] == "Avian"))
if(character.dna.species.mutant_bodyparts["legs"] && (character.dna.features["legs"] == "Digitigrade" || character.dna.features["legs"] == "Avian"))
pref_species.species_traits |= DIGITIGRADE
else
pref_species.species_traits -= DIGITIGRADE
@@ -2429,6 +2431,10 @@ GLOBAL_LIST_EMPTY(preferences_datums)
else
character.Digitigrade_Leg_Swap(TRUE)
character.give_genitals(TRUE) //character.update_genitals() is already called on genital.update_appearance()
SEND_SIGNAL(character, COMSIG_HUMAN_PREFS_COPIED_TO, src, icon_updates, roundstart_checks)
//let's be sure the character updates
if(icon_updates)
character.update_body()
+126 -22
View File
@@ -5,7 +5,7 @@
// You do not need to raise this if you are adding new values that have sane defaults.
// Only raise this value when changing the meaning/format/name/layout of an existing value
// where you would want the updater procs below to run
#define SAVEFILE_VERSION_MAX 25
#define SAVEFILE_VERSION_MAX 27
/*
SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn
@@ -115,6 +115,42 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
if(digi == "Digitigrade Legs")
WRITE_FILE(S["feature_lizard_legs"], "Digitigrade")
if(current_version < 26)
var/vr_path = "data/player_saves/[parent.ckey[1]]/[parent.ckey]/vore/character[default_slot].json"
if(fexists(vr_path))
var/list/json_from_file = json_decode(file2text(vr_path))
if(json_from_file)
digestable = json_from_file["digestable"]
devourable = json_from_file["devourable"]
feeding = json_from_file["feeding"]
lickable = json_from_file["lickable"]
belly_prefs = json_from_file["belly_prefs"]
vore_taste = json_from_file["vore_taste"]
for(var/V in all_quirks) // quirk migration
switch(V)
if("Acute hepatic pharmacokinesis")
DISABLE_BITFIELD(cit_toggles, PENIS_ENLARGEMENT)
DISABLE_BITFIELD(cit_toggles, BREAST_ENLARGEMENT)
ENABLE_BITFIELD(cit_toggles,FORCED_FEM)
ENABLE_BITFIELD(cit_toggles,FORCED_MASC)
all_quirks -= V
if("Crocin Immunity")
ENABLE_BITFIELD(cit_toggles,NO_APHRO)
all_quirks -= V
if("Buns of Steel")
ENABLE_BITFIELD(cit_toggles,NO_ASS_SLAP)
all_quirks -= V
if(features["meat_type"] == "Inesct")
features["meat_type"] = "Insect"
if(current_version < 27)
var/tennis
S["feature_balls_shape"] >> tennis
if(tennis == "Hidden")
features["balls_visibility"] = GEN_VISIBLE_NEVER
/datum/preferences/proc/load_path(ckey,filename="preferences.sav")
if(!ckey)
return
@@ -170,6 +206,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["auto_fit_viewport"] >> auto_fit_viewport
S["sprint_spacebar"] >> sprint_spacebar
S["sprint_toggle"] >> sprint_toggle
S["hud_toggle_flash"] >> hud_toggle_flash
S["hud_toggle_color"] >> hud_toggle_color
S["menuoptions"] >> menuoptions
S["enable_tips"] >> enable_tips
S["tip_delay"] >> tip_delay
@@ -209,6 +247,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
auto_fit_viewport = sanitize_integer(auto_fit_viewport, 0, 1, initial(auto_fit_viewport))
sprint_spacebar = sanitize_integer(sprint_spacebar, 0, 1, initial(sprint_spacebar))
sprint_toggle = sanitize_integer(sprint_toggle, 0, 1, initial(sprint_toggle))
hud_toggle_flash = sanitize_integer(hud_toggle_flash, 0, 1, initial(hud_toggle_flash))
hud_toggle_color = sanitize_hexcolor(hud_toggle_color, 6, 1, initial(hud_toggle_color))
ghost_form = sanitize_inlist(ghost_form, GLOB.ghost_forms, initial(ghost_form))
ghost_orbit = sanitize_inlist(ghost_orbit, GLOB.ghost_orbits, initial(ghost_orbit))
ghost_accs = sanitize_inlist(ghost_accs, GLOB.ghost_accs_options, GHOST_ACCS_DEFAULT_OPTION)
@@ -218,7 +258,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
pda_style = sanitize_inlist(pda_style, GLOB.pda_styles, initial(pda_style))
pda_color = sanitize_hexcolor(pda_color, 6, 1, initial(pda_color))
pda_skin = sanitize_inlist(pda_skin, GLOB.pda_reskins, PDA_SKIN_ALT)
screenshake = sanitize_integer(screenshake, 0, 800, initial(screenshake))
damagescreenshake = sanitize_integer(damagescreenshake, 0, 2, initial(damagescreenshake))
widescreenpref = sanitize_integer(widescreenpref, 0, 1, initial(widescreenpref))
@@ -271,6 +310,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["auto_fit_viewport"], auto_fit_viewport)
WRITE_FILE(S["sprint_spacebar"], sprint_spacebar)
WRITE_FILE(S["sprint_toggle"], sprint_toggle)
WRITE_FILE(S["hud_toggle_flash"], hud_toggle_flash)
WRITE_FILE(S["hud_toggle_color"], hud_toggle_color)
WRITE_FILE(S["menuoptions"], menuoptions)
WRITE_FILE(S["enable_tips"], enable_tips)
WRITE_FILE(S["tip_delay"], tip_delay)
@@ -345,6 +386,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["name_is_always_random"] >> be_random_name
S["body_is_always_random"] >> be_random_body
S["gender"] >> gender
S["body_model"] >> features["body_model"]
S["age"] >> age
S["hair_color"] >> hair_color
S["facial_hair_color"] >> facial_hair_color
@@ -396,7 +438,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
//Citadel code
S["feature_genitals_use_skintone"] >> features["genitals_use_skintone"]
S["feature_exhibitionist"] >> features["exhibitionist"]
S["feature_mcolor2"] >> features["mcolor2"]
S["feature_mcolor3"] >> features["mcolor3"]
S["feature_mam_body_markings"] >> features["mam_body_markings"]
@@ -416,23 +457,24 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["feature_cock_color"] >> features["cock_color"]
S["feature_cock_length"] >> features["cock_length"]
S["feature_cock_diameter"] >> features["cock_diameter"]
S["feature_has_sheath"] >> features["sheath_color"]
S["feature_cock_visibility"] >> features["cock_visibility"]
//balls features
S["feature_has_balls"] >> features["has_balls"]
S["feature_balls_color"] >> features["balls_color"]
S["feature_balls_size"] >> features["balls_size"]
S["feature_balls_shape"] >> features["balls_shape"]
S["feature_balls_sack_size"] >> features["balls_sack_size"]
S["feature_balls_visibility"] >> features["balls_visibility"]
//breasts features
S["feature_has_breasts"] >> features["has_breasts"]
S["feature_breasts_size"] >> features["breasts_size"]
S["feature_breasts_shape"] >> features["breasts_shape"]
S["feature_breasts_color"] >> features["breasts_color"]
S["feature_breasts_producing"] >> features["breasts_producing"]
S["feature_breasts_visibility"] >> features["breasts_visibility"]
//vagina features
S["feature_has_vag"] >> features["has_vag"]
S["feature_vag_shape"] >> features["vag_shape"]
S["feature_vag_color"] >> features["vag_color"]
S["feature_vag_visibility"] >> features["vag_visibility"]
//womb features
S["feature_has_womb"] >> features["has_womb"]
//flavor text
@@ -446,6 +488,12 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
else //We have no old flavortext, default to new
S["feature_flavor_text"] >> features["flavor_text"]
S["digestable"] >> digestable
S["devourable"] >> devourable
S["feeding"] >> feeding
S["vore_taste"] >> vore_taste
S["lickable"] >> lickable
S["belly_prefs"] >> belly_prefs
//try to fix any outdated data if necessary
if(needs_update >= 0)
@@ -455,6 +503,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
real_name = reject_bad_name(real_name)
gender = sanitize_gender(gender, TRUE, TRUE)
features["body_model"] = sanitize_gender(features["body_model"], FALSE, FALSE, gender == FEMALE ? FEMALE : MALE)
if(!real_name)
real_name = random_unique_name(gender)
custom_species = reject_bad_name(custom_species)
@@ -510,6 +559,39 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
features["insect_markings"] = sanitize_inlist(features["insect_markings"], GLOB.insect_markings_list, "None")
features["insect_wings"] = sanitize_inlist(features["insect_wings"], GLOB.insect_wings_list)
var/static/list/B_sizes
if(!B_sizes)
var/list/L = CONFIG_GET(keyed_list/breasts_cups_prefs)
B_sizes = L.Copy()
var/static/min_D
if(!min_D)
min_D = CONFIG_GET(number/penis_min_inches_prefs)
var/static/max_D
if(!max_D)
max_D = CONFIG_GET(number/penis_max_inches_prefs)
var/static/safe_visibilities
if(!safe_visibilities)
var/list/L = CONFIG_GET(keyed_list/safe_visibility_toggles)
safe_visibilities = L.Copy()
features["breasts_size"] = sanitize_inlist(features["breasts_size"], B_sizes, BREASTS_SIZE_DEF)
features["cock_length"] = sanitize_integer(features["cock_length"], min_D, max_D, COCK_SIZE_DEF)
features["breasts_shape"] = sanitize_inlist(features["breasts_shape"], GLOB.breasts_shapes_list, DEF_BREASTS_SHAPE)
features["cock_shape"] = sanitize_inlist(features["cock_shape"], GLOB.cock_shapes_list, DEF_COCK_SHAPE)
features["balls_shape"] = sanitize_inlist(features["balls_shape"], GLOB.balls_shapes_list, DEF_BALLS_SHAPE)
features["vag_shape"] = sanitize_inlist(features["vag_shape"], GLOB.vagina_shapes_list, DEF_VAGINA_SHAPE)
features["breasts_color"] = sanitize_hexcolor(features["breasts_color"], 3, FALSE, "FFF")
features["cock_color"] = sanitize_hexcolor(features["cock_color"], 3, FALSE, "FFF")
features["balls_color"] = sanitize_hexcolor(features["balls_color"], 3, FALSE, "FFF")
features["vag_color"] = sanitize_hexcolor(features["vag_color"], 3, FALSE, "FFF")
features["breasts_visibility"] = sanitize_inlist(features["breasts_visibility"], safe_visibilities, GEN_VISIBLE_NO_UNDIES)
features["cock_visibility"] = sanitize_inlist(features["cock_visibility"], safe_visibilities, GEN_VISIBLE_NO_UNDIES)
features["balls_visibility"] = sanitize_inlist(features["balls_visibility"], safe_visibilities, GEN_VISIBLE_NO_UNDIES)
features["vag_visibility"] = sanitize_inlist(features["vag_visibility"], safe_visibilities, GEN_VISIBLE_NO_UNDIES)
features["flavor_text"] = copytext(features["flavor_text"], 1, MAX_FLAVOR_LEN)
joblessrole = sanitize_integer(joblessrole, 1, 3, initial(joblessrole))
//Validate job prefs
for(var/j in job_preferences)
@@ -518,23 +600,13 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
all_quirks = SANITIZE_LIST(all_quirks)
for(var/V in all_quirks) // quirk migration
switch(V)
if("Acute hepatic pharmacokinesis")
DISABLE_BITFIELD(cit_toggles, PENIS_ENLARGEMENT)
DISABLE_BITFIELD(cit_toggles, BREAST_ENLARGEMENT)
ENABLE_BITFIELD(cit_toggles,FORCED_FEM)
ENABLE_BITFIELD(cit_toggles,FORCED_MASC)
all_quirks -= V
if("Crocin Immunity")
ENABLE_BITFIELD(cit_toggles,NO_APHRO)
all_quirks -= V
if("Buns of Steel")
ENABLE_BITFIELD(cit_toggles,NO_ASS_SLAP)
all_quirks -= V
lickable = sanitize_integer(lickable, FALSE, TRUE, initial(lickable))
devourable = sanitize_integer(devourable, FALSE, TRUE, initial(devourable))
digestable = sanitize_integer(digestable, FALSE, TRUE, initial(digestable))
feeding = sanitize_integer(feeding, FALSE, TRUE, initial(feeding))
vore_taste = copytext(vore_taste, 1, MAX_TASTE_LEN)
belly_prefs = SANITIZE_LIST(belly_prefs)
if(features["meat_type"] == "Inesct")
features["meat_type"] = "Insect"
cit_character_pref_load(S)
return 1
@@ -561,6 +633,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["name_is_always_random"] , be_random_name)
WRITE_FILE(S["body_is_always_random"] , be_random_body)
WRITE_FILE(S["gender"] , gender)
WRITE_FILE(S["body_model"] , features["body_model"])
WRITE_FILE(S["age"] , age)
WRITE_FILE(S["hair_color"] , hair_color)
WRITE_FILE(S["facial_hair_color"] , facial_hair_color)
@@ -596,6 +669,30 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["feature_insect_markings"] , features["insect_markings"])
WRITE_FILE(S["feature_meat"] , features["meat_type"])
WRITE_FILE(S["feature_has_cock"], features["has_cock"])
WRITE_FILE(S["feature_cock_shape"], features["cock_shape"])
WRITE_FILE(S["feature_cock_color"], features["cock_color"])
WRITE_FILE(S["feature_cock_length"], features["cock_length"])
WRITE_FILE(S["feature_cock_visibility"], features["cock_visibility"])
WRITE_FILE(S["feature_has_balls"], features["has_balls"])
WRITE_FILE(S["feature_balls_color"], features["balls_color"])
WRITE_FILE(S["feature_balls_size"], features["balls_size"])
WRITE_FILE(S["feature_balls_visibility"], features["balls_visibility"])
WRITE_FILE(S["feature_has_breasts"], features["has_breasts"])
WRITE_FILE(S["feature_breasts_size"], features["breasts_size"])
WRITE_FILE(S["feature_breasts_shape"], features["breasts_shape"])
WRITE_FILE(S["feature_breasts_color"], features["breasts_color"])
WRITE_FILE(S["feature_breasts_producing"], features["breasts_producing"])
WRITE_FILE(S["feature_breasts_visibility"], features["breasts_visibility"])
WRITE_FILE(S["feature_has_vag"], features["has_vag"])
WRITE_FILE(S["feature_vag_shape"], features["vag_shape"])
WRITE_FILE(S["feature_vag_color"], features["vag_color"])
WRITE_FILE(S["feature_vag_visibility"], features["vag_visibility"])
WRITE_FILE(S["feature_has_womb"], features["has_womb"])
//Custom names
for(var/custom_name_id in GLOB.preferences_custom_names)
@@ -613,6 +710,13 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
//Quirks
WRITE_FILE(S["all_quirks"] , all_quirks)
WRITE_FILE(S["digestable"] , digestable)
WRITE_FILE(S["devourable"] , devourable)
WRITE_FILE(S["feeding"] , feeding)
WRITE_FILE(S["vore_taste"] , vore_taste)
WRITE_FILE(S["lickable"] , lickable)
WRITE_FILE(S["belly_prefs"] , belly_prefs)
cit_character_pref_save(S)
return 1
+10
View File
@@ -0,0 +1,10 @@
/client/verb/show_station_minimap()
set category = "OOC"
set name = "Show Station Minimap"
set desc = "Shows a minimap of the currently loaded station map."
if(!CONFIG_GET(flag/minimaps_enabled))
to_chat(usr, "<span class='boldwarning'>Minimap generation is not enabled in the server's configuration.</span>")
return
SSminimaps.station_minimap.show(src)
+4 -5
View File
@@ -447,7 +447,7 @@
permeability_coefficient = 0.01
flags_cover = MASKCOVERSEYES | MASKCOVERSMOUTH
var/vchange = 1
var/voice_change = 1 ///This determines if the voice changer is on or off.
var/datum/action/item_action/chameleon/change/chameleon_action
@@ -470,15 +470,14 @@
chameleon_action.emp_randomise(INFINITY)
/obj/item/clothing/mask/chameleon/attack_self(mob/user)
vchange = !vchange
to_chat(user, "<span class='notice'>The voice changer is now [vchange ? "on" : "off"]!</span>")
voice_change = !voice_change
to_chat(user, "<span class='notice'>The voice changer is now [voice_change ? "on" : "off"]!</span>")
/obj/item/clothing/mask/chameleon/drone
//Same as the drone chameleon hat, undroppable and no protection
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
// Can drones use the voice changer part? Let's not find out.
vchange = 0
voice_change = 0
/obj/item/clothing/mask/chameleon/drone/Initialize()
. = ..()
+14 -1
View File
@@ -82,6 +82,7 @@
icon_state = "nvgmeson"
item_state = "nvgmeson"
darkness_view = 8
flash_protect = -2
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
glass_colour_type = /datum/client_colour/glass_colour/green
@@ -97,6 +98,11 @@
hitsound = 'sound/weapons/bladeslice.ogg'
sharpness = IS_SHARP
/obj/item/clothing/glasses/meson/eyepatch
name = "eyepatch mesons"
desc = "A meson system that connects directly to the optical nerve of the user, replacing the need for that useless eyeball."
icon_state = "mesonpatch"
/obj/item/clothing/glasses/science
name = "science goggles"
desc = "A pair of snazzy goggles used to protect against chemical spills. Fitted with an analyzer for scanning items and reagents."
@@ -114,10 +120,11 @@
/obj/item/clothing/glasses/night
name = "night vision goggles"
desc = "You can totally see in the dark now!"
desc = "You can totally see in the dark now! Just don't look too closely at bright lights. This lacks any flash correction."
icon_state = "night"
item_state = "glasses"
darkness_view = 8
flash_protect = -2
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
glass_colour_type = /datum/client_colour/glass_colour/green
@@ -125,6 +132,12 @@
name = "prescription night vision goggles"
desc = "NVGs but for those with nearsightedness."
vision_correction = 1
/obj/item/clothing/glasses/night/syndicate
name = "combat night vision goggles"
desc = "See everything, without fear."
flash_protect = 1
vision_correction = 1
/obj/item/clothing/glasses/science/suicide_act(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user] is tightening \the [src]'s straps around [user.p_their()] neck! It looks like [user.p_theyre()] trying to commit suicide!</span>")
+27 -7
View File
@@ -63,12 +63,19 @@
/obj/item/clothing/glasses/hud/health/night
name = "night vision health scanner HUD"
desc = "An advanced medical head-up display that allows doctors to find patients in complete darkness."
desc = "An advanced medical heads-up display that allows doctors to find patients in complete darkness."
icon_state = "healthhudnight"
item_state = "glasses"
darkness_view = 8
flash_protect = -2
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
glass_colour_type = /datum/client_colour/glass_colour/green
/obj/item/clothing/glasses/hud/health/night/syndicate
name = "combat night vision health scanner HUD"
desc = "An advanced shielded medical heads-up display that allows soldiers to approximate how much lead poisoning their allies have suffered in complete darkness."
flash_protect = 1
vision_correction = 1
/obj/item/clothing/glasses/hud/health/sunglasses
name = "medical HUDSunglasses"
@@ -83,6 +90,11 @@
name = "prescription medical HUDSunglasses"
vision_correction = 1
/obj/item/clothing/glasses/hud/health/eyepatch
name = "eyepatch medHUD"
desc = "A heads-up display that connects directly to the optical nerve of the user, replacing the need for that useless eyeball."
icon_state = "medpatch"
///////////////////
//Diagnostic Huds//
///////////////////
@@ -97,7 +109,8 @@
/obj/item/clothing/glasses/hud/diagnostic/sunglasses
name = "diagnostic HUDSunglasses"
desc = "Sunglasses with a diagnostic HUD."
icon_state = "sunhuddiagnostic"
icon_state = "sunhuddiag"
item_state = "glasses"
darkness_view = 1
flash_protect = 1
tint = 1
@@ -120,9 +133,15 @@
icon_state = "diagnostichudnight"
item_state = "glasses"
darkness_view = 8
flash_protect = -2
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
glass_colour_type = /datum/client_colour/glass_colour/green
/obj/item/clothing/glasses/hud/diagnostic/eyepatch
name = "eyepatch diagnostic HUD"
desc = "A heads-up display that connects directly to the optical nerve of the user, replacing the need for that useless eyeball."
icon_state = "diagpatch"
////////////
//Sec Huds//
////////////
@@ -165,11 +184,6 @@
return
chameleon_action.emp_randomise()
/obj/item/clothing/glasses/hud/security/sunglasses/eyepatch
name = "eyepatch HUD"
desc = "A heads-up display that connects directly to the optical nerve of the user, replacing the need for that useless eyeball."
icon_state = "hudpatch"
/obj/item/clothing/glasses/hud/security/sunglasses
name = "security HUDSunglasses"
desc = "Sunglasses with a security HUD."
@@ -179,6 +193,11 @@
tint = 1
glass_colour_type = /datum/client_colour/glass_colour/darkred
/obj/item/clothing/glasses/hud/security/sunglasses/eyepatch // why was this defined *before* the sunglasses it is a subtype of.
name = "eyepatch HUD"
desc = "A heads-up display that connects directly to the optical nerve of the user, replacing the need for that useless eyeball."
icon_state = "hudpatch"
/obj/item/clothing/glasses/hud/security/sunglasses/prescription
name = "prescription security HUDSunglasses"
vision_correction = 1
@@ -188,6 +207,7 @@
desc = "An advanced heads-up display which provides id data and vision in complete darkness."
icon_state = "securityhudnight"
darkness_view = 8
flash_protect = -2 //You either are flashproof or you can see in the dark, pick one.
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
glass_colour_type = /datum/client_colour/glass_colour/green
@@ -35,10 +35,10 @@
return
if(slot != SLOT_GLASSES)
return
RegisterSignal(user, COMSIG_COMBAT_TOGGLED, .proc/injectadrenaline)
RegisterSignal(user, COMSIG_LIVING_COMBAT_ENABLED, .proc/injectadrenaline)
/obj/item/clothing/glasses/phantomthief/syndicate/dropped(mob/user)
. = ..()
if(!istype(user))
return
UnregisterSignal(user, COMSIG_COMBAT_TOGGLED)
UnregisterSignal(user, COMSIG_LIVING_COMBAT_ENABLED)
+22 -2
View File
@@ -194,7 +194,7 @@
/obj/item/clothing/gloves/color/latex
name = "latex gloves"
desc = "Cheap sterile gloves made from latex."
desc = "Cheap sterile gloves made from latex. Transfers basic paramedical knowledge to the wearer via the use of nanochips."
icon_state = "latex"
item_state = "lgloves"
siemens_coefficient = 0.3
@@ -202,14 +202,34 @@
item_color="mime"
transfer_prints = TRUE
resistance_flags = NONE
var/carrytrait = TRAIT_QUICK_CARRY
/obj/item/clothing/gloves/color/latex/equipped(mob/user, slot)
..()
if(slot == SLOT_GLOVES)
ADD_TRAIT(user, carrytrait, CLOTHING_TRAIT)
/obj/item/clothing/gloves/color/latex/dropped(mob/user)
..()
REMOVE_TRAIT(user, carrytrait, CLOTHING_TRAIT)
/obj/item/clothing/gloves/color/latex/nitrile
name = "nitrile gloves"
desc = "Pricy sterile gloves that are stronger than latex."
desc = "Pricy sterile gloves that are stronger than latex. Transfers advanced paramedical knowledge to the wearer via the use of nanochips."
icon_state = "nitrile"
item_state = "nitrilegloves"
item_color = "cmo"
transfer_prints = FALSE
carrytrait = TRAIT_QUICKER_CARRY
/obj/item/clothing/gloves/color/latex/nitrile/infiltrator
name = "insidious combat gloves"
desc = "Specialized combat gloves for carrying people around. Transfers tactical kidnapping knowledge to the user via the use of nanochips."
icon_state = "infiltrator"
item_state = "infiltrator"
siemens_coefficient = 0
permeability_coefficient = 0.3
resistance_flags = FIRE_PROOF | ACID_PROOF
/obj/item/clothing/gloves/color/white
name = "white gloves"
+15
View File
@@ -256,6 +256,21 @@
strip_delay = 100
mutantrace_variation = STYLE_MUZZLE
/obj/item/clothing/head/helmet/infiltrator
name = "insidious helmet"
desc = "An insidious armored combat helmet signed with Syndicate insignia. The visor is coated with a resistant paste guaranteed to withstand bright flashes perfectly."
icon_state = "infiltrator"
item_state = "infiltrator"
armor = list("melee" = 40, "bullet" = 40, "laser" = 30, "energy" = 40, "bomb" = 70, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
resistance_flags = FIRE_PROOF | ACID_PROOF
flash_protect = 2
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH
dynamic_hair_suffix = ""
dynamic_fhair_suffix = ""
strip_delay = 80
mutantrace_variation = STYLE_MUZZLE
//LightToggle
/obj/item/clothing/head/helment/ComponentInitialize()
+4 -4
View File
@@ -9,10 +9,10 @@
var/flipped = 0
/obj/item/clothing/head/soft/dropped()
src.icon_state = "[item_color]soft"
src.flipped=0
..()
/obj/item/clothing/head/soft/dropped(mob/user)
icon_state = "[item_color]soft"
flipped = FALSE
return ..()
/obj/item/clothing/head/soft/verb/flipcap()
set category = "Object"

Some files were not shown because too many files have changed in this diff Show More