Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into Ghommie-cit387
This commit is contained in:
@@ -56,7 +56,7 @@
|
||||
if(used)
|
||||
to_chat(H, "You already used this contract!")
|
||||
return
|
||||
var/list/candidates = pollCandidatesForMob("Do you want to play as a wizard's [href_list["school"]] apprentice?", ROLE_WIZARD, null, ROLE_WIZARD, 150, src)
|
||||
var/list/candidates = pollCandidatesForMob("Do you want to play as a wizard's [href_list["school"]] apprentice?", ROLE_WIZARD, null, ROLE_WIZARD, 150, src, ignore_category = POLL_IGNORE_WIZARD)
|
||||
if(LAZYLEN(candidates))
|
||||
if(QDELETED(src))
|
||||
return
|
||||
@@ -182,6 +182,10 @@
|
||||
name = "syndicate medical teleporter"
|
||||
borg_to_spawn = "Medical"
|
||||
|
||||
/obj/item/antag_spawner/nuke_ops/borg_tele/saboteur
|
||||
name = "syndicate saboteur teleporter"
|
||||
borg_to_spawn = "Saboteur"
|
||||
|
||||
/obj/item/antag_spawner/nuke_ops/borg_tele/spawn_antag(client/C, turf/T, kind, datum/mind/user)
|
||||
var/mob/living/silicon/robot/R
|
||||
var/datum/antagonist/nukeop/creator_op = user.has_antag_datum(/datum/antagonist/nukeop,TRUE)
|
||||
@@ -191,6 +195,8 @@
|
||||
switch(borg_to_spawn)
|
||||
if("Medical")
|
||||
R = new /mob/living/silicon/robot/modules/syndicate/medical(T)
|
||||
if("Saboteur")
|
||||
R = new /mob/living/silicon/robot/modules/syndicate/saboteur(T)
|
||||
else
|
||||
R = new /mob/living/silicon/robot/modules/syndicate(T) //Assault borg by default
|
||||
|
||||
@@ -235,7 +241,7 @@
|
||||
return
|
||||
if(used)
|
||||
return
|
||||
var/list/candidates = pollCandidatesForMob("Do you want to play as a [initial(demon_type.name)]?", ROLE_ALIEN, null, ROLE_ALIEN, 50, src)
|
||||
var/list/candidates = pollCandidatesForMob("Do you want to play as a [initial(demon_type.name)]?", ROLE_ALIEN, null, ROLE_ALIEN, 50, src, ignore_category = POLL_IGNORE_DEMON)
|
||||
if(LAZYLEN(candidates))
|
||||
if(used || QDELETED(src))
|
||||
return
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
/obj/item/borg_chameleon
|
||||
name = "cyborg chameleon projector"
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "shield0"
|
||||
flags_1 = CONDUCT_1
|
||||
item_flags = NOBLUDGEON
|
||||
item_state = "electronic"
|
||||
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
var/friendlyName
|
||||
var/savedName
|
||||
var/active = FALSE
|
||||
var/activationCost = 300
|
||||
var/activationUpkeep = 50
|
||||
var/disguise = null
|
||||
var/disguise_icon_override = null
|
||||
var/disguise_pixel_offset = null
|
||||
var/mob/listeningTo
|
||||
var/static/list/signalCache = list( // list here all signals that should break the camouflage
|
||||
COMSIG_PARENT_ATTACKBY,
|
||||
COMSIG_ATOM_ATTACK_HAND,
|
||||
COMSIG_MOVABLE_IMPACT_ZONE,
|
||||
COMSIG_ATOM_BULLET_ACT,
|
||||
COMSIG_ATOM_EX_ACT,
|
||||
COMSIG_ATOM_FIRE_ACT,
|
||||
COMSIG_ATOM_EMP_ACT,
|
||||
)
|
||||
var/mob/living/silicon/robot/user // needed for process()
|
||||
var/animation_playing = FALSE
|
||||
|
||||
var/list/engymodels = list("Default", "Default - Treads", "Heavy", "Sleek", "Marina", "Can", "Spider", "Loader","Handy", "Pup Dozer", "Vale")
|
||||
|
||||
|
||||
/obj/item/borg_chameleon/Initialize()
|
||||
. = ..()
|
||||
friendlyName = pick(GLOB.ai_names)
|
||||
|
||||
/obj/item/borg_chameleon/Destroy()
|
||||
listeningTo = null
|
||||
return ..()
|
||||
|
||||
/obj/item/borg_chameleon/dropped(mob/user)
|
||||
. = ..()
|
||||
disrupt(user)
|
||||
|
||||
/obj/item/borg_chameleon/equipped(mob/user)
|
||||
. = ..()
|
||||
disrupt(user)
|
||||
|
||||
/obj/item/borg_chameleon/attack_self(mob/living/silicon/robot/user)
|
||||
if (user && user.cell && user.cell.charge > activationCost)
|
||||
if (isturf(user.loc))
|
||||
toggle(user)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You can't use [src] while inside something!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need at least [activationCost] charge in your cell to use [src]!</span>")
|
||||
|
||||
/obj/item/borg_chameleon/proc/toggle(mob/living/silicon/robot/user)
|
||||
if(active)
|
||||
playsound(src, 'sound/effects/pop.ogg', 100, TRUE, -6)
|
||||
to_chat(user, "<span class='notice'>You deactivate \the [src].</span>")
|
||||
deactivate(user)
|
||||
else
|
||||
if(animation_playing)
|
||||
to_chat(user, "<span class='notice'>\the [src] is recharging.</span>")
|
||||
return
|
||||
var/borg_icon = input(user, "Select an icon!", "Robot Icon", null) as null|anything in engymodels
|
||||
if(!borg_icon)
|
||||
return FALSE
|
||||
switch(borg_icon)
|
||||
if("Default")
|
||||
disguise = "engineer"
|
||||
disguise_icon_override = 'icons/mob/robots.dmi'
|
||||
if("Default - Treads")
|
||||
disguise = "engi-tread"
|
||||
disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
|
||||
if("Loader")
|
||||
disguise = "loaderborg"
|
||||
disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
|
||||
if("Handy")
|
||||
disguise = "handyeng"
|
||||
disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
|
||||
if("Sleek")
|
||||
disguise = "sleekeng"
|
||||
disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
|
||||
if("Can")
|
||||
disguise = "caneng"
|
||||
disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
|
||||
if("Marina")
|
||||
disguise = "marinaeng"
|
||||
disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
|
||||
if("Spider")
|
||||
disguise = "spidereng"
|
||||
disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
|
||||
if("Heavy")
|
||||
disguise = "heavyeng"
|
||||
disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
|
||||
if("Pup Dozer")
|
||||
disguise = "pupdozer"
|
||||
disguise_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
|
||||
disguise_pixel_offset = -16
|
||||
if("Vale")
|
||||
disguise = "valeeng"
|
||||
disguise_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
|
||||
disguise_pixel_offset = -16
|
||||
animation_playing = TRUE
|
||||
to_chat(user, "<span class='notice'>You activate \the [src].</span>")
|
||||
playsound(src, 'sound/effects/seedling_chargeup.ogg', 100, TRUE, -6)
|
||||
var/start = user.filters.len
|
||||
var/X,Y,rsq,i,f
|
||||
for(i=1, i<=7, ++i)
|
||||
do
|
||||
X = 60*rand() - 30
|
||||
Y = 60*rand() - 30
|
||||
rsq = X*X + Y*Y
|
||||
while(rsq<100 || rsq>900)
|
||||
user.filters += filter(type="wave", x=X, y=Y, size=rand()*2.5+0.5, offset=rand())
|
||||
for(i=1, i<=7, ++i)
|
||||
f = user.filters[start+i]
|
||||
animate(f, offset=f:offset, time=0, loop=3, flags=ANIMATION_PARALLEL)
|
||||
animate(offset=f:offset-1, time=rand()*20+10)
|
||||
if (do_after(user, 50, target=user) && user.cell.use(activationCost))
|
||||
playsound(src, 'sound/effects/bamf.ogg', 100, TRUE, -6)
|
||||
to_chat(user, "<span class='notice'>You are now disguised as the Nanotrasen engineering borg \"[friendlyName]\".</span>")
|
||||
activate(user)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The chameleon field fizzles.</span>")
|
||||
do_sparks(3, FALSE, user)
|
||||
for(i=1, i<=min(7, user.filters.len), ++i) // removing filters that are animating does nothing, we gotta stop the animations first
|
||||
f = user.filters[start+i]
|
||||
animate(f)
|
||||
user.filters = null
|
||||
animation_playing = FALSE
|
||||
|
||||
/obj/item/borg_chameleon/process()
|
||||
if (user)
|
||||
if (!user.cell || !user.cell.use(activationUpkeep))
|
||||
disrupt(user)
|
||||
else
|
||||
return PROCESS_KILL
|
||||
|
||||
/obj/item/borg_chameleon/proc/activate(mob/living/silicon/robot/user)
|
||||
START_PROCESSING(SSobj, src)
|
||||
src.user = user
|
||||
savedName = user.name
|
||||
user.name = friendlyName
|
||||
user.module.cyborg_base_icon = disguise
|
||||
user.module.cyborg_icon_override = disguise_icon_override
|
||||
user.module.cyborg_pixel_offset = disguise_pixel_offset
|
||||
user.bubble_icon = "robot"
|
||||
active = TRUE
|
||||
user.update_icons()
|
||||
|
||||
if(listeningTo == user)
|
||||
return
|
||||
if(listeningTo)
|
||||
UnregisterSignal(listeningTo, signalCache)
|
||||
RegisterSignal(user, signalCache, .proc/disrupt)
|
||||
listeningTo = user
|
||||
|
||||
/obj/item/borg_chameleon/proc/deactivate(mob/living/silicon/robot/user)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
if(listeningTo)
|
||||
UnregisterSignal(listeningTo, signalCache)
|
||||
listeningTo = null
|
||||
do_sparks(5, FALSE, user)
|
||||
user.name = savedName
|
||||
user.module.cyborg_base_icon = initial(user.module.cyborg_base_icon)
|
||||
user.module.cyborg_icon_override = 'icons/mob/robots.dmi'
|
||||
user.bubble_icon = "syndibot"
|
||||
active = FALSE
|
||||
user.update_icons()
|
||||
user.pixel_x = 0 //this solely exists because of dogborgs. I want anyone who ever reads this code later on to know this. Don't ask me why it's here, doesn't work above update_icons()
|
||||
src.user = user
|
||||
|
||||
/obj/item/borg_chameleon/proc/disrupt(mob/living/silicon/robot/user)
|
||||
if(active)
|
||||
to_chat(user, "<span class='danger'>Your chameleon field deactivates.</span>")
|
||||
deactivate(user)
|
||||
@@ -383,7 +383,9 @@
|
||||
if(!istype(user) || on_cooldown)
|
||||
return
|
||||
var/turf/T = get_turf(user)
|
||||
if(!T)
|
||||
var/area/A = get_area(user)
|
||||
if(!T || !A || A.noteleport)
|
||||
to_chat(user, "<span class='warning'>You play \the [src], yet no sound comes out of it... Looks like it won't work here.</span>")
|
||||
return
|
||||
on_cooldown = TRUE
|
||||
last_user = user
|
||||
|
||||
@@ -11,12 +11,18 @@
|
||||
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()
|
||||
..()
|
||||
no_coexistance_typecache = typecacheof(no_coexistance_typecache)
|
||||
|
||||
/datum/spellbook_entry/proc/IsAvailible() // For config prefs / gamemode restrictions - these are round applied
|
||||
if(istype(SSticker.mode,/datum/game_mode/dynamic))
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
if(dynamic_requirement > 0 && mode.threat_level < dynamic_requirement)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/datum/spellbook_entry/proc/CanBuy(mob/living/carbon/human/user,obj/item/spellbook/book) // Specific circumstances
|
||||
@@ -25,6 +31,10 @@
|
||||
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
|
||||
@@ -60,6 +70,10 @@
|
||||
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>")
|
||||
@@ -83,6 +97,10 @@
|
||||
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
|
||||
@@ -285,20 +303,8 @@
|
||||
name = "Staff of Change"
|
||||
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
|
||||
|
||||
/datum/spellbook_entry/item/staffchange/IsAvailible()
|
||||
if(istype(SSticker.mode,/datum/game_mode/dynamic))
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
if(mode.threat < CONFIG_GET(number/dynamic_staff_of_change_requirement))
|
||||
return 0
|
||||
|
||||
/datum/spellbook_entry/item/staffchange/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
|
||||
if(istype(SSticker.mode,/datum/game_mode/dynamic))
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
var/threat_spent = CONFIG_GET(number/dynamic_staff_of_change_cost)
|
||||
mode.spend_threat(threat_spent)
|
||||
mode.log_threat("Wizard spent [threat_spent] on staff of change.")
|
||||
return ..()
|
||||
dynamic_requirement = 60
|
||||
dynamic_cost = 20
|
||||
|
||||
/datum/spellbook_entry/item/staffanimation
|
||||
name = "Staff of Animation"
|
||||
@@ -383,20 +389,8 @@
|
||||
desc = "A magical contract binding an apprentice wizard to your service, using it will summon them to your side."
|
||||
item_path = /obj/item/antag_spawner/contract
|
||||
category = "Assistance"
|
||||
|
||||
/datum/spellbook_entry/item/contract/IsAvailible()
|
||||
if(istype(SSticker.mode,/datum/game_mode/dynamic))
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
if(mode.threat < CONFIG_GET(number/dynamic_apprentice_cost))
|
||||
return 0
|
||||
|
||||
/datum/spellbook_entry/item/contract/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
|
||||
if(istype(SSticker.mode,/datum/game_mode/dynamic))
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
var/threat_spent = CONFIG_GET(number/dynamic_apprentice_cost)
|
||||
mode.spend_threat(threat_spent)
|
||||
mode.log_threat("Wizard spent [threat_spent] on apprentice contract.")
|
||||
return ..()
|
||||
dynamic_requirement = 50
|
||||
dynamic_cost = 10
|
||||
|
||||
/datum/spellbook_entry/item/guardian
|
||||
name = "Guardian Deck"
|
||||
@@ -416,20 +410,11 @@
|
||||
item_path = /obj/item/antag_spawner/slaughter_demon
|
||||
limit = 3
|
||||
category = "Assistance"
|
||||
dynamic_requirement = 60
|
||||
|
||||
/datum/spellbook_entry/item/bloodbottle/IsAvailible()
|
||||
if(istype(SSticker.mode,/datum/game_mode/dynamic))
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
if(mode.threat < CONFIG_GET(keyed_list/dynamic_cost)["slaughter_demon"])
|
||||
return 0
|
||||
|
||||
/datum/spellbook_entry/item/bloodbottle/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
|
||||
if(istype(SSticker.mode,/datum/game_mode/dynamic))
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
var/threat_spent = CONFIG_GET(keyed_list/dynamic_cost)["slaughter_demon"]
|
||||
mode.spend_threat(threat_spent)
|
||||
mode.log_threat("Wizard spent [threat_spent] on slaughter demon.")
|
||||
return ..()
|
||||
/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"
|
||||
@@ -444,20 +429,11 @@
|
||||
cost = 1 //non-destructive; it's just a jape, sibling!
|
||||
limit = 3
|
||||
category = "Assistance"
|
||||
dynamic_requirement = 40
|
||||
|
||||
/datum/spellbook_entry/item/hugbottle/IsAvailible()
|
||||
if(istype(SSticker.mode,/datum/game_mode/dynamic))
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
if(mode.threat < round(CONFIG_GET(keyed_list/dynamic_cost)["slaughter_demon"]/3))
|
||||
return 0
|
||||
|
||||
/datum/spellbook_entry/item/hugbottle/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
|
||||
if(istype(SSticker.mode,/datum/game_mode/dynamic))
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
var/threat_spent = CONFIG_GET(keyed_list/dynamic_cost)["slaughter_demon"]/3
|
||||
mode.spend_threat(threat_spent)
|
||||
mode.log_threat("Wizard spent [threat_spent] on laughter demon.")
|
||||
return ..()
|
||||
/datum/spellbook_entry/item/hugbottle/New()
|
||||
..()
|
||||
dynamic_cost = CONFIG_GET(keyed_list/dynamic_cost)["slaughter_demon"]/3
|
||||
|
||||
/datum/spellbook_entry/item/mjolnir
|
||||
name = "Mjolnir"
|
||||
@@ -521,7 +497,7 @@
|
||||
if(!SSticker.mode)
|
||||
return FALSE
|
||||
else
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/datum/spellbook_entry/summon/ghosts/Buy(mob/living/carbon/human/user, obj/item/spellbook/book)
|
||||
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
|
||||
@@ -534,15 +510,13 @@
|
||||
/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()
|
||||
if(!SSticker.mode) // In case spellbook is placed on map
|
||||
return 0
|
||||
if(istype(SSticker.mode,/datum/game_mode/dynamic))
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
if(mode.threat < CONFIG_GET(number/dynamic_summon_guns_requirement))
|
||||
return 0
|
||||
return !CONFIG_GET(flag/no_summon_guns)
|
||||
return (!CONFIG_GET(flag/no_summon_guns) && ..())
|
||||
|
||||
/datum/spellbook_entry/summon/guns/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
|
||||
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
|
||||
@@ -552,7 +526,7 @@
|
||||
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 = CONFIG_GET(number/dynamic_summon_guns_cost)
|
||||
var/threat_spent = dynamic_cost
|
||||
mode.spend_threat(threat_spent)
|
||||
mode.log_threat("Wizard spent [threat_spent] on summon guns.")
|
||||
return 1
|
||||
@@ -560,15 +534,13 @@
|
||||
/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()
|
||||
if(!SSticker.mode) // In case spellbook is placed on map
|
||||
return 0
|
||||
if(istype(SSticker.mode,/datum/game_mode/dynamic))
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
if(mode.threat < CONFIG_GET(number/dynamic_summon_magic_requirement))
|
||||
return 0
|
||||
return !CONFIG_GET(flag/no_summon_magic)
|
||||
return (!CONFIG_GET(flag/no_summon_guns) && ..())
|
||||
|
||||
/datum/spellbook_entry/summon/magic/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
|
||||
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
|
||||
@@ -578,7 +550,7 @@
|
||||
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 = CONFIG_GET(number/dynamic_summon_magic_cost)
|
||||
var/threat_spent = dynamic_cost
|
||||
mode.spend_threat(threat_spent)
|
||||
mode.log_threat("Wizard spent [threat_spent] on summon magic.")
|
||||
return 1
|
||||
@@ -586,28 +558,26 @@
|
||||
/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
|
||||
|
||||
/datum/spellbook_entry/summon/events/IsAvailible()
|
||||
if(!SSticker.mode) // In case spellbook is placed on map
|
||||
return 0
|
||||
if(istype(SSticker.mode,/datum/game_mode/dynamic) && times == 0)
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
if(mode.threat < CONFIG_GET(number/dynamic_summon_events_requirement))
|
||||
return 0
|
||||
return !CONFIG_GET(flag/no_summon_events)
|
||||
return (!CONFIG_GET(flag/no_summon_events) && ..())
|
||||
|
||||
/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>")
|
||||
if(istype(SSticker.mode,/datum/game_mode/dynamic) && times == 0)
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
var/threat_spent = CONFIG_GET(number/dynamic_summon_events_cost)
|
||||
mode.spend_threat(threat_spent)
|
||||
mode.log_threat("Wizard spent [threat_spent] on summon events.")
|
||||
return 1
|
||||
|
||||
/datum/spellbook_entry/summon/events/GetInfo()
|
||||
|
||||
@@ -165,7 +165,7 @@
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/aimed/fireball(null))
|
||||
to_chat(owner, "<B>Your service has not gone unrewarded, however. Studying under [master.current.real_name], you have learned powerful, destructive spells. You are able to cast magic missile and fireball.")
|
||||
if(APPRENTICE_BLUESPACE)
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/area_teleport/teleport(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/turf_teleport/blink(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(null))
|
||||
to_chat(owner, "<B>Your service has not gone unrewarded, however. Studying under [master.current.real_name], you have learned reality bending mobility spells. You are able to cast teleport and ethereal jaunt.")
|
||||
if(APPRENTICE_HEALING)
|
||||
|
||||
@@ -199,7 +199,7 @@
|
||||
var/radiated_temperature = location.air.temperature*FIRE_SPREAD_RADIOSITY_SCALE
|
||||
for(var/t in location.atmos_adjacent_turfs)
|
||||
var/turf/open/T = t
|
||||
if(T.active_hotspot)
|
||||
if(!T.active_hotspot)
|
||||
T.hotspot_expose(radiated_temperature, CELL_VOLUME/4)
|
||||
|
||||
else
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
//used for mapping and for breathing while in walls (because that's a thing that needs to be accounted for...)
|
||||
//string parsed by /datum/gas/proc/copy_from_turf
|
||||
var/initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
|
||||
var/initial_gas_mix = OPENTURF_DEFAULT_ATMOS
|
||||
//approximation of MOLES_O2STANDARD and MOLES_N2STANDARD pending byond allowing constant expressions to be embedded in constant strings
|
||||
// If someone will place 0 of some gas there, SHIT WILL BREAK. Do not do that.
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@
|
||||
//liquid plasma!!!!!!//
|
||||
|
||||
/turf/open/floor/plasteel/dark/snowdin
|
||||
initial_gas_mix = "o2=22;n2=82;TEMP=180"
|
||||
initial_gas_mix = FROZEN_ATMOS
|
||||
planetary_atmos = 1
|
||||
temperature = 180
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
/obj/item/clothing/gloves/ComponentInitialize()
|
||||
. = ..()
|
||||
RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, /obj/item/clothing/gloves/clean_blood)
|
||||
RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, /atom.proc/clean_blood)
|
||||
|
||||
/obj/item/clothing/gloves/clean_blood(datum/source, strength)
|
||||
. = ..()
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
/obj/item/clothing/shoes/ComponentInitialize()
|
||||
. = ..()
|
||||
RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, /obj/item/clothing/shoes/clean_blood)
|
||||
RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, /atom.proc/clean_blood)
|
||||
|
||||
/obj/item/clothing/shoes/suicide_act(mob/living/carbon/user)
|
||||
if(rand(2)>1)
|
||||
|
||||
@@ -636,7 +636,7 @@
|
||||
|
||||
/obj/item/clothing/suit/assu_suit
|
||||
name = "DAB suit"
|
||||
desc = "A cheap replica of old SWAT armor. On its back, it is written: \"<i>Desperate Assistance Battle-force</i>\"."
|
||||
desc = "A cheap replica of old SWAT armor. On its back, it is written: \"<i>Desperate Assistance Battleforce</i>\"."
|
||||
icon_state = "assu_suit"
|
||||
item_state = "assu_suit"
|
||||
blood_overlay_type = "armor"
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
/datum/round_event_control/wizard
|
||||
wizardevent = 1
|
||||
var/can_be_midround_wizard = TRUE
|
||||
|
||||
// Checks if the event can be spawned. Used by event controller and "false alarm" event.
|
||||
// Admin-created events override this.
|
||||
@@ -54,6 +55,13 @@
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/round_event_control/wizard/canSpawnEvent(var/players_amt, var/gamemode)
|
||||
if(istype(SSticker.mode, /datum/game_mode/dynamic))
|
||||
var/var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
if (locate(/datum/dynamic_ruleset/midround/from_ghosts/wizard) in mode.executed_rules)
|
||||
return can_be_midround_wizard && ..()
|
||||
return ..()
|
||||
|
||||
/datum/round_event_control/proc/preRunEvent()
|
||||
if(!ispath(typepath, /datum/round_event))
|
||||
return EVENT_CANT_RUN
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
name = "Major Space Dust"
|
||||
typepath = /datum/round_event/meteor_wave/major_dust
|
||||
weight = 8
|
||||
gamemode_blacklist = list("dynamic")
|
||||
|
||||
/datum/round_event/meteor_wave/major_dust
|
||||
wave_name = "space dust"
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
min_players = 15
|
||||
max_occurrences = 3
|
||||
earliest_start = 25 MINUTES
|
||||
gamemode_blacklist = list("dynamic")
|
||||
|
||||
/datum/round_event/meteor_wave
|
||||
startWhen = 6
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
typepath = /datum/round_event/processor_overload
|
||||
weight = 15
|
||||
min_players = 20
|
||||
gamemode_blacklist = list("dynamic")
|
||||
|
||||
/datum/round_event/processor_overload
|
||||
announceWhen = 1
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
typepath = /datum/round_event/wizard/cursed_items
|
||||
max_occurrences = 3
|
||||
earliest_start = 0 MINUTES
|
||||
can_be_midround_wizard = FALSE
|
||||
|
||||
//Note about adding items to this: Because of how NODROP_1 works if an item spawned to the hands can also be equiped to a slot
|
||||
//it will be able to be put into that slot from the hand, but then get stuck there. To avoid this make a new subtype of any
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
typepath = /datum/round_event/wizard/deprevolt
|
||||
max_occurrences = 1
|
||||
earliest_start = 0 MINUTES
|
||||
can_be_midround_wizard = FALSE // not removing it completely yet
|
||||
|
||||
/datum/round_event/wizard/deprevolt/start()
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
typepath = /datum/round_event/wizard/race
|
||||
max_occurrences = 5
|
||||
earliest_start = 0 MINUTES
|
||||
can_be_midround_wizard = FALSE
|
||||
|
||||
/datum/round_event/wizard/race
|
||||
var/list/stored_name
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
typepath = /datum/round_event/wizard/shuffleloc
|
||||
max_occurrences = 5
|
||||
earliest_start = 0 MINUTES
|
||||
can_be_midround_wizard = FALSE // not removing it completely yet
|
||||
|
||||
/datum/round_event/wizard/shuffleloc/start()
|
||||
var/list/moblocs = list()
|
||||
@@ -43,6 +44,7 @@
|
||||
typepath = /datum/round_event/wizard/shufflenames
|
||||
max_occurrences = 5
|
||||
earliest_start = 0 MINUTES
|
||||
can_be_midround_wizard = FALSE // not removing it completely yet
|
||||
|
||||
/datum/round_event/wizard/shufflenames/start()
|
||||
var/list/mobnames = list()
|
||||
@@ -77,6 +79,7 @@
|
||||
typepath = /datum/round_event/wizard/shuffleminds
|
||||
max_occurrences = 3
|
||||
earliest_start = 0 MINUTES
|
||||
can_be_midround_wizard = FALSE // not removing it completely yet
|
||||
|
||||
/datum/round_event/wizard/shuffleminds/start()
|
||||
var/list/mobs = list()
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
typepath = /datum/round_event/wizard/summonguns
|
||||
max_occurrences = 1
|
||||
earliest_start = 0 MINUTES
|
||||
can_be_midround_wizard = FALSE // not removing it completely yet
|
||||
|
||||
/datum/round_event_control/wizard/summonguns/New()
|
||||
if(CONFIG_GET(flag/no_summon_guns))
|
||||
@@ -19,6 +20,7 @@
|
||||
typepath = /datum/round_event/wizard/summonmagic
|
||||
max_occurrences = 1
|
||||
earliest_start = 0 MINUTES
|
||||
can_be_midround_wizard = FALSE // not removing it completely yet
|
||||
|
||||
/datum/round_event_control/wizard/summonmagic/New()
|
||||
if(CONFIG_GET(flag/no_summon_magic))
|
||||
|
||||
@@ -546,3 +546,10 @@ Since Ramadan is an entire month that lasts 29.5 days on average, the start and
|
||||
|
||||
/datum/holiday/easter/getStationPrefix()
|
||||
return pick("Fluffy","Bunny","Easter","Egg")
|
||||
|
||||
//Random citadel thing for halloween species
|
||||
/proc/force_enable_halloween_species()
|
||||
var/list/oldlist = SSevents.holidays
|
||||
SSevents.holidays = list(HALLOWEEN = new /datum/holiday/halloween)
|
||||
generate_selectable_species(FALSE)
|
||||
SSevents.holidays = oldlist
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
/turf/open/floor/holofloor/plating/burnmix
|
||||
name = "burn-mix floor"
|
||||
initial_gas_mix = "o2=2500;plasma=5000;TEMP=370"
|
||||
initial_gas_mix = BURNMIX_ATMOS
|
||||
|
||||
/turf/open/floor/holofloor/grass
|
||||
gender = PLURAL
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
max_matter = 600 //Bigger container and faster speeds due to being specialized and stationary.
|
||||
no_ammo_message = "<span class='warning'>Internal matter exhausted. Please add additional materials.</span>"
|
||||
delay_mod = 0.5
|
||||
adjacency_check = FALSE
|
||||
upgrade = TRUE
|
||||
var/obj/machinery/computer/camera_advanced/base_construction/console
|
||||
|
||||
@@ -207,19 +206,14 @@
|
||||
to_chat(owner, "Build mode is now [buildmode].")
|
||||
|
||||
/datum/action/innate/aux_base/airlock_type
|
||||
name = "Change Airlock Settings"
|
||||
name = "Select Airlock Type"
|
||||
button_icon_state = "airlock_select"
|
||||
|
||||
/datum/action/innate/aux_base/airlock_type/Activate()
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/mode = alert("Modify Type or Access?", "Airlock Settings", "Type", "Access", "None")
|
||||
switch(mode)
|
||||
if("Type")
|
||||
B.RCD.change_airlock_setting(usr)
|
||||
if("Access")
|
||||
B.RCD.change_airlock_access(usr)
|
||||
B.RCD.change_airlock_access(usr)
|
||||
|
||||
|
||||
/datum/action/innate/aux_base/window_type
|
||||
|
||||
@@ -473,10 +473,7 @@
|
||||
var/free_space = 0
|
||||
for(var/list/category in list(GLOB.command_positions) + list(GLOB.supply_positions) + list(GLOB.engineering_positions) + list(GLOB.nonhuman_positions - "pAI") + list(GLOB.civilian_positions) + list(GLOB.medical_positions) + list(GLOB.science_positions) + list(GLOB.security_positions))
|
||||
var/cat_color = "fff" //random default
|
||||
if(SSjob.name_occupations && SSjob.name_occupations[category[1]])
|
||||
cat_color = SSjob.name_occupations[category[1]].selection_color //use the color of the first job in the category (the department head) as the category color
|
||||
else
|
||||
cat_color = SSjob.occupations[category[1]].selection_color
|
||||
cat_color = SSjob.name_occupations[category[1]].selection_color //use the color of the first job in the category (the department head) as the category color
|
||||
dat += "<fieldset style='width: 185px; border: 2px solid [cat_color]; display: inline'>"
|
||||
dat += "<legend align='center' style='color: [cat_color]'>[SSjob.name_occupations[category[1]].exp_type_department]</legend>"
|
||||
|
||||
|
||||
@@ -307,7 +307,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
if(stat == DEAD)
|
||||
ghostize(1)
|
||||
else
|
||||
var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst alive you won't be able to re-enter this round [penalty ? "or play ghost roles [penalty != CANT_REENTER_ROUND ? "until the round is over" : "for the next [DisplayTimeText(penalty)]"]" : ""]! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body")
|
||||
var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst alive you won't be able to re-enter this round [penalty ? "or play ghost roles [penalty == CANT_REENTER_ROUND ? "until the round is over" : "for the next [DisplayTimeText(penalty)]"]" : ""]! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body")
|
||||
if(response != "Ghost")
|
||||
return //didn't want to ghost after-all
|
||||
if(istype(loc, /obj/machinery/cryopod))
|
||||
@@ -332,7 +332,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
if(penalty + world.realtime - SSshuttle.realtimeofstart > SSshuttle.auto_call + SSshuttle.emergencyCallTime + SSshuttle.emergencyDockTime + SSshuttle.emergencyEscapeTime)
|
||||
penalty = CANT_REENTER_ROUND
|
||||
|
||||
var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst alive you won't be able to re-enter this round [penalty ? "or play ghost roles [penalty != CANT_REENTER_ROUND ? "until the round is over" : "for the next [DisplayTimeText(penalty)]"]" : ""]! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body")
|
||||
var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst alive you won't be able to re-enter this round [penalty ? "or play ghost roles [penalty == CANT_REENTER_ROUND ? "until the round is over" : "for the next [DisplayTimeText(penalty)]"]" : ""]! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body")
|
||||
if(response != "Ghost")
|
||||
return
|
||||
ghostize(0, penalize = TRUE)
|
||||
@@ -630,8 +630,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
set name = "Possess!"
|
||||
set desc= "Take over the body of a mindless creature!"
|
||||
|
||||
if(reenter_round_timeout > world.realtime)
|
||||
to_chat(src, "<span class='warning'>You are unable to re-enter the round yet. Your ghost role blacklist will expire in [DisplayTimeText(reenter_round_timeout - world.realtime)].</span>")
|
||||
if(!can_reenter_round())
|
||||
return FALSE
|
||||
|
||||
var/list/possessible = list()
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
var/datum/dna/stored/stored_dna // dna var for brain. Used to store dna, brain dna is not considered like actual dna, brain.has_dna() returns FALSE.
|
||||
stat = DEAD //we start dead by default
|
||||
see_invisible = SEE_INVISIBLE_LIVING
|
||||
possible_a_intents = list(INTENT_HELP, INTENT_HARM) //for mechas
|
||||
speech_span = SPAN_ROBOT
|
||||
|
||||
/mob/living/brain/Initialize()
|
||||
@@ -72,10 +73,9 @@
|
||||
|
||||
/mob/living/brain/ClickOn(atom/A, params)
|
||||
..()
|
||||
if(istype(loc, /obj/item/mmi))
|
||||
var/obj/item/mmi/MMI = loc
|
||||
var/obj/mecha/M = MMI.mecha
|
||||
if((src == MMI.brainmob) && istype(M))
|
||||
if(container)
|
||||
var/obj/mecha/M = container.mecha
|
||||
if(istype(M))
|
||||
return M.click_action(A,src,params)
|
||||
|
||||
/mob/living/brain/forceMove(atom/destination)
|
||||
@@ -90,3 +90,16 @@
|
||||
doMove(destination)
|
||||
else
|
||||
CRASH("Brainmob without a container [src] attempted to move to [destination].")
|
||||
|
||||
/mob/living/brain/update_mouse_pointer()
|
||||
if (!client)
|
||||
return
|
||||
client.mouse_pointer_icon = initial(client.mouse_pointer_icon)
|
||||
if(!container)
|
||||
return
|
||||
if (container.mecha)
|
||||
var/obj/mecha/M = container.mecha
|
||||
if(M.mouse_pointer)
|
||||
client.mouse_pointer_icon = M.mouse_pointer
|
||||
if (client && ranged_ability && ranged_ability.ranged_mousepointer)
|
||||
client.mouse_pointer_icon = ranged_ability.ranged_mousepointer
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
adjustStaminaLoss(damage_amount, forced = forced)
|
||||
//citadel code
|
||||
if(AROUSAL)
|
||||
adjustArousalLoss(damage_amount, forced = forced)
|
||||
adjustArousalLoss(damage_amount)
|
||||
return TRUE
|
||||
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
if(CONFIG_GET(flag/disable_stambuffer))
|
||||
togglesprint()
|
||||
|
||||
RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, /mob/living/carbon/human/clean_blood)
|
||||
RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, /atom.proc/clean_blood)
|
||||
|
||||
|
||||
/mob/living/carbon/human/ComponentInitialize()
|
||||
|
||||
@@ -118,11 +118,14 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
..()
|
||||
|
||||
|
||||
/proc/generate_selectable_species()
|
||||
/proc/generate_selectable_species(clear = FALSE)
|
||||
if(clear)
|
||||
GLOB.roundstart_races = list()
|
||||
GLOB.roundstart_race_names = list()
|
||||
for(var/I in subtypesof(/datum/species))
|
||||
var/datum/species/S = new I
|
||||
if(S.check_roundstart_eligible())
|
||||
GLOB.roundstart_races += S.id
|
||||
GLOB.roundstart_races |= S.id
|
||||
GLOB.roundstart_race_names["[S.name]"] = S.id
|
||||
qdel(S)
|
||||
if(!GLOB.roundstart_races.len)
|
||||
|
||||
@@ -336,7 +336,7 @@ There are several things that need to be remembered:
|
||||
if(!t_state)
|
||||
t_state = s_store.icon_state
|
||||
overlays_standing[SUIT_STORE_LAYER] = mutable_appearance(((s_store.alternate_worn_icon) ? s_store.alternate_worn_icon : 'icons/mob/belt_mirror.dmi'), t_state, -SUIT_STORE_LAYER)
|
||||
var/mutable_appearance/s_store_overlay = overlays_standing[SUIT_LAYER]
|
||||
var/mutable_appearance/s_store_overlay = overlays_standing[SUIT_STORE_LAYER]
|
||||
if(OFFSET_S_STORE in dna.species.offset_features)
|
||||
s_store_overlay.pixel_x += dna.species.offset_features[OFFSET_S_STORE][1]
|
||||
s_store_overlay.pixel_y += dna.species.offset_features[OFFSET_S_STORE][2]
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
var/datum/gas_mixture/breath
|
||||
|
||||
if(!getorganslot(ORGAN_SLOT_BREATHING_TUBE))
|
||||
if(health <= HEALTH_THRESHOLD_FULLCRIT || (pulledby && pulledby.grab_state >= GRAB_KILL) || !lungs || lungs.organ_flags & ORGAN_FAILING)
|
||||
if(health <= HEALTH_THRESHOLD_FULLCRIT || (pulledby && pulledby.grab_state >= GRAB_KILL) || (lungs && lungs.organ_flags & ORGAN_FAILING))
|
||||
losebreath++ //You can't breath at all when in critical or when being choked, so you're going to miss a breath
|
||||
|
||||
else if(health <= crit_threshold)
|
||||
|
||||
@@ -58,7 +58,10 @@
|
||||
var/canholo = TRUE
|
||||
var/obj/item/card/id/access_card = null
|
||||
var/chassis = "repairbot"
|
||||
var/list/possible_chassis = list("cat" = TRUE, "mouse" = TRUE, "monkey" = TRUE, "corgi" = FALSE, "fox" = FALSE, "repairbot" = TRUE, "rabbit" = TRUE) //assoc value is whether it can be picked up.
|
||||
var/list/possible_chassis = list("cat" = TRUE, "mouse" = TRUE, "monkey" = TRUE, "corgi" = FALSE,
|
||||
"fox" = FALSE, "repairbot" = TRUE, "rabbit" = TRUE, "borgi" = FALSE ,
|
||||
"parrot" = FALSE, "bear" = FALSE , "mushroom" = FALSE, "crow" = FALSE ,
|
||||
"fairy" = FALSE , "spiderbot" = FALSE) //assoc value is whether it can be picked up.
|
||||
var/static/item_head_icon = 'icons/mob/pai_item_head.dmi'
|
||||
var/static/item_lh_icon = 'icons/mob/pai_item_lh.dmi'
|
||||
var/static/item_rh_icon = 'icons/mob/pai_item_rh.dmi'
|
||||
|
||||
@@ -917,6 +917,17 @@
|
||||
<i>Help the operatives secure the disk at all costs!</i></b>"
|
||||
set_module = /obj/item/robot_module/syndicate_medical
|
||||
|
||||
/mob/living/silicon/robot/modules/syndicate/saboteur
|
||||
icon_state = "synd_engi"
|
||||
playstyle_string = "<span class='big bold'>You are a Syndicate saboteur cyborg!</span><br>\
|
||||
<b>You are armed with robust engineering tools to aid you in your mission: help the operatives secure the nuclear authentication disk. \
|
||||
Your destination tagger will allow you to stealthily traverse the disposal network across the station \
|
||||
Your welder will allow you to repair the operatives' exosuits, but also yourself and your fellow cyborgs \
|
||||
Your cyborg chameleon projector allows you to assume the appearance and registered name of a Nanotrasen engineering borg, and undertake covert actions on the station \
|
||||
Be aware that almost any physical contact or incidental damage will break your camouflage \
|
||||
<i>Help the operatives secure the disk at all costs!</i></b>"
|
||||
set_module = /obj/item/robot_module/saboteur
|
||||
|
||||
/mob/living/silicon/robot/proc/notify_ai(notifytype, oldname, newname)
|
||||
if(!connected_ai)
|
||||
return
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
var/list/ride_offset_y = list("north" = 4, "south" = 4, "east" = 3, "west" = 3)
|
||||
var/ride_allow_incapacitated = FALSE
|
||||
var/allow_riding = TRUE
|
||||
var/canDispose = FALSE // Whether the borg can stuff itself into disposal
|
||||
|
||||
var/sleeper_overlay
|
||||
var/icon/cyborg_icon_override
|
||||
@@ -989,6 +990,47 @@
|
||||
can_be_pushed = FALSE
|
||||
hat_offset = 3
|
||||
|
||||
/obj/item/robot_module/saboteur
|
||||
name = "Syndicate Saboteur"
|
||||
basic_modules = list(
|
||||
/obj/item/assembly/flash/cyborg,
|
||||
/obj/item/borg/sight/thermal,
|
||||
/obj/item/construction/rcd/borg/syndicate,
|
||||
/obj/item/pipe_dispenser,
|
||||
/obj/item/restraints/handcuffs/cable/zipties,
|
||||
/obj/item/extinguisher,
|
||||
/obj/item/weldingtool/largetank/cyborg,
|
||||
/obj/item/screwdriver/nuke,
|
||||
/obj/item/wrench/cyborg,
|
||||
/obj/item/crowbar/cyborg,
|
||||
/obj/item/wirecutters/cyborg,
|
||||
/obj/item/multitool/cyborg,
|
||||
/obj/item/storage/part_replacer/cyborg,
|
||||
/obj/item/holosign_creator/atmos,
|
||||
/obj/item/weapon/gripper,
|
||||
/obj/item/lightreplacer/cyborg,
|
||||
/obj/item/stack/sheet/metal/cyborg,
|
||||
/obj/item/stack/sheet/glass/cyborg,
|
||||
/obj/item/stack/sheet/rglass/cyborg,
|
||||
/obj/item/stack/rods/cyborg,
|
||||
/obj/item/stack/tile/plasteel/cyborg,
|
||||
/obj/item/destTagger/borg,
|
||||
/obj/item/stack/cable_coil/cyborg,
|
||||
/obj/item/pinpointer/syndicate_cyborg,
|
||||
/obj/item/borg_chameleon,
|
||||
)
|
||||
|
||||
ratvar_modules = list(
|
||||
/obj/item/clockwork/slab/cyborg/engineer,
|
||||
/obj/item/clockwork/replica_fabricator/cyborg)
|
||||
|
||||
cyborg_base_icon = "synd_engi"
|
||||
moduleselect_icon = "malf"
|
||||
can_be_pushed = FALSE
|
||||
magpulsing = TRUE
|
||||
hat_offset = -4
|
||||
canDispose = TRUE
|
||||
|
||||
/datum/robot_energy_storage
|
||||
var/name = "Generic energy storage"
|
||||
var/max_energy = 30000
|
||||
|
||||
@@ -440,7 +440,7 @@
|
||||
var/reagent_id = null
|
||||
|
||||
if(emagged == 2) //Emagged! Time to poison everybody.
|
||||
reagent_id = "toxin"
|
||||
reagent_id = HAS_TRAIT(C, TRAIT_TOXINLOVER)? "charcoal" : "toxin"
|
||||
|
||||
else
|
||||
if(treat_virus)
|
||||
|
||||
@@ -64,6 +64,8 @@
|
||||
/obj/item/gun/energy/laser/cyborg
|
||||
can_charge = FALSE
|
||||
desc = "An energy-based laser gun that draws power from the cyborg's internal energy cell directly. So this is what freedom looks like?"
|
||||
icon = 'icons/obj/items_cyborg.dmi'
|
||||
icon_state = "laser_cyborg"
|
||||
selfcharge = EGUN_SELFCHARGE_BORG
|
||||
cell_type = /obj/item/stock_parts/cell/secborg
|
||||
charge_delay = 3
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
/obj/item/gun/energy/e_gun/advtaser/cyborg
|
||||
name = "cyborg taser"
|
||||
desc = "An integrated hybrid taser that draws directly from a cyborg's power cell. The one contains a limiter to prevent the cyborg's power cell from overheating."
|
||||
icon = 'icons/obj/items_cyborg.dmi'
|
||||
icon_state = "taser"
|
||||
can_flashlight = FALSE
|
||||
can_charge = FALSE
|
||||
selfcharge = EGUN_SELFCHARGE_BORG
|
||||
@@ -48,6 +50,8 @@
|
||||
/obj/item/gun/energy/disabler/cyborg
|
||||
name = "cyborg disabler"
|
||||
desc = "An integrated disabler that draws from a cyborg's power cell. This one contains a limiter to prevent the cyborg's power cell from overheating."
|
||||
icon = 'icons/obj/items_cyborg.dmi'
|
||||
icon_state = "taser"
|
||||
can_charge = FALSE
|
||||
ammo_type = list(/obj/item/ammo_casing/energy/disabler/secborg)
|
||||
selfcharge = EGUN_SELFCHARGE_BORG
|
||||
|
||||
@@ -69,12 +69,12 @@
|
||||
/obj/item/projectile/beam/disabler
|
||||
name = "disabler beam"
|
||||
icon_state = "omnilaser"
|
||||
damage = 24 // Citadel change for balance from 36
|
||||
damage = 28 // Citadel change for balance from 36
|
||||
damage_type = STAMINA
|
||||
flag = "energy"
|
||||
hitsound = 'sound/weapons/tap.ogg'
|
||||
eyeblur = 0
|
||||
speed = 0.7
|
||||
speed = 0.6
|
||||
impact_effect_type = /obj/effect/temp_visual/impact_effect/blue_laser
|
||||
light_color = LIGHT_COLOR_BLUE
|
||||
tracer_type = /obj/effect/projectile/tracer/disabler
|
||||
|
||||
@@ -153,6 +153,7 @@
|
||||
var/robot = pick(200;/mob/living/silicon/robot,
|
||||
/mob/living/silicon/robot/modules/syndicate,
|
||||
/mob/living/silicon/robot/modules/syndicate/medical,
|
||||
/mob/living/silicon/robot/modules/syndicate/saboteur,
|
||||
200;/mob/living/simple_animal/drone/polymorphed)
|
||||
new_mob = new robot(M.loc)
|
||||
if(issilicon(new_mob))
|
||||
|
||||
@@ -515,6 +515,7 @@
|
||||
///Stronger kind of lube. Applies TURF_WET_SUPERLUBE.
|
||||
/datum/reagent/lube/superlube
|
||||
name = "Super Duper Lube"
|
||||
id = "superlube"
|
||||
description = "This \[REDACTED\] has been outlawed after the incident on \[DATA EXPUNGED\]."
|
||||
lube_kind = TURF_WET_SUPERLUBE
|
||||
|
||||
|
||||
@@ -230,7 +230,7 @@
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
icon_state = "clownflower"
|
||||
volume = 30
|
||||
list_reagents = list(/datum/reagent/lube/superlube = 30)
|
||||
list_reagents = list("superlube" = 30)
|
||||
|
||||
/obj/item/reagent_containers/spray/waterflower/cyborg
|
||||
reagent_flags = NONE
|
||||
|
||||
@@ -132,7 +132,12 @@
|
||||
|
||||
/obj/machinery/disposal/proc/can_stuff_mob_in(mob/living/target, mob/living/user, pushing = FALSE)
|
||||
if(!pushing && !iscarbon(user) && !user.ventcrawler) //only carbon and ventcrawlers can climb into disposal by themselves.
|
||||
return FALSE
|
||||
if (iscyborg(user))
|
||||
var/mob/living/silicon/robot/borg = user
|
||||
if (!borg.module || !borg.module.canDispose)
|
||||
return
|
||||
else
|
||||
return FALSE
|
||||
if(!isturf(user.loc)) //No magically doing it from inside closets
|
||||
return FALSE
|
||||
if(target.buckled || target.has_buckled_mobs())
|
||||
|
||||
@@ -52,6 +52,10 @@
|
||||
if(istype(AM, /obj/item/smallDelivery) && !hasmob)
|
||||
var/obj/item/smallDelivery/T = AM
|
||||
src.destinationTag = T.sortTag
|
||||
else if(istype(AM, /mob/living/silicon/robot))
|
||||
var/obj/item/destTagger/borg/tagger = locate() in AM
|
||||
if (tagger)
|
||||
src.destinationTag = tagger.currTag
|
||||
|
||||
|
||||
// start the movement process
|
||||
|
||||
@@ -147,6 +147,7 @@
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "cargotagger"
|
||||
var/currTag = 0 //Destinations are stored in code\globalvars\lists\flavor_misc.dm
|
||||
var/locked_destination = FALSE //if true, users can't open the destination tag window to prevent changing the tagger's current destination
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
item_state = "electronic"
|
||||
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
|
||||
@@ -154,6 +155,10 @@
|
||||
flags_1 = CONDUCT_1
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
|
||||
/obj/item/destTagger/borg
|
||||
name = "cyborg destination tagger"
|
||||
desc = "Used to fool the disposal mail network into thinking that you're a harmless parcel. Does actually work as a regular destination tagger as well."
|
||||
|
||||
/obj/item/destTagger/suicide_act(mob/living/user)
|
||||
user.visible_message("<span class='suicide'>[user] begins tagging [user.p_their()] final destination! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
if (islizard(user))
|
||||
@@ -179,8 +184,9 @@
|
||||
onclose(user, "destTagScreen")
|
||||
|
||||
/obj/item/destTagger/attack_self(mob/user)
|
||||
openwindow(user)
|
||||
return
|
||||
if(!locked_destination)
|
||||
openwindow(user)
|
||||
return
|
||||
|
||||
/obj/item/destTagger/Topic(href, href_list)
|
||||
add_fingerprint(usr)
|
||||
|
||||
@@ -41,6 +41,14 @@
|
||||
category = list ("Misc. Machinery")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SERVICE
|
||||
|
||||
/datum/design/board/ayyplantgenes
|
||||
name = "Machine Design (Alien Plant DNA Manipulator Board)"
|
||||
desc = "The circuit board for an advanced plant DNA manipulator, utilizing alien technologies."
|
||||
id = "ayyplantgenes"
|
||||
build_path = /obj/item/circuitboard/machine/plantgenes/vault
|
||||
category = list ("Misc. Machinery")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SERVICE
|
||||
|
||||
/datum/design/board/deepfryer
|
||||
name = "Machine Design (Deep Fryer)"
|
||||
desc = "The circuit board for a Deep Fryer."
|
||||
|
||||
@@ -84,8 +84,9 @@
|
||||
investigate_log("[key_name(user)] built [amount] of [path] at [src]([type]).", INVESTIGATE_RESEARCH)
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] has built [amount] of [path] at a [src]([type]).")
|
||||
for(var/i in 1 to amount)
|
||||
var/obj/item/I = new path(get_turf(src))
|
||||
if(efficient_with(I.type))
|
||||
var/obj/O = new path(get_turf(src))
|
||||
if(efficient_with(O.type) && isitem(O))
|
||||
var/obj/item/I = O
|
||||
I.materials = matlist.Copy()
|
||||
SSblackbox.record_feedback("nested tally", "item_printed", amount, list("[type]", "[path]"))
|
||||
|
||||
|
||||
@@ -616,7 +616,7 @@
|
||||
/datum/techweb_node/botany
|
||||
id = "botany"
|
||||
display_name = "Botanical Engineering"
|
||||
description = "Botanical tools"
|
||||
description = "Botanical tools."
|
||||
prereq_ids = list("adv_engi", "biotech")
|
||||
design_ids = list("diskplantgene", "portaseeder", "plantgenes", "flora_gun", "hydro_tray", "biogenerator", "seed_extractor")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750)
|
||||
@@ -1047,14 +1047,14 @@
|
||||
display_name = "Alien Biological Tools"
|
||||
description = "Advanced biological tools."
|
||||
prereq_ids = list("alientech", "advance_surgerytools")
|
||||
design_ids = list("alien_scalpel", "alien_hemostat", "alien_retractor", "alien_saw", "alien_drill", "alien_cautery")
|
||||
design_ids = list("alien_scalpel", "alien_hemostat", "alien_retractor", "alien_saw", "alien_drill", "alien_cautery", "ayyplantgenes")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
|
||||
export_price = 10000
|
||||
|
||||
/datum/techweb_node/alien_engi
|
||||
id = "alien_engi"
|
||||
display_name = "Alien Engineering"
|
||||
description = "Alien engineering tools"
|
||||
description = "Alien engineering tools."
|
||||
prereq_ids = list("alientech", "exp_tools")
|
||||
design_ids = list("alien_wrench", "alien_wirecutters", "alien_screwdriver", "alien_crowbar", "alien_welder", "alien_multitool")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
|
||||
|
||||
@@ -24,12 +24,9 @@ Self-sustaining extracts:
|
||||
A.icon = icon
|
||||
A.icon_state = icon_state
|
||||
A.color = color
|
||||
A.name = "self-sustaining " + colour + " extract"
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
/obj/item/autoslime/Initialize()
|
||||
name = "self-sustaining " + extract.name
|
||||
return ..()
|
||||
|
||||
/obj/item/autoslime/attack_self(mob/user)
|
||||
var/reagentselect = input(user, "Choose the reagent the extract will produce.", "Self-sustaining Reaction") as null|anything in extract.activate_reagents
|
||||
var/amount = 5
|
||||
|
||||
@@ -20,8 +20,11 @@
|
||||
after_cast(targets)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/area_teleport/before_cast(list/targets)
|
||||
var/A = null
|
||||
|
||||
var/area/U = get_area(usr)
|
||||
if(U.noteleport && !istype(U, /area/wizard_station)) // Wizard den special check for those complaining about being unable to tele on station.
|
||||
to_chat(usr, "<span class='warning'>Unseen forces prevent you from casting this spell in this area</span>")
|
||||
return
|
||||
var/A
|
||||
if(!randomise_selection)
|
||||
A = input("Area to teleport to", "Teleport", A) as null|anything in GLOB.teleportlocs
|
||||
else
|
||||
@@ -53,12 +56,13 @@
|
||||
if(target && target.buckled)
|
||||
target.buckled.unbuckle_mob(target, force=1)
|
||||
|
||||
var/forcecheck = istype(get_area(target), /area/wizard_station)
|
||||
var/list/tempL = L
|
||||
var/attempt = null
|
||||
var/success = 0
|
||||
while(tempL.len)
|
||||
attempt = pick(tempL)
|
||||
do_teleport(target, attempt, channel = TELEPORT_CHANNEL_MAGIC)
|
||||
do_teleport(target, attempt, channel = TELEPORT_CHANNEL_MAGIC, forced = forcecheck)
|
||||
if(get_turf(target) == attempt)
|
||||
success = 1
|
||||
break
|
||||
@@ -66,7 +70,7 @@
|
||||
tempL.Remove(attempt)
|
||||
|
||||
if(!success)
|
||||
do_teleport(target, L, forceMove = TRUE, channel = TELEPORT_CHANNEL_MAGIC)
|
||||
do_teleport(target, L, forceMove = TRUE, channel = TELEPORT_CHANNEL_MAGIC, forced = forcecheck)
|
||||
playsound(get_turf(user), sound2, 50,1)
|
||||
|
||||
return
|
||||
|
||||
@@ -354,7 +354,7 @@
|
||||
if("legs" in S.default_features)
|
||||
if(body_zone == BODY_ZONE_L_LEG || body_zone == BODY_ZONE_R_LEG)
|
||||
if(DIGITIGRADE in S.species_traits)
|
||||
digitigrade_type = lowertext(H.dna.features.["legs"])
|
||||
digitigrade_type = lowertext(H.dna.features["legs"])
|
||||
else
|
||||
digitigrade_type = null
|
||||
|
||||
@@ -363,9 +363,9 @@
|
||||
Smark = GLOB.mam_body_markings_list[H.dna.features["mam_body_markings"]]
|
||||
if(Smark)
|
||||
body_markings_icon = Smark.icon
|
||||
if(H.dna.features.["mam_body_markings"] != "None")
|
||||
body_markings = lowertext(H.dna.features.["mam_body_markings"])
|
||||
aux_marking = lowertext(H.dna.features.["mam_body_markings"])
|
||||
if(H.dna.features["mam_body_markings"] != "None")
|
||||
body_markings = lowertext(H.dna.features["mam_body_markings"])
|
||||
aux_marking = lowertext(H.dna.features["mam_body_markings"])
|
||||
else
|
||||
body_markings = "plain"
|
||||
aux_marking = "plain"
|
||||
|
||||
@@ -110,4 +110,4 @@
|
||||
requires_tech = TRUE
|
||||
replaced_by = null
|
||||
|
||||
#undef EXPDIS_FAIL_MSG
|
||||
#undef BASE_HUMAN_REWARD
|
||||
@@ -212,7 +212,6 @@ obj/item/organ/heart/cybernetic/upgraded/on_life()
|
||||
ramount += regen_amount
|
||||
|
||||
/obj/item/organ/heart/cybernetic/upgraded/proc/used_dose()
|
||||
. = ..()
|
||||
addtimer(VARSET_CALLBACK(src, dose_available, TRUE), 5 MINUTES)
|
||||
ramount = 0
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
#define STANDARD_ORGAN_THRESHOLD 100
|
||||
#define STANDARD_ORGAN_HEALING 0.001
|
||||
|
||||
/obj/item/organ
|
||||
name = "organ"
|
||||
icon = 'icons/obj/surgery.dmi'
|
||||
|
||||
@@ -1123,6 +1123,16 @@ datum/uplink_item/stealthy_weapons/taeclowndo_shoes
|
||||
cost = 35
|
||||
restricted = TRUE
|
||||
|
||||
/datum/uplink_item/support/reinforcement/saboteur_borg
|
||||
name = "Syndicate Saboteur Cyborg"
|
||||
desc = "A streamlined engineering cyborg, equipped with covert modules. Also incapable of leaving the welder in the shuttle. \
|
||||
Aside from regular Engineering equipment, it comes with a special destination tagger that lets it traverse disposals networks. \
|
||||
Its chameleon projector lets it disguise itself as a Nanotrasen cyborg, on top it has thermal vision and a pinpointer."
|
||||
item = /obj/item/antag_spawner/nuke_ops/borg_tele/saboteur
|
||||
refundable = TRUE
|
||||
cost = 35
|
||||
restricted = TRUE
|
||||
|
||||
/datum/uplink_item/support/gygax
|
||||
name = "Dark Gygax Exosuit"
|
||||
desc = "A lightweight exosuit, painted in a dark scheme. Its speed and equipment selection make it excellent \
|
||||
@@ -1794,6 +1804,21 @@ datum/uplink_item/stealthy_weapons/taeclowndo_shoes
|
||||
cost = 4
|
||||
restricted_roles = list("Cook", "Botanist", "Clown", "Mime")
|
||||
|
||||
/datum/uplink_item/role_restricted/strange_seeds
|
||||
name = "Pack of strange seeds"
|
||||
desc = "Mysterious seeds as strange as their name implies. Spooky."
|
||||
item = /obj/item/seeds/random
|
||||
cost = 2
|
||||
restricted_roles = list("Botanist")
|
||||
illegal_tech = FALSE
|
||||
|
||||
/datum/uplink_item/role_restricted/strange_seeds_10pack
|
||||
name = "Pack of strange seeds x10"
|
||||
desc = "Mysterious seeds as strange as their name implies. Spooky. These come in bulk"
|
||||
item = /obj/item/storage/box/strange_seeds_10pack
|
||||
cost = 20
|
||||
restricted_roles = list("Botanist")
|
||||
|
||||
/datum/uplink_item/role_restricted/ez_clean_bundle
|
||||
name = "EZ Clean Grenade Bundle"
|
||||
desc = "A box with three cleaner grenades using the trademark Waffle Co. formula. Serves as a cleaner and causes acid damage to anyone standing nearby. \
|
||||
|
||||
Reference in New Issue
Block a user