diff --git a/baystation12.dme b/baystation12.dme
index eeeb9223bc4..20a5dec8478 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -140,7 +140,6 @@
#include "code\datums\diseases\advance\symptoms\sneeze.dm"
#include "code\datums\diseases\advance\symptoms\stimulant.dm"
#include "code\datums\diseases\advance\symptoms\symptoms.dm"
-#include "code\datums\diseases\advance\symptoms\visionloss.dm"
#include "code\datums\diseases\advance\symptoms\vitiligo.dm"
#include "code\datums\diseases\advance\symptoms\voice_change.dm"
#include "code\datums\diseases\advance\symptoms\vomit.dm"
@@ -148,12 +147,13 @@
#include "code\datums\diseases\advance\symptoms\youth.dm"
#include "code\datums\helper_datums\construction_datum.dm"
#include "code\datums\helper_datums\events.dm"
-#include "code\datums\helper_datums\getrev.dm"
#include "code\datums\helper_datums\global_iterator.dm"
#include "code\datums\helper_datums\teleport.dm"
#include "code\datums\helper_datums\topic_input.dm"
#include "code\datums\spells\area_teleport.dm"
+#include "code\datums\spells\charge.dm"
#include "code\datums\spells\conjure.dm"
+#include "code\datums\spells\construct_spells.dm"
#include "code\datums\spells\dumbfire.dm"
#include "code\datums\spells\emplosion.dm"
#include "code\datums\spells\ethereal_jaunt.dm"
@@ -250,14 +250,18 @@
#include "code\game\gamemodes\revolution\revolution.dm"
#include "code\game\gamemodes\revolution\rp_revolution.dm"
#include "code\game\gamemodes\traitor\traitor.dm"
+#include "code\game\gamemodes\vampire\hud.dm"
+#include "code\game\gamemodes\vampire\vampire.dm"
+#include "code\game\gamemodes\vampire\vampire_powers.dm"
#include "code\game\gamemodes\vox\vox.dm"
#include "code\game\gamemodes\vox\heist\heist.dm"
#include "code\game\gamemodes\vox\trade\trade.dm"
+#include "code\game\gamemodes\wizard\artefact.dm"
#include "code\game\gamemodes\wizard\rightandwrong.dm"
#include "code\game\gamemodes\wizard\soulstone.dm"
#include "code\game\gamemodes\wizard\spellbook.dm"
-#include "code\game\gamemodes\wizard\veilrender.dm"
#include "code\game\gamemodes\wizard\wizard.dm"
+#include "code\game\gamemodes\xenos\xenos.dm"
#include "code\game\jobs\access.dm"
#include "code\game\jobs\job_controller.dm"
#include "code\game\jobs\job_objective.dm"
@@ -290,9 +294,11 @@
#include "code\game\machinery\cloning.dm"
#include "code\game\machinery\constructable_frame.dm"
#include "code\game\machinery\cryo.dm"
+#include "code\game\machinery\cryopod.dm"
#include "code\game\machinery\deployable.dm"
#include "code\game\machinery\door_control.dm"
#include "code\game\machinery\doppler_array.dm"
+#include "code\game\machinery\drying_rack.dm"
#include "code\game\machinery\flasher.dm"
#include "code\game\machinery\floodlight.dm"
#include "code\game\machinery\Freezer.dm"
@@ -384,6 +390,7 @@
#include "code\game\machinery\computer\syndicate_specops_shuttle.dm"
#include "code\game\machinery\computer\telescience.dm"
#include "code\game\machinery\computer\vox_shuttle.dm"
+#include "code\game\machinery\computer\xenos_shuttle.dm"
#include "code\game\machinery\doors\airlock.dm"
#include "code\game\machinery\doors\airlock_electronics.dm"
#include "code\game\machinery\doors\alarmlock.dm"
@@ -565,6 +572,7 @@
#include "code\game\objects\items\weapons\teleportation.dm"
#include "code\game\objects\items\weapons\tools.dm"
#include "code\game\objects\items\weapons\twohanded.dm"
+#include "code\game\objects\items\weapons\vending_items.dm"
#include "code\game\objects\items\weapons\weaponry.dm"
#include "code\game\objects\items\weapons\wires.dm"
#include "code\game\objects\items\weapons\grenades\bananade.dm"
@@ -649,6 +657,7 @@
#include "code\game\objects\structures\crates_lockers\closets\job_closets.dm"
#include "code\game\objects\structures\crates_lockers\closets\l3closet.dm"
#include "code\game\objects\structures\crates_lockers\closets\malfunction.dm"
+#include "code\game\objects\structures\crates_lockers\closets\statue.dm"
#include "code\game\objects\structures\crates_lockers\closets\syndicate.dm"
#include "code\game\objects\structures\crates_lockers\closets\utility_closets.dm"
#include "code\game\objects\structures\crates_lockers\closets\wardrobe.dm"
@@ -666,6 +675,7 @@
#include "code\game\objects\structures\stool_bed_chair_nest\bed.dm"
#include "code\game\objects\structures\stool_bed_chair_nest\chairs.dm"
#include "code\game\objects\structures\stool_bed_chair_nest\stools.dm"
+#include "code\game\structure\structure.dm"
#include "code\game\turfs\simulated.dm"
#include "code\game\turfs\turf.dm"
#include "code\game\turfs\unsimulated.dm"
@@ -768,7 +778,6 @@
#include "code\modules\clothing\gloves\color.dm"
#include "code\modules\clothing\gloves\miscellaneous.dm"
#include "code\modules\clothing\gloves\ninja.dm"
-#include "code\modules\clothing\gloves\stungloves.dm"
#include "code\modules\clothing\head\collectable.dm"
#include "code\modules\clothing\head\hardhat.dm"
#include "code\modules\clothing\head\helmet.dm"
@@ -812,6 +821,7 @@
#include "code\modules\customitems\item_defines.dm"
#include "code\modules\customitems\item_spawning.dm"
#include "code\modules\customitems\definitions\base.dm"
+#include "code\modules\destilery\main.dm"
#include "code\modules\DetectiveWork\detective_work.dm"
#include "code\modules\DetectiveWork\evidence.dm"
#include "code\modules\DetectiveWork\footprints_and_rag.dm"
@@ -827,6 +837,7 @@
#include "code\modules\economy\Job_Departments.dm"
#include "code\modules\economy\TradeDestinations.dm"
#include "code\modules\events\blob.dm"
+#include "code\modules\events\borers.dm"
#include "code\modules\events\carp_migration.dm"
#include "code\modules\events\comms_blackout.dm"
#include "code\modules\events\communications_blackout.dm"
@@ -848,6 +859,7 @@
#include "code\modules\events\rogue_drones.dm"
#include "code\modules\events\space_ninja.dm"
#include "code\modules\events\spontaneous_appendicitis.dm"
+#include "code\modules\events\tear.dm"
#include "code\modules\events\viral_infection.dm"
#include "code\modules\events\viral_outbreak.dm"
#include "code\modules\events\wallrot.dm"
@@ -886,6 +898,7 @@
#include "code\modules\maps\reader.dm"
#include "code\modules\maps\swapmaps.dm"
#include "code\modules\maps\writer.dm"
+#include "code\modules\mining\abandonedcrates.dm"
#include "code\modules\mining\machine_input_output_plates.dm"
#include "code\modules\mining\machine_processing.dm"
#include "code\modules\mining\machine_stacking.dm"
@@ -901,6 +914,7 @@
#include "code\modules\mining\laborcamp\laborminerals.dm"
#include "code\modules\mining\laborcamp\laborshuttle.dm"
#include "code\modules\mining\laborcamp\laborstacker.dm"
+#include "code\modules\mob\abilities.dm"
#include "code\modules\mob\death.dm"
#include "code\modules\mob\emote.dm"
#include "code\modules\mob\inventory.dm"
@@ -1056,6 +1070,7 @@
#include "code\modules\mob\living\simple_animal\constructs.dm"
#include "code\modules\mob\living\simple_animal\corpse.dm"
#include "code\modules\mob\living\simple_animal\parrot.dm"
+#include "code\modules\mob\living\simple_animal\powers.dm"
#include "code\modules\mob\living\simple_animal\shade.dm"
#include "code\modules\mob\living\simple_animal\simple_animal.dm"
#include "code\modules\mob\living\simple_animal\tribbles.dm"
@@ -1072,6 +1087,7 @@
#include "code\modules\mob\living\simple_animal\friendly\spiderbot.dm"
#include "code\modules\mob\living\simple_animal\friendly\tomato.dm"
#include "code\modules\mob\living\simple_animal\hostile\alien.dm"
+#include "code\modules\mob\living\simple_animal\hostile\bat.dm"
#include "code\modules\mob\living\simple_animal\hostile\bear.dm"
#include "code\modules\mob\living\simple_animal\hostile\carp.dm"
#include "code\modules\mob\living\simple_animal\hostile\creature.dm"
@@ -1105,6 +1121,7 @@
#include "code\modules\organs\organ_external.dm"
#include "code\modules\organs\organ_internal.dm"
#include "code\modules\organs\pain.dm"
+#include "code\modules\organs\skeleton.dm"
#include "code\modules\organs\wound.dm"
#include "code\modules\paperwork\clipboard.dm"
#include "code\modules\paperwork\filingcabinet.dm"
@@ -1158,6 +1175,7 @@
#include "code\modules\projectiles\ammunition\bullets.dm"
#include "code\modules\projectiles\ammunition\magazines.dm"
#include "code\modules\projectiles\guns\energy.dm"
+#include "code\modules\projectiles\guns\magic.dm"
#include "code\modules\projectiles\guns\projectile.dm"
#include "code\modules\projectiles\guns\energy\laser.dm"
#include "code\modules\projectiles\guns\energy\nuclear.dm"
@@ -1165,6 +1183,8 @@
#include "code\modules\projectiles\guns\energy\special.dm"
#include "code\modules\projectiles\guns\energy\stun.dm"
#include "code\modules\projectiles\guns\energy\temperature.dm"
+#include "code\modules\projectiles\guns\magic\staff.dm"
+#include "code\modules\projectiles\guns\magic\wand.dm"
#include "code\modules\projectiles\guns\projectile\automatic.dm"
#include "code\modules\projectiles\guns\projectile\bow.dm"
#include "code\modules\projectiles\guns\projectile\launcher.dm"
@@ -1178,6 +1198,7 @@
#include "code\modules\projectiles\projectile\change.dm"
#include "code\modules\projectiles\projectile\energy.dm"
#include "code\modules\projectiles\projectile\force.dm"
+#include "code\modules\projectiles\projectile\magic.dm"
#include "code\modules\projectiles\projectile\special.dm"
#include "code\modules\reagents\Chemistry-Colours.dm"
#include "code\modules\reagents\Chemistry-Holder.dm"
@@ -1334,6 +1355,7 @@
#include "code\WorkInProgress\autopsy.dm"
#include "code\WorkInProgress\buildmode.dm"
#include "code\WorkInProgress\explosion_particles.dm"
+#include "code\WorkInProgress\fireworks.dm"
#include "code\WorkInProgress\periodic_news.dm"
#include "code\WorkInProgress\Apples\artifacts.dm"
#include "code\WorkInProgress\Cael_Aislinn\Jungle\falsewall.dm"
@@ -1371,6 +1393,7 @@
#include "code\WorkInProgress\Cael_Aislinn\Supermatter\LaserComputer.dm"
#include "code\WorkInProgress\Cael_Aislinn\Supermatter\ZeroPointLaser.dm"
#include "code\WorkInProgress\Chinsky\ashtray.dm"
+#include "code\WorkInProgress\Chinsky\guestpass.dm"
#include "code\WorkInProgress\Cib\MedicalSideEffects.dm"
#include "code\WorkInProgress\computer3\bios.dm"
#include "code\WorkInProgress\computer3\buildandrepair.dm"
@@ -1409,6 +1432,7 @@
#include "code\WorkInProgress\SkyMarshal\officer_stuff.dm"
#include "code\WorkInProgress\SkyMarshal\Ultralight_procs.dm"
#include "code\WorkInProgress\Yinadele\Supermatter.dm"
+#include "code\WorkInProgress\ZomgPonies\Colored-windows.dm"
#include "code\WorkInProgress\ZomgPonies\karma.dm"
#include "code\WorkInProgress\ZomgPonies\clothing\civilian.dm"
#include "code\WorkInProgress\ZomgPonies\mobs\pony.dm"
diff --git a/code/WorkInProgress/Chinsky/ashtray.dm b/code/WorkInProgress/Chinsky/ashtray.dm
index ab3a6362515..5ec88ac8bdf 100644
--- a/code/WorkInProgress/Chinsky/ashtray.dm
+++ b/code/WorkInProgress/Chinsky/ashtray.dm
@@ -17,35 +17,34 @@
/obj/item/ashtray/attackby(obj/item/weapon/W as obj, mob/user as mob)
if (health < 1)
return
- if (istype(W,/obj/item/clothing/mask/cigarette) || istype(W, /obj/item/weapon/match))
- if(user)
- if (contents.len >= max_butts)
- user << "This ashtray is full."
- return
- user.u_equip(W)
- W.loc = src
- if ((user.client && user.s_active != src))
- user.client.screen -= W
+ if (istype(W,/obj/item/weapon/cigbutt) || istype(W,/obj/item/clothing/mask/cigarette) || istype(W, /obj/item/weapon/match))
+ if (contents.len >= max_butts)
+ user << "This ashtray is full."
+ return
+ user.u_equip(W)
+ W.loc = src
+
+ if (istype(W,/obj/item/clothing/mask/cigarette))
var/obj/item/clothing/mask/cigarette/cig = W
if (cig.lit == 1)
src.visible_message("[user] crushes [cig] in [src], putting it out.")
- cig.smoketime = 0
+ processing_objects.Remove(cig)
+ var/obj/item/butt = new cig.type_butt(src)
+ cig.transfer_fingerprints_to(butt)
+ del(cig)
else if (cig.lit == 0)
- if(istype(cig, /obj/item/weapon/match))
- user << "You place [cig] in [src] without even lighting it. Why would you do that?"
- else
- user << "You place [cig] in [src] without even smoking it. Why would you do that?"
- else if (cig.lit == -1)
- src.visible_message("[user] places [cig] in [src].")
- user.update_inv_l_hand()
- user.update_inv_r_hand()
- add_fingerprint(user)
- if (contents.len == max_butts)
- icon_state = icon_full
- desc = empty_desc + " It's stuffed full."
- else if (contents.len > max_butts/2)
- icon_state = icon_half
- desc = empty_desc + " It's half-filled."
+ user << "You place [cig] in [src] without even smoking it. Why would you do that?"
+
+ src.visible_message("[user] places [W] in [src].")
+ user.update_inv_l_hand()
+ user.update_inv_r_hand()
+ add_fingerprint(user)
+ if (contents.len == max_butts)
+ icon_state = icon_full
+ desc = empty_desc + " It's stuffed full."
+ else if (contents.len > max_butts/2)
+ icon_state = icon_half
+ desc = empty_desc + " It's half-filled."
else
health = max(0,health - W.force)
user << "You hit [src] with [W]."
@@ -62,7 +61,6 @@
if (contents.len)
src.visible_message("\red [src] slams into [hit_atom] spilling its contents!")
for (var/obj/item/clothing/mask/cigarette/O in contents)
- contents -= O
O.loc = src.loc
icon_state = icon_empty
return ..()
@@ -70,7 +68,6 @@
/obj/item/ashtray/proc/die()
src.visible_message("\red [src] shatters spilling its contents!")
for (var/obj/item/clothing/mask/cigarette/O in contents)
- contents -= O
O.loc = src.loc
icon_state = icon_broken
diff --git a/code/WorkInProgress/Chinsky/guestpass.dm b/code/WorkInProgress/Chinsky/guestpass.dm
new file mode 100644
index 00000000000..1e2f3b8a957
--- /dev/null
+++ b/code/WorkInProgress/Chinsky/guestpass.dm
@@ -0,0 +1,182 @@
+/////////////////////////////////////////////
+//Guest pass ////////////////////////////////
+/////////////////////////////////////////////
+/obj/item/weapon/card/id/guest
+ name = "guest pass"
+ desc = "Allows temporary access to station areas."
+ icon_state = "guest"
+
+ var/temp_access = list() //to prevent agent cards stealing access as permanent
+ var/expiration_time = 0
+ var/reason = "NOT SPECIFIED"
+
+/obj/item/weapon/card/id/guest/GetAccess()
+ if (world.time > expiration_time)
+ return access
+ else
+ return temp_access
+
+/obj/item/weapon/card/id/guest/examine()
+ ..()
+ if (world.time < expiration_time)
+ usr << "\blue This pass expires at [worldtime2text(expiration_time)]."
+ else
+ usr << "\red It expired at [worldtime2text(expiration_time)]."
+
+/obj/item/weapon/card/id/guest/read()
+ if (world.time > expiration_time)
+ usr << "This pass expired at [worldtime2text(expiration_time)]."
+ else
+ usr << "This pass expires at [worldtime2text(expiration_time)]."
+
+ usr << "It grants access to following areas:"
+ for (var/A in temp_access)
+ usr << "[get_access_desc(A)]."
+ usr << "Issuing reason: [reason]."
+ return
+
+/////////////////////////////////////////////
+//Guest pass terminal////////////////////////
+/////////////////////////////////////////////
+
+/obj/machinery/computer/guestpass
+ name = "guest pass terminal"
+ icon_state = "guest"
+ density = 0
+
+
+ var/obj/item/weapon/card/id/giver
+ var/list/accesses = list()
+ var/giv_name = "NOT SPECIFIED"
+ var/reason = "NOT SPECIFIED"
+ var/duration = 0
+
+ var/list/internal_log = list()
+ var/mode = 0 // 0 - making pass, 1 - viewing logs
+
+/obj/machinery/computer/guestpass/attackby(obj/O, mob/user)
+ if(istype(O, /obj/item/weapon/card/id))
+ user.drop_item()
+ O.loc = src
+ giver = O
+ updateUsrDialog()
+
+/obj/machinery/computer/guestpass/attack_ai(var/mob/user as mob)
+ return attack_hand(user)
+
+/obj/machinery/computer/guestpass/attack_paw(var/mob/user as mob)
+ return attack_hand(user)
+
+/obj/machinery/computer/guestpass/attack_hand(var/mob/user as mob)
+ if(..())
+ return
+
+ user.set_machine(src)
+ var/dat
+
+ if (mode == 1) //Logs
+ dat += "
Activity log
"
+ for (var/entry in internal_log)
+ dat += "[entry]
"
+ dat += "Print
"
+ dat += "Back
"
+ else
+ dat += "Guest pass terminal #[uid]
"
+ dat += "View activity log
"
+ dat += "Issuing ID: [giver]
"
+ dat += "Issued to: [giv_name]
"
+ dat += "Reason: [reason]
"
+ dat += "Duration (minutes): [duration] m
"
+ dat += "Access to areas:
"
+ if (giver && giver.access)
+ for (var/A in giver.access)
+ var/area = get_access_desc(A)
+ if (A in accesses)
+ area = "[area]"
+ dat += "[area]
"
+ dat += "
Issue pass
"
+
+ user << browse(dat, "window=guestpass;size=400x520")
+ onclose(user, "guestpass")
+
+
+/obj/machinery/computer/guestpass/Topic(href, href_list)
+ if(..())
+ return
+ usr.set_machine(src)
+ if (href_list["mode"])
+ mode = text2num(href_list["mode"])
+
+ if (href_list["choice"])
+ switch(href_list["choice"])
+ if ("giv_name")
+ var/nam = input("Person pass is issued to", "Name", name)
+ if (nam)
+ giv_name = nam
+ if ("reason")
+ var/reas = input("Reason why pass is issued", "Reason", reason)
+ reason = reas
+ if ("duration")
+ var/dur = input("Duration (in minutes) during which pass is valid.", "Duration") as num
+ if (dur > 0 && dur < 30)
+ duration = dur
+ else
+ usr << "\red Invalid duration."
+ if ("access")
+ var/A = text2num(href_list["access"])
+ if (A in accesses)
+ accesses.Remove(A)
+ else
+ accesses.Add(A)
+ if (href_list["action"])
+ switch(href_list["action"])
+ if ("id")
+ if (giver)
+ if(ishuman(usr))
+ giver.loc = usr.loc
+ if(!usr.get_active_hand())
+ usr.put_in_hands(giver)
+ giver = null
+ else
+ giver.loc = src.loc
+ giver = null
+ else
+ var/obj/item/I = usr.get_active_hand()
+ if (istype(I, /obj/item/weapon/card/id))
+ usr.drop_item()
+ I.loc = src
+ giver = I
+ updateUsrDialog()
+
+ if ("print")
+ var/dat = "Activity log of guest pass terminal #[uid]
"
+ for (var/entry in internal_log)
+ dat += "[entry]
"
+ //usr << "Printing the log, standby..."
+ //sleep(50)
+ var/obj/item/weapon/paper/P = new/obj/item/weapon/paper( loc )
+ P.name = "activity log"
+ P.info = dat
+
+ if ("issue")
+ if (giver)
+ var/number = add_zero("[rand(0,9999)]", 4)
+ var/entry = "\[[worldtime2text()]\] Pass #[number] issued by [giver.registered_name] ([giver.assignment]) to [giv_name]. Reason: [reason]. Grants access to following areas: "
+ for (var/i=1 to accesses.len)
+ var/A = accesses[i]
+ if (A)
+ var/area = get_access_desc(A)
+ entry += "[i > 1 ? ", [area]" : "[area]"]"
+ entry += ". Expires at [worldtime2text(world.time + duration*10*60)]."
+ internal_log.Add(entry)
+
+ var/obj/item/weapon/card/id/guest/pass = new(src.loc)
+ pass.temp_access = accesses.Copy()
+ pass.registered_name = giv_name
+ pass.expiration_time = world.time + duration*10*60
+ pass.reason = reason
+ pass.name = "guest pass #[number]"
+ else
+ usr << "\red Cannot issue pass without issuing ID."
+ updateUsrDialog()
+ return
\ No newline at end of file
diff --git a/code/WorkInProgress/Mini/atmos_control.dm b/code/WorkInProgress/Mini/atmos_control.dm
index 943b6dd012c..7ae23e7e4b8 100644
--- a/code/WorkInProgress/Mini/atmos_control.dm
+++ b/code/WorkInProgress/Mini/atmos_control.dm
@@ -14,25 +14,6 @@
var/overridden = 0 //not set yet, can't think of a good way to do it
req_one_access = list(access_ce)
-/*
-/obj/machinery/computer/atmoscontrol/xeno
- name = "\improper Xenobiology Atmospherics Computer"
- filter=list(
- /area/toxins/xenobiology/specimen_1,
- /area/toxins/xenobiology/specimen_2,
- /area/toxins/xenobiology/specimen_3,
- /area/toxins/xenobiology/specimen_4,
- /area/toxins/xenobiology/specimen_5,
- /area/toxins/xenobiology/specimen_6)
- req_one_access = list(access_xenobiology,access_ce)
-
-
-/obj/machinery/computer/atmoscontrol/gas_chamber
- name = "\improper Gas Chamber Atmospherics Computer"
- filter=list(
- /area/security/gas_chamber)
- req_one_access = list(access_ce,access_hos)
-*/
/obj/machinery/computer/atmoscontrol/attack_ai(var/mob/user as mob)
src.add_hiddenprint(user)
@@ -104,7 +85,7 @@
var/list/alarm_data=list()
alarm_data["ID"]="\ref[alarm]"
- alarm_data["danger"] = max(alarm.danger_level, alarm.alarm_area.atmosalm)
+ alarm_data["danger"] = max(alarm.local_danger_level, alarm.alarm_area.atmosalm-1)
alarm_data["name"] = "[alarm]"
alarms+=list(alarm_data)
data["alarms"]=alarms
@@ -239,15 +220,15 @@
current.air_doors_open(1)
if(href_list["atmos_alarm"])
- if (current.alarm_area.atmosalert(2))
- current.apply_danger_level(2)
+ current.alarmActivated=1
+ current.alarm_area.updateDangerLevel()
spawn(1)
src.updateUsrDialog()
current.update_icon()
return
if(href_list["atmos_reset"])
- if (current.alarm_area.atmosalert(0))
- current.apply_danger_level(0)
+ current.alarmActivated=0
+ current.alarm_area.updateDangerLevel()
spawn(1)
src.updateUsrDialog()
current.update_icon()
diff --git a/code/WorkInProgress/Yinadele/Supermatter.dm b/code/WorkInProgress/Yinadele/Supermatter.dm
index 75ef4706e41..5b3f2e6e5b9 100644
--- a/code/WorkInProgress/Yinadele/Supermatter.dm
+++ b/code/WorkInProgress/Yinadele/Supermatter.dm
@@ -7,8 +7,8 @@
//These would be what you would get at point blank, decreases with distance
-#define DETONATION_RADS 200
-#define DETONATION_HALLUCINATION 600
+#define DETONATION_RADS 300000
+#define DETONATION_HALLUCINATION 60000
#define WARNING_DELAY 60 //45 seconds between warnings.
@@ -124,8 +124,8 @@
for(var/mob/living/mob in living_mob_list)
if(istype(mob, /mob/living/carbon/human))
//Hilariously enough, running into a closet should make you get hit the hardest.
- mob:hallucination += max(50, min(300, DETONATION_HALLUCINATION * sqrt(1 / (get_dist(mob, src) + 1)) ) )
- var/rads = DETONATION_RADS * sqrt( 1 / (get_dist(mob, src) + 1) )
+ mob:hallucination += max(50, min(300, DETONATION_HALLUCINATION/((get_dist(mob, src)+1)**2) ) )
+ var/rads = DETONATION_RADS/((get_dist(mob, src)+1)**2)
mob.apply_effect(rads, IRRADIATE)
explode()
diff --git a/code/WorkInProgress/ZomgPonies/Colored-windows.dm b/code/WorkInProgress/ZomgPonies/Colored-windows.dm
new file mode 100644
index 00000000000..a49ffe6bae1
--- /dev/null
+++ b/code/WorkInProgress/ZomgPonies/Colored-windows.dm
@@ -0,0 +1,47 @@
+var/global/wcBrig
+var/global/wcBar
+var/global/wcCommon
+
+//for all window/New and door/window/New
+/proc/color_windows(area = "common")
+ var/list/common = list("#379963", "#0d8395", "#58b5c3", "#49e46e", "#8fcf44", "#ffffff")
+ if(!wcCommon)
+ wcCommon = pick(common)
+ return wcCommon
+
+//This func called in master-controller, replaces color in some area
+/proc/color_windows_init()
+ var/list/brig = list("#aa0808", "#7f0606", "#ff0000")
+ var/list/bar = list("#0d8395", "#58b5c3", "#58c366", "#90d79a", "#ffffff")
+
+ wcBrig = pick(brig)
+ wcBar = pick(bar)
+
+ //BRIG
+ var/wsBrigList = list(
+ /area/security/brig,
+ /area/security/detectives_office,
+ /area/security/hos,
+ /area/security/lobby,
+ /area/security/main,
+ /area/security/prison,
+ /area/security/warden,
+ /area/security/range,
+ /area/prison/cell_block/A,
+ /area/prison/cell_block/B,
+ /area/security/processing,
+ /area/security/armoury
+
+ )
+
+ for(var/A in wsBrigList)
+ for(var/obj/structure/window/W in locate(A))
+ W.color = wcBrig
+ for(var/obj/machinery/door/window/D in locate(A))
+ D.color = wcBrig
+
+ //BAR
+ for(var/obj/structure/window/W in locate(/area/crew_quarters/bar))
+ W.color = wcBar
+ for(var/obj/machinery/door/window/D in locate(/area/crew_quarters/bar))
+ D.color = wcBar
\ No newline at end of file
diff --git a/code/WorkInProgress/ZomgPonies/mobs/metroid/powers.dm b/code/WorkInProgress/ZomgPonies/mobs/metroid/powers.dm
index f06fbbe2331..6f054846308 100644
--- a/code/WorkInProgress/ZomgPonies/mobs/metroid/powers.dm
+++ b/code/WorkInProgress/ZomgPonies/mobs/metroid/powers.dm
@@ -247,7 +247,7 @@
new_slime.key = key
new_slime << "You are now a slime!"
-
+/*
if(new_slime.client)
if(babies.len)
var/list/candidates = get_active_candidates()
@@ -261,7 +261,7 @@
else
- new_slime << "You're an only child!"
+ new_slime << "You're an only child!"*/
else
src << "I am not ready to reproduce yet..."
else
diff --git a/code/WorkInProgress/ZomgPonies/mobs/pony.dm b/code/WorkInProgress/ZomgPonies/mobs/pony.dm
index c9742e32f87..c57f841a63f 100644
--- a/code/WorkInProgress/ZomgPonies/mobs/pony.dm
+++ b/code/WorkInProgress/ZomgPonies/mobs/pony.dm
@@ -23,7 +23,7 @@
status_flags = 0
faction = "cult"
status_flags = CANPUSH
-
+ universal_speak = 1
Life()
..()
diff --git a/code/WorkInProgress/fireworks.dm b/code/WorkInProgress/fireworks.dm
new file mode 100644
index 00000000000..6372145968e
--- /dev/null
+++ b/code/WorkInProgress/fireworks.dm
@@ -0,0 +1,66 @@
+obj/item/weapon/firework
+ name = "fireworks"
+ icon = 'icons/obj/fireworks.dmi'
+ icon_state = "rocket_0"
+ var/litzor = 0
+ var/datum/effects/system/sparkel_spread/S
+obj/item/weapon/firework/attackby(obj/item/weapon/W,mob/user)
+ if(litzor)
+ return
+ if (istype(W, /obj/item/weapon/weldingtool) && W:welding || istype(W,/obj/item/weapon/lighter) && W:lit)
+ for(var/mob/M in viewers(user))
+ M << "[user] lits \the [src]"
+ litzor = 1
+ icon_state = "rocket_1"
+ S = new()
+ S.set_up(5,0,src.loc)
+ sleep(30)
+ if(ismob(src.loc) || isobj(src.loc))
+ S.attach(src.loc)
+ S.start()
+ del(src)
+
+obj/item/weapon/sparkler
+ name = "sparkler"
+ icon = 'icons/obj/fireworks.dmi'
+ icon_state = "sparkler_0"
+ var/litzor = 0
+ var/datum/effect/effect/system/spark_spread/S
+obj/item/weapon/sparkler/attackby(obj/item/weapon/W,mob/user)
+ if(litzor)
+ return
+ if (istype(W, /obj/item/weapon/weldingtool) && W:welding || istype(W,/obj/item/weapon/lighter) && W:lit)
+ for(var/mob/M in viewers(user))
+ M << "[user] lits \the [src]"
+ litzor = 1
+ icon_state = "sparkler_1"
+ var/b = rand(5,9)
+ for(var/xy, xy<=b, xy++)
+ S = new()
+ S.set_up(1,0,src.loc)
+ if(ismob(src.loc) || isobj(src.loc))
+ S.attach(src.loc)
+ S.start()
+ sleep(10)
+ del(src)
+/obj/crate/fireworks
+ name = "Fireworks!"
+/obj/crate/fireworks/New()
+ new /obj/item/weapon/sparkler(src)
+ new /obj/item/weapon/sparkler(src)
+ new /obj/item/weapon/sparkler(src)
+ new /obj/item/weapon/sparkler(src)
+ new /obj/item/weapon/sparkler(src)
+ new /obj/item/weapon/sparkler(src)
+ new /obj/item/weapon/sparkler(src)
+ new /obj/item/weapon/sparkler(src)
+ new /obj/item/weapon/firework(src)
+ new /obj/item/weapon/firework(src)
+ new /obj/item/weapon/firework(src)
+ new /obj/item/weapon/firework(src)
+ new /obj/item/weapon/firework(src)
+ new /obj/item/weapon/firework(src)
+ new /obj/item/weapon/firework(src)
+ new /obj/item/weapon/firework(src)
+ new /obj/item/weapon/firework(src)
+ new /obj/item/weapon/firework(src)
\ No newline at end of file
diff --git a/code/ZAS/Plasma.dm b/code/ZAS/Plasma.dm
index 9f0e95f6617..716ea216403 100644
--- a/code/ZAS/Plasma.dm
+++ b/code/ZAS/Plasma.dm
@@ -118,12 +118,12 @@ obj/var/contaminated = 0
/mob/living/carbon/human/proc/burn_eyes()
//The proc that handles eye burning.
if(prob(20)) src << "\red Your eyes burn!"
- eye_stat += 2.5
+ var/datum/organ/internal/eyes/E = internal_organs["eyes"]
+ E.damage += 2.5
eye_blurry = min(eye_blurry+1.5,50)
- if (prob(max(0,eye_stat - 20) + 1) &&!eye_blind)
+ if (prob(max(0,E.damage - 15) + 1) &&!eye_blind)
src << "\red You are blinded!"
eye_blind += 20
- eye_stat = 0
/mob/living/carbon/human/proc/pl_head_protected()
//Checks if the head is adequately sealed.
diff --git a/code/ZAS/Variable Settings.dm b/code/ZAS/Variable Settings.dm
index a66f80adf01..5dd951fe52e 100644
--- a/code/ZAS/Variable Settings.dm
+++ b/code/ZAS/Variable Settings.dm
@@ -9,8 +9,7 @@ var/global/vs_control/vsc = new
var/fire_firelevel_multiplier_NAME = "Fire - Firelevel Constant"
var/fire_firelevel_multiplier_DESC = "Multiplied by the equation for firelevel, affects mainly the extingiushing of fires."
-// var/fire_fuel_energy_release = 397000
- var/fire_fuel_energy_release = 300000
+ var/fire_fuel_energy_release = 397000
var/fire_fuel_energy_release_NAME = "Fire - Fuel energy release"
var/fire_fuel_energy_release_DESC = "The energy in joule released when burning one mol of a burnable substance"
diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm
index 65eddd6cdf0..763c6136a9f 100644
--- a/code/__HELPERS/game.dm
+++ b/code/__HELPERS/game.dm
@@ -287,7 +287,7 @@ proc/isInSight(var/atom/A, var/atom/B)
var/list/candidates = list() //List of candidate KEYS to assume control of the new larva ~Carn
var/i = 0
while(candidates.len <= 0 && i < 5)
- for(var/mob/dead/observer/G in player_list)
+ for(var/mob/G in respawnable_list)
if(((G.client.inactivity/10)/60) <= buffer + i) // the most active players are more likely to become an alien
if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD))
candidates += G.key
@@ -301,8 +301,8 @@ proc/isInSight(var/atom/A, var/atom/B)
var/list/candidates = list() //List of candidate KEYS to assume control of the new larva ~Carn
var/i = 0
while(candidates.len <= 0 && i < 5)
- for(var/mob/dead/observer/G in player_list)
- if(G.client.prefs.be_special & BE_ALIEN)
+ for(var/mob/G in respawnable_list)
+ if( G.client && G.client.prefs.be_special & BE_ALIEN)
if(((G.client.inactivity/10)/60) <= ALIEN_SELECT_AFK_BUFFER + i) // the most active players are more likely to become an alien
if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD))
candidates += G.key
@@ -311,7 +311,7 @@ proc/isInSight(var/atom/A, var/atom/B)
proc/get_candidates(be_special_flag=0)
. = list()
- for(var/mob/dead/observer/G in player_list)
+ for(var/mob/G in respawnable_list)
if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD))
if(!G.client.is_afk() && (G.client.prefs.be_special & be_special_flag))
. += G.client
diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm
index d4c7f2b9df3..6125ec18368 100644
--- a/code/__HELPERS/global_lists.dm
+++ b/code/__HELPERS/global_lists.dm
@@ -9,6 +9,7 @@ var/global/list/player_list = list() //List of all mobs **with clients attach
var/global/list/mob_list = list() //List of all mobs, including clientless
var/global/list/living_mob_list = list() //List of all alive mobs, including clientless. Excludes /mob/new_player
var/global/list/dead_mob_list = list() //List of all dead mobs, including clientless. Excludes /mob/new_player
+var/global/list/respawnable_list = list() //List of all mobs, dead or in mindless creatures that still be respawned.
var/global/list/portals = list() //for use by portals
var/global/list/cable_list = list() //Index for all cables, so that powernets don't have to look through the entire world all the time
diff --git a/code/__HELPERS/maths.dm b/code/__HELPERS/maths.dm
index b174147d583..6be724fbd99 100644
--- a/code/__HELPERS/maths.dm
+++ b/code/__HELPERS/maths.dm
@@ -111,4 +111,30 @@ var/const/Sqrt2 = 1.41421356
/proc/Wrap(val, min, max)
var/d = max - min
var/t = Floor((val - min) / d)
- return val - (t * d)
\ No newline at end of file
+ return val - (t * d)
+
+//converts a uniform distributed random number into a normal distributed one
+//since this method produces two random numbers, one is saved for subsequent calls
+//(making the cost negligble for every second call)
+//This will return +/- decimals, situated about mean with standard deviation stddev
+//68% chance that the number is within 1stddev
+//95% chance that the number is within 2stddev
+//98% chance that the number is within 3stddev...etc
+var/gaussian_next
+#define ACCURACY 10000
+/proc/gaussian(mean, stddev)
+ var/R1;var/R2;var/working
+ if(gaussian_next != null)
+ R1 = gaussian_next
+ gaussian_next = null
+ else
+ do
+ R1 = rand(-ACCURACY,ACCURACY)/ACCURACY
+ R2 = rand(-ACCURACY,ACCURACY)/ACCURACY
+ working = R1*R1 + R2*R2
+ while(working >= 1 || working==0)
+ working = sqrt(-2 * log(working) / working)
+ R1 *= working
+ gaussian_next = R2 * working
+ return (mean + stddev * R1)
+#undef ACCURACY
\ No newline at end of file
diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm
index 324cfad6323..af1641f804d 100644
--- a/code/__HELPERS/mobs.dm
+++ b/code/__HELPERS/mobs.dm
@@ -74,4 +74,25 @@ proc/age2agedescription(age)
if(45 to 60) return "middle-aged"
if(60 to 70) return "aging"
if(70 to INFINITY) return "elderly"
- else return "unknown"
\ No newline at end of file
+ else return "unknown"
+
+
+
+/*
+Proc for attack log creation, because really why not
+1 argument is the actor
+2 argument is the target of action
+3 is the description of action(like punched, throwed, or any other verb)
+4 is the tool with which the action was made(usually item)
+5 is additional information, anything that needs to be added
+*/
+
+proc/add_logs(mob/target, mob/user, what_done, var/object=null, var/addition=null)
+ if(ismob(user))
+ user.attack_log += text("\[[time_stamp()]\] Has [what_done] [target.name][ismob(target) ? "([target.ckey])" : ""][object ? " with [object]" : " "][addition]")
+ if(ismob(target))
+ target.attack_log += text("\[[time_stamp()]\] Has been [what_done] by [user.name][ismob(user) ? "([user.ckey])" : ""][object ? " with [object]" : " "][addition]")
+ log_attack("[user.name][ismob(user) ? "([user.ckey])" : ""] [what_done] [target.name][ismob(target) ? "([target.ckey])" : ""][object ? " with [object]" : " "][addition]")
+ if(target.client)
+ if(what_done != ("shaked" || "CPRed" || "grabbed"))
+ message_admins("[user.name][ismob(user) ? "([user.ckey])" : ""] [what_done] [target.name][ismob(target) ? "([target.ckey])" : ""][object ? " with [object]" : " "][addition](JMP)")
\ No newline at end of file
diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm
index 29d9d4a5e3a..afcffc098c6 100644
--- a/code/__HELPERS/type2type.dm
+++ b/code/__HELPERS/type2type.dm
@@ -269,6 +269,5 @@ proc/tg_list2text(list/list, glue=",")
/proc/ui_style2icon(ui_style)
switch(ui_style)
- if("old") return 'icons/mob/screen1_old.dmi'
- if("Orange") return 'icons/mob/screen1_Orange.dmi'
- else return 'icons/mob/screen1_Midnight.dmi'
+ if("Midnight") return 'icons/mob/screen1_Midnight.dmi'
+ else return 'icons/mob/screen1_White.dmi'
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index d414a395549..dd13a83e708 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -96,6 +96,7 @@ var/datum/global_hud/global_hud = new()
var/obj/screen/lingchemdisplay
var/obj/screen/blobpwrdisplay
var/obj/screen/blobhealthdisplay
+ var/obj/screen/vampire_blood_display
var/obj/screen/alien_plasma_display
var/obj/screen/r_hand_hud_object
var/obj/screen/l_hand_hud_object
@@ -169,9 +170,11 @@ datum/hud/New(mob/owner)
if(!ismob(mymob)) return 0
if(!mymob.client) return 0
var/ui_style = ui_style2icon(mymob.client.prefs.UI_style)
+ var/ui_color = mymob.client.prefs.UI_style_color
+ var/ui_alpha = mymob.client.prefs.UI_style_alpha
if(ishuman(mymob))
- human_hud(ui_style) // Pass the player the UI style chosen in preferences
+ human_hud(ui_style, ui_color, ui_alpha) // Pass the player the UI style chosen in preferences
else if(ismonkey(mymob))
monkey_hud(ui_style)
else if(isbrain(mymob))
@@ -186,7 +189,10 @@ datum/hud/New(mob/owner)
robot_hud()
else if(isobserver(mymob))
ghost_hud()
-
+ else if(isovermind(mymob))
+ blob_hud()
+ else if(mymob.mind && mymob.mind.vampire)
+ vampire_hud()
//Triggered when F12 is pressed (Unless someone changed something in the DMF)
/mob/verb/button_pressed_F12()
diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm
index d5afad47f58..38bb1173ce4 100644
--- a/code/_onclick/hud/human.dm
+++ b/code/_onclick/hud/human.dm
@@ -1,4 +1,4 @@
-/datum/hud/proc/human_hud(var/ui_style='icons/mob/screen1_old.dmi')
+/datum/hud/proc/human_hud(var/ui_style='icons/mob/screen1_White.dmi', var/ui_color = "#ffffff", var/ui_alpha = 255)
src.adding = list()
src.other = list()
@@ -73,6 +73,8 @@
using.icon_state = (mymob.m_intent == "run" ? "running" : "walking")
using.screen_loc = ui_movi
using.layer = 20
+ using.color = ui_color
+ using.alpha = ui_alpha
src.adding += using
move_intent = using
@@ -82,6 +84,8 @@
using.icon_state = "act_drop"
using.screen_loc = ui_drop_throw
using.layer = 19
+ using.color = ui_color
+ using.alpha = ui_alpha
src.hotkeybuttons += using
inv_box = new /obj/screen/inventory()
@@ -92,6 +96,8 @@
inv_box.icon_state = "center"
inv_box.screen_loc = ui_iclothing
inv_box.layer = 19
+ inv_box.color = ui_color
+ inv_box.alpha = ui_alpha
src.other += inv_box
inv_box = new /obj/screen/inventory()
@@ -101,6 +107,8 @@
inv_box.slot_id = slot_wear_suit
inv_box.icon_state = "equip"
inv_box.screen_loc = ui_oclothing
+ inv_box.color = ui_color
+ inv_box.alpha = ui_alpha
inv_box.layer = 19
src.other += inv_box
@@ -114,6 +122,8 @@
inv_box.screen_loc = ui_rhand
inv_box.slot_id = slot_r_hand
inv_box.layer = 19
+ inv_box.color = ui_color
+ inv_box.alpha = ui_alpha
src.r_hand_hud_object = inv_box
src.adding += inv_box
@@ -127,6 +137,8 @@
inv_box.screen_loc = ui_lhand
inv_box.slot_id = slot_l_hand
inv_box.layer = 19
+ inv_box.color = ui_color
+ inv_box.alpha = ui_alpha
src.l_hand_hud_object = inv_box
src.adding += inv_box
@@ -137,6 +149,8 @@
using.icon_state = "hand1"
using.screen_loc = ui_swaphand1
using.layer = 19
+ using.color = ui_color
+ using.alpha = ui_alpha
src.adding += using
using = new /obj/screen/inventory()
@@ -146,6 +160,8 @@
using.icon_state = "hand2"
using.screen_loc = ui_swaphand2
using.layer = 19
+ using.color = ui_color
+ using.alpha = ui_alpha
src.adding += using
inv_box = new /obj/screen/inventory()
@@ -156,6 +172,8 @@
inv_box.screen_loc = ui_id
inv_box.slot_id = slot_wear_id
inv_box.layer = 19
+ inv_box.color = ui_color
+ inv_box.alpha = ui_alpha
src.adding += inv_box
inv_box = new /obj/screen/inventory()
@@ -166,6 +184,8 @@
inv_box.screen_loc = ui_pda
inv_box.slot_id = slot_wear_pda
inv_box.layer = 19
+ inv_box.color = ui_color
+ inv_box.alpha = ui_alpha
src.adding += inv_box
inv_box = new /obj/screen/inventory()
@@ -176,6 +196,8 @@
inv_box.screen_loc = ui_mask
inv_box.slot_id = slot_wear_mask
inv_box.layer = 19
+ inv_box.color = ui_color
+ inv_box.alpha = ui_alpha
src.other += inv_box
inv_box = new /obj/screen/inventory()
@@ -186,6 +208,8 @@
inv_box.screen_loc = ui_back
inv_box.slot_id = slot_back
inv_box.layer = 19
+ inv_box.color = ui_color
+ inv_box.alpha = ui_alpha
src.adding += inv_box
inv_box = new /obj/screen/inventory()
@@ -195,6 +219,8 @@
inv_box.screen_loc = ui_storage1
inv_box.slot_id = slot_l_store
inv_box.layer = 19
+ inv_box.color = ui_color
+ inv_box.alpha = ui_alpha
src.adding += inv_box
inv_box = new /obj/screen/inventory()
@@ -204,6 +230,8 @@
inv_box.screen_loc = ui_storage2
inv_box.slot_id = slot_r_store
inv_box.layer = 19
+ inv_box.color = ui_color
+ inv_box.alpha = ui_alpha
src.adding += inv_box
inv_box = new /obj/screen/inventory()
@@ -214,6 +242,8 @@
inv_box.screen_loc = ui_sstore1
inv_box.slot_id = slot_s_store
inv_box.layer = 19
+ inv_box.color = ui_color
+ inv_box.alpha = ui_alpha
src.adding += inv_box
using = new /obj/screen()
@@ -222,6 +252,8 @@
using.icon_state = "act_resist"
using.screen_loc = ui_pull_resist
using.layer = 19
+ using.color = ui_color
+ using.alpha = ui_alpha
src.hotkeybuttons += using
using = new /obj/screen()
@@ -230,6 +262,8 @@
using.icon_state = "other"
using.screen_loc = ui_inventory
using.layer = 20
+ using.color = ui_color
+ using.alpha = ui_alpha
src.adding += using
using = new /obj/screen()
@@ -238,6 +272,8 @@
using.icon_state = "act_equip"
using.screen_loc = ui_equip
using.layer = 20
+ using.color = ui_color
+ using.alpha = ui_alpha
src.adding += using
inv_box = new /obj/screen/inventory()
@@ -247,6 +283,8 @@
inv_box.screen_loc = ui_gloves
inv_box.slot_id = slot_gloves
inv_box.layer = 19
+ inv_box.color = ui_color
+ inv_box.alpha = ui_alpha
src.other += inv_box
inv_box = new /obj/screen/inventory()
@@ -256,6 +294,8 @@
inv_box.screen_loc = ui_glasses
inv_box.slot_id = slot_glasses
inv_box.layer = 19
+ inv_box.color = ui_color
+ inv_box.alpha = ui_alpha
src.other += inv_box
inv_box = new /obj/screen/inventory()
@@ -265,6 +305,8 @@
inv_box.screen_loc = ui_l_ear
inv_box.slot_id = slot_l_ear
inv_box.layer = 19
+ inv_box.color = ui_color
+ inv_box.alpha = ui_alpha
src.other += inv_box
inv_box = new /obj/screen/inventory()
@@ -274,6 +316,8 @@
inv_box.screen_loc = ui_r_ear
inv_box.slot_id = slot_r_ear
inv_box.layer = 19
+ inv_box.color = ui_color
+ inv_box.alpha = ui_alpha
src.other += inv_box
inv_box = new /obj/screen/inventory()
@@ -283,6 +327,8 @@
inv_box.screen_loc = ui_head
inv_box.slot_id = slot_head
inv_box.layer = 19
+ inv_box.color = ui_color
+ inv_box.alpha = ui_alpha
src.other += inv_box
inv_box = new /obj/screen/inventory()
@@ -292,6 +338,8 @@
inv_box.screen_loc = ui_shoes
inv_box.slot_id = slot_shoes
inv_box.layer = 19
+ inv_box.color = ui_color
+ inv_box.alpha = ui_alpha
src.other += inv_box
inv_box = new /obj/screen/inventory()
@@ -301,6 +349,8 @@
inv_box.screen_loc = ui_belt
inv_box.slot_id = slot_belt
inv_box.layer = 19
+ inv_box.color = ui_color
+ inv_box.alpha = ui_alpha
src.adding += inv_box
mymob.throw_icon = new /obj/screen()
@@ -308,6 +358,8 @@
mymob.throw_icon.icon_state = "act_throw_off"
mymob.throw_icon.name = "throw"
mymob.throw_icon.screen_loc = ui_drop_throw
+ mymob.throw_icon.color = ui_color
+ mymob.throw_icon.alpha = ui_alpha
src.hotkeybuttons += mymob.throw_icon
mymob.oxygen = new /obj/screen()
@@ -392,6 +444,8 @@
mymob.zone_sel = new /obj/screen/zone_sel( null )
mymob.zone_sel.icon = ui_style
+ mymob.zone_sel.color = ui_color
+ mymob.zone_sel.alpha = ui_alpha
mymob.zone_sel.overlays.Cut()
mymob.zone_sel.overlays += image('icons/mob/zone_sel.dmi', "[mymob.zone_sel.selecting]")
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index 54a7974d586..69b7eb3a510 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -36,6 +36,9 @@
if(istype(master, /obj/item/weapon/storage))
var/obj/item/weapon/storage/S = master
S.close(usr)
+ else if(istype(master,/obj/item/clothing/suit/storage))
+ var/obj/item/clothing/suit/storage/S = master
+ S.close(usr)
return 1
diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index 11022a232ac..ab6a39ac0b7 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -39,9 +39,7 @@
user.lastattacked = M
M.lastattacker = user
- user.attack_log += "\[[time_stamp()]\] Attacked [M.name] ([M.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])"
- M.attack_log += "\[[time_stamp()]\] Attacked by [user.name] ([user.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])"
- log_attack("[user.name] ([user.ckey]) attacked [M.name] ([M.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" )
+ add_logs(M, user, "attacked", src.name, "(INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])")
//spawn(1800) // this wont work right
// M.lastattacker = null
diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm
index c6b0edcff49..200dccdfe7a 100644
--- a/code/controllers/configuration.dm
+++ b/code/controllers/configuration.dm
@@ -43,7 +43,8 @@
var/Tickcomp = 0
var/socket_talk = 0 // use socket_talk to communicate with other processes
var/list/resource_urls = null
-
+ var/antag_hud_allowed = 0 // Ghosts can turn on Antagovision to see a HUD of who is the bad guys this round.
+ var/antag_hud_restricted = 0 // Ghosts that turn on Antagovision cannot rejoin the round.
var/list/mode_names = list()
var/list/modes = list() // allowed modes
var/list/votable_modes = list() // votable modes
@@ -384,6 +385,12 @@
if("tickcomp")
Tickcomp = 1
+ if("allow_antag_hud")
+ config.antag_hud_allowed = 1
+
+ if("antag_hud_restricted")
+ config.antag_hud_restricted = 1
+
if("humans_need_surnames")
humans_need_surnames = 1
diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm
index 2a3da63ef72..f3f07df9af6 100644
--- a/code/controllers/master_controller.dm
+++ b/code/controllers/master_controller.dm
@@ -72,6 +72,8 @@ datum/controller/game_controller/proc/setup()
for(var/i=0, iAll the changelings are dead! Restart in [round((changeling.TIME_TO_GET_REVIVED-(world.time-changeling.changelingdeathtime))/10)] seconds."
sections["changeling"] = text
+ /** VAMPIRE ***/
+ text = "vampire"
+ if (ticker.mode.config_tag=="vampire")
+ text = uppertext(text)
+ text = "[text]: "
+ if (src in ticker.mode.vampires)
+ text += "YES|no"
+ if (objectives.len==0)
+ text += "
Objectives are empty! Randomize!"
+ else
+ text += "yes|NO"
+ /** Enthralled ***/
+ text += "
enthralled"
+ if(src in ticker.mode.enthralled)
+ text += " YES | no"
+ else
+ text += " yes | NO"
+ sections["vampire"] = text
+
+
/** NUCLEAR ***/
text = "nuclear"
if (ticker.mode.config_tag=="nuclear")
@@ -387,7 +411,7 @@ datum/mind
if(!def_value)//If it's a custom objective, it will be an empty string.
def_value = "custom"
- var/new_obj_type = input("Select objective type:", "Objective type", def_value) as null|anything in list("assassinate", "debrain", "protect", "prevent", "harm", "brig", "hijack", "escape", "survive", "steal", "download", "nuclear", "capture", "absorb", "custom")
+ var/new_obj_type = input("Select objective type:", "Objective type", def_value) as null|anything in list("assassinate", "blood", "debrain", "protect", "prevent", "harm", "brig", "hijack", "escape", "survive", "steal", "download", "nuclear", "capture", "absorb", "custom")
if (!new_obj_type) return
var/datum/objective/new_objective = null
@@ -455,7 +479,7 @@ datum/mind
if (!steal.select_target())
return
- if("download","capture","absorb")
+ if("download","capture","absorb", "blood")
var/def_num
if(objective&&objective.type==text2path("/datum/objective/[new_obj_type]"))
def_num = objective.target_amount
@@ -474,6 +498,9 @@ datum/mind
if("absorb")
new_objective = new /datum/objective/absorb
new_objective.explanation_text = "Absorb [target_number] compatible genomes."
+ if("blood")
+ new_objective = new /datum/objective/blood
+ new_objective.explanation_text = "Accumulate atleast [target_number] units of blood in total."
new_objective.owner = src
new_objective.target_amount = target_number
@@ -735,6 +762,28 @@ datum/mind
updateappearance(current, current.dna.uni_identity)
domutcheck(current, null)
+ else if (href_list["vampire"])
+ switch(href_list["vampire"])
+ if("clear")
+ if(src in ticker.mode.vampires)
+ ticker.mode.vampires -= src
+ special_role = null
+ current.remove_vampire_powers()
+ if(vampire) del(vampire)
+ current << "You grow weak and lose your powers! You are no longer a vampire and are stuck in your current form!"
+ log_admin("[key_name_admin(usr)] has de-vampired [current].")
+ if("vampire")
+ if(!(src in ticker.mode.vampires))
+ ticker.mode.vampires += src
+ ticker.mode.grant_vampire_powers(current)
+ special_role = "Vampire"
+ current << "Your powers are awoken. Your lust for blood grows... You are a Vampire!"
+ log_admin("[key_name_admin(usr)] has vampired [current].")
+ if("autoobjectives")
+ ticker.mode.forge_vampire_objectives(src)
+ usr << "\blue The objectives for vampire [key] have been generated. You can edit them and announce manually."
+
+
else if (href_list["nuclear"])
switch(href_list["nuclear"])
if("clear")
diff --git a/code/datums/spell.dm b/code/datums/spell.dm
index a483596cfe7..8e733d4df39 100644
--- a/code/datums/spell.dm
+++ b/code/datums/spell.dm
@@ -26,6 +26,9 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
var/range = 7 //the range of the spell; outer radius for aoe spells
var/message = "" //whatever it says to the guy affected by it
var/selection_type = "view" //can be "range" or "view"
+ var/spell_level = 0 //if a spell can be taken multiple times, this raises
+ var/level_max = 4 //The max possible level_max is 4
+ var/cooldown_min = 0 //This defines what spell quickened four timeshas as a cooldown. Make sure to set this for every spell
var/overlay = 0
var/overlay_icon = 'icons/obj/wizard.dmi'
@@ -38,49 +41,53 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
var/smoke_amt = 0 //cropped at 10
var/critfailchance = 0
- var/centcomm_cancast = 1 //Whether or not the spell should be allowed on z2
+ var/centcom_cancast = 1 //Whether or not the spell should be allowed on z2
/obj/effect/proc_holder/spell/proc/cast_check(skipcharge = 0,mob/user = usr) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell
- if(!(src in usr.spell_list))
- usr << "\red You shouldn't have this spell! Something's wrong."
+ if(!(src in user.spell_list))
+ user << "You shouldn't have this spell! Something's wrong."
return 0
- if(usr.z == 2 && !centcomm_cancast) //Certain spells are not allowed on the centcomm zlevel
+ if(user.z == 2 && !centcom_cancast) //Certain spells are not allowed on the centcom zlevel
return 0
if(!skipcharge)
switch(charge_type)
if("recharge")
if(charge_counter < charge_max)
- usr << "[name] is still recharging."
+ user << "[name] is still recharging."
return 0
if("charges")
if(!charge_counter)
- usr << "[name] has no charges left."
+ user << "[name] has no charges left."
return 0
- if(usr.stat && !stat_allowed)
- usr << "Not when you're incapacitated."
+ if(user.stat && !stat_allowed)
+ user << "Not when you're incapacitated."
return 0
- if(ishuman(usr) || ismonkey(usr))
- if(istype(usr.wear_mask, /obj/item/clothing/mask/muzzle))
- usr << "Mmmf mrrfff!"
+ if(ishuman(user))
+
+ var/mob/living/carbon/human/H = user
+
+ if(istype(H.wear_mask, /obj/item/clothing/mask/muzzle))
+ user << "You can't get the words out!"
return 0
- if(clothes_req) //clothes check
- if(!istype(usr, /mob/living/carbon/human))
- usr << "You aren't a human, Why are you trying to cast a human spell, silly non-human? Casting human spells is for humans."
- return 0
- if(!istype(usr:wear_suit, /obj/item/clothing/suit/wizrobe) && !istype(user:wear_suit, /obj/item/clothing/suit/space/rig/wizard))
- usr << "I don't feel strong enough without my robe."
- return 0
- if(!istype(usr:shoes, /obj/item/clothing/shoes/sandal))
- usr << "I don't feel strong enough without my sandals."
- return 0
- if(!istype(usr:head, /obj/item/clothing/head/wizard) && !istype(user:head, /obj/item/clothing/head/helmet/space/rig/wizard))
- usr << "I don't feel strong enough without my hat."
+ if(clothes_req) //clothes check
+ if(!istype(H.wear_suit, /obj/item/clothing/suit/wizrobe) && !istype(H.wear_suit, /obj/item/clothing/suit/space/rig/wizard))
+ H << "I don't feel strong enough without my robe."
+ return 0
+ if(!istype(H.shoes, /obj/item/clothing/shoes/sandal))
+ H << "I don't feel strong enough without my sandals."
+ return 0
+ if(!istype(H.head, /obj/item/clothing/head/wizard) && !istype(H.head, /obj/item/clothing/head/helmet/space/rig/wizard))
+ H << "I don't feel strong enough without my hat."
+ return 0
+ else
+ if(clothes_req)
+ user << "This spell can only be casted by humans!"
return 0
if(!skipcharge)
@@ -95,22 +102,17 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
return 1
/obj/effect/proc_holder/spell/proc/invocation(mob/user = usr) //spelling the spell out and setting it on recharge/reducing charges amount
-
switch(invocation_type)
if("shout")
if(prob(50))//Auto-mute? Fuck that noise
- usr.say(invocation)
+ user.say(invocation)
else
- usr.say(replacetext(invocation," ","`"))
- if(usr.gender==MALE)
- playsound(usr.loc, pick('sound/misc/null.ogg','sound/misc/null.ogg'), 100, 1)
- else
- playsound(usr.loc, pick('sound/misc/null.ogg','sound/misc/null.ogg'), 100, 1)
+ user.say(replacetext(invocation," ","`"))
if("whisper")
if(prob(50))
- usr.whisper(invocation)
+ user.whisper(invocation)
else
- usr.whisper(replacetext(invocation," ","`"))
+ user.whisper(replacetext(invocation," ","`"))
/obj/effect/proc_holder/spell/New()
..()
diff --git a/code/datums/spells/charge.dm b/code/datums/spells/charge.dm
new file mode 100644
index 00000000000..c1fa2866b67
--- /dev/null
+++ b/code/datums/spells/charge.dm
@@ -0,0 +1,85 @@
+/obj/effect/proc_holder/spell/targeted/charge
+ name = "Charge"
+ desc = "This spell can be used to charge up spent magical artifacts, among other things."
+
+ school = "transmutation"
+ charge_max = 600
+ clothes_req = 0
+ invocation = "DIRI CEL"
+ invocation_type = "whisper"
+ range = -1
+// cooldown_min = 400 //50 deciseconds reduction per rank
+ include_user = 1
+
+
+/obj/effect/proc_holder/spell/targeted/charge/cast(list/targets)
+ for(var/mob/living/user in targets)
+ var/list/hand_items = list(user.get_active_hand(),user.get_inactive_hand())
+ var/charged_item = null
+ var/burnt_out = 0
+ for(var/obj/item in hand_items)
+ if(istype(item, /obj/item/weapon/grab))
+ var/obj/item/weapon/grab/G = item
+ if(G.affecting)
+ var/mob/M = G.affecting
+ if(M.spell_list.len != 0)
+ for(var/obj/effect/proc_holder/spell/S in M.spell_list)
+ S.charge_counter = S.charge_max
+ M <<"you feel raw magic flowing through you, it feels good!"
+ else
+ M <<"you feel very strange for a moment, but then it passes."
+ burnt_out = 1
+ charged_item = M
+ break
+ else if(istype(item, /obj/item/weapon/spellbook/oneuse))
+ var/obj/item/weapon/spellbook/oneuse/I = item
+ if(prob(80))
+ user.visible_message("[I] catches fire!")
+ del(I)
+ else
+ I.used = 0
+ charged_item = I
+ break
+ else if(istype(item, /obj/item/weapon/gun/magic))
+ var/obj/item/weapon/gun/magic/I = item
+ if(prob(80))
+ I.max_charges--
+ if(I.max_charges <= 0)
+ I.max_charges = 0
+ burnt_out = 1
+ I.charges = I.max_charges
+ if(istype(item,/obj/item/weapon/gun/magic/wand) && I.max_charges != 0)
+ var/obj/item/weapon/gun/magic/W = item
+ W.icon_state = initial(W.icon_state)
+ charged_item = I
+ break
+ else if(istype(item, /obj/item/weapon/cell/))
+ var/obj/item/weapon/cell/C = item
+ if(prob(80))
+ C.maxcharge -= 200
+ if(C.maxcharge <= 1) //Div by 0 protection
+ C.maxcharge = 1
+ burnt_out = 1
+ C.charge = C.maxcharge
+ charged_item = C
+ break
+ else if(item.contents)
+ var/obj/I = null
+ for(I in item.contents)
+ if(istype(I, /obj/item/weapon/cell/))
+ var/obj/item/weapon/cell/C = I
+ if(prob(80))
+ C.maxcharge -= 200
+ if(C.maxcharge <= 1) //Div by 0 protection
+ C.maxcharge = 1
+ burnt_out = 1
+ C.charge = C.maxcharge
+ item.update_icon()
+ charged_item = item
+ break
+ if(!charged_item)
+ user << "you feel magical power surging to your hands, but the feeling rapidly fades..."
+ else if(burnt_out)
+ user << "[charged_item] doesn't seem to be reacting to the spell..."
+ else
+ user << "[charged_item] suddenly feels very warm!"
diff --git a/code/datums/spells/conjure.dm b/code/datums/spells/conjure.dm
index de84db5915b..5bccf70dc50 100644
--- a/code/datums/spells/conjure.dm
+++ b/code/datums/spells/conjure.dm
@@ -30,8 +30,11 @@
if(summon_ignore_prev_spawn_points)
targets -= spawn_place
if(ispath(summoned_object_type,/turf))
+ if(istype(get_turf(usr),/turf/simulated/shuttle))
+ usr << "\red You can't build things on shuttles!"
+ break
var/turf/O = spawn_place
- var/turf/N = summoned_object_type
+ var/N = summoned_object_type
O.ChangeTurf(N)
else
var/atom/summoned_object = new summoned_object_type(spawn_place)
@@ -61,27 +64,4 @@
summon_type = list(/obj/machinery/bot/ed209)
summon_amt = 10
range = 3
- newVars = list("emagged" = 1,"name" = "Wizard's Justicebot")
-
-
-//This was previously left in the old wizard code, not being included.
-//Wasn't sure if I should transfer it here, or to code/datums/spells.dm
-//But I decided because it is a conjuration related object it would fit better here
-//Feel free to change this, I don't know.
-/obj/effect/forcefield
- desc = "A space wizard's magic wall."
- name = "FORCEWALL"
- icon = 'icons/effects/effects.dmi'
- icon_state = "m_shield"
- anchored = 1.0
- opacity = 0
- density = 1
- unacidable = 1
-
-
- bullet_act(var/obj/item/projectile/Proj, var/def_zone)
- var/turf/T = get_turf(src.loc)
- if(T)
- for(var/mob/M in T)
- Proj.on_hit(M,M.bullet_act(Proj, def_zone))
- return
\ No newline at end of file
+ newVars = list("emagged" = 1,"name" = "Wizard's Justicebot")
\ No newline at end of file
diff --git a/code/datums/spells/construct_spells.dm b/code/datums/spells/construct_spells.dm
new file mode 100644
index 00000000000..5d94f28cdb7
--- /dev/null
+++ b/code/datums/spells/construct_spells.dm
@@ -0,0 +1,101 @@
+//////////////////////////////Construct Spells/////////////////////////
+
+/obj/effect/proc_holder/spell/aoe_turf/conjure/construct/lesser
+ charge_max = 1800
+
+/obj/effect/proc_holder/spell/aoe_turf/conjure/floor
+ name = "Floor Construction"
+ desc = "This spell constructs a cult floor"
+
+ school = "conjuration"
+ charge_max = 20
+ clothes_req = 0
+ invocation = "none"
+ invocation_type = "none"
+ range = 0
+ summon_type = list(/turf/simulated/floor/engine/cult)
+ centcom_cancast = 0 //Stop crashing the server by spawning turfs on transit tiles
+
+/obj/effect/proc_holder/spell/aoe_turf/conjure/wall
+ name = "Lesser Construction"
+ desc = "This spell constructs a cult wall"
+
+ school = "conjuration"
+ charge_max = 100
+ clothes_req = 0
+ invocation = "none"
+ invocation_type = "none"
+ range = 0
+ summon_type = list(/turf/simulated/wall/cult)
+ centcom_cancast = 0 //Stop crashing the server by spawning turfs on transit tiles
+
+/obj/effect/proc_holder/spell/aoe_turf/conjure/wall/reinforced
+ name = "Greater Construction"
+ desc = "This spell constructs a reinforced metal wall"
+
+ school = "conjuration"
+ charge_max = 300
+ clothes_req = 0
+ invocation = "none"
+ invocation_type = "none"
+ range = 0
+ centcom_cancast = 0 //Stop crashing the server by spawning turfs on transit tiles
+ delay = 50
+
+ summon_type = list(/turf/simulated/wall/r_wall)
+
+/obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone
+ name = "Summon Soulstone"
+ desc = "This spell reaches into Nar-Sie's realm, summoning one of the legendary fragments across time and space"
+
+ school = "conjuration"
+ charge_max = 3000
+ clothes_req = 0
+ invocation = "none"
+ invocation_type = "none"
+ range = 0
+
+ summon_type = list(/obj/item/device/soulstone)
+
+
+/obj/effect/proc_holder/spell/aoe_turf/conjure/lesserforcewall
+ name = "Shield"
+ desc = "This spell creates a temporary forcefield to shield yourself and allies from incoming fire"
+
+ school = "transmutation"
+ charge_max = 300
+ clothes_req = 0
+ invocation = "none"
+ invocation_type = "none"
+ range = 0
+ summon_type = list(/obj/effect/forcefield)
+ summon_lifespan = 200
+
+
+/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift
+ name = "Phase Shift"
+ desc = "This spell allows you to pass through walls"
+
+ school = "transmutation"
+ charge_max = 200
+ clothes_req = 0
+ invocation = "none"
+ invocation_type = "none"
+ range = -1
+ include_user = 1
+ phaseshift = 1
+ jaunt_duration = 50 //in deciseconds
+ centcom_cancast = 0 //Stop people from getting to centcom
+
+
+/obj/effect/proc_holder/spell/targeted/projectile/magic_missile/lesser
+ name = "Lesser Magic Missile"
+ desc = "This spell fires several, slow moving, magic projectiles at nearby targets."
+
+ school = "evocation"
+ charge_max = 400
+ clothes_req = 0
+ invocation = "none"
+ invocation_type = "none"
+ proj_lifespan = 10
+ max_targets = 6
diff --git a/code/datums/spells/dumbfire.dm b/code/datums/spells/dumbfire.dm
index 4a466d1663a..e5f67e32a82 100644
--- a/code/datums/spells/dumbfire.dm
+++ b/code/datums/spells/dumbfire.dm
@@ -64,7 +64,7 @@
break
var/mob/living/L = locate(/mob/living) in range(projectile, proj_trigger_range) - usr
- if(L)
+ if(L && L.stat != DEAD)
projectile.cast(L.loc)
break
diff --git a/code/datums/spells/ethereal_jaunt.dm b/code/datums/spells/ethereal_jaunt.dm
index 2ec9a723678..9991e8d676c 100644
--- a/code/datums/spells/ethereal_jaunt.dm
+++ b/code/datums/spells/ethereal_jaunt.dm
@@ -8,8 +8,9 @@
invocation = "none"
invocation_type = "none"
range = -1
+ cooldown_min = 100 //50 deciseconds reduction per rank
include_user = 1
- centcomm_cancast = 0 //Prevent people from getting to centcomm
+ centcom_cancast = 0 //Prevent people from getting to centcom
var phaseshift = 0
var/jaunt_duration = 50 //in deciseconds
@@ -27,6 +28,9 @@
animation.icon_state = "liquify"
animation.layer = 5
animation.master = holder
+ target.ExtinguishMob()
+ if(target.buckled)
+ target.buckled.unbuckle()
if(phaseshift == 1)
animation.dir = target.dir
flick("phase_shift",animation)
diff --git a/code/datums/spells/genetic.dm b/code/datums/spells/genetic.dm
index cff51ec6ff3..e0d9b2d5b80 100644
--- a/code/datums/spells/genetic.dm
+++ b/code/datums/spells/genetic.dm
@@ -18,13 +18,11 @@
/obj/effect/proc_holder/spell/targeted/genetic/cast(list/targets)
for(var/mob/living/target in targets)
- for(var/x in mutations)
- target.mutations.Add(x)
+ target.mutations.Add(mutations)
target.disabilities |= disabilities
target.update_mutations() //update target's mutation overlays
spawn(duration)
- for(var/x in mutations)
- target.mutations.Remove(x)
+ target.mutations.Remove(mutations)
target.disabilities &= ~disabilities
target.update_mutations()
diff --git a/code/datums/spells/horsemask.dm b/code/datums/spells/horsemask.dm
index f3ecc121516..30ddb9b1577 100644
--- a/code/datums/spells/horsemask.dm
+++ b/code/datums/spells/horsemask.dm
@@ -10,6 +10,7 @@
invocation = "KN'A FTAGHU, PUCK 'BTHNK!"
invocation_type = "shout"
range = 7
+ cooldown_min = 30 //30 deciseconds reduction per rank
selection_type = "range"
var/list/compatible_mobs = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
@@ -34,6 +35,7 @@
magichead.voicechange = 1 //NEEEEIIGHH
target.visible_message( "[target]'s face lights up in fire, and after the event a horse's head takes its place!", \
"Your face burns up, and shortly after the fire you realise you have the face of a horse!")
- target.equip_to_slot(magichead, slot_wear_mask)
+ target.drop_from_inventory(target.wear_mask)
+ target.equip_to_slot_if_possible(magichead, slot_wear_mask, 1, 1)
flick("e_flash", target.flash)
diff --git a/code/datums/spells/inflict_handler.dm b/code/datums/spells/inflict_handler.dm
index ac85b18ae3b..342c4720e77 100644
--- a/code/datums/spells/inflict_handler.dm
+++ b/code/datums/spells/inflict_handler.dm
@@ -17,6 +17,8 @@
var/destroys = "none" //can be "none", "gib" or "disintegrate"
+ var/summon_type = null //this will put an obj at the target's location
+
/obj/effect/proc_holder/spell/targeted/inflict_handler/cast(list/targets)
for(var/mob/living/target in targets)
@@ -56,4 +58,7 @@
target.Stun(amt_stunned)
target.eye_blind += amt_eye_blind
- target.eye_blurry += amt_eye_blurry
\ No newline at end of file
+ target.eye_blurry += amt_eye_blurry
+ //summoning
+ if(summon_type)
+ new summon_type(target.loc, target)
\ No newline at end of file
diff --git a/code/datums/spells/knock.dm b/code/datums/spells/knock.dm
index a67eefe65f4..b96c96455a8 100644
--- a/code/datums/spells/knock.dm
+++ b/code/datums/spells/knock.dm
@@ -8,6 +8,7 @@
invocation = "AULIE OXIN FIERA"
invocation_type = "whisper"
range = 3
+ cooldown_min = 20 //20 deciseconds reduction per rank
/obj/effect/proc_holder/spell/aoe_turf/knock/cast(list/targets)
for(var/turf/T in targets)
diff --git a/code/datums/spells/mind_transfer.dm b/code/datums/spells/mind_transfer.dm
index c8952cc8a91..7284ec29e09 100644
--- a/code/datums/spells/mind_transfer.dm
+++ b/code/datums/spells/mind_transfer.dm
@@ -8,6 +8,7 @@
invocation = "GIN'YU CAPAN"
invocation_type = "whisper"
range = 1
+ cooldown_min = 200 //100 deciseconds reduction per rank
var/list/protected_roles = list("Wizard","Changeling","Cultist") //which roles are immune to the spell
var/list/compatible_mobs = list(/mob/living/carbon/human,/mob/living/carbon/monkey) //which types of mobs are affected by the spell. NOTE: change at your own risk
var/base_spell_loss_chance = 20 //base probability of the wizard losing a spell in the process
diff --git a/code/datums/spells/projectile.dm b/code/datums/spells/projectile.dm
index 5d5ba5e1f8e..1df999cecce 100644
--- a/code/datums/spells/projectile.dm
+++ b/code/datums/spells/projectile.dm
@@ -57,6 +57,9 @@
else
step(projectile,dir)
+ if(!projectile) // step and step_to sleeps so we'll have to check again.
+ break
+
if(!proj_lingering && projectile.loc == current_loc) //if it didn't move since last time
del(projectile)
break
diff --git a/code/datums/spells/wizard.dm b/code/datums/spells/wizard.dm
index 6e9db54b477..f02a6fc33a7 100644
--- a/code/datums/spells/wizard.dm
+++ b/code/datums/spells/wizard.dm
@@ -8,6 +8,7 @@
invocation = "FORTI GY AMA"
invocation_type = "shout"
range = 7
+ cooldown_min = 90 //15 deciseconds reduction per rank
max_targets = 0
@@ -42,6 +43,7 @@
mutations = list(LASER, HULK)
duration = 300
+ cooldown_min = 300 //25 deciseconds reduction per rank
/obj/effect/proc_holder/spell/targeted/inflict_handler/disintegrate
name = "Disintegrate"
@@ -53,6 +55,7 @@
invocation = "EI NATH"
invocation_type = "shout"
range = 1
+ cooldown_min = 200 //100 deciseconds reduction per rank
destroys = "gib_brain"
@@ -70,6 +73,7 @@
invocation_type = "none"
range = -1
include_user = 1
+ cooldown_min = 20 //25 deciseconds reduction per rank
smoke_spread = 2
smoke_amt = 10
@@ -83,6 +87,7 @@
invocation_type = "shout"
range = -1
include_user = 1
+ cooldown_min = 200 //50 deciseconds reduction per rank
emp_heavy = 6
emp_light = 10
@@ -98,6 +103,8 @@
invocation_type = "none"
range = -1
include_user = 1
+ cooldown_min = 5 //4 deciseconds reduction per rank
+
smoke_spread = 1
smoke_amt = 10
@@ -105,7 +112,7 @@
inner_tele_radius = 0
outer_tele_radius = 6
- centcomm_cancast = 0 //prevent people from getting to centcomm
+ centcom_cancast = 0 //prevent people from getting to centcom
/obj/effect/proc_holder/spell/targeted/area_teleport/teleport
name = "Teleport"
@@ -118,6 +125,7 @@
invocation_type = "shout"
range = -1
include_user = 1
+ cooldown_min = 200 //100 deciseconds reduction per rank
smoke_spread = 1
smoke_amt = 5
@@ -132,6 +140,7 @@
invocation = "TARCOL MINTI ZHERI"
invocation_type = "whisper"
range = 0
+ cooldown_min = 50 //12 deciseconds reduction per rank
summon_type = list("/obj/effect/forcefield")
summon_lifespan = 300
@@ -189,6 +198,7 @@
invocation = "STI KALY"
invocation_type = "whisper"
message = "\blue Your eyes cry out in pain!"
+ cooldown_min = 50 //12 deciseconds reduction per rank
starting_spells = list("/obj/effect/proc_holder/spell/targeted/inflict_handler/blind","/obj/effect/proc_holder/spell/targeted/genetic/blind")
@@ -200,16 +210,32 @@
disabilities = 1
duration = 300
+/obj/effect/proc_holder/spell/targeted/inflict_handler/flesh_to_stone
+ name = "Flesh to Stone"
+ desc = "This spell turns a single person into an inert statue for a long period of time."
+
+ school = "transmutation"
+ charge_max = 600
+ clothes_req = 1
+ range = 2
+ invocation = "STAUN EI"
+ invocation_type = "shout"
+ amt_stunned = 2//just exists to make sure the statue "catches" them
+ cooldown_min = 200 //100 deciseconds reduction per rank
+
+ summon_type = "/obj/structure/closet/statue"
+
/obj/effect/proc_holder/spell/dumbfire/fireball
name = "Fireball"
desc = "This spell fires a fireball at a target and does not require wizard garb."
school = "evocation"
- charge_max = 100
+ charge_max = 60
clothes_req = 0
invocation = "ONI SOMA"
invocation_type = "shout"
range = 20
+ cooldown_min = 20 //10 deciseconds reduction per rank
proj_icon_state = "fireball"
proj_name = "a fireball"
@@ -219,7 +245,7 @@
proj_step_delay = 1
/obj/effect/proc_holder/spell/turf/fireball/cast(var/turf/T)
- explosion(T, -1, 1, 2, 3)
+ explosion(T, -1, 0, 2, 3, 0, flame_range = 2)
/obj/effect/proc_holder/spell/targeted/inflict_handler/fireball
@@ -230,98 +256,4 @@
ex_severe = -1
ex_heavy = -1
ex_light = 2
- ex_flash = 5
-
-
-
-
-
-
-//////////////////////////////Construct Spells/////////////////////////
-
-/obj/effect/proc_holder/spell/aoe_turf/conjure/construct/lesser
- charge_max = 1800
-
-/obj/effect/proc_holder/spell/aoe_turf/conjure/floor
- name = "Floor Construction"
- desc = "This spell constructs a cult floor"
-
- school = "conjuration"
- charge_max = 20
- clothes_req = 0
- invocation = "none"
- invocation_type = "none"
- range = 0
- summon_type = list(/turf/simulated/floor/engine/cult)
- centcomm_cancast = 0 //Stop crashing the server by spawning turfs on transit tiles
-
-/obj/effect/proc_holder/spell/aoe_turf/conjure/wall
- name = "Leser Construction"
- desc = "This spell constructs a cult wall"
-
- school = "conjuration"
- charge_max = 100
- clothes_req = 0
- invocation = "none"
- invocation_type = "none"
- range = 0
- summon_type = list(/turf/simulated/wall/cult)
- centcomm_cancast = 0 //Stop crashing the server by spawning turfs on transit tiles
-
-/obj/effect/proc_holder/spell/aoe_turf/conjure/wall/reinforced
- name = "Greater Construction"
- desc = "This spell constructs a reinforced metal wall"
-
- school = "conjuration"
- charge_max = 300
- clothes_req = 0
- invocation = "none"
- invocation_type = "none"
- range = 0
- centcomm_cancast = 0 //Stop crashing the server by spawning turfs on transit tiles
- delay = 50
-
- summon_type = list(/turf/simulated/wall/r_wall)
-
-/obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone
- name = "Summon Soulstone"
- desc = "This spell reaches into Nar-Sie's realm, summoning one of the legendary fragments across time and space"
-
- school = "conjuration"
- charge_max = 3000
- clothes_req = 0
- invocation = "none"
- invocation_type = "none"
- range = 0
-
- summon_type = list(/obj/item/device/soulstone)
-
-
-/obj/effect/proc_holder/spell/aoe_turf/conjure/lesserforcewall
- name = "Shield"
- desc = "This spell creates a temporary forcefield to shield yourself and allies from incoming fire"
-
- school = "transmutation"
- charge_max = 300
- clothes_req = 0
- invocation = "none"
- invocation_type = "none"
- range = 0
- summon_type = list(/obj/effect/forcefield)
- summon_lifespan = 50
-
-
-/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift
- name = "Phase Shift"
- desc = "This spell allows you to pass through walls"
-
- school = "transmutation"
- charge_max = 200
- clothes_req = 0
- invocation = "none"
- invocation_type = "none"
- range = -1
- include_user = 1
- phaseshift = 1
- jaunt_duration = 50 //in deciseconds
- centcomm_cancast = 0 //Stop people from getting to centcomm
\ No newline at end of file
+ ex_flash = 5
\ No newline at end of file
diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm
index 6cedd5722fb..3150f2c09cd 100755
--- a/code/datums/supplypacks.dm
+++ b/code/datums/supplypacks.dm
@@ -611,8 +611,8 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/datum/supply_packs/weapons
name = "Weapons crate"
- contains = list(/obj/item/weapon/melee/baton,
- /obj/item/weapon/melee/baton,
+ contains = list(/obj/item/weapon/melee/baton/loaded,
+ /obj/item/weapon/melee/baton/loaded,
/obj/item/weapon/gun/energy/laser,
/obj/item/weapon/gun/energy/laser,
/obj/item/weapon/gun/energy/taser,
@@ -654,9 +654,9 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/datum/supply_packs/riot
name = "Riot gear crate"
- contains = list(/obj/item/weapon/melee/baton,
- /obj/item/weapon/melee/baton,
- /obj/item/weapon/melee/baton,
+ contains = list(/obj/item/weapon/melee/baton/loaded,
+ /obj/item/weapon/melee/baton/loaded,
+ /obj/item/weapon/melee/baton/loaded,
/obj/item/weapon/shield/riot,
/obj/item/weapon/shield/riot,
/obj/item/weapon/shield/riot,
@@ -1006,3 +1006,39 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
containername = "Beekeeping crate"
access = access_hydroponics
group = "Hydroponics"
+
+
+/datum/supply_packs/organic/vending
+ name = "Bartending Supply Crate"
+ contains = list(/obj/item/weapon/vending_refill/boozeomat,
+ /obj/item/weapon/vending_refill/coffee)
+ cost = 15
+ containername = "bartending supply crate"
+
+/datum/supply_packs/organic/vending/snack
+ name = "Snack Supply Crate"
+ contains = list(/obj/item/weapon/vending_refill/snack,
+ /obj/item/weapon/vending_refill/snack,
+ /obj/item/weapon/vending_refill/snack)
+ cost = 15
+ containername = "snacks supply crate"
+
+/datum/supply_packs/organic/vending/cola
+ name = "Softdrinks Supply Crate"
+ contains = list(/obj/item/weapon/vending_refill/cola,
+ /obj/item/weapon/vending_refill/cola)
+ cost = 15
+ containername = "softdrinks supply crate"
+
+/datum/supply_packs/organic/vending/cigarette
+ name = "Cigarette Supply Crate"
+ contains = list(/obj/item/weapon/vending_refill/cigarette)
+ cost = 15
+ containername = "cigarette supply crate"
+
+/datum/supply_packs/misc/autodrobe
+ name = "Autodrobe Supply crate"
+ contains = list(/obj/item/weapon/vending_refill/autodrobe,
+ /obj/item/weapon/vending_refill/autodrobe)
+ cost = 15
+ containername = "autodrobe supply crate"
diff --git a/code/defines/obj.dm b/code/defines/obj.dm
index 702b6c64c31..c3d6102ca76 100644
--- a/code/defines/obj.dm
+++ b/code/defines/obj.dm
@@ -51,122 +51,194 @@
//This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character().
var/locked[] = list()
- proc/get_manifest(monochrome, OOC)
- var/list/heads = new()
- var/list/sec = new()
- var/list/eng = new()
- var/list/med = new()
- var/list/sci = new()
- var/list/civ = new()
- var/list/bot = new()
- var/list/misc = new()
- var/list/isactive = new()
- var/dat = {"
-
-
- | Name | Rank | Activity |
- "}
- var/even = 0
-
- // sort mobs
- for(var/datum/data/record/t in data_core.general)
- var/name = t.fields["name"]
- var/rank = t.fields["rank"]
- var/real_rank = t.fields["real_rank"]
- if(OOC)
- var/active = 0
- for(var/mob/M in player_list)
- if(M.real_name == name && M.client && M.client.inactivity <= 10 * 60 * 10)
- active = 1
- break
- isactive[name] = active ? "Active" : "Inactive"
- else
- isactive[name] = t.fields["p_stat"]
+/obj/effect/datacore/proc/get_manifest(monochrome, OOC)
+ var/list/heads = new()
+ var/list/sec = new()
+ var/list/eng = new()
+ var/list/med = new()
+ var/list/sci = new()
+ var/list/civ = new()
+ var/list/bot = new()
+ var/list/misc = new()
+ var/list/isactive = new()
+ var/dat = {"
+
+
+ | Name | Rank | Activity |
+ "}
+ var/even = 0
+ // sort mobs
+ for(var/datum/data/record/t in data_core.general)
+ var/name = t.fields["name"]
+ var/rank = t.fields["rank"]
+ var/real_rank = t.fields["real_rank"]
+ if(OOC)
+ var/active = 0
+ for(var/mob/M in player_list)
+ if(M.real_name == name && M.client && M.client.inactivity <= 10 * 60 * 10)
+ active = 1
+ break
+ isactive[name] = active ? "Active" : "Inactive"
+ else
+ isactive[name] = t.fields["p_stat"]
//world << "[name]: [rank]"
-
//cael - to prevent multiple appearances of a player/job combination, add a continue after each line
- var/department = 0
- if(real_rank in command_positions)
- heads[name] = rank
- department = 1
- if(real_rank in security_positions)
- sec[name] = rank
- department = 1
- if(real_rank in engineering_positions)
- eng[name] = rank
- department = 1
- if(real_rank in medical_positions)
- med[name] = rank
- department = 1
- if(real_rank in science_positions)
- sci[name] = rank
- department = 1
- if(real_rank in civilian_positions)
- civ[name] = rank
- department = 1
- if(real_rank in nonhuman_positions)
- bot[name] = rank
- department = 1
+ var/department = 0
+ if(real_rank in command_positions)
+ heads[name] = rank
+ department = 1
+ if(real_rank in security_positions)
+ sec[name] = rank
+ department = 1
+ if(real_rank in engineering_positions)
+ eng[name] = rank
+ department = 1
+ if(real_rank in medical_positions)
+ med[name] = rank
+ department = 1
+ if(real_rank in science_positions)
+ sci[name] = rank
+ department = 1
+ if(real_rank in civilian_positions)
+ civ[name] = rank
+ department = 1
+ if(real_rank in nonhuman_positions)
+ bot[name] = rank
+ department = 1
+ if(!department && !(name in heads))
+ misc[name] = rank
+ if(heads.len > 0)
+ dat += "| Heads |
"
+ for(name in heads)
+ dat += "| [name] | [heads[name]] | [isactive[name]] |
"
+ even = !even
+ if(sec.len > 0)
+ dat += "| Security |
"
+ for(name in sec)
+ dat += "| [name] | [sec[name]] | [isactive[name]] |
"
+ even = !even
+ if(eng.len > 0)
+ dat += "| Engineering |
"
+ for(name in eng)
+ dat += "| [name] | [eng[name]] | [isactive[name]] |
"
+ even = !even
+ if(med.len > 0)
+ dat += "| Medical |
"
+ for(name in med)
+ dat += "| [name] | [med[name]] | [isactive[name]] |
"
+ even = !even
+ if(sci.len > 0)
+ dat += "| Science |
"
+ for(name in sci)
+ dat += "| [name] | [sci[name]] | [isactive[name]] |
"
+ even = !even
+ if(civ.len > 0)
+ dat += "| Civilian |
"
+ for(name in civ)
+ dat += "| [name] | [civ[name]] | [isactive[name]] |
"
+ even = !even
+ // in case somebody is insane and added them to the manifest, why not
+ if(bot.len > 0)
+ dat += "| Silicon |
"
+ for(name in bot)
+ dat += "| [name] | [bot[name]] | [isactive[name]] |
"
+ even = !even
+ // misc guys
+ if(misc.len > 0)
+ dat += "| Miscellaneous |
"
+ for(name in misc)
+ dat += "| [name] | [misc[name]] | [isactive[name]] |
"
+ even = !even
- if(!department && !(name in heads))
- misc[name] = rank
-
- if(heads.len > 0)
- dat += "| Heads |
"
- for(name in heads)
- dat += "| [name] | [heads[name]] | [isactive[name]] |
"
- even = !even
- if(sec.len > 0)
- dat += "| Security |
"
- for(name in sec)
- dat += "| [name] | [sec[name]] | [isactive[name]] |
"
- even = !even
- if(eng.len > 0)
- dat += "| Engineering |
"
- for(name in eng)
- dat += "| [name] | [eng[name]] | [isactive[name]] |
"
- even = !even
- if(med.len > 0)
- dat += "| Medical |
"
- for(name in med)
- dat += "| [name] | [med[name]] | [isactive[name]] |
"
- even = !even
- if(sci.len > 0)
- dat += "| Science |
"
- for(name in sci)
- dat += "| [name] | [sci[name]] | [isactive[name]] |
"
- even = !even
- if(civ.len > 0)
- dat += "| Civilian |
"
- for(name in civ)
- dat += "| [name] | [civ[name]] | [isactive[name]] |
"
- even = !even
- // in case somebody is insane and added them to the manifest, why not
- if(bot.len > 0)
- dat += "| Silicon |
"
- for(name in bot)
- dat += "| [name] | [bot[name]] | [isactive[name]] |
"
- even = !even
- // misc guys
- if(misc.len > 0)
- dat += "| Miscellaneous |
"
- for(name in misc)
- dat += "| [name] | [misc[name]] | [isactive[name]] |
"
- even = !even
+ dat += "
"
+ dat = replacetext(dat, "\n", "") // so it can be placed on paper correctly
+ dat = replacetext(dat, "\t", "")
+ return dat
- dat += "
"
- dat = replacetext(dat, "\n", "") // so it can be placed on paper correctly
- dat = replacetext(dat, "\t", "")
- return dat
+/*
+We can't just insert in HTML into the nanoUI so we need the raw data to play with.
+*/
+
+/obj/effect/datacore/proc/get_manifest_json()
+ var/heads[0]
+ var/sec[0]
+ var/eng[0]
+ var/med[0]
+ var/sci[0]
+ var/civ[0]
+ var/bot[0]
+ var/misc[0]
+ for(var/datum/data/record/t in data_core.general)
+ var/name = t.fields["name"]
+ var/rank = t.fields["rank"]
+ var/real_rank = t.fields["real_rank"]
+ var/isactive = t.fields["p_stat"]
+ var/department = 0
+ var/depthead = 0 // Department Heads will be placed at the top of their lists.
+ if(real_rank in command_positions)
+ heads[++heads.len] = list("name" = name, "rank" = rank, "active" = isactive)
+ department = 1
+ depthead = 1
+ if(rank=="Captain" && heads.len != 1)
+ heads.Swap(1,heads.len)
+
+ if(real_rank in security_positions)
+ sec[++sec.len] = list("name" = name, "rank" = rank, "active" = isactive)
+ department = 1
+ if(depthead && sec.len != 1)
+ sec.Swap(1,sec.len)
+
+ if(real_rank in engineering_positions)
+ eng[++eng.len] = list("name" = name, "rank" = rank, "active" = isactive)
+ department = 1
+ if(depthead && eng.len != 1)
+ eng.Swap(1,eng.len)
+
+ if(real_rank in medical_positions)
+ med[++med.len] = list("name" = name, "rank" = rank, "active" = isactive)
+ department = 1
+ if(depthead && med.len != 1)
+ med.Swap(1,med.len)
+
+ if(real_rank in science_positions)
+ sci[++sci.len] = list("name" = name, "rank" = rank, "active" = isactive)
+ department = 1
+ if(depthead && sci.len != 1)
+ sci.Swap(1,sci.len)
+
+ if(real_rank in civilian_positions)
+ civ[++civ.len] = list("name" = name, "rank" = rank, "active" = isactive)
+ department = 1
+ if(depthead && civ.len != 1)
+ civ.Swap(1,civ.len)
+
+ if(real_rank in nonhuman_positions)
+ bot[++bot.len] = list("name" = name, "rank" = rank, "active" = isactive)
+ department = 1
+
+ if(!department && !(name in heads))
+ misc[++misc.len] = list("name" = name, "rank" = rank, "active" = isactive)
+
+ return list(\
+ "heads" = heads,\
+ "sec" = sec,\
+ "eng" = eng,\
+ "med" = med,\
+ "sci" = sci,\
+ "civ" = civ,\
+ "bot" = bot,\
+ "misc" = misc\
+ )
+
/obj/effect/laser
name = "laser"
diff --git a/code/defines/obj/hydro.dm b/code/defines/obj/hydro.dm
index b2854f21d36..dd5d2a5edb4 100644
--- a/code/defines/obj/hydro.dm
+++ b/code/defines/obj/hydro.dm
@@ -1111,6 +1111,107 @@
del(src)
+/obj/item/seeds/coffee_arabica_seed
+ name = "pack of coffee arabica seeds"
+ desc = "These seeds grow into coffee arabica bushes."
+ icon_state = "seed-coffeea"
+ species = "coffeea"
+ plantname = "Coffee Arabica Bush"
+ productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/coffee_arabica"
+ lifespan = 30
+ endurance = 20
+ maturation = 5
+ production = 5
+ yield = 5
+ potency = 10
+ plant_type = 0
+ growthstages = 5
+// mutatelist = list(/obj/item/seeds/coffee_robusta_seed)
+
+/obj/item/seeds/coffee_robusta_seed
+ name = "pack of coffee robusta seeds"
+ desc = "These seeds grow into coffee robusta bushes."
+ icon_state = "seed-coffeer"
+ species = "coffeer"
+ plantname = "Coffee Robusta Bush"
+ productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/coffee_robusta"
+ lifespan = 20
+ endurance = 15
+ maturation = 5
+ production = 5
+ yield = 5
+ potency = 10
+ plant_type = 0
+ growthstages = 5
+
+/obj/item/seeds/tobacco_seed
+ name = "pack of tobacco seeds"
+ desc = "These seeds grow into tobacco plants."
+ icon_state = "seed-tobacco"
+ species = "tobacco"
+ plantname = "Tobacco Plant"
+ productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/tobacco"
+ lifespan = 20
+ endurance = 15
+ maturation = 5
+ production = 5
+ oneharvest = 1
+ yield = 10
+ potency = 10
+ plant_type = 0
+ growthstages = 3
+// mutatelist = list(/obj/item/seeds/tobacco_space_seed)
+
+/obj/item/seeds/tobacco_space_seed
+ name = "pack of space tobacco seeds"
+ desc = "These seeds grow into space tobacco plants."
+ icon_state = "seed-stobacco"
+ species = "stobacco"
+ plantname = "Space Tobacco Plant"
+ productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/tobacco_space"
+ lifespan = 20
+ endurance = 15
+ maturation = 5
+ production = 5
+ oneharvest = 1
+ yield = 10
+ potency = 10
+ plant_type = 0
+ growthstages = 3
+
+/obj/item/seeds/tea_aspera_seed
+ name = "pack of tea aspera seeds"
+ desc = "These seeds grow into tea plants."
+ icon_state = "seed-teaaspera"
+ species = "teaaspera"
+ plantname = "Tea Aspera Plant"
+ productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/tea_aspera"
+ lifespan = 20
+ endurance = 15
+ maturation = 5
+ production = 5
+ yield = 5
+ potency = 10
+ plant_type = 0
+ growthstages = 5
+// mutatelist = list(/obj/item/seeds/tea_astra_seed)
+
+/obj/item/seeds/tea_astra_seed
+ name = "pack of tea astra seeds"
+ desc = "These seeds grow into tea plants."
+ icon_state = "seed-teaastra"
+ species = "teaastra"
+ plantname = "Tea Astra Plant"
+ productname = "/obj/item/weapon/reagent_containers/food/snacks/grown/tea_astra"
+ lifespan = 20
+ endurance = 15
+ maturation = 5
+ production = 5
+ yield = 5
+ potency = 10
+ plant_type = 0
+ growthstages = 5
+
/* // Maybe one day when I get it to work like a grenade which exlodes gibs.
/obj/item/seeds/gibtomatoseed
diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm
index 75d3e402f8a..753e6f1f099 100644
--- a/code/game/area/Space Station 13 areas.dm
+++ b/code/game/area/Space Station 13 areas.dm
@@ -542,6 +542,46 @@ proc/process_ghost_teleport_locs()
icon_state = "north"
requires_power = 0
+/area/xenos_station/start
+ name = "\improper start area"
+ icon_state = "north"
+ requires_power = 0
+
+/area/xenos_station/transit
+ name = "\improper hyperspace"
+ icon_state = "shuttle"
+ requires_power = 0
+
+/area/xenos_station/southwest
+ name = "\improper aft port solars"
+ icon_state = "southwest"
+ requires_power = 0
+
+/area/xenos_station/northwest
+ name = "\improper fore port solars"
+ icon_state = "northwest"
+ requires_power = 0
+
+/area/xenos_station/northeast
+ name = "\improper fore starboard solars"
+ icon_state = "northeast"
+ requires_power = 0
+
+/area/xenos_station/southeast
+ name = "\improper aft starboard solars"
+ icon_state = "southeast"
+ requires_power = 0
+
+/area/xenos_station/north
+ name = "\improper north landing area"
+ icon_state = "north"
+ requires_power = 0
+
+/area/xenos_station/south
+ name = "\improper south landing area"
+ icon_state = "south"
+ requires_power = 0
+
//PRISON
/area/prison
name = "\improper Prison Station"
@@ -876,8 +916,8 @@ proc/process_ghost_teleport_locs()
name = "\improper Bar"
icon_state = "bar"
-/area/crew_quarters/theatre
- name = "\improper Theatre"
+/area/crew_quarters/mrchangs
+ name = "\improper Mr Chang's"
icon_state = "Theatre"
/area/library
@@ -1234,7 +1274,10 @@ proc/process_ghost_teleport_locs()
/area/security/armoury
name = "\improper Armory"
icon_state = "Warden"
-
+/area/security/armoury/gamma
+ name = "\improper Gamma Armory"
+ icon_state = "Warden"
+ requires_power = 0
/area/security/hos
name = "\improper Head of Security's Office"
icon_state = "sec_hos"
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index d561875973d..0f57c7f736a 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -66,13 +66,31 @@
a.triggerAlarm("Power", src, cameras, source)
return
-/area/proc/atmosalert(danger_level)
+/area/proc/updateDangerLevel()
// if(type==/area) //No atmos alarms in space
// return 0 //redudant
+
+
+ var/danger_level = 0
+
+ // Determine what the highest DL reported by air alarms is
+ for (var/area/RA in related)
+ for(var/obj/machinery/alarm/AA in RA)
+ if((AA.stat & (NOPOWER|BROKEN)) || AA.shorted || AA.buildstage != 2)
+ continue
+ var/reported_danger_level=AA.local_danger_level
+ if(AA.alarmActivated)
+ reported_danger_level=2
+ if(reported_danger_level>danger_level)
+ danger_level=reported_danger_level
+ testing("Danger level at [AA.name]: [AA.local_danger_level] (reported [reported_danger_level])")
+
+ testing("Danger level decided upon in [name]: [danger_level] (from [atmosalm])")
+
+ // Danger level change?
if(danger_level != atmosalm)
- //updateicon()
- //mouse_opacity = 0
- if (danger_level==2)
+ // Going to danger level 2 from something else
+ if (danger_level == 2)
var/list/cameras = list()
for(var/area/RA in related)
//updateicon()
@@ -83,6 +101,8 @@
aiPlayer.triggerAlarm("Atmosphere", src, cameras, src)
for(var/obj/machinery/computer/station_alert/a in machines)
a.triggerAlarm("Atmosphere", src, cameras, src)
+ CloseFirelocks()
+ // Dropping from danger level 2.
else if (atmosalm == 2)
for(var/area/RA in related)
for(var/obj/machinery/camera/C in RA)
@@ -91,6 +111,7 @@
aiPlayer.cancelAlarm("Atmosphere", src, src)
for(var/obj/machinery/computer/station_alert/a in machines)
a.cancelAlarm("Atmosphere", src, src)
+ OpenFirelocks()
atmosalm = danger_level
for (var/obj/machinery/alarm/AA in src)
if ( !(AA.stat & (NOPOWER|BROKEN)) && !AA.shorted)
@@ -98,6 +119,24 @@
return 1
return 0
+/area/proc/CloseFirelocks()
+ for(var/obj/machinery/door/firedoor/D in all_doors)
+ if(!D.blocked)
+ if(D.operating)
+ D.nextstate = CLOSED
+ else if(!D.density)
+ spawn()
+ D.close()
+
+/area/proc/OpenFirelocks()
+ for(var/obj/machinery/door/firedoor/D in all_doors)
+ if(!D.blocked)
+ if(D.operating)
+ D.nextstate = OPEN
+ else if(D.density)
+ spawn()
+ D.open()
+
/area/proc/firealert()
if(name == "Space") //no fire alarms in space
return
@@ -105,13 +144,7 @@
fire = 1
updateicon()
mouse_opacity = 0
- for(var/obj/machinery/door/firedoor/D in all_doors)
- if(!D.blocked)
- if(D.operating)
- D.nextstate = CLOSED
- else if(!D.density)
- spawn()
- D.close()
+ CloseFirelocks()
var/list/cameras = list()
for(var/area/RA in related)
for (var/obj/machinery/camera/C in RA)
@@ -127,13 +160,6 @@
fire = 0
mouse_opacity = 0
updateicon()
- for(var/obj/machinery/door/firedoor/D in all_doors)
- if(!D.blocked)
- if(D.operating)
- D.nextstate = OPEN
- else if(D.density)
- spawn(0)
- D.open()
for(var/area/RA in related)
for (var/obj/machinery/camera/C in RA)
C.network.Remove("Fire Alarms")
@@ -141,20 +167,7 @@
aiPlayer.cancelAlarm("Fire", src, src)
for (var/obj/machinery/computer/station_alert/a in machines)
a.cancelAlarm("Fire", src, src)
-
-/area/proc/readyalert()
- if(name == "Space")
- return
- if(!eject)
- eject = 1
- updateicon()
- return
-
-/area/proc/readyreset()
- if(eject)
- eject = 0
- updateicon()
- return
+ OpenFirelocks()
/area/proc/radiation_alert()
if(name == "Space")
@@ -172,6 +185,20 @@
updateicon()
return
+/area/proc/readyalert()
+ if(name == "Space")
+ return
+ if(!eject)
+ eject = 1
+ updateicon()
+ return
+
+/area/proc/readyreset()
+ if(eject)
+ eject = 0
+ updateicon()
+ return
+
/area/proc/partyalert()
if(name == "Space") //no parties in space!!!
return
@@ -186,13 +213,6 @@
party = 0
mouse_opacity = 0
updateicon()
- for(var/obj/machinery/door/firedoor/D in src)
- if(!D.blocked)
- if(D.operating)
- D.nextstate = OPEN
- else if(D.density)
- spawn(0)
- D.open()
return
/area/proc/updateicon()
@@ -200,19 +220,25 @@
// Highest priority at the top.
if(radalert && !fire)
icon_state = "radiation"
+ blend_mode = BLEND_MULTIPLY
else if(fire && !radalert && !eject && !party)
- icon_state = "blue"
+ icon_state = "red"
+ blend_mode = BLEND_MULTIPLY
/*else if(atmosalm && !fire && !eject && !party)
icon_state = "bluenew"*/
else if(!fire && eject && !party)
icon_state = "red"
+ blend_mode = BLEND_MULTIPLY
else if(party && !fire && !eject)
icon_state = "party"
+ blend_mode = BLEND_MULTIPLY
else
icon_state = "blue-red"
+ blend_mode = BLEND_MULTIPLY
else
// new lighting behaviour with obj lights
icon_state = null
+ blend_mode = BLEND_DEFAULT
/*
@@ -267,7 +293,15 @@
master.used_environ = 0
/area/proc/use_power(var/amount, var/chan)
+ switch(chan)
+ if(EQUIP)
+ master.used_equip += amount
+ if(LIGHT)
+ master.used_light += amount
+ if(ENVIRON)
+ master.used_environ += amount
+/area/proc/use_battery_power(var/amount, var/chan)
switch(chan)
if(EQUIP)
master.used_equip += amount
diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm
index 4f4adf9bee4..454a8b03f4c 100644
--- a/code/game/dna/dna_modifier.dm
+++ b/code/game/dna/dna_modifier.dm
@@ -128,10 +128,17 @@
|| locate(/obj/machinery/computer/cloning, get_step(src, WEST)))
if(!M.client && M.mind)
- for(var/mob/dead/observer/ghost in player_list)
- if(ghost.mind == M.mind)
- ghost << "Your corpse has been placed into a cloning scanner. Return to your body if you want to be resurrected/cloned! (Verbs -> Ghost -> Re-enter corpse)"
- break
+ message_admins("No client found, searching for compatible mind")
+ for(var/mob/C in respawnable_list)
+ if(C.mind && C.mind.key == M.mind.key)
+ message_admins("Found mind, asking for respawn")
+ switch(alert(C,"Your corpse has been placed into a cloning scanner. Do you want to be resurrected/cloned? Please not if you select 'No', you will be able to be cloned or borged again this round.","Clone Alert","Yes","No"))
+ if("Yes")
+ M.key = C.key
+ return
+ if("No")
+ return
+
del(G)
return
diff --git a/code/game/gamemodes/blob/blobs/core.dm b/code/game/gamemodes/blob/blobs/core.dm
index a3b658ce058..8eb6520bb01 100644
--- a/code/game/gamemodes/blob/blobs/core.dm
+++ b/code/game/gamemodes/blob/blobs/core.dm
@@ -82,6 +82,7 @@
C = new_overmind
if(C)
+ respawnable_list -= C
var/mob/camera/blob/B = new(src.loc)
B.key = C.key
B.blob_core = src
diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm
index c840c9bd4e0..e96fdf4029b 100644
--- a/code/game/gamemodes/changeling/changeling_powers.dm
+++ b/code/game/gamemodes/changeling/changeling_powers.dm
@@ -2,6 +2,7 @@
/mob/proc/make_changeling()
if(!mind) return
if(!mind.changeling) mind.changeling = new /datum/changeling(gender)
+ if(!ishuman(src) && !ismonkey(src)) return
verbs += /datum/changeling/proc/EvolutionMenu
var/lesser_form = !ishuman(src)
@@ -205,6 +206,10 @@
var/datum/changeling/changeling = changeling_power(1,0,0)
if(!changeling) return
+ if(src.has_brain_worms())
+ src << "We cannot perform this ability at the present time!"
+ return
+
var/mob/living/carbon/C = src
changeling.chem_charges--
C.remove_changeling_powers()
diff --git a/code/game/gamemodes/events.dm b/code/game/gamemodes/events.dm
index b9f68fb143c..a210143ac06 100644
--- a/code/game/gamemodes/events.dm
+++ b/code/game/gamemodes/events.dm
@@ -201,7 +201,7 @@
var/mob/living/carbon/alien/larva/new_xeno = new(vent.loc)
new_xeno.key = candidate
-
+ respawnable_list -= candidate
candidates -= candidate
vents -= vent
spawncount--
diff --git a/code/game/gamemodes/events/space_ninja.dm b/code/game/gamemodes/events/space_ninja.dm
index bfbdfc417f0..365c72dab3b 100644
--- a/code/game/gamemodes/events/space_ninja.dm
+++ b/code/game/gamemodes/events/space_ninja.dm
@@ -153,7 +153,7 @@ Malf AIs/silicons aren't added. Monkeys aren't added. Messes with objective comp
else
var/list/candidates = list() //list of candidate keys
- for(var/mob/dead/observer/G in player_list)
+ for(var/mob/G in respawnable_list)
if(G.client && !G.client.holder && !G.client.is_afk() && G.client.prefs.be_special & BE_NINJA)
if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD))
candidates += G
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index 33440ae4448..0f74c65dcee 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -26,12 +26,50 @@
var/required_players = 0
var/required_players_secret = 0 //Minimum number of players for that game mode to be chose in Secret
var/required_enemies = 0
+ var/recommended_players = 0
var/recommended_enemies = 0
var/newscaster_announcements = null
var/uplink_welcome = "Syndicate Uplink Console:"
var/uplink_uses = 10
-
-
+ var/uplink_items = {"Highly Visible and Dangerous Weapons;
+/obj/item/weapon/gun/projectile:6:Revolver;
+/obj/item/ammo_magazine/a357:2:Ammo-357;
+/obj/item/weapon/gun/energy/crossbow:5:Energy Crossbow;
+/obj/item/weapon/melee/energy/sword:4:Energy Sword;
+/obj/item/weapon/storage/box/syndicate:10:Syndicate Bundle;
+/obj/item/weapon/storage/box/emps:3:5 EMP Grenades;
+Whitespace:Seperator;
+Stealthy and Inconspicuous Weapons;
+/obj/item/weapon/pen/paralysis:3:Paralysis Pen;
+/obj/item/weapon/soap/syndie:1:Syndicate Soap;
+/obj/item/weapon/cartridge/syndicate:3:Detomatix PDA Cartridge;
+Whitespace:Seperator;
+Stealth and Camouflage Items;
+/obj/item/clothing/under/chameleon:3:Chameleon Jumpsuit;
+/obj/item/clothing/shoes/syndigaloshes:2:No-Slip Syndicate Shoes;
+/obj/item/weapon/card/id/syndicate:2:Agent ID card;
+/obj/item/clothing/mask/gas/voice:4:Voice Changer;
+/obj/item/device/chameleon:4:Chameleon-Projector;
+Whitespace:Seperator;
+Devices and Tools;
+/obj/item/weapon/card/emag:3:Cryptographic Sequencer;
+/obj/item/weapon/storage/toolbox/syndicate:1:Fully Loaded Toolbox;
+/obj/item/weapon/storage/box/syndie_kit/space:3:Space Suit;
+/obj/item/clothing/glasses/thermal/syndi:3:Thermal Imaging Glasses;
+/obj/item/device/encryptionkey/binary:3:Binary Translator Key;
+/obj/item/weapon/aiModule/syndicate:7:Hacked AI Upload Module;
+/obj/item/weapon/plastique:2:C-4 (Destroys walls);
+/obj/item/device/powersink:5:Powersink (DANGER!);
+/obj/item/device/radio/beacon/syndicate:7:Singularity Beacon (DANGER!);
+/obj/item/weapon/circuitboard/teleporter:20:Teleporter Circuit Board;
+Whitespace:Seperator;
+Implants;
+/obj/item/weapon/storage/box/syndie_kit/imp_freedom:3:Freedom Implant;
+/obj/item/weapon/storage/box/syndie_kit/imp_uplink:10:Uplink Implant (Contains 5 Telecrystals);
+/obj/item/weapon/storage/box/syndie_kit/imp_explosive:6:Explosive Implant (DANGER!);
+/obj/item/weapon/storage/box/syndie_kit/imp_compress:4:Compressed Matter Implant;Whitespace:Seperator;
+(Pointless) Badassery;
+/obj/item/toy/syndicateballoon:10:For showing that You Are The BOSS (Useless Balloon);"}
/datum/game_mode/proc/announce() //to be calles when round starts
world << "Notice: [src] did not define announce()"
@@ -69,8 +107,8 @@
feedback_set_details("round_start","[time2text(world.realtime)]")
if(ticker && ticker.mode)
feedback_set_details("game_mode","[ticker.mode]")
- if(revdata)
- feedback_set_details("revision","[revdata.revision]")
+// if(revdata)
+// feedback_set_details("revision","[revdata.revision]")
feedback_set_details("server_ip","[world.internet_address]:[world.port]")
return 1
diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm
index 0fc89e14dec..d5450da2507 100644
--- a/code/game/gamemodes/gameticker.dm
+++ b/code/game/gamemodes/gameticker.dm
@@ -172,7 +172,6 @@ var/global/datum/controller/gameticker/ticker
//initialise our cinematic screen object
cinematic = new(src)
- sleep(100)
cinematic.icon = 'icons/effects/station_explosion.dmi'
cinematic.icon_state = "station_intact"
cinematic.layer = 20
diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm
index c3720275ee2..3ec8719490e 100644
--- a/code/game/gamemodes/meteor/meteors.dm
+++ b/code/game/gamemodes/meteor/meteors.dm
@@ -1,5 +1,3 @@
-#define METEOR_TEMPERATURE
-
/var/const/meteor_wave_delay = 625 //minimum wait between waves in tenths of seconds
//set to at least 100 unless you want evarr ruining every round
@@ -95,18 +93,9 @@
icon_state = "smallf"
pass_flags = PASSTABLE | PASSGRILLE
-/obj/effect/meteor/Move()
- var/turf/T = src.loc
- if (istype(T, /turf))
- T.hotspot_expose(METEOR_TEMPERATURE, 1000)
- ..()
- return
-
/obj/effect/meteor/Bump(atom/A)
spawn(0)
- for(var/mob/M in range(10, src))
- if(!M.stat && !istype(M, /mob/living/silicon/ai)) //bad idea to shake an ai's view
- shake_camera(M, 3, 1)
+
if (A)
A.meteorhit(src)
playsound(src.loc, 'sound/effects/meteorimpact.ogg', 40, 1)
@@ -117,9 +106,7 @@
if(!istype(A,/obj/machinery/power/emitter) && \
!istype(A,/obj/machinery/field_generator) && \
prob(15))
-
explosion(src.loc, 4, 5, 6, 7, 0)
- playsound(src.loc, "explosion", 50, 1)
del(src)
return
@@ -146,16 +133,18 @@
if(--src.hits <= 0)
del(src) //Dont blow up singularity containment if we get stuck there.
- for(var/mob/M in range(10, src))
- if(!M.stat && !istype(M, /mob/living/silicon/ai)) //bad idea to shake an ai's view
- shake_camera(M, 3, 1)
if (A)
+ for(var/mob/M in player_list)
+ var/turf/T = get_turf(M)
+ if(!T || T.z != src.z)
+ continue
+ shake_camera(M, 3, get_dist(M.loc, src.loc) > 20 ? 1 : 3)
+ M.playsound_local(src.loc, 'sound/effects/meteorimpact.ogg', 50, 1, get_rand_frequency(), 10)
explosion(src.loc, 0, 1, 2, 3, 0)
- playsound(src.loc, 'sound/effects/meteorimpact.ogg', 40, 1)
+
if (--src.hits <= 0)
if(prob(15) && !istype(A, /obj/structure/grille))
explosion(src.loc, 1, 2, 3, 4, 0)
- playsound(src.loc, "explosion", 50, 1)
del(src)
return
diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm
index 1c00948f67c..aaaa37a706d 100644
--- a/code/game/gamemodes/nuclear/nuclear.dm
+++ b/code/game/gamemodes/nuclear/nuclear.dm
@@ -209,9 +209,7 @@
synd_mob.equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(synd_mob), slot_w_uniform)
synd_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(synd_mob), slot_shoes)
- synd_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/armor/vest(synd_mob), slot_wear_suit)
synd_mob.equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(synd_mob), slot_gloves)
- synd_mob.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/swat(synd_mob), slot_head)
synd_mob.equip_to_slot_or_del(new /obj/item/weapon/card/id/syndicate(synd_mob), slot_wear_id)
if(synd_mob.backbag == 2) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(synd_mob), slot_back)
if(synd_mob.backbag == 3) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_norm(synd_mob), slot_back)
@@ -221,6 +219,27 @@
synd_mob.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/pill/cyanide(synd_mob), slot_in_backpack)
synd_mob.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/automatic/c20r(synd_mob), slot_belt)
synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(synd_mob.back), slot_in_backpack)
+
+ if(synd_mob.species)
+ var/race = synd_mob.species.name
+
+ if(race == "Unathi")
+ synd_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/space/rig/syndi/unathi(synd_mob), slot_wear_suit)
+ synd_mob.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/rig/syndi/unathi(synd_mob), slot_head)
+ else if(race == "Tajaran")
+ synd_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/space/rig/syndi/tajara(synd_mob), slot_wear_suit)
+ synd_mob.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/rig/syndi/tajara(synd_mob), slot_head)
+ else if(race == "Skrell")
+ synd_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/space/rig/syndi/skrell(synd_mob), slot_wear_suit)
+ synd_mob.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/rig/syndi/skrell(synd_mob), slot_head)
+ else
+ synd_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/space/rig/syndi/human(synd_mob), slot_wear_suit)
+ synd_mob.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/rig/syndi/human(synd_mob), slot_head)
+ else
+ synd_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/space/rig/syndi/human(synd_mob), slot_wear_suit)
+ synd_mob.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/rig/syndi/human(synd_mob), slot_head)
+
+
var/obj/item/weapon/implant/explosive/E = new/obj/item/weapon/implant/explosive(synd_mob)
E.imp_in = synd_mob
E.implanted = 1
diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm
index 7480555d694..b8faeeef976 100644
--- a/code/game/gamemodes/nuclear/nuclearbomb.dm
+++ b/code/game/gamemodes/nuclear/nuclearbomb.dm
@@ -8,6 +8,8 @@ var/bomb_set
density = 1
var/deployable = 0.0
var/extended = 0.0
+ var/lighthack = 0
+ var/opened = 0.0
var/timeleft = 60.0
var/timing = 0.0
var/r_code = "ADMIN"
@@ -15,15 +17,36 @@ var/bomb_set
var/yes_code = 0.0
var/safety = 1.0
var/obj/item/weapon/disk/nuclear/auth = null
+ var/list/wires = list()
+ var/light_wire
+ var/safety_wire
+ var/timing_wire
var/removal_stage = 0 // 0 is no removal, 1 is covers removed, 2 is covers open,
// 3 is sealant open, 4 is unwrenched, 5 is removed from bolts.
flags = FPRINT
use_power = 0
+
+
/obj/machinery/nuclearbomb/New()
..()
r_code = "[rand(10000, 99999.0)]"//Creates a random code upon object spawn.
+ src.wires["Red"] = 0
+ src.wires["Blue"] = 0
+ src.wires["Green"] = 0
+ src.wires["Marigold"] = 0
+ src.wires["Fuschia"] = 0
+ src.wires["Black"] = 0
+ src.wires["Pearl"] = 0
+ var/list/w = list("Red","Blue","Green","Marigold","Black","Fuschia","Pearl")
+ src.light_wire = pick(w)
+ w -= src.light_wire
+ src.timing_wire = pick(w)
+ w -= src.timing_wire
+ src.safety_wire = pick(w)
+ w -= src.safety_wire
+
/obj/machinery/nuclearbomb/process()
if (src.timing)
bomb_set = 1 //So long as there is one nuke timing, it means one nuke is armed.
@@ -36,6 +59,30 @@ var/bomb_set
return
/obj/machinery/nuclearbomb/attackby(obj/item/weapon/O as obj, mob/user as mob)
+
+ if (istype(O, /obj/item/weapon/screwdriver))
+ src.add_fingerprint(user)
+ if (src.auth)
+ if (src.opened == 0)
+ src.opened = 1
+ overlays += image(icon, "npanel_open")
+ user << "You unscrew the control panel of [src]."
+
+ else
+ src.opened = 0
+ overlays -= image(icon, "npanel_open")
+ user << "You screw the control panel of [src] back on."
+ else
+ if (src.opened == 0)
+ user << "The [src] emits a buzzing noise, the panel staying locked in."
+ if (src.opened == 1)
+ src.opened = 0
+ overlays -= image(icon, "npanel_open")
+ user << "You screw the control panel of [src] back on."
+ flick("nuclearbombc", src)
+
+ return
+
if (src.extended)
if (istype(O, /obj/item/weapon/disk/nuclear))
usr.drop_item()
@@ -119,6 +166,8 @@ var/bomb_set
/obj/machinery/nuclearbomb/attack_hand(mob/user as mob)
if (src.extended)
+ if (src.opened)
+ nukehack_win(user,50)
user.set_machine(src)
var/dat = text("Nuclear Fission Explosive
\nAuth. Disk: []
", src, (src.auth ? "++++++++++" : "----------"))
if (src.auth)
@@ -145,11 +194,23 @@ var/bomb_set
visible_message("\red With a steely snap, bolts slide out of [src] and anchor it to the flooring!")
else
visible_message("\red \The [src] makes a highly unpleasant crunching noise. It looks like the anchoring bolts have been cut.")
- flick("nuclearbombc", src)
- src.icon_state = "nuclearbomb1"
+ if(!src.lighthack)
+ flick("nuclearbombc", src)
+ src.icon_state = "nuclearbomb1"
src.extended = 1
return
+obj/machinery/nuclearbomb/proc/nukehack_win(mob/user as mob)
+ var/dat as text
+ dat += "Nuclear Fission Explosive
\nNuclear Device Wires:
"
+ for(var/wire in src.wires)
+ dat += text("[wire] Wire: [src.wires[wire] ? "Mend" : "Cut"] Pulse
")
+ dat += text("
The device is [src.timing ? "shaking!" : "still"]
")
+ dat += text("The device is [src.safety ? "quiet" : "whirring"].
")
+ dat += text("The lights are [src.lighthack ? "static" : "functional"].
")
+ user << browse("Bomb Defusion[dat]","window=nukebomb_hack")
+ onclose(user, "nukebomb_hack")
+
/obj/machinery/nuclearbomb/verb/make_deployable()
set category = "Object"
set name = "Make Deployable"
@@ -161,16 +222,57 @@ var/bomb_set
else
usr << "\red You adjust some panels to make [src] deployable."
src.deployable = 1
+ return
+
/obj/machinery/nuclearbomb/Topic(href, href_list)
..()
if (!usr.canmove || usr.stat || usr.restrained())
return
- if (!ishuman(usr))
- usr << "\red You don't have the dexterity to do this!"
- return 1
if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))))
usr.set_machine(src)
+ if(href_list["act"])
+ var/temp_wire = href_list["wire"]
+ if(href_list["act"] == "pulse")
+ if (!istype(usr.get_active_hand(), /obj/item/device/multitool))
+ usr << "You need a multitool!"
+ else
+ if(src.wires[temp_wire])
+ usr << "You can't pulse a cut wire."
+ else
+ if(src.light_wire == temp_wire)
+ src.lighthack = !src.lighthack
+ spawn(100) src.lighthack = !src.lighthack
+ if(src.timing_wire == temp_wire)
+ if(src.timing)
+ explode()
+ if(src.safety_wire == temp_wire)
+ src.safety = !src.safety
+ spawn(100) src.safety = !src.safety
+ if(src.safety == 1)
+ visible_message("\blue The [src] quiets down.")
+ if(!src.lighthack)
+ if (src.icon_state == "nuclearbomb2")
+ src.icon_state = "nuclearbomb1"
+ else
+ visible_message("\blue The [src] emits a quiet whirling noise!")
+ if(href_list["act"] == "wire")
+ if (!istype(usr.get_active_hand(), /obj/item/weapon/wirecutters))
+ usr << "You need wirecutters!"
+ else
+ wires[temp_wire] = !wires[temp_wire]
+ if(src.safety_wire == temp_wire)
+ if(src.timing)
+ explode()
+ if(src.timing_wire == temp_wire)
+ if(!src.lighthack)
+ if (src.icon_state == "nuclearbomb2")
+ src.icon_state = "nuclearbomb1"
+ src.timing = 0
+ bomb_set = 0
+ if(src.light_wire == temp_wire)
+ src.lighthack = !src.lighthack
+
if (href_list["auth"])
if (src.auth)
src.auth.loc = src.loc
@@ -211,14 +313,16 @@ var/bomb_set
return
src.timing = !( src.timing )
if (src.timing)
- src.icon_state = "nuclearbomb2"
+ if(!src.lighthack)
+ src.icon_state = "nuclearbomb2"
if(!src.safety)
bomb_set = 1//There can still be issues with this reseting when there are multiple bombs. Not a big deal tho for Nuke/N
else
bomb_set = 0
else
- src.icon_state = "nuclearbomb1"
bomb_set = 0
+ if(!src.lighthack)
+ src.icon_state = "nuclearbomb1"
if (href_list["safety"])
src.safety = !( src.safety )
if(safety)
@@ -266,7 +370,8 @@ var/bomb_set
src.timing = -1.0
src.yes_code = 0
src.safety = 1
- src.icon_state = "nuclearbomb3"
+ if(!src.lighthack)
+ src.icon_state = "nuclearbomb3"
playsound(src,'sound/machines/Alarm.ogg',100,0,5)
if (ticker && ticker.mode)
ticker.mode.explosion_in_progress = 1
diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm
index f262818d656..3302cbe5abe 100644
--- a/code/game/gamemodes/objective.dm
+++ b/code/game/gamemodes/objective.dm
@@ -745,3 +745,15 @@ datum/objective/absorb
/*-------ENDOF CULTIST------*/
*/
+datum/objective/blood
+ proc/gen_amount_goal(low = 150, high = 400)
+ target_amount = rand(low,high)
+ target_amount = round(round(target_amount/5)*5)
+ explanation_text = "Accumulate atleast [target_amount] units of blood in total."
+ return target_amount
+
+ check_completion()
+ if(owner && owner.vampire && owner.vampire.bloodtotal && owner.vampire.bloodtotal >= target_amount)
+ return 1
+ else
+ return 0
diff --git a/code/game/gamemodes/scoreboard.dm b/code/game/gamemodes/scoreboard.dm
index 8169e0a3ca3..c4c836b5b11 100644
--- a/code/game/gamemodes/scoreboard.dm
+++ b/code/game/gamemodes/scoreboard.dm
@@ -29,10 +29,15 @@
if (I.stat == 2 && I.z == 1)
score_deadaipenalty = 1
score_deadcrew += 1
-/* for (var/mob/living/carbon/human/I in mob_list)
- for (var/datum/ailment/disease/V in I.ailments)
- if (!V.vaccine && !V.spread != "Remissive") score_disease++
- if (I.stat == 2 && I.z == 1) score_deadcrew += 1*/
+ for (var/mob/living/carbon/human/I in mob_list)
+// for (var/datum/ailment/disease/V in I.ailments)
+// if (!V.vaccine && !V.spread != "Remissive") score_disease++
+ if (I.stat == 2 && I.z == 1) score_deadcrew += 1
+ if (I.job == "Clown")
+ for(var/thing in I.attack_log)
+ if(findtext(thing, "")) score_clownabuse++
+
+
for(var/mob/living/player in mob_list)
if (player.client)
if (player.stat != 2)
@@ -143,17 +148,17 @@
// Bonus Modifiers
//var/traitorwins = score_traitorswon
- var/deathpoints = score_deadcrew * 25
+ var/deathpoints = score_deadcrew * 25 //done
var/researchpoints = score_researchdone * 30
var/eventpoints = score_eventsendured * 50
- var/escapoints = score_escapees * 25
+ var/escapoints = score_escapees * 25 //done
var/harvests = score_stuffharvested * 5 //done
var/shipping = score_stuffshipped * 5
var/mining = score_oremined * 2 //done
var/meals = score_meals * 5 //done, but this only counts cooked meals, not drinks served
var/power = score_powerloss * 20
var/messpoints
- if (score_mess != 0) messpoints = score_mess
+ if (score_mess != 0) messpoints = score_mess //done
var/plaguepoints = score_disease * 30
// Mode Specific
diff --git a/code/game/gamemodes/vampire/hud.dm b/code/game/gamemodes/vampire/hud.dm
new file mode 100644
index 00000000000..44b34d00e0f
--- /dev/null
+++ b/code/game/gamemodes/vampire/hud.dm
@@ -0,0 +1,9 @@
+/datum/hud/proc/vampire_hud(ui_style = 'icons/mob/screen1_Midnight.dmi')
+
+ vampire_blood_display = new /obj/screen()
+ vampire_blood_display.name = "Vampire Blood"
+ vampire_blood_display.icon_state = "dark128"
+ vampire_blood_display.screen_loc = "14:28,9:15"
+ vampire_blood_display.layer = 20
+
+ mymob.client.screen += list(vampire_blood_display)
\ No newline at end of file
diff --git a/code/game/gamemodes/vampire/vampire.dm b/code/game/gamemodes/vampire/vampire.dm
new file mode 100644
index 00000000000..7b9304bf529
--- /dev/null
+++ b/code/game/gamemodes/vampire/vampire.dm
@@ -0,0 +1,492 @@
+//This is the gamemode file for the ported goon gamemode vampires.
+//They get a traitor objective and a blood sucking objective
+/datum/game_mode
+ var/list/datum/mind/vampires = list()
+ var/list/datum/mind/enthralled = list() //those controlled by a vampire
+ var/list/thralls = list() //vammpires controlling somebody
+/datum/game_mode/vampire
+ name = "vampire"
+ config_tag = "vampire"
+ restricted_jobs = list("AI", "Cyborg", "Mobile MMI", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Chaplain") //Consistent screening has filtered all infiltration attempts on high value jobs
+ protected_jobs = list()
+ required_players = 1
+ required_players_secret = 15
+ required_enemies = 1
+ recommended_enemies = 4
+
+ uplink_welcome = "Syndicate Uplink Console:"
+ uplink_uses = 10
+
+ var/const/prob_int_murder_target = 50 // intercept names the assassination target half the time
+ var/const/prob_right_murder_target_l = 25 // lower bound on probability of naming right assassination target
+ var/const/prob_right_murder_target_h = 50 // upper bound on probability of naimg the right assassination target
+
+ var/const/prob_int_item = 50 // intercept names the theft target half the time
+ var/const/prob_right_item_l = 25 // lower bound on probability of naming right theft target
+ var/const/prob_right_item_h = 50 // upper bound on probability of naming the right theft target
+
+ var/const/prob_int_sab_target = 50 // intercept names the sabotage target half the time
+ var/const/prob_right_sab_target_l = 25 // lower bound on probability of naming right sabotage target
+ var/const/prob_right_sab_target_h = 50 // upper bound on probability of naming right sabotage target
+
+ var/const/prob_right_killer_l = 25 //lower bound on probability of naming the right operative
+ var/const/prob_right_killer_h = 50 //upper bound on probability of naming the right operative
+ var/const/prob_right_objective_l = 25 //lower bound on probability of determining the objective correctly
+ var/const/prob_right_objective_h = 50 //upper bound on probability of determining the objective correctly
+
+ var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds)
+ var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds)
+
+ var/vampire_amount = 4
+
+
+/datum/game_mode/vampire/announce()
+ world << "The current game mode is - Vampires!"
+ world << "There are Vampires from Space Transylvania on the station, keep your blood close and neck safe!"
+
+/datum/game_mode/vampire/pre_setup()
+
+ if(config.protect_roles_from_antagonist)
+ restricted_jobs += protected_jobs
+
+ var/list/datum/mind/possible_vampires = get_players_for_role(BE_VAMPIRE)
+
+ for(var/datum/mind/player in possible_vampires)
+ for(var/job in restricted_jobs)//Removing robots from the list
+ if(player.assigned_role == job)
+ possible_vampires -= player
+
+ vampire_amount = max(1,round(num_players() / 10)) //1 + round(num_players() / 10)
+
+ if(possible_vampires.len>0)
+ for(var/i = 0, i < vampire_amount, i++)
+ if(!possible_vampires.len) break
+ var/datum/mind/vampire = pick(possible_vampires)
+ possible_vampires -= vampire
+ vampires += vampire
+ modePlayer += vampires
+ return 1
+ else
+ return 0
+
+/datum/game_mode/vampire/post_setup()
+ for(var/datum/mind/vampire in vampires)
+ grant_vampire_powers(vampire.current)
+ vampire.special_role = "Vampire"
+ forge_vampire_objectives(vampire)
+ greet_vampire(vampire)
+
+ spawn (rand(waittime_l, waittime_h))
+ send_intercept()
+ ..()
+ return
+
+/datum/game_mode/proc/auto_declare_completion_vampire()
+ if(vampires.len)
+ var/text = "The vampires were:"
+ for(var/datum/mind/vampire in vampires)
+ var/traitorwin = 1
+
+ text += "
[vampire.key] was [vampire.name] ("
+ if(vampire.current)
+ if(vampire.current.stat == DEAD)
+ text += "died"
+ else
+ text += "survived"
+ if(vampire.current.real_name != vampire.name)
+ text += " as [vampire.current.real_name]"
+ else
+ text += "body destroyed"
+ text += ")"
+
+ if(vampire.objectives.len)//If the traitor had no objectives, don't need to process this.
+ var/count = 1
+ for(var/datum/objective/objective in vampire.objectives)
+ if(objective.check_completion())
+ text += "
Objective #[count]: [objective.explanation_text] Success!"
+ feedback_add_details("traitor_objective","[objective.type]|SUCCESS")
+ else
+ text += "
Objective #[count]: [objective.explanation_text] Fail."
+ feedback_add_details("traitor_objective","[objective.type]|FAIL")
+ traitorwin = 0
+ count++
+
+ var/special_role_text
+ if(vampire.special_role)
+ special_role_text = lowertext(vampire.special_role)
+ else
+ special_role_text = "antagonist"
+
+ if(traitorwin)
+ text += "
The [special_role_text] was successful!"
+ feedback_add_details("traitor_success","SUCCESS")
+ else
+ text += "
The [special_role_text] has failed!"
+ feedback_add_details("traitor_success","FAIL")
+ world << text
+ return 1
+
+/datum/game_mode/proc/auto_declare_completion_enthralled()
+ if(enthralled.len)
+ var/text = "The Enthralled were:"
+ for(var/datum/mind/enthralled in enthralled)
+ text += "
[enthralled.key] was [enthralled.name] ("
+ if(enthralled.current)
+ if(enthralled.current.stat == DEAD)
+ text += "died"
+ else
+ text += "survived"
+ if(enthralled.current.real_name != enthralled.name)
+ text += " as [enthralled.current.real_name]"
+ else
+ text += "body destroyed"
+ text += ")"
+ world << text
+ return 1
+
+/datum/game_mode/proc/forge_vampire_objectives(var/datum/mind/vampire)
+ //Objectives are traitor objectives plus blood objectives
+
+ var/datum/objective/blood/blood_objective = new
+ blood_objective.owner = vampire
+ blood_objective.gen_amount_goal(150, 400)
+ vampire.objectives += blood_objective
+
+ var/datum/objective/assassinate/kill_objective = new
+ kill_objective.owner = vampire
+ kill_objective.find_target()
+ vampire.objectives += kill_objective
+
+ var/datum/objective/steal/steal_objective = new
+ steal_objective.owner = vampire
+ steal_objective.find_target()
+ vampire.objectives += steal_objective
+
+
+ switch(rand(1,100))
+ if(1 to 80)
+ if (!(locate(/datum/objective/escape) in vampire.objectives))
+ var/datum/objective/escape/escape_objective = new
+ escape_objective.owner = vampire
+ vampire.objectives += escape_objective
+ else
+ if (!(locate(/datum/objective/survive) in vampire.objectives))
+ var/datum/objective/survive/survive_objective = new
+ survive_objective.owner = vampire
+ vampire.objectives += survive_objective
+ return
+
+/datum/game_mode/proc/grant_vampire_powers(mob/living/carbon/vampire_mob)
+ if(!istype(vampire_mob)) return
+ vampire_mob.make_vampire()
+
+/datum/game_mode/proc/greet_vampire(var/datum/mind/vampire, var/you_are=1)
+ var/dat
+ if (you_are)
+ dat = "\red You are a Vampire! \black"
+ dat += {"To bite someone, target the head and use harm intent with an empty hand. Drink blood to gain new powers.
+You are weak to holy things and starlight. Don't go into space and avoid the Chaplain, the chapel and especially Holy Water."}
+ vampire.current << dat
+ vampire.current << "You must complete the following tasks:"
+
+ if (vampire.current.mind)
+ if (vampire.current.mind.assigned_role == "Clown")
+ vampire.current << "Your lust for blood has allowed you to overcome your clumsy nature allowing you to wield weapons without harming yourself."
+ vampire.current.mutations.Remove(CLUMSY)
+
+ var/obj_count = 1
+ for(var/datum/objective/objective in vampire.objectives)
+ vampire.current << "Objective #[obj_count]: [objective.explanation_text]"
+ obj_count++
+ return
+
+/datum/vampire
+ var/bloodtotal = 0 // CHANGE TO ZERO WHEN PLAYTESTING HAPPENS
+ var/bloodusable = 0 // CHANGE TO ZERO WHEN PLAYTESTING HAPPENS
+ var/mob/living/owner = null
+ var/gender = FEMALE
+ var/iscloaking = 0 // handles the vampire cloak toggle
+ var/list/powers = list() // list of available powers and passives, see defines in setup.dm
+ var/mob/living/carbon/human/draining // who the vampire is draining of blood
+ var/nullified = 0 //Nullrod makes them useless for a short while.
+/datum/vampire/New(gend = FEMALE)
+ gender = gend
+
+/mob/proc/make_vampire()
+ if(!mind) return
+ if(!mind.vampire)
+ mind.vampire = new /datum/vampire(gender)
+ mind.vampire.owner = src
+ verbs += /client/proc/vampire_rejuvinate
+ verbs += /client/proc/vampire_hypnotise
+ verbs += /client/proc/vampire_glare
+ //testing purposes REMOVE BEFORE PUSH TO MASTER
+ /*for(var/handler in typesof(/client/proc))
+ if(findtext("[handler]","vampire_"))
+ verbs += handler*/
+ for(var/i = 1; i <= 3; i++) // CHANGE TO 3 RATHER THAN 12 AFTER TESTING IS DONE
+ if(!(i in mind.vampire.powers))
+ mind.vampire.powers.Add(i)
+
+
+ for(var/n in mind.vampire.powers)
+ switch(n)
+ if(VAMP_SHAPE)
+ verbs += /client/proc/vampire_shapeshift
+ if(VAMP_VISION)
+ continue
+ if(VAMP_DISEASE)
+ verbs += /client/proc/vampire_disease
+ if(VAMP_CLOAK)
+ verbs += /client/proc/vampire_cloak
+ if(VAMP_BATS)
+ verbs += /client/proc/vampire_bats
+ if(VAMP_SCREAM)
+ verbs += /client/proc/vampire_screech
+ if(VAMP_JAUNT)
+ verbs += /client/proc/vampire_jaunt
+ if(VAMP_BLINK)
+ verbs += /client/proc/vampire_shadowstep
+ if(VAMP_SLAVE)
+ verbs += /client/proc/vampire_enthrall
+ if(VAMP_FULL)
+ continue
+/mob/proc/remove_vampire_powers()
+ for(var/handler in typesof(/client/proc))
+ if(findtext("[handler]","vampire_"))
+ verbs -= handler
+
+/mob/proc/handle_bloodsucking(mob/living/carbon/human/H)
+ src.mind.vampire.draining = H
+ var/blood = 0
+ var/bloodtotal = 0 //used to see if we increased our blood total
+ var/bloodusable = 0 //used to see if we increased our blood usable
+ src.attack_log += text("\[[time_stamp()]\] Bit [src.name] ([src.ckey]) in the neck and draining their blood")
+ H.attack_log += text("\[[time_stamp()]\] Has been bit in the neck by [src.name] ([src.ckey])")
+ log_attack("[src.name] ([src.ckey]) bit [H.name] ([H.ckey]) in the neck")
+ src.visible_message("\red [src.name] bites [H.name]'s neck!", "\red You bite [H.name]'s neck and begin to drain their blood.", "\blue You hear a soft puncture and a wet sucking noise")
+ while(do_mob(src, H, 50))
+ if(!mind.vampire || !(mind in ticker.mode.vampires))
+ src << "\red Your fangs have disappeared!"
+ return 0
+ bloodtotal = src.mind.vampire.bloodtotal
+ bloodusable = src.mind.vampire.bloodusable
+ if(!H.vessel.get_reagent_amount("blood"))
+ src << "\red They've got no blood left to give."
+ break
+ if(H.stat < 2) //alive
+ blood = min(10, H.vessel.get_reagent_amount("blood"))// if they have less than 10 blood, give them the remnant else they get 10 blood
+ src.mind.vampire.bloodtotal += blood
+ src.mind.vampire.bloodusable += blood
+ H.adjustCloneLoss(5) // beep boop 10 damage
+ else
+ blood = min(5, H.vessel.get_reagent_amount("blood"))// The dead only give 5 bloods
+ src.mind.vampire.bloodtotal += blood
+ if(bloodtotal != src.mind.vampire.bloodtotal)
+ src << "\blue You have accumulated [src.mind.vampire.bloodtotal] [src.mind.vampire.bloodtotal > 1 ? "units" : "unit"] of blood[src.mind.vampire.bloodusable != bloodusable ?", and have [src.mind.vampire.bloodusable] left to use" : "."]"
+ check_vampire_upgrade(mind)
+ H.vessel.remove_reagent("blood",25)
+
+ src.mind.vampire.draining = null
+ src << "\blue You stop draining [H.name] of blood."
+ return 1
+
+/mob/proc/check_vampire_upgrade(datum/mind/v)
+ if(!v) return
+ if(!v.vampire) return
+ var/datum/vampire/vamp = v.vampire
+ var/list/old_powers = vamp.powers.Copy()
+
+ // This used to be a switch statement.
+ // Don't use switch statements for shit like this, since blood can be any random-ass value.
+ // if(100) requires the blood to be at EXACTLY 100 units to trigger.
+ // if(blud >= 100) activates when blood is at or over 100 units.
+ // TODO: Make this modular.
+
+ // TIER 1
+ if(vamp.bloodtotal >= 100)
+ if(!(VAMP_VISION in vamp.powers))
+ vamp.powers.Add(VAMP_VISION)
+ if(!(VAMP_SHAPE in vamp.powers))
+ vamp.powers.Add(VAMP_SHAPE)
+
+ // TIER 2
+ if(vamp.bloodtotal >= 150)
+ if(!(VAMP_CLOAK in vamp.powers))
+ vamp.powers.Add(VAMP_CLOAK)
+ if(!(VAMP_DISEASE in vamp.powers))
+ vamp.powers.Add(VAMP_DISEASE)
+
+ // TIER 3
+ if(vamp.bloodtotal >= 200)
+ if(!(VAMP_BATS in vamp.powers))
+ vamp.powers.Add(VAMP_BATS)
+ if(!(VAMP_SCREAM in vamp.powers))
+ vamp.powers.Add(VAMP_SCREAM)
+ // Commented out until we can figured out a way to stop this from spamming.
+ //src << "\blue Your rejuvination abilities have improved and will now heal you over time when used."
+
+ // TIER 3.5 (/vg/)
+ if(vamp.bloodtotal >= 250)
+ if(!(VAMP_BLINK in vamp.powers))
+ vamp.powers.Add(VAMP_BLINK)
+
+ // TIER 4
+ if(vamp.bloodtotal >= 300)
+ if(!(VAMP_JAUNT in vamp.powers))
+ vamp.powers.Add(VAMP_JAUNT)
+ if(!(VAMP_SLAVE in vamp.powers))
+ vamp.powers.Add(VAMP_SLAVE)
+
+ // TIER 5
+ if(vamp.bloodtotal >= 500)
+ if(!(VAMP_FULL in vamp.powers))
+ vamp.powers.Add(VAMP_FULL)
+
+ announce_new_power(old_powers, vamp.powers)
+
+/mob/proc/announce_new_power(list/old_powers, list/new_powers)
+ for(var/n in new_powers)
+ if(!(n in old_powers))
+ switch(n)
+ if(VAMP_SHAPE)
+ src << "\blue You have gained the shapeshifting ability, at the cost of stored blood you can change your form permanently."
+ verbs += /client/proc/vampire_shapeshift
+ if(VAMP_VISION)
+ src << "\blue Your vampiric vision has improved."
+ //no verb
+ if(VAMP_DISEASE)
+ src << "\blue You have gained the Diseased Touch ability which causes those you touch to die shortly after unless treated medically."
+ verbs += /client/proc/vampire_disease
+ if(VAMP_CLOAK)
+ src << "\blue You have gained the Cloak of Darkness ability which when toggled makes you near invisible in the shroud of darkness."
+ verbs += /client/proc/vampire_cloak
+ if(VAMP_BATS)
+ src << "\blue You have gained the Summon Bats ability."
+ verbs += /client/proc/vampire_bats // work in progress
+ if(VAMP_SCREAM)
+ src << "\blue You have gained the Chriopteran Screech ability which stuns anything with ears in a large radius and shatters glass in the process."
+ verbs += /client/proc/vampire_screech
+ if(VAMP_JAUNT)
+ src << "\blue You have gained the Mist Form ability which allows you to take on the form of mist for a short period and pass over any obstacle in your path."
+ verbs += /client/proc/vampire_jaunt
+ if(VAMP_SLAVE)
+ src << "\blue You have gained the Enthrall ability which at a heavy blood cost allows you to enslave a human that is not loyal to any other for a random period of time."
+ verbs += /client/proc/vampire_enthrall
+ if(VAMP_BLINK)
+ src << "\blue You have gained the ability to shadowstep, which makes you disappear into nearby shadows at the cost of blood."
+ verbs += /client/proc/vampire_shadowstep
+ if(VAMP_FULL)
+ src << "\blue You have reached your full potential and are no longer weak to the effects of anything holy and your vision has been improved greatly."
+ //no verb
+//prepare for copypaste
+/datum/game_mode/proc/update_vampire_icons_added(datum/mind/vampire_mind)
+ var/ref = "\ref[vampire_mind]"
+ if(ref in thralls)
+ if(vampire_mind.current)
+ if(vampire_mind.current.client)
+ var/I = image('icons/mob/mob.dmi', loc = vampire_mind.current, icon_state = "vampire")
+ vampire_mind.current.client.images += I
+ for(var/headref in thralls)
+ for(var/datum/mind/t_mind in thralls[headref])
+ var/datum/mind/head = locate(headref)
+ if(head)
+ if(head.current)
+ if(head.current.client)
+ var/I = image('icons/mob/mob.dmi', loc = t_mind.current, icon_state = "vampthrall")
+ head.current.client.images += I
+ if(t_mind.current)
+ if(t_mind.current.client)
+ var/I = image('icons/mob/mob.dmi', loc = head.current, icon_state = "vampire")
+ t_mind.current.client.images += I
+ if(t_mind.current)
+ if(t_mind.current.client)
+ var/I = image('icons/mob/mob.dmi', loc = t_mind.current, icon_state = "vampthrall")
+ t_mind.current.client.images += I
+
+/datum/game_mode/proc/update_vampire_icons_removed(datum/mind/vampire_mind)
+ for(var/headref in thralls)
+ var/datum/mind/head = locate(headref)
+ for(var/datum/mind/t_mind in thralls[headref])
+ if(t_mind.current)
+ if(t_mind.current.client)
+ for(var/image/I in t_mind.current.client.images)
+ if((I.icon_state == "vampthrall" || I.icon_state == "vampire") && I.loc == vampire_mind.current)
+ //world.log << "deleting [vampire_mind] overlay"
+ del(I)
+ if(head)
+ //world.log << "found [head.name]"
+ if(head.current)
+ if(head.current.client)
+ for(var/image/I in head.current.client.images)
+ if((I.icon_state == "vampthrall" || I.icon_state == "vampire") && I.loc == vampire_mind.current)
+ //world.log << "deleting [vampire_mind] overlay"
+ del(I)
+ if(vampire_mind.current)
+ if(vampire_mind.current.client)
+ for(var/image/I in vampire_mind.current.client.images)
+ if(I.icon_state == "vampthrall" || I.icon_state == "vampire")
+ del(I)
+
+/datum/game_mode/proc/remove_vampire_mind(datum/mind/vampire_mind, datum/mind/head)
+ //var/list/removal
+ if(!istype(head))
+ head = vampire_mind //workaround for removing a thrall's control over the enthralled
+ var/ref = "\ref[head]"
+ if(ref in thralls)
+ thralls[ref] -= vampire_mind
+ enthralled -= vampire_mind
+ vampire_mind.special_role = null
+ update_vampire_icons_removed(vampire_mind)
+ //world << "Removed [vampire_mind.current.name] from vampire shit"
+ vampire_mind.current << "\red The fog clouding your mind clears. You remember nothing from the moment you were enthralled until now."
+
+/mob/living/carbon/human/proc/check_sun()
+
+ var/ax = x
+ var/ay = y
+
+ for(var/i = 1 to 20)
+ ax += sun.dx
+ ay += sun.dy
+
+ var/turf/T = locate( round(ax,0.5),round(ay,0.5),z)
+
+ if(T.x == 1 || T.x==world.maxx || T.y==1 || T.y==world.maxy)
+ break
+
+ if(T.density)
+ return
+ if(prob(35))
+ switch(health)
+ if(80 to 100)
+ src << "\red Your skin flakes away..."
+ if(60 to 80)
+ src << "Your skin sizzles!"
+ if((-INFINITY) to 60)
+ if(!on_fire)
+ src << "\red Your skin catches fire!"
+ else
+ src << "\red You continue to burn!"
+ fire_stacks += 5
+ IgniteMob()
+ emote("scream")
+ else
+ switch(health)
+ if((-INFINITY) to 60)
+ fire_stacks++
+ IgniteMob()
+ adjustFireLoss(3)
+
+/mob/living/carbon/human/proc/handle_vampire()
+ if(hud_used)
+ if(!hud_used.vampire_blood_display)
+ hud_used.vampire_hud()
+ //hud_used.human_hud(hud_used.ui_style)
+ hud_used.vampire_blood_display.maptext_width = 64
+ hud_used.vampire_blood_display.maptext_height = 26
+ hud_used.vampire_blood_display.maptext = " U:[mind.vampire.bloodusable]
T:[mind.vampire.bloodtotal]
"
+ handle_vampire_cloak()
+ if(istype(loc, /turf/space))
+ check_sun()
+ mind.vampire.nullified = max(0, mind.vampire.nullified - 1)
\ No newline at end of file
diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm
new file mode 100644
index 00000000000..c03af44cad8
--- /dev/null
+++ b/code/game/gamemodes/vampire/vampire_powers.dm
@@ -0,0 +1,469 @@
+//This should hold all the vampire related powers
+
+
+/mob/proc/vampire_power(required_blood=0, max_stat=0)
+
+ if(!src.mind) return 0
+ if(!ishuman(src))
+ src << "You are in too weak of a form to do this!"
+ return 0
+
+ var/datum/vampire/vampire = src.mind.vampire
+
+ if(!vampire)
+ world.log << "[src] has vampire verbs but isn't a vampire."
+ return 0
+
+ var/fullpower = (VAMP_FULL in vampire.powers)
+
+ if(src.stat > max_stat)
+ src << "You are incapacitated."
+ return 0
+
+ if(vampire.nullified)
+ if(!fullpower)
+ src << "Something is blocking your powers!"
+ return 0
+ if(vampire.bloodusable < required_blood)
+ src << "You require at least [required_blood] units of usable blood to do that!"
+ return 0
+ //chapel check
+ if(istype(loc.loc, /area/chapel))
+ if(!fullpower)
+ src << "Your powers are useless on this holy ground."
+ return 0
+ return 1
+
+/mob/proc/vampire_affected(datum/mind/M)
+ //Other vampires aren't affected
+ if(mind && mind.vampire) return 0
+ //Vampires who have reached their full potential can affect nearly everything
+ if(M && M.vampire && (VAMP_FULL in M.vampire.powers))
+ return 1
+ //Chaplains are resistant to vampire powers
+ if(mind && mind.assigned_role == "Chaplain")
+ return 0
+ return 1
+
+/mob/proc/vampire_can_reach(mob/M as mob, active_range = 1)
+ if(M.loc == src.loc) return 1 //target and source are in the same thing
+ if(!isturf(src.loc) || !isturf(M.loc)) return 0 //One is inside, the other is outside something.
+ if(AStar(src.loc, M.loc, /turf/proc/AdjacentTurfs, /turf/proc/Distance, active_range)) //If a path exists, good!
+ return 1
+ return 0
+
+/mob/proc/vampire_active(required_blood=0, max_stat=0, active_range=1)
+ var/pass = vampire_power(required_blood, max_stat)
+ if(!pass) return
+ var/datum/vampire/vampire = mind.vampire
+ if(!vampire) return
+ var/list/victims = list()
+ for(var/mob/living/carbon/C in oview(active_range))
+ victims += C
+ var/mob/living/carbon/T = input(src, "Victim?") as null|anything in victims
+
+ if(!T) return
+ if(!(T in view(active_range))) return
+ if(!vampire_can_reach(T, active_range)) return
+ if(!vampire_power(required_blood, max_stat)) return
+ return T
+
+/client/proc/vampire_rejuvinate()
+ set category = "Vampire"
+ set name = "Rejuvinate "
+ set desc= "Flush your system with spare blood to remove any incapacitating effects"
+ var/datum/mind/M = usr.mind
+ if(!M) return
+ if(M.current.vampire_power(0, 1))
+ M.current.weakened = 0
+ M.current.stunned = 0
+ M.current.paralysis = 0
+ //M.vampire.bloodusable -= 10
+ M.current << "\blue You flush your system with clean blood and remove any incapacitating effects."
+ spawn(1)
+ if(M.vampire.bloodtotal >= 200)
+ for(var/i = 0; i < 5; i++)
+ M.current.adjustBruteLoss(-2)
+ M.current.adjustOxyLoss(-5)
+ M.current.adjustToxLoss(-2)
+ M.current.adjustFireLoss(-2)
+ sleep(35)
+ M.current.verbs -= /client/proc/vampire_rejuvinate
+ spawn(200)
+ M.current.verbs += /client/proc/vampire_rejuvinate
+
+/client/proc/vampire_hypnotise()
+ set category = "Vampire"
+ set name = "Hypnotise (20)"
+ set desc= "A piercing stare that incapacitates your victim for a good length of time."
+ var/datum/mind/M = usr.mind
+ if(!M) return
+
+ var/mob/living/carbon/C = M.current.vampire_active(20, 0, 1)
+
+ if(!C) return
+ M.current.visible_message("[M]'s eyes flash briefly as he stares into [C.name]'s eyes")
+ M.current.remove_vampire_blood(20)
+ M.current.verbs -= /client/proc/vampire_hypnotise
+ spawn(1800)
+ M.current.verbs += /client/proc/vampire_hypnotise
+ if(do_mob(M.current, C, 50))
+ if(C.mind && C.mind.vampire)
+ M.current << "\red Your piercing gaze fails to knock out [C.name]."
+ C << "\blue [M.current]'s feeble gaze is ineffective."
+ return
+ else
+ M.current << "\red Your piercing gaze knocks out [C.name]."
+ C << "\red You find yourself unable to move and barely able to speak"
+ C.Weaken(20)
+ C.Stun(20)
+ C.stuttering = 20
+ else
+ M.current << "\red You broke your gaze."
+ return
+
+/client/proc/vampire_disease()
+ set category = "Vampire"
+ set name = "Diseased Touch (100)"
+ set desc = "Touches your victim with infected blood giving them the Shutdown Syndrome which quickly shutsdown their major organs resulting in a quick painful death."
+ var/datum/mind/M = usr.mind
+ if(!M) return
+
+ var/mob/living/carbon/C = M.current.vampire_active(100, 0, 1)
+ if(!C) return
+ if(!M.current.vampire_can_reach(C, 1))
+ M.current << "\red You cannot touch [C.name] from where you are standing!"
+ return
+ M.current << "\red You stealthily infect [C.name] with your diseased touch."
+ /*var/t_him = "it"
+ if (src.gender == MALE)
+ t_him = "him"
+ else if (src.gender == FEMALE)
+ t_him = "her"
+ M.current.visible_message("\blue [M] shakes [src] trying to wake [t_him] up!" )
+ playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)*/
+ C.help_shake_act(M.current) // i use da colon
+ if(!C.vampire_affected(M))
+ M.current << "\red They seem to be unaffected."
+ return
+ var/datum/disease2/disease/shutdown = new /datum/disease2/disease
+ var/datum/disease2/effectholder/holder = new /datum/disease2/effectholder
+ var/datum/disease2/effect/organs/vampire/O = new /datum/disease2/effect/organs/vampire
+ holder.effect += O
+ holder.chance = 10
+ shutdown.infectionchance = 100
+ shutdown.antigen |= text2num(pick(ANTIGENS))
+ shutdown.antigen |= text2num(pick(ANTIGENS))
+ shutdown.spreadtype = "None"
+ shutdown.uniqueID = rand(0,10000)
+ shutdown.effects += holder
+ shutdown.speed = 1
+ shutdown.stage = 2
+ shutdown.clicks = 185
+ infect_virus2(C,shutdown,0)
+ M.current.remove_vampire_blood(100)
+ M.current.verbs -= /client/proc/vampire_disease
+ spawn(1800) M.current.verbs += /client/proc/vampire_disease
+
+/client/proc/vampire_glare()
+ set category = "Vampire"
+ set name = "Glare"
+ set desc= "A scary glare that incapacitates people for a short while around you."
+ var/datum/mind/M = usr.mind
+ if(!M) return
+ if(M.current.vampire_power(0, 1))
+ M.current.visible_message("\red [M.current]'s eyes emit a blinding flash!")
+ //M.vampire.bloodusable -= 10
+ M.current.verbs -= /client/proc/vampire_glare
+ spawn(300)
+ M.current.verbs += /client/proc/vampire_glare
+ if(istype(M.current:glasses, /obj/item/clothing/glasses/sunglasses/blindfold))
+ M.current << "You're blindfolded!"
+ return
+ for(var/mob/living/carbon/C in oview(1))
+ if(!C.vampire_affected(M)) continue
+ if(!M.current.vampire_can_reach(C, 1)) continue
+ C.Stun(8)
+ C.Weaken(8)
+ C.stuttering = 20
+ C << "\red You are blinded by [M.current]'s glare"
+
+/client/proc/vampire_shapeshift()
+ set category = "Vampire"
+ set name = "Shapeshift (50)"
+ set desc = "Changes your name and appearance at the cost of 50 blood and has a cooldown of 3 minutes."
+ var/datum/mind/M = usr.mind
+ if(!M) return
+ if(M.current.vampire_power(50, 0))
+ M.current.visible_message("[M.current] transforms!")
+ M.current.client.prefs.real_name = random_name(M.current.gender)
+ M.current.client.prefs.randomize_appearance_for(M.current)
+ M.current.regenerate_icons()
+ M.current.remove_vampire_blood(50)
+ M.current.verbs -= /client/proc/vampire_shapeshift
+ spawn(1800) M.current.verbs += /client/proc/vampire_shapeshift
+
+/client/proc/vampire_screech()
+ set category = "Vampire"
+ set name = "Chiroptean Screech (30)"
+ set desc = "An extremely loud shriek that stuns nearby humans and breaks windows as well."
+ var/datum/mind/M = usr.mind
+ if(!M) return
+ if(M.current.vampire_power(30, 0))
+ M.current.visible_message("\red [M.current.name] lets out an ear piercing shriek!", "\red You let out a loud shriek.", "\red You hear a loud painful shriek!")
+ for(var/mob/living/carbon/C in ohearers(4, M.current))
+ if(C == M.current) continue
+ if(ishuman(C) && (C:l_ear || C:r_ear) && istype((C:l_ear || C:r_ear), /obj/item/clothing/ears/earmuffs)) continue
+ if(!C.vampire_affected(M)) continue
+ C << "You hear a ear piercing shriek and your senses dull!"
+ C.Weaken(8)
+ C.ear_deaf = 20
+ C.stuttering = 20
+ C.Stun(8)
+ C.make_jittery(150)
+ for(var/obj/structure/window/W in oview(3))
+ new W.shardtype(W.loc)
+ if(W.reinf) new /obj/item/stack/rods(W.loc)
+ del(W)
+ playsound(M.current.loc, 'sound/effects/creepyshriek.ogg', 100, 1)
+ M.current.remove_vampire_blood(30)
+ M.current.verbs -= /client/proc/vampire_screech
+ spawn(1800) M.current.verbs += /client/proc/vampire_screech
+
+/client/proc/vampire_enthrall()
+ set category = "Vampire"
+ set name = "Enthrall (300)"
+ set desc = "You use a large portion of your power to sway those loyal to none to be loyal to you only."
+ var/datum/mind/M = usr.mind
+ if(!M) return
+ var/mob/living/carbon/C = M.current.vampire_active(300, 0, 1)
+ if(!C) return
+ M.current.visible_message("\red [M.current.name] bites [C.name]'s neck!", "\red You bite [C.name]'s neck and begin the flow of power.")
+ C << "You feel the tendrils of evil invade your mind."
+ if(!ishuman(C))
+ M.current << "\red You can only enthrall humans"
+ return
+
+ if(do_mob(M.current, C, 50))
+ if(M.current.can_enthrall(C) && M.current.vampire_power(300, 0)) // recheck
+ M.current.handle_enthrall(C)
+ M.current.remove_vampire_blood(300)
+ M.current.verbs -= /client/proc/vampire_enthrall
+ spawn(1800) M.current.verbs += /client/proc/vampire_enthrall
+ else
+ M.current << "\red You or your target either moved or you dont have enough usable blood."
+ return
+
+
+
+/client/proc/vampire_cloak()
+ set category = "Vampire"
+ set name = "Cloak of Darkness (toggle)"
+ set desc = "Toggles whether you are currently cloaking yourself in darkness."
+ var/datum/mind/M = usr.mind
+ if(!M) return
+ if(M.current.vampire_power(0, 0))
+ M.vampire.iscloaking = !M.vampire.iscloaking
+ M.current << "\blue You will now be [M.vampire.iscloaking ? "hidden" : "seen"] in darkness."
+
+/mob/proc/handle_vampire_cloak()
+ if(!mind || !mind.vampire || !ishuman(src))
+ alpha = 255
+ return
+ var/turf/simulated/T = get_turf(src)
+
+ if(!istype(T))
+ return 0
+
+ if(!mind.vampire.iscloaking)
+ alpha = 255
+ return 0
+ if(T.lighting_lumcount <= 2)
+ alpha = round((255 * 0.15))
+ return 1
+ else
+ alpha = round((255 * 0.80))
+
+/mob/proc/can_enthrall(mob/living/carbon/C)
+ if(!C)
+ world.log << "something bad happened on enthralling a mob src is [src] [src.key] \ref[src]"
+ return 0
+ if(!C.mind)
+ src << "\red [C.name]'s mind is not there for you to enthrall."
+ return 0
+ if((/obj/item/weapon/implant/traitor in C.contents) || (/obj/item/weapon/implant/loyalty in C.contents )||( C.mind in ticker.mode.vampires )||( C.mind.vampire )||( C.mind in ticker.mode.enthralled ))
+ C.visible_message("\red [C] seems to resist the takeover!", "\blue You feel a familiar sensation in your skull that quickly dissipates.")
+ return 0
+ if(!C.vampire_affected(mind))
+ C.visible_message("\red [C] seems to resist the takeover!", "\blue Your faith of [ticker.Bible_deity_name] has kept your mind clear of all evil")
+ if(!ishuman(C))
+ src << "\red You can only enthrall humans!"
+ return 0
+ return 1
+
+/mob/proc/handle_enthrall(mob/living/carbon/human/H as mob)
+ if(!istype(H))
+ src << "\red SOMETHING WENT WRONG, YELL AT POMF OR NEXIS"
+ return 0
+ var/ref = "\ref[src.mind]"
+ if(!(ref in ticker.mode.thralls))
+ ticker.mode.thralls[ref] = list(H.mind)
+ else
+ ticker.mode.thralls[ref] += H.mind
+ ticker.mode.enthralled.Add(H.mind)
+ ticker.mode.enthralled[H.mind] = src.mind
+ H.mind.special_role = "VampThrall"
+ H << "\red You have been Enthralled by [name]. Follow their every command."
+ src << "\red You have successfully Enthralled [H.name]. If they refuse to do as you say just adminhelp."
+ ticker.mode.update_vampire_icons_added(H.mind)
+ ticker.mode.update_vampire_icons_added(src.mind)
+ log_admin("[ckey(src.key)] has mind-slaved [ckey(H.key)].")
+
+/client/proc/vampire_bats()
+ set category = "Vampire"
+ set name = "Summon Bats (75)"
+ set desc = "You summon a pair of space bats who attack nearby targets until they or their target is dead."
+ var/datum/mind/M = usr.mind
+ if(!M) return
+ if(M.current.vampire_power(75, 0))
+ var/list/turf/locs = new
+ var/number = 0
+ for(var/direction in alldirs) //looking for bat spawns
+ if(locs.len == 2) //we found 2 locations and thats all we need
+ break
+ var/turf/T = get_step(M.current,direction) //getting a loc in that direction
+ if(AStar(M.current.loc, T, /turf/proc/AdjacentTurfs, /turf/proc/Distance, 1)) // if a path exists, so no dense objects in the way its valid salid
+ locs += T
+ if(locs.len)
+ for(var/turf/tospawn in locs)
+ number++
+ new /mob/living/simple_animal/hostile/scarybat(tospawn, M.current)
+ if(number != 2) //if we only found one location, spawn one on top of our tile so we dont get stacked bats
+ new /mob/living/simple_animal/hostile/scarybat(M.current.loc, M.current)
+ else // we had no good locations so make two on top of us
+ new /mob/living/simple_animal/hostile/scarybat(M.current.loc, M.current)
+ new /mob/living/simple_animal/hostile/scarybat(M.current.loc, M.current)
+ M.current.remove_vampire_blood(75)
+ M.current.verbs -= /client/proc/vampire_bats
+ spawn(1200) M.current.verbs += /client/proc/vampire_bats
+
+/client/proc/vampire_jaunt()
+ //AHOY COPY PASTE INCOMING
+ set category = "Vampire"
+ set name = "Mist Form (30)"
+ set desc = "You take on the form of mist for a short period of time."
+ var/jaunt_duration = 50 //in deciseconds
+ var/datum/mind/M = usr.mind
+ if(!M) return
+
+ if(M.current.vampire_power(30, 0))
+ if(M.current.buckled) M.current.buckled.unbuckle()
+ spawn(0)
+ var/mobloc = get_turf(M.current.loc)
+ var/obj/effect/dummy/spell_jaunt/holder = new /obj/effect/dummy/spell_jaunt( mobloc )
+ var/atom/movable/overlay/animation = new /atom/movable/overlay( mobloc )
+ animation.name = "water"
+ animation.density = 0
+ animation.anchored = 1
+ animation.icon = 'icons/mob/mob.dmi'
+ animation.icon_state = "liquify"
+ animation.layer = 5
+ animation.master = holder
+ M.current.ExtinguishMob()
+ if(M.current.buckled)
+ M.current.buckled.unbuckle()
+ flick("liquify",animation)
+ M.current.loc = holder
+ M.current.client.eye = holder
+ var/datum/effect/effect/system/steam_spread/steam = new /datum/effect/effect/system/steam_spread()
+ steam.set_up(10, 0, mobloc)
+ steam.start()
+ sleep(jaunt_duration)
+ mobloc = get_turf(M.current.loc)
+ animation.loc = mobloc
+ steam.location = mobloc
+ steam.start()
+ M.current.canmove = 0
+ sleep(20)
+ flick("reappear",animation)
+ sleep(5)
+ if(!M.current.Move(mobloc))
+ for(var/direction in list(1,2,4,8,5,6,9,10))
+ var/turf/T = get_step(mobloc, direction)
+ if(T)
+ if(M.current.Move(T))
+ break
+ M.current.canmove = 1
+ M.current.client.eye = M.current
+ del(animation)
+ del(holder)
+ M.current.remove_vampire_blood(30)
+ M.current.verbs -= /client/proc/vampire_jaunt
+ spawn(600) M.current.verbs += /client/proc/vampire_jaunt
+
+// Blink for vamps
+// Less smoke spam.
+/client/proc/vampire_shadowstep()
+ set category = "Vampire"
+ set name = "Shadowstep (30)"
+ set desc = "Vanish into the shadows."
+ var/datum/mind/M = usr.mind
+ if(!M) return
+
+ // Teleport radii
+ var/inner_tele_radius = 0
+ var/outer_tele_radius = 6
+
+ // Maximum lighting_lumcount.
+ var/max_lum = 1
+
+ if(M.current.vampire_power(30, 0))
+ if(M.current.buckled) M.current.buckled.unbuckle()
+ spawn(0)
+ var/list/turfs = new/list()
+ for(var/turf/T in range(usr,outer_tele_radius))
+ if(T in range(usr,inner_tele_radius)) continue
+ if(istype(T,/turf/space)) continue
+ if(T.density) continue
+ if(T.x>world.maxx-outer_tele_radius || T.xworld.maxy-outer_tele_radius || T.y max_lum) continue
+ turfs += T
+
+ if(!turfs.len)
+ usr << "\red You cannot find darkness to step to."
+ return
+
+ var/turf/picked = pick(turfs)
+
+ if(!picked || !isturf(picked))
+ return
+ M.current.ExtinguishMob()
+ if(M.current.buckled)
+ M.current.buckled.unbuckle()
+ var/atom/movable/overlay/animation = new /atom/movable/overlay( get_turf(usr) )
+ animation.name = usr.name
+ animation.density = 0
+ animation.anchored = 1
+ animation.icon = usr.icon
+ animation.alpha = 127
+ animation.layer = 5
+ //animation.master = src
+ usr.loc = picked
+ spawn(10)
+ del(animation)
+ M.current.remove_vampire_blood(30)
+ M.current.verbs -= /client/proc/vampire_shadowstep
+ spawn(20)
+ M.current.verbs += /client/proc/vampire_shadowstep
+
+/mob/proc/remove_vampire_blood(amount = 0)
+ var/bloodold
+ if(!mind || !mind.vampire)
+ return
+ bloodold = mind.vampire.bloodusable
+ mind.vampire.bloodusable = max(0, (mind.vampire.bloodusable - amount))
+ if(bloodold != mind.vampire.bloodusable)
+ src << "\blue You have [mind.vampire.bloodusable] left to use."
\ No newline at end of file
diff --git a/code/game/gamemodes/wizard/artefact.dm b/code/game/gamemodes/wizard/artefact.dm
new file mode 100644
index 00000000000..ace9429c751
--- /dev/null
+++ b/code/game/gamemodes/wizard/artefact.dm
@@ -0,0 +1,206 @@
+
+/////////Apprentice Contract//////////
+
+/obj/item/weapon/contract
+ name = "contract"
+ desc = "A magic contract previously signed by an apprentice. In exchange for instruction in the magical arts, they are bound to answer your call for aid."
+ icon = 'icons/obj/wizard.dmi'
+ icon_state ="scroll2"
+ throw_speed = 1
+ throw_range = 5
+ w_class = 1.0
+ var/used = 0
+ flags = FPRINT | TABLEPASS
+
+
+/obj/item/weapon/contract/attack_self(mob/user as mob)
+ user.set_machine(src)
+ var/dat
+ if(used)
+ dat = "You have already summoned your apprentice.
"
+ else
+ dat = "Contract of Apprenticeship:
"
+ dat += "Using this contract, you may summon an apprentice to aid you on your mission.
"
+ dat += "If you are unable to establish contact with your apprentice, you can feed the contract back to the spellbook to refund your points.
"
+ dat += "Which school of magic is your apprentice studying?:
"
+ dat += "Destruction
"
+ dat += "Your apprentice is skilled in offensive magic. They know Magic Missile and Fireball.
"
+ dat += "Bluespace Manipulation
"
+ dat += "Your apprentice is able to defy physics, melting through solid objects and travelling great distances in the blink of an eye. They know Teleport and Ethereal Jaunt.
"
+ dat += "Healing
"
+ dat += "Your apprentice is training to cast spells that will aid your survival. They know Forcewall and Charge and come with a Staff of Healing.
"
+ dat += "Robeless
"
+ dat += "Your apprentice is training to cast spells without their robes. They know Knock and Mindswap.
"
+ user << browse(dat, "window=radio")
+ onclose(user, "radio")
+ return
+
+
+/obj/item/weapon/contract/Topic(href, href_list)
+ ..()
+ var/mob/living/carbon/human/H = usr
+
+ if(H.stat || H.restrained())
+ return
+ if(!istype(H, /mob/living/carbon/human))
+ return 1
+
+ if(loc == H || (in_range(src, H) && istype(loc, /turf)))
+ H.set_machine(src)
+ if(href_list["school"])
+ if (used)
+ H << "You already used this contract!"
+ return
+ var/list/candidates = get_candidates(BE_WIZARD)
+ if(candidates.len)
+ src.used = 1
+ var/client/C = pick(candidates)
+ new /obj/effect/effect/harmless_smoke(H.loc)
+ var/mob/living/carbon/human/M = new/mob/living/carbon/human(H.loc)
+ M.key = C.key
+ M << "You are the [H.real_name]'s apprentice! You are bound by magic contract to follow their orders and help them in accomplishing their goals."
+ switch(href_list["school"])
+ if("destruction")
+ M.spell_list += new /obj/effect/proc_holder/spell/targeted/projectile/magic_missile(M)
+ M.spell_list += new /obj/effect/proc_holder/spell/dumbfire/fireball(M)
+ M << "Your service has not gone unrewarded, however. Studying under [H.real_name], you have learned powerful, destructive spells. You are able to cast magic missile and fireball."
+ if("bluespace")
+ M.spell_list += new /obj/effect/proc_holder/spell/targeted/area_teleport/teleport(M)
+ M.spell_list += new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(M)
+ M << "Your service has not gone unrewarded, however. Studying under [H.real_name], you have learned reality bending mobility spells. You are able to cast teleport and ethereal jaunt."
+ if("healing")
+ M.spell_list += new /obj/effect/proc_holder/spell/targeted/charge(M)
+ M.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/forcewall(M)
+ M.equip_to_slot_or_del(new /obj/item/weapon/gun/magic/staff/healing(M), slot_r_hand)
+ M << "Your service has not gone unrewarded, however. Studying under [H.real_name], you have learned livesaving survival spells. You are able to cast charge and forcewall."
+ if("robeless")
+ M.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/knock(M)
+ M.spell_list += new /obj/effect/proc_holder/spell/targeted/mind_transfer(M)
+ M << "Your service has not gone unrewarded, however. Studying under [H.real_name], you have learned stealthy, robeless spells. You are able to cast knock and mindswap."
+ M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_l_ear)
+ M.equip_to_slot_or_del(new /obj/item/clothing/under/lightpurple(M), slot_w_uniform)
+ M.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(M), slot_shoes)
+ M.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(M), slot_wear_suit)
+ M.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(M), slot_head)
+ M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(M), slot_back)
+ M.equip_to_slot_or_del(new /obj/item/weapon/storage/box(M), slot_in_backpack)
+ M.equip_to_slot_or_del(new /obj/item/weapon/teleportation_scroll/apprentice(M), slot_r_store)
+ var/wizard_name_first = pick(wizard_first)
+ var/wizard_name_second = pick(wizard_second)
+ var/randomname = "[wizard_name_first] [wizard_name_second]"
+ var/newname = copytext(sanitize(input(M, "You are the wizard's apprentice. Would you like to change your name to something else?", "Name change", randomname) as null|text),1,MAX_NAME_LEN)
+
+ if (!newname)
+ newname = randomname
+ M.mind.name = newname
+ M.real_name = newname
+ M.name = newname
+ var/datum/objective/protect/new_objective = new /datum/objective/protect
+ new_objective.owner = M:mind
+ new_objective:target = H:mind
+ new_objective.explanation_text = "Protect [H.real_name], the wizard."
+ M.mind.objectives += new_objective
+ ticker.mode.traitors += M.mind
+ M.mind.special_role = "apprentice"
+
+ else
+ H << "Unable to reach your apprentice! You can either attack the spellbook with the contract to refund your points, or wait and try again later."
+ return
+
+
+///////////////////////////Veil Render//////////////////////
+
+/obj/item/weapon/veilrender
+ name = "veil render"
+ desc = "A wicked curved blade of alien origin, recovered from the ruins of a vast city."
+ icon = 'icons/obj/wizard.dmi'
+ icon_state = "render"
+ item_state = "render"
+ flags = FPRINT | TABLEPASS
+ force = 15
+ throwforce = 10
+ w_class = 3
+ var/charged = 1
+
+/obj/effect/rend
+ name = "tear in the fabric of reality"
+ desc = "You should run now"
+ icon = 'icons/obj/biomass.dmi'
+ icon_state = "rift"
+ density = 1
+ unacidable = 1
+ anchored = 1.0
+
+/obj/effect/rend/New()
+ spawn(50)
+ new /obj/machinery/singularity/narsie/wizard(get_turf(src))
+ del(src)
+ return
+ return
+
+/obj/item/weapon/veilrender/attack_self(mob/user as mob)
+ if(charged == 1)
+ new /obj/effect/rend(get_turf(usr))
+ charged = 0
+ visible_message("\red [src] hums with power as [usr] deals a blow to reality itself!")
+ else
+ user << "\red The unearthly energies that powered the blade are now dormant."
+
+
+
+/obj/item/weapon/veilrender/vealrender
+ name = "veal render"
+ desc = "A wicked curved blade of alien origin, recovered from the ruins of a vast farm."
+
+/obj/item/weapon/veilrender/vealrender/attack_self(mob/user as mob)
+ if(charged)
+ new /obj/effect/rend/cow(get_turf(usr))
+ charged = 0
+ visible_message("\red [src] hums with power as [usr] deals a blow to hunger itself!")
+ else
+ user << "\red The unearthly energies that powered the blade are now dormant."
+
+/obj/effect/rend/cow
+ desc = "Reverberates with the sound of ten thousand moos."
+ var/cowsleft = 20
+
+/obj/effect/rend/cow/New()
+ processing_objects.Add(src)
+ return
+
+/obj/effect/rend/cow/process()
+ if(locate(/mob) in loc) return
+ new /mob/living/simple_animal/cow(loc)
+ cowsleft--
+ if(cowsleft <= 0)
+ del src
+
+/obj/effect/rend/cow/attackby(obj/item/I as obj, mob/user as mob)
+ if(istype(I, /obj/item/weapon/nullrod))
+ visible_message("\red [I] strikes a blow against \the [src], banishing it!")
+ spawn(1)
+ del src
+ return
+ ..()
+
+
+/////////////////////////////////////////Scrying///////////////////
+
+/obj/item/weapon/scrying
+ name = "scrying orb"
+ desc = "An incandescent orb of otherworldly energy, staring into it gives you vision beyond mortal means."
+ icon = 'icons/obj/projectiles.dmi'
+ icon_state ="bluespace"
+ throw_speed = 7
+ throw_range = 15
+ throwforce = 15
+ damtype = BURN
+ force = 15
+ flags = FPRINT | TABLEPASS
+ hitsound = 'sound/items/welder2.ogg'
+
+/obj/item/weapon/scrying/attack_self(mob/user as mob)
+ user << "\blue You can see...everything!"
+ visible_message("\red [usr] stares into [src], their eyes glazing over.")
+ user.ghostize(1)
+ return
\ No newline at end of file
diff --git a/code/game/gamemodes/wizard/rightandwrong.dm b/code/game/gamemodes/wizard/rightandwrong.dm
index e39cb1fdf34..ba5f062ada4 100644
--- a/code/game/gamemodes/wizard/rightandwrong.dm
+++ b/code/game/gamemodes/wizard/rightandwrong.dm
@@ -1,62 +1,111 @@
-/mob/proc/rightandwrong()
- usr << "You summoned guns!"
- message_admins("[key_name_admin(usr, 1)] summoned guns!")
+/mob/proc/rightandwrong(var/summon_type) //0 = Summon Guns, 1 = Summon Magic
+ usr << "You summoned [summon_type ? "magic" : "guns"]!"
+ message_admins("[key_name_admin(usr, 1)] summoned [summon_type ? "magic" : "guns"]!")
for(var/mob/living/carbon/human/H in player_list)
if(H.stat == 2 || !(H.client)) continue
- if(is_special_character(H)) continue
- if(prob(25))
+ if(H.mind)
+ if(H.mind.special_role == "Wizard" || H.mind.special_role == "apprentice") continue
+ if(prob(25) && !(H.mind in ticker.mode.traitors))
ticker.mode.traitors += H.mind
H.mind.special_role = "traitor"
var/datum/objective/survive/survive = new
survive.owner = H.mind
H.mind.objectives += survive
+ H.attack_log += "\[[time_stamp()]\] Was made into a survivor, and trusts no one!"
H << "You are the survivor! Your own safety matters above all else, trust no one and kill anyone who gets in your way. However, armed as you are, now would be the perfect time to settle that score or grab that pair of yellow gloves you've been eyeing..."
var/obj_count = 1
for(var/datum/objective/OBJ in H.mind.objectives)
H << "Objective #[obj_count]: [OBJ.explanation_text]"
obj_count++
- var/randomize = pick("taser","egun","laser","revolver","detective","smg","nuclear","deagle","gyrojet","pulse","silenced","cannon","doublebarrel","shotgun","combatshotgun","mateba","smg","uzi","crossbow","saw")
- switch (randomize)
- if("taser")
- new /obj/item/weapon/gun/energy/taser(get_turf(H))
- if("egun")
- new /obj/item/weapon/gun/energy/gun(get_turf(H))
- if("laser")
- new /obj/item/weapon/gun/energy/laser(get_turf(H))
- if("revolver")
- new /obj/item/weapon/gun/projectile/revolver(get_turf(H))
- if("detective")
- new /obj/item/weapon/gun/projectile/revolver/detective(get_turf(H))
- if("smg")
- new /obj/item/weapon/gun/projectile/automatic/c20r(get_turf(H))
- if("nuclear")
- new /obj/item/weapon/gun/energy/gun/nuclear(get_turf(H))
- if("deagle")
- new /obj/item/weapon/gun/projectile/automatic/deagle/camo(get_turf(H))
- if("gyrojet")
- new /obj/item/weapon/gun/projectile/automatic/gyropistol(get_turf(H))
- if("pulse")
- new /obj/item/weapon/gun/energy/pulse_rifle(get_turf(H))
- if("silenced")
- new /obj/item/weapon/gun/projectile/automatic/pistol(get_turf(H))
- new /obj/item/weapon/silencer(get_turf(H))
- if("cannon")
- new /obj/item/weapon/gun/energy/lasercannon(get_turf(H))
- if("doublebarrel")
- new /obj/item/weapon/gun/projectile/revolver/doublebarrel/(get_turf(H))
- if("shotgun")
- new /obj/item/weapon/gun/projectile/shotgun/(get_turf(H))
- if("combatshotgun")
- new /obj/item/weapon/gun/projectile/shotgun/combat(get_turf(H))
- if("mateba")
- new /obj/item/weapon/gun/projectile/revolver/mateba(get_turf(H))
- if("smg")
- new /obj/item/weapon/gun/projectile/automatic(get_turf(H))
- if("uzi")
- new /obj/item/weapon/gun/projectile/automatic/mini_uzi(get_turf(H))
- if("crossbow")
- new /obj/item/weapon/gun/energy/crossbow(get_turf(H))
- if("saw")
- new /obj/item/weapon/gun/projectile/automatic/l6_saw(get_turf(H))
\ No newline at end of file
+ var/randomizeguns = pick("taser","egun","laser","revolver","detective","smg","nuclear","deagle","gyrojet","pulse","silenced","cannon","doublebarrel","shotgun","combatshotgun","mateba","smg","uzi","crossbow","saw")
+ var/randomizemagic = pick("fireball","smoke","blind","mindswap","forcewall","knock","horsemask","charge","wandnothing", "wanddeath", "wandresurrection", "wandpolymorph", "wandteleport", "wanddoor", "wandfireball", "staffchange", "staffhealing", "armor", "scrying")
+ if(!summon_type)
+ switch (randomizeguns)
+ if("taser")
+ new /obj/item/weapon/gun/energy/taser(get_turf(H))
+ if("egun")
+ new /obj/item/weapon/gun/energy/gun(get_turf(H))
+ if("laser")
+ new /obj/item/weapon/gun/energy/laser(get_turf(H))
+ if("revolver")
+ new /obj/item/weapon/gun/projectile/revolver(get_turf(H))
+ if("detective")
+ new /obj/item/weapon/gun/projectile/revolver/detective(get_turf(H))
+ if("smg")
+ new /obj/item/weapon/gun/projectile/automatic/c20r(get_turf(H))
+ if("nuclear")
+ new /obj/item/weapon/gun/energy/gun/nuclear(get_turf(H))
+ if("deagle")
+ new /obj/item/weapon/gun/projectile/automatic/deagle/camo(get_turf(H))
+ if("gyrojet")
+ new /obj/item/weapon/gun/projectile/automatic/gyropistol(get_turf(H))
+ if("pulse")
+ new /obj/item/weapon/gun/energy/pulse_rifle(get_turf(H))
+ if("silenced")
+ new /obj/item/weapon/gun/projectile/automatic/pistol(get_turf(H))
+ new /obj/item/weapon/silencer(get_turf(H))
+ if("cannon")
+ new /obj/item/weapon/gun/energy/lasercannon(get_turf(H))
+ if("doublebarrel")
+ new /obj/item/weapon/gun/projectile/revolver/doublebarrel(get_turf(H))
+ if("shotgun")
+ new /obj/item/weapon/gun/projectile/shotgun/(get_turf(H))
+ if("combatshotgun")
+ new /obj/item/weapon/gun/projectile/shotgun/combat(get_turf(H))
+ if("mateba")
+ new /obj/item/weapon/gun/projectile/revolver/mateba(get_turf(H))
+ if("smg")
+ new /obj/item/weapon/gun/projectile/automatic(get_turf(H))
+ if("uzi")
+ new /obj/item/weapon/gun/projectile/automatic/mini_uzi(get_turf(H))
+ if("crossbow")
+ new /obj/item/weapon/gun/energy/crossbow(get_turf(H))
+ if("saw")
+ new /obj/item/weapon/gun/projectile/automatic/l6_saw(get_turf(H))
+ else
+ switch (randomizemagic)
+ if("fireball")
+ new /obj/item/weapon/spellbook/oneuse/fireball(get_turf(H))
+ if("smoke")
+ new /obj/item/weapon/spellbook/oneuse/smoke(get_turf(H))
+ if("blind")
+ new /obj/item/weapon/spellbook/oneuse/blind(get_turf(H))
+ if("mindswap")
+ new /obj/item/weapon/spellbook/oneuse/mindswap(get_turf(H))
+ if("forcewall")
+ new /obj/item/weapon/spellbook/oneuse/forcewall(get_turf(H))
+ if("knock")
+ new /obj/item/weapon/spellbook/oneuse/knock(get_turf(H))
+ if("horsemask")
+ new /obj/item/weapon/spellbook/oneuse/horsemask(get_turf(H))
+ if("charge")
+ new /obj/item/weapon/spellbook/oneuse/charge(get_turf(H))
+ if("wandnothing")
+ new /obj/item/weapon/gun/magic/wand(get_turf(H))
+ if("wanddeath")
+ new /obj/item/weapon/gun/magic/wand/death(get_turf(H))
+ if("wandresurrection")
+ new /obj/item/weapon/gun/magic/wand/resurrection(get_turf(H))
+ if("wandpolymorph")
+ new /obj/item/weapon/gun/magic/wand/polymorph(get_turf(H))
+ if("wandteleport")
+ new /obj/item/weapon/gun/magic/wand/teleport(get_turf(H))
+ if("wanddoor")
+ new /obj/item/weapon/gun/magic/wand/door(get_turf(H))
+ if("staffchange")
+ new /obj/item/weapon/gun/magic/staff/change(get_turf(H))
+ if("staffhealing")
+ new /obj/item/weapon/gun/magic/staff/healing(get_turf(H))
+ if("armor")
+ new /obj/item/clothing/suit/space/rig/wizard(get_turf(H))
+ new /obj/item/clothing/head/helmet/space/rig/wizard(get_turf(H))
+ if("scrying")
+ new /obj/item/weapon/scrying(get_turf(H))
+ if (!(XRAY in H.mutations))
+ H.mutations.Add(XRAY)
+ H.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS)
+ H.see_in_dark = 8
+ H.see_invisible = SEE_INVISIBLE_LEVEL_TWO
+ H << "\blue The walls suddenly disappear."
diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm
index 70c655ce576..4ed953d36e4 100644
--- a/code/game/gamemodes/wizard/soulstone.dm
+++ b/code/game/gamemodes/wizard/soulstone.dm
@@ -19,9 +19,15 @@
if(istype(M, /mob/living/carbon/human/dummy))
return..()
+ if(M.has_brain_worms()) //Borer stuff - RR
+ user << "This being is corrupted by an alien intelligence and cannot be soul trapped."
+ return..()
+
M.attack_log += text("\[[time_stamp()]\] Has had their soul captured with [src.name] by [user.name] ([user.ckey])")
user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to capture the soul of [M.name] ([M.ckey])")
- msg_admin_attack("[user.name] ([user.ckey]) used the [src.name] to capture the soul of [M.name] ([M.ckey]) (JMP)")
+
+ log_attack("[user.name] ([user.ckey]) used the [src.name] to capture the soul of [M.name] ([M.ckey])")
+
transfer_soul("VICTIM", M, user)
return
@@ -173,9 +179,8 @@
ticker.mode.cult+=Z.mind
ticker.mode.update_cult_icons_added(Z.mind)
del(T)
- Z << "You are playing a Juggernaut. Though slow, you can withstand extreme punishment, and rip apart enemies and walls alike."
+ Z << "You are a Juggernaut. Though slow, your shell can withstand extreme punishment, create shield walls and even deflect energy weapons, and rip apart enemies and walls alike."
Z << "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs."
- Z.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/lesserforcewall(Z)
Z.cancel_camera()
del(C)
@@ -189,9 +194,8 @@
ticker.mode.cult+=Z.mind
ticker.mode.update_cult_icons_added(Z.mind)
del(T)
- Z << "You are playing a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls."
+ Z << "You are a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls."
Z << "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs."
- Z.spell_list += new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift(Z)
Z.cancel_camera()
del(C)
@@ -205,12 +209,8 @@
ticker.mode.cult+=Z.mind
ticker.mode.update_cult_icons_added(Z.mind)
del(T)
- Z << "You are playing an Artificer. You are incredibly weak and fragile, but you are able to construct fortifications, repair allied constructs (by clicking on them), and even create new constructs"
+ Z << "You are an Artificer. You are incredibly weak and fragile, but you are able to construct fortifications, use magic missile, repair allied constructs (by clicking on them), and most important of all create new constructs (Use your Artificer spell to summon a new construct shell and Summon Soulstone to create a new soulstone)."
Z << "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs."
- Z.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/construct/lesser(Z)
- Z.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/wall(Z)
- Z.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/floor(Z)
- Z.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone(Z)
Z.cancel_camera()
del(C)
else
diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm
index ff19ce77648..375a5129c4a 100644
--- a/code/game/gamemodes/wizard/spellbook.dm
+++ b/code/game/gamemodes/wizard/spellbook.dm
@@ -12,6 +12,19 @@
var/max_uses = 5
var/op = 1
+/obj/item/weapon/spellbook/attackby(obj/item/O as obj, mob/user as mob)
+ if(istype(O, /obj/item/weapon/contract))
+ var/obj/item/weapon/contract/contract = O
+ if(contract.used)
+ user << "The contract has been used, you can't get your points back now."
+ else
+ user << "You feed the contract back into the spellbook, refunding your points."
+ src.max_uses++
+ src.uses++
+ del (O)
+
+
+
/obj/item/weapon/spellbook/attack_self(mob/user as mob)
user.set_machine(src)
@@ -24,39 +37,89 @@
dat += "
"
dat += "Memorize which spell:
"
dat += "The number after the spell name is the cooldown time.
"
- dat += "Magic Missile (10)
"
+
+ dat += "Magic Missile (15)
"
+ dat += "This spell fires several, slow moving, magic projectiles at nearby targets. If they hit a target, it is paralyzed and takes minor damage.
"
+
dat += "Fireball (10)
"
- //dat += "Disintegrate (60)
"
+ dat += "This spell fires a fireball in the direction you're facing and does not require wizard garb. Be careful not to fire it at people that are standing next to you.
"
+
+ dat += "Disintegrate (60)
"
+ dat += "This spell instantly kills somebody adjacent to you with the vilest of magick. It has a long cooldown.
"
+
dat += "Disable Technology (60)
"
+ dat += "This spell disables all weapons, cameras and most other technology in range.
"
+
dat += "Smoke (10)
"
+ dat += "This spell spawns a cloud of choking smoke at your location and does not require wizard garb.
"
+
dat += "Blind (30)
"
+ dat += "This spell temporarly blinds a single person and does not require wizard garb.
"
+
dat += "Mind Transfer (60)
"
+ dat += "This spell allows the user to switch bodies with a target. Careful to not lose your memory in the process.
"
+
dat += "Forcewall (10)
"
+ dat += "This spell creates an unbreakable wall that lasts for 30 seconds and does not need wizard garb.
"
+
dat += "Blink (2)
"
+ dat += "This spell randomly teleports you a short distance. Useful for evasion or getting into areas if you have patience.
"
+
dat += "Teleport (60)
"
+ dat += "This spell teleports you to a type of area of your selection. Very useful if you are in danger, but has a decent cooldown, and is unpredictable.
"
+
dat += "Mutate (60)
"
- dat += "Ethereal Jaunt (60)
"
+ dat += "This spell causes you to turn into a hulk and gain telekinesis for a short while.
"
+
+ dat += "Ethereal Jaunt (30)
"
+ dat += "This spell creates your ethereal form, temporarily making you invisible and able to pass through walls.
"
+
dat += "Knock (10)
"
+ dat += "This spell opens nearby doors and does not require wizard garb.
"
+
dat += "Curse of the Horseman (15)
"
-// if(op)
-// dat += "Summon Guns (One time use, global spell)
"
+ dat += "This spell will curse a person to wear an unremovable horse mask (it has glue on the inside) and speak like a horse. It does not require wizard garb.
"
+
+ dat += "Flesh to Stone (60)
"
+ dat += "This spell will curse a person to immediately turn into an unmoving statue. The effect will eventually wear off if the statue is not destroyed.
"
+
+ dat += "Summon Guns (One time use, global spell)
"
+ dat += "Nothing could possibly go wrong with arming a crew of lunatics just itching for an excuse to kill eachother. Just be careful not to get hit in the crossfire!
"
+
+ dat += "Summon Magic (One time use, global spell)
"
+ dat += "Share the wonders of magic with the crew and show them why they aren't to be trusted with it at the same time.
"
+
dat += "
"
dat += "Artefacts:
"
dat += "Powerful items imbued with eldritch magics. Summoning one will count towards your maximum number of spells.
"
dat += "It is recommended that only experienced wizards attempt to wield such artefacts.
"
dat += "
"
+
dat += "Staff of Change
"
+ dat += "An artefact that spits bolts of coruscating energy which cause the target's very form to reshape itself.
"
dat += "
"
- dat += "Mental Focus
"
- dat += "
"
+
dat += "Six Soul Stone Shards and the spell Artificer
"
+ dat += "Soul Stone Shards are ancient tools capable of capturing and harnessing the spirits of the dead and dying. The spell Artificer allows you to create arcane machines for the captured souls to pilot.
"
dat += "
"
+
dat += "Mastercrafted Armor Set
"
+ dat += "An artefact suit of armor that allows you to cast spells while providing more protection against attacks and the void of space.
"
dat += "
"
+
dat += "Staff of Animation
"
+ dat += "An arcane staff capable of shooting bolts of eldritch energy which cause inanimate objects to come to life. This magic doesn't affect machines.
"
dat += "
"
- if(op)
- dat += "Re-memorize Spells
"
+
+ dat += "Contract of Apprenticeship
"
+ dat += "A magical contract binding an apprentice wizard to your service, using it will summon them to your side.
"
+ dat += "
"
+
+ dat += "Scrying Orb
"
+ dat += "An incandescent orb of crackling energy, using it will allow you to ghost while alive, allowing you to spy upon the station with ease. In addition, buying it will permanently grant you x-ray vision.
"
+
+ dat += "
"
+ dat += "Re-memorize Spells
"
user << browse(dat, "window=radio")
onclose(user, "radio")
return
@@ -70,6 +133,10 @@
if(!istype(H, /mob/living/carbon/human))
return 1
+ if(H.mind.special_role == "apprentice")
+ temp = "If you got caught sneaking a peak from your teacher's spellbook, you'd likely be expelled from the Wizard Academy. Better not."
+ return
+
if(loc == H || (in_range(src, H) && istype(loc, /turf)))
H.set_machine(src)
if(href_list["spell_choice"])
@@ -86,14 +153,36 @@
uses--
/*
*/
- var/list/available_spells = list(magicmissile = "Magic Missile", fireball = "Fireball", disintegrate = "Disintegrate", disabletech = "Disable Tech", smoke = "Smoke", blind = "Blind", mindswap = "Mind Transfer", forcewall = "Forcewall", blink = "Blink", teleport = "Teleport", mutate = "Mutate", etherealjaunt = "Ethereal Jaunt", knock = "Knock", horseman = "Curse of the Horseman", summonguns = "Summon Guns", staffchange = "Staff of Change", mentalfocus = "Mental Focus", soulstone = "Six Soul Stone Shards and the spell Artificer", armor = "Mastercrafted Armor Set", staffanimate = "Staff of Animation")
+ var/list/available_spells = list(magicmissile = "Magic Missile", fireball = "Fireball", disintegrate = "Disintegrate", disabletech = "Disable Tech", smoke = "Smoke", blind = "Blind", mindswap = "Mind Transfer", forcewall = "Forcewall", blink = "Blink", teleport = "Teleport", mutate = "Mutate", etherealjaunt = "Ethereal Jaunt", knock = "Knock", horseman = "Curse of the Horseman", fleshtostone = "Flesh to Stone", summonguns = "Summon Guns", summonmagic = "Summon Magic", staffchange = "Staff of Change", soulstone = "Six Soul Stone Shards and the spell Artificer", armor = "Mastercrafted Armor Set", staffanimate = "Staff of Animation")
var/already_knows = 0
for(var/obj/effect/proc_holder/spell/aspell in H.spell_list)
- if(available_spells[href_list["spell_choice"]] == aspell.name)
+ if(available_spells[href_list["spell_choice"]] == initial(aspell.name))
already_knows = 1
- temp = "You already know that spell."
- uses++
- break
+ if(aspell.spell_level >= aspell.level_max)
+ temp = "This spell cannot be improved further."
+ uses++
+ break
+ else
+ aspell.name = initial(aspell.name)
+ aspell.spell_level++
+ aspell.charge_max = round(initial(aspell.charge_max) - aspell.spell_level * (initial(aspell.charge_max) - aspell.cooldown_min)/ aspell.level_max)
+ if(aspell.charge_max < aspell.charge_counter)
+ aspell.charge_counter = aspell.charge_max
+ switch(aspell.spell_level)
+ if(1)
+ temp = "You have improved [aspell.name] into Efficient [aspell.name]."
+ aspell.name = "Efficient [aspell.name]"
+ if(2)
+ temp = "You have further improved [aspell.name] into Quickened [aspell.name]."
+ aspell.name = "Quickened [aspell.name]"
+ if(3)
+ temp = "You have further improved [aspell.name] into Free [aspell.name]."
+ aspell.name = "Free [aspell.name]"
+ if(4)
+ temp = "You have further improved [aspell.name] into Instant [aspell.name]."
+ aspell.name = "Instant [aspell.name]"
+ if(aspell.spell_level >= aspell.level_max)
+ temp += " This spell cannot be strengthened any further."
/*
*/
if(!already_knows)
@@ -101,79 +190,83 @@
if("magicmissile")
feedback_add_details("wizard_spell_learned","MM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
H.spell_list += new /obj/effect/proc_holder/spell/targeted/projectile/magic_missile(H)
- temp = "This spell fires several, slow moving, magic projectiles at nearby targets. If they hit a target, it is paralyzed and takes minor damage."
+ temp = "You have learned magic missile."
if("fireball")
feedback_add_details("wizard_spell_learned","FB") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
H.spell_list += new /obj/effect/proc_holder/spell/dumbfire/fireball(H)
- temp = "This spell fires a fireball in the direction you're facing and does not require wizard garb. Be careful not to fire it at people that are standing next to you."
+ temp = "You have learned fireball."
if("disintegrate")
feedback_add_details("wizard_spell_learned","DG") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
H.spell_list += new /obj/effect/proc_holder/spell/targeted/inflict_handler/disintegrate(H)
- temp = "This spell instantly kills somebody adjacent to you with the vilest of magick. It has a long cooldown."
+ temp = "You have learned disintegrate."
if("disabletech")
feedback_add_details("wizard_spell_learned","DT") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
H.spell_list += new /obj/effect/proc_holder/spell/targeted/emplosion/disable_tech(H)
- temp = "This spell disables all weapons, cameras and most other technology in range."
+ temp = "You have learned disable technology."
if("smoke")
feedback_add_details("wizard_spell_learned","SM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
H.spell_list += new /obj/effect/proc_holder/spell/targeted/smoke(H)
- temp = "This spell spawns a cloud of choking smoke at your location and does not require wizard garb."
+ temp = "You have learned smoke."
if("blind")
feedback_add_details("wizard_spell_learned","BD") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
H.spell_list += new /obj/effect/proc_holder/spell/targeted/trigger/blind(H)
- temp = "This spell temporarly blinds a single person and does not require wizard garb."
+ temp = "You have learned blind."
if("mindswap")
feedback_add_details("wizard_spell_learned","MT") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
H.spell_list += new /obj/effect/proc_holder/spell/targeted/mind_transfer(H)
- temp = "This spell allows the user to switch bodies with a target. Careful to not lose your memory in the process."
+ temp = "You have learned mindswap."
if("forcewall")
feedback_add_details("wizard_spell_learned","FW") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
H.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/forcewall(H)
- temp = "This spell creates an unbreakable wall that lasts for 30 seconds and does not need wizard garb."
+ temp = "You have learned forcewall."
if("blink")
feedback_add_details("wizard_spell_learned","BL") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
H.spell_list += new /obj/effect/proc_holder/spell/targeted/turf_teleport/blink(H)
- temp = "This spell randomly teleports you a short distance. Useful for evasion or getting into areas if you have patience."
+ temp = "You have learned blink."
if("teleport")
feedback_add_details("wizard_spell_learned","TP") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
H.spell_list += new /obj/effect/proc_holder/spell/targeted/area_teleport/teleport(H)
- temp = "This spell teleports you to a type of area of your selection. Very useful if you are in danger, but has a decent cooldown, and is unpredictable."
+ temp = "You have learned teleport."
if("mutate")
feedback_add_details("wizard_spell_learned","MU") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
H.spell_list += new /obj/effect/proc_holder/spell/targeted/genetic/mutate(H)
- temp = "This spell causes you to turn into a hulk and gain telekinesis for a short while."
+ temp = "You have learned mutate."
if("etherealjaunt")
feedback_add_details("wizard_spell_learned","EJ") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
H.spell_list += new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(H)
- temp = "This spell creates your ethereal form, temporarily making you invisible and able to pass through walls."
+ temp = "You have learned ethereal jaunt."
if("knock")
feedback_add_details("wizard_spell_learned","KN") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
H.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/knock(H)
- temp = "This spell opens nearby doors and does not require wizard garb."
+ temp = "You have learned knock."
if("horseman")
feedback_add_details("wizard_spell_learned","HH") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
H.spell_list += new /obj/effect/proc_holder/spell/targeted/horsemask(H)
- temp = "This spell will curse a person to wear an unremovable horse mask (it has glue on the inside) and speak like a horse. It does not require a wizard garb. Do note the curse will disintegrate the target's current mask if they are wearing one."
+ temp = "You have learned curse of the horseman."
+ if("fleshtostone")
+ feedback_add_details("wizard_spell_learned","FS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
+ H.spell_list += new /obj/effect/proc_holder/spell/targeted/inflict_handler/flesh_to_stone(H)
+ temp = "You have learned flesh to stone."
if("summonguns")
feedback_add_details("wizard_spell_learned","SG") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
- H.rightandwrong()
+ H.rightandwrong(0)
max_uses--
- temp = "Nothing could possibly go wrong with arming a crew of lunatics just itching for an excuse to kill eachother. Just be careful not to get hit in the crossfire!"
+ temp = "You have cast summon guns."
+ if("summonmagic")
+ feedback_add_details("wizard_spell_learned","SM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
+ H.rightandwrong(1)
+ max_uses--
+ temp = "You have cast summon magic."
if("staffchange")
feedback_add_details("wizard_spell_learned","ST") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
- new /obj/item/weapon/gun/energy/staff(get_turf(H))
- temp = "An artefact that spits bolts of coruscating energy which cause the target's very form to reshape itself"
- max_uses--
- if("mentalfocus")
- feedback_add_details("wizard_spell_learned","MF") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
- new /obj/item/weapon/gun/energy/staff/focus(get_turf(H))
- temp = "An artefact that channels the will of the user into destructive bolts of force."
+ new /obj/item/weapon/gun/magic/staff/change(get_turf(H))
+ temp = "You have purchased a staff of change."
max_uses--
if("soulstone")
feedback_add_details("wizard_spell_learned","SS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
new /obj/item/weapon/storage/belt/soulstone/full(get_turf(H))
H.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/construct(H)
- temp = "Soul Stone Shards are ancient tools capable of capturing and harnessing the spirits of the dead and dying. The spell Artificer allows you to create arcane machines for the captured souls to pilot."
+ temp = "You have purchased a belt full of soulstones and have learned the artificer spell."
max_uses--
if("armor")
feedback_add_details("wizard_spell_learned","HS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
@@ -181,12 +274,28 @@
new /obj/item/clothing/gloves/purple(get_turf(H))//To complete the outfit
new /obj/item/clothing/suit/space/rig/wizard(get_turf(H))
new /obj/item/clothing/head/helmet/space/rig/wizard(get_turf(H))
- temp = "An artefact suit of armor that allows you to cast spells while providing more protection against attacks and the void of space."
+ temp = "You have purchased a suit of wizard armor."
max_uses--
if("staffanimation")
feedback_add_details("wizard_spell_learned","SA") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
- new /obj/item/weapon/gun/energy/staff/animate(get_turf(H))
- temp = "An artefact that spits bolts of life-force which causes objects which are hit by it to animate and come to life! This magic doesn't affect machines."
+ new /obj/item/weapon/gun/magic/staff/animate(get_turf(H))
+ temp = "You have purchased a staff of animation."
+ max_uses--
+ if("contract")
+ feedback_add_details("wizard_spell_learned","CT") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
+ new /obj/item/weapon/contract(get_turf(H))
+ temp = "You have purchased a contract of apprenticeship."
+ max_uses--
+ if("scrying")
+ feedback_add_details("wizard_spell_learned","SO") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
+ new /obj/item/weapon/scrying(get_turf(H))
+ if (!(XRAY in H.mutations))
+ H.mutations.Add(XRAY)
+ H.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS)
+ H.see_in_dark = 8
+ H.see_invisible = SEE_INVISIBLE_LEVEL_TWO
+ H << "\blue The walls suddenly disappear."
+ temp = "You have purchased a scrying orb, and gained x-ray vision."
max_uses--
else
if(href_list["temp"])
@@ -194,3 +303,154 @@
attack_self(H)
return
+
+//Single Use Spellbooks//
+
+/obj/item/weapon/spellbook/oneuse
+ var/spell = /obj/effect/proc_holder/spell/targeted/projectile/magic_missile //just a placeholder to avoid runtimes if someone spawned the generic
+ var/spellname = "sandbox"
+ var/used = 0
+ name = "spellbook of "
+ uses = 1
+ max_uses = 1
+ desc = "This template spellbook was never meant for the eyes of man..."
+
+/obj/item/weapon/spellbook/oneuse/New()
+ ..()
+ name += spellname
+
+/obj/item/weapon/spellbook/oneuse/attack_self(mob/user as mob)
+ var/obj/effect/proc_holder/spell/S = new spell
+ for(var/obj/effect/proc_holder/spell/knownspell in user.spell_list)
+ if(knownspell.type == S.type)
+ if(user.mind)
+ if(user.mind.special_role == "apprentice" || user.mind.special_role == "Wizard")
+ user <<"You're already far more versed in this spell than this flimsy how-to book can provide."
+ else
+ user <<"You've already read this one."
+ return
+ if(used)
+ recoil(user)
+ else
+ user.spell_list += S
+ user <<"you rapidly read through the arcane book. Suddenly you realize you understand [spellname]!"
+ onlearned(user)
+
+/obj/item/weapon/spellbook/oneuse/proc/recoil(mob/user as mob)
+ user.visible_message("[src] glows in a black light!")
+
+/obj/item/weapon/spellbook/oneuse/proc/onlearned(mob/user as mob)
+ used = 1
+ user.visible_message("[src] glows dark for a second!")
+
+/obj/item/weapon/spellbook/oneuse/attackby()
+ return
+
+/obj/item/weapon/spellbook/oneuse/fireball
+ spell = /obj/effect/proc_holder/spell/dumbfire/fireball
+ spellname = "fireball"
+ icon_state ="bookfireball"
+ desc = "This book feels warm to the touch."
+
+/obj/item/weapon/spellbook/oneuse/fireball/recoil(mob/user as mob)
+ ..()
+ explosion(user.loc, -1, 0, 2, 3, 0, flame_range = 2)
+ del(src)
+
+/obj/item/weapon/spellbook/oneuse/smoke
+ spell = /obj/effect/proc_holder/spell/targeted/smoke
+ spellname = "smoke"
+ icon_state ="booksmoke"
+ desc = "This book is overflowing with the dank arts."
+
+/obj/item/weapon/spellbook/oneuse/smoke/recoil(mob/user as mob)
+ ..()
+ user <<"Your stomach rumbles..."
+ if(user.nutrition)
+ user.nutrition -= 200
+ if(user.nutrition <= 0)
+ user.nutrition = 0
+
+/obj/item/weapon/spellbook/oneuse/blind
+ spell = /obj/effect/proc_holder/spell/targeted/trigger/blind
+ spellname = "blind"
+ icon_state ="bookblind"
+ desc = "This book looks blurry, no matter how you look at it."
+
+/obj/item/weapon/spellbook/oneuse/blind/recoil(mob/user as mob)
+ ..()
+ user <<"You go blind!"
+ user.eye_blind = 10
+
+/obj/item/weapon/spellbook/oneuse/mindswap
+ spell = /obj/effect/proc_holder/spell/targeted/mind_transfer
+ spellname = "mindswap"
+ icon_state ="bookmindswap"
+ desc = "This book's cover is pristine, though its pages look ragged and torn."
+
+/obj/item/weapon/spellbook/oneuse/mindswap/onlearned()
+ spellname = pick("fireball","smoke","blind","forcewall","knock","horses","charge")
+ icon_state = "book[spellname]"
+ name = "spellbook of [spellname]" //Note, desc doesn't change by design
+ ..()
+
+/obj/item/weapon/spellbook/oneuse/mindswap/recoil(mob/user as mob)
+ ..()
+ user <<"You suddenly don't feel like yourself!"
+ wabbajack(user)
+
+/obj/item/weapon/spellbook/oneuse/forcewall
+ spell = /obj/effect/proc_holder/spell/aoe_turf/conjure/forcewall
+ spellname = "forcewall"
+ icon_state ="bookforcewall"
+ desc = "This book has a dedication to mimes everywhere inside the front cover."
+
+/obj/item/weapon/spellbook/oneuse/forcewall/recoil(mob/user as mob)
+ ..()
+ user <<"You suddenly feel very solid!"
+ var/obj/structure/closet/statue/S = new /obj/structure/closet/statue(user.loc, user)
+ S.timer = 30
+ user.drop_item()
+
+
+/obj/item/weapon/spellbook/oneuse/knock
+ spell = /obj/effect/proc_holder/spell/aoe_turf/knock
+ spellname = "knock"
+ icon_state ="bookknock"
+ desc = "This book is hard to hold closed properly."
+
+/obj/item/weapon/spellbook/oneuse/knock/recoil(mob/user as mob)
+ ..()
+ user <<"You're knocked down!"
+ user.Stun(20)
+ user.Weaken(20)
+
+/obj/item/weapon/spellbook/oneuse/horsemask
+ spell = /obj/effect/proc_holder/spell/targeted/horsemask
+ spellname = "horses"
+ icon_state ="bookhorses"
+ desc = "This book is more horse than your mind has room for."
+
+/obj/item/weapon/spellbook/oneuse/horsemask/recoil(mob/living/carbon/user as mob)
+ if(istype(user, /mob/living/carbon/human))
+ user <<"HOR-SIE HAS RISEN"
+ var/obj/item/clothing/mask/horsehead/magichead = new /obj/item/clothing/mask/horsehead
+ magichead.canremove = 0 //curses!
+ magichead.flags_inv = null //so you can still see their face
+ magichead.voicechange = 1 //NEEEEIIGHH
+ user.drop_from_inventory(user.wear_mask)
+ user.equip_to_slot_if_possible(magichead, slot_wear_mask, 1, 1)
+ del(src)
+ else
+ user <<"I say thee neigh"
+
+/obj/item/weapon/spellbook/oneuse/charge
+ spell = /obj/effect/proc_holder/spell/targeted/charge
+ spellname = "charging"
+ icon_state ="bookcharge"
+ desc = "This book is made of 100% post-consumer wizard."
+
+/obj/item/weapon/spellbook/oneuse/charge/recoil(mob/user as mob)
+ ..()
+ user <<"[src] suddenly feels very warm!"
+ empulse(src, 1, 1)
\ No newline at end of file
diff --git a/code/game/gamemodes/wizard/veilrender.dm b/code/game/gamemodes/wizard/veilrender.dm
deleted file mode 100644
index 225158465fa..00000000000
--- a/code/game/gamemodes/wizard/veilrender.dm
+++ /dev/null
@@ -1,39 +0,0 @@
-/obj/item/weapon/veilrender
- name = "veil render"
- desc = "A wicked curved blade of alien origin, recovered from the ruins of a vast city."
- icon = 'icons/obj/wizard.dmi'
- icon_state = "render"
- item_state = "render"
- flags = FPRINT | TABLEPASS
- force = 15
- throwforce = 10
- w_class = 3
- var/charged = 1
-
-
-/obj/effect/rend
- name = "Tear in the fabric of reality"
- desc = "You should run now"
- icon = 'icons/obj/biomass.dmi'
- icon_state = "rift"
- density = 1
- unacidable = 1
- anchored = 1.0
-
-
-/obj/effect/rend/New()
- spawn(50)
- new /obj/machinery/singularity/narsie/wizard(get_turf(src))
- del(src)
- return
- return
-
-
-/obj/item/weapon/veilrender/attack_self(mob/user as mob)
- if(charged == 1)
- new /obj/effect/rend(get_turf(usr))
- charged = 0
- visible_message("\red [src] hums with power as [usr] deals a blow to reality itself!")
- else
- user << "\red The unearthly energies that powered the blade are now dormant"
-
diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm
index add8ee00a66..6bc076304c6 100644
--- a/code/game/gamemodes/wizard/wizard.dm
+++ b/code/game/gamemodes/wizard/wizard.dm
@@ -1,4 +1,3 @@
-
/datum/game_mode
var/list/datum/mind/wizards = list()
@@ -18,7 +17,6 @@
var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds)
var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds)
-
/datum/game_mode/wizard/announce()
world << "The current game mode is - Wizard!"
world << "There is a \red SPACE WIZARD\black on the station. You can't let him achieve his objective!"
@@ -31,6 +29,7 @@
if(possible_wizards.len==0)
return 0
var/datum/mind/wizard = pick(possible_wizards)
+
wizards += wizard
modePlayer += wizard
wizard.assigned_role = "MODE" //So they aren't chosen for other jobs.
@@ -41,15 +40,16 @@
return 0
return 1
-
/datum/game_mode/wizard/pre_setup()
- for(var/datum/mind/wizard in wizards)
- wizard.current.loc = pick(wizardstart)
+ for(var/datum/mind/wiz in wizards)
+ wiz.current.loc = pick(wizardstart)
+
return 1
/datum/game_mode/wizard/post_setup()
for(var/datum/mind/wizard in wizards)
+ log_game("[wizard.key] (ckey) has been selected as a Wizard")
forge_wizard_objectives(wizard)
//learn_basic_spells(wizard.current)
equip_wizard(wizard.current)
@@ -86,7 +86,7 @@
escape_objective.owner = wizard
wizard.objectives += escape_objective
- if(61 to 100)
+ if(61 to 85)
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = wizard
kill_objective.find_target()
@@ -169,8 +169,7 @@
wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(wizard_mob), slot_head)
if(wizard_mob.backbag == 2) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(wizard_mob), slot_back)
if(wizard_mob.backbag == 3) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_norm(wizard_mob), slot_back)
- if(wizard_mob.backbag == 4) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(wizard_mob), slot_back)
- wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/box(wizard_mob), slot_in_backpack)
+ wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(wizard_mob), slot_in_backpack)
// wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/scrying_gem(wizard_mob), slot_l_store) For scrying gem.
wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/teleportation_scroll(wizard_mob), slot_r_store)
wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/spellbook(wizard_mob), slot_r_hand)
@@ -188,6 +187,7 @@
return ..()
var/wizards_alive = 0
+ var/traitors_alive = 0
for(var/datum/mind/wizard in wizards)
if(!istype(wizard.current,/mob/living/carbon))
continue
@@ -195,7 +195,15 @@
continue
wizards_alive++
- if (wizards_alive)
+ if(!wizards_alive)
+ for(var/datum/mind/traitor in traitors)
+ if(!istype(traitor.current,/mob/living/carbon))
+ continue
+ if(traitor.current.stat==2)
+ continue
+ traitors_alive++
+
+ if (wizards_alive || traitors_alive)
return ..()
else
finished = 1
@@ -213,18 +221,18 @@
/datum/game_mode/proc/auto_declare_completion_wizard()
if(wizards.len)
- var/text = "The wizards/witches were:"
+ var/text = "
the wizards/witches were:"
for(var/datum/mind/wizard in wizards)
- text += "
[wizard.key] was [wizard.name] ("
+ text += "
[wizard.key] was [wizard.name] ("
if(wizard.current)
if(wizard.current.stat == DEAD)
text += "died"
else
text += "survived"
if(wizard.current.real_name != wizard.name)
- text += " as [wizard.current.real_name]"
+ text += " as [wizard.current.real_name]"
else
text += "body destroyed"
text += ")"
@@ -247,6 +255,15 @@
else
text += "
The wizard has failed!"
feedback_add_details("wizard_success","FAIL")
+ if(wizard.current && wizard.current.spell_list)
+ text += "
[wizard.name] used the following spells: "
+ var/i = 1
+ for(var/obj/effect/proc_holder/spell/S in wizard.current.spell_list)
+ text += "[S.name]"
+ if(wizard.current.spell_list.len > i)
+ text += ", "
+ i++
+ text += "
"
world << text
return 1
diff --git a/code/game/gamemodes/xenos/xenos.dm b/code/game/gamemodes/xenos/xenos.dm
new file mode 100644
index 00000000000..0dea8e90573
--- /dev/null
+++ b/code/game/gamemodes/xenos/xenos.dm
@@ -0,0 +1,146 @@
+/datum/game_mode
+ var/list/datum/mind/xenos = list()
+
+
+/datum/game_mode/xenos
+ name = "xenos"
+ config_tag = "xenos"
+ required_players = 15
+ recommended_players = 20
+ required_players_secret = 15
+ required_enemies = 3
+ recommended_enemies = 5
+
+ var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds)
+ var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds)
+
+ var/list/raid_objectives = list() //Raid objectives.
+
+/datum/game_mode/xenos/announce()
+ world << "The current game mode is - Xenos!"
+ world << "There is a \red Xenos Attack\black on the station. You can't let them take over!"
+
+/datum/game_mode/xenos/can_start()
+
+ if(!..())
+ return 0
+
+ var/list/candidates = get_players_for_role(BE_ALIEN)
+ var/playersready = 0
+ var/xenos_num
+ for(var/mob/new_player/player in player_list)
+ if((player.client)&&(player.ready))
+ playersready += 1
+
+
+ //Check that we have enough alien candidates
+ if(candidates.len < required_enemies)
+ return 0
+ if (playersready < recommended_players)
+ xenos_num = required_enemies
+ if (playersready >= recommended_players)
+ xenos_num = recommended_enemies
+
+ //Grab candidates randomly until we have enough.
+ while(xenos_num > 0)
+ var/datum/mind/new_xenos = pick(candidates)
+ xenos += new_xenos
+ candidates -= new_xenos
+ xenos_num--
+
+ for(var/datum/mind/xeno in xenos)
+ xeno.assigned_role = "MODE"
+ xeno.special_role = "Alien"
+ return 1
+
+/datum/game_mode/xenos/pre_setup()
+ return 1
+
+/datum/game_mode/xenos/post_setup()
+
+ var/list/turf/xenos_spawn = list()
+
+ for(var/obj/effect/landmark/A in landmarks_list)
+ if(A.name == "Xenos-Spawn")
+ xenos_spawn += get_turf(A)
+ del(A)
+ continue
+
+ var/xenoai_selected = 0
+ var/xenoborg_selected=0
+ var/xenoqueen_selected=0
+ var/spawnpos = 1
+
+ for(var/datum/mind/xeno_mind in xenos)
+ if(spawnpos > xenos_spawn.len)
+ spawnpos = 1
+ xeno_mind.current.loc = xenos_spawn[spawnpos]
+//XenoAI selection
+ if(!xenoai_selected)
+ var/mob/living/silicon/ai/O = new(xeno_mind.current.loc, base_law_type,,1)//No MMI but safety is in effect.
+ O.invisibility = 0
+ O.aiRestorePowerRoutine = 0
+
+ if(xeno_mind.current)
+ xeno_mind.transfer_to(O)
+ O.mind.original = O
+ else
+ O.key = xeno_mind.current.key
+ del(xeno_mind)
+ var/obj/loc_landmark
+ for(var/obj/effect/landmark/start/sloc in landmarks_list)
+ if (sloc.name == "XenoAI")
+ loc_landmark = sloc
+ O.loc = loc_landmark.loc
+ O.icon_state = "ai-alien"
+ O.verbs.Remove(/mob/living/silicon/ai/verb/pick_icon)
+ O.laws = new /datum/ai_laws/alienmov
+ O.name = "Alien AI"
+ xenoai_selected = 1
+ spawnpos++
+ continue
+//XenoQueen Selection
+ if(!xenoqueen_selected)
+ var/mob/living/carbon/alien/humanoid/queen/large/O = new(xeno_mind.current.loc)
+ if(xeno_mind.current)
+ xeno_mind.transfer_to(O)
+ else
+ O.key = xeno_mind.current.key
+ del(xeno_mind)
+ xenoqueen_selected = 1
+ spawnpos++
+ continue
+//XenoBorg Selection
+ if(!xenoborg_selected)
+ var/mob/living/silicon/robot/O = new(xeno_mind.current.loc,0,0,1)
+ O.mmi = new /obj/item/device/mmi(O)
+ O.mmi.alien = 1
+ O.mmi.transfer_identity(xeno_mind.current)//Does not transfer key/client.
+ O.cell = new(O)
+ O.cell.maxcharge = 15000
+ O.cell.charge = 15000
+ O.gender = xeno_mind.current.gender
+ O.invisibility = 0
+
+ O.key = xeno_mind.current.key
+ del(xeno_mind)
+ O.job = "Alien Cyborg"
+ O.name = "Alien Cyborg"
+
+ xenoborg_selected = 1
+ spawnpos++
+ continue
+//Additional larvas if playercount > 20
+ else
+ var/mob/living/carbon/alien/larva/O = new(xeno_mind.current.loc)
+ if(xeno_mind.current)
+ xeno_mind.transfer_to(O)
+ else
+ O.key = xeno_mind.current.key
+ del(xeno_mind)
+ spawnpos++
+
+ spawn (rand(waittime_l, waittime_h))
+ send_intercept()
+
+ return ..()
\ No newline at end of file
diff --git a/code/game/jobs/job/supervisor.dm b/code/game/jobs/job/supervisor.dm
index 95987ded83a..2399dc4aaba 100644
--- a/code/game/jobs/job/supervisor.dm
+++ b/code/game/jobs/job/supervisor.dm
@@ -128,7 +128,7 @@
if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_norm(H), slot_back)
if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back)
H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H.back), slot_in_backpack)
- H.equip_to_slot_or_del(new /obj/item/weapon/melee/baton/ntcane(H.back), slot_in_backpack)
+ H.equip_to_slot_or_del(new /obj/item/weapon/melee/baton/loaded/ntcane(H.back), slot_in_backpack)
H.equip_to_slot_or_del(new /obj/item/weapon/lighter/zippo/fluff/nt_rep(H.back), slot_in_backpack)
H.equip_if_possible(new /obj/item/clothing/under/rank/centcom/representative(H), slot_w_uniform)
H.equip_if_possible(new /obj/item/clothing/shoes/centcom(H), slot_shoes)
diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm
index 81a4338e733..154bbd047d7 100644
--- a/code/game/machinery/Sleeper.dm
+++ b/code/game/machinery/Sleeper.dm
@@ -11,6 +11,11 @@
density = 1
var/orient = "LEFT" // "RIGHT" changes the dir suffix to "-r"
+/obj/machinery/sleep_console/process()
+ if(stat & (NOPOWER|BROKEN))
+ return
+ src.updateUsrDialog()
+ return
/obj/machinery/sleep_console/ex_act(severity)
switch(severity)
@@ -72,10 +77,11 @@
if(occupant.reagents)
for(var/chemical in connected.available_chemicals)
dat += "[connected.available_chemicals[chemical]]: [occupant.reagents.get_reagent_amount(chemical)] units
"
- dat += "
Refresh meter readings each second
"
+ dat += "Refresh Meter Readings
"
if(src.connected.beaker)
+ dat += "
Remove Beaker
"
if(src.connected.filtering)
- dat += "
Stop Dialysis
"
+ dat += "Stop Dialysis
"
dat += text("Output Beaker has [] units of free space remaining
", src.connected.beaker.reagents.maximum_volume - src.connected.beaker.reagents.total_volume)
else
dat += "
Start Dialysis
"
@@ -85,8 +91,8 @@
for(var/chemical in connected.available_chemicals)
dat += "Inject [connected.available_chemicals[chemical]]: "
for(var/amount in connected.amounts)
- dat += "[amount] units "
- dat += "
"
+ dat += "[amount] units
"
+ dat += "
Eject Patient"
else
dat += "The sleeper is empty."
dat += text("
Close", user)
@@ -108,19 +114,21 @@
src.connected.inject_chemical(usr,href_list["chemical"],text2num(href_list["amount"]))
else
usr << "\red \b This person is not in good enough condition for sleepers to be effective! Use another means of treatment, such as cryogenics!"
+ src.updateUsrDialog()
if (href_list["refresh"])
src.updateUsrDialog()
+ if (href_list["removebeaker"])
+ src.connected.remove_beaker()
+ src.updateUsrDialog()
if (href_list["togglefilter"])
src.connected.toggle_filter()
src.updateUsrDialog()
+ if (href_list["ejectify"])
+ src.connected.eject()
+ src.updateUsrDialog()
src.add_fingerprint(usr)
return
-/obj/machinery/sleep_console/process()
- if(stat & (NOPOWER|BROKEN))
- return
- src.updateUsrDialog()
- return
/obj/machinery/sleep_console/power_change()
return
@@ -144,7 +152,7 @@
anchored = 1
var/orient = "LEFT" // "RIGHT" changes the dir suffix to "-r"
var/mob/living/carbon/human/occupant = null
- var/available_chemicals = list("inaprovaline" = "Inaprovaline", "stoxin" = "Soporific", "dermaline" = "Dermaline", "bicaridine" = "Bicaridine", "dexalin" = "Dexalin")
+ var/available_chemicals = list("inaprovaline" = "Inaprovaline", "stoxin" = "Soporific", "anti_toxin" = "Dylovene", "dexalin" = "Dexalin")
var/amounts = list(10, 20)
var/obj/item/weapon/reagent_containers/glass/beaker = null
var/filtering = 0
@@ -192,6 +200,7 @@
user.drop_item()
G.loc = src
user.visible_message("[user] adds \a [G] to \the [src]!", "You add \a [G] to \the [src]!")
+ src.updateUsrDialog()
return
else
user << "\red The sleeper has a beaker already."
diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm
index 28f9bfe4126..31640d7cf1d 100644
--- a/code/game/machinery/adv_med.dm
+++ b/code/game/machinery/adv_med.dm
@@ -249,6 +249,9 @@
dat += text("Paralysis Summary %: [] ([] seconds left!)
", occupant.paralysis, round(occupant.paralysis / 4))
dat += text("Body Temperature: [occupant.bodytemperature-T0C]°C ([occupant.bodytemperature*1.8-459.67]°F)
")
+ if(occupant.has_brain_worms())
+ dat += "Large growth detected in frontal lobe, possibly cancerous. Surgical removal is recommended.
"
+
if(occupant.vessel)
var/blood_volume = round(occupant.vessel.get_reagent_amount("blood"))
var/blood_percent = blood_volume / 560
@@ -278,6 +281,7 @@
var/AN = ""
var/open = ""
var/infected = ""
+ var/robot = ""
var/imp = ""
var/bled = ""
var/splint = ""
@@ -294,6 +298,8 @@
bled = "Bleeding:"
if(e.status & ORGAN_BROKEN)
AN = "[e.broken_description]:"
+ if(e.status & ORGAN_ROBOT)
+ robot = "Prosthetic:"
if(e.open)
open = "Open:"
if(e.implants.len)
@@ -301,16 +307,25 @@
if(!AN && !open && !infected & !imp)
AN = "None:"
if(!(e.status & ORGAN_DESTROYED))
- dat += "[e.display_name] | [e.burn_dam] | [e.brute_dam] | [bled][AN][splint][open][infected][imp][internal_bleeding][lung_ruptured] | "
+ dat += "[e.display_name] | [e.burn_dam] | [e.brute_dam] | [robot][bled][AN][splint][open][infected][imp][internal_bleeding][lung_ruptured] | "
else
dat += "[e.display_name] | - | - | Not Found | "
dat += ""
for(var/organ_name in occupant.internal_organs)
var/datum/organ/internal/i = occupant.internal_organs[organ_name]
+ var/mech = ""
+ if(i.robotic == 1)
+ mech = "Assisted:"
+ if(i.robotic == 2)
+ mech = "Mechanical:"
dat += ""
- dat += "| [i.name] | N/A | [i.damage] | None: | "
+ dat += "[i.name] | N/A | [i.damage] | None:[mech] | | "
dat += "
"
dat += ""
+ if(occupant.sdisabilities & BLIND)
+ dat += text("Cataracts detected.
")
+ if(occupant.sdisabilities & NEARSIGHTED)
+ dat += text("Retinal misalignment detected.
")
else
dat += "\The [src] is empty."
else
diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm
index 6cbdea01e46..557c54e74ad 100644
--- a/code/game/machinery/alarm.dm
+++ b/code/game/machinery/alarm.dm
@@ -96,7 +96,8 @@
var/screen = AALARM_SCREEN_MAIN
var/area_uid
var/area/alarm_area
- var/danger_level = 0
+ var/local_danger_level = 0
+ var/alarmActivated = 0 // Manually activated (independent from danger level)
var/danger_averted_confidence=0
var/buildstage = 2 //2 is built, 1 is building, 0 is frame.
@@ -226,10 +227,8 @@
target_temperature = T0C + MIN_TEMPERATURE
var/datum/gas_mixture/gas = location.remove_air(0.25*environment.total_moles)
- var/heat_capacity = 0
- if(gas)
- heat_capacity = gas.heat_capacity()
- var/energy_used = min( abs( heat_capacity*(gas.temperature - target_temperature) ), MAX_ENERGY_CHANGE)
+ var/heat_capacity = gas.heat_capacity()
+ var/energy_used = max( abs( heat_capacity*(gas.temperature - target_temperature) ), MAX_ENERGY_CHANGE)
//Use power. Assuming that each power unit represents 1000 watts....
use_power(energy_used/1000, ENVIRON)
@@ -247,15 +246,15 @@
visible_message("\The [src] clicks quietly as it stops [environment.temperature > target_temperature ? "cooling" : "heating"] the room.",\
"You hear a click as a faint electronic humming stops.")
- var/old_level = danger_level
- danger_level = overall_danger_level()
- if(danger_level < old_level)
+ var/old_level = local_danger_level
+ var/new_danger = calculate_local_danger_level()
+ if(new_danger < old_level)
danger_averted_confidence++
// Only change danger level if:
// we're going up a level
- // OR if we're going down a level and have sufficient confidence (prevents doors smashing open and closed).
- if (old_level < danger_level || (danger_averted_confidence >= 5 && danger_level < old_level))
- refresh_danger_level()
+ // OR if we're going down a level and have sufficient confidence (prevents spamming update_icon).
+ if (old_level < new_danger || (danger_averted_confidence >= 5 && new_danger < old_level))
+ setDangerLevel(new_danger)
update_icon()
danger_averted_confidence=0 // Reset counter.
@@ -269,7 +268,7 @@
if(RCON_NO)
remote_control = 0
if(RCON_AUTO)
- if(danger_level == 2)
+ if(local_danger_level == 2)
remote_control = 1
else
remote_control = 0
@@ -279,7 +278,7 @@
updateDialog()
return
-/obj/machinery/alarm/proc/overall_danger_level()
+/obj/machinery/alarm/proc/calculate_local_danger_level()
var/turf/simulated/location = loc
if(!istype(location)) return//returns if loc is not simulated
@@ -335,7 +334,8 @@
if((stat & (NOPOWER|BROKEN)) || shorted)
icon_state = "alarmp"
return
- switch(max(danger_level, alarm_area.atmosalm))
+
+ switch(max(local_danger_level, alarm_area.atmosalm-1))
if (0)
icon_state = "alarm0"
if (1)
@@ -344,7 +344,7 @@
icon_state = "alarm1"
/obj/machinery/alarm/receive_signal(datum/signal/signal)
- if(stat & (NOPOWER|BROKEN))
+ if(stat & (NOPOWER|BROKEN) || !alarm_area)
return
if (alarm_area.master_air_alarm != src)
if (master_is_operating())
@@ -457,23 +457,14 @@
for(var/device_id in alarm_area.air_vent_names)
send_signal(device_id, list("power"= 0) )
-/obj/machinery/alarm/proc/apply_danger_level(var/new_danger_level)
- if (alarm_area.atmosalert(new_danger_level))
+// This sets our danger level, and, if it's changed, forces a new election of danger levels.
+/obj/machinery/alarm/proc/setDangerLevel(var/new_danger_level)
+ if(local_danger_level==new_danger_level)
+ return
+ local_danger_level=new_danger_level
+ if(alarm_area.updateDangerLevel())
post_alert(new_danger_level)
- if(danger_level > 1)
- air_doors_close(0)
- else
- air_doors_open(0)
-
- update_icon()
-
- for (var/area/A in alarm_area.related)
- for (var/obj/machinery/alarm/AA in A)
- if ( !(AA.stat & (NOPOWER|BROKEN)) && !AA.shorted && AA.danger_level != new_danger_level)
- AA.danger_level=new_danger_level
- AA.update_icon()
-
/obj/machinery/alarm/proc/post_alert(alert_level)
var/datum/radio_frequency/frequency = radio_controller.return_frequency(alarm_frequency)
if(!frequency)
@@ -494,15 +485,6 @@
frequency.post_signal(src, alert_signal)
-/obj/machinery/alarm/proc/refresh_danger_level()
- var/level = 0
- for (var/area/A in alarm_area.related)
- for (var/obj/machinery/alarm/AA in A)
- if ( !(AA.stat & (NOPOWER|BROKEN)) && !AA.shorted)
- if (AA.danger_level > level)
- level = AA.danger_level
- apply_danger_level(level)
-
/obj/machinery/alarm/proc/air_doors_close(manual)
var/area/A = get_area(src)
if(!A.master.air_doors_activated)
@@ -601,9 +583,8 @@
apply_mode()
if(AALARM_WIRE_AALARM)
-
- if (alarm_area.atmosalert(2))
- apply_danger_level(2)
+ alarmActivated=1
+ alarm_area.updateDangerLevel()
spawn(1)
updateUsrDialog()
update_icon()
@@ -665,8 +646,8 @@
apply_mode()
if(AALARM_WIRE_AALARM)
- if (alarm_area.atmosalert(0))
- apply_danger_level(0)
+ alarmActivated=0
+ alarm_area.updateDangerLevel()
spawn(1)
updateUsrDialog()
update_icon()
@@ -767,10 +748,11 @@
data["danger"]=danger
return data
-
/obj/machinery/alarm/proc/get_nano_data(mob/user, fromAtmosConsole=0)
+
var/data[0]
data["air"]=ui_air_status()
+ data["alarmActivated"]=alarmActivated || local_danger_level==2
data["sensors"]=TLV
data["locked"]=fromAtmosConsole || (!(istype(user, /mob/living/silicon)) && locked)
data["rcon"]=rcon_setting
@@ -818,11 +800,13 @@
data["scrubbers"]=scrubbers
return data
+
/obj/machinery/alarm/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null)
if(user.stat && !isobserver(user))
return
var/list/data=src.get_nano_data(user,FALSE)
+
if (!ui) // no ui has been passed, so we'll search for one
{
ui = nanomanager.get_open_ui(user, src, ui_key)
@@ -888,288 +872,6 @@
ui_interact(user)
return
-/*
-/obj/machinery/alarm/proc/return_text(mob/user)
- if(!(istype(user, /mob/living/silicon)) && locked)
- return "\The [src][return_status()]
[rcon_text()]
(Swipe ID card to unlock interface)"
- else
- return "\The [src][return_status()]
[rcon_text()]
[return_controls()]"
-
-/obj/machinery/alarm/proc/return_status()
- var/turf/location = get_turf(src)
- var/datum/gas_mixture/environment = location.return_air()
- var/total = environment.oxygen + environment.carbon_dioxide + environment.toxins + environment.nitrogen
- var/output = "Air Status:
"
-
- if(total == 0)
- output += "Warning: Cannot obtain air sample for analysis."
- return output
-
- output += {"
-
-"}
-
- var/partial_pressure = R_IDEAL_GAS_EQUATION*environment.temperature/environment.volume
-
- var/list/current_settings = TLV["pressure"]
- var/environment_pressure = environment.return_pressure()
- var/pressure_dangerlevel = get_danger_level(environment_pressure, current_settings)
-
- current_settings = TLV["oxygen"]
- var/oxygen_dangerlevel = get_danger_level(environment.oxygen*partial_pressure, current_settings)
- var/oxygen_percent = round(environment.oxygen / total * 100, 2)
-
- current_settings = TLV["carbon_dioxide"]
- var/co2_dangerlevel = get_danger_level(environment.carbon_dioxide*partial_pressure, current_settings)
- var/co2_percent = round(environment.carbon_dioxide / total * 100, 2)
-
- current_settings = TLV["plasma"]
- var/plasma_dangerlevel = get_danger_level(environment.toxins*partial_pressure, current_settings)
- var/plasma_percent = round(environment.toxins / total * 100, 2)
-
- current_settings = TLV["other"]
- var/other_moles = 0.0
- for(var/datum/gas/G in environment.trace_gases)
- other_moles+=G.moles
- var/other_dangerlevel = get_danger_level(other_moles*partial_pressure, current_settings)
-
- current_settings = TLV["temperature"]
- var/temperature_dangerlevel = get_danger_level(environment.temperature, current_settings)
-
- output += {"
-Pressure: [environment_pressure]kPa
-Oxygen: [oxygen_percent]%
-Carbon dioxide: [co2_percent]%
-Toxins: [plasma_percent]%
-"}
- if (other_dangerlevel==2)
- output += "Notice: High Concentration of Unknown Particles Detected
"
- else if (other_dangerlevel==1)
- output += "Notice: Low Concentration of Unknown Particles Detected
"
-
- output += "Temperature: [environment.temperature]K ([round(environment.temperature - T0C, 0.1)]C)
"
-
- //Overall status
- output += "Local Status: "
- switch(max(pressure_dangerlevel,oxygen_dangerlevel,co2_dangerlevel,plasma_dangerlevel,other_dangerlevel,temperature_dangerlevel))
- if(2)
- output += "DANGER: Internals Required"
- if(1)
- output += "Caution"
- if(0)
- if(alarm_area.atmosalm)
- output += {"Caution: Atmos alert in area"}
- else
- output += {"Optimal"}
-
- return output
-
-/obj/machinery/alarm/proc/rcon_text()
- var/dat = "Remote Control: "
- if(rcon_setting == RCON_NO)
- dat += "Off"
- else
- dat += "Off"
- dat += " | "
- if(rcon_setting == RCON_AUTO)
- dat += "Auto"
- else
- dat += "Auto"
- dat += " | "
- if(rcon_setting == RCON_YES)
- dat += "On"
- else
- dat += "On | "
-
- //Hackish, I know. I didn't feel like bothering to rework all of this.
- dat += "Thermostat: [target_temperature - T0C]C |
"
-
- return dat
-
-/obj/machinery/alarm/proc/fmtScrubberGasStatus(var/id_tag,var/code,var/list/data)
- var/label=replacetext(uppertext(code),"2","2")
- if(code=="tox")
- label="Plasma"
- return "[label]"
-
-/obj/machinery/alarm/proc/return_controls()
- var/output = ""//"[alarm_zone] Air [name]
"
-
- switch(screen)
- if (AALARM_SCREEN_MAIN)
- if(alarm_area.atmosalm)
- output += "Reset - Atmospheric Alarm
"
- else
- output += "Activate - Atmospheric Alarm
"
-
- output += {"
-Scrubbers Control
-Vents Control
-Set environmentals mode
-Sensor Settings
-
-"}
- if (mode==AALARM_MODE_PANIC)
- output += "PANIC SYPHON ACTIVE
Turn syphoning off"
- else
- output += "ACTIVATE PANIC SYPHON IN AREA"
-
-
- if (AALARM_SCREEN_VENT)
- var/sensor_data = ""
- if(alarm_area.air_vent_names.len)
- for(var/id_tag in alarm_area.air_vent_names)
- var/long_name = alarm_area.air_vent_names[id_tag]
- var/list/data = alarm_area.air_vent_info[id_tag]
- if(!data)
- continue;
- var/state = ""
-
- sensor_data += {"
-[long_name][state]
-Operating:
-[data["power"]?"on":"off"]
-
-Pressure checks:
-external
-internal
-
-External pressure bound:
--
--
--
--
-[data["external"]]
-+
-+
-+
-+
- (reset)
-
-"}
- if (data["direction"] == "siphon")
- sensor_data += {"
-Direction:
-siphoning
-
-"}
- sensor_data += {"
"}
- else
- sensor_data = "No vents connected.
"
- output = {"Main menu
[sensor_data]"}
- if (AALARM_SCREEN_SCRUB)
- var/sensor_data = ""
- if(alarm_area.air_scrub_names.len)
- for(var/id_tag in alarm_area.air_scrub_names)
- var/long_name = alarm_area.air_scrub_names[id_tag]
- var/list/data = alarm_area.air_scrub_info[id_tag]
- if(!data)
- continue;
- var/state = ""
-
- sensor_data += {"
-[long_name][state]
-Operating:
-[data["power"]?"on":"off"]
-Type:
-[data["scrubbing"]?"scrubbing":"syphoning"]
-"}
-
- if(data["scrubbing"])
- sensor_data += {"
-Filtering:
-[fmtScrubberGasStatus(id_tag,"co2",data)],
-[fmtScrubberGasStatus(id_tag,"tox",data)],
-[fmtScrubberGasStatus(id_tag,"n2o",data)],
-[fmtScrubberGasStatus(id_tag,"o2",data)]
-
-"}
- sensor_data += {"
-Panic syphon: [data["panic"]?"PANIC SYPHON ACTIVATED":""]
-Dea":"red'>A")]ctivate
-
-"}
- else
- sensor_data = "No scrubbers connected.
"
- output = {"Main menu
[sensor_data]"}
-
- if (AALARM_SCREEN_MODE)
- output += "Main menu
Air machinery mode for the area:"
- var/list/modes = list(
- AALARM_MODE_SCRUBBING = "Filtering - Scrubs out contaminants",\
- AALARM_MODE_REPLACEMENT = "Replace Air - Siphons out air while replacing",\
- AALARM_MODE_PANIC = "Panic - Siphons air out of the room",\
- AALARM_MODE_CYCLE = "Cycle - Siphons air before replacing",\
- AALARM_MODE_FILL = "Fill - Shuts off scrubbers and opens vents",\
- AALARM_MODE_OFF = "Off - Shuts off vents and scrubbers",)
- for (var/m=1,m<=modes.len,m++)
- if (mode==m)
- output += "- [modes[m]] (selected)
"
- else
- output += "- [modes[m]]
"
- output += {"
-
Sensor presets:
(Note, this only sets sensors, air supplied to vents must still be changed.)"}
- var/list/presets = list(
- AALARM_PRESET_HUMAN = "Human - Checks for Oxygen and Nitrogen",\
- AALARM_PRESET_VOX = "Vox - Checks for Nitrogen only",\
- AALARM_PRESET_SERVER = "Coldroom - For server rooms and freezers")
- for(var/p=1;p<=presets.len;p++)
- if (preset==p)
- output += "- [presets[p]] (selected)
"
- else
- output += "- [presets[p]]
"
- output += "
"
-
- if (AALARM_SCREEN_SENSORS)
- output += {"
-Main menu
-Alarm thresholds:
-Partial pressure for gases
-
- | min2 | min1 | max1 | max2 |
-"}
- var/list/gases = list(
- "oxygen" = "O2",
- "carbon_dioxide" = "CO2",
- "plasma" = "Toxin",
- "other" = "Other",)
-
- var/list/selected
- for (var/g in gases)
- output += "| [gases[g]] | "
- selected = TLV[g]
- for(var/i = 1, i <= 4, i++)
- output += "[selected[i] >= 0 ? selected[i] :"OFF"] | "
- output += "
"
-
- selected = TLV["pressure"]
- output += " | Pressure | "
- for(var/i = 1, i <= 4, i++)
- output += "[selected[i] >= 0 ? selected[i] :"OFF"] | "
- output += "
"
-
- selected = TLV["temperature"]
- output += "| Temperature | "
- for(var/i = 1, i <= 4, i++)
- output += "[selected[i] >= 0 ? selected[i] :"OFF"] | "
- output += "
|---|
"
-
- return output
-*/
/obj/machinery/alarm/Topic(href, href_list)
var/changed=0
@@ -1225,8 +927,8 @@ table tr:first-child th:first-child { border: none;}
var/threshold = text2num(href_list["var"])
var/list/selected = TLV[env]
var/list/thresholds = list("lower bound", "low warning", "high warning", "upper bound")
- var/newval = input("Enter [thresholds[threshold]] for [env]", "Alarm triggers", selected[threshold]) as null|num
- if (isnull(newval) || ..() || (locked && issilicon(usr)))
+ var/newval = input("Enter [thresholds[threshold]] for [env]", "Alarm triggers", selected[threshold]) as num|null
+ if (isnull(newval) || ..() || (locked && !issilicon(usr)))
return
if (newval<0)
selected[threshold] = -1.0
@@ -1287,14 +989,14 @@ table tr:first-child th:first-child { border: none;}
*/
if(href_list["atmos_alarm"])
- if (alarm_area.atmosalert(2))
- apply_danger_level(2)
+ alarmActivated=1
+ alarm_area.updateDangerLevel()
update_icon()
changed=1
if(href_list["atmos_reset"])
- if (alarm_area.atmosalert(0))
- apply_danger_level(0)
+ alarmActivated=0
+ alarm_area.updateDangerLevel()
update_icon()
changed=1
@@ -1446,6 +1148,7 @@ table tr:first-child th:first-child { border: none;}
usr << "It is not wired."
if (buildstage < 1)
usr << "The circuit is missing."
+
/*
AIR ALARM CIRCUIT
Just a object used in constructing air alarms
@@ -1525,8 +1228,6 @@ FIRE ALARM
var/wiresexposed = 0
var/buildstage = 2 // 2 = complete, 1 = no wires, 0 = circuit gone
- var/area/A
-
/obj/machinery/firealarm/update_icon()
if(wiresexposed)
@@ -1656,38 +1357,49 @@ FIRE ALARM
stat |= NOPOWER
update_icon()
-
-/obj/machinery/firealarm/New()
- ..()
-
-
-/obj/machinery/firealarm/attack_hand(var/mob/user as mob)
- if(stat & BROKEN)
+/obj/machinery/firealarm/attack_hand(mob/user as mob)
+ if((user.stat && !isobserver(user)) || stat & (NOPOWER|BROKEN))
return
- ui_interact(user)
+ if (buildstage != 2)
+ return
-/obj/machinery/firealarm/ui_interact(mob/user, ui_key = "fire_alarm")
- A = src.loc.loc
- if(stat & (BROKEN|NOPOWER)) return
- if(user.stat || user.restrained()) return
- var/data[0]
- data["working"] = working
- data["time"] = round(time)
- data["timing"] = timing
- data["securityLevel"] = uppertext(get_security_level())
- data["fire"] = A.fire
- var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, ui_key)
- if (!ui)
- ui = new(user, src, ui_key, "firealarm.tmpl", "Fire Alarm", 375, 250)
- ui.set_initial_data(data)
- ui.set_auto_update(1)
- ui.open()
+ user.set_machine(src)
+ var/area/A = src.loc
+ var/d1
+ var/d2
+ if (istype(user, /mob/living/carbon/human) || istype(user, /mob/living/silicon))
+ A = A.loc
+
+ if (A.fire)
+ d1 = text("Reset - Lockdown", src)
+ else
+ d1 = text("Alarm - Lockdown", src)
+ if (src.timing)
+ d2 = text("Stop Time Lock", src)
+ else
+ d2 = text("Initiate Time Lock", src)
+ var/second = round(src.time) % 60
+ var/minute = (round(src.time) - second) / 60
+ var/dat = "Fire alarm [d1]\n
The current alert level is: [get_security_level()]
\nTimer System: [d2]
\nTime Left: [(minute ? "[minute]:" : null)][second] - - + +\n"
+ user << browse(dat, "window=firealarm")
+ onclose(user, "firealarm")
else
- ui.push_data(data)
- return
-
-
+ A = A.loc
+ if (A.fire)
+ d1 = text("[]", src, stars("Reset - Lockdown"))
+ else
+ d1 = text("[]", src, stars("Alarm - Lockdown"))
+ if (src.timing)
+ d2 = text("[]", src, stars("Stop Time Lock"))
+ else
+ d2 = text("[]", src, stars("Initiate Time Lock"))
+ var/second = round(src.time) % 60
+ var/minute = (round(src.time) - second) / 60
+ var/dat = "[stars("Fire alarm")] [d1]\n
The current alert level is: [stars(get_security_level())]
\nTimer System: [d2]
\nTime Left: [(minute ? text("[]:", minute) : null)][second] - - + +\n"
+ user << browse(dat, "window=firealarm")
+ onclose(user, "firealarm")
+ return
/obj/machinery/firealarm/Topic(href, href_list)
..()
@@ -1844,7 +1556,7 @@ Code shamelessly copied from apc_frame
return attack_hand(user)
/obj/machinery/partyalarm/attack_hand(mob/user as mob)
- if(user.stat || stat & (NOPOWER|BROKEN))
+ if((user.stat && !isobserver(user)) || stat & (NOPOWER|BROKEN))
return
user.machine = src
diff --git a/code/game/machinery/atmo_control.dm b/code/game/machinery/atmo_control.dm
index 3f1e72f43a2..80f794c99b7 100644
--- a/code/game/machinery/atmo_control.dm
+++ b/code/game/machinery/atmo_control.dm
@@ -74,7 +74,7 @@ obj/machinery/air_sensor
if(radio_controller)
set_frequency(frequency)
-obj/machinery/computer/general_air_control
+/obj/machinery/computer/general_air_control
icon = 'icons/obj/computer.dmi'
icon_state = "tank"
@@ -89,13 +89,18 @@ obj/machinery/computer/general_air_control
attack_hand(mob/user)
if(..(user))
return
- user << browse(return_text(),"window=computer")
+ var/html=return_text()+"