diff --git a/README.md b/README.md index 661c7de6fde..2c1859126cf 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Click [here](https://github.com/Baystation12/Baystation12/archive/master.zip) to The more complicated and easier to update method is using git. You'll need to download git or some client from [here](http://git-scm.com/). When that's installed, right click in any folder and click on "Git Bash". When that opens, type in: - git clone git@github.com:Baystation12/Baystation12.git + git clone https://github.com/Baystation12/Baystation12.git (hint: hold down ctrl and press insert to paste into git bash) @@ -58,6 +58,12 @@ When you have done this, you'll need to recompile the code, but then it should w --- +### Configuration + +For a basic setup, simply copy every file from config/example to config. + +--- + ### SQL Setup The SQL backend for the library and stats tracking requires a MySQL server. Your server details go in /config/dbconfig.txt, and the SQL schema is in /SQL/tgstation_schema.sql. More detailed setup instructions arecoming soon, for now ask in our IRC channel. diff --git a/baystation12.dme b/baystation12.dme index e92625188cf..106f13e2db4 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -216,8 +216,6 @@ #include "code\game\gamemodes\setupgame.dm" #include "code\game\gamemodes\autotraitor\autotraitor.dm" #include "code\game\gamemodes\blob\blob.dm" -#include "code\game\gamemodes\blob\blob_finish.dm" -#include "code\game\gamemodes\blob\blob_report.dm" #include "code\game\gamemodes\blob\theblob.dm" #include "code\game\gamemodes\blob\blobs\core.dm" #include "code\game\gamemodes\blob\blobs\factory.dm" @@ -248,6 +246,7 @@ #include "code\game\gamemodes\events\holidays\Holidays.dm" #include "code\game\gamemodes\events\holidays\Other.dm" #include "code\game\gamemodes\extended\extended.dm" +#include "code\game\gamemodes\heist\heist.dm" #include "code\game\gamemodes\malfunction\Malf_Modules.dm" #include "code\game\gamemodes\malfunction\malfunction.dm" #include "code\game\gamemodes\meteor\meteor.dm" @@ -312,6 +311,7 @@ #include "code\game\machinery\newscaster.dm" #include "code\game\machinery\OpTable.dm" #include "code\game\machinery\overview.dm" +#include "code\game\machinery\podmen.dm" #include "code\game\machinery\portable_turret.dm" #include "code\game\machinery\recharger.dm" #include "code\game\machinery\rechargestation.dm" @@ -374,10 +374,12 @@ #include "code\game\machinery\computer\robot.dm" #include "code\game\machinery\computer\security.dm" #include "code\game\machinery\computer\shuttle.dm" +#include "code\game\machinery\computer\skills.dm" #include "code\game\machinery\computer\specops_shuttle.dm" #include "code\game\machinery\computer\station_alert.dm" #include "code\game\machinery\computer\syndicate_shuttle.dm" #include "code\game\machinery\computer\syndicate_specops_shuttle.dm" +#include "code\game\machinery\computer\vox_shuttle.dm" #include "code\game\machinery\doors\airlock.dm" #include "code\game\machinery\doors\airlock_electronics.dm" #include "code\game\machinery\doors\alarmlock.dm" @@ -485,6 +487,7 @@ #include "code\game\objects\items\devices\lightreplacer.dm" #include "code\game\objects\items\devices\multitool.dm" #include "code\game\objects\items\devices\paicard.dm" +#include "code\game\objects\items\devices\pipe_painter.dm" #include "code\game\objects\items\devices\powersink.dm" #include "code\game\objects\items\devices\scanners.dm" #include "code\game\objects\items\devices\taperecorder.dm" @@ -845,6 +848,7 @@ #include "code\modules\mob\death.dm" #include "code\modules\mob\emote.dm" #include "code\modules\mob\inventory.dm" +#include "code\modules\mob\language.dm" #include "code\modules\mob\login.dm" #include "code\modules\mob\logout.dm" #include "code\modules\mob\mob.dm" @@ -875,6 +879,7 @@ #include "code\modules\mob\living\carbon\carbon_defines.dm" #include "code\modules\mob\living\carbon\give.dm" #include "code\modules\mob\living\carbon\shock.dm" +#include "code\modules\mob\living\carbon\species.dm" #include "code\modules\mob\living\carbon\alien\alien.dm" #include "code\modules\mob\living\carbon\alien\death.dm" #include "code\modules\mob\living\carbon\alien\login.dm" @@ -1000,6 +1005,7 @@ #include "code\modules\mob\living\silicon\robot\say.dm" #include "code\modules\mob\living\silicon\robot\wires.dm" #include "code\modules\mob\living\simple_animal\bees.dm" +#include "code\modules\mob\living\simple_animal\borer.dm" #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" @@ -1260,6 +1266,17 @@ #include "code\modules\surgery\ribcage.dm" #include "code\modules\surgery\robolimbs.dm" #include "code\modules\surgery\surgery.dm" +#include "code\modules\virus2\analyser.dm" +#include "code\modules\virus2\antibodies.dm" +#include "code\modules\virus2\centrifuge.dm" +#include "code\modules\virus2\curer.dm" +#include "code\modules\virus2\disease2.dm" +#include "code\modules\virus2\diseasesplicer.dm" +#include "code\modules\virus2\dishincubator.dm" +#include "code\modules\virus2\effect.dm" +#include "code\modules\virus2\helpers.dm" +#include "code\modules\virus2\isolator.dm" +#include "code\modules\virus2\items_devices.dm" #include "code\WorkInProgress\autopsy.dm" #include "code\WorkInProgress\buildmode.dm" #include "code\WorkInProgress\explosion_particles.dm" @@ -1310,20 +1327,12 @@ #include "code\WorkInProgress\Cael_Aislinn\Supermatter\ZeroPointLaser.dm" #include "code\WorkInProgress\Chinsky\ashtray.dm" #include "code\WorkInProgress\Cib\MedicalSideEffects.dm" -#include "code\WorkInProgress\kilakk\responseteam.dm" #include "code\WorkInProgress\Mini\ATM.dm" #include "code\WorkInProgress\Mini\atmos_control.dm" #include "code\WorkInProgress\Ported\policetape.dm" #include "code\WorkInProgress\SkyMarshal\officer_stuff.dm" #include "code\WorkInProgress\SkyMarshal\Ultralight_procs.dm" #include "code\WorkInProgress\Susan\susan_desert_turfs.dm" -#include "code\WorkInProgress\virus2\analyser.dm" -#include "code\WorkInProgress\virus2\antibodies.dm" -#include "code\WorkInProgress\virus2\base.dm" -#include "code\WorkInProgress\virus2\curer.dm" -#include "code\WorkInProgress\virus2\diseasesplicer.dm" -#include "code\WorkInProgress\virus2\dishincubator.dm" -#include "code\WorkInProgress\virus2\isolator.dm" #include "code\ZAS\Airflow.dm" #include "code\ZAS\Connection.dm" #include "code\ZAS\Debug.dm" @@ -1337,7 +1346,7 @@ #include "code\ZAS\ZAS_Zones.dm" #include "interface\interface.dm" #include "interface\skin.dmf" -#include "maps\tgstation.2.1.0.0.1.dmm" +#include "maps\tgstation2.dmm" #include "maps\RandomZLevels\Academy.dm" #include "maps\RandomZLevels\challenge.dm" #include "maps\RandomZLevels\stationCollision.dm" diff --git a/code/ATMOSPHERICS/pipes.dm b/code/ATMOSPHERICS/pipes.dm index c9e763e8390..6f16f501cf2 100644 --- a/code/ATMOSPHERICS/pipes.dm +++ b/code/ATMOSPHERICS/pipes.dm @@ -527,7 +527,7 @@ obj/machinery/atmospherics/pipe var/build_killswitch = 1 var/obj/machinery/atmospherics/node1 - New() + New() initialize_directions = dir ..() @@ -722,7 +722,7 @@ obj/machinery/atmospherics/pipe icon_state = "manifold_[connected]_[unconnected]" - if(!connected) + if(!connected) del(src) return @@ -922,6 +922,7 @@ obj/machinery/atmospherics/pipe ..() update_icon() + overlays.Cut() if(node1&&node2&&node3&&node4) var/C = "" switch(color) @@ -951,7 +952,7 @@ obj/machinery/atmospherics/pipe return initialize() - + for(var/obj/machinery/atmospherics/target in get_step(src,1)) if(target.initialize_directions & 2) node1 = target @@ -1028,7 +1029,7 @@ obj/machinery/atmospherics/pipe manifold4w/general/hidden level = 1 icon_state = "manifold4w-f" - + cap name = "pipe endcap" desc = "An endcap for pipes" @@ -1117,28 +1118,9 @@ obj/machinery/atmospherics/pipe/attackby(var/obj/item/weapon/W as obj, var/mob/u if (istype(src, /obj/machinery/atmospherics/pipe/vent)) return ..() - // ===== Handle paints ===== - if(istype(W, /obj/item/weapon/reagent_containers/glass/paint/red)) - src.color = "red" - user << "\red You paint the pipe red." - update_icon() + if(istype(W,/obj/item/device/pipe_painter)) return 1 - if(istype(W, /obj/item/weapon/reagent_containers/glass/paint/blue)) - src.color = "blue" - user << "\red You paint the pipe blue." - update_icon() - return 1 - if(istype(W, /obj/item/weapon/reagent_containers/glass/paint/green)) - src.color = "green" - user << "\red You paint the pipe green." - update_icon() - return 1 - if(istype(W, /obj/item/weapon/reagent_containers/glass/paint/yellow)) - src.color = "yellow" - user << "\red You paint the pipe yellow." - update_icon() - return 1 - + if (!istype(W, /obj/item/weapon/wrench)) return ..() var/turf/T = src.loc diff --git a/code/WorkInProgress/Cael_Aislinn/Economy/EFTPOS.dm b/code/WorkInProgress/Cael_Aislinn/Economy/EFTPOS.dm index f3160a3f8a5..7a00499be4f 100644 --- a/code/WorkInProgress/Cael_Aislinn/Economy/EFTPOS.dm +++ b/code/WorkInProgress/Cael_Aislinn/Economy/EFTPOS.dm @@ -70,7 +70,7 @@ D.name = "small parcel - 'EFTPOS access code'" /obj/item/device/eftpos/proc/reconnect_database() - for(var/obj/machinery/account_database/DB in machines) + for(var/obj/machinery/account_database/DB in world) //Hotfix until someone finds out why it isn't in 'machines' if(DB.z == src.z) linked_db = DB break diff --git a/code/WorkInProgress/Mini/ATM.dm b/code/WorkInProgress/Mini/ATM.dm index a7c0544591b..97b056a2ca6 100644 --- a/code/WorkInProgress/Mini/ATM.dm +++ b/code/WorkInProgress/Mini/ATM.dm @@ -70,7 +70,7 @@ log transactions break /obj/machinery/atm/proc/reconnect_database() - for(var/obj/machinery/account_database/DB in machines) + for(var/obj/machinery/account_database/DB in world) //Hotfix until someone finds out why it isn't in 'machines' if( DB.z == src.z && !(DB.stat & NOPOWER) && DB.activated ) linked_db = DB break diff --git a/code/WorkInProgress/Ported/policetape.dm b/code/WorkInProgress/Ported/policetape.dm index f5d17f81378..1160a8a6dcb 100644 --- a/code/WorkInProgress/Ported/policetape.dm +++ b/code/WorkInProgress/Ported/policetape.dm @@ -72,6 +72,8 @@ while (cur!=end && can_place) if(cur.density == 1) can_place = 0 + else if (istype(cur, /turf/space)) + can_place = 0 else for(var/obj/O in cur) if(!istype(O, /obj/item/tape) && O.density) diff --git a/code/WorkInProgress/carn/Explosion2.dm b/code/WorkInProgress/carn/Explosion2.dm index a1f2687cc85..06b85690024 100644 --- a/code/WorkInProgress/carn/Explosion2.dm +++ b/code/WorkInProgress/carn/Explosion2.dm @@ -9,7 +9,7 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa if(!epicenter) return if(adminlog) - message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ") + message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z] - JMP)") log_game("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ") playsound(epicenter, 'sound/effects/explosionfar.ogg', 100, 1, round(devastation_range*2,1) ) diff --git a/code/WorkInProgress/kilakk/responseteam.dm b/code/WorkInProgress/kilakk/responseteam.dm index 575e5ab6fd0..6faafad342f 100644 --- a/code/WorkInProgress/kilakk/responseteam.dm +++ b/code/WorkInProgress/kilakk/responseteam.dm @@ -2,7 +2,9 @@ // work in progress var/const/members_possible = 5 -var/sent_emergency_team = 0 +var/const/members_required = 1 // We need at least *one* person ;_; +var/global/admin_emergency_team = 0 // Used for admin-spawned response teams +// 'sent_response_team' for automagic response teams /client/proc/response_team() set name = "Dispatch Emergency Response Team" @@ -18,7 +20,7 @@ var/sent_emergency_team = 0 if(ticker.current_state == GAME_STATE_PREGAME) usr << "\red The round hasn't started yet!" return - if(sent_emergency_team == 1) + if(admin_emergency_team || send_emergency_team) usr << "\red Central Command has already dispatched an emergency response team!" return if(alert("Do you want to dispatch an Emergency Response Team?",,"Yes","No") != "Yes") @@ -35,11 +37,11 @@ var/sent_emergency_team = 0 if(alert("You haven't specified a mission. Exit the setup process?",,"No","Yes")=="Yes") return - if(sent_emergency_team) + if(admin_emergency_team || send_emergency_team) usr << "\red Looks like somebody beat you to it!" return - sent_emergency_team = 1 + admin_emergency_team = 1 message_admins("[key_name_admin(usr)] is dispatching an Emergency Response Team.", 1) log_admin("[key_name(usr)] used Dispatch Response Team.") @@ -87,6 +89,12 @@ var/sent_emergency_team = 0 sleep(300) + if(candidates.len < members_required) + message_admins("Not enough people signed up for [key_name_admin(usr)]'s response team! Aborting.") + log_admin("Response Team aborted: Not Enough Signups.") + admin_emergency_team = 0 + return + for(var/i=members_possible,(i>0&&candidates.len), i--) // The rest of the choosing process is just an input with a list of candidates on it var/chosen = input("Time's up! Choose characters to spawn as reponse team members. This will go on until there are no more ghosts to pick from or until all slots are full.", "Considered Players") as null|anything in candidates candidates -= chosen @@ -111,6 +119,7 @@ var/sent_emergency_team = 0 break spawn(0) + switch(alert(new_member, "You are an Emergency Response Team member! Are you a boy or a girl?",,"Male","Female")) if("Male") new_member.gender = MALE @@ -122,9 +131,12 @@ var/sent_emergency_team = 0 if(!new_name) new_member.real_name = "Agent [pick("Red","Yellow","Orange","Silver","Gold", "Pink", "Purple", "Rainbow")]" // Choose a "random" agent name new_member.name = usr.real_name + new_member.mind.name = usr.real_name + else new_member.real_name = new_name new_member.name = new_name + new_member.mind.name = new_name // -- CHANGE APPEARANCE -- var/new_tone = input(new_member, "Please select your new skin tone: 1-220 (1=albino, 35=caucasian, 150=black, 220='very' black)", "Character Generation") as num @@ -171,13 +183,16 @@ var/sent_emergency_team = 0 new_member.update_hair(1) new_member.mind_initialize() + new_member.mind.assigned_role = "Emergency Response Team" new_member.mind.special_role = "Emergency Response Team" - ticker.mode.traitors += new_member.mind // ERTs will show up at the end of the round on the "traitor" list + ticker.mode.traitors |= new_member.mind // ERTs will show up at the end of the round on the "traitor" list + // Join message new_member << "\blue You are the Emergency Response Team[!leader_selected?"!":" Leader!"] \nAs a response team [!leader_selected?"member":"leader"] you answer directly to [!leader_selected?"your team leader.":"Central Command."] \nYou have been deployed by NanoTrasen Central Command in Tau Ceti to resolve a Code Red alert aboard [station_name()], and have been provided with the following instructions and information regarding your mission: \red [situation]" new_member.mind.store_memory("Mission Parameters: \red [situation].") + // Leader join message if(leader_selected) new_member << "\red The Nuclear Authentication Code is: [nuke_code]. You are instructed not to detonate the nuclear device aboard [station_name()] unless absolutely necessary." new_member.mind.store_memory("Nuclear Authentication Code: \red [nuke_code]") @@ -213,7 +228,7 @@ var/sent_emergency_team = 0 // Put stuff into their backpacks equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(src), slot_in_backpack) - equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid(src), slot_in_backpack) // Not sure about this + // equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/regular(src), slot_in_backpack) // Regular medkit // Loyalty implants var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(src) @@ -235,5 +250,7 @@ var/sent_emergency_team = 0 E.registered_name = real_name equip_to_slot_or_del(E, slot_wear_id) + update_icons() + return 1 diff --git a/code/WorkInProgress/virus2/Disease2/biohazard destroyer.dm b/code/WorkInProgress/virus2/Disease2/biohazard destroyer.dm deleted file mode 100644 index 1f390433269..00000000000 --- a/code/WorkInProgress/virus2/Disease2/biohazard destroyer.dm +++ /dev/null @@ -1,20 +0,0 @@ -/obj/machinery/disease2/biodestroyer - name = "Biohazard destroyer" - icon = 'icons/obj/pipes/disposal.dmi' - icon_state = "disposal" - var/list/accepts = list(/obj/item/clothing,/obj/item/weapon/virusdish/,/obj/item/weapon/cureimplanter,/obj/item/weapon/diseasedisk) - density = 1 - anchored = 1 - -/obj/machinery/disease2/biodestroyer/attackby(var/obj/I as obj, var/mob/user as mob) - for(var/path in accepts) - if(I.type in typesof(path)) - user.drop_item() - del(I) - overlays += image('icons/obj/pipes/disposal.dmi', "dispover-handle") - return - user.drop_item() - I.loc = src.loc - - for(var/mob/O in hearers(src, null)) - O.show_message("\icon[src] \blue The [src.name] beeps", 2) diff --git a/code/WorkInProgress/virus2/Disease2/cureimplanter.dm b/code/WorkInProgress/virus2/Disease2/cureimplanter.dm deleted file mode 100644 index 45064954561..00000000000 --- a/code/WorkInProgress/virus2/Disease2/cureimplanter.dm +++ /dev/null @@ -1,42 +0,0 @@ -/obj/item/weapon/cureimplanter - name = "Hypospray injector" - icon = 'icons/obj/items.dmi' - icon_state = "implanter1" - var/datum/disease2/resistance/resistance = null - var/works = 0 - var/datum/disease2/disease/virus2 = null - item_state = "syringe_0" - throw_speed = 1 - throw_range = 5 - w_class = 2.0 - - -/obj/item/weapon/cureimplanter/attack(mob/target as mob, mob/user as mob) - if(ismob(target)) - for(var/mob/O in viewers(world.view, user)) - if (target != user) - O.show_message(text("\red [] is trying to inject [] with [src.name]!", user, target), 1) - else - O.show_message("\red [user] is trying to inject themselves with [src.name]!", 1) - if(!do_mob(user, target,60)) return - - - for(var/mob/O in viewers(world.view, user)) - if (target != user) - O.show_message(text("\red [] injects [] with [src.name]!", user, target), 1) - else - O.show_message("\red [user] injects themself with [src.name]!", 1) - - - var/mob/living/carbon/M = target - - if(works == 0 && prob(25)) - M.resistances2 += resistance - if(M.virus2) - M.virus2.cure_added(resistance) - else if(works == 1) - M.adjustToxLoss(rand(20,50)) - else if(works == 2) - M.adjustToxLoss(rand(50,100)) - else if(works == 3) - infect_virus2(M,virus2,1) diff --git a/code/WorkInProgress/virus2/Disease2/diseasesplicer.dm b/code/WorkInProgress/virus2/Disease2/diseasesplicer.dm deleted file mode 100644 index 958a14b1f11..00000000000 --- a/code/WorkInProgress/virus2/Disease2/diseasesplicer.dm +++ /dev/null @@ -1,202 +0,0 @@ -/obj/machinery/computer/diseasesplicer - name = "Disease Splicer" - icon = 'icons/obj/computer.dmi' - icon_state = "crew" - //brightnessred = 0 -// brightnessgreen = 2 -// brightnessblue = 2 -// broken_icon - - var/datum/disease2/effectholder/memorybank = null - var/analysed = 0 - var/obj/item/weapon/virusdish/dish = null - var/burning = 0 - - var/splicing = 0 - var/scanning = 0 - -/obj/machinery/computer/diseasesplicer/attackby(var/obj/I as obj, var/mob/user as mob) -/* - if(istype(I, /obj/item/weapon/screwdriver)) - playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) - if(do_after(user, 20)) - if (src.stat & BROKEN) - user << "\blue The broken glass falls out." - var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) - new /obj/item/weapon/shard( src.loc ) - var/obj/item/weapon/circuitboard/diseasesplicer/M = new /obj/item/weapon/circuitboard/diseasesplicer( A ) - for (var/obj/C in src) - C.loc = src.loc - A.circuit = M - A.state = 3 - A.icon_state = "3" - A.anchored = 1 - del(src) - else - user << "\blue You disconnect the monitor." - var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) - var/obj/item/weapon/circuitboard/diseasesplicer/M = new /obj/item/weapon/circuitboard/diseasesplicer( A ) - for (var/obj/C in src) - C.loc = src.loc - A.circuit = M - A.state = 4 - A.icon_state = "4" - A.anchored = 1 - del(src)*/ - if(istype(I,/obj/item/weapon/virusdish)) - var/mob/living/carbon/c = user - if(!dish) - - dish = I - c.drop_item() - I.loc = src - if(istype(I,/obj/item/weapon/diseasedisk)) - user << "You upload the contents of the disk into the buffer" - memorybank = I:effect - - - //else - src.attack_hand(user) - return - -/obj/machinery/computer/diseasesplicer/attack_ai(var/mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/computer/diseasesplicer/attack_paw(var/mob/user as mob) - - return src.attack_hand(user) - return - -/obj/machinery/computer/diseasesplicer/attack_hand(var/mob/user as mob) - if(..()) - return - user.machine = src - var/dat - if(splicing) - dat = "Splicing in progress" - else if(scanning) - dat = "Splicing in progress" - else if(burning) - dat = "Data disk burning in progress" - else - if(dish) - dat = "Virus dish inserted" - - dat += "
Current DNA strand : " - if(memorybank) - dat += "" - if(analysed) - dat += "[memorybank.effect.name] ([5-memorybank.effect.stage])" - else - dat += "Unknown DNA strand ([5-memorybank.effect.stage])" - dat += "" - - dat += "
Burn DNA Sequence to data storage disk" - else - dat += "Empty" - - dat += "

" - - if(dish) - if(dish.virus2) - if(dish.growth >= 50) - for(var/datum/disease2/effectholder/e in dish.virus2.effects) - dat += "
DNA strand" - if(dish.analysed) - dat += ": [e.effect.name]" - dat += " (5-[e.effect.stage])" - else - dat += "
Insufficent cells to attempt gene splicing" - else - dat += "
No virus found in dish" - - dat += "

Eject disk" - else - dat += "
Please insert dish" - - user << browse(dat, "window=computer;size=400x500") - onclose(user, "computer") - return - -/obj/machinery/computer/diseasesplicer/process() - if(stat & (NOPOWER|BROKEN)) - return - use_power(500) - src.updateDialog() - - if(scanning) - scanning -= 1 - if(!scanning) - state("The [src.name] beeps") - icon_state = "crew" - if(splicing) - splicing -= 1 - if(!splicing) - state("The [src.name] pings") - icon_state = "crew" - if(burning) - burning -= 1 - if(!burning) - var/obj/item/weapon/diseasedisk/d = new /obj/item/weapon/diseasedisk(src.loc) - if(analysed) - d.name = "[memorybank.effect.name] GNA disk (Stage: [5-memorybank.effect.stage])" - else - d.name = "Unknown GNA disk (Stage: [5-memorybank.effect.stage])" - d.effect = memorybank - state("The [src.name] zings") - icon_state = "crew" - - - return - -/obj/machinery/computer/diseasesplicer/Topic(href, href_list) - if(..()) - return - if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon))) - usr.machine = src - - if (href_list["grab"]) - memorybank = locate(href_list["grab"]) - analysed = dish.analysed - del(dish) - dish = null - scanning = 30 - icon_state = "crew" - - else if(href_list["eject"]) - dish.loc = src.loc - dish = null - - else if(href_list["splice"]) - for(var/datum/disease2/effectholder/e in dish.virus2.effects) - if(e.stage == memorybank.stage) - e.effect = memorybank.effect - splicing = 50 - dish.virus2.spreadtype = "Blood" - icon_state = "crew" - - else if(href_list["disk"]) - burning = 20 - icon_state = "crew" - - src.add_fingerprint(usr) - src.updateUsrDialog() - return - -/obj/machinery/computer/diseasesplicer/proc/state(var/msg) - for(var/mob/O in hearers(src, null)) - O.show_message("\icon[src] \blue [msg]", 2) - - -/obj/item/weapon/diseasedisk - name = "Blank GNA disk" - icon = 'icons/obj/cloning.dmi' - icon_state = "datadisk2" - var/datum/disease2/effectholder/effect = null - var/stage = 1 - -/obj/item/weapon/diseasedisk/premade/New() - name = "Blank GNA disk (stage: [5-stage])" - effect = new /datum/disease2/effectholder - effect.effect = new /datum/disease2/effect/invisible - effect.stage = stage diff --git a/code/WorkInProgress/virus2/Disease2/dishincubator.dm b/code/WorkInProgress/virus2/Disease2/dishincubator.dm deleted file mode 100644 index 921ed21574d..00000000000 --- a/code/WorkInProgress/virus2/Disease2/dishincubator.dm +++ /dev/null @@ -1,176 +0,0 @@ -/obj/machinery/disease2/incubator/ - name = "Pathogenic incubator" - density = 1 - anchored = 1 - icon = 'icons/obj/virology.dmi' - icon_state = "incubator" - var/obj/item/weapon/virusdish/dish - var/obj/item/weapon/reagent_containers/glass/beaker = null - var/radiation = 0 - - var/on = 0 - var/power = 0 - - var/foodsupply = 0 - var/toxins = 0 - - ex_act(severity) - switch(severity) - if(1.0) - del(src) - return - if(2.0) - if (prob(50)) - del(src) - return - - blob_act() - if (prob(25)) - del(src) - - meteorhit() - del(src) - return - - attackby(var/obj/B as obj, var/mob/user as mob) - if(istype(B, /obj/item/weapon/reagent_containers/glass) || istype(B,/obj/item/weapon/reagent_containers/syringe)) - - if(src.beaker) - if(istype(beaker,/obj/item/weapon/reagent_containers/syringe)) - user << "A syringe is already loaded into the machine." - else - user << "A beaker is already loaded into the machine." - return - - src.beaker = B - user.drop_item() - B.loc = src - if(istype(B,/obj/item/weapon/reagent_containers/syringe)) - user << "You add the syringe to the machine!" - src.updateUsrDialog() - else - user << "You add the beaker to the machine!" - src.updateUsrDialog() - else - if(istype(B,/obj/item/weapon/virusdish)) - if(src.dish) - user << "A dish is already loaded into the machine." - return - - src.dish = B - user.drop_item() - B.loc = src - if(istype(B,/obj/item/weapon/virusdish)) - user << "You add the dish to the machine!" - src.updateUsrDialog() - - Topic(href, href_list) - if(stat & BROKEN) return - if(usr.stat || usr.restrained()) return - if(!in_range(src, usr)) return - - usr.machine = src - if(!dish) return - - if (href_list["power"]) - on = !on - if(on) - icon_state = "incubator_on" - else - icon_state = "incubator" - if (href_list["ejectchem"]) - if(beaker) - beaker.loc = src.loc - beaker = null - if (href_list["ejectdish"]) - if(dish) - dish.loc = src.loc - dish = null - if (href_list["rad"]) - radiation += 10 - if (href_list["flush"]) - radiation = 0 - toxins = 0 - foodsupply = 0 - - - src.add_fingerprint(usr) - src.updateUsrDialog() - - attack_hand(mob/user as mob) - if(stat & BROKEN) - return - user.machine = src - var/dat = "" - if(!dish) - dat = "Please insert dish into the incubator.
" - dat += "Close" - var/string = "Off" - if(on) - string = "On" - dat += "Power status : [string]" - dat += "
" - dat += "Food supply : [foodsupply]" - dat += "
" - dat += "Radiation Levels : [radiation] RADS : Radiate" - dat += "
" - dat += "Toxins : [toxins]" - dat += "

" - if(beaker) - dat += "Eject chemicals : Eject" - dat += "
" - if(dish) - dat += "Eject Virus dish : Eject" - dat += "
" - dat += "

" - dat += "Flush system" - - - user << browse("Pathogenic incubatorincubator menu:

[dat]", "window=incubator;size=575x400") - onclose(user, "incubator") - return - - - - - process() - - if(dish && on && dish.virus2) - use_power(50,EQUIP) - if(!powered(EQUIP)) - on = 0 - icon_state = "incubator" - if(foodsupply) - foodsupply -= 1 - dish.growth += 1 - if(dish.growth == 100) - state("The [src.name] pings") - if(radiation) - if(radiation > 50 & prob(5)) - dish.virus2.majormutate() - if(dish.info) - dish.info = "OUTDATED : [dish.info]" - dish.analysed = 0 - state("The [src.name] beeps") - - else if(prob(5)) - dish.virus2.minormutate() - radiation -= 1 - if(toxins && prob(5)) - dish.virus2.infectionchance -= 1 - if(toxins > 50) - dish.virus2 = null - else if(!dish) - on = 0 - icon_state = "incubator" - - - if(beaker) - if(!beaker.reagents.remove_reagent("virusfood",5)) - foodsupply += 20 - if(!beaker.reagents.remove_reagent("toxins",1)) - toxins += 1 - - proc/state(var/msg) - for(var/mob/O in hearers(src, null)) - O.show_message("\icon[src] \blue [msg]", 2) diff --git a/code/WorkInProgress/virus2/Disease2/isolator.dm b/code/WorkInProgress/virus2/Disease2/isolator.dm deleted file mode 100644 index a8b4f0e8320..00000000000 --- a/code/WorkInProgress/virus2/Disease2/isolator.dm +++ /dev/null @@ -1,139 +0,0 @@ -/obj/machinery/disease2/isolator/ - name = "Pathogenic Isolator" - density = 1 - anchored = 1 - icon = 'icons/obj/virology.dmi' - icon_state = "isolator" - var/datum/disease2/disease/virus2 = null - var/isolating = 0 - var/beaker = null - - ex_act(severity) - switch(severity) - if(1.0) - del(src) - return - if(2.0) - if (prob(50)) - del(src) - return - - blob_act() - if (prob(25)) - del(src) - - meteorhit() - del(src) - return - - attackby(var/obj/item/weapon/reagent_containers/glass/B as obj, var/mob/user as mob) - if(!istype(B,/obj/item/weapon/reagent_containers/syringe)) - return - - if(src.beaker) - user << "A syringe is already loaded into the machine." - return - - src.beaker = B - user.drop_item() - B.loc = src - if(istype(B,/obj/item/weapon/reagent_containers/syringe)) - user << "You add the syringe to the machine!" - src.updateUsrDialog() - icon_state = "isolator_in" - - Topic(href, href_list) - if(stat & BROKEN) return - if(usr.stat || usr.restrained()) return - if(!in_range(src, usr)) return - - usr.machine = src - if(!beaker) return - var/datum/reagents/R = beaker:reagents - - if (href_list["isolate"]) - var/datum/reagent/blood/Blood - for(var/datum/reagent/blood/B in R.reagent_list) - if(B) - Blood = B - break - - if(Blood.data["virus2"]) - virus2 = Blood.data["virus2"] - isolating = 40 - icon_state = "isolator_processing" - src.updateUsrDialog() - return - - else if (href_list["main"]) - attack_hand(usr) - return - else if (href_list["eject"]) - beaker:loc = src.loc - beaker = null - icon_state = "isolator" - src.updateUsrDialog() - return - - attack_hand(mob/user as mob) - if(stat & BROKEN) - return - user.machine = src - var/dat = "" - if(!beaker) - dat = "Please insert sample into the isolator.
" - dat += "Close" - else if(isolating) - dat = "Isolating" - else - var/datum/reagents/R = beaker:reagents - dat += "Eject

" - if(!R.total_volume) - dat += "[beaker] is empty." - else - dat += "Contained reagents:
" - for(var/datum/reagent/blood/G in R.reagent_list) - dat += " [G.name]: Isolate" - user << browse("Pathogenic IsolatorIsolator menu:

[dat]", "window=isolator;size=575x400") - onclose(user, "isolator") - return - - - - - process() - if(isolating > 0) - isolating -= 1 - if(isolating == 0) - var/obj/item/weapon/virusdish/d = new /obj/item/weapon/virusdish(src.loc) - d.virus2 = virus2.getcopy() - virus2 = null - icon_state = "isolator_in" - - - - -/obj/item/weapon/virusdish - name = "Virus containment/growth dish" - icon = 'icons/obj/items.dmi' - icon_state = "implantcase-b" - var/datum/disease2/disease/virus2 = null - var/growth = 0 - var/info = 0 - var/analysed = 0 - -/obj/item/weapon/virusdish/attackby(var/obj/item/weapon/W as obj,var/mob/living/carbon/user as mob) - if(istype(W,/obj/item/weapon/hand_labeler)) - return - ..() - if(prob(50)) - user << "The dish shatters" - if(virus2.infectionchance > 0) - infect_virus2(user,virus2) - del src - -/obj/item/weapon/virusdish/examine() - usr << "This is a virus containment dish" - if(src.info) - usr << "It has the following information about its contents" - usr << src.info diff --git a/code/WorkInProgress/virus2/Disease2/monkeydispensor.dm b/code/WorkInProgress/virus2/Disease2/monkeydispensor.dm deleted file mode 100644 index 13d1b9806f6..00000000000 --- a/code/WorkInProgress/virus2/Disease2/monkeydispensor.dm +++ /dev/null @@ -1,30 +0,0 @@ -/obj/machinery/disease2/monkeycloner - name = "Monkey dispensor" - icon = 'icons/obj/cloning.dmi' - icon_state = "pod_0" - density = 1 - anchored = 1 - - var/cloning = 0 - -/obj/machinery/disease2/monkeycloner/attack_hand() - if(!cloning) - cloning = 150 - - icon_state = "pod_g" - -/obj/machinery/disease2/monkeycloner/process() - if(stat & (NOPOWER|BROKEN)) - return - use_power(500) - src.updateDialog() - - if(cloning) - cloning -= 1 - if(!cloning) - new /mob/living/carbon/monkey(src.loc) - icon_state = "pod_0" - - - - return diff --git a/code/WorkInProgress/virus2/analyser.dm b/code/WorkInProgress/virus2/analyser.dm deleted file mode 100644 index 3604d7955f7..00000000000 --- a/code/WorkInProgress/virus2/analyser.dm +++ /dev/null @@ -1,78 +0,0 @@ -/obj/machinery/disease2/diseaseanalyser - name = "Disease Analyser" - icon = 'virology.dmi' - icon_state = "analyser" - anchored = 1 - density = 1 - - var/scanning = 0 - var/pause = 0 - - var/obj/item/weapon/virusdish/dish = null - -/obj/machinery/disease2/diseaseanalyser/attackby(var/obj/I as obj, var/mob/user as mob) - if(istype(I,/obj/item/weapon/virusdish)) - var/mob/living/carbon/c = user - if(!dish) - - dish = I - c.drop_item() - I.loc = src - for(var/mob/M in viewers(src)) - if(M == user) continue - M.show_message("\blue [user.name] inserts the [dish.name] in the [src.name]", 3) - - - else - user << "There is already a dish inserted" - - //else - return - - -/obj/machinery/disease2/diseaseanalyser/process() - if(stat & (NOPOWER|BROKEN)) - return - use_power(500) - //src.updateDialog() - - - if(scanning) - scanning -= 1 - if(scanning == 0) - var/r = "GNAv2 based virus lifeform" - r += "
Infection rate : [dish.virus2.infectionchance * 10]" - r += "
Spread form : [dish.virus2.spreadtype]" - r += "
Progress Speed : [dish.virus2.stageprob * 10]" - for(var/datum/disease2/effectholder/E in dish.virus2.effects) - r += "
Effect:[E.effect.name]. Strength : [E.multiplier * 8]. Verosity : [E.chance * 15]. Type : [5-E.stage]." - // display the antigens - var/code = "" - for(var/V in ANTIGENS) if(text2num(V) & dish.virus2.antigen) code += ANTIGENS[V] - r += "
Antigen pattern: [code]" - - var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(src.loc) - P.info = r - dish.info = r - dish.analysed = 1 - dish.loc = src.loc - dish = null - icon_state = "analyser" - - for(var/mob/O in hearers(src, null)) - O.show_message("\icon[src] \blue The [src.name] prints a sheet of paper", 3) - else if(dish && !scanning && !pause) - if(dish.virus2 && dish.growth > 50) - dish.growth -= 10 - scanning = 5 - icon_state = "analyser_processing" - else - pause = 1 - spawn(25) - dish.loc = src.loc - dish = null - for(var/mob/M in viewers(src)) - M.show_message("\icon[src] \blue The [src.name] buzzes", 2) - pause = 0 - - return \ No newline at end of file diff --git a/code/WorkInProgress/virus2/antibodies.dm b/code/WorkInProgress/virus2/antibodies.dm deleted file mode 100644 index b8810e322da..00000000000 --- a/code/WorkInProgress/virus2/antibodies.dm +++ /dev/null @@ -1,58 +0,0 @@ -//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 - -// pure concentrated antibodies -datum/reagent/antibodies - data = new/list("antibodies"=0) - name = "Antibodies" - id = "antibodies" - reagent_state = LIQUID - color = "#0050F0" - - reaction_mob(var/mob/M, var/method=TOUCH, var/volume) - if(istype(M,/mob/living/carbon)) - if(src.data && method == INGEST) - if(M:virus2) if(src.data["antibodies"] & M:virus2.antigen) - M:virus2.dead = 1 - // if the virus is killed this way it immunizes - // M:antibodies |= M:virus2.antigen - M:antibodies |= src.data["antibodies"] - return - -// reserving some numbers for later special antigens -var/global/const/ANTIGEN_A = 1 -var/global/const/ANTIGEN_B = 2 -var/global/const/ANTIGEN_RH = 4 -var/global/const/ANTIGEN_Q = 8 -var/global/const/ANTIGEN_U = 16 -var/global/const/ANTIGEN_V = 32 -var/global/const/ANTIGEN_X = 64 -var/global/const/ANTIGEN_Y = 128 -var/global/const/ANTIGEN_Z = 256 -var/global/const/ANTIGEN_M = 512 -var/global/const/ANTIGEN_N = 1024 -var/global/const/ANTIGEN_P = 2048 -var/global/const/ANTIGEN_O = 4096 - -var/global/list/ANTIGENS = list("[ANTIGEN_A]" = "A", "[ANTIGEN_B]" = "B", "[ANTIGEN_RH]" = "RH", "[ANTIGEN_Q]" = "Q", - "[ANTIGEN_U]" = "U", "[ANTIGEN_V]" = "V", "[ANTIGEN_Z]" = "Z", "[ANTIGEN_M]" = "M", - "[ANTIGEN_N]" = "N", "[ANTIGEN_P]" = "P", "[ANTIGEN_O]" = "O") - - - -/obj/item/device/antibody_scanner - name = "Antibody Scanner" - desc = "Used to scan living beings for antibodies in their blood." - icon_state = "health" - w_class = 2.0 - item_state = "electronic" - flags = FPRINT | TABLEPASS | CONDUCT | USEDELAY - - -/obj/item/device/antibody_scanner/attack(mob/living/carbon/human/M as mob, mob/user as mob) - if(! istype(M, /mob/living/carbon) || !M:antibodies) - user << "Unable to detect antibodies.." - else - // iterate over the list of antigens and see what matches - var/code = "" - for(var/V in ANTIGENS) if(text2num(V) & M.antibodies) code += ANTIGENS[V] - user << text("\blue [src] The antibody scanner displays a cryptic set of data: [code]") diff --git a/code/WorkInProgress/virus2/base.dm b/code/WorkInProgress/virus2/base.dm deleted file mode 100644 index 3d8954fc996..00000000000 --- a/code/WorkInProgress/virus2/base.dm +++ /dev/null @@ -1,601 +0,0 @@ -/obj/virus - // a virus instance that is placed on the map, moves, and infects - invisibility = INVISIBILITY_MAXIMUM - - var/datum/disease2/disease - - New() - ..() - step_rand(src) - step_rand(src) - anchored = 1 - spawn(300) del(src) - -/mob/living/carbon/proc/get_infection_chance() - var/score = 0 - var/mob/living/carbon/M = src - if(istype(M, /mob/living/carbon/human)) - if(M:gloves) - score += 5 - if(istype(M:wear_suit, /obj/item/clothing/suit/space)) score += 10 - if(istype(M:wear_suit, /obj/item/clothing/suit/bio_suit)) score += 10 - if(istype(M:head, /obj/item/clothing/head/helmet/space)) score += 5 - if(istype(M:head, /obj/item/clothing/head/bio_hood)) score += 5 - if(M.wear_mask) - score += 5 - if(istype(M:wear_mask, /obj/item/clothing/mask/surgical) && !M.internal) - score += 10 - if(M.internal) - score += 10 - - if(score >= 30) - return 0 - else if(score == 25 && prob(99)) - return 0 - else if(score == 20 && prob(95)) - return 0 - else if(score == 15 && prob(75)) - return 0 - else if(score == 10 && prob(55)) - return 0 - else if(score == 5 && prob(35)) - return 0 - - return 1 - - -proc/airborne_can_reach(turf/source, turf/target) - var/obj/dummy = new(source) - dummy.flags = FPRINT | TABLEPASS - dummy.pass_flags = PASSTABLE - - for(var/i=0, i<5, i++) if(!step_towards(dummy, target)) break - - var/rval = (dummy.loc in range(1,target)) - del dummy - return rval - -/proc/infect_virus2(var/mob/living/carbon/M,var/datum/disease2/disease/disease,var/forced = 0) - if(M.virus2) - return - if(!disease) - return - //immunity - /*for(var/iii = 1, iii <= M.immunevirus2.len, iii++) - if(disease.issame(M.immunevirus2[iii])) - return*/ - - // if one of the antibodies in the mob's body matches one of the disease's antigens, don't infect - if(M.antibodies & disease.antigen != 0) return - - for(var/datum/disease2/resistance/res in M.resistances) - if(res.resistsdisease(disease)) - return - if(prob(disease.infectionchance) || forced) - if(M.virus2) - return - else - // certain clothes can prevent an infection - if(!forced && !M.get_infection_chance()) - return - - M.virus2 = disease.getcopy() - M.virus2.minormutate() - - for(var/datum/disease2/resistance/res in M.resistances) - if(res.resistsdisease(M.virus2)) - M.virus2 = null - - - -/datum/disease2/resistance - var/list/datum/disease2/effect/resistances = list() - - proc/resistsdisease(var/datum/disease2/disease/virus2) - var/list/res2 = list() - for(var/datum/disease2/effect/e in resistances) - res2 += e.type - for(var/datum/disease2/effectholder/holder in virus2) - if(!(holder.effect.type in res2)) - return 0 - else - res2 -= holder.effect.type - if(res2.len > 0) - return 0 - else - return 1 - - New(var/datum/disease2/disease/virus2) - for(var/datum/disease2/effectholder/h in virus2.effects) - resistances += h.effect.type - - -/proc/infect_mob_random_lesser(var/mob/living/carbon/M) - if(!M.virus2) - M.virus2 = new /datum/disease2/disease - M.virus2.makerandom() - M.virus2.infectionchance = 1 - -/proc/infect_mob_random_greater(var/mob/living/carbon/M) - if(!M.virus2) - M.virus2 = new /datum/disease2/disease - M.virus2.makerandom(1) - -/datum/disease2/var/antigen = 0 // 16 bits describing the antigens, when one bit is set, a cure with that bit can dock here - -/datum/disease2/disease - var/infectionchance = 10 - var/speed = 1 - var/spreadtype = "Blood" // Can also be "Airborne" - var/stage = 1 - var/stageprob = 10 - var/dead = 0 - var/clicks = 0 - - var/uniqueID = 0 - var/list/datum/disease2/effectholder/effects = list() - proc/makerandom(var/greater=0) - var/datum/disease2/effectholder/holder = new /datum/disease2/effectholder - holder.stage = 1 - if(greater) - holder.getrandomeffect_greater() - else - holder.getrandomeffect_lesser() - effects += holder - holder = new /datum/disease2/effectholder - holder.stage = 2 - if(greater) - holder.getrandomeffect_greater() - else - holder.getrandomeffect_lesser() - effects += holder - holder = new /datum/disease2/effectholder - holder.stage = 3 - if(greater) - holder.getrandomeffect_greater() - else - holder.getrandomeffect_lesser() - effects += holder - holder = new /datum/disease2/effectholder - holder.stage = 4 - if(greater) - holder.getrandomeffect_greater() - else - holder.getrandomeffect_lesser() - effects += holder - uniqueID = rand(0,10000) - infectionchance = rand(1,10) - // pick 2 antigens - antigen |= text2num(pick(ANTIGENS)) - antigen |= text2num(pick(ANTIGENS)) - spreadtype = "Airborne" - - proc/makealien() - var/datum/disease2/effectholder/holder = new /datum/disease2/effectholder - holder.stage = 1 - holder.chance = 10 - holder.effect = new/datum/disease2/effect/lesser/gunck() - effects += holder - - holder = new /datum/disease2/effectholder - holder.stage = 2 - holder.chance = 10 - holder.effect = new/datum/disease2/effect/lesser/cough() - effects += holder - - holder = new /datum/disease2/effectholder - holder.stage = 3 - holder.chance = 10 - holder.effect = new/datum/disease2/effect/greater/toxins() - effects += holder - - holder = new /datum/disease2/effectholder - holder.stage = 4 - holder.chance = 10 - holder.effect = new/datum/disease2/effect/alien() - effects += holder - - uniqueID = 896 // all alien diseases have the same ID - infectionchance = 0 - spreadtype = "Airborne" - - proc/minormutate() - var/datum/disease2/effectholder/holder = pick(effects) - holder.minormutate() - infectionchance = min(10,infectionchance + rand(0,1)) - - proc/issame(var/datum/disease2/disease/disease) - var/list/types = list() - var/list/types2 = list() - for(var/datum/disease2/effectholder/d in effects) - types += d.effect.type - var/equal = 1 - - for(var/datum/disease2/effectholder/d in disease.effects) - types2 += d.effect.type - - for(var/type in types) - if(!(type in types2)) - equal = 0 - return equal - - proc/activate(var/mob/living/carbon/mob) - if(dead) - cure(mob) - mob.virus2 = null - return - if(mob.stat == 2) - return - // with a certain chance, the mob may become immune to the disease before it starts properly - if(stage <= 1 && clicks == 0) - if(prob(20)) - mob.antibodies |= antigen // 20% immunity is a good chance IMO, because it allows finding an immune person easily - else - if(mob.radiation > 50) - if(prob(1)) - majormutate() - if(mob.reagents.has_reagent("spaceacillin")) - return - if(mob.reagents.has_reagent("virusfood")) - mob.reagents.remove_reagent("virusfood",0.1) - clicks += 10 - if(clicks > stage*100 && prob(10)) - if(stage == 4) - var/datum/disease2/resistance/res = new /datum/disease2/resistance(src) - src.cure(mob) - mob.resistances2 += res - mob.antibodies |= src.antigen - mob.virus2 = null - del src - stage++ - clicks = 0 - for(var/datum/disease2/effectholder/e in effects) - e.runeffect(mob,stage) - clicks+=speed - - proc/cure(var/mob/living/carbon/mob) - var/datum/disease2/effectholder/E - if(stage>1) - E = effects[1] - E.effect.deactivate(mob) - if(stage>2) - E = effects[2] - E.effect.deactivate(mob) - if(stage>3) - E = effects[3] - E.effect.deactivate(mob) - if(stage>4) - E = effects[4] - E.effect.deactivate(mob) - - proc/cure_added(var/datum/disease2/resistance/res) - if(res.resistsdisease(src)) - dead = 1 - - proc/majormutate() - var/datum/disease2/effectholder/holder = pick(effects) - holder.majormutate() - - - proc/getcopy() -// world << "getting copy" - var/datum/disease2/disease/disease = new /datum/disease2/disease - disease.infectionchance = infectionchance - disease.spreadtype = spreadtype - disease.stageprob = stageprob - disease.antigen = antigen - for(var/datum/disease2/effectholder/holder in effects) - // world << "adding effects" - var/datum/disease2/effectholder/newholder = new /datum/disease2/effectholder - newholder.effect = new holder.effect.type - newholder.chance = holder.chance - newholder.cure = holder.cure - newholder.multiplier = holder.multiplier - newholder.happensonce = holder.happensonce - newholder.stage = holder.stage - disease.effects += newholder - // world << "[newholder.effect.name]" - // world << "[disease]" - return disease - -/datum/disease2/effect - var/chance_maxm = 100 - var/name = "Blanking effect" - var/stage = 4 - var/maxm = 1 - proc/activate(var/mob/living/carbon/mob,var/multiplier) - proc/deactivate(var/mob/living/carbon/mob) - -/datum/disease2/effect/alien - name = "Unidentified Foreign Body" - stage = 4 - activate(var/mob/living/carbon/mob,var/multiplier) - mob << "\red You feel something tearing its way out of your stomach..." - mob.adjustToxLoss(10) - mob.updatehealth() - if(prob(40)) - if(mob.client) - mob.client.mob = new/mob/living/carbon/alien/larva(mob.loc) - else - new/mob/living/carbon/alien/larva(mob.loc) - var/datum/disease2/disease/D = mob:virus2 - mob:gib() - del D - -/datum/disease2/effect/greater/gibbingtons - name = "Gibbingtons Syndrome" - stage = 4 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.gib() - -/datum/disease2/effect/greater/radian - name = "Radian's syndrome" - stage = 4 - maxm = 3 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.radiation += (2*multiplier) - -/datum/disease2/effect/greater/toxins - name = "Hyperacid Syndrome" - stage = 3 - maxm = 3 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.adjustToxLoss((2*multiplier)) - -/datum/disease2/effect/greater/scream - name = "Random screaming syndrome" - stage = 2 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.say("*scream") - -/datum/disease2/effect/greater/drowsness - name = "Automated sleeping syndrome" - stage = 2 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.drowsyness += 10 - -/datum/disease2/effect/greater/shakey - name = "World Shaking syndrome" - stage = 3 - maxm = 3 - activate(var/mob/living/carbon/mob,var/multiplier) - shake_camera(mob,5*multiplier) - -/datum/disease2/effect/greater/deaf - name = "Hard of hearing syndrome" - stage = 4 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.ear_deaf += 20 - -/datum/disease2/effect/invisible - name = "Waiting Syndrome" - stage = 1 - activate(var/mob/living/carbon/mob,var/multiplier) - return - -/datum/disease2/effect/greater/telepathic - name = "Telepathy Syndrome" - stage = 3 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.mutations |= 512 - -/*/datum/disease2/effect/greater/noface - name = "Identity Loss syndrome" - stage = 4 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.face_dmg++ - deactivate(var/mob/living/carbon/mob) - mob.face_dmg--*/ - -/datum/disease2/effect/greater/monkey - name = "Monkism syndrome" - stage = 4 - activate(var/mob/living/carbon/mob,var/multiplier) - if(istype(mob,/mob/living/carbon/human)) - var/mob/living/carbon/human/h = mob - h.monkeyize() - -/datum/disease2/effect/greater/sneeze - name = "Coldingtons Effect" - stage = 1 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.say("*sneeze") - -/datum/disease2/effect/greater/gunck - name = "Flemmingtons" - stage = 1 - activate(var/mob/living/carbon/mob,var/multiplier) - mob << "\red Mucous runs down the back of your throat." - -/datum/disease2/effect/greater/killertoxins - name = "Toxification syndrome" - stage = 4 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.adjustToxLoss(15) - -/*/datum/disease2/effect/greater/hallucinations - name = "Hallucinational Syndrome" - stage = 3 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.hallucination += 25*/ - -/datum/disease2/effect/greater/sleepy - name = "Resting syndrome" - stage = 2 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.say("*collapse") - -/datum/disease2/effect/greater/mind - name = "Lazy mind syndrome" - stage = 3 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.setBrainLoss(50) - -/datum/disease2/effect/greater/suicide - name = "Suicidal syndrome" - stage = 4 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.suiciding = 1 - //instead of killing them instantly, just put them at -175 health and let 'em gasp for a while - viewers(mob) << "\red [mob.name] is holding \his breath. It looks like \he's trying to commit suicide." - mob.adjustOxyLoss(175 - mob.getToxLoss() - mob.getFireLoss() - mob.getBruteLoss() - mob.getOxyLoss()) - mob.updatehealth() - spawn(200) //in case they get revived by cryo chamber or something stupid like that, let them suicide again in 20 seconds - mob.suiciding = 0 - -// lesser syndromes, partly just copypastes -/datum/disease2/effect/lesser/mind - name = "Lazy mind syndrome" - stage = 3 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.setBrainLoss(20) - -/datum/disease2/effect/lesser/drowsy - name = "Bedroom Syndrome" - stage = 2 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.drowsyness = 5 - -/datum/disease2/effect/lesser/deaf - name = "Hard of hearing syndrome" - stage = 3 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.ear_deaf = 5 - -/datum/disease2/effect/lesser/gunck - name = "Flemmingtons" - stage = 1 - activate(var/mob/living/carbon/mob,var/multiplier) - mob << "\red Mucous runs down the back of your throat." - -/datum/disease2/effect/lesser/radian - name = "Radian's syndrome" - stage = 4 - maxm = 3 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.radiation += 1 - -/datum/disease2/effect/lesser/sneeze - name = "Coldingtons Effect" - stage = 1 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.say("*sneeze") - -/datum/disease2/effect/lesser/cough - name = "Anima Syndrome" - stage = 2 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.say("*cough") - -/*/datum/disease2/effect/lesser/hallucinations - name = "Hallucinational Syndrome" - stage = 3 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.hallucination += 5*/ - -/*/datum/disease2/effect/lesser/arm - name = "Disarming Syndrome" - stage = 4 - activate(var/mob/living/carbon/mob,var/multiplier) - var/datum/organ/external/org = mob.organs["r_arm"] - org.take_damage(3,0,0,0) - mob << "\red You feel a sting in your right arm."*/ - -/datum/disease2/effect/lesser/hungry - name = "Appetiser Effect" - stage = 2 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.nutrition = max(0, mob.nutrition - 200) - -/datum/disease2/effect/lesser/groan - name = "Groaning Syndrome" - stage = 3 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.say("*groan") - -/datum/disease2/effect/lesser/scream - name = "Loudness Syndrome" - stage = 4 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.say("*scream") - -/datum/disease2/effect/lesser/drool - name = "Saliva Effect" - stage = 1 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.say("*drool") - -/datum/disease2/effect/lesser/fridge - name = "Refridgerator Syndrome" - stage = 2 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.say("*shiver") - -/datum/disease2/effect/lesser/twitch - name = "Twitcher" - stage = 1 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.say("*twitch") - -/*Removed on request by Spaceman, due to it being detrimental to RP. -CN -/datum/disease2/effect/lesser/deathgasp - name = "Zombie Syndrome" - stage = 4 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.say("*deathgasp")*/ - -/datum/disease2/effect/lesser/giggle - name = "Uncontrolled Laughter Effect" - stage = 3 - activate(var/mob/living/carbon/mob,var/multiplier) - mob.say("*giggle") - - -/datum/disease2/effect/lesser - chance_maxm = 10 - -/datum/disease2/effectholder - var/name = "Holder" - var/datum/disease2/effect/effect - var/chance = 0 //Chance in percentage each tick - var/cure = "" //Type of cure it requires - var/happensonce = 0 - var/multiplier = 1 //The chance the effects are WORSE - var/stage = 0 - - proc/runeffect(var/mob/living/carbon/human/mob,var/stage) - if(happensonce > -1 && effect.stage <= stage && prob(chance)) - effect.activate(mob) - if(happensonce == 1) - happensonce = -1 - - proc/getrandomeffect_greater() - var/list/datum/disease2/effect/list = list() - for(var/e in (typesof(/datum/disease2/effect/greater) - /datum/disease2/effect/greater)) - // world << "Making [e]" - var/datum/disease2/effect/f = new e - if(f.stage == src.stage) - list += f - effect = pick(list) - chance = rand(1,6) - - proc/getrandomeffect_lesser() - var/list/datum/disease2/effect/list = list() - for(var/e in (typesof(/datum/disease2/effect/lesser) - /datum/disease2/effect/lesser)) - var/datum/disease2/effect/f = new e - if(f.stage == src.stage) - list += f - effect = pick(list) - chance = rand(1,6) - - proc/minormutate() - switch(pick(1,2,3,4,5)) - if(1) - chance = rand(0,effect.chance_maxm) - if(2) - multiplier = rand(1,effect.maxm) - proc/majormutate() - getrandomeffect_greater() - -/proc/dprob(var/p) - return(prob(sqrt(p)) && prob(sqrt(p))) diff --git a/code/WorkInProgress/virus2/cureimplanter.dm b/code/WorkInProgress/virus2/cureimplanter.dm deleted file mode 100644 index 80354e5765b..00000000000 --- a/code/WorkInProgress/virus2/cureimplanter.dm +++ /dev/null @@ -1,43 +0,0 @@ -/obj/item/weapon/cureimplanter - name = "Hypospray injector" - icon = 'items.dmi' - icon_state = "implanter1" - var/datum/disease2/resistance/resistance = null - var/works = 0 - var/datum/disease2/disease/virus2 = null - item_state = "syringe_0" - throw_speed = 1 - throw_range = 5 - w_class = 2.0 - - -/obj/item/weapon/cureimplanter/attack(mob/target as mob, mob/user as mob) - if(ismob(target)) - for(var/mob/O in viewers(world.view, user)) - if (target != user) - O.show_message(text("\red [] is trying to inject [] with [src.name]!", user, target), 1) - else - O.show_message("\red [user] is trying to inject themselves with [src.name]!", 1) - if(!do_mob(user, target,60)) return - - - for(var/mob/O in viewers(world.view, user)) - if (target != user) - O.show_message(text("\red [] injects [] with [src.name]!", user, target), 1) - else - O.show_message("\red [user] injects themself with [src.name]!", 1) - - - var/mob/living/carbon/M = target - - if(works == 0) - M.resistances2 += resistance - //M.immunevirus2 += M.virus2.getcopy() - if(M.virus2) - M.virus2.cure_added(resistance) - else if(works == 1) - M.adjustToxLoss(60) - else if(works == 2) - M.gib() - else if(works == 3) - infect_virus2(M,virus2,1) \ No newline at end of file diff --git a/code/WorkInProgress/virus2/dishincubator.dm b/code/WorkInProgress/virus2/dishincubator.dm deleted file mode 100644 index f2aefe07ead..00000000000 --- a/code/WorkInProgress/virus2/dishincubator.dm +++ /dev/null @@ -1,169 +0,0 @@ -/obj/machinery/disease2/incubator/ - name = "Pathogenic incubator" - density = 1 - anchored = 1 - icon = 'virology.dmi' - icon_state = "incubator" - var/obj/item/weapon/virusdish/dish - var/obj/item/weapon/reagent_containers/glass/beaker = null - var/radiation = 0 - - var/on = 0 - var/power = 0 - - var/foodsupply = 0 - var/toxins = 0 - - ex_act(severity) - switch(severity) - if(1.0) - del(src) - return - if(2.0) - if (prob(50)) - del(src) - return - - blob_act() - if (prob(25)) - del(src) - - meteorhit() - del(src) - return - - attackby(var/obj/B as obj, var/mob/user as mob) - if(istype(B, /obj/item/weapon/reagent_containers/glass) || istype(B,/obj/item/weapon/reagent_containers/syringe)) - - if(src.beaker) - if(istype(beaker,/obj/item/weapon/reagent_containers/syringe)) - user << "A syringe is already loaded into the machine." - else - user << "A beaker is already loaded into the machine." - return - - src.beaker = B - user.drop_item() - B.loc = src - if(istype(B,/obj/item/weapon/reagent_containers/syringe)) - user << "You add the syringe to the machine!" - src.updateUsrDialog() - else - user << "You add the beaker to the machine!" - src.updateUsrDialog() - else - if(istype(B,/obj/item/weapon/virusdish)) - if(src.dish) - user << "A dish is already loaded into the machine." - return - - src.dish = B - user.drop_item() - B.loc = src - if(istype(B,/obj/item/weapon/virusdish)) - user << "You add the dish to the machine!" - src.updateUsrDialog() - - Topic(href, href_list) - if(stat & BROKEN) return - if(usr.stat || usr.restrained()) return - if(!in_range(src, usr)) return - if (href_list["ejectchem"]) - if(beaker) - beaker.loc = src.loc - beaker = null - if(!dish) - return - usr.machine = src - if (href_list["power"]) - on = !on - if(on) - icon_state = "incubator_on" - else - icon_state = "incubator" - if (href_list["ejectdish"]) - if(dish) - dish.loc = src.loc - dish = null - if (href_list["rad"]) - radiation += 10 - if (href_list["flush"]) - radiation = 0 - toxins = 0 - foodsupply = 0 - - - src.add_fingerprint(usr) - src.updateUsrDialog() - - attack_hand(mob/user as mob) - if(stat & BROKEN) - return - user.machine = src - var/dat = "" - if(!dish) - dat = "Please insert dish into the incubator.
" - var/string = "Off" - if(on) - string = "On" - dat += "Power status : [string]" - dat += "
" - dat += "Food supply : [foodsupply]" - dat += "
" - dat += "Radiation Levels : [radiation] RADS : Radiate" - dat += "
" - dat += "Toxins : [toxins]" - dat += "

" - if(beaker) - dat += "Eject chemicals : Eject" - dat += "
" - if(dish) - dat += "Eject Virus dish : Eject" - dat += "
" - dat += "

" - dat += "Flush system
" - dat += "Close
" - user << browse("Pathogenic incubatorincubator menu:

[dat]", "window=incubator;size=575x400") - onclose(user, "incubator") - return - - - - - process() - - if(dish && on && dish.virus2) - use_power(50,EQUIP) - if(!powered(EQUIP)) - on = 0 - icon_state = "incubator" - if(foodsupply) - foodsupply -= 1 - dish.growth += 3 - if(dish.growth >= 100) - state("The [src.name] pings", "blue") - if(radiation) - if(radiation > 50 & prob(5)) - dish.virus2.majormutate() - if(dish.info) - dish.info = "OUTDATED : [dish.info]" - dish.analysed = 0 - state("The [src.name] beeps", "blue") - - else if(prob(5)) - dish.virus2.minormutate() - radiation -= 1 - if(toxins && prob(5)) - dish.virus2.infectionchance -= 1 - if(toxins > 50) - dish.virus2 = null - else if(!dish) - on = 0 - icon_state = "incubator" - - - if(beaker) - if(!beaker.reagents.remove_reagent("virusfood",5)) - foodsupply += 10 - if(!beaker.reagents.remove_reagent("toxin",1)) - toxins += 1 \ No newline at end of file diff --git a/code/WorkInProgress/virus2/isolator.dm b/code/WorkInProgress/virus2/isolator.dm deleted file mode 100644 index d337959fd6a..00000000000 --- a/code/WorkInProgress/virus2/isolator.dm +++ /dev/null @@ -1,161 +0,0 @@ -/obj/machinery/disease2/isolator/ - name = "Pathogenic Isolator" - density = 1 - anchored = 1 - icon = 'virology.dmi' - icon_state = "isolator" - var/datum/disease2/disease/virus2 = null - var/isolating = 0 - var/beaker = null - - ex_act(severity) - switch(severity) - if(1.0) - del(src) - return - if(2.0) - if (prob(50)) - del(src) - return - - blob_act() - if (prob(25)) - del(src) - - meteorhit() - del(src) - return - - attackby(var/obj/item/weapon/reagent_containers/glass/B as obj, var/mob/user as mob) - if(!istype(B,/obj/item/weapon/reagent_containers/syringe)) - return - - if(src.beaker) - user << "A syringe is already loaded into the machine." - return - - src.beaker = B - user.drop_item() - B.loc = src - if(istype(B,/obj/item/weapon/reagent_containers/syringe)) - user << "You add the syringe to the machine!" - src.updateUsrDialog() - icon_state = "isolator_in" - - Topic(href, href_list) - if(stat & BROKEN) return - if(usr.stat || usr.restrained()) return - if(!in_range(src, usr)) return - - usr.machine = src - if(!beaker) return - var/datum/reagents/R = beaker:reagents - - if (href_list["isolate"]) - var/datum/reagent/blood/Blood - for(var/datum/reagent/blood/B in R.reagent_list) - if(B) - Blood = B - break - - if(Blood.data["virus2"]) - virus2 = Blood.data["virus2"] - isolating = 40 - icon_state = "isolator_processing" - src.updateUsrDialog() - return - - else if (href_list["main"]) - attack_hand(usr) - return - else if (href_list["eject"]) - beaker:loc = src.loc - beaker = null - icon_state = "isolator" - src.updateUsrDialog() - return - - attack_hand(mob/user as mob) - if(stat & BROKEN) - return - user.machine = src - var/dat = "" - if(!beaker) - dat = "Please insert sample into the isolator.
" - dat += "Close" - else if(isolating) - dat = "Isolating" - else - var/datum/reagents/R = beaker:reagents - dat += "Eject

" - if(!R.total_volume) - dat += "[beaker] is empty." - else - dat += "Contained reagents:
" - for(var/datum/reagent/blood/G in R.reagent_list) - if(G.data["virus2"]) - dat += " [G.name]: Isolate" - else - dat += " No pathogen" - user << browse("Pathogenic IsolatorIsolator menu:

[dat]", "window=isolator;size=575x400") - onclose(user, "isolator") - return - - - - - process() - if(isolating > 0) - isolating -= 1 - if(isolating == 0) - var/obj/item/weapon/virusdish/d = new /obj/item/weapon/virusdish(src.loc) - d.virus2 = virus2.getcopy() - virus2 = null - icon_state = "isolator_in" - - - - -/obj/item/weapon/virusdish - name = "Virus containment/growth dish" - icon = 'items.dmi' - icon_state = "implantcase-b" - var/datum/disease2/disease/virus2 = null - var/growth = 0 - var/info = 0 - var/analysed = 0 - - reagents = list() - -/obj/item/weapon/virusdish/random - name = "Virus Sample" - -/obj/item/weapon/virusdish/random/New() - ..() - // add a random virus to this dish - src.virus2 = new /datum/disease2/disease - src.virus2.makerandom() - growth = rand(5, 50) - -/obj/item/weapon/virusdish/attackby(var/obj/item/weapon/W as obj,var/mob/living/carbon/user as mob) - if(istype(W,/obj/item/weapon/hand_labeler) || istype(W,/obj/item/weapon/reagent_containers/syringe)) - return - ..() - if(prob(50)) - user << "The dish shatters" - if(virus2.infectionchance > 0) - for(var/mob/living/carbon/target in view(null, src)) if(!target.virus2) - if(airborne_can_reach(src.loc, target.loc)) - if(target.get_infection_chance()) - infect_virus2(target,src.virus2) - del src - -/obj/item/weapon/virusdish/examine() - usr << "This is a virus containment dish" - if(src.info) - usr << "It has the following information about its contents" - usr << src.info - -/obj/machinery/proc/state(var/msg) - for(var/mob/O in hearers(src, null)) - O.show_message("\icon[src] \blue [msg]", 2) diff --git a/code/WorkInProgress/virus2/monkeydispensor.dm b/code/WorkInProgress/virus2/monkeydispensor.dm deleted file mode 100644 index aee24b0d4a1..00000000000 --- a/code/WorkInProgress/virus2/monkeydispensor.dm +++ /dev/null @@ -1,30 +0,0 @@ -/obj/machinery/disease2/monkeycloner - name = "Monkey dispensor" - icon = 'cloning.dmi' - icon_state = "pod_0" - density = 1 - anchored = 1 - - var/cloning = 0 - -/obj/machinery/disease2/monkeycloner/attack_hand() - if(!cloning) - cloning = 150 - - icon_state = "pod_g" - -/obj/machinery/disease2/monkeycloner/process() - if(stat & (NOPOWER|BROKEN)) - return - use_power(500) - //src.updateDialog() - - if(cloning) - cloning -= 1 - if(!cloning) - new /mob/living/carbon/monkey(src.loc) - icon_state = "pod_0" - - - - return \ No newline at end of file diff --git a/code/ZAS/Airflow.dm b/code/ZAS/Airflow.dm index a2506bb2d92..894dc92c72b 100644 --- a/code/ZAS/Airflow.dm +++ b/code/ZAS/Airflow.dm @@ -225,142 +225,142 @@ proc/AirflowSpace(zone/A) if(M) M.GotoAirflowDest(n/10) //Sometimes shit breaks, and M isn't there after the spawn. -atom/movable - var/tmp/turf/airflow_dest - var/tmp/airflow_speed = 0 - var/tmp/airflow_time = 0 - var/tmp/last_airflow = 0 - proc/GotoAirflowDest(n) - if(!airflow_dest) return - if(airflow_speed < 0) return - if(last_airflow > world.time - vsc.airflow_delay) return - if(airflow_speed) - airflow_speed = n/max(get_dist(src,airflow_dest),1) +/atom/movable/var/tmp/turf/airflow_dest +/atom/movable/var/tmp/airflow_speed = 0 +/atom/movable/var/tmp/airflow_time = 0 +/atom/movable/var/tmp/last_airflow = 0 + +/atom/movable/proc/GotoAirflowDest(n) + if(!airflow_dest) return + if(airflow_speed < 0) return + if(last_airflow > world.time - vsc.airflow_delay) return + if(airflow_speed) + airflow_speed = n/max(get_dist(src,airflow_dest),1) + return + last_airflow = world.time + if(airflow_dest == loc) + step_away(src,loc) + if(ismob(src)) + if(src:status_flags & GODMODE) return - last_airflow = world.time - if(airflow_dest == loc) - step_away(src,loc) - if(ismob(src)) - if(src:status_flags & GODMODE) + if(istype(src, /mob/living/carbon/human)) + if(src:buckled) return - if(istype(src, /mob/living/carbon/human)) - if(src:buckled) - return - if(src:shoes) - if(istype(src:shoes, /obj/item/clothing/shoes/magboots)) - if(src:shoes:magpulse) - return - src << "\red You are sucked away by airflow!" - var/airflow_falloff = 9 - ul_FalloffAmount(airflow_dest) //It's a fast falloff calc. Very useful. - if(airflow_falloff < 1) - airflow_dest = null - return - airflow_speed = min(max(n * (9/airflow_falloff),1),9) - var - xo = airflow_dest.x - src.x - yo = airflow_dest.y - src.y - od = 0 + if(src:shoes) + if(istype(src:shoes, /obj/item/clothing/shoes/magboots)) + if(src:shoes:magpulse) + return + src << "\red You are sucked away by airflow!" + var/airflow_falloff = 9 - ul_FalloffAmount(airflow_dest) //It's a fast falloff calc. Very useful. + if(airflow_falloff < 1) airflow_dest = null - if(!density) - density = 1 - od = 1 - while(airflow_speed > 0) - if(airflow_speed <= 0) return - airflow_speed = min(airflow_speed,15) - airflow_speed -= vsc.airflow_speed_decay - if(airflow_speed > 7) - if(airflow_time++ >= airflow_speed - 7) - if(od) - density = 0 - sleep(1 * tick_multiplier) - else + return + airflow_speed = min(max(n * (9/airflow_falloff),1),9) + var + xo = airflow_dest.x - src.x + yo = airflow_dest.y - src.y + od = 0 + airflow_dest = null + if(!density) + density = 1 + od = 1 + while(airflow_speed > 0) + if(airflow_speed <= 0) return + airflow_speed = min(airflow_speed,15) + airflow_speed -= vsc.airflow_speed_decay + if(airflow_speed > 7) + if(airflow_time++ >= airflow_speed - 7) if(od) density = 0 - sleep(max(1,10-(airflow_speed+3)) * tick_multiplier) - if(od) - density = 1 - if ((!( src.airflow_dest ) || src.loc == src.airflow_dest)) - src.airflow_dest = locate(min(max(src.x + xo, 1), world.maxx), min(max(src.y + yo, 1), world.maxy), src.z) - if ((src.x == 1 || src.x == world.maxx || src.y == 1 || src.y == world.maxy)) - return - if(!istype(loc, /turf)) - return - step_towards(src, src.airflow_dest) - if(ismob(src) && src:client) - src:client:move_delay = world.time + vsc.airflow_mob_slowdown - airflow_dest = null - airflow_speed = 0 - airflow_time = 0 - if(od) - density = 0 - - - proc/RepelAirflowDest(n) - if(!airflow_dest) return - if(airflow_speed < 0) return - if(last_airflow > world.time - vsc.airflow_delay) return - if(airflow_speed) - airflow_speed = n/max(get_dist(src,airflow_dest),1) - return - if(airflow_dest == loc) - step_away(src,loc) - if(ismob(src)) - if(src:status_flags & GODMODE) - return - if(istype(src, /mob/living/carbon/human)) - if(src:buckled) - return - if(src:shoes) - if(src:shoes.type == /obj/item/clothing/shoes/magboots) - if(src:shoes.flags & NOSLIP) - return - src << "\red You are pushed away by airflow!" - last_airflow = world.time - var/airflow_falloff = 9 - ul_FalloffAmount(airflow_dest) //It's a fast falloff calc. Very useful. - if(airflow_falloff < 1) - airflow_dest = null - return - airflow_speed = min(max(n * (9/airflow_falloff),1),9) - var - xo = -(airflow_dest.x - src.x) - yo = -(airflow_dest.y - src.y) - od = 0 - airflow_dest = null - if(!density) - density = 1 - od = 1 - while(airflow_speed > 0) - if(airflow_speed <= 0) return - airflow_speed = min(airflow_speed,15) - airflow_speed -= vsc.airflow_speed_decay - if(airflow_speed > 7) - if(airflow_time++ >= airflow_speed - 7) - sleep(1 * tick_multiplier) - else - sleep(max(1,10-(airflow_speed+3)) * tick_multiplier) - if ((!( src.airflow_dest ) || src.loc == src.airflow_dest)) - src.airflow_dest = locate(min(max(src.x + xo, 1), world.maxx), min(max(src.y + yo, 1), world.maxy), src.z) - if ((src.x == 1 || src.x == world.maxx || src.y == 1 || src.y == world.maxy)) - return - if(!istype(loc, /turf)) - return - step_towards(src, src.airflow_dest) - if(ismob(src) && src:client) - src:client:move_delay = world.time + vsc.airflow_mob_slowdown - airflow_dest = null - airflow_speed = 0 - airflow_time = 0 - if(od) - density = 0 - - Bump(atom/A) - if(airflow_speed > 0 && airflow_dest) - airflow_hit(A) + sleep(1 * tick_multiplier) else - airflow_speed = 0 - airflow_time = 0 - . = ..() + if(od) + density = 0 + sleep(max(1,10-(airflow_speed+3)) * tick_multiplier) + if(od) + density = 1 + if ((!( src.airflow_dest ) || src.loc == src.airflow_dest)) + src.airflow_dest = locate(min(max(src.x + xo, 1), world.maxx), min(max(src.y + yo, 1), world.maxy), src.z) + if ((src.x == 1 || src.x == world.maxx || src.y == 1 || src.y == world.maxy)) + return + if(!istype(loc, /turf)) + return + step_towards(src, src.airflow_dest) + if(ismob(src) && src:client) + src:client:move_delay = world.time + vsc.airflow_mob_slowdown + airflow_dest = null + airflow_speed = 0 + airflow_time = 0 + if(od) + density = 0 + + +/atom/movable/proc/RepelAirflowDest(n) + if(!airflow_dest) return + if(airflow_speed < 0) return + if(last_airflow > world.time - vsc.airflow_delay) return + if(airflow_speed) + airflow_speed = n/max(get_dist(src,airflow_dest),1) + return + if(airflow_dest == loc) + step_away(src,loc) + if(ismob(src)) + if(src:status_flags & GODMODE) + return + if(istype(src, /mob/living/carbon/human)) + if(src:buckled) + return + if(src:shoes) + if(istype(src:shoes, /obj/item/clothing/shoes/magboots)) + if(src:shoes.flags & NOSLIP) + return + src << "\red You are pushed away by airflow!" + last_airflow = world.time + var/airflow_falloff = 9 - ul_FalloffAmount(airflow_dest) //It's a fast falloff calc. Very useful. + if(airflow_falloff < 1) + airflow_dest = null + return + airflow_speed = min(max(n * (9/airflow_falloff),1),9) + var + xo = -(airflow_dest.x - src.x) + yo = -(airflow_dest.y - src.y) + od = 0 + airflow_dest = null + if(!density) + density = 1 + od = 1 + while(airflow_speed > 0) + if(airflow_speed <= 0) return + airflow_speed = min(airflow_speed,15) + airflow_speed -= vsc.airflow_speed_decay + if(airflow_speed > 7) + if(airflow_time++ >= airflow_speed - 7) + sleep(1 * tick_multiplier) + else + sleep(max(1,10-(airflow_speed+3)) * tick_multiplier) + if ((!( src.airflow_dest ) || src.loc == src.airflow_dest)) + src.airflow_dest = locate(min(max(src.x + xo, 1), world.maxx), min(max(src.y + yo, 1), world.maxy), src.z) + if ((src.x == 1 || src.x == world.maxx || src.y == 1 || src.y == world.maxy)) + return + if(!istype(loc, /turf)) + return + step_towards(src, src.airflow_dest) + if(ismob(src) && src:client) + src:client:move_delay = world.time + vsc.airflow_mob_slowdown + airflow_dest = null + airflow_speed = 0 + airflow_time = 0 + if(od) + density = 0 + +/atom/movable/Bump(atom/A) + if(airflow_speed > 0 && airflow_dest) + airflow_hit(A) + else + airflow_speed = 0 + airflow_time = 0 + . = ..() atom/movable/proc/airflow_hit(atom/A) airflow_speed = 0 diff --git a/code/ZAS/Connection.dm b/code/ZAS/Connection.dm index f9697207c60..8a919d50435 100644 --- a/code/ZAS/Connection.dm +++ b/code/ZAS/Connection.dm @@ -6,393 +6,396 @@ Indirect connections will not merge the two zones after they reach equilibrium. #define CONNECTION_INDIRECT 1 #define CONNECTION_CLOSED 0 +/connection + var/turf/simulated/A + var/turf/simulated/B -connection - var - turf/simulated //The turfs involved in the connection. - A - B - zone - zone_A - zone_B - ref_A - ref_B - indirect = CONNECTION_DIRECT //If the connection is purely indirect, the zones should not join. - last_updated //The tick at which this was last updated. - no_zone_count = 0 + var/zone/zone_A + var/zone/zone_B + + var/ref_A + var/ref_B + + var/indirect = CONNECTION_DIRECT //If the connection is purely indirect, the zones should not join. + + var/last_updated //The tick at which this was last updated. + + var/no_zone_count = 0 - New(turf/T,turf/O) - A = T - B = O - if(A.zone && B.zone) - if(!A.zone.connections) A.zone.connections = list() - A.zone.connections += src - zone_A = A.zone - ref_A = "\ref[A]" - if(!B.zone.connections) B.zone.connections = list() - B.zone.connections += src - zone_B = B.zone - ref_B = "\ref[B]" +/connection/New(turf/T,turf/O) + A = T + B = O + if(A.zone && B.zone) + if(!A.zone.connections) A.zone.connections = list() + A.zone.connections += src + zone_A = A.zone + ref_A = "\ref[A]" - if(ref_A in air_master.turfs_with_connections) - var/list/connections = air_master.turfs_with_connections[ref_A] - connections.Add(src) - else - air_master.turfs_with_connections[ref_A] = list(src) - - if(ref_B in air_master.turfs_with_connections) - var/list/connections = air_master.turfs_with_connections[ref_B] - connections.Add(src) - else - air_master.turfs_with_connections[ref_B] = list(src) - - if(A.CanPass(null, B, 0, 0)) - - ConnectZones(A.zone, B.zone, 1) - - if(A.HasDoor(B) || B.HasDoor(A)) - indirect = CONNECTION_INDIRECT - - else - ConnectZones(A.zone, B.zone) - indirect = CONNECTION_CLOSED - - - else - world.log << "Attempted to create connection object for non-zone tiles: [T] ([T.x],[T.y],[T.z]) -> [O] ([O.x],[O.y],[O.z])" - del(src) - - - Del() - //remove connections from master lists. - if(ref_B in air_master.turfs_with_connections) - var/list/connections = air_master.turfs_with_connections[ref_B] - connections.Remove(src) + if(!B.zone.connections) B.zone.connections = list() + B.zone.connections += src + zone_B = B.zone + ref_B = "\ref[B]" if(ref_A in air_master.turfs_with_connections) var/list/connections = air_master.turfs_with_connections[ref_A] - connections.Remove(src) + connections.Add(src) + else + air_master.turfs_with_connections[ref_A] = list(src) - //Remove connection from zones. - if(A) - if(A.zone && A.zone.connections) - A.zone.connections.Remove(src) - if(!A.zone.connections.len) - A.zone.connections = null + if(ref_B in air_master.turfs_with_connections) + var/list/connections = air_master.turfs_with_connections[ref_B] + connections.Add(src) + else + air_master.turfs_with_connections[ref_B] = list(src) - if(istype(zone_A) && (!A || A.zone != zone_A)) + if(A.CanPass(null, B, 0, 0)) + + ConnectZones(A.zone, B.zone, 1) + + if(A.HasDoor(B) || B.HasDoor(A)) + indirect = CONNECTION_INDIRECT + + else + ConnectZones(A.zone, B.zone) + indirect = CONNECTION_CLOSED + + + else + world.log << "Attempted to create connection object for non-zone tiles: [T] ([T.x],[T.y],[T.z]) -> [O] ([O.x],[O.y],[O.z])" + del(src) + + +/connection/Del() + //remove connections from master lists. + if(ref_B in air_master.turfs_with_connections) + var/list/connections = air_master.turfs_with_connections[ref_B] + connections.Remove(src) + + if(ref_A in air_master.turfs_with_connections) + var/list/connections = air_master.turfs_with_connections[ref_A] + connections.Remove(src) + + //Remove connection from zones. + if(A) + if(A.zone && A.zone.connections) + A.zone.connections.Remove(src) + if(!A.zone.connections.len) + A.zone.connections = null + + if(istype(zone_A) && (!A || A.zone != zone_A)) + if(zone_A.connections) + zone_A.connections.Remove(src) + if(!zone_A.connections.len) + zone_A.connections = null + + if(B) + if(B.zone && B.zone.connections) + B.zone.connections.Remove(src) + if(!B.zone.connections.len) + B.zone.connections = null + + if(istype(zone_B) && (!B || B.zone != zone_B)) + if(zone_B.connections) + zone_B.connections.Remove(src) + if(!zone_B.connections.len) + zone_B.connections = null + + //Disconnect zones while handling unusual conditions. + // e.g. loss of a zone on a turf + if(A && A.zone && B && B.zone) + DisconnectZones(A.zone, B.zone) + + //Finally, preform actual deletion. + . = ..() + + +/connection/proc/ConnectZones(var/zone/zone_1, var/zone/zone_2, open = 0) + + //Sanity checking + if(!istype(zone_1) || !istype(zone_2)) + return + + //Handle zones connecting indirectly/directly. + if(open) + + //Create the lists if necessary. + if(!zone_1.connected_zones) + zone_1.connected_zones = list() + + if(!zone_2.connected_zones) + zone_2.connected_zones = list() + + //Increase the number of connections between zones. + if(zone_2 in zone_1.connected_zones) + zone_1.connected_zones[zone_2]++ + else + zone_1.connected_zones += zone_2 + zone_1.connected_zones[zone_2] = 1 + + if(zone_1 in zone_2.connected_zones) + zone_2.connected_zones[zone_1]++ + else + zone_2.connected_zones += zone_1 + zone_2.connected_zones[zone_1] = 1 + + //Handle closed connections. + else + + //Create the lists + if(!zone_1.closed_connection_zones) + zone_1.closed_connection_zones = list() + + if(!zone_2.closed_connection_zones) + zone_2.closed_connection_zones = list() + + //Increment the connections. + if(zone_2 in zone_1.closed_connection_zones) + zone_1.closed_connection_zones[zone_2]++ + else + zone_1.closed_connection_zones += zone_2 + zone_1.closed_connection_zones[zone_2] = 1 + + if(zone_1 in zone_2.closed_connection_zones) + zone_2.closed_connection_zones[zone_1]++ + else + zone_2.closed_connection_zones += zone_1 + zone_2.closed_connection_zones[zone_1] = 1 + + +/connection/proc/DisconnectZones(var/zone/zone_1, var/zone/zone_2) + //Sanity checking + if(!istype(zone_1) || !istype(zone_2)) + return + + if(indirect != CONNECTION_CLOSED) + //Handle disconnection of indirectly or directly connected zones. + if( (zone_1 in zone_2.connected_zones) || (zone_2 in zone_1.connected_zones) ) + + //If there are more than one connection, decrement the number of connections + //Otherwise, remove all connections between the zones. + if(zone_2 in zone_1.connected_zones) + if(zone_1.connected_zones[zone_2] > 1) + zone_1.connected_zones[zone_2]-- + else + zone_1.connected_zones -= zone_2 + //remove the list if it is empty + if(!zone_1.connected_zones.len) + zone_1.connected_zones = null + + //Then do the same for the other zone. + if(zone_1 in zone_2.connected_zones) + if(zone_2.connected_zones[zone_1] > 1) + zone_2.connected_zones[zone_1]-- + else + zone_2.connected_zones -= zone_1 + if(!zone_2.connected_zones.len) + zone_2.connected_zones = null + + else + //Handle disconnection of closed zones. + if( (zone_1 in zone_2.closed_connection_zones) || (zone_2 in zone_1.closed_connection_zones) ) + + //If there are more than one connection, decrement the number of connections + //Otherwise, remove all connections between the zones. + if(zone_2 in zone_1.closed_connection_zones) + if(zone_1.closed_connection_zones[zone_2] > 1) + zone_1.closed_connection_zones[zone_2]-- + else + zone_1.closed_connection_zones -= zone_2 + //remove the list if it is empty + if(!zone_1.closed_connection_zones.len) + zone_1.closed_connection_zones = null + + //Then do the same for the other zone. + if(zone_1 in zone_2.closed_connection_zones) + if(zone_2.closed_connection_zones[zone_1] > 1) + zone_2.closed_connection_zones[zone_1]-- + else + zone_2.closed_connection_zones -= zone_1 + if(!zone_2.closed_connection_zones.len) + zone_2.closed_connection_zones = null + + +/connection/proc/Cleanup() + + //Check sanity: existance of turfs + if(!A || !B) + del src + + //Check sanity: zones are different + if(A.zone == B.zone) + del src + + //Check sanity: same turfs as before. + if(ref_A != "\ref[A]" || ref_B != "\ref[B]") + del src + + //Handle zones changing on a turf. + if((A.zone && A.zone != zone_A) || (B.zone && B.zone != zone_B)) + Sanitize() + + //Manage sudden loss of a turfs zone. (e.g. a wall being built) + if(!A.zone || !B.zone) + no_zone_count++ + if(no_zone_count >= 5) + //world.log << "Connection removed: [A] or [B] missing a zone." + del src + return 0 + + return 1 + + +/connection/proc/CheckPassSanity() + //Sanity check, first. + Cleanup() + + if(A.zone && B.zone) + + //If no walls are blocking us... + if(A.ZAirPass(B)) + //...we check to see if there is a door in the way... + var/door_pass = A.CanPass(null,B,1.5,1) + //...and if it is opened. + if(door_pass || A.CanPass(null,B,0,0)) + + //Make and remove connections to let air pass. + if(indirect == CONNECTION_CLOSED) + DisconnectZones(A.zone, B.zone) + ConnectZones(A.zone, B.zone, 1) + + if(door_pass) + indirect = CONNECTION_DIRECT + else if(!door_pass) + indirect = CONNECTION_INDIRECT + + //The door is instead closed. + else if(indirect > CONNECTION_CLOSED) + DisconnectZones(A.zone, B.zone) + indirect = CONNECTION_CLOSED + ConnectZones(A.zone, B.zone) + + //If I can no longer pass air, better delete + else + del src + +/connection/proc/Sanitize() + //If the zones change on connected turfs, update it. + + //Both zones changed (wat) + if(A.zone && A.zone != zone_A && B.zone && B.zone != zone_B) + + //If the zones have gotten swapped + // (do not ask me how, I am just being anal retentive about sanity) + if(A.zone == zone_B && B.zone == zone_A) + var/turf/temp = B + B = A + A = temp + zone_B = B.zone + zone_A = A.zone + var/temp_ref = ref_A + ref_A = ref_B + ref_B = temp_ref + return + + //Handle removal of connections from archived zones. + if(zone_A && zone_A.connections) + zone_A.connections.Remove(src) + if(!zone_A.connections.len) + zone_A.connections = null + + if(zone_B && zone_B.connections) + zone_B.connections.Remove(src) + if(!zone_B.connections.len) + zone_B.connections = null + + if(A.zone) + if(!A.zone.connections) + A.zone.connections = list() + A.zone.connections |= src + + if(B.zone) + if(!B.zone.connections) + B.zone.connections = list() + B.zone.connections |= src + + //If either zone is null, we disconnect the archived ones after cleaning up the connections. + if(!A.zone || !B.zone) + if(zone_A && zone_B) + DisconnectZones(zone_B, zone_A) + + if(!A.zone) + zone_A = A.zone + + if(!B.zone) + zone_B = B.zone + return + + //Handle diconnection and reconnection of zones. + if(zone_A && zone_B) + DisconnectZones(zone_A, zone_B) + ConnectZones(A.zone, B.zone, indirect) + + //resetting values of archived values. + zone_B = B.zone + zone_A = A.zone + + //The "A" zone changed. + else if(A.zone && A.zone != zone_A) + + //Handle connection cleanup + if(zone_A) if(zone_A.connections) zone_A.connections.Remove(src) if(!zone_A.connections.len) zone_A.connections = null - if(B) - if(B.zone && B.zone.connections) - B.zone.connections.Remove(src) - if(!B.zone.connections.len) - B.zone.connections = null + if(A.zone) + if(!A.zone.connections) + A.zone.connections = list() + A.zone.connections |= src - if(istype(zone_B) && (!B || B.zone != zone_B)) + //If the "A" zone is null, we disconnect the archived ones after cleaning up the connections. + if(!A.zone) + if(zone_A && zone_B) + DisconnectZones(zone_A, zone_B) + zone_A = A.zone + return + + //Handle diconnection and reconnection of zones. + if(zone_A && zone_B) + DisconnectZones(zone_A, zone_B) + ConnectZones(A.zone, B.zone, indirect) + zone_A = A.zone + + //The "B" zone changed. + else if(B.zone && B.zone != zone_B) + + //Handle connection cleanup + if(zone_B) if(zone_B.connections) zone_B.connections.Remove(src) if(!zone_B.connections.len) zone_B.connections = null - //Disconnect zones while handling unusual conditions. - // e.g. loss of a zone on a turf - if(A && A.zone && B && B.zone) - DisconnectZones(A.zone, B.zone) + if(B.zone) + if(!B.zone.connections) + B.zone.connections = list() + B.zone.connections |= src - //Finally, preform actual deletion. - . = ..() - - - proc/ConnectZones(var/zone/zone_1, var/zone/zone_2, open = 0) - - //Sanity checking - if(!istype(zone_1) || !istype(zone_2)) - return - - //Handle zones connecting indirectly/directly. - if(open) - - //Create the lists if necessary. - if(!zone_1.connected_zones) - zone_1.connected_zones = list() - - if(!zone_2.connected_zones) - zone_2.connected_zones = list() - - //Increase the number of connections between zones. - if(zone_2 in zone_1.connected_zones) - zone_1.connected_zones[zone_2]++ - else - zone_1.connected_zones += zone_2 - zone_1.connected_zones[zone_2] = 1 - - if(zone_1 in zone_2.connected_zones) - zone_2.connected_zones[zone_1]++ - else - zone_2.connected_zones += zone_1 - zone_2.connected_zones[zone_1] = 1 - - //Handle closed connections. - else - - //Create the lists - if(!zone_1.closed_connection_zones) - zone_1.closed_connection_zones = list() - - if(!zone_2.closed_connection_zones) - zone_2.closed_connection_zones = list() - - //Increment the connections. - if(zone_2 in zone_1.closed_connection_zones) - zone_1.closed_connection_zones[zone_2]++ - else - zone_1.closed_connection_zones += zone_2 - zone_1.closed_connection_zones[zone_2] = 1 - - if(zone_1 in zone_2.closed_connection_zones) - zone_2.closed_connection_zones[zone_1]++ - else - zone_2.closed_connection_zones += zone_1 - zone_2.closed_connection_zones[zone_1] = 1 - - - proc/DisconnectZones(var/zone/zone_1, var/zone/zone_2) - - //Sanity checking - if(!istype(zone_1) || !istype(zone_2)) - return - - if(indirect != CONNECTION_CLOSED) - //Handle disconnection of indirectly or directly connected zones. - if( (zone_1 in zone_2.connected_zones) || (zone_2 in zone_1.connected_zones) ) - - //If there are more than one connection, decrement the number of connections - //Otherwise, remove all connections between the zones. - if(zone_2 in zone_1.connected_zones) - if(zone_1.connected_zones[zone_2] > 1) - zone_1.connected_zones[zone_2]-- - else - zone_1.connected_zones -= zone_2 - //remove the list if it is empty - if(!zone_1.connected_zones.len) - zone_1.connected_zones = null - - //Then do the same for the other zone. - if(zone_1 in zone_2.connected_zones) - if(zone_2.connected_zones[zone_1] > 1) - zone_2.connected_zones[zone_1]-- - else - zone_2.connected_zones -= zone_1 - if(!zone_2.connected_zones.len) - zone_2.connected_zones = null - - else - //Handle disconnection of closed zones. - if( (zone_1 in zone_2.closed_connection_zones) || (zone_2 in zone_1.closed_connection_zones) ) - - //If there are more than one connection, decrement the number of connections - //Otherwise, remove all connections between the zones. - if(zone_2 in zone_1.closed_connection_zones) - if(zone_1.closed_connection_zones[zone_2] > 1) - zone_1.closed_connection_zones[zone_2]-- - else - zone_1.closed_connection_zones -= zone_2 - //remove the list if it is empty - if(!zone_1.closed_connection_zones.len) - zone_1.closed_connection_zones = null - - //Then do the same for the other zone. - if(zone_1 in zone_2.closed_connection_zones) - if(zone_2.closed_connection_zones[zone_1] > 1) - zone_2.closed_connection_zones[zone_1]-- - else - zone_2.closed_connection_zones -= zone_1 - if(!zone_2.closed_connection_zones.len) - zone_2.closed_connection_zones = null - - - proc/Cleanup() - - //Check sanity: existance of turfs - if(!A || !B) - del src - - //Check sanity: zones are different - if(A.zone == B.zone) - del src - - //Check sanity: same turfs as before. - if(ref_A != "\ref[A]" || ref_B != "\ref[B]") - del src - - //Handle zones changing on a turf. - if((A.zone && A.zone != zone_A) || (B.zone && B.zone != zone_B)) - Sanitize() - - //Manage sudden loss of a turfs zone. (e.g. a wall being built) - if(!A.zone || !B.zone) - no_zone_count++ - if(no_zone_count >= 5) - //world.log << "Connection removed: [A] or [B] missing a zone." - del src - return 0 - - return 1 - - - proc/CheckPassSanity() - //Sanity check, first. - Cleanup() - - if(A.zone && B.zone) - - //If no walls are blocking us... - if(A.ZAirPass(B)) - //...we check to see if there is a door in the way... - var/door_pass = A.CanPass(null,B,1.5,1) - //...and if it is opened. - if(door_pass || A.CanPass(null,B,0,0)) - - //Make and remove connections to let air pass. - if(indirect == CONNECTION_CLOSED) - DisconnectZones(A.zone, B.zone) - ConnectZones(A.zone, B.zone, 1) - - if(door_pass) - indirect = CONNECTION_DIRECT - else if(!door_pass) - indirect = CONNECTION_INDIRECT - - //The door is instead closed. - else if(indirect > CONNECTION_CLOSED) - DisconnectZones(A.zone, B.zone) - indirect = CONNECTION_CLOSED - ConnectZones(A.zone, B.zone) - - //If I can no longer pass air, better delete - else - del src - - proc/Sanitize() - //If the zones change on connected turfs, update it. - - //Both zones changed (wat) - if(A.zone && A.zone != zone_A && B.zone && B.zone != zone_B) - - //If the zones have gotten swapped - // (do not ask me how, I am just being anal retentive about sanity) - if(A.zone == zone_B && B.zone == zone_A) - var/turf/temp = B - B = A - A = temp - zone_B = B.zone - zone_A = A.zone - var/temp_ref = ref_A - ref_A = ref_B - ref_B = temp_ref - return - - //Handle removal of connections from archived zones. - if(zone_A && zone_A.connections) - zone_A.connections.Remove(src) - if(!zone_A.connections.len) - zone_A.connections = null - - if(zone_B && zone_B.connections) - zone_B.connections.Remove(src) - if(!zone_B.connections.len) - zone_B.connections = null - - if(A.zone) - if(!A.zone.connections) - A.zone.connections = list() - A.zone.connections |= src - - if(B.zone) - if(!B.zone.connections) - B.zone.connections = list() - B.zone.connections |= src - - //If either zone is null, we disconnect the archived ones after cleaning up the connections. - if(!A.zone || !B.zone) - if(zone_A && zone_B) - DisconnectZones(zone_B, zone_A) - - if(!A.zone) - zone_A = A.zone - - if(!B.zone) - zone_B = B.zone - return - - //Handle diconnection and reconnection of zones. + //If the "B" zone is null, we disconnect the archived ones after cleaning up the connections. + if(!B.zone) if(zone_A && zone_B) DisconnectZones(zone_A, zone_B) - ConnectZones(A.zone, B.zone, indirect) - - //resetting values of archived values. zone_B = B.zone - zone_A = A.zone + return - //The "A" zone changed. - else if(A.zone && A.zone != zone_A) - - //Handle connection cleanup - if(zone_A) - if(zone_A.connections) - zone_A.connections.Remove(src) - if(!zone_A.connections.len) - zone_A.connections = null - - if(A.zone) - if(!A.zone.connections) - A.zone.connections = list() - A.zone.connections |= src - - //If the "A" zone is null, we disconnect the archived ones after cleaning up the connections. - if(!A.zone) - if(zone_A && zone_B) - DisconnectZones(zone_A, zone_B) - zone_A = A.zone - return - - //Handle diconnection and reconnection of zones. - if(zone_A && zone_B) - DisconnectZones(zone_A, zone_B) - ConnectZones(A.zone, B.zone, indirect) - - //The "B" zone changed. - else if(B.zone && B.zone != zone_B) - - //Handle connection cleanup - if(zone_B) - if(zone_B.connections) - zone_B.connections.Remove(src) - if(!zone_B.connections.len) - zone_B.connections = null - - if(B.zone) - if(!B.zone.connections) - B.zone.connections = list() - B.zone.connections |= src - - //If the "B" zone is null, we disconnect the archived ones after cleaning up the connections. - if(!B.zone) - if(zone_A && zone_B) - DisconnectZones(zone_A, zone_B) - zone_B = B.zone - return - - //Handle diconnection and reconnection of zones. - if(zone_A && zone_B) - DisconnectZones(zone_A, zone_B) - ConnectZones(A.zone, B.zone, indirect) + //Handle diconnection and reconnection of zones. + if(zone_A && zone_B) + DisconnectZones(zone_A, zone_B) + ConnectZones(A.zone, B.zone, indirect) + zone_B = B.zone #undef CONNECTION_DIRECT diff --git a/code/ZAS/Debug.dm b/code/ZAS/Debug.dm index b3f069a5540..807208a5a3e 100644 --- a/code/ZAS/Debug.dm +++ b/code/ZAS/Debug.dm @@ -8,7 +8,8 @@ client/proc/Zone_Info(turf/T as null|turf) mob << "No zone here." else if(zone_debug_images) - images -= zone_debug_images + for(var/zone in zone_debug_images) + images -= zone_debug_images[zone] zone_debug_images = null client/var/list/zone_debug_images @@ -23,12 +24,12 @@ client/proc/Test_ZAS_Connection(var/turf/simulated/T as turf) "South" = SOUTH,\ "East" = EAST,\ "West" = WEST,\ - "None" = null) + "N/A" = null) var/direction = input("What direction do you wish to test?","Set direction") as null|anything in direction_list if(!direction) return - if(direction == "None") + if(direction == "N/A") if(T.CanPass(null, T, 0,0)) mob << "The turf can pass air! :D" else @@ -55,61 +56,67 @@ client/proc/Test_ZAS_Connection(var/turf/simulated/T as turf) mob << "Both turfs can connect! :)" -zone/proc - DebugDisplay(client/client) - if(!istype(client)) - return +zone/proc/DebugDisplay(client/client) + if(!istype(client)) + return - if(!dbg_output) - dbg_output = 1 //Don't want to be spammed when someone investigates a zone... + if(!dbg_output) + dbg_output = 1 //Don't want to be spammed when someone investigates a zone... - if(!client.zone_debug_images) - client.zone_debug_images = list() - for(var/turf/T in contents) - client.zone_debug_images += image('debug_group.dmi', T) + if(!client.zone_debug_images) + client.zone_debug_images = list() - for(var/turf/space/S in unsimulated_tiles) - client.zone_debug_images += image('debug_space.dmi', S) + var/list/current_zone_images = list() - client << "Zone Air Contents" - client << "Oxygen: [air.oxygen]" - client << "Nitrogen: [air.nitrogen]" - client << "Plasma: [air.toxins]" - client << "Carbon Dioxide: [air.carbon_dioxide]" - client << "Temperature: [air.temperature] K" - client << "Heat Energy: [air.temperature * air.heat_capacity()] J" - client << "Pressure: [air.return_pressure()] KPa" - client << "" - client << "Space Tiles: [length(unsimulated_tiles)]" - client << "Movable Objects: [length(movables())]" - client << "Connections: [length(connections)]" + for(var/turf/T in contents) + current_zone_images += image('debug_group.dmi', T, null, TURF_LAYER) - for(var/connection/C in connections) - client << "\ref[C] [C.A] --> [C.B] [(C.indirect?"Open":"Closed")]" - client.zone_debug_images += image('debug_connect.dmi', C.A) - client.zone_debug_images += image('debug_connect.dmi', C.B) + for(var/turf/space/S in unsimulated_tiles) + current_zone_images += image('debug_space.dmi', S, null, TURF_LAYER) - client << "Connected Zones:" - for(var/zone/zone in connected_zones) - client << "\ref[zone] [zone] - [connected_zones[zone]] (Connected)" + client << "Zone Air Contents" + client << "Oxygen: [air.oxygen]" + client << "Nitrogen: [air.nitrogen]" + client << "Plasma: [air.toxins]" + client << "Carbon Dioxide: [air.carbon_dioxide]" + client << "Temperature: [air.temperature] K" + client << "Heat Energy: [air.temperature * air.heat_capacity()] J" + client << "Pressure: [air.return_pressure()] KPa" + client << "" + client << "Space Tiles: [length(unsimulated_tiles)]" + client << "Movable Objects: [length(movables())]" + client << "Connections: [length(connections)]" - for(var/zone/zone in closed_connection_zones) - client << "\ref[zone] [zone] - [closed_connection_zones[zone]] (Unconnected)" + for(var/connection/C in connections) + client << "\ref[C] [C.A] --> [C.B] [(C.indirect?"Open":"Closed")]" + current_zone_images += image('debug_connect.dmi', C.A, null, TURF_LAYER) + current_zone_images += image('debug_connect.dmi', C.B, null, TURF_LAYER) - for(var/C in connections) - if(!istype(C,/connection)) - client << "[C] (Not Connection!)" + client << "Connected Zones:" + for(var/zone/zone in connected_zones) + client << "\ref[zone] [zone] - [connected_zones[zone]] (Connected)" - client.images += client.zone_debug_images + for(var/zone/zone in closed_connection_zones) + client << "\ref[zone] [zone] - [closed_connection_zones[zone]] (Unconnected)" - else - dbg_output = 0 + for(var/C in connections) + if(!istype(C,/connection)) + client << "[C] (Not Connection!)" - client.images -= client.zone_debug_images - client.zone_debug_images = null + if(!client.zone_debug_images) + client.zone_debug_images = list() + client.zone_debug_images[src] = current_zone_images - for(var/zone/Z in zones) - if(Z.air == air && Z != src) - var/turf/zloc = pick(Z.contents) - client << "\red Illegal air datum shared by: [zloc.loc.name]" + client.images += client.zone_debug_images[src] + + else + dbg_output = 0 + + client.images -= client.zone_debug_images[src] + client.zone_debug_images.Remove(src) + + for(var/zone/Z in zones) + if(Z.air == air && Z != src) + var/turf/zloc = pick(Z.contents) + client << "\red Illegal air datum shared by: [zloc.loc.name]" diff --git a/code/ZAS/FEA_gas_mixture.dm b/code/ZAS/FEA_gas_mixture.dm index a4104ab01c7..8b7ab992c93 100644 --- a/code/ZAS/FEA_gas_mixture.dm +++ b/code/ZAS/FEA_gas_mixture.dm @@ -14,141 +14,135 @@ What are the archived variables for? #define QUANTIZE(variable) (round(variable,0.0001)) #define TRANSFER_FRACTION 5 //What fraction (1/#) of the air difference to try and transfer -datum - gas //These are used for the "Trace Gases" stuff, but is buggy. - sleeping_agent - specific_heat = 40 +/datum/gas/sleeping_agent/specific_heat = 40 //These are used for the "Trace Gases" stuff, but is buggy. - oxygen_agent_b - specific_heat = 300 +/datum/gas/oxygen_agent_b/specific_heat = 300 - volatile_fuel - specific_heat = 30 +/datum/gas/volatile_fuel/specific_heat = 30 - var - moles = 0 - specific_heat = 0 +/datum/gas + var/moles = 0 - moles_archived = 0 + var/specific_heat = 0 - gas_mixture - var //Holds the "moles" of each of the four gases. - oxygen = 0 - carbon_dioxide = 0 - nitrogen = 0 - toxins = 0 - total_moles = 0 //Updated when a reaction occurs. + var/moles_archived = 0 - volume = CELL_VOLUME +/datum/gas_mixture/ + var/oxygen = 0 //Holds the "moles" of each of the four gases. + var/carbon_dioxide = 0 + var/nitrogen = 0 + var/toxins = 0 - temperature = 0 //in Kelvin, use calculate_temperature() to modify + var/total_moles = 0 //Updated when a reaction occurs. - group_multiplier = 1 + var/volume = CELL_VOLUME + + var/temperature = 0 //in Kelvin, use calculate_temperature() to modify + + var/group_multiplier = 1 //Size of the group this gas_mixture is representing. //=1 for singletons - graphic + var/graphic - list/datum/gas/trace_gases = list() //Seemed to be a good idea that was abandoned + var/list/datum/gas/trace_gases = list() //Seemed to be a good idea that was abandoned - tmp //These are variables for use with the archived data - oxygen_archived - carbon_dioxide_archived - nitrogen_archived - toxins_archived + var/tmp/oxygen_archived //These are variables for use with the archived data + var/tmp/carbon_dioxide_archived + var/tmp/nitrogen_archived + var/tmp/toxins_archived - temperature_archived + var/tmp/temperature_archived - graphic_archived = 0 - fuel_burnt = 0 + var/tmp/graphic_archived = 0 + var/tmp/fuel_burnt = 0 //FOR THE LOVE OF GOD PLEASE USE THIS PROC //Call it with negative numbers to remove gases. - proc/adjust(o2 = 0, co2 = 0, n2 = 0, tx = 0, list/datum/gas/traces = list()) - //Purpose: Adjusting the gases within a airmix - //Called by: Nothing, yet! - //Inputs: The values of the gases to adjust - //Outputs: null +/datum/gas_mixture/proc/adjust(o2 = 0, co2 = 0, n2 = 0, tx = 0, list/datum/gas/traces = list()) + //Purpose: Adjusting the gases within a airmix + //Called by: Nothing, yet! + //Inputs: The values of the gases to adjust + //Outputs: null - oxygen = max(0, oxygen + o2) - carbon_dioxide = max(0, carbon_dioxide + co2) - nitrogen = max(0, nitrogen + n2) - toxins = max(0, toxins + tx) + oxygen = max(0, oxygen + o2) + carbon_dioxide = max(0, carbon_dioxide + co2) + nitrogen = max(0, nitrogen + n2) + toxins = max(0, toxins + tx) - //handle trace gasses - for(var/datum/gas/G in traces) - var/datum/gas/T = locate(G.type) in trace_gases - if(T) - T.moles = max(G.moles + T.moles, 0) - else if(G.moles > 0) - trace_gases |= G - update_values() - return + //handle trace gasses + for(var/datum/gas/G in traces) + var/datum/gas/T = locate(G.type) in trace_gases + if(T) + T.moles = max(G.moles + T.moles, 0) + else if(G.moles > 0) + trace_gases |= G + update_values() + return //tg seems to like using these a lot - proc/return_temperature() - return temperature +/datum/gas_mixture/proc/return_temperature() + return temperature - proc/return_volume() - return max(0, volume) +/datum/gas_mixture/proc/return_volume() + return max(0, volume) - proc/thermal_energy() - return temperature*heat_capacity() +/datum/gas_mixture/proc/thermal_energy() + return temperature*heat_capacity() /////////////////////////////// //PV=nRT - related procedures// /////////////////////////////// +/datum/gas_mixture/proc/heat_capacity() + //Purpose: Returning the heat capacity of the gas mix + //Called by: UNKNOWN + //Inputs: None + //Outputs: Heat capacity - proc/heat_capacity() - //Purpose: Returning the heat capacity of the gas mix - //Called by: UNKNOWN - //Inputs: None - //Outputs: Heat capacity + var/heat_capacity = HEAT_CAPACITY_CALCULATION(oxygen,carbon_dioxide,nitrogen,toxins) - var/heat_capacity = HEAT_CAPACITY_CALCULATION(oxygen,carbon_dioxide,nitrogen,toxins) + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + heat_capacity += trace_gas.moles*trace_gas.specific_heat - if(trace_gases.len) - for(var/datum/gas/trace_gas in trace_gases) - heat_capacity += trace_gas.moles*trace_gas.specific_heat + return max(MINIMUM_HEAT_CAPACITY,heat_capacity) - return max(MINIMUM_HEAT_CAPACITY,heat_capacity) +/datum/gas_mixture/proc/heat_capacity_archived() + //Purpose: Returning the archived heat capacity of the gas mix + //Called by: UNKNOWN + //Inputs: None + //Outputs: Archived heat capacity - proc/heat_capacity_archived() - //Purpose: Returning the archived heat capacity of the gas mix - //Called by: UNKNOWN - //Inputs: None - //Outputs: Archived heat capacity + var/heat_capacity_archived = HEAT_CAPACITY_CALCULATION(oxygen_archived,carbon_dioxide_archived,nitrogen_archived,toxins_archived) - var/heat_capacity_archived = HEAT_CAPACITY_CALCULATION(oxygen_archived,carbon_dioxide_archived,nitrogen_archived,toxins_archived) + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + heat_capacity_archived += trace_gas.moles_archived*trace_gas.specific_heat - if(trace_gases.len) - for(var/datum/gas/trace_gas in trace_gases) - heat_capacity_archived += trace_gas.moles_archived*trace_gas.specific_heat + return max(MINIMUM_HEAT_CAPACITY,heat_capacity_archived) - return max(MINIMUM_HEAT_CAPACITY,heat_capacity_archived) +/datum/gas_mixture/proc/total_moles() + return total_moles + /*var/moles = oxygen + carbon_dioxide + nitrogen + toxins - proc/total_moles() - return total_moles - /*var/moles = oxygen + carbon_dioxide + nitrogen + toxins + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + moles += trace_gas.moles + return moles*/ - if(trace_gases.len) - for(var/datum/gas/trace_gas in trace_gases) - moles += trace_gas.moles - return moles*/ +/datum/gas_mixture/proc/return_pressure() + //Purpose: Calculating Current Pressure + //Called by: + //Inputs: None + //Outputs: Gas pressure. - proc/return_pressure() - //Purpose: Calculating Current Pressure - //Called by: - //Inputs: None - //Outputs: Gas pressure. - - if(volume>0) - return total_moles()*R_IDEAL_GAS_EQUATION*temperature/volume - return 0 + if(volume>0) + return total_moles()*R_IDEAL_GAS_EQUATION*temperature/volume + return 0 // proc/return_temperature() //Purpose: @@ -171,868 +165,865 @@ datum // return temperature*heat_capacity() - proc/update_values() - //Purpose: Calculating and storing values which were normally called CONSTANTLY - //Called by: Anything that changes values within a gas mix. - //Inputs: None - //Outputs: None +/datum/gas_mixture/proc/update_values() + //Purpose: Calculating and storing values which were normally called CONSTANTLY + //Called by: Anything that changes values within a gas mix. + //Inputs: None + //Outputs: None - total_moles = oxygen + carbon_dioxide + nitrogen + toxins + total_moles = oxygen + carbon_dioxide + nitrogen + toxins - if(trace_gases.len) - for(var/datum/gas/trace_gas in trace_gases) - total_moles += trace_gas.moles + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + total_moles += trace_gas.moles - return + return //////////////////////////////////////////// //Procedures used for very specific events// //////////////////////////////////////////// +/datum/gas_mixture/proc/check_tile_graphic() + //Purpose: Calculating the graphic for a tile + //Called by: Turfs updating + //Inputs: None + //Outputs: 1 if graphic changed, 0 if unchanged - proc/check_tile_graphic() - //Purpose: Calculating the graphic for a tile - //Called by: Turfs updating - //Inputs: None - //Outputs: 1 if graphic changed, 0 if unchanged - + graphic = 0 + if(toxins > MOLES_PLASMA_VISIBLE) + graphic = 1 + else if(length(trace_gases)) + var/datum/gas/sleeping_agent = locate(/datum/gas/sleeping_agent) in trace_gases + if(sleeping_agent && (sleeping_agent.moles > 1)) + graphic = 2 + else graphic = 0 - if(toxins > MOLES_PLASMA_VISIBLE) - graphic = 1 - else if(length(trace_gases)) - var/datum/gas/sleeping_agent = locate(/datum/gas/sleeping_agent) in trace_gases - if(sleeping_agent && (sleeping_agent.moles > 1)) - graphic = 2 - else - graphic = 0 - return graphic != graphic_archived + return graphic != graphic_archived - proc/react(atom/dump_location) - //Purpose: Calculating if it is possible for a fire to occur in the airmix - //Called by: Air mixes updating? - //Inputs: None - //Outputs: If a fire occured +/datum/gas_mixture/proc/react(atom/dump_location) + //Purpose: Calculating if it is possible for a fire to occur in the airmix + //Called by: Air mixes updating? + //Inputs: None + //Outputs: If a fire occured - var/reacting = 0 //set to 1 if a notable reaction occured (used by pipe_network) + var/reacting = 0 //set to 1 if a notable reaction occured (used by pipe_network) - if(temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST) - if(zburn(null) > 0) - reacting = 1 + if(temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST) + if(zburn(null) > 0) + reacting = 1 - return reacting + return reacting - proc/fire() - //Purpose: Calculating any fire reactions. - //Called by: react() (See above) - //Inputs: None - //Outputs: How much fuel burned +/datum/gas_mixture/proc/fire() + //Purpose: Calculating any fire reactions. + //Called by: react() (See above) + //Inputs: None + //Outputs: How much fuel burned - return zburn(null) + return zburn(null) - /*var/energy_released = 0 - var/old_heat_capacity = heat_capacity() + /*var/energy_released = 0 + var/old_heat_capacity = heat_capacity() - var/datum/gas/volatile_fuel/fuel_store = locate(/datum/gas/volatile_fuel) in trace_gases - if(fuel_store) //General volatile gas burn - var/burned_fuel = 0 + var/datum/gas/volatile_fuel/fuel_store = locate(/datum/gas/volatile_fuel) in trace_gases + if(fuel_store) //General volatile gas burn + var/burned_fuel = 0 - if(oxygen < fuel_store.moles) - burned_fuel = oxygen - fuel_store.moles -= burned_fuel - oxygen = 0 - else - burned_fuel = fuel_store.moles - oxygen -= fuel_store.moles - del(fuel_store) + if(oxygen < fuel_store.moles) + burned_fuel = oxygen + fuel_store.moles -= burned_fuel + oxygen = 0 + else + burned_fuel = fuel_store.moles + oxygen -= fuel_store.moles + del(fuel_store) - energy_released += FIRE_CARBON_ENERGY_RELEASED * burned_fuel - carbon_dioxide += burned_fuel - fuel_burnt += burned_fuel + energy_released += FIRE_CARBON_ENERGY_RELEASED * burned_fuel + carbon_dioxide += burned_fuel + fuel_burnt += burned_fuel - //Handle plasma burning - if(toxins > MINIMUM_HEAT_CAPACITY) - var/plasma_burn_rate = 0 - var/oxygen_burn_rate = 0 - //more plasma released at higher temperatures - var/temperature_scale - if(temperature > PLASMA_UPPER_TEMPERATURE) - temperature_scale = 1 - else - temperature_scale = (temperature-PLASMA_MINIMUM_BURN_TEMPERATURE)/(PLASMA_UPPER_TEMPERATURE-PLASMA_MINIMUM_BURN_TEMPERATURE) - if(temperature_scale > 0) - oxygen_burn_rate = 1.4 - temperature_scale - if(oxygen > toxins*PLASMA_OXYGEN_FULLBURN) - plasma_burn_rate = (toxins*temperature_scale)/4 - else - plasma_burn_rate = (temperature_scale*(oxygen/PLASMA_OXYGEN_FULLBURN))/4 - if(plasma_burn_rate > MINIMUM_HEAT_CAPACITY) - toxins -= plasma_burn_rate - oxygen -= plasma_burn_rate*oxygen_burn_rate - carbon_dioxide += plasma_burn_rate + //Handle plasma burning + if(toxins > MINIMUM_HEAT_CAPACITY) + var/plasma_burn_rate = 0 + var/oxygen_burn_rate = 0 + //more plasma released at higher temperatures + var/temperature_scale + if(temperature > PLASMA_UPPER_TEMPERATURE) + temperature_scale = 1 + else + temperature_scale = (temperature-PLASMA_MINIMUM_BURN_TEMPERATURE)/(PLASMA_UPPER_TEMPERATURE-PLASMA_MINIMUM_BURN_TEMPERATURE) + if(temperature_scale > 0) + oxygen_burn_rate = 1.4 - temperature_scale + if(oxygen > toxins*PLASMA_OXYGEN_FULLBURN) + plasma_burn_rate = (toxins*temperature_scale)/4 + else + plasma_burn_rate = (temperature_scale*(oxygen/PLASMA_OXYGEN_FULLBURN))/4 + if(plasma_burn_rate > MINIMUM_HEAT_CAPACITY) + toxins -= plasma_burn_rate + oxygen -= plasma_burn_rate*oxygen_burn_rate + carbon_dioxide += plasma_burn_rate - energy_released += FIRE_PLASMA_ENERGY_RELEASED * (plasma_burn_rate) + energy_released += FIRE_PLASMA_ENERGY_RELEASED * (plasma_burn_rate) - fuel_burnt += (plasma_burn_rate)*(1+oxygen_burn_rate) + fuel_burnt += (plasma_burn_rate)*(1+oxygen_burn_rate) - if(energy_released > 0) - var/new_heat_capacity = heat_capacity() - if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - temperature = (temperature*old_heat_capacity + energy_released)/new_heat_capacity - update_values() + if(energy_released > 0) + var/new_heat_capacity = heat_capacity() + if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) + temperature = (temperature*old_heat_capacity + energy_released)/new_heat_capacity + update_values() - return fuel_burnt*/ + return fuel_burnt*/ ////////////////////////////////////////////// //Procs for general gas spread calculations.// ////////////////////////////////////////////// - proc/archive() - //Purpose: Archives the current gas values - //Called by: UNKNOWN - //Inputs: None - //Outputs: 1 +/datum/gas_mixture/proc/archive() + //Purpose: Archives the current gas values + //Called by: UNKNOWN + //Inputs: None + //Outputs: 1 - oxygen_archived = oxygen - carbon_dioxide_archived = carbon_dioxide - nitrogen_archived = nitrogen - toxins_archived = toxins + oxygen_archived = oxygen + carbon_dioxide_archived = carbon_dioxide + nitrogen_archived = nitrogen + toxins_archived = toxins - if(trace_gases.len) - for(var/datum/gas/trace_gas in trace_gases) - trace_gas.moles_archived = trace_gas.moles + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + trace_gas.moles_archived = trace_gas.moles - temperature_archived = temperature + temperature_archived = temperature - graphic_archived = graphic + graphic_archived = graphic - return 1 + return 1 - proc/check_then_merge(datum/gas_mixture/giver) - //Purpose: Similar to merge(...) but first checks to see if the amount of air assumed is small enough - // that group processing is still accurate for source (aborts if not) - //Called by: airgroups/machinery expelling air, ? - //Inputs: The gas to try and merge - //Outputs: 1 on successful merge. 0 otherwise. +/datum/gas_mixture/proc/check_then_merge(datum/gas_mixture/giver) + //Purpose: Similar to merge(...) but first checks to see if the amount of air assumed is small enough + // that group processing is still accurate for source (aborts if not) + //Called by: airgroups/machinery expelling air, ? + //Inputs: The gas to try and merge + //Outputs: 1 on successful merge. 0 otherwise. - if(!giver) - return 0 - if(((giver.oxygen > MINIMUM_AIR_TO_SUSPEND) && (giver.oxygen >= oxygen*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ - || ((giver.carbon_dioxide > MINIMUM_AIR_TO_SUSPEND) && (giver.carbon_dioxide >= carbon_dioxide*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ - || ((giver.nitrogen > MINIMUM_AIR_TO_SUSPEND) && (giver.nitrogen >= nitrogen*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ - || ((giver.toxins > MINIMUM_AIR_TO_SUSPEND) && (giver.toxins >= toxins*MINIMUM_AIR_RATIO_TO_SUSPEND))) - return 0 - if(abs(giver.temperature - temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) + if(!giver) + return 0 + if(((giver.oxygen > MINIMUM_AIR_TO_SUSPEND) && (giver.oxygen >= oxygen*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((giver.carbon_dioxide > MINIMUM_AIR_TO_SUSPEND) && (giver.carbon_dioxide >= carbon_dioxide*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((giver.nitrogen > MINIMUM_AIR_TO_SUSPEND) && (giver.nitrogen >= nitrogen*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((giver.toxins > MINIMUM_AIR_TO_SUSPEND) && (giver.toxins >= toxins*MINIMUM_AIR_RATIO_TO_SUSPEND))) + return 0 + if(abs(giver.temperature - temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) + return 0 + + if(giver.trace_gases.len) + for(var/datum/gas/trace_gas in giver.trace_gases) + var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases + if((trace_gas.moles > MINIMUM_AIR_TO_SUSPEND) && (!corresponding || (trace_gas.moles >= corresponding.moles*MINIMUM_AIR_RATIO_TO_SUSPEND))) return 0 - if(giver.trace_gases.len) - for(var/datum/gas/trace_gas in giver.trace_gases) - var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases - if((trace_gas.moles > MINIMUM_AIR_TO_SUSPEND) && (!corresponding || (trace_gas.moles >= corresponding.moles*MINIMUM_AIR_RATIO_TO_SUSPEND))) + return merge(giver) + +/datum/gas_mixture/proc/merge(datum/gas_mixture/giver) + //Purpose: Merges all air from giver into self. Deletes giver. + //Called by: Machinery expelling air, check_then_merge, ? + //Inputs: The gas to merge. + //Outputs: 1 + + if(!giver) + return 0 + + if(abs(temperature-giver.temperature)>MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + var/self_heat_capacity = heat_capacity()*group_multiplier + var/giver_heat_capacity = giver.heat_capacity()*giver.group_multiplier + var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity + if(combined_heat_capacity != 0) + temperature = (giver.temperature*giver_heat_capacity + temperature*self_heat_capacity)/combined_heat_capacity + + if((group_multiplier>1)||(giver.group_multiplier>1)) + oxygen += giver.oxygen*giver.group_multiplier/group_multiplier + carbon_dioxide += giver.carbon_dioxide*giver.group_multiplier/group_multiplier + nitrogen += giver.nitrogen*giver.group_multiplier/group_multiplier + toxins += giver.toxins*giver.group_multiplier/group_multiplier + else + oxygen += giver.oxygen + carbon_dioxide += giver.carbon_dioxide + nitrogen += giver.nitrogen + toxins += giver.toxins + + if(giver.trace_gases.len) + for(var/datum/gas/trace_gas in giver.trace_gases) + var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases + if(!corresponding) + corresponding = new trace_gas.type() + trace_gases += corresponding + corresponding.moles += trace_gas.moles*giver.group_multiplier/group_multiplier + update_values() + + // Let the garbage collector handle it, faster according to /tg/ testers + //del(giver) + return 1 + +/datum/gas_mixture/proc/remove(amount) + //Purpose: Removes a certain number of moles from the air. + //Called by: ? + //Inputs: How many moles to remove. + //Outputs: Removed air. + + var/sum = total_moles() + amount = min(amount,sum) //Can not take more air than tile has! + if(amount <= 0) + return null + + var/datum/gas_mixture/removed = new + + + removed.oxygen = QUANTIZE((oxygen/sum)*amount) + removed.nitrogen = QUANTIZE((nitrogen/sum)*amount) + removed.carbon_dioxide = QUANTIZE((carbon_dioxide/sum)*amount) + removed.toxins = QUANTIZE((toxins/sum)*amount) + + oxygen -= removed.oxygen/group_multiplier + nitrogen -= removed.nitrogen/group_multiplier + carbon_dioxide -= removed.carbon_dioxide/group_multiplier + toxins -= removed.toxins/group_multiplier + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + var/datum/gas/corresponding = new trace_gas.type() + removed.trace_gases += corresponding + + corresponding.moles = (trace_gas.moles/sum)*amount + trace_gas.moles -= corresponding.moles/group_multiplier + + removed.temperature = temperature + update_values() + removed.update_values() + + return removed + +/datum/gas_mixture/proc/remove_ratio(ratio) + //Purpose: Removes a certain ratio of the air. + //Called by: ? + //Inputs: Percentage to remove. + //Outputs: Removed air. + + if(ratio <= 0) + return null + + ratio = min(ratio, 1) + + var/datum/gas_mixture/removed = new + + removed.oxygen = QUANTIZE(oxygen*ratio) + removed.nitrogen = QUANTIZE(nitrogen*ratio) + removed.carbon_dioxide = QUANTIZE(carbon_dioxide*ratio) + removed.toxins = QUANTIZE(toxins*ratio) + + oxygen -= removed.oxygen/group_multiplier + nitrogen -= removed.nitrogen/group_multiplier + carbon_dioxide -= removed.carbon_dioxide/group_multiplier + toxins -= removed.toxins/group_multiplier + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + var/datum/gas/corresponding = new trace_gas.type() + removed.trace_gases += corresponding + + corresponding.moles = trace_gas.moles*ratio + trace_gas.moles -= corresponding.moles/group_multiplier + + removed.temperature = temperature + update_values() + removed.update_values() + + return removed + +/datum/gas_mixture/proc/check_then_remove(amount) + //Purpose: Similar to remove(...) but first checks to see if the amount of air removed is small enough + // that group processing is still accurate for source (aborts if not) + //Called by: ? + //Inputs: Number of moles to remove + //Outputs: Removed air or 0 if it can remove air or not. + + amount = min(amount,total_moles()) //Can not take more air than tile has! + + if((amount > MINIMUM_AIR_RATIO_TO_SUSPEND) && (amount > total_moles()*MINIMUM_AIR_RATIO_TO_SUSPEND)) + return 0 + + return remove(amount) + +/datum/gas_mixture/proc/copy_from(datum/gas_mixture/sample) + //Purpose: Duplicates the sample air mixture. + //Called by: airgroups splitting, ? + //Inputs: Gas to copy + //Outputs: 1 + + oxygen = sample.oxygen + carbon_dioxide = sample.carbon_dioxide + nitrogen = sample.nitrogen + toxins = sample.toxins + total_moles = sample.total_moles() + + trace_gases.len=null + if(sample.trace_gases.len > 0) + for(var/datum/gas/trace_gas in sample.trace_gases) + var/datum/gas/corresponding = new trace_gas.type() + trace_gases += corresponding + + corresponding.moles = trace_gas.moles + + temperature = sample.temperature + + return 1 + +/datum/gas_mixture/proc/check_gas_mixture(datum/gas_mixture/sharer) + //Purpose: Telling if one or both airgroups needs to disable group processing. + //Called by: Airgroups sharing air, checking if group processing needs disabled. + //Inputs: Gas to compare from other airgroup + //Outputs: 0 if the self-check failed (local airgroup breaks?) + // then -1 if sharer-check failed (sharing airgroup breaks?) + // then 1 if both checks pass (share succesful?) + if(!istype(sharer)) + return + + var/delta_oxygen = QUANTIZE(oxygen_archived - sharer.oxygen_archived)/TRANSFER_FRACTION + var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - sharer.carbon_dioxide_archived)/TRANSFER_FRACTION + var/delta_nitrogen = QUANTIZE(nitrogen_archived - sharer.nitrogen_archived)/TRANSFER_FRACTION + var/delta_toxins = QUANTIZE(toxins_archived - sharer.toxins_archived)/TRANSFER_FRACTION + + var/delta_temperature = (temperature_archived - sharer.temperature_archived) + + if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND))) + return 0 + + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) + return 0 + + if(sharer.trace_gases.len) + for(var/datum/gas/trace_gas in sharer.trace_gases) + if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4) + var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases + if(corresponding) + if(trace_gas.moles_archived >= corresponding.moles_archived*MINIMUM_AIR_RATIO_TO_SUSPEND*4) return 0 - - return merge(giver) - - proc/merge(datum/gas_mixture/giver) - //Purpose: Merges all air from giver into self. Deletes giver. - //Called by: Machinery expelling air, check_then_merge, ? - //Inputs: The gas to merge. - //Outputs: 1 - - if(!giver) - return 0 - - if(abs(temperature-giver.temperature)>MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - var/self_heat_capacity = heat_capacity()*group_multiplier - var/giver_heat_capacity = giver.heat_capacity()*giver.group_multiplier - var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity - if(combined_heat_capacity != 0) - temperature = (giver.temperature*giver_heat_capacity + temperature*self_heat_capacity)/combined_heat_capacity - - if((group_multiplier>1)||(giver.group_multiplier>1)) - oxygen += giver.oxygen*giver.group_multiplier/group_multiplier - carbon_dioxide += giver.carbon_dioxide*giver.group_multiplier/group_multiplier - nitrogen += giver.nitrogen*giver.group_multiplier/group_multiplier - toxins += giver.toxins*giver.group_multiplier/group_multiplier - else - oxygen += giver.oxygen - carbon_dioxide += giver.carbon_dioxide - nitrogen += giver.nitrogen - toxins += giver.toxins - - if(giver.trace_gases.len) - for(var/datum/gas/trace_gas in giver.trace_gases) - var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases - if(!corresponding) - corresponding = new trace_gas.type() - trace_gases += corresponding - corresponding.moles += trace_gas.moles*giver.group_multiplier/group_multiplier - update_values() - - // Let the garbage collector handle it, faster according to /tg/ testers - //del(giver) - return 1 - - proc/remove(amount) - //Purpose: Removes a certain number of moles from the air. - //Called by: ? - //Inputs: How many moles to remove. - //Outputs: Removed air. - - var/sum = total_moles() - amount = min(amount,sum) //Can not take more air than tile has! - if(amount <= 0) - return null - - var/datum/gas_mixture/removed = new - - - removed.oxygen = QUANTIZE((oxygen/sum)*amount) - removed.nitrogen = QUANTIZE((nitrogen/sum)*amount) - removed.carbon_dioxide = QUANTIZE((carbon_dioxide/sum)*amount) - removed.toxins = QUANTIZE((toxins/sum)*amount) - - oxygen -= removed.oxygen/group_multiplier - nitrogen -= removed.nitrogen/group_multiplier - carbon_dioxide -= removed.carbon_dioxide/group_multiplier - toxins -= removed.toxins/group_multiplier - - if(trace_gases.len) - for(var/datum/gas/trace_gas in trace_gases) - var/datum/gas/corresponding = new trace_gas.type() - removed.trace_gases += corresponding - - corresponding.moles = (trace_gas.moles/sum)*amount - trace_gas.moles -= corresponding.moles/group_multiplier - - removed.temperature = temperature - update_values() - removed.update_values() - - return removed - - proc/remove_ratio(ratio) - //Purpose: Removes a certain ratio of the air. - //Called by: ? - //Inputs: Percentage to remove. - //Outputs: Removed air. - - if(ratio <= 0) - return null - - ratio = min(ratio, 1) - - var/datum/gas_mixture/removed = new - - removed.oxygen = QUANTIZE(oxygen*ratio) - removed.nitrogen = QUANTIZE(nitrogen*ratio) - removed.carbon_dioxide = QUANTIZE(carbon_dioxide*ratio) - removed.toxins = QUANTIZE(toxins*ratio) - - oxygen -= removed.oxygen/group_multiplier - nitrogen -= removed.nitrogen/group_multiplier - carbon_dioxide -= removed.carbon_dioxide/group_multiplier - toxins -= removed.toxins/group_multiplier - - if(trace_gases.len) - for(var/datum/gas/trace_gas in trace_gases) - var/datum/gas/corresponding = new trace_gas.type() - removed.trace_gases += corresponding - - corresponding.moles = trace_gas.moles*ratio - trace_gas.moles -= corresponding.moles/group_multiplier - - removed.temperature = temperature - update_values() - removed.update_values() - - return removed - - proc/check_then_remove(amount) - //Purpose: Similar to remove(...) but first checks to see if the amount of air removed is small enough - // that group processing is still accurate for source (aborts if not) - //Called by: ? - //Inputs: Number of moles to remove - //Outputs: Removed air or 0 if it can remove air or not. - - amount = min(amount,total_moles()) //Can not take more air than tile has! - - if((amount > MINIMUM_AIR_RATIO_TO_SUSPEND) && (amount > total_moles()*MINIMUM_AIR_RATIO_TO_SUSPEND)) - return 0 - - return remove(amount) - - proc/copy_from(datum/gas_mixture/sample) - //Purpose: Duplicates the sample air mixture. - //Called by: airgroups splitting, ? - //Inputs: Gas to copy - //Outputs: 1 - - oxygen = sample.oxygen - carbon_dioxide = sample.carbon_dioxide - nitrogen = sample.nitrogen - toxins = sample.toxins - total_moles = sample.total_moles() - - trace_gases.len=null - if(sample.trace_gases.len > 0) - for(var/datum/gas/trace_gas in sample.trace_gases) - var/datum/gas/corresponding = new trace_gas.type() - trace_gases += corresponding - - corresponding.moles = trace_gas.moles - - temperature = sample.temperature - - return 1 - - proc/check_gas_mixture(datum/gas_mixture/sharer) - //Purpose: Telling if one or both airgroups needs to disable group processing. - //Called by: Airgroups sharing air, checking if group processing needs disabled. - //Inputs: Gas to compare from other airgroup - //Outputs: 0 if the self-check failed (local airgroup breaks?) - // then -1 if sharer-check failed (sharing airgroup breaks?) - // then 1 if both checks pass (share succesful?) - if(!istype(sharer)) - return - - var/delta_oxygen = QUANTIZE(oxygen_archived - sharer.oxygen_archived)/TRANSFER_FRACTION - var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - sharer.carbon_dioxide_archived)/TRANSFER_FRACTION - var/delta_nitrogen = QUANTIZE(nitrogen_archived - sharer.nitrogen_archived)/TRANSFER_FRACTION - var/delta_toxins = QUANTIZE(toxins_archived - sharer.toxins_archived)/TRANSFER_FRACTION - - var/delta_temperature = (temperature_archived - sharer.temperature_archived) - - if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ - || ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ - || ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ - || ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND))) - return 0 - - if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) - return 0 - - if(sharer.trace_gases.len) - for(var/datum/gas/trace_gas in sharer.trace_gases) - if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4) - var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases - if(corresponding) - if(trace_gas.moles_archived >= corresponding.moles_archived*MINIMUM_AIR_RATIO_TO_SUSPEND*4) - return 0 - else - return 0 - - if(trace_gases.len) - for(var/datum/gas/trace_gas in trace_gases) - if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4) - if(!locate(trace_gas.type) in sharer.trace_gases) - return 0 - - if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= sharer.oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ - || ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= sharer.carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ - || ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= sharer.nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ - || ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= sharer.toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND))) - return -1 - - if(trace_gases.len) - for(var/datum/gas/trace_gas in trace_gases) - if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4) - var/datum/gas/corresponding = locate(trace_gas.type) in sharer.trace_gases - if(corresponding) - if(trace_gas.moles_archived >= corresponding.moles_archived*MINIMUM_AIR_RATIO_TO_SUSPEND*4) - return -1 - else - return -1 - - return 1 - - proc/check_turf(turf/model) - //Purpose: Used to compare the gases in an unsimulated turf with the gas in a simulated one. - //Called by: Sharing air (mimicing) with adjacent unsimulated turfs - //Inputs: Unsimulated turf - //Outputs: 1 if safe to mimic, 0 if needs to break airgroup. - - var/delta_oxygen = (oxygen_archived - model.oxygen)/TRANSFER_FRACTION - var/delta_carbon_dioxide = (carbon_dioxide_archived - model.carbon_dioxide)/TRANSFER_FRACTION - var/delta_nitrogen = (nitrogen_archived - model.nitrogen)/TRANSFER_FRACTION - var/delta_toxins = (toxins_archived - model.toxins)/TRANSFER_FRACTION - - var/delta_temperature = (temperature_archived - model.temperature) - - if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ - || ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ - || ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ - || ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND))) - return 0 - if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) - return 0 - - if(trace_gases.len) - for(var/datum/gas/trace_gas in trace_gases) - if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4) - return 0 - - return 1 - - proc/share(datum/gas_mixture/sharer) - //Purpose: Used to transfer gas from a more pressurised tile to a less presurised tile - // (Two directional, if the other tile is more pressurised, air travels to current tile) - //Called by: Sharing air with adjacent simulated turfs - //Inputs: Air datum to share with - //Outputs: Amount of gas exchanged (Negative if lost air, positive if gained.) - - - if(!istype(sharer)) - return - - var/delta_oxygen = QUANTIZE(oxygen_archived - sharer.oxygen_archived)/TRANSFER_FRACTION - var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - sharer.carbon_dioxide_archived)/TRANSFER_FRACTION - var/delta_nitrogen = QUANTIZE(nitrogen_archived - sharer.nitrogen_archived)/TRANSFER_FRACTION - var/delta_toxins = QUANTIZE(toxins_archived - sharer.toxins_archived)/TRANSFER_FRACTION - - var/delta_temperature = (temperature_archived - sharer.temperature_archived) - - var/old_self_heat_capacity = 0 - var/old_sharer_heat_capacity = 0 - - var/heat_self_to_sharer = 0 - var/heat_capacity_self_to_sharer = 0 - var/heat_sharer_to_self = 0 - var/heat_capacity_sharer_to_self = 0 - - if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - - var/delta_air = delta_oxygen+delta_nitrogen - if(delta_air) - var/air_heat_capacity = SPECIFIC_HEAT_AIR*delta_air - if(delta_air > 0) - heat_self_to_sharer += air_heat_capacity*temperature_archived - heat_capacity_self_to_sharer += air_heat_capacity - else - heat_sharer_to_self -= air_heat_capacity*sharer.temperature_archived - heat_capacity_sharer_to_self -= air_heat_capacity - - if(delta_carbon_dioxide) - var/carbon_dioxide_heat_capacity = SPECIFIC_HEAT_CDO*delta_carbon_dioxide - if(delta_carbon_dioxide > 0) - heat_self_to_sharer += carbon_dioxide_heat_capacity*temperature_archived - heat_capacity_self_to_sharer += carbon_dioxide_heat_capacity - else - heat_sharer_to_self -= carbon_dioxide_heat_capacity*sharer.temperature_archived - heat_capacity_sharer_to_self -= carbon_dioxide_heat_capacity - - if(delta_toxins) - var/toxins_heat_capacity = SPECIFIC_HEAT_TOXIN*delta_toxins - if(delta_toxins > 0) - heat_self_to_sharer += toxins_heat_capacity*temperature_archived - heat_capacity_self_to_sharer += toxins_heat_capacity - else - heat_sharer_to_self -= toxins_heat_capacity*sharer.temperature_archived - heat_capacity_sharer_to_self -= toxins_heat_capacity - - old_self_heat_capacity = heat_capacity()*group_multiplier - old_sharer_heat_capacity = sharer.heat_capacity()*sharer.group_multiplier - - oxygen -= delta_oxygen/group_multiplier - sharer.oxygen += delta_oxygen/sharer.group_multiplier - - carbon_dioxide -= delta_carbon_dioxide/group_multiplier - sharer.carbon_dioxide += delta_carbon_dioxide/sharer.group_multiplier - - nitrogen -= delta_nitrogen/group_multiplier - sharer.nitrogen += delta_nitrogen/sharer.group_multiplier - - toxins -= delta_toxins/group_multiplier - sharer.toxins += delta_toxins/sharer.group_multiplier - - var/moved_moles = (delta_oxygen + delta_carbon_dioxide + delta_nitrogen + delta_toxins) - - var/list/trace_types_considered = list() - - if(trace_gases.len) - for(var/datum/gas/trace_gas in trace_gases) - - var/datum/gas/corresponding = locate(trace_gas.type) in sharer.trace_gases - var/delta = 0 - - if(corresponding) - delta = QUANTIZE(trace_gas.moles_archived - corresponding.moles_archived)/TRANSFER_FRACTION - else - corresponding = new trace_gas.type() - sharer.trace_gases += corresponding - - delta = trace_gas.moles_archived/TRANSFER_FRACTION - - trace_gas.moles -= delta/group_multiplier - corresponding.moles += delta/sharer.group_multiplier - - if(delta) - var/individual_heat_capacity = trace_gas.specific_heat*delta - if(delta > 0) - heat_self_to_sharer += individual_heat_capacity*temperature_archived - heat_capacity_self_to_sharer += individual_heat_capacity - else - heat_sharer_to_self -= individual_heat_capacity*sharer.temperature_archived - heat_capacity_sharer_to_self -= individual_heat_capacity - - moved_moles += delta - - trace_types_considered += trace_gas.type - - - if(sharer.trace_gases.len) - for(var/datum/gas/trace_gas in sharer.trace_gases) - if(trace_gas.type in trace_types_considered) continue - else - var/datum/gas/corresponding - var/delta = 0 - - corresponding = new trace_gas.type() - trace_gases += corresponding - - delta = trace_gas.moles_archived/TRANSFER_FRACTION - - trace_gas.moles -= delta/sharer.group_multiplier - corresponding.moles += delta/group_multiplier - - //Guaranteed transfer from sharer to self - var/individual_heat_capacity = trace_gas.specific_heat*delta - heat_sharer_to_self += individual_heat_capacity*sharer.temperature_archived - heat_capacity_sharer_to_self += individual_heat_capacity - - moved_moles += -delta - update_values() - sharer.update_values() - - if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - var/new_self_heat_capacity = old_self_heat_capacity + heat_capacity_sharer_to_self - heat_capacity_self_to_sharer - var/new_sharer_heat_capacity = old_sharer_heat_capacity + heat_capacity_self_to_sharer - heat_capacity_sharer_to_self - - if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY) - temperature = (old_self_heat_capacity*temperature - heat_capacity_self_to_sharer*temperature_archived + heat_capacity_sharer_to_self*sharer.temperature_archived)/new_self_heat_capacity - - if(new_sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) - sharer.temperature = (old_sharer_heat_capacity*sharer.temperature-heat_capacity_sharer_to_self*sharer.temperature_archived + heat_capacity_self_to_sharer*temperature_archived)/new_sharer_heat_capacity - - if(abs(old_sharer_heat_capacity) > MINIMUM_HEAT_CAPACITY) - if(abs(new_sharer_heat_capacity/old_sharer_heat_capacity - 1) < 0.10) // <10% change in sharer heat capacity - temperature_share(sharer, OPEN_HEAT_TRANSFER_COEFFICIENT) - - if((delta_temperature > MINIMUM_TEMPERATURE_TO_MOVE) || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE) - var/delta_pressure = temperature_archived*(total_moles() + moved_moles) - sharer.temperature_archived*(sharer.total_moles() - moved_moles) - return delta_pressure*R_IDEAL_GAS_EQUATION/volume - - else - return 0 - - proc/mimic(turf/model, border_multiplier) - //Purpose: Used transfer gas from a more pressurised tile to a less presurised unsimulated tile. - //Called by: "sharing" from unsimulated to simulated turfs. - //Inputs: Unsimulated turf, Multiplier for gas transfer (optional) - //Outputs: Amount of gas exchanged - - var/delta_oxygen = QUANTIZE(oxygen_archived - model.oxygen)/TRANSFER_FRACTION - var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - model.carbon_dioxide)/TRANSFER_FRACTION - var/delta_nitrogen = QUANTIZE(nitrogen_archived - model.nitrogen)/TRANSFER_FRACTION - var/delta_toxins = QUANTIZE(toxins_archived - model.toxins)/TRANSFER_FRACTION - - var/delta_temperature = (temperature_archived - model.temperature) - - var/heat_transferred = 0 - var/old_self_heat_capacity = 0 - var/heat_capacity_transferred = 0 - - if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - - var/delta_air = delta_oxygen+delta_nitrogen - if(delta_air) - var/air_heat_capacity = SPECIFIC_HEAT_AIR*delta_air - heat_transferred -= air_heat_capacity*model.temperature - heat_capacity_transferred -= air_heat_capacity - - if(delta_carbon_dioxide) - var/carbon_dioxide_heat_capacity = SPECIFIC_HEAT_CDO*delta_carbon_dioxide - heat_transferred -= carbon_dioxide_heat_capacity*model.temperature - heat_capacity_transferred -= carbon_dioxide_heat_capacity - - if(delta_toxins) - var/toxins_heat_capacity = SPECIFIC_HEAT_TOXIN*delta_toxins - heat_transferred -= toxins_heat_capacity*model.temperature - heat_capacity_transferred -= toxins_heat_capacity - - old_self_heat_capacity = heat_capacity()*group_multiplier - - if(border_multiplier) - oxygen -= delta_oxygen*border_multiplier/group_multiplier - carbon_dioxide -= delta_carbon_dioxide*border_multiplier/group_multiplier - nitrogen -= delta_nitrogen*border_multiplier/group_multiplier - toxins -= delta_toxins*border_multiplier/group_multiplier - else - oxygen -= delta_oxygen/group_multiplier - carbon_dioxide -= delta_carbon_dioxide/group_multiplier - nitrogen -= delta_nitrogen/group_multiplier - toxins -= delta_toxins/group_multiplier - - var/moved_moles = (delta_oxygen + delta_carbon_dioxide + delta_nitrogen + delta_toxins) - - if(trace_gases.len) - for(var/datum/gas/trace_gas in trace_gases) - var/delta = 0 - - delta = trace_gas.moles_archived/TRANSFER_FRACTION - - if(border_multiplier) - trace_gas.moles -= delta*border_multiplier/group_multiplier - else - trace_gas.moles -= delta/group_multiplier - - var/heat_cap_transferred = delta*trace_gas.specific_heat - heat_transferred += heat_cap_transferred*temperature_archived - heat_capacity_transferred += heat_cap_transferred - moved_moles += delta - update_values() - - if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - var/new_self_heat_capacity = old_self_heat_capacity - heat_capacity_transferred - if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY) - if(border_multiplier) - temperature = (old_self_heat_capacity*temperature - heat_capacity_transferred*border_multiplier*temperature_archived)/new_self_heat_capacity - else - temperature = (old_self_heat_capacity*temperature - heat_capacity_transferred*border_multiplier*temperature_archived)/new_self_heat_capacity - - temperature_mimic(model, model.thermal_conductivity, border_multiplier) - - if((delta_temperature > MINIMUM_TEMPERATURE_TO_MOVE) || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE) - var/delta_pressure = temperature_archived*(total_moles() + moved_moles) - model.temperature*(model.oxygen+model.carbon_dioxide+model.nitrogen+model.toxins) - return delta_pressure*R_IDEAL_GAS_EQUATION/volume - else - return 0 - - proc/check_both_then_temperature_share(datum/gas_mixture/sharer, conduction_coefficient) - var/delta_temperature = (temperature_archived - sharer.temperature_archived) - - var/self_heat_capacity = heat_capacity_archived() - var/sharer_heat_capacity = sharer.heat_capacity_archived() - - var/self_temperature_delta = 0 - var/sharer_temperature_delta = 0 - - if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) - var/heat = conduction_coefficient*delta_temperature* \ - (self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity)) - - self_temperature_delta = -heat/(self_heat_capacity*group_multiplier) - sharer_temperature_delta = heat/(sharer_heat_capacity*sharer.group_multiplier) - else - return 1 - - if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \ - && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived)) - return 0 - - if((abs(sharer_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \ - && (abs(sharer_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*sharer.temperature_archived)) - return -1 - - temperature += self_temperature_delta - sharer.temperature += sharer_temperature_delta - - return 1 - //Logic integrated from: temperature_share(sharer, conduction_coefficient) for efficiency - - proc/check_me_then_temperature_share(datum/gas_mixture/sharer, conduction_coefficient) - var/delta_temperature = (temperature_archived - sharer.temperature_archived) - - var/self_heat_capacity = heat_capacity_archived() - var/sharer_heat_capacity = sharer.heat_capacity_archived() - - var/self_temperature_delta = 0 - var/sharer_temperature_delta = 0 - - if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) - var/heat = conduction_coefficient*delta_temperature* \ - (self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity)) - - self_temperature_delta = -heat/(self_heat_capacity*group_multiplier) - sharer_temperature_delta = heat/(sharer_heat_capacity*sharer.group_multiplier) - else - return 1 - - if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \ - && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived)) - return 0 - - temperature += self_temperature_delta - sharer.temperature += sharer_temperature_delta - - return 1 - //Logic integrated from: temperature_share(sharer, conduction_coefficient) for efficiency - - proc/check_me_then_temperature_turf_share(turf/simulated/sharer, conduction_coefficient) - var/delta_temperature = (temperature_archived - sharer.temperature) - - var/self_temperature_delta = 0 - var/sharer_temperature_delta = 0 - - if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - var/self_heat_capacity = heat_capacity_archived() - - if((sharer.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) - var/heat = conduction_coefficient*delta_temperature* \ - (self_heat_capacity*sharer.heat_capacity/(self_heat_capacity+sharer.heat_capacity)) - - self_temperature_delta = -heat/(self_heat_capacity*group_multiplier) - sharer_temperature_delta = heat/sharer.heat_capacity - else - return 1 - - if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \ - && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived)) - return 0 - - temperature += self_temperature_delta - sharer.temperature += sharer_temperature_delta - - return 1 - //Logic integrated from: temperature_turf_share(sharer, conduction_coefficient) for efficiency - - proc/check_me_then_temperature_mimic(turf/model, conduction_coefficient) - var/delta_temperature = (temperature_archived - model.temperature) - var/self_temperature_delta = 0 - - if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - var/self_heat_capacity = heat_capacity_archived() - - if((model.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) - var/heat = conduction_coefficient*delta_temperature* \ - (self_heat_capacity*model.heat_capacity/(self_heat_capacity+model.heat_capacity)) - - self_temperature_delta = -heat/(self_heat_capacity*group_multiplier) - - if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \ - && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived)) - return 0 - - temperature += self_temperature_delta - - return 1 - //Logic integrated from: temperature_mimic(model, conduction_coefficient) for efficiency - - proc/temperature_share(datum/gas_mixture/sharer, conduction_coefficient) - - var/delta_temperature = (temperature_archived - sharer.temperature_archived) - if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - var/self_heat_capacity = heat_capacity_archived() - var/sharer_heat_capacity = sharer.heat_capacity_archived() - if(!group_multiplier) - message_admins("Error! The gas mixture (ref \ref[src]) has no group multiplier!") - return - - if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) - var/heat = conduction_coefficient*delta_temperature* \ - (self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity)) - - temperature -= heat/(self_heat_capacity*group_multiplier) - sharer.temperature += heat/(sharer_heat_capacity*sharer.group_multiplier) - - proc/temperature_mimic(turf/model, conduction_coefficient, border_multiplier) - var/delta_temperature = (temperature - model.temperature) - if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - var/self_heat_capacity = heat_capacity()//_archived() - if(!group_multiplier) - message_admins("Error! The gas mixture (ref \ref[src]) has no group multiplier!") - return - - if((model.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) - var/heat = conduction_coefficient*delta_temperature* \ - (self_heat_capacity*model.heat_capacity/(self_heat_capacity+model.heat_capacity)) - - if(border_multiplier) - temperature -= heat*border_multiplier/(self_heat_capacity*group_multiplier) - else - temperature -= heat/(self_heat_capacity*group_multiplier) - - proc/temperature_turf_share(turf/simulated/sharer, conduction_coefficient) - var/delta_temperature = (temperature_archived - sharer.temperature) - if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - var/self_heat_capacity = heat_capacity() - - if((sharer.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) - var/heat = conduction_coefficient*delta_temperature* \ - (self_heat_capacity*sharer.heat_capacity/(self_heat_capacity+sharer.heat_capacity)) - - temperature -= heat/(self_heat_capacity*group_multiplier) - sharer.temperature += heat/sharer.heat_capacity - - proc/compare(datum/gas_mixture/sample) - //Purpose: Compares sample to self to see if within acceptable ranges that group processing may be enabled - //Called by: Airgroups trying to rebuild - //Inputs: Gas mix to compare - //Outputs: 1 if can rebuild, 0 if not. - if(!sample) return 0 - - if((abs(oxygen-sample.oxygen) > MINIMUM_AIR_TO_SUSPEND) && \ - ((oxygen < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.oxygen) || (oxygen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.oxygen))) - return 0 - if((abs(nitrogen-sample.nitrogen) > MINIMUM_AIR_TO_SUSPEND) && \ - ((nitrogen < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.nitrogen) || (nitrogen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.nitrogen))) - return 0 - if((abs(carbon_dioxide-sample.carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && \ - ((carbon_dioxide < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide) || (oxygen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide))) - return 0 - if((abs(toxins-sample.toxins) > MINIMUM_AIR_TO_SUSPEND) && \ - ((toxins < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.toxins) || (toxins > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.toxins))) - return 0 - - if(total_moles() > MINIMUM_AIR_TO_SUSPEND) - if((abs(temperature-sample.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) && \ - ((temperature < (1-MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature) || (temperature > (1+MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature))) - //world << "temp fail [temperature] & [sample.temperature]" + else return 0 - if(sample.trace_gases.len) - for(var/datum/gas/trace_gas in sample.trace_gases) - if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND) - var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases - if(corresponding) - if((abs(trace_gas.moles - corresponding.moles) > MINIMUM_AIR_TO_SUSPEND) && \ - ((corresponding.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles) || (corresponding.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles))) - return 0 - else - return 0 + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4) + if(!locate(trace_gas.type) in sharer.trace_gases) + return 0 - if(trace_gases.len) - for(var/datum/gas/trace_gas in trace_gases) - if(trace_gas.moles > MINIMUM_AIR_TO_SUSPEND) - var/datum/gas/corresponding = locate(trace_gas.type) in sample.trace_gases - if(corresponding) - if((abs(trace_gas.moles - corresponding.moles) > MINIMUM_AIR_TO_SUSPEND) && \ - ((trace_gas.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*corresponding.moles) || (trace_gas.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*corresponding.moles))) - return 0 - else - return 0 - return 1 + if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= sharer.oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= sharer.carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= sharer.nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= sharer.toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND))) + return -1 + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4) + var/datum/gas/corresponding = locate(trace_gas.type) in sharer.trace_gases + if(corresponding) + if(trace_gas.moles_archived >= corresponding.moles_archived*MINIMUM_AIR_RATIO_TO_SUSPEND*4) + return -1 + else + return -1 + + return 1 + +/datum/gas_mixture/proc/check_turf(turf/model) + //Purpose: Used to compare the gases in an unsimulated turf with the gas in a simulated one. + //Called by: Sharing air (mimicing) with adjacent unsimulated turfs + //Inputs: Unsimulated turf + //Outputs: 1 if safe to mimic, 0 if needs to break airgroup. + + var/delta_oxygen = (oxygen_archived - model.oxygen)/TRANSFER_FRACTION + var/delta_carbon_dioxide = (carbon_dioxide_archived - model.carbon_dioxide)/TRANSFER_FRACTION + var/delta_nitrogen = (nitrogen_archived - model.nitrogen)/TRANSFER_FRACTION + var/delta_toxins = (toxins_archived - model.toxins)/TRANSFER_FRACTION + + var/delta_temperature = (temperature_archived - model.temperature) + + if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \ + || ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND))) + return 0 + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) + return 0 + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4) + return 0 + + return 1 + +/datum/gas_mixture/proc/share(datum/gas_mixture/sharer) + //Purpose: Used to transfer gas from a more pressurised tile to a less presurised tile + // (Two directional, if the other tile is more pressurised, air travels to current tile) + //Called by: Sharing air with adjacent simulated turfs + //Inputs: Air datum to share with + //Outputs: Amount of gas exchanged (Negative if lost air, positive if gained.) - proc/subtract(datum/gas_mixture/right_side) - //Purpose: Subtracts right_side from air_mixture. Used to help turfs mingle - //Called by: Pipelines ending in a break (or something) - //Inputs: Gas mix to remove - //Outputs: 1 + if(!istype(sharer)) + return - oxygen -= right_side.oxygen - carbon_dioxide -= right_side.carbon_dioxide - nitrogen -= right_side.nitrogen - toxins -= right_side.toxins + var/delta_oxygen = QUANTIZE(oxygen_archived - sharer.oxygen_archived)/TRANSFER_FRACTION + var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - sharer.carbon_dioxide_archived)/TRANSFER_FRACTION + var/delta_nitrogen = QUANTIZE(nitrogen_archived - sharer.nitrogen_archived)/TRANSFER_FRACTION + var/delta_toxins = QUANTIZE(toxins_archived - sharer.toxins_archived)/TRANSFER_FRACTION - if((trace_gases.len > 0)||(right_side.trace_gases.len > 0)) - for(var/datum/gas/trace_gas in right_side.trace_gases) - var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases - if(!corresponding) - corresponding = new trace_gas.type() - trace_gases += corresponding + var/delta_temperature = (temperature_archived - sharer.temperature_archived) - corresponding.moles -= trace_gas.moles - update_values() - return 1 \ No newline at end of file + var/old_self_heat_capacity = 0 + var/old_sharer_heat_capacity = 0 + + var/heat_self_to_sharer = 0 + var/heat_capacity_self_to_sharer = 0 + var/heat_sharer_to_self = 0 + var/heat_capacity_sharer_to_self = 0 + + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + + var/delta_air = delta_oxygen+delta_nitrogen + if(delta_air) + var/air_heat_capacity = SPECIFIC_HEAT_AIR*delta_air + if(delta_air > 0) + heat_self_to_sharer += air_heat_capacity*temperature_archived + heat_capacity_self_to_sharer += air_heat_capacity + else + heat_sharer_to_self -= air_heat_capacity*sharer.temperature_archived + heat_capacity_sharer_to_self -= air_heat_capacity + + if(delta_carbon_dioxide) + var/carbon_dioxide_heat_capacity = SPECIFIC_HEAT_CDO*delta_carbon_dioxide + if(delta_carbon_dioxide > 0) + heat_self_to_sharer += carbon_dioxide_heat_capacity*temperature_archived + heat_capacity_self_to_sharer += carbon_dioxide_heat_capacity + else + heat_sharer_to_self -= carbon_dioxide_heat_capacity*sharer.temperature_archived + heat_capacity_sharer_to_self -= carbon_dioxide_heat_capacity + + if(delta_toxins) + var/toxins_heat_capacity = SPECIFIC_HEAT_TOXIN*delta_toxins + if(delta_toxins > 0) + heat_self_to_sharer += toxins_heat_capacity*temperature_archived + heat_capacity_self_to_sharer += toxins_heat_capacity + else + heat_sharer_to_self -= toxins_heat_capacity*sharer.temperature_archived + heat_capacity_sharer_to_self -= toxins_heat_capacity + + old_self_heat_capacity = heat_capacity()*group_multiplier + old_sharer_heat_capacity = sharer.heat_capacity()*sharer.group_multiplier + + oxygen -= delta_oxygen/group_multiplier + sharer.oxygen += delta_oxygen/sharer.group_multiplier + + carbon_dioxide -= delta_carbon_dioxide/group_multiplier + sharer.carbon_dioxide += delta_carbon_dioxide/sharer.group_multiplier + + nitrogen -= delta_nitrogen/group_multiplier + sharer.nitrogen += delta_nitrogen/sharer.group_multiplier + + toxins -= delta_toxins/group_multiplier + sharer.toxins += delta_toxins/sharer.group_multiplier + + var/moved_moles = (delta_oxygen + delta_carbon_dioxide + delta_nitrogen + delta_toxins) + + var/list/trace_types_considered = list() + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + + var/datum/gas/corresponding = locate(trace_gas.type) in sharer.trace_gases + var/delta = 0 + + if(corresponding) + delta = QUANTIZE(trace_gas.moles_archived - corresponding.moles_archived)/TRANSFER_FRACTION + else + corresponding = new trace_gas.type() + sharer.trace_gases += corresponding + + delta = trace_gas.moles_archived/TRANSFER_FRACTION + + trace_gas.moles -= delta/group_multiplier + corresponding.moles += delta/sharer.group_multiplier + + if(delta) + var/individual_heat_capacity = trace_gas.specific_heat*delta + if(delta > 0) + heat_self_to_sharer += individual_heat_capacity*temperature_archived + heat_capacity_self_to_sharer += individual_heat_capacity + else + heat_sharer_to_self -= individual_heat_capacity*sharer.temperature_archived + heat_capacity_sharer_to_self -= individual_heat_capacity + + moved_moles += delta + + trace_types_considered += trace_gas.type + + + if(sharer.trace_gases.len) + for(var/datum/gas/trace_gas in sharer.trace_gases) + if(trace_gas.type in trace_types_considered) continue + else + var/datum/gas/corresponding + var/delta = 0 + + corresponding = new trace_gas.type() + trace_gases += corresponding + + delta = trace_gas.moles_archived/TRANSFER_FRACTION + + trace_gas.moles -= delta/sharer.group_multiplier + corresponding.moles += delta/group_multiplier + + //Guaranteed transfer from sharer to self + var/individual_heat_capacity = trace_gas.specific_heat*delta + heat_sharer_to_self += individual_heat_capacity*sharer.temperature_archived + heat_capacity_sharer_to_self += individual_heat_capacity + + moved_moles += -delta + update_values() + sharer.update_values() + + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + var/new_self_heat_capacity = old_self_heat_capacity + heat_capacity_sharer_to_self - heat_capacity_self_to_sharer + var/new_sharer_heat_capacity = old_sharer_heat_capacity + heat_capacity_self_to_sharer - heat_capacity_sharer_to_self + + if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY) + temperature = (old_self_heat_capacity*temperature - heat_capacity_self_to_sharer*temperature_archived + heat_capacity_sharer_to_self*sharer.temperature_archived)/new_self_heat_capacity + + if(new_sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) + sharer.temperature = (old_sharer_heat_capacity*sharer.temperature-heat_capacity_sharer_to_self*sharer.temperature_archived + heat_capacity_self_to_sharer*temperature_archived)/new_sharer_heat_capacity + + if(abs(old_sharer_heat_capacity) > MINIMUM_HEAT_CAPACITY) + if(abs(new_sharer_heat_capacity/old_sharer_heat_capacity - 1) < 0.10) // <10% change in sharer heat capacity + temperature_share(sharer, OPEN_HEAT_TRANSFER_COEFFICIENT) + + if((delta_temperature > MINIMUM_TEMPERATURE_TO_MOVE) || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE) + var/delta_pressure = temperature_archived*(total_moles() + moved_moles) - sharer.temperature_archived*(sharer.total_moles() - moved_moles) + return delta_pressure*R_IDEAL_GAS_EQUATION/volume + + else + return 0 + +/datum/gas_mixture/proc/mimic(turf/model, border_multiplier) + //Purpose: Used transfer gas from a more pressurised tile to a less presurised unsimulated tile. + //Called by: "sharing" from unsimulated to simulated turfs. + //Inputs: Unsimulated turf, Multiplier for gas transfer (optional) + //Outputs: Amount of gas exchanged + + var/delta_oxygen = QUANTIZE(oxygen_archived - model.oxygen)/TRANSFER_FRACTION + var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - model.carbon_dioxide)/TRANSFER_FRACTION + var/delta_nitrogen = QUANTIZE(nitrogen_archived - model.nitrogen)/TRANSFER_FRACTION + var/delta_toxins = QUANTIZE(toxins_archived - model.toxins)/TRANSFER_FRACTION + + var/delta_temperature = (temperature_archived - model.temperature) + + var/heat_transferred = 0 + var/old_self_heat_capacity = 0 + var/heat_capacity_transferred = 0 + + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + + var/delta_air = delta_oxygen+delta_nitrogen + if(delta_air) + var/air_heat_capacity = SPECIFIC_HEAT_AIR*delta_air + heat_transferred -= air_heat_capacity*model.temperature + heat_capacity_transferred -= air_heat_capacity + + if(delta_carbon_dioxide) + var/carbon_dioxide_heat_capacity = SPECIFIC_HEAT_CDO*delta_carbon_dioxide + heat_transferred -= carbon_dioxide_heat_capacity*model.temperature + heat_capacity_transferred -= carbon_dioxide_heat_capacity + + if(delta_toxins) + var/toxins_heat_capacity = SPECIFIC_HEAT_TOXIN*delta_toxins + heat_transferred -= toxins_heat_capacity*model.temperature + heat_capacity_transferred -= toxins_heat_capacity + + old_self_heat_capacity = heat_capacity()*group_multiplier + + if(border_multiplier) + oxygen -= delta_oxygen*border_multiplier/group_multiplier + carbon_dioxide -= delta_carbon_dioxide*border_multiplier/group_multiplier + nitrogen -= delta_nitrogen*border_multiplier/group_multiplier + toxins -= delta_toxins*border_multiplier/group_multiplier + else + oxygen -= delta_oxygen/group_multiplier + carbon_dioxide -= delta_carbon_dioxide/group_multiplier + nitrogen -= delta_nitrogen/group_multiplier + toxins -= delta_toxins/group_multiplier + + var/moved_moles = (delta_oxygen + delta_carbon_dioxide + delta_nitrogen + delta_toxins) + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + var/delta = 0 + + delta = trace_gas.moles_archived/TRANSFER_FRACTION + + if(border_multiplier) + trace_gas.moles -= delta*border_multiplier/group_multiplier + else + trace_gas.moles -= delta/group_multiplier + + var/heat_cap_transferred = delta*trace_gas.specific_heat + heat_transferred += heat_cap_transferred*temperature_archived + heat_capacity_transferred += heat_cap_transferred + moved_moles += delta + update_values() + + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + var/new_self_heat_capacity = old_self_heat_capacity - heat_capacity_transferred + if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY) + if(border_multiplier) + temperature = (old_self_heat_capacity*temperature - heat_capacity_transferred*border_multiplier*temperature_archived)/new_self_heat_capacity + else + temperature = (old_self_heat_capacity*temperature - heat_capacity_transferred*border_multiplier*temperature_archived)/new_self_heat_capacity + + temperature_mimic(model, model.thermal_conductivity, border_multiplier) + + if((delta_temperature > MINIMUM_TEMPERATURE_TO_MOVE) || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE) + var/delta_pressure = temperature_archived*(total_moles() + moved_moles) - model.temperature*(model.oxygen+model.carbon_dioxide+model.nitrogen+model.toxins) + return delta_pressure*R_IDEAL_GAS_EQUATION/volume + else + return 0 + +/datum/gas_mixture/proc/check_both_then_temperature_share(datum/gas_mixture/sharer, conduction_coefficient) + var/delta_temperature = (temperature_archived - sharer.temperature_archived) + + var/self_heat_capacity = heat_capacity_archived() + var/sharer_heat_capacity = sharer.heat_capacity_archived() + + var/self_temperature_delta = 0 + var/sharer_temperature_delta = 0 + + if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) + var/heat = conduction_coefficient*delta_temperature* \ + (self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity)) + + self_temperature_delta = -heat/(self_heat_capacity*group_multiplier) + sharer_temperature_delta = heat/(sharer_heat_capacity*sharer.group_multiplier) + else + return 1 + + if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \ + && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived)) + return 0 + + if((abs(sharer_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \ + && (abs(sharer_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*sharer.temperature_archived)) + return -1 + + temperature += self_temperature_delta + sharer.temperature += sharer_temperature_delta + + return 1 + //Logic integrated from: temperature_share(sharer, conduction_coefficient) for efficiency + +/datum/gas_mixture/proc/check_me_then_temperature_share(datum/gas_mixture/sharer, conduction_coefficient) + var/delta_temperature = (temperature_archived - sharer.temperature_archived) + + var/self_heat_capacity = heat_capacity_archived() + var/sharer_heat_capacity = sharer.heat_capacity_archived() + + var/self_temperature_delta = 0 + var/sharer_temperature_delta = 0 + + if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) + var/heat = conduction_coefficient*delta_temperature* \ + (self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity)) + + self_temperature_delta = -heat/(self_heat_capacity*group_multiplier) + sharer_temperature_delta = heat/(sharer_heat_capacity*sharer.group_multiplier) + else + return 1 + + if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \ + && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived)) + return 0 + + temperature += self_temperature_delta + sharer.temperature += sharer_temperature_delta + + return 1 + //Logic integrated from: temperature_share(sharer, conduction_coefficient) for efficiency + +/datum/gas_mixture/proc/check_me_then_temperature_turf_share(turf/simulated/sharer, conduction_coefficient) + var/delta_temperature = (temperature_archived - sharer.temperature) + + var/self_temperature_delta = 0 + var/sharer_temperature_delta = 0 + + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + var/self_heat_capacity = heat_capacity_archived() + + if((sharer.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) + var/heat = conduction_coefficient*delta_temperature* \ + (self_heat_capacity*sharer.heat_capacity/(self_heat_capacity+sharer.heat_capacity)) + + self_temperature_delta = -heat/(self_heat_capacity*group_multiplier) + sharer_temperature_delta = heat/sharer.heat_capacity + else + return 1 + + if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \ + && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived)) + return 0 + + temperature += self_temperature_delta + sharer.temperature += sharer_temperature_delta + + return 1 + //Logic integrated from: temperature_turf_share(sharer, conduction_coefficient) for efficiency + +/datum/gas_mixture/proc/check_me_then_temperature_mimic(turf/model, conduction_coefficient) + var/delta_temperature = (temperature_archived - model.temperature) + var/self_temperature_delta = 0 + + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + var/self_heat_capacity = heat_capacity_archived() + + if((model.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) + var/heat = conduction_coefficient*delta_temperature* \ + (self_heat_capacity*model.heat_capacity/(self_heat_capacity+model.heat_capacity)) + + self_temperature_delta = -heat/(self_heat_capacity*group_multiplier) + + if((abs(self_temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) \ + && (abs(self_temperature_delta) > MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND*temperature_archived)) + return 0 + + temperature += self_temperature_delta + + return 1 + //Logic integrated from: temperature_mimic(model, conduction_coefficient) for efficiency + +/datum/gas_mixture/proc/temperature_share(datum/gas_mixture/sharer, conduction_coefficient) + var/delta_temperature = (temperature_archived - sharer.temperature_archived) + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + var/self_heat_capacity = heat_capacity_archived() + var/sharer_heat_capacity = sharer.heat_capacity_archived() + if(!group_multiplier) + message_admins("Error! The gas mixture (ref \ref[src]) has no group multiplier!") + return + + if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) + var/heat = conduction_coefficient*delta_temperature* \ + (self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity)) + + temperature -= heat/(self_heat_capacity*group_multiplier) + sharer.temperature += heat/(sharer_heat_capacity*sharer.group_multiplier) + +/datum/gas_mixture/proc/temperature_mimic(turf/model, conduction_coefficient, border_multiplier) + var/delta_temperature = (temperature - model.temperature) + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + var/self_heat_capacity = heat_capacity()//_archived() + if(!group_multiplier) + message_admins("Error! The gas mixture (ref \ref[src]) has no group multiplier!") + return + + if((model.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) + var/heat = conduction_coefficient*delta_temperature* \ + (self_heat_capacity*model.heat_capacity/(self_heat_capacity+model.heat_capacity)) + + if(border_multiplier) + temperature -= heat*border_multiplier/(self_heat_capacity*group_multiplier) + else + temperature -= heat/(self_heat_capacity*group_multiplier) + +/datum/gas_mixture/proc/temperature_turf_share(turf/simulated/sharer, conduction_coefficient) + var/delta_temperature = (temperature_archived - sharer.temperature) + if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + var/self_heat_capacity = heat_capacity() + + if((sharer.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY)) + var/heat = conduction_coefficient*delta_temperature* \ + (self_heat_capacity*sharer.heat_capacity/(self_heat_capacity+sharer.heat_capacity)) + + temperature -= heat/(self_heat_capacity*group_multiplier) + sharer.temperature += heat/sharer.heat_capacity + +/datum/gas_mixture/proc/compare(datum/gas_mixture/sample) + //Purpose: Compares sample to self to see if within acceptable ranges that group processing may be enabled + //Called by: Airgroups trying to rebuild + //Inputs: Gas mix to compare + //Outputs: 1 if can rebuild, 0 if not. + if(!sample) return 0 + + if((abs(oxygen-sample.oxygen) > MINIMUM_AIR_TO_SUSPEND) && \ + ((oxygen < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.oxygen) || (oxygen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.oxygen))) + return 0 + if((abs(nitrogen-sample.nitrogen) > MINIMUM_AIR_TO_SUSPEND) && \ + ((nitrogen < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.nitrogen) || (nitrogen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.nitrogen))) + return 0 + if((abs(carbon_dioxide-sample.carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && \ + ((carbon_dioxide < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide) || (oxygen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide))) + return 0 + if((abs(toxins-sample.toxins) > MINIMUM_AIR_TO_SUSPEND) && \ + ((toxins < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.toxins) || (toxins > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.toxins))) + return 0 + + if(total_moles() > MINIMUM_AIR_TO_SUSPEND) + if((abs(temperature-sample.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) && \ + ((temperature < (1-MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature) || (temperature > (1+MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature))) + //world << "temp fail [temperature] & [sample.temperature]" + return 0 + + if(sample.trace_gases.len) + for(var/datum/gas/trace_gas in sample.trace_gases) + if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND) + var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases + if(corresponding) + if((abs(trace_gas.moles - corresponding.moles) > MINIMUM_AIR_TO_SUSPEND) && \ + ((corresponding.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles) || (corresponding.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles))) + return 0 + else + return 0 + + if(trace_gases.len) + for(var/datum/gas/trace_gas in trace_gases) + if(trace_gas.moles > MINIMUM_AIR_TO_SUSPEND) + var/datum/gas/corresponding = locate(trace_gas.type) in sample.trace_gases + if(corresponding) + if((abs(trace_gas.moles - corresponding.moles) > MINIMUM_AIR_TO_SUSPEND) && \ + ((trace_gas.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*corresponding.moles) || (trace_gas.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*corresponding.moles))) + return 0 + else + return 0 + return 1 + +/datum/gas_mixture/proc/subtract(datum/gas_mixture/right_side) + //Purpose: Subtracts right_side from air_mixture. Used to help turfs mingle + //Called by: Pipelines ending in a break (or something) + //Inputs: Gas mix to remove + //Outputs: 1 + + oxygen -= right_side.oxygen + carbon_dioxide -= right_side.carbon_dioxide + nitrogen -= right_side.nitrogen + toxins -= right_side.toxins + + if((trace_gases.len > 0)||(right_side.trace_gases.len > 0)) + for(var/datum/gas/trace_gas in right_side.trace_gases) + var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases + if(!corresponding) + corresponding = new trace_gas.type() + trace_gases += corresponding + + corresponding.moles -= trace_gas.moles + update_values() + return 1 \ No newline at end of file diff --git a/code/ZAS/FEA_system.dm b/code/ZAS/FEA_system.dm index 94b7c5cf6d1..c2a33ad99db 100644 --- a/code/ZAS/FEA_system.dm +++ b/code/ZAS/FEA_system.dm @@ -64,49 +64,46 @@ atom/proc/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) return (!density || !height || air_group) -turf - CanPass(atom/movable/mover, turf/target, height=1.5,air_group=0) - if(!target) return 0 +/turf/CanPass(atom/movable/mover, turf/target, height=1.5,air_group=0) + if(!target) return 0 - if(istype(mover)) // turf/Enter(...) will perform more advanced checks - return !density + if(istype(mover)) // turf/Enter(...) will perform more advanced checks + return !density - else // Now, doing more detailed checks for air movement and air group formation - if(target.blocks_air||blocks_air) + else // Now, doing more detailed checks for air movement and air group formation + if(target.blocks_air||blocks_air) + return 0 + + for(var/obj/obstacle in src) + if(!obstacle.CanPass(mover, target, height, air_group)) return 0 - - for(var/obj/obstacle in src) - if(!obstacle.CanPass(mover, target, height, air_group)) + if(target != src) + for(var/obj/obstacle in target) + if(!obstacle.CanPass(mover, src, height, air_group)) return 0 - if(target != src) - for(var/obj/obstacle in target) - if(!obstacle.CanPass(mover, src, height, air_group)) - return 0 - return 1 + return 1 -var/global/datum/controller/air_system/air_master +var/datum/controller/air_system/air_master -datum - controller - air_system - //Geoemetry lists - var/list/turfs_with_connections = list() - var/list/active_hotspots = list() +/datum/controller/air_system/ + //Geoemetry lists + var/list/turfs_with_connections = list() + var/list/active_hotspots = list() - //Special functions lists - var/list/tiles_to_reconsider_zones = list() + //Special functions lists + var/list/tiles_to_reconsider_zones = list() - //Geometry updates lists - var/list/tiles_to_update = list() - var/list/connections_to_check = list() + //Geometry updates lists + var/list/tiles_to_update = list() + var/list/connections_to_check = list() - var/current_cycle = 0 - var/update_delay = 5 //How long between check should it try to process atmos again. - var/failed_ticks = 0 //How many ticks have runtimed? + var/current_cycle = 0 + var/update_delay = 5 //How long between check should it try to process atmos again. + var/failed_ticks = 0 //How many ticks have runtimed? - var/tick_progress = 0 + var/tick_progress = 0 /* process() @@ -122,97 +119,103 @@ datum */ - proc/setup() - //Purpose: Call this at the start to setup air groups geometry - // (Warning: Very processor intensive but only must be done once per round) - //Called by: Gameticker/Master controller - //Inputs: None. - //Outputs: None. +/datum/controller/air_system/proc/setup() + //Purpose: Call this at the start to setup air groups geometry + // (Warning: Very processor intensive but only must be done once per round) + //Called by: Gameticker/Master controller + //Inputs: None. + //Outputs: None. - set background = 1 - world << "\red \b Processing Geometry..." - sleep(-1) + set background = 1 + world << "\red \b Processing Geometry..." + sleep(-1) - var/start_time = world.timeofday + var/start_time = world.timeofday - var/simulated_turf_count = 0 + var/simulated_turf_count = 0 - for(var/turf/simulated/S in world) - simulated_turf_count++ - if(!S.zone && !S.blocks_air) - if(S.CanPass(null, S, 0, 0)) - new/zone(S) + for(var/turf/simulated/S in world) + simulated_turf_count++ + if(!S.zone && !S.blocks_air) + if(S.CanPass(null, S, 0, 0)) + new/zone(S) - for(var/turf/simulated/S in world) - S.update_air_properties() + for(var/turf/simulated/S in world) + S.update_air_properties() - world << {"Geometry initialized in [round(0.1*(world.timeofday-start_time),0.1)] seconds. - Total Simulated Turfs: [simulated_turf_count] - Total Zones: [zones.len] - Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_count]"} - /* - spawn start() + world << {"Geometry initialized in [round(0.1*(world.timeofday-start_time),0.1)] seconds. +Total Simulated Turfs: [simulated_turf_count] +Total Zones: [zones.len] +Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_count]"} + /* + spawn start() - proc/start() - //Purpose: This is kicked off by the master controller, and controls the processing of all atmosphere. - //Called by: Master controller - //Inputs: None. - //Outputs: None. +/datum/controller/air_system/proc/start() + //Purpose: This is kicked off by the master controller, and controls the processing of all atmosphere. + //Called by: Master controller + //Inputs: None. + //Outputs: None. - set background = 1 + set background = 1 - while(1) - if(!kill_air) - current_cycle++ - var/success = tick() //Changed so that a runtime does not crash the ticker. - if(!success) //Runtimed. - failed_ticks++ - if(failed_ticks > 20) - world << "ERROR IN ATMOS TICKER. Killing air simulation!" - kill_air = 1 - sleep(max(5,update_delay*tick_multiplier)) - */ + while(1) + if(!kill_air) + current_cycle++ + var/success = tick() //Changed so that a runtime does not crash the ticker. + if(!success) //Runtimed. + failed_ticks++ + if(failed_ticks > 20) + world << "ERROR IN ATMOS TICKER. Killing air simulation!" + kill_air = 1 + sleep(max(5,update_delay*tick_multiplier)) + */ - proc/tick() - . = 1 //Set the default return value, for runtime detection. +/datum/controller/air_system/proc/tick() + . = 1 //Set the default return value, for runtime detection. - tick_progress = "update_air_properties" - if(tiles_to_update.len) //If there are tiles to update, do so. - for(var/turf/simulated/T in tiles_to_update) - if(. && T && !T.update_air_properties()) - . = 0 //If a runtime occured, make sure we can sense it. - //message_admins("ZASALERT: Unable run turf/simualted/update_air_properties()") - tiles_to_update = list() + tick_progress = "update_air_properties" + if(tiles_to_update.len) //If there are tiles to update, do so. + for(var/turf/simulated/T in tiles_to_update) + if(. && T && !T.update_air_properties()) + . = 0 //If a runtime occured, make sure we can sense it. + //message_admins("ZASALERT: Unable run turf/simualted/update_air_properties()") + if(.) + tiles_to_update = list() - //Check sanity on connection objects. - tick_progress = "connections_to_check" - if(connections_to_check.len) - for(var/connection/C in connections_to_check) - C.CheckPassSanity() - connections_to_check = list() + //Check sanity on connection objects. + if(.) + tick_progress = "connections_to_check" + if(connections_to_check.len) + for(var/connection/C in connections_to_check) + C.CheckPassSanity() + connections_to_check = list() - //Ensure tiles still have zones. - tick_progress = "tiles_to_reconsider_zones" - if(tiles_to_reconsider_zones.len) - for(var/turf/simulated/T in tiles_to_reconsider_zones) - if(!T.zone) - new /zone(T) - tiles_to_reconsider_zones = list() + //Ensure tiles still have zones. + if(.) + tick_progress = "tiles_to_reconsider_zones" + if(tiles_to_reconsider_zones.len) + for(var/turf/simulated/T in tiles_to_reconsider_zones) + if(!T.zone) + new /zone(T) + tiles_to_reconsider_zones = list() - //Process zones. - tick_progress = "zone/process()" - for(var/zone/Z in zones) - if(Z.last_update < current_cycle) - var/output = Z.process() - if(Z) - Z.last_update = current_cycle - if(. && Z && !output) - . = 0 - //Process fires. - tick_progress = "active_hotspots (fire)" - for(var/obj/fire/F in active_hotspots) - if(. && F && !F.process()) - . = 0 + //Process zones. + if(.) + tick_progress = "zone/process()" + for(var/zone/Z in zones) + if(Z.last_update < current_cycle) + var/output = Z.process() + if(Z) + Z.last_update = current_cycle + if(. && Z && !output) + . = 0 + //Process fires. + if(.) + tick_progress = "active_hotspots (fire)" + for(var/obj/fire/F in active_hotspots) + if(. && F && !F.process()) + . = 0 - tick_progress = "success" \ No newline at end of file + if(.) + tick_progress = "success" \ No newline at end of file diff --git a/code/ZAS/Fire.dm b/code/ZAS/Fire.dm index 023d60acf08..0a9240faee3 100644 --- a/code/ZAS/Fire.dm +++ b/code/ZAS/Fire.dm @@ -30,7 +30,7 @@ turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh) var/igniting = 0 var/obj/effect/decal/cleanable/liquid_fuel/liquid = locate() in src - + if(air_contents.check_combustability(liquid)) igniting = 1 @@ -43,132 +43,120 @@ turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh) return igniting -obj - fire - //Icon for fire on turfs. +/obj/fire + //Icon for fire on turfs. - anchored = 1 - mouse_opacity = 0 + anchored = 1 + mouse_opacity = 0 - //luminosity = 3 + //luminosity = 3 - icon = 'fire.dmi' + icon = 'fire.dmi' + icon_state = "1" + + layer = TURF_LAYER + + var/firelevel = 10000 //Calculated by gas_mixture.calculate_firelevel() + +/obj/fire/process() + . = 1 + + //get location and check if it is in a proper ZAS zone + var/turf/simulated/floor/S = loc + if(!S.zone) + del src + + if(!istype(S)) + del src + + var/datum/gas_mixture/air_contents = S.return_air() + //get liquid fuels on the ground. + var/obj/effect/decal/cleanable/liquid_fuel/liquid = locate() in S + //and the volatile stuff from the air + //var/datum/gas/volatile_fuel/fuel = locate() in air_contents.trace_gases + + //check if there is something to combust + if(!air_contents.check_combustability(liquid)) + del src + + //get a firelevel and set the icon + firelevel = air_contents.calculate_firelevel(liquid) + + if(firelevel > 6) + icon_state = "3" + SetLuminosity(7) + else if(firelevel > 2.5) + icon_state = "2" + SetLuminosity(5) + else icon_state = "1" + SetLuminosity(3) - layer = TURF_LAYER + //im not sure how to implement a version that works for every creature so for now monkeys are firesafe + for(var/mob/living/carbon/human/M in loc) + M.FireBurn(firelevel, air_contents.temperature, air_contents.return_pressure() ) //Burn the humans! - var - firelevel = 10000 //Calculated by gas_mixture.calculate_firelevel() - process() - . = 1 - - //get location and check if it is in a proper ZAS zone - var/turf/simulated/floor/S = loc - if(!S.zone) - del src - - if(!istype(S)) - del src - - var/datum/gas_mixture/air_contents = S.return_air() - //get liquid fuels on the ground. - var/obj/effect/decal/cleanable/liquid_fuel/liquid = locate() in S - //and the volatile stuff from the air - var/datum/gas/volatile_fuel/fuel = locate() in air_contents.trace_gases - - //since the air is processed in fractions, we need to make sure not to have any minuscle residue or - //the amount of moles might get to low for some functions to catch them and thus result in wonky behaviour - if(air_contents.oxygen < 0.001) - air_contents.oxygen = 0 - if(air_contents.toxins < 0.001) - air_contents.toxins = 0 - if(fuel) - if(fuel.moles < 0.001) - air_contents.trace_gases.Remove(fuel) - - //check if there is something to combust - if(!air_contents.check_combustability(liquid)) - del src - - //get a firelevel and set the icon - firelevel = air_contents.calculate_firelevel(liquid) - - if(firelevel > 6) - icon_state = "3" - SetLuminosity(7) - else if(firelevel > 2.5) - icon_state = "2" - SetLuminosity(5) - else - icon_state = "1" - SetLuminosity(3) - - //im not sure how to implement a version that works for every creature so for now monkeys are firesafe - for(var/mob/living/carbon/human/M in loc) - M.FireBurn(firelevel, air_contents.temperature, air_contents.return_pressure() ) //Burn the humans! + //spread! + for(var/direction in cardinal) + if(S.air_check_directions&direction) //Grab all valid bordering tiles - - //spread! - for(var/direction in cardinal) - if(S.air_check_directions&direction) //Grab all valid bordering tiles + var/turf/simulated/enemy_tile = get_step(S, direction) - var/turf/simulated/enemy_tile = get_step(S, direction) + if(istype(enemy_tile)) + //If extinguisher mist passed over the turf it's trying to spread to, don't spread and + //reduce firelevel. + if(enemy_tile.fire_protection > world.time-30) + firelevel -= 1.5 + continue - if(istype(enemy_tile)) - //If extinguisher mist passed over the turf it's trying to spread to, don't spread and - //reduce firelevel. - if(enemy_tile.fire_protection > world.time-30) - firelevel -= 1.5 - continue + //Spread the fire. + if(!(locate(/obj/fire) in enemy_tile)) + if( prob( 50 + 50 * (firelevel/vsc.fire_firelevel_multiplier) ) && S.CanPass(null, enemy_tile, 0,0) && enemy_tile.CanPass(null, S, 0,0)) + new/obj/fire(enemy_tile,firelevel) + + //seperate part of the present gas + //this is done to prevent the fire burning all gases in a single pass + var/datum/gas_mixture/flow = air_contents.remove_ratio(vsc.fire_consuption_rate) - //Spread the fire. - if(!(locate(/obj/fire) in enemy_tile)) - if( prob( 50 + 50 * (firelevel/vsc.fire_firelevel_multiplier) ) && S.CanPass(null, enemy_tile, 0,0) && enemy_tile.CanPass(null, S, 0,0)) - new/obj/fire(enemy_tile,firelevel) - - //seperate part of the present gas - //this is done to prevent the fire burning all gases in a single pass - var/datum/gas_mixture/flow = air_contents.remove_ratio(vsc.fire_consuption_rate) - ///////////////////////////////// FLOW HAS BEEN CREATED /// DONT DELETE THE FIRE UNTIL IT IS MERGED BACK OR YOU WILL DELETE AIR /////////////////////////////////////////////// - - if(flow) - if(flow.check_combustability(liquid)) - //Ensure flow temperature is higher than minimum fire temperatures. - //this creates some energy ex nihilo but is necessary to get a fire started - //lets just pretend this energy comes from the ignition source and dont mention this again - //flow.temperature = max(PLASMA_MINIMUM_BURN_TEMPERATURE+0.1,flow.temperature) - - //burn baby burn! - flow.zburn(liquid,1) - - //merge the air back - S.assume_air(flow) + + if(flow) + if(flow.check_combustability(liquid)) + //Ensure flow temperature is higher than minimum fire temperatures. + //this creates some energy ex nihilo but is necessary to get a fire started + //lets just pretend this energy comes from the ignition source and dont mention this again + //flow.temperature = max(PLASMA_MINIMUM_BURN_TEMPERATURE+0.1,flow.temperature) + + //burn baby burn! + flow.zburn(liquid,1) + + //merge the air back + S.assume_air(flow) ///////////////////////////////// FLOW HAS BEEN REMERGED /// feel free to delete the fire again from here on ////////////////////////////////////////////////////////////////// - - New(newLoc,fl) - ..() - if(!istype(loc, /turf)) - del src +/obj/fire/New(newLoc,fl) + ..() - dir = pick(cardinal) - SetLuminosity(3) - firelevel = fl - air_master.active_hotspots.Add(src) + if(!istype(loc, /turf)) + del src + + dir = pick(cardinal) + SetLuminosity(3) + firelevel = fl + air_master.active_hotspots.Add(src) - Del() - if (istype(loc, /turf/simulated)) - SetLuminosity(0) +/obj/fire/Del() + if (istype(loc, /turf/simulated)) + SetLuminosity(0) - loc = null - air_master.active_hotspots.Remove(src) + loc = null + air_master.active_hotspots.Remove(src) - ..() + ..() @@ -180,13 +168,13 @@ turf/simulated/apply_fire_protection() datum/gas_mixture/proc/zburn(obj/effect/decal/cleanable/liquid_fuel/liquid,force_burn) var/value = 0 - + if((temperature > PLASMA_MINIMUM_BURN_TEMPERATURE || force_burn) && check_combustability(liquid) ) - var/total_fuel = 0 + var/total_fuel = 0 var/datum/gas/volatile_fuel/fuel = locate() in trace_gases total_fuel += toxins - + if(fuel) //Volatile Fuel total_fuel += fuel.moles @@ -207,7 +195,7 @@ datum/gas_mixture/proc/zburn(obj/effect/decal/cleanable/liquid_fuel/liquid,force //determine the amount of oxygen used var/total_oxygen = min(oxygen, 2 * total_fuel) - + //determine the amount of fuel actually used var/used_fuel_ratio = min(oxygen / 2 , total_fuel) / total_fuel total_fuel = total_fuel * used_fuel_ratio @@ -234,31 +222,31 @@ datum/gas_mixture/proc/zburn(obj/effect/decal/cleanable/liquid_fuel/liquid,force //calculate the energy produced by the reaction and then set the new temperature of the mix temperature = (starting_energy + vsc.fire_fuel_energy_release * total_fuel) / heat_capacity() - + update_values() value = total_reactants * used_reactants_ratio return value datum/gas_mixture/proc/check_combustability(obj/effect/decal/cleanable/liquid_fuel/liquid) //this check comes up very often and is thus centralized here to ease adding stuff - - var/datum/gas/volatile_fuel/fuel = locate() in trace_gases + + var/datum/gas/volatile_fuel/fuel = locate() in trace_gases var/value = 0 - - if(oxygen && (toxins || fuel || liquid)) + + if(oxygen > 0.01 && (toxins > 0.01 || (fuel && fuel.moles > 0.01) || liquid)) value = 1 - + return value datum/gas_mixture/proc/calculate_firelevel(obj/effect/decal/cleanable/liquid_fuel/liquid) //Calculates the firelevel based on one equation instead of having to do this multiple times in different areas. - + var/datum/gas/volatile_fuel/fuel = locate() in trace_gases var/total_fuel = 0 var/firelevel = 0 - + if(check_combustability(liquid)) - + total_fuel += toxins if(liquid) @@ -268,16 +256,16 @@ datum/gas_mixture/proc/calculate_firelevel(obj/effect/decal/cleanable/liquid_fue total_fuel += fuel.moles var/total_combustables = (total_fuel + oxygen) - + if(total_fuel > 0 && oxygen > 0) - + //slows down the burning when the concentration of the reactants is low var/dampening_multiplier = total_combustables / (total_combustables + nitrogen + carbon_dioxide) //calculates how close the mixture of the reactants is to the optimum var/mix_multiplier = 1 / (1 + (5 * ((oxygen / total_combustables) ^2))) //toss everything together firelevel = vsc.fire_firelevel_multiplier * mix_multiplier * dampening_multiplier - + return max( 0, firelevel) diff --git a/code/ZAS/Plasma.dm b/code/ZAS/Plasma.dm index 3196d93db92..9f0e95f6617 100644 --- a/code/ZAS/Plasma.dm +++ b/code/ZAS/Plasma.dm @@ -1,61 +1,61 @@ var/image/contamination_overlay = image('icons/effects/contamination.dmi') -pl_control/var - PLASMA_DMG = 3 - PLASMA_DMG_NAME = "Plasma Damage Amount" - PLASMA_DMG_DESC = "Self Descriptive" +/pl_control + var/PLASMA_DMG = 3 + var/PLASMA_DMG_NAME = "Plasma Damage Amount" + var/PLASMA_DMG_DESC = "Self Descriptive" - CLOTH_CONTAMINATION = 1 - CLOTH_CONTAMINATION_NAME = "Cloth Contamination" - CLOTH_CONTAMINATION_DESC = "If this is on, plasma does damage by getting into cloth." + var/CLOTH_CONTAMINATION = 1 + var/CLOTH_CONTAMINATION_NAME = "Cloth Contamination" + var/CLOTH_CONTAMINATION_DESC = "If this is on, plasma does damage by getting into cloth." - PLASMAGUARD_ONLY = 0 - PLASMAGUARD_ONLY_NAME = "\"PlasmaGuard Only\"" - PLASMAGUARD_ONLY_DESC = "If this is on, only biosuits and spacesuits protect against contamination and ill effects." + var/PLASMAGUARD_ONLY = 0 + var/PLASMAGUARD_ONLY_NAME = "\"PlasmaGuard Only\"" + var/PLASMAGUARD_ONLY_DESC = "If this is on, only biosuits and spacesuits protect against contamination and ill effects." - GENETIC_CORRUPTION = 0 - GENETIC_CORRUPTION_NAME = "Genetic Corruption Chance" - GENETIC_CORRUPTION_DESC = "Chance of genetic corruption as well as toxic damage, X in 10,000." + var/GENETIC_CORRUPTION = 0 + var/GENETIC_CORRUPTION_NAME = "Genetic Corruption Chance" + var/GENETIC_CORRUPTION_DESC = "Chance of genetic corruption as well as toxic damage, X in 10,000." - SKIN_BURNS = 0 - SKIN_BURNS_DESC = "Plasma has an effect similar to mustard gas on the un-suited." - SKIN_BURNS_NAME = "Skin Burns" + var/SKIN_BURNS = 0 + var/SKIN_BURNS_DESC = "Plasma has an effect similar to mustard gas on the un-suited." + var/SKIN_BURNS_NAME = "Skin Burns" - EYE_BURNS = 1 - EYE_BURNS_NAME = "Eye Burns" - EYE_BURNS_DESC = "Plasma burns the eyes of anyone not wearing eye protection." + var/EYE_BURNS = 1 + var/EYE_BURNS_NAME = "Eye Burns" + var/EYE_BURNS_DESC = "Plasma burns the eyes of anyone not wearing eye protection." - CONTAMINATION_LOSS = 0.02 - CONTAMINATION_LOSS_NAME = "Contamination Loss" - CONTAMINATION_LOSS_DESC = "How much toxin damage is dealt from contaminated clothing" //Per tick? ASK ARYN + var/CONTAMINATION_LOSS = 0.02 + var/CONTAMINATION_LOSS_NAME = "Contamination Loss" + var/CONTAMINATION_LOSS_DESC = "How much toxin damage is dealt from contaminated clothing" //Per tick? ASK ARYN - PLASMA_HALLUCINATION = 0 - PLASMA_HALLUCINATION_NAME = "Plasma Hallucination" - PLASMA_HALLUCINATION_DESC = "Does being in plasma cause you to hallucinate?" + var/PLASMA_HALLUCINATION = 0 + var/PLASMA_HALLUCINATION_NAME = "Plasma Hallucination" + var/PLASMA_HALLUCINATION_DESC = "Does being in plasma cause you to hallucinate?" - N2O_HALLUCINATION = 1 - N2O_HALLUCINATION_NAME = "N2O Hallucination" - N2O_HALLUCINATION_DESC = "Does being in sleeping gas cause you to hallucinate?" + var/N2O_HALLUCINATION = 1 + var/N2O_HALLUCINATION_NAME = "N2O Hallucination" + var/N2O_HALLUCINATION_DESC = "Does being in sleeping gas cause you to hallucinate?" obj/var/contaminated = 0 -obj/item/proc - can_contaminate() - //Clothing and backpacks can be contaminated. - if(flags & PLASMAGUARD) return 0 - else if(istype(src,/obj/item/weapon/storage/backpack)) return 0 //Cannot be washed :( - else if(istype(src,/obj/item/clothing)) return 1 - contaminate() - //Do a contamination overlay? Temporary measure to keep contamination less deadly than it was. - if(!contaminated) - contaminated = 1 - overlays += contamination_overlay +/obj/item/proc/can_contaminate() + //Clothing and backpacks can be contaminated. + if(flags & PLASMAGUARD) return 0 + else if(istype(src,/obj/item/weapon/storage/backpack)) return 0 //Cannot be washed :( + else if(istype(src,/obj/item/clothing)) return 1 - decontaminate() - contaminated = 0 - overlays -= contamination_overlay +/obj/item/proc/contaminate() + //Do a contamination overlay? Temporary measure to keep contamination less deadly than it was. + if(!contaminated) + contaminated = 1 + overlays += contamination_overlay + +/obj/item/proc/decontaminate() + contaminated = 0 + overlays -= contamination_overlay /mob/proc/contaminate() diff --git a/code/ZAS/Variable Settings.dm b/code/ZAS/Variable Settings.dm index dd22765e99c..743eadd3178 100644 --- a/code/ZAS/Variable Settings.dm +++ b/code/ZAS/Variable Settings.dm @@ -1,322 +1,332 @@ var/global/vs_control/vsc = new -vs_control/var - fire_consuption_rate = 0.25 - fire_consuption_rate_NAME = "Fire - Air Consumption Ratio" - fire_consuption_rate_DESC = "Ratio of air removed and combusted per tick." +/vs_control + var/fire_consuption_rate = 0.25 + var/fire_consuption_rate_NAME = "Fire - Air Consumption Ratio" + var/fire_consuption_rate_DESC = "Ratio of air removed and combusted per tick." - fire_firelevel_multiplier = 25 - fire_firelevel_multiplier_NAME = "Fire - Firelevel Constant" - fire_firelevel_multiplier_DESC = "Multiplied by the equation for firelevel, affects mainly the extingiushing of fires." + var/fire_firelevel_multiplier = 25 + 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." - fire_fuel_energy_release = 397000 - fire_fuel_energy_release_NAME = "Fire - Fuel energy release" - fire_fuel_energy_release_DESC = "The energy in joule released when burning one mol of a burnable substance" - - - airflow_lightest_pressure = 20 - airflow_lightest_pressure_NAME = "Airflow - Small Movement Threshold %" - airflow_lightest_pressure_DESC = "Percent of 1 Atm. at which items with the small weight classes will move." - - airflow_light_pressure = 35 - airflow_light_pressure_NAME = "Airflow - Medium Movement Threshold %" - airflow_light_pressure_DESC = "Percent of 1 Atm. at which items with the medium weight classes will move." - - airflow_medium_pressure = 50 - airflow_medium_pressure_NAME = "Airflow - Heavy Movement Threshold %" - airflow_medium_pressure_DESC = "Percent of 1 Atm. at which items with the largest weight classes will move." - - airflow_heavy_pressure = 65 - airflow_heavy_pressure_NAME = "Airflow - Mob Movement Threshold %" - airflow_heavy_pressure_DESC = "Percent of 1 Atm. at which mobs will move." - - airflow_dense_pressure = 85 - airflow_dense_pressure_NAME = "Airflow - Dense Movement Threshold %" - airflow_dense_pressure_DESC = "Percent of 1 Atm. at which items with canisters and closets will move." - - airflow_stun_pressure = 60 - airflow_stun_pressure_NAME = "Airflow - Mob Stunning Threshold %" - airflow_stun_pressure_DESC = "Percent of 1 Atm. at which mobs will be stunned by airflow." - - airflow_stun_cooldown = 60 - airflow_stun_cooldown_NAME = "Aiflow Stunning - Cooldown" - airflow_stun_cooldown_DESC = "How long, in tenths of a second, to wait before stunning them again." - - airflow_stun = 1 - airflow_stun_NAME = "Airflow Impact - Stunning" - airflow_stun_DESC = "How much a mob is stunned when hit by an object." - - airflow_damage = 2 - airflow_damage_NAME = "Airflow Impact - Damage" - airflow_damage_DESC = "Damage from airflow impacts." - - airflow_speed_decay = 1.5 - airflow_speed_decay_NAME = "Airflow Speed Decay" - airflow_speed_decay_DESC = "How rapidly the speed gained from airflow decays." - - airflow_delay = 30 - airflow_delay_NAME = "Airflow Retrigger Delay" - airflow_delay_DESC = "Time in deciseconds before things can be moved by airflow again." - - airflow_mob_slowdown = 1 - airflow_mob_slowdown_NAME = "Airflow Slowdown" - airflow_mob_slowdown_DESC = "Time in tenths of a second to add as a delay to each movement by a mob if they are fighting the pull of the airflow." + 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" -vs_control - var - list/settings = list() - list/bitflags = list("1","2","4","8","16","32","64","128","256","512","1024") - pl_control/plc = new() + var/airflow_lightest_pressure = 20 + var/airflow_lightest_pressure_NAME = "Airflow - Small Movement Threshold %" + var/airflow_lightest_pressure_DESC = "Percent of 1 Atm. at which items with the small weight classes will move." - New() - . = ..() - settings = vars.Copy() + var/airflow_light_pressure = 35 + var/airflow_light_pressure_NAME = "Airflow - Medium Movement Threshold %" + var/airflow_light_pressure_DESC = "Percent of 1 Atm. at which items with the medium weight classes will move." - var/datum/D = new() //Ensure only unique vars are put through by making a datum and removing all common vars. - for(var/V in D.vars) + var/airflow_medium_pressure = 50 + var/airflow_medium_pressure_NAME = "Airflow - Heavy Movement Threshold %" + var/airflow_medium_pressure_DESC = "Percent of 1 Atm. at which items with the largest weight classes will move." + + var/airflow_heavy_pressure = 65 + var/airflow_heavy_pressure_NAME = "Airflow - Mob Movement Threshold %" + var/airflow_heavy_pressure_DESC = "Percent of 1 Atm. at which mobs will move." + + var/airflow_dense_pressure = 85 + var/airflow_dense_pressure_NAME = "Airflow - Dense Movement Threshold %" + var/airflow_dense_pressure_DESC = "Percent of 1 Atm. at which items with canisters and closets will move." + + var/airflow_stun_pressure = 60 + var/airflow_stun_pressure_NAME = "Airflow - Mob Stunning Threshold %" + var/airflow_stun_pressure_DESC = "Percent of 1 Atm. at which mobs will be stunned by airflow." + + var/airflow_stun_cooldown = 60 + var/airflow_stun_cooldown_NAME = "Aiflow Stunning - Cooldown" + var/airflow_stun_cooldown_DESC = "How long, in tenths of a second, to wait before stunning them again." + + var/airflow_stun = 1 + var/airflow_stun_NAME = "Airflow Impact - Stunning" + var/airflow_stun_DESC = "How much a mob is stunned when hit by an object." + + var/airflow_damage = 2 + var/airflow_damage_NAME = "Airflow Impact - Damage" + var/airflow_damage_DESC = "Damage from airflow impacts." + + var/airflow_speed_decay = 1.5 + var/airflow_speed_decay_NAME = "Airflow Speed Decay" + var/airflow_speed_decay_DESC = "How rapidly the speed gained from airflow decays." + + var/airflow_delay = 30 + var/airflow_delay_NAME = "Airflow Retrigger Delay" + var/airflow_delay_DESC = "Time in deciseconds before things can be moved by airflow again." + + var/airflow_mob_slowdown = 1 + var/airflow_mob_slowdown_NAME = "Airflow Slowdown" + var/airflow_mob_slowdown_DESC = "Time in tenths of a second to add as a delay to each movement by a mob if they are fighting the pull of the airflow." + + var/connection_insulation = 1 + var/connection_insulation_NAME = "Connections - Insulation" + var/connection_insulation_DESC = "How insulative a connection is, in terms of heat transfer. 1 is perfectly insulative, and 0 is perfectly conductive." + + var/connection_temperature_delta = 10 + var/connection_temperature_delta_NAME = "Connections - Temperature Difference" + var/connection_temperature_delta_DESC = "The smallest temperature difference which will cause heat to travel through doors." + + +/vs_control/var/list/settings = list() +/vs_control/var/list/bitflags = list("1","2","4","8","16","32","64","128","256","512","1024") +/vs_control/var/pl_control/plc = new() + +/vs_control/New() + . = ..() + settings = vars.Copy() + + var/datum/D = new() //Ensure only unique vars are put through by making a datum and removing all common vars. + for(var/V in D.vars) + settings -= V + + for(var/V in settings) + if(findtextEx(V,"_RANDOM") || findtextEx(V,"_DESC") || findtextEx(V,"_METHOD")) settings -= V - for(var/V in settings) - if(findtextEx(V,"_RANDOM") || findtextEx(V,"_DESC") || findtextEx(V,"_METHOD")) - settings -= V + settings -= "settings" + settings -= "bitflags" + settings -= "plc" - settings -= "settings" - settings -= "bitflags" - settings -= "plc" - - proc/ChangeSettingsDialog(mob/user,list/L) - //var/which = input(user,"Choose a setting:") in L - var/dat = "" - for(var/ch in L) - if(findtextEx(ch,"_RANDOM") || findtextEx(ch,"_DESC") || findtextEx(ch,"_METHOD") || findtextEx(ch,"_NAME")) continue - var/vw - var/vw_desc = "No Description." - var/vw_name = ch - if(ch in plc.settings) - vw = plc.vars[ch] - if("[ch]_DESC" in plc.vars) vw_desc = plc.vars["[ch]_DESC"] - if("[ch]_NAME" in plc.vars) vw_name = plc.vars["[ch]_NAME"] - else - vw = vars[ch] - if("[ch]_DESC" in vars) vw_desc = vars["[ch]_DESC"] - if("[ch]_NAME" in vars) vw_name = vars["[ch]_NAME"] - dat += "[vw_name] = [vw] \[Change\]
" - dat += "[vw_desc]

" - user << browse(dat,"window=settings") - Topic(href,href_list) - if("changevar" in href_list) - ChangeSetting(usr,href_list["changevar"]) - proc/ChangeSetting(mob/user,ch) +/vs_control/proc/ChangeSettingsDialog(mob/user,list/L) + //var/which = input(user,"Choose a setting:") in L + var/dat = "" + for(var/ch in L) + if(findtextEx(ch,"_RANDOM") || findtextEx(ch,"_DESC") || findtextEx(ch,"_METHOD") || findtextEx(ch,"_NAME")) continue var/vw - var/how = "Text" - var/display_description = ch + var/vw_desc = "No Description." + var/vw_name = ch if(ch in plc.settings) vw = plc.vars[ch] - if("[ch]_NAME" in plc.vars) - display_description = plc.vars["[ch]_NAME"] - if("[ch]_METHOD" in plc.vars) - how = plc.vars["[ch]_METHOD"] - else - if(isnum(vw)) - how = "Numeric" - else - how = "Text" + if("[ch]_DESC" in plc.vars) vw_desc = plc.vars["[ch]_DESC"] + if("[ch]_NAME" in plc.vars) vw_name = plc.vars["[ch]_NAME"] else vw = vars[ch] - if("[ch]_NAME" in vars) - display_description = vars["[ch]_NAME"] - if("[ch]_METHOD" in vars) - how = vars["[ch]_METHOD"] + if("[ch]_DESC" in vars) vw_desc = vars["[ch]_DESC"] + if("[ch]_NAME" in vars) vw_name = vars["[ch]_NAME"] + dat += "[vw_name] = [vw] \[Change\]
" + dat += "[vw_desc]

" + user << browse(dat,"window=settings") + +/vs_control/Topic(href,href_list) + if("changevar" in href_list) + ChangeSetting(usr,href_list["changevar"]) + +/vs_control/proc/ChangeSetting(mob/user,ch) + var/vw + var/how = "Text" + var/display_description = ch + if(ch in plc.settings) + vw = plc.vars[ch] + if("[ch]_NAME" in plc.vars) + display_description = plc.vars["[ch]_NAME"] + if("[ch]_METHOD" in plc.vars) + how = plc.vars["[ch]_METHOD"] + else + if(isnum(vw)) + how = "Numeric" else - if(isnum(vw)) - how = "Numeric" - else - how = "Text" - var/newvar = vw - switch(how) - if("Numeric") - newvar = input(user,"Enter a number:","Settings",newvar) as num - if("Bit Flag") - var/flag = input(user,"Toggle which bit?","Settings") in bitflags - flag = text2num(flag) - if(newvar & flag) - newvar &= ~flag - else - newvar |= flag - if("Toggle") - newvar = !newvar - if("Text") - newvar = input(user,"Enter a string:","Settings",newvar) as text - if("Long Text") - newvar = input(user,"Enter text:","Settings",newvar) as message - vw = newvar - if(ch in plc.settings) - plc.vars[ch] = vw + how = "Text" + else + vw = vars[ch] + if("[ch]_NAME" in vars) + display_description = vars["[ch]_NAME"] + if("[ch]_METHOD" in vars) + how = vars["[ch]_METHOD"] else - vars[ch] = vw - if(how == "Toggle") - newvar = (newvar?"ON":"OFF") - world << "\blue [key_name(user)] changed the setting [display_description] to [newvar]." - if(ch in plc.settings) - ChangeSettingsDialog(user,plc.settings) - else - ChangeSettingsDialog(user,settings) - proc/RandomizeWithProbability() - for(var/V in settings) - var/newvalue - if("[V]_RANDOM" in vars) - if(isnum(vars["[V]_RANDOM"])) - newvalue = prob(vars["[V]_RANDOM"]) - else if(istext(vars["[V]_RANDOM"])) - newvalue = roll(vars["[V]_RANDOM"]) - else - newvalue = vars[V] - V = newvalue + if(isnum(vw)) + how = "Numeric" + else + how = "Text" + var/newvar = vw + switch(how) + if("Numeric") + newvar = input(user,"Enter a number:","Settings",newvar) as num + if("Bit Flag") + var/flag = input(user,"Toggle which bit?","Settings") in bitflags + flag = text2num(flag) + if(newvar & flag) + newvar &= ~flag + else + newvar |= flag + if("Toggle") + newvar = !newvar + if("Text") + newvar = input(user,"Enter a string:","Settings",newvar) as text + if("Long Text") + newvar = input(user,"Enter text:","Settings",newvar) as message + vw = newvar + if(ch in plc.settings) + plc.vars[ch] = vw + else + vars[ch] = vw + if(how == "Toggle") + newvar = (newvar?"ON":"OFF") + world << "\blue [key_name(user)] changed the setting [display_description] to [newvar]." + if(ch in plc.settings) + ChangeSettingsDialog(user,plc.settings) + else + ChangeSettingsDialog(user,settings) - proc/ChangePlasma() - for(var/V in plc.settings) - plc.Randomize(V) - - proc/SetDefault(var/mob/user) - var/list/setting_choices = list("Plasma - Standard", "Plasma - Low Hazard", "Plasma - High Hazard", "Plasma - Oh Shit!",\ - "ZAS - Normal", "ZAS - Forgiving", "ZAS - Dangerous", "ZAS - Hellish") - var/def = input(user, "Which of these presets should be used?") as null|anything in setting_choices - if(!def) - return - switch(def) - if("Plasma - Standard") - plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth. - plc.PLASMAGUARD_ONLY = 0 - plc.GENETIC_CORRUPTION = 0 //Chance of genetic corruption as well as toxic damage, X in 1000. - plc.SKIN_BURNS = 0 //Plasma has an effect similar to mustard gas on the un-suited. - plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection. - plc.PLASMA_HALLUCINATION = 0 - plc.CONTAMINATION_LOSS = 0.02 - - if("Plasma - Low Hazard") - plc.CLOTH_CONTAMINATION = 0 //If this is on, plasma does damage by getting into cloth. - plc.PLASMAGUARD_ONLY = 0 - plc.GENETIC_CORRUPTION = 0 //Chance of genetic corruption as well as toxic damage, X in 1000 - plc.SKIN_BURNS = 0 //Plasma has an effect similar to mustard gas on the un-suited. - plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection. - plc.PLASMA_HALLUCINATION = 0 - plc.CONTAMINATION_LOSS = 0.01 - - if("Plasma - High Hazard") - plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth. - plc.PLASMAGUARD_ONLY = 0 - plc.GENETIC_CORRUPTION = 0 //Chance of genetic corruption as well as toxic damage, X in 1000. - plc.SKIN_BURNS = 1 //Plasma has an effect similar to mustard gas on the un-suited. - plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection. - plc.PLASMA_HALLUCINATION = 1 - plc.CONTAMINATION_LOSS = 0.05 - - if("Plasma - Oh Shit!") - plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth. - plc.PLASMAGUARD_ONLY = 1 - plc.GENETIC_CORRUPTION = 5 //Chance of genetic corruption as well as toxic damage, X in 1000. - plc.SKIN_BURNS = 1 //Plasma has an effect similar to mustard gas on the un-suited. - plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection. - plc.PLASMA_HALLUCINATION = 1 - plc.CONTAMINATION_LOSS = 0.075 - - if("ZAS - Normal") - airflow_lightest_pressure = 20 - airflow_light_pressure = 35 - airflow_medium_pressure = 50 - airflow_heavy_pressure = 65 - airflow_dense_pressure = 85 - airflow_stun_pressure = 60 - airflow_stun_cooldown = 60 - airflow_stun = 1 - airflow_damage = 2 - airflow_speed_decay = 1.5 - airflow_delay = 30 - airflow_mob_slowdown = 1 - - if("ZAS - Forgiving") - airflow_lightest_pressure = 45 - airflow_light_pressure = 60 - airflow_medium_pressure = 120 - airflow_heavy_pressure = 110 - airflow_dense_pressure = 200 - airflow_stun_pressure = 150 - airflow_stun_cooldown = 90 - airflow_stun = 0.15 - airflow_damage = 0.15 - airflow_speed_decay = 1.5 - airflow_delay = 50 - airflow_mob_slowdown = 0 - - if("ZAS - Dangerous") - airflow_lightest_pressure = 15 - airflow_light_pressure = 30 - airflow_medium_pressure = 45 - airflow_heavy_pressure = 55 - airflow_dense_pressure = 70 - airflow_stun_pressure = 50 - airflow_stun_cooldown = 50 - airflow_stun = 2 - airflow_damage = 3 - airflow_speed_decay = 1.2 - airflow_delay = 25 - airflow_mob_slowdown = 2 - - if("ZAS - Hellish") - airflow_lightest_pressure = 20 - airflow_light_pressure = 30 - airflow_medium_pressure = 40 - airflow_heavy_pressure = 50 - airflow_dense_pressure = 60 - airflow_stun_pressure = 40 - airflow_stun_cooldown = 40 - airflow_stun = 3 - airflow_damage = 4 - airflow_speed_decay = 1 - airflow_delay = 20 - airflow_mob_slowdown = 3 - - - world << "\blue [key_name(user)] changed the global plasma/ZAS settings to \"[def]\"" - -pl_control - var/list/settings = list() - New() - . = ..() - settings = vars.Copy() - - var/datum/D = new() //Ensure only unique vars are put through by making a datum and removing all common vars. - for(var/V in D.vars) - settings -= V - - for(var/V in settings) - if(findtextEx(V,"_RANDOM") || findtextEx(V,"_DESC")) - settings -= V - - settings -= "settings" - proc/Randomize(V) +/vs_control/proc/RandomizeWithProbability() + for(var/V in settings) var/newvalue if("[V]_RANDOM" in vars) if(isnum(vars["[V]_RANDOM"])) newvalue = prob(vars["[V]_RANDOM"]) else if(istext(vars["[V]_RANDOM"])) - var/txt = vars["[V]_RANDOM"] - if(findtextEx(txt,"PROB")) - txt = text2list(txt,"/") - txt[1] = replacetext(txt[1],"PROB","") - var/p = text2num(txt[1]) - var/r = txt[2] - if(prob(p)) - newvalue = roll(r) - else - newvalue = vars[V] - else if(findtextEx(txt,"PICK")) - txt = replacetext(txt,"PICK","") - txt = text2list(txt,",") - newvalue = pick(txt) - else - newvalue = roll(txt) + newvalue = roll(vars["[V]_RANDOM"]) else newvalue = vars[V] - vars[V] = newvalue + V = newvalue + +/vs_control/proc/ChangePlasma() + for(var/V in plc.settings) + plc.Randomize(V) + +/vs_control/proc/SetDefault(var/mob/user) + var/list/setting_choices = list("Plasma - Standard", "Plasma - Low Hazard", "Plasma - High Hazard", "Plasma - Oh Shit!",\ + "ZAS - Normal", "ZAS - Forgiving", "ZAS - Dangerous", "ZAS - Hellish") + var/def = input(user, "Which of these presets should be used?") as null|anything in setting_choices + if(!def) + return + switch(def) + if("Plasma - Standard") + plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth. + plc.PLASMAGUARD_ONLY = 0 + plc.GENETIC_CORRUPTION = 0 //Chance of genetic corruption as well as toxic damage, X in 1000. + plc.SKIN_BURNS = 0 //Plasma has an effect similar to mustard gas on the un-suited. + plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection. + plc.PLASMA_HALLUCINATION = 0 + plc.CONTAMINATION_LOSS = 0.02 + + if("Plasma - Low Hazard") + plc.CLOTH_CONTAMINATION = 0 //If this is on, plasma does damage by getting into cloth. + plc.PLASMAGUARD_ONLY = 0 + plc.GENETIC_CORRUPTION = 0 //Chance of genetic corruption as well as toxic damage, X in 1000 + plc.SKIN_BURNS = 0 //Plasma has an effect similar to mustard gas on the un-suited. + plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection. + plc.PLASMA_HALLUCINATION = 0 + plc.CONTAMINATION_LOSS = 0.01 + + if("Plasma - High Hazard") + plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth. + plc.PLASMAGUARD_ONLY = 0 + plc.GENETIC_CORRUPTION = 0 //Chance of genetic corruption as well as toxic damage, X in 1000. + plc.SKIN_BURNS = 1 //Plasma has an effect similar to mustard gas on the un-suited. + plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection. + plc.PLASMA_HALLUCINATION = 1 + plc.CONTAMINATION_LOSS = 0.05 + + if("Plasma - Oh Shit!") + plc.CLOTH_CONTAMINATION = 1 //If this is on, plasma does damage by getting into cloth. + plc.PLASMAGUARD_ONLY = 1 + plc.GENETIC_CORRUPTION = 5 //Chance of genetic corruption as well as toxic damage, X in 1000. + plc.SKIN_BURNS = 1 //Plasma has an effect similar to mustard gas on the un-suited. + plc.EYE_BURNS = 1 //Plasma burns the eyes of anyone not wearing eye protection. + plc.PLASMA_HALLUCINATION = 1 + plc.CONTAMINATION_LOSS = 0.075 + + if("ZAS - Normal") + airflow_lightest_pressure = 20 + airflow_light_pressure = 35 + airflow_medium_pressure = 50 + airflow_heavy_pressure = 65 + airflow_dense_pressure = 85 + airflow_stun_pressure = 60 + airflow_stun_cooldown = 60 + airflow_stun = 1 + airflow_damage = 2 + airflow_speed_decay = 1.5 + airflow_delay = 30 + airflow_mob_slowdown = 1 + + if("ZAS - Forgiving") + airflow_lightest_pressure = 45 + airflow_light_pressure = 60 + airflow_medium_pressure = 120 + airflow_heavy_pressure = 110 + airflow_dense_pressure = 200 + airflow_stun_pressure = 150 + airflow_stun_cooldown = 90 + airflow_stun = 0.15 + airflow_damage = 0.15 + airflow_speed_decay = 1.5 + airflow_delay = 50 + airflow_mob_slowdown = 0 + + if("ZAS - Dangerous") + airflow_lightest_pressure = 15 + airflow_light_pressure = 30 + airflow_medium_pressure = 45 + airflow_heavy_pressure = 55 + airflow_dense_pressure = 70 + airflow_stun_pressure = 50 + airflow_stun_cooldown = 50 + airflow_stun = 2 + airflow_damage = 3 + airflow_speed_decay = 1.2 + airflow_delay = 25 + airflow_mob_slowdown = 2 + + if("ZAS - Hellish") + airflow_lightest_pressure = 20 + airflow_light_pressure = 30 + airflow_medium_pressure = 40 + airflow_heavy_pressure = 50 + airflow_dense_pressure = 60 + airflow_stun_pressure = 40 + airflow_stun_cooldown = 40 + airflow_stun = 3 + airflow_damage = 4 + airflow_speed_decay = 1 + airflow_delay = 20 + airflow_mob_slowdown = 3 + + + world << "\blue [key_name(user)] changed the global plasma/ZAS settings to \"[def]\"" + +/pl_control/var/list/settings = list() + +/pl_control/New() + . = ..() + settings = vars.Copy() + + var/datum/D = new() //Ensure only unique vars are put through by making a datum and removing all common vars. + for(var/V in D.vars) + settings -= V + + for(var/V in settings) + if(findtextEx(V,"_RANDOM") || findtextEx(V,"_DESC")) + settings -= V + + settings -= "settings" + +/pl_control/proc/Randomize(V) + var/newvalue + if("[V]_RANDOM" in vars) + if(isnum(vars["[V]_RANDOM"])) + newvalue = prob(vars["[V]_RANDOM"]) + else if(istext(vars["[V]_RANDOM"])) + var/txt = vars["[V]_RANDOM"] + if(findtextEx(txt,"PROB")) + txt = text2list(txt,"/") + txt[1] = replacetext(txt[1],"PROB","") + var/p = text2num(txt[1]) + var/r = txt[2] + if(prob(p)) + newvalue = roll(r) + else + newvalue = vars[V] + else if(findtextEx(txt,"PICK")) + txt = replacetext(txt,"PICK","") + txt = text2list(txt,",") + newvalue = pick(txt) + else + newvalue = roll(txt) + else + newvalue = vars[V] + vars[V] = newvalue diff --git a/code/ZAS/ZAS_Turfs.dm b/code/ZAS/ZAS_Turfs.dm index 2ed0478aba6..0070a19c5d2 100644 --- a/code/ZAS/ZAS_Turfs.dm +++ b/code/ZAS/ZAS_Turfs.dm @@ -1,278 +1,266 @@ -atom/var/pressure_resistance = ONE_ATMOSPHERE -turf +/atom/var/pressure_resistance = ONE_ATMOSPHERE - var/zone/zone +/turf/var/zone/zone - assume_air(datum/gas_mixture/giver) //use this for machines to adjust air - del(giver) - return 0 +/turf/assume_air(datum/gas_mixture/giver) //use this for machines to adjust air + del(giver) + return 0 - return_air() - //Create gas mixture to hold data for passing - var/datum/gas_mixture/GM = new +/turf/return_air() + //Create gas mixture to hold data for passing + var/datum/gas_mixture/GM = new - GM.oxygen = oxygen - GM.carbon_dioxide = carbon_dioxide - GM.nitrogen = nitrogen - GM.toxins = toxins + GM.oxygen = oxygen + GM.carbon_dioxide = carbon_dioxide + GM.nitrogen = nitrogen + GM.toxins = toxins - GM.temperature = temperature - GM.update_values() + GM.temperature = temperature + GM.update_values() - return GM + return GM - remove_air(amount as num) - var/datum/gas_mixture/GM = new +/turf/remove_air(amount as num) + var/datum/gas_mixture/GM = new - var/sum = oxygen + carbon_dioxide + nitrogen + toxins - if(sum>0) - GM.oxygen = (oxygen/sum)*amount - GM.carbon_dioxide = (carbon_dioxide/sum)*amount - GM.nitrogen = (nitrogen/sum)*amount - GM.toxins = (toxins/sum)*amount + var/sum = oxygen + carbon_dioxide + nitrogen + toxins + if(sum>0) + GM.oxygen = (oxygen/sum)*amount + GM.carbon_dioxide = (carbon_dioxide/sum)*amount + GM.nitrogen = (nitrogen/sum)*amount + GM.toxins = (toxins/sum)*amount - GM.temperature = temperature - GM.update_values() + GM.temperature = temperature + GM.update_values() - return GM + return GM -turf - simulated +/turf/simulated/var/current_graphic = null - var/current_graphic = null +/turf/simulated/var/tmp/datum/gas_mixture/air - var/tmp - datum/gas_mixture/air +/turf/simulated/var/tmp/processing = 1 - processing = 1 +/turf/simulated/var/tmp/air_check_directions = 0 //Do not modify this, just add turf to air_master.tiles_to_update - air_check_directions = 0 //Do not modify this, just add turf to air_master.tiles_to_update +/turf/simulated/var/tmp/obj/fire/active_hotspot - obj/fire/active_hotspot +/turf/simulated/proc/update_visuals() + overlays = null + var/siding_icon_state = return_siding_icon_state() + if(siding_icon_state) + overlays += image('floors.dmi',siding_icon_state) + var/datum/gas_mixture/model = return_air() + switch(model.graphic) + if(1) + overlays.Add(plmaster) //TODO: Make invisible plasma an option + if(2) + overlays.Add(slmaster) - proc/update_visuals() - overlays = null +/turf/simulated/New() + ..() - var/siding_icon_state = return_siding_icon_state() - if(siding_icon_state) - overlays += image('floors.dmi',siding_icon_state) - var/datum/gas_mixture/model = return_air() - switch(model.graphic) - if(1) - overlays.Add(plmaster) //TODO: Make invisible plasma an option - if(2) - overlays.Add(slmaster) + if(!blocks_air) + air = new + air.oxygen = oxygen + air.carbon_dioxide = carbon_dioxide + air.nitrogen = nitrogen + air.toxins = toxins + air.temperature = temperature + air.update_values() - New() - ..() - - if(!blocks_air) - air = new - - air.oxygen = oxygen - air.carbon_dioxide = carbon_dioxide - air.nitrogen = nitrogen - air.toxins = toxins - - air.temperature = temperature - air.update_values() - - if(air_master) - air_master.tiles_to_update.Add(src) - - else - if(air_master) - for(var/direction in cardinal) - var/turf/simulated/floor/target = get_step(src,direction) - if(istype(target)) - air_master.tiles_to_update |= target - - Del() - if(active_hotspot) - del(active_hotspot) - if(blocks_air) - for(var/direction in list(NORTH, SOUTH, EAST, WEST)) - var/turf/simulated/tile = get_step(src,direction) - if(istype(tile) && !tile.blocks_air) - air_master.tiles_to_update.Add(tile) - ..() - - assume_air(datum/gas_mixture/giver) - if(!giver) return 0 - if(zone) - zone.air.merge(giver) - return 1 - else - return ..() - - return_air() - if(zone) - return zone.air - else if(air) - return air - - else - return ..() - - remove_air(amount as num) - if(zone) - var/datum/gas_mixture/removed = null - removed = zone.air.remove(amount) - return removed - else if(air) - var/datum/gas_mixture/removed = null - removed = air.remove(amount) - - if(air.check_tile_graphic()) - update_visuals(air) - return removed - - else - return ..() - - proc/update_air_properties() - var/air_directions_archived = air_check_directions - air_check_directions = 0 + if(air_master) + air_master.tiles_to_update.Add(src) + else + if(air_master) for(var/direction in cardinal) - if(ZAirPass(get_step(src,direction))) - air_check_directions |= direction + var/turf/simulated/floor/target = get_step(src,direction) + if(istype(target)) + air_master.tiles_to_update |= target - if(!zone && !blocks_air) //No zone, but not a wall. - for(var/direction in DoorDirections) //Check door directions first. - if(air_check_directions&direction) - var/turf/simulated/T = get_step(src,direction) - if(!istype(T)) - continue - if(T.zone) - T.zone.AddTurf(src) - break - if(!zone) //Still no zone - for(var/direction in CounterDoorDirections) //Check the others second. - if(air_check_directions&direction) - var/turf/simulated/T = get_step(src,direction) - if(!istype(T)) - continue - if(T.zone) - T.zone.AddTurf(src) - break - if(!zone) //No zone found, new zone! - new/zone(src) - if(!zone) //Still no zone, the floodfill determined it is not part of a larger zone. Force a zone on it. - new/zone(list(src)) +/turf/simulated/Del() + if(active_hotspot) + del(active_hotspot) + if(blocks_air) + for(var/direction in list(NORTH, SOUTH, EAST, WEST)) + var/turf/simulated/tile = get_step(src,direction) + if(istype(tile) && !tile.blocks_air) + air_master.tiles_to_update.Add(tile) + ..() - //Check pass sanity of the connections. - if("\ref[src]" in air_master.turfs_with_connections) - for(var/connection/C in air_master.turfs_with_connections["\ref[src]"]) - air_master.connections_to_check |= C +/turf/simulated/assume_air(datum/gas_mixture/giver) + if(!giver) return 0 + if(zone) + zone.air.merge(giver) + return 1 + else + return ..() - if(zone && !zone.rebuild) - for(var/direction in cardinal) - var/turf/T = get_step(src,direction) +/turf/simulated/return_air() + if(zone) + return zone.air + else if(air) + return air + + else + return ..() + +/turf/simulated/remove_air(amount as num) + if(zone) + var/datum/gas_mixture/removed = null + removed = zone.air.remove(amount) + return removed + else if(air) + var/datum/gas_mixture/removed = null + removed = air.remove(amount) + + if(air.check_tile_graphic()) + update_visuals(air) + return removed + + else + return ..() + +/turf/simulated/proc/update_air_properties() + var/air_directions_archived = air_check_directions + air_check_directions = 0 + + for(var/direction in cardinal) + if(ZAirPass(get_step(src,direction))) + air_check_directions |= direction + + if(!zone && !blocks_air) //No zone, but not a wall. + for(var/direction in DoorDirections) //Check door directions first. + if(air_check_directions&direction) + var/turf/simulated/T = get_step(src,direction) + if(!istype(T)) + continue + if(T.zone) + T.zone.AddTurf(src) + break + if(!zone) //Still no zone + for(var/direction in CounterDoorDirections) //Check the others second. + if(air_check_directions&direction) + var/turf/simulated/T = get_step(src,direction) if(!istype(T)) continue + if(T.zone) + T.zone.AddTurf(src) + break + if(!zone) //No zone found, new zone! + new/zone(src) + if(!zone) //Still no zone, the floodfill determined it is not part of a larger zone. Force a zone on it. + new/zone(list(src)) - //I can connect to air in this direction - if(air_check_directions&direction) + //Check pass sanity of the connections. + if("\ref[src]" in air_master.turfs_with_connections) + for(var/connection/C in air_master.turfs_with_connections["\ref[src]"]) + air_master.connections_to_check |= C - //If either block air, we must look to see if the adjacent turfs need rebuilt. - if(!CanPass(null, T, 0, 0)) + if(zone && !zone.rebuild) + for(var/direction in cardinal) + var/turf/T = get_step(src,direction) + if(!istype(T)) + continue - //Target blocks air - if(!T.CanPass(null, T, 0, 0)) - var/turf/NT = get_step(T, direction) + //I can connect to air in this direction + if(air_check_directions&direction) - //If that turf is in my zone still, rebuild. - if(istype(NT,/turf/simulated) && NT in zone.contents) - zone.rebuild = 1 + //If either block air, we must look to see if the adjacent turfs need rebuilt. + if(!CanPass(null, T, 0, 0)) - //If that is an unsimulated tile in my zone, see if we need to rebuild or just remove. - else if(istype(NT) && NT in zone.unsimulated_tiles) - var/consider_rebuild = 0 - for(var/d in cardinal) - var/turf/UT = get_step(NT,d) - if(istype(UT, /turf/simulated) && UT.zone == zone && UT.CanPass(null, NT, 0, 0)) //If we find a neighboring tile that is in the same zone, check if we need to rebuild - consider_rebuild = 1 - break - if(consider_rebuild) - zone.rebuild = 1 //Gotta check if we need to rebuild, dammit - else - zone.RemoveTurf(NT) //Not adjacent to anything, and unsimulated. Goodbye~ - - //To make a closed connection through closed door. - ZConnect(T, src) - - //If I block air. - else if(T.zone && !T.zone.rebuild) - var/turf/NT = get_step(src, reverse_direction(direction)) - - //If I am splitting a zone, rebuild. - if(istype(NT,/turf/simulated) && (NT in T.zone.contents || (NT.zone && T in NT.zone.contents))) - T.zone.rebuild = 1 - - //If NT is unsimulated, parse if I should remove it or rebuild. - else if(istype(NT) && NT in T.zone.unsimulated_tiles) - var/consider_rebuild = 0 - for(var/d in cardinal) - var/turf/UT = get_step(NT,d) - if(istype(UT, /turf/simulated) && UT.zone == T.zone && UT.CanPass(null, NT, 0, 0)) //If we find a neighboring tile that is in the same zone, check if we need to rebuild - consider_rebuild = 1 - break - - //Needs rebuilt. - if(consider_rebuild) - T.zone.rebuild = 1 - - //Not adjacent to anything, and unsimulated. Goodbye~ - else - T.zone.RemoveTurf(NT) - - else - //Produce connection through open door. - ZConnect(src,T) - - //Something like a wall was built, changing the geometry. - else if(air_directions_archived&direction) + //Target blocks air + if(!T.CanPass(null, T, 0, 0)) var/turf/NT = get_step(T, direction) - //If the tile is in our own zone, and we cannot connect to it, better rebuild. + //If that turf is in my zone still, rebuild. if(istype(NT,/turf/simulated) && NT in zone.contents) zone.rebuild = 1 - //Parse if we need to remove the tile, or rebuild the zone. + //If that is an unsimulated tile in my zone, see if we need to rebuild or just remove. else if(istype(NT) && NT in zone.unsimulated_tiles) var/consider_rebuild = 0 - - //Loop through all neighboring turfs to see if we should remove the turf or just rebuild. for(var/d in cardinal) var/turf/UT = get_step(NT,d) + if(istype(UT, /turf/simulated) && UT.zone == zone && UT.CanPass(null, NT, 0, 0)) //If we find a neighboring tile that is in the same zone, check if we need to rebuild + consider_rebuild = 1 + break + if(consider_rebuild) + zone.rebuild = 1 //Gotta check if we need to rebuild, dammit + else + zone.RemoveTurf(NT) //Not adjacent to anything, and unsimulated. Goodbye~ - //If we find a neighboring tile that is in the same zone, rebuild - if(istype(UT, /turf/simulated) && UT.zone == zone && UT.CanPass(null, NT, 0, 0)) + //To make a closed connection through closed door. + ZConnect(T, src) + + //If I block air. + else if(T.zone && !T.zone.rebuild) + var/turf/NT = get_step(src, reverse_direction(direction)) + + //If I am splitting a zone, rebuild. + if(istype(NT,/turf/simulated) && (NT in T.zone.contents || (NT.zone && T in NT.zone.contents))) + T.zone.rebuild = 1 + + //If NT is unsimulated, parse if I should remove it or rebuild. + else if(istype(NT) && NT in T.zone.unsimulated_tiles) + var/consider_rebuild = 0 + for(var/d in cardinal) + var/turf/UT = get_step(NT,d) + if(istype(UT, /turf/simulated) && UT.zone == T.zone && UT.CanPass(null, NT, 0, 0)) //If we find a neighboring tile that is in the same zone, check if we need to rebuild consider_rebuild = 1 break - //The unsimulated turf is adjacent to another one of our zone's turfs, - // better rebuild to be sure we didn't get cut in twain + //Needs rebuilt. if(consider_rebuild) - zone.rebuild = 1 + T.zone.rebuild = 1 //Not adjacent to anything, and unsimulated. Goodbye~ else - zone.RemoveTurf(NT) + T.zone.RemoveTurf(NT) - if(air_check_directions) - processing = 1 - else - processing = 0 - return 1 + else + //Produce connection through open door. + ZConnect(src,T) + //Something like a wall was built, changing the geometry. + else if(air_directions_archived&direction) + var/turf/NT = get_step(T, direction) + //If the tile is in our own zone, and we cannot connect to it, better rebuild. + if(istype(NT,/turf/simulated) && NT in zone.contents) + zone.rebuild = 1 + //Parse if we need to remove the tile, or rebuild the zone. + else if(istype(NT) && NT in zone.unsimulated_tiles) + var/consider_rebuild = 0 + //Loop through all neighboring turfs to see if we should remove the turf or just rebuild. + for(var/d in cardinal) + var/turf/UT = get_step(NT,d) + + //If we find a neighboring tile that is in the same zone, rebuild + if(istype(UT, /turf/simulated) && UT.zone == zone && UT.CanPass(null, NT, 0, 0)) + consider_rebuild = 1 + break + + //The unsimulated turf is adjacent to another one of our zone's turfs, + // better rebuild to be sure we didn't get cut in twain + if(consider_rebuild) + zone.rebuild = 1 + + //Not adjacent to anything, and unsimulated. Goodbye~ + else + zone.RemoveTurf(NT) + + if(air_check_directions) + processing = 1 + else + processing = 0 + return 1 /turf/proc/HasDoor(turf/O) //Checks for the presence of doors, used for zone spreading and connection. @@ -289,7 +277,7 @@ turf else return 1 -turf/proc/ZCanPass(turf/simulated/T, var/include_space = 0) +/turf/proc/ZCanPass(turf/simulated/T, var/include_space = 0) //Fairly standard pass checks for turfs, objects and directional windows. Also stops at the edge of space. if(!istype(T)) return 0 @@ -314,7 +302,7 @@ turf/proc/ZCanPass(turf/simulated/T, var/include_space = 0) return 1 -turf/proc/ZAirPass(turf/T) +/turf/proc/ZAirPass(turf/T) //Fairly standard pass checks for turfs, objects and directional windows. if(!istype(T)) return 0 @@ -336,7 +324,6 @@ turf/proc/ZAirPass(turf/T) return 1 - /*UNUSED /turf/proc/check_connections() //Checks for new connections that can be made. diff --git a/code/ZAS/ZAS_Zones.dm b/code/ZAS/ZAS_Zones.dm index 2f5d564b3b4..860f57cd370 100644 --- a/code/ZAS/ZAS_Zones.dm +++ b/code/ZAS/ZAS_Zones.dm @@ -2,129 +2,126 @@ var/list/zones = list() var/list/DoorDirections = list(NORTH,WEST) //Which directions doors turfs can connect to zones var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs can connect to zones -zone - - var - dbg_output = 0 //Enables debug output. - rebuild = 0 //If 1, zone will be rebuilt on next process. Not sure if used. - datum/gas_mixture/air //The air contents of the zone. - list/contents //All the tiles that are contained in this zone. - list/connections // /connection objects which refer to connections with other zones, e.g. through a door. - list/connected_zones //Parallels connections, but lists zones to which this one is connected and the number +/zone + var/dbg_output = 0 //Enables debug output. + var/rebuild = 0 //If 1, zone will be rebuilt on next process. Not sure if used. + var/datum/gas_mixture/air //The air contents of the zone. + var/list/contents //All the tiles that are contained in this zone. + var/list/connections // /connection objects which refer to connections with other zones, e.g. through a door. + var/list/connected_zones //Parallels connections, but lists zones to which this one is connected and the number //of points they're connected at. - list/closed_connection_zones //Same as connected_zones, but for zones where the door or whatever is closed. - list/unsimulated_tiles // Any space tiles in this list will cause air to flow out. - last_update = 0 - progress = "nothing" - - // To make sure you're not spammed to death by airflow sound effects - tmp/playsound_cooldown = 0 + var/list/closed_connection_zones //Same as connected_zones, but for zones where the door or whatever is closed. + var/list/unsimulated_tiles // Any space tiles in this list will cause air to flow out. + var/last_update = 0 + var/progress = "nothing" //CREATION AND DELETION - New(turf/start) - . = ..() - //Get the turfs that are part of the zone using a floodfill method - if(istype(start,/list)) - contents = start - else - contents = FloodFill(start) +/zone/New(turf/start) + . = ..() + //Get the turfs that are part of the zone using a floodfill method + if(istype(start,/list)) + contents = start + else + contents = FloodFill(start) - //Change all the zone vars of the turfs, check for space to be added to unsimulated_tiles. - for(var/turf/T in contents) - if(T.zone && T.zone != src) - T.zone.RemoveTurf(T) - T.zone = src - if(!istype(T,/turf/simulated)) - AddTurf(T) + //Change all the zone vars of the turfs, check for space to be added to unsimulated_tiles. + for(var/turf/T in contents) + if(T.zone && T.zone != src) + T.zone.RemoveTurf(T) + T.zone = src + if(!istype(T,/turf/simulated)) + AddTurf(T) - //Generate the gas_mixture for use in txhis zone by using the average of the gases - //defined at startup. - air = new - var/members = contents.len - for(var/turf/simulated/T in contents) - air.oxygen += T.oxygen / members - air.nitrogen += T.nitrogen / members - air.carbon_dioxide += T.carbon_dioxide / members - air.toxins += T.toxins / members - air.temperature += T.temperature / members - air.group_multiplier = contents.len - air.update_values() + //Generate the gas_mixture for use in txhis zone by using the average of the gases + //defined at startup. + air = new + air.group_multiplier = contents.len + for(var/turf/simulated/T in contents) + air.oxygen += T.oxygen / air.group_multiplier + air.nitrogen += T.nitrogen / air.group_multiplier + air.carbon_dioxide += T.carbon_dioxide / air.group_multiplier + air.toxins += T.toxins / air.group_multiplier + air.temperature += T.temperature / air.group_multiplier + air.update_values() - //Add this zone to the global list. - zones.Add(src) + //Add this zone to the global list. + zones.Add(src) //LEGACY, DO NOT USE. Use the SoftDelete proc. - Del() - //Ensuring the zone list doesn't get clogged with null values. - for(var/turf/simulated/T in contents) - RemoveTurf(T) - air_master.tiles_to_reconsider_zones += T - for(var/zone/Z in connected_zones) - if(src in Z.connected_zones) - Z.connected_zones.Remove(src) - for(var/connection/C in connections) - air_master.connections_to_check += C - zones.Remove(src) - air = null - . = ..() +/zone/Del() + //Ensuring the zone list doesn't get clogged with null values. + for(var/turf/simulated/T in contents) + RemoveTurf(T) + air_master.tiles_to_reconsider_zones += T + for(var/zone/Z in connected_zones) + if(src in Z.connected_zones) + Z.connected_zones.Remove(src) + for(var/connection/C in connections) + air_master.connections_to_check += C + zones.Remove(src) + air = null + . = ..() //Handles deletion via garbage collection. - proc/SoftDelete() - zones.Remove(src) - air = null +/zone/proc/SoftDelete() + zones.Remove(src) + air = null - //Ensuring the zone list doesn't get clogged with null values. - for(var/turf/simulated/T in contents) - RemoveTurf(T) - air_master.tiles_to_reconsider_zones += T + //Ensuring the zone list doesn't get clogged with null values. + for(var/turf/simulated/T in contents) + RemoveTurf(T) + air_master.tiles_to_reconsider_zones += T - //Removing zone connections and scheduling connection cleanup - for(var/zone/Z in connected_zones) - if(src in Z.connected_zones) - Z.connected_zones.Remove(src) - for(var/connection/C in connections) - air_master.connections_to_check += C + //Removing zone connections and scheduling connection cleanup + for(var/zone/Z in connected_zones) + if(src in Z.connected_zones) + Z.connected_zones.Remove(src) + connected_zones = null - return 1 + for(var/connection/C in connections) + air_master.connections_to_check += C + connections = null + + return 1 //ZONE MANAGEMENT FUNCTIONS - proc/AddTurf(turf/T) - //Adds the turf to contents, increases the size of the zone, and sets the zone var. - if(istype(T, /turf/simulated)) - if(T in contents) - return - if(T.zone) - T.zone.RemoveTurf(T) - contents += T - if(air) - air.group_multiplier++ - T.zone = src - else - if(!unsimulated_tiles) - unsimulated_tiles = list() - else if(T in unsimulated_tiles) - return - unsimulated_tiles += T - contents -= T +/zone/proc/AddTurf(turf/T) + //Adds the turf to contents, increases the size of the zone, and sets the zone var. + if(istype(T, /turf/simulated)) + if(T in contents) + return + if(T.zone) + T.zone.RemoveTurf(T) + contents += T + if(air) + air.group_multiplier++ + T.zone = src + else + if(!unsimulated_tiles) + unsimulated_tiles = list() + else if(T in unsimulated_tiles) + return + unsimulated_tiles += T + contents -= T - proc/RemoveTurf(turf/T) - //Same, but in reverse. - if(istype(T, /turf/simulated)) - if(!(T in contents)) - return - contents -= T - if(air) - air.group_multiplier-- - if(T.zone == src) - T.zone = null - else if(unsimulated_tiles) - unsimulated_tiles -= T - if(!unsimulated_tiles.len) - unsimulated_tiles = null +/zone/proc/RemoveTurf(turf/T) + //Same, but in reverse. + if(istype(T, /turf/simulated)) + if(!(T in contents)) + return + contents -= T + if(air) + air.group_multiplier-- + if(T.zone == src) + T.zone = null + else if(unsimulated_tiles) + unsimulated_tiles -= T + if(!unsimulated_tiles.len) + unsimulated_tiles = null ////////////// //PROCESSING// @@ -132,7 +129,7 @@ zone #define QUANTIZE(variable) (round(variable,0.0001)) -zone/proc/process() +/zone/proc/process() . = 1 progress = "problem with: SoftDelete()" @@ -151,7 +148,7 @@ zone/proc/process() if(!contents.len) //If we got soft deleted. return - progress = "problem with: air.adjust()" + progress = "problem with: air regeneration" //Sometimes explosions will cause the air to be deleted for some reason. if(!air) @@ -162,36 +159,23 @@ zone/proc/process() air.total_moles() world.log << "Air object lost in zone. Regenerating." - progress = "problem with: ShareSpace()" + progress = "problem with: ShareSpace()" if(unsimulated_tiles) if(locate(/turf/simulated) in unsimulated_tiles) for(var/turf/simulated/T in unsimulated_tiles) - RemoveTurf(T) - if(unsimulated_tiles) + unsimulated_tiles -= T + + if(unsimulated_tiles.len) var/moved_air = ShareSpace(air,unsimulated_tiles) - // Only play a sound effect every once in a while - if(playsound_cooldown <= world.time) - // Play a nice sound effect at one of the bordering turfs - - playsound_cooldown = world.time + rand(30, 70) - - var/turf/random_border = pick(contents) - play_wind_sound(random_border, abs(moved_air)) - if(moved_air > vsc.airflow_lightest_pressure) AirflowSpace(src) - - progress = "problem with: air.react()" - - //React the air here. - //Handled by fire, no need for this. -// air.react(null,0) + else + unsimulated_tiles = null //Check the graphic. - progress = "problem with: modifying turf graphics" air.graphic = 0 @@ -246,12 +230,13 @@ zone/proc/process() //Check if the connection is valid first. if(!C.Cleanup()) continue + //Do merging if conditions are met. Specifically, if there's a non-door connection //to somewhere with space, the zones are merged regardless of equilibrium, to speed //up spacing in areas with double-plated windows. if(C && C.A.zone && C.B.zone) //indirect = 2 is a direct connection. - if(C.indirect == 2 ) + if( C.indirect == 2 ) if(C.A.zone.air.compare(C.B.zone.air) || unsimulated_tiles) ZMerge(C.A.zone,C.B.zone) @@ -259,18 +244,13 @@ zone/proc/process() //Share some for(var/zone/Z in connected_zones) + //If that zone has already processed, skip it. + if(Z.last_update > last_update) + continue + if(air && Z.air) //Ensure we're not doing pointless calculations on equilibrium zones. var/moles_delta = abs(air.total_moles() - Z.air.total_moles()) - if(moles_delta > 0.1) - // Only play a sound effect every once in a while - if(playsound_cooldown <= world.time) - // Play a nice sound effect at one of the bordering turfs - - playsound_cooldown = world.time + rand(30, 70) - - var/turf/random_border = pick(contents) - play_wind_sound(random_border, abs(moles_delta)) if(moles_delta > 0.1 || abs(air.temperature - Z.air.temperature) > 0.1) if(abs(Z.air.return_pressure() - air.return_pressure()) > vsc.airflow_lightest_pressure) Airflow(src,Z) @@ -283,8 +263,11 @@ zone/proc/process() ShareRatio( air , Z.air , connected_zones[Z] + unsimulated_boost) for(var/zone/Z in closed_connection_zones) + //If that zone has already processed, skip it. + if(Z.last_update > last_update) + continue if(air && Z.air) - if( abs(air.temperature - Z.air.temperature) > 10 ) + if( abs(air.temperature - Z.air.temperature) > vsc.connection_temperature_delta ) ShareHeat(air, Z.air, closed_connection_zones[Z]) progress = "all components completed successfully, the problem is not here" @@ -293,7 +276,7 @@ zone/proc/process() //Air Movement// //////////////// -var/list/sharing_lookup_table = list(0.15, 0.20, 0.24, 0.27, 0.30, 0.33) +var/list/sharing_lookup_table = list(0.30, 0.40, 0.48, 0.54, 0.60, 0.66) proc/ShareRatio(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles) //Shares a specific ratio of gas between mixtures using simple weighted averages. @@ -423,7 +406,6 @@ proc/ShareSpace(datum/gas_mixture/A, list/unsimulated_tiles, dbg_output) if(sharing_lookup_table.len >= unsimulated_tiles.len) //6 or more interconnecting tiles will max at 42% of air moved per tick. ratio = sharing_lookup_table[unsimulated_tiles.len] - ratio *= 2 A.oxygen = max(0, (A.oxygen - oxy_avg) * (1 - ratio) + oxy_avg ) A.nitrogen = max(0, (A.nitrogen - nit_avg) * (1 - ratio) + nit_avg ) @@ -459,6 +441,9 @@ proc/ShareHeat(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles) ratio = sharing_lookup_table[connecting_tiles] //WOOT WOOT TOUCH THIS AND YOU ARE A RETARD + //We need to adjust it to account for the insulation settings. + ratio *= 1 - vsc.connection_insulation + A.temperature = max(0, (A.temperature - temp_avg) * (1- (ratio / max(1,A.group_multiplier)) ) + temp_avg ) B.temperature = max(0, (B.temperature - temp_avg) * (1- (ratio / max(1,B.group_multiplier)) ) + temp_avg ) @@ -543,22 +528,6 @@ zone/proc/Rebuild() if(istype(T) && T.zone && S.CanPass(null, T, 0, 0)) T.zone.AddTurf(S) - -proc/play_wind_sound(var/turf/random_border, var/n) - if(random_border) - var/windsound = 'sound/effects/wind/wind_2_1.ogg' - switch(n) - if(31 to 40) - windsound = pick('sound/effects/wind/wind_2_1.ogg', 'sound/effects/wind/wind_2_2.ogg') - if(41 to 50) - windsound = pick('sound/effects/wind/wind_3_1.ogg') - if(51 to 60) - windsound = pick('sound/effects/wind/wind_4_1.ogg', 'sound/effects/wind/wind_4_2.ogg') - if(61 to 1000000) - windsound = pick('sound/effects/wind/wind_5_1.ogg') - - playsound(random_border, windsound, 50, 1, 1) - //UNUSED /* zone/proc/connected_zones() diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index ed740f85d16..956e6be2557 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -17,6 +17,11 @@ var/global/list/landmarks_list = list() //list of all landmarks created var/global/list/surgery_steps = list() //list of all surgery steps |BS12 var/global/list/mechas_list = list() //list of all mechs. Used by hostile mobs target tracking. +//Languages/species/whitelist. +var/global/list/all_species[0] +var/global/list/all_languages[0] +var/global/list/whitelisted_species = list("Human") + //Preferences stuff //Hairstyles var/global/list/hair_styles_list = list() //stores /datum/sprite_accessory/hair indexed by name @@ -69,6 +74,21 @@ var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Al var/datum/surgery_step/S = new T surgery_steps += S sort_surgeries() + + //Languages and species. + paths = typesof(/datum/language)-/datum/language + for(var/T in paths) + var/datum/language/L = new T + all_languages[L.name] = L + + paths = typesof(/datum/species)-/datum/species + for(var/T in paths) + var/datum/species/S = new T + all_species[S.name] = S + + if(S.flags & WHITELISTED) + whitelisted_species += S.name + /* // Uncomment to debug chemical reaction list. /client/verb/debug_chemical_list() diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index d0a60a08162..a22c9eec5f1 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -118,7 +118,10 @@ var/gateway_delay = 18000 //How long the gateway takes before it activates. Default is half an hour. var/ghost_interaction = 0 + var/comms_password = "" + var/use_irc_bot = 0 + var/irc_bot_host = "" var/main_irc = "" var/admin_irc = "" var/python_path = "" //Path to the python executable. Defaults to "python" on windows and "/usr/bin/env python2" on unix @@ -407,6 +410,12 @@ if("ghost_interaction") config.ghost_interaction = 1 + if("comms_password") + config.comms_password = value + + if("irc_bot_host") + config.irc_bot_host = value + if("main_irc") config.main_irc = value diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm index c22bf1e2dd8..22a905a2070 100644 --- a/code/controllers/master_controller.dm +++ b/code/controllers/master_controller.dm @@ -132,12 +132,12 @@ datum/controller/game_controller/proc/process() //src.set_debug_state("Air Master") air_master.current_cycle++ - var/success = air_master.tick() //Changed so that a runtime does not crash the ticker. - if(!success) //Runtimed. + if(!air_master.tick()) //Runtimed. air_master.failed_ticks++ if(air_master.failed_ticks > 5) world << "RUNTIMES IN ATMOS TICKER. Killing air simulation!" - message_admins("ZASALERT: unable run [air_master.tick_progress], tell someone about this!") + world.log << "### ZAS SHUTDOWN" + message_admins("ZASALERT: unable to run [air_master.tick_progress], shutting down!") log_admin("ZASALERT: unable run zone/process() -- [air_master.tick_progress]") air_processing_killed = 1 air_master.failed_ticks = 0 diff --git a/code/controllers/shuttle_controller.dm b/code/controllers/shuttle_controller.dm index e6d58ef6386..f92d8b1c7b1 100644 --- a/code/controllers/shuttle_controller.dm +++ b/code/controllers/shuttle_controller.dm @@ -45,381 +45,382 @@ datum/shuttle_controller if(istype(A, /area/hallway)) A.readyalert() - proc/shuttlealert(var/X) +datum/shuttle_controller/proc/shuttlealert(var/X) alert = X - proc/recall() - if(direction == 1) - var/timeleft = timeleft() - if(alert == 0) - if(timeleft >= 600) - return - captain_announce("The emergency shuttle has been recalled.") - world << sound('sound/AI/shuttlerecalled.ogg') - setdirection(-1) - online = 1 - for(var/area/A in world) - if(istype(A, /area/hallway)) - A.readyreset() - return - else //makes it possible to send shuttle back. - captain_announce("The shuttle has been recalled.") - setdirection(-1) - online = 1 - alert = 0 // set alert back to 0 after an admin recall +datum/shuttle_controller/proc/recall() + if(direction == 1) + var/timeleft = timeleft() + if(alert == 0) + if(timeleft >= 600) return + captain_announce("The emergency shuttle has been recalled.") + world << sound('sound/AI/shuttlerecalled.ogg') + setdirection(-1) + online = 1 + for(var/area/A in world) + if(istype(A, /area/hallway)) + A.readyreset() + return + else //makes it possible to send shuttle back. + captain_announce("The shuttle has been recalled.") + setdirection(-1) + online = 1 + alert = 0 // set alert back to 0 after an admin recall + return // returns the time (in seconds) before shuttle arrival // note if direction = -1, gives a count-up to SHUTTLEARRIVETIME - proc/timeleft() - if(online) - var/timeleft = round((endtime - world.timeofday)/10 ,1) - if(direction == 1 || direction == 2) - return timeleft - else - return SHUTTLEARRIVETIME-timeleft +datum/shuttle_controller/proc/timeleft() + if(online) + var/timeleft = round((endtime - world.timeofday)/10 ,1) + if(direction == 1 || direction == 2) + return timeleft else - return SHUTTLEARRIVETIME + return SHUTTLEARRIVETIME-timeleft + else + return SHUTTLEARRIVETIME // sets the time left to a given delay (in seconds) - proc/settimeleft(var/delay) - endtime = world.timeofday + delay * 10 - timelimit = delay +datum/shuttle_controller/proc/settimeleft(var/delay) + endtime = world.timeofday + delay * 10 + timelimit = delay // sets the shuttle direction // 1 = towards SS13, -1 = back to centcom - proc/setdirection(var/dirn) - if(direction == dirn) - return - direction = dirn - // if changing direction, flip the timeleft by SHUTTLEARRIVETIME - var/ticksleft = endtime - world.timeofday - endtime = world.timeofday + (SHUTTLEARRIVETIME*10 - ticksleft) +datum/shuttle_controller/proc/setdirection(var/dirn) + if(direction == dirn) return + direction = dirn + // if changing direction, flip the timeleft by SHUTTLEARRIVETIME + var/ticksleft = endtime - world.timeofday + endtime = world.timeofday + (SHUTTLEARRIVETIME*10 - ticksleft) + return - proc/process() +datum/shuttle_controller/proc/process() - emergency_shuttle - process() - if(!online) - return - var/timeleft = timeleft() - if(timeleft > 1e5) // midnight rollover protection - timeleft = 0 - switch(location) - if(0) +datum/shuttle_controller/emergency_shuttle/process() + if(!online) + return + var/timeleft = timeleft() + if(timeleft > 1e5) // midnight rollover protection + timeleft = 0 + switch(location) + if(0) - /* --- Shuttle is in transit to Central Command from SS13 --- */ - if(direction == 2) - if(timeleft>0) - return 0 + /* --- Shuttle is in transit to Central Command from SS13 --- */ + if(direction == 2) + if(timeleft>0) + return 0 - /* --- Shuttle has arrived at Centrcal Command --- */ - else - // turn off the star spawners - /* - for(var/obj/effect/starspawner/S in world) - S.spawning = 0 - */ + /* --- Shuttle has arrived at Centrcal Command --- */ + else + // turn off the star spawners + /* + for(var/obj/effect/starspawner/S in world) + S.spawning = 0 + */ - location = 2 + location = 2 - //main shuttle - var/area/start_location = locate(/area/shuttle/escape/transit) - var/area/end_location = locate(/area/shuttle/escape/centcom) + //main shuttle + var/area/start_location = locate(/area/shuttle/escape/transit) + var/area/end_location = locate(/area/shuttle/escape/centcom) - start_location.move_contents_to(end_location, null, NORTH) + start_location.move_contents_to(end_location, null, NORTH) - for(var/obj/machinery/door/unpowered/D in machines) - if( get_area(D) == end_location ) - spawn(0) - D.locked = 0 - D.open() + for(var/obj/machinery/door/unpowered/shuttle/D in end_location) + spawn(0) + D.locked = 0 + D.open() - for(var/mob/M in end_location) - if(M.client) - spawn(0) - if(M.buckled) - shake_camera(M, 4, 1) // buckled, not a lot of shaking - else - shake_camera(M, 10, 2) // unbuckled, HOLY SHIT SHAKE THE ROOM - if(istype(M, /mob/living/carbon)) - if(!M.buckled) - M.Weaken(5) + for(var/mob/M in end_location) + if(M.client) + spawn(0) + if(M.buckled) + shake_camera(M, 4, 1) // buckled, not a lot of shaking + else + shake_camera(M, 10, 2) // unbuckled, HOLY SHIT SHAKE THE ROOM + if(istype(M, /mob/living/carbon)) + if(!M.buckled) + M.Weaken(5) //pods - start_location = locate(/area/shuttle/escape_pod1/transit) - end_location = locate(/area/shuttle/escape_pod1/centcom) - start_location.move_contents_to(end_location, null, NORTH) + start_location = locate(/area/shuttle/escape_pod1/transit) + end_location = locate(/area/shuttle/escape_pod1/centcom) + start_location.move_contents_to(end_location, null, NORTH) - for(var/obj/machinery/door/D in machines) - if( get_area(D) == end_location ) - spawn(0) - D.open() + for(var/obj/machinery/door/D in machines) + if( get_area(D) == end_location ) + spawn(0) + D.open() - for(var/mob/M in end_location) - if(M.client) - spawn(0) - if(M.buckled) - shake_camera(M, 4, 1) // buckled, not a lot of shaking - else - shake_camera(M, 10, 2) // unbuckled, HOLY SHIT SHAKE THE ROOM - if(istype(M, /mob/living/carbon)) - if(!M.buckled) - M.Weaken(5) + for(var/mob/M in end_location) + if(M.client) + spawn(0) + if(M.buckled) + shake_camera(M, 4, 1) // buckled, not a lot of shaking + else + shake_camera(M, 10, 2) // unbuckled, HOLY SHIT SHAKE THE ROOM + if(istype(M, /mob/living/carbon)) + if(!M.buckled) + M.Weaken(5) - start_location = locate(/area/shuttle/escape_pod2/transit) - end_location = locate(/area/shuttle/escape_pod2/centcom) - start_location.move_contents_to(end_location, null, NORTH) + start_location = locate(/area/shuttle/escape_pod2/transit) + end_location = locate(/area/shuttle/escape_pod2/centcom) + start_location.move_contents_to(end_location, null, NORTH) - for(var/obj/machinery/door/D in machines) - if( get_area(D) == end_location ) - spawn(0) - D.open() + for(var/obj/machinery/door/D in machines) + if( get_area(D) == end_location ) + spawn(0) + D.open() - for(var/mob/M in end_location) - if(M.client) - spawn(0) - if(M.buckled) - shake_camera(M, 4, 1) // buckled, not a lot of shaking - else - shake_camera(M, 10, 2) // unbuckled, HOLY SHIT SHAKE THE ROOM - if(istype(M, /mob/living/carbon)) - if(!M.buckled) - M.Weaken(5) + for(var/mob/M in end_location) + if(M.client) + spawn(0) + if(M.buckled) + shake_camera(M, 4, 1) // buckled, not a lot of shaking + else + shake_camera(M, 10, 2) // unbuckled, HOLY SHIT SHAKE THE ROOM + if(istype(M, /mob/living/carbon)) + if(!M.buckled) + M.Weaken(5) - start_location = locate(/area/shuttle/escape_pod3/transit) - end_location = locate(/area/shuttle/escape_pod3/centcom) - start_location.move_contents_to(end_location, null, NORTH) + start_location = locate(/area/shuttle/escape_pod3/transit) + end_location = locate(/area/shuttle/escape_pod3/centcom) + start_location.move_contents_to(end_location, null, NORTH) - for(var/obj/machinery/door/D in machines) - if( get_area(D) == end_location ) - spawn(0) - D.open() + for(var/obj/machinery/door/D in machines) + if( get_area(D) == end_location ) + spawn(0) + D.open() - for(var/mob/M in end_location) - if(M.client) - spawn(0) - if(M.buckled) - shake_camera(M, 4, 1) // buckled, not a lot of shaking - else - shake_camera(M, 10, 2) // unbuckled, HOLY SHIT SHAKE THE ROOM - if(istype(M, /mob/living/carbon)) - if(!M.buckled) - M.Weaken(5) + for(var/mob/M in end_location) + if(M.client) + spawn(0) + if(M.buckled) + shake_camera(M, 4, 1) // buckled, not a lot of shaking + else + shake_camera(M, 10, 2) // unbuckled, HOLY SHIT SHAKE THE ROOM + if(istype(M, /mob/living/carbon)) + if(!M.buckled) + M.Weaken(5) - start_location = locate(/area/shuttle/escape_pod5/transit) - end_location = locate(/area/shuttle/escape_pod5/centcom) - start_location.move_contents_to(end_location, null, EAST) + start_location = locate(/area/shuttle/escape_pod5/transit) + end_location = locate(/area/shuttle/escape_pod5/centcom) + start_location.move_contents_to(end_location, null, EAST) - for(var/obj/machinery/door/D in machines) - if( get_area(D) == end_location ) - spawn(0) - D.open() + for(var/obj/machinery/door/D in machines) + if( get_area(D) == end_location ) + spawn(0) + D.open() - for(var/mob/M in end_location) - if(M.client) - spawn(0) - if(M.buckled) - shake_camera(M, 4, 1) // buckled, not a lot of shaking - else - shake_camera(M, 10, 2) // unbuckled, HOLY SHIT SHAKE THE ROOM - if(istype(M, /mob/living/carbon)) - if(!M.buckled) - M.Weaken(5) + for(var/mob/M in end_location) + if(M.client) + spawn(0) + if(M.buckled) + shake_camera(M, 4, 1) // buckled, not a lot of shaking + else + shake_camera(M, 10, 2) // unbuckled, HOLY SHIT SHAKE THE ROOM + if(istype(M, /mob/living/carbon)) + if(!M.buckled) + M.Weaken(5) - online = 0 + online = 0 - return 1 + return 1 /* --- Shuttle has docked centcom after being recalled --- */ - if(timeleft>timelimit) - online = 0 - direction = 1 - endtime = null + if(timeleft>timelimit) + online = 0 + direction = 1 + endtime = null - return 0 + return 0 - else if((fake_recall != 0) && (timeleft <= fake_recall)) - recall() - fake_recall = 0 - return 0 + else if((fake_recall != 0) && (timeleft <= fake_recall)) + recall() + fake_recall = 0 + return 0 /* --- Shuttle has docked with the station - begin countdown to transit --- */ - else if(timeleft <= 0) - location = 1 - var/area/start_location = locate(/area/shuttle/escape/centcom) - var/area/end_location = locate(/area/shuttle/escape/station) + else if(timeleft <= 0) + location = 1 + var/area/start_location = locate(/area/shuttle/escape/centcom) + var/area/end_location = locate(/area/shuttle/escape/station) - var/list/dstturfs = list() - var/throwy = world.maxy + var/list/dstturfs = list() + var/throwy = world.maxy - for(var/turf/T in end_location) - dstturfs += T - if(T.y < throwy) - throwy = T.y + for(var/turf/T in end_location) + dstturfs += T + if(T.y < throwy) + throwy = T.y - // hey you, get out of the way! - for(var/turf/T in dstturfs) - // find the turf to move things to - var/turf/D = locate(T.x, throwy - 1, 1) - //var/turf/E = get_step(D, SOUTH) - for(var/atom/movable/AM as mob|obj in T) - AM.Move(D) - // NOTE: Commenting this out to avoid recreating mass driver glitch - /* - spawn(0) - AM.throw_at(E, 1, 1) - return - */ - - if(istype(T, /turf/simulated)) - del(T) - - for(var/mob/living/carbon/bug in end_location) // If someone somehow is still in the shuttle's docking area... - bug.gib() - - for(var/mob/living/simple_animal/pest in end_location) // And for the other kind of bug... - pest.gib() - - start_location.move_contents_to(end_location) - settimeleft(SHUTTLELEAVETIME) - //send2irc("Server", "The Emergency Shuttle has docked with the station.") - captain_announce("The Emergency Shuttle has docked with the station. You have [round(timeleft()/60,1)] minutes to board the Emergency Shuttle.") - world << sound('sound/AI/shuttledock.ogg') - - return 1 - - if(1) - - // Just before it leaves, close the damn doors! - if(timeleft == 2 || timeleft == 1) - var/area/start_location = locate(/area/shuttle/escape/station) - for(var/obj/machinery/door/unpowered/shuttle/D in start_location) - spawn(0) - D.close() - D.locked = 1 - - if(timeleft>0) - return 0 - - /* --- Shuttle leaves the station, enters transit --- */ - else - - // Turn on the star effects - - /* // kinda buggy atm, i'll fix this later - for(var/obj/effect/starspawner/S in world) - if(!S.spawning) - spawn() S.startspawn() + // hey you, get out of the way! + for(var/turf/T in dstturfs) + // find the turf to move things to + var/turf/D = locate(T.x, throwy - 1, 1) + //var/turf/E = get_step(D, SOUTH) + for(var/atom/movable/AM as mob|obj in T) + AM.Move(D) + // NOTE: Commenting this out to avoid recreating mass driver glitch + /* + spawn(0) + AM.throw_at(E, 1, 1) + return */ - departed = 1 // It's going! - location = 0 // in deep space - direction = 2 // heading to centcom + if(istype(T, /turf/simulated)) + del(T) - //main shuttle - var/area/start_location = locate(/area/shuttle/escape/station) - var/area/end_location = locate(/area/shuttle/escape/transit) + for(var/mob/living/carbon/bug in end_location) // If someone somehow is still in the shuttle's docking area... + bug.gib() - settimeleft(SHUTTLETRANSITTIME) - start_location.move_contents_to(end_location, null, NORTH) + for(var/mob/living/simple_animal/pest in end_location) // And for the other kind of bug... + pest.gib() + + start_location.move_contents_to(end_location) + settimeleft(SHUTTLELEAVETIME) + //send2irc("Server", "The Emergency Shuttle has docked with the station.") + captain_announce("The Emergency Shuttle has docked with the station. You have [round(timeleft()/60,1)] minutes to board the Emergency Shuttle.") + world << sound('sound/AI/shuttledock.ogg') + + return 1 + + if(1) + + // Just before it leaves, close the damn doors! + if(timeleft == 2 || timeleft == 1) + var/area/start_location = locate(/area/shuttle/escape/station) + for(var/obj/machinery/door/unpowered/shuttle/D in start_location) + spawn(0) + D.close() + D.locked = 1 + + if(timeleft>0) + return 0 + + /* --- Shuttle leaves the station, enters transit --- */ + else + + // Turn on the star effects + + /* // kinda buggy atm, i'll fix this later + for(var/obj/effect/starspawner/S in world) + if(!S.spawning) + spawn() S.startspawn() + */ + + departed = 1 // It's going! + location = 0 // in deep space + direction = 2 // heading to centcom + + //main shuttle + var/area/start_location = locate(/area/shuttle/escape/station) + var/area/end_location = locate(/area/shuttle/escape/transit) + + settimeleft(SHUTTLETRANSITTIME) + start_location.move_contents_to(end_location, null, NORTH) + + // Close shuttle doors, lock + for(var/obj/machinery/door/unpowered/shuttle/D in end_location) + spawn(0) + D.close() + D.locked = 1 - for(var/obj/machinery/door/D in end_location) - spawn(0) - D.close() // Some aesthetic turbulance shaking - for(var/mob/M in end_location) - if(M.client) - spawn(0) - if(M.buckled) - shake_camera(M, 4, 1) // buckled, not a lot of shaking - else - shake_camera(M, 10, 2) // unbuckled, HOLY SHIT SHAKE THE ROOM - if(istype(M, /mob/living/carbon)) - if(!M.buckled) - M.Weaken(5) + for(var/mob/M in end_location) + if(M.client) + spawn(0) + if(M.buckled) + shake_camera(M, 4, 1) // buckled, not a lot of shaking + else + shake_camera(M, 10, 2) // unbuckled, HOLY SHIT SHAKE THE ROOM + if(istype(M, /mob/living/carbon)) + if(!M.buckled) + M.Weaken(5) - //pods - start_location = locate(/area/shuttle/escape_pod1/station) - end_location = locate(/area/shuttle/escape_pod1/transit) - start_location.move_contents_to(end_location, null, NORTH) - for(var/obj/machinery/door/D in end_location) - spawn(0) - D.close() + //pods + start_location = locate(/area/shuttle/escape_pod1/station) + end_location = locate(/area/shuttle/escape_pod1/transit) + start_location.move_contents_to(end_location, null, NORTH) + for(var/obj/machinery/door/D in end_location) + spawn(0) + D.close() - for(var/mob/M in end_location) - if(M.client) - spawn(0) - if(M.buckled) - shake_camera(M, 4, 1) // buckled, not a lot of shaking - else - shake_camera(M, 10, 2) // unbuckled, HOLY SHIT SHAKE THE ROOM - if(istype(M, /mob/living/carbon)) - if(!M.buckled) - M.Weaken(5) + for(var/mob/M in end_location) + if(M.client) + spawn(0) + if(M.buckled) + shake_camera(M, 4, 1) // buckled, not a lot of shaking + else + shake_camera(M, 10, 2) // unbuckled, HOLY SHIT SHAKE THE ROOM + if(istype(M, /mob/living/carbon)) + if(!M.buckled) + M.Weaken(5) - start_location = locate(/area/shuttle/escape_pod2/station) - end_location = locate(/area/shuttle/escape_pod2/transit) - start_location.move_contents_to(end_location, null, NORTH) - for(var/obj/machinery/door/D in end_location) - spawn(0) - D.close() + start_location = locate(/area/shuttle/escape_pod2/station) + end_location = locate(/area/shuttle/escape_pod2/transit) + start_location.move_contents_to(end_location, null, NORTH) + for(var/obj/machinery/door/D in end_location) + spawn(0) + D.close() - for(var/mob/M in end_location) - if(M.client) - spawn(0) - if(M.buckled) - shake_camera(M, 4, 1) // buckled, not a lot of shaking - else - shake_camera(M, 10, 2) // unbuckled, HOLY SHIT SHAKE THE ROOM - if(istype(M, /mob/living/carbon)) - if(!M.buckled) - M.Weaken(5) + for(var/mob/M in end_location) + if(M.client) + spawn(0) + if(M.buckled) + shake_camera(M, 4, 1) // buckled, not a lot of shaking + else + shake_camera(M, 10, 2) // unbuckled, HOLY SHIT SHAKE THE ROOM + if(istype(M, /mob/living/carbon)) + if(!M.buckled) + M.Weaken(5) - start_location = locate(/area/shuttle/escape_pod3/station) - end_location = locate(/area/shuttle/escape_pod3/transit) - start_location.move_contents_to(end_location, null, NORTH) - for(var/obj/machinery/door/D in end_location) - spawn(0) - D.close() + start_location = locate(/area/shuttle/escape_pod3/station) + end_location = locate(/area/shuttle/escape_pod3/transit) + start_location.move_contents_to(end_location, null, NORTH) + for(var/obj/machinery/door/D in end_location) + spawn(0) + D.close() - for(var/mob/M in end_location) - if(M.client) - spawn(0) - if(M.buckled) - shake_camera(M, 4, 1) // buckled, not a lot of shaking - else - shake_camera(M, 10, 2) // unbuckled, HOLY SHIT SHAKE THE ROOM - if(istype(M, /mob/living/carbon)) - if(!M.buckled) - M.Weaken(5) + for(var/mob/M in end_location) + if(M.client) + spawn(0) + if(M.buckled) + shake_camera(M, 4, 1) // buckled, not a lot of shaking + else + shake_camera(M, 10, 2) // unbuckled, HOLY SHIT SHAKE THE ROOM + if(istype(M, /mob/living/carbon)) + if(!M.buckled) + M.Weaken(5) - start_location = locate(/area/shuttle/escape_pod5/station) - end_location = locate(/area/shuttle/escape_pod5/transit) - start_location.move_contents_to(end_location, null, EAST) - for(var/obj/machinery/door/D in end_location) - spawn(0) - D.close() + start_location = locate(/area/shuttle/escape_pod5/station) + end_location = locate(/area/shuttle/escape_pod5/transit) + start_location.move_contents_to(end_location, null, EAST) + for(var/obj/machinery/door/D in end_location) + spawn(0) + D.close() - for(var/mob/M in end_location) - if(M.client) - spawn(0) - if(M.buckled) - shake_camera(M, 4, 1) // buckled, not a lot of shaking - else - shake_camera(M, 10, 2) // unbuckled, HOLY SHIT SHAKE THE ROOM - if(istype(M, /mob/living/carbon)) - if(!M.buckled) - M.Weaken(5) + for(var/mob/M in end_location) + if(M.client) + spawn(0) + if(M.buckled) + shake_camera(M, 4, 1) // buckled, not a lot of shaking + else + shake_camera(M, 10, 2) // unbuckled, HOLY SHIT SHAKE THE ROOM + if(istype(M, /mob/living/carbon)) + if(!M.buckled) + M.Weaken(5) - captain_announce("The Emergency Shuttle has left the station. Estimate [round(timeleft()/60,1)] minutes until the shuttle docks at Central Command.") + captain_announce("The Emergency Shuttle has left the station. Estimate [round(timeleft()/60,1)] minutes until the shuttle docks at Central Command.") - return 1 + return 1 - else - return 1 + else + return 1 /* @@ -434,23 +435,23 @@ datum/shuttle_controller var/direction = SOUTH layer = 2 // TURF_LAYER - New() - ..() - pixel_x += rand(-2,30) - pixel_y += rand(-2,30) - var/starnum = pick("1", "1", "1", "2", "3", "4") +/obj/effect/bgstar/New() + ..() + pixel_x += rand(-2,30) + pixel_y += rand(-2,30) + var/starnum = pick("1", "1", "1", "2", "3", "4") - icon_state = "star"+starnum + icon_state = "star"+starnum - speed = rand(2, 5) + speed = rand(2, 5) - proc/startmove() +/obj/effect/bgstar/proc/startmove() - while(src) - sleep(speed) - step(src, direction) - for(var/obj/effect/starender/E in loc) - del(src) + while(src) + sleep(speed) + step(src, direction) + for(var/obj/effect/starender/E in loc) + del(src) /obj/effect/starender @@ -461,16 +462,16 @@ datum/shuttle_controller var/spawndir = SOUTH var/spawning = 0 - West - spawndir = WEST +/obj/effect/starspawner/West + spawndir = WEST - proc/startspawn() - spawning = 1 - while(spawning) - sleep(rand(2, 30)) - var/obj/effect/bgstar/S = new/obj/effect/bgstar(locate(x,y,z)) - S.direction = spawndir - spawn() - S.startmove() +/obj/effect/starspawner/proc/startspawn() + spawning = 1 + while(spawning) + sleep(rand(2, 30)) + var/obj/effect/bgstar/S = new/obj/effect/bgstar(locate(x,y,z)) + S.direction = spawndir + spawn() + S.startmove() diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index 904761eba83..1a7d97e99cf 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -58,6 +58,10 @@ G.fields["sex"] = H.gender G.fields["species"] = H.get_species() G.fields["photo"] = get_id_photo(H) + if(H.gen_record && !jobban_isbanned(H, "Records")) + G.fields["notes"] = H.gen_record + else + G.fields["notes"] = "No notes found." general += G //Medical Record @@ -119,20 +123,7 @@ proc/get_id_photo(var/mob/living/carbon/human/H) if (H.gender == FEMALE) g = "f" - var/icon/icobase - switch(H.get_species()) - if("Tajaran") - icobase = 'icons/mob/human_races/r_tajaran.dmi' - if("Unathi") - icobase = 'icons/mob/human_races/r_lizard.dmi' - if("Skrell") - icobase = 'icons/mob/human_races/r_skrell.dmi' - - if("Vox") - icobase = 'icons/mob/human_races/r_vox.dmi' - - else - icobase = 'icons/mob/human_races/r_human.dmi' + var/icon/icobase = H.species.icobase preview_icon = new /icon(icobase, "torso_[g]") var/icon/temp @@ -149,15 +140,13 @@ proc/get_id_photo(var/mob/living/carbon/human/H) preview_icon.Blend(temp, ICON_OVERLAY) // Skin tone - if(H.get_species() == "Human") + if(H.species.flags & HAS_SKIN_TONE) if (H.s_tone >= 0) preview_icon.Blend(rgb(H.s_tone, H.s_tone, H.s_tone), ICON_ADD) else preview_icon.Blend(rgb(-H.s_tone, -H.s_tone, -H.s_tone), ICON_SUBTRACT) - var/icon/eyes_s = new/icon("icon" = 'icons/mob/human_face.dmi', "icon_state" = "eyes_s") - if(H.get_species()=="Vox") - eyes_s = new/icon("icon" = 'icons/mob/human_face.dmi', "icon_state" = "vox_eyes_s") + var/icon/eyes_s = new/icon("icon" = 'icons/mob/human_face.dmi', "icon_state" = H.species ? H.species.eyes : "eyes_s") eyes_s.Blend(rgb(H.r_eyes, H.g_eyes, H.b_eyes), ICON_ADD) diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index 81abf92546a..517c6d0931e 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -256,9 +256,12 @@ client body += "" body += "" + body += "" + body += "" if(ishuman(D)) body += "" body += "" + body += "" body += "" body += "" body += "" @@ -743,6 +746,67 @@ client H.dna.mutantrace = new_mutantrace H.update_mutantrace() + else if(href_list["setspecies"]) + if(!check_rights(R_SPAWN)) return + + var/mob/living/carbon/human/H = locate(href_list["setspecies"]) + if(!istype(H)) + usr << "This can only be done to instances of type /mob/living/carbon/human" + return + + var/new_species = input("Please choose a new species.","Species",null) as null|anything in all_species + + if(!H) + usr << "Mob doesn't exist anymore" + return + + if(H.set_species(new_species)) + usr << "Set species of [H] to [H.species]." + else + usr << "Failed! Something went wrong." + + else if(href_list["addlanguage"]) + if(!check_rights(R_SPAWN)) return + + var/mob/H = locate(href_list["addlanguage"]) + if(!istype(H)) + usr << "This can only be done to instances of type /mob" + return + + var/new_language = input("Please choose a language to add.","Language",null) as null|anything in all_languages + + if(!H) + usr << "Mob doesn't exist anymore" + return + + if(H.add_language(new_language)) + usr << "Added [new_language] to [H]." + else + usr << "Mob already knows that language." + + else if(href_list["remlanguage"]) + if(!check_rights(R_SPAWN)) return + + var/mob/H = locate(href_list["remlanguage"]) + if(!istype(H)) + usr << "This can only be done to instances of type /mob" + return + + if(!H.languages.len) + usr << "This mob knows no languages." + return + + var/datum/language/rem_language = input("Please choose a language to remove.","Language",null) as null|anything in H.languages + + if(!H) + usr << "Mob doesn't exist anymore" + return + + if(H.remove_language(rem_language.name)) + usr << "Removed [rem_language] from [H]." + else + usr << "Mob doesn't know that language." + else if(href_list["regenerateicons"]) if(!check_rights(0)) return diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index 57ddf7817e5..b3b03e6ac26 100755 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -356,10 +356,12 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee /obj/item/weapon/storage/firstaid/fire, /obj/item/weapon/storage/firstaid/toxin, /obj/item/weapon/storage/firstaid/o2, + /obj/item/weapon/storage/firstaid/adv, /obj/item/weapon/reagent_containers/glass/bottle/antitoxin, /obj/item/weapon/reagent_containers/glass/bottle/inaprovaline, /obj/item/weapon/reagent_containers/glass/bottle/stoxin, - /obj/item/weapon/storage/box/syringes) + /obj/item/weapon/storage/box/syringes, + /obj/item/weapon/storage/box/autoinjectors) cost = 10 containertype = /obj/structure/closet/crate/medical containername = "Medical crate" diff --git a/code/defines/obj.dm b/code/defines/obj.dm index 661f4c43b38..a4ef521d9d7 100644 --- a/code/defines/obj.dm +++ b/code/defines/obj.dm @@ -51,7 +51,7 @@ //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) + proc/get_manifest(monochrome, OOC) var/list/heads = new() var/list/sec = new() var/list/eng = new() @@ -80,7 +80,15 @@ var/name = t.fields["name"] var/rank = t.fields["rank"] var/real_rank = t.fields["real_rank"] - isactive[name] = t.fields["p_stat"] + 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]" diff --git a/code/defines/obj/hydro.dm b/code/defines/obj/hydro.dm index 9e26cb48fdb..bfea9a3b22b 100644 --- a/code/defines/obj/hydro.dm +++ b/code/defines/obj/hydro.dm @@ -81,30 +81,6 @@ plant_type = 2 growthstages = 3 -/obj/item/seeds/replicapod - name = "pack of replica pod seeds" - desc = "These seeds grow into replica pods. They say these are used to harvest humans." - icon_state = "seed-replicapod" - mypath = "/obj/item/seeds/replicapod" - species = "replicapod" - plantname = "Replica Pod" - productname = "/mob/living/carbon/human" //verrry special -- Urist - lifespan = 50 //no idea what those do - endurance = 8 - maturation = 10 - production = 10 - yield = 1 //seeds if there isn't a dna inside - oneharvest = 1 - potency = 30 - plant_type = 0 - growthstages = 6 - var/ui = null //for storing the guy - var/se = null - var/ckey = null - var/realName = null - var/datum/mind/mind = null - gender = MALE - /obj/item/seeds/grapeseed name = "pack of grape seeds" desc = "These seeds grow into grape vines." diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm index bd57ca478c4..5064113e153 100644 --- a/code/defines/obj/weapon.dm +++ b/code/defines/obj/weapon.dm @@ -557,6 +557,13 @@ playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) return ..() +/obj/item/weapon/hatchet/unathiknife + name = "duelling knife" + desc = "A length of leather-bound wood studded with razor-sharp teeth. How crude." + icon = 'icons/obj/weapons.dmi' + icon_state = "unathiknife" + attack_verb = list("ripped", "torn", "cut") + /obj/item/weapon/scythe icon_state = "scythe0" name = "scythe" diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index 049d7f0cd70..fd034fbf5ae 100755 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -309,6 +309,11 @@ proc/process_ghost_teleport_locs() /area/shuttle/research/outpost icon_state = "shuttle" +/area/shuttle/vox/station + name = "\improper Vox Skipjack" + icon_state = "yellow" + requires_power = 0 + /area/airtunnel1/ // referenced in airtunnel.dm:759 /area/dummy/ // Referenced in engine.dm:261 @@ -489,10 +494,29 @@ proc/process_ghost_teleport_locs() icon_state = "yellow" requires_power = 0 +/area/vox_station/transit + name = "\improper hyperspace" + icon_state = "shuttle" +/area/vox_station/southwest_solars + name = "\improper aft port solars" + icon_state = "southwest" +/area/vox_station/northwest_solars + name = "\improper fore port solars" + icon_state = "northwest" +/area/vox_station/northeast_solars + name = "\improper fore starboard solars" + icon_state = "northeast" +/area/vox_station/southeast_solars + name = "\improper aft starboard solars" + icon_state = "southeast" + +/area/vox_station/mining + name = "\improper nearby mining asteroid" + icon_state = "north" //PRISON /area/prison diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index c0921cd54a1..6695fe44027 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -45,8 +45,13 @@ poweralm = state if(istype(source)) //Only report power alarms on the z-level where the source is located. var/list/cameras = list() - for (var/obj/machinery/camera/C in src) - cameras += C + for (var/area/RA in related) + for (var/obj/machinery/camera/C in RA) + cameras += C + if(state == 1) + C.network.Remove("Power Alarms") + else + C.network.Add("Power Alarms") for (var/mob/living/silicon/aiPlayer in player_list) if(aiPlayer.z == source.z) if (state == 1) @@ -73,11 +78,15 @@ //updateicon() for(var/obj/machinery/camera/C in RA) cameras += C + C.network.Add("Atmosphere Alarms") for(var/mob/living/silicon/aiPlayer in player_list) aiPlayer.triggerAlarm("Atmosphere", src, cameras, src) for(var/obj/machinery/computer/station_alert/a in machines) a.triggerAlarm("Atmosphere", src, cameras, src) else if (atmosalm == 2) + for(var/area/RA in related) + for(var/obj/machinery/camera/C in RA) + C.network.Remove("Atmosphere Alarms") for(var/mob/living/silicon/aiPlayer in player_list) aiPlayer.cancelAlarm("Atmosphere", src, src) for(var/obj/machinery/computer/station_alert/a in machines) @@ -101,8 +110,10 @@ spawn() D.close() var/list/cameras = list() - for (var/obj/machinery/camera/C in src) - cameras += C + for(var/area/RA in related) + for (var/obj/machinery/camera/C in RA) + cameras.Add(C) + C.network.Add("Fire Alarms") for (var/mob/living/silicon/ai/aiPlayer in player_list) aiPlayer.triggerAlarm("Fire", src, cameras, src) for (var/obj/machinery/computer/station_alert/a in machines) @@ -120,6 +131,9 @@ 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") for (var/mob/living/silicon/ai/aiPlayer in player_list) aiPlayer.cancelAlarm("Fire", src, src) for (var/obj/machinery/computer/station_alert/a in machines) diff --git a/code/game/communications.dm b/code/game/communications.dm index 94d53f6bf52..32d8ca69348 100644 --- a/code/game/communications.dm +++ b/code/game/communications.dm @@ -74,7 +74,6 @@ Radio: 1359 - Security 1441 - death squad 1443 - Confession Intercom -1349 - Miners 1347 - Cargo techs Devices: @@ -110,10 +109,21 @@ var/list/radiochannels = list( "Supply" = 1347, ) //depenging helpers -var/list/DEPT_FREQS = list(1351,1355,1357,1359,1213, 1443, 1441,1347) +var/list/DEPT_FREQS = list(1351, 1355, 1357, 1359, 1213, 1443, 1441, 1347) + +// central command channels, i.e deathsquid & response teams +var/list/CENT_FREQS = list(1441, 1443) + var/const/COMM_FREQ = 1353 //command, colored gold in chat window var/const/SYND_FREQ = 1213 +// department channels +var/const/SEC_FREQ = 1359 +var/const/ENG_FREQ = 1357 +var/const/SCI_FREQ = 1351 +var/const/MED_FREQ = 1355 +var/const/SUP_FREQ = 1347 + #define TRANSMISSION_WIRE 0 #define TRANSMISSION_RADIO 1 diff --git a/code/game/dna.dm b/code/game/dna.dm index cb58013e016..13f90e7d506 100644 --- a/code/game/dna.dm +++ b/code/game/dna.dm @@ -550,15 +550,11 @@ var/mob/living/carbon/monkey/O = null - switch(M.dna.mutantrace) - if("tajaran") - O = new /mob/living/carbon/monkey/tajara(src) - if("lizard") - O = new /mob/living/carbon/monkey/unathi(src) - if("skrell") - O = new /mob/living/carbon/monkey/skrell(src) - else - O = new /mob/living/carbon/monkey(src) + if(H.species.primitive) + O = new H.species.primitive(src) + else + H.gib() //Trying to change the species of a creature with no primitive var set is messy. + return if(M) if (M.dna) @@ -626,6 +622,9 @@ del(animation) var/mob/living/carbon/human/O = new( src ) + if(Mo.greaterform) + O.set_species(Mo.greaterform) + if (isblockon(getblock(M.dna.uni_identity, 11,3),11)) O.gender = FEMALE else diff --git a/code/game/gamemodes/autotraitor/autotraitor.dm b/code/game/gamemodes/autotraitor/autotraitor.dm index 74bced44214..de795b19222 100644 --- a/code/game/gamemodes/autotraitor/autotraitor.dm +++ b/code/game/gamemodes/autotraitor/autotraitor.dm @@ -4,7 +4,7 @@ /datum/game_mode/traitor/autotraitor name = "AutoTraitor" - config_tag = "Extend-A-Traitormongous" + config_tag = "extend-a-traitormongous" var/list/possible_traitors var/num_players = 0 diff --git a/code/game/gamemodes/blob/blob.dm b/code/game/gamemodes/blob/blob.dm index 7cca20dfac0..e53053764b2 100644 --- a/code/game/gamemodes/blob/blob.dm +++ b/code/game/gamemodes/blob/blob.dm @@ -6,7 +6,7 @@ var/list/blob_cores = list() var/list/blob_nodes = list() -/datum/game_mode/blob +/*/datum/game_mode/blob name = "blob" config_tag = "blob" required_players = 0 @@ -130,3 +130,4 @@ var/list/blob_nodes = list() stage = 3 return +*/ \ No newline at end of file diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm index 93d54a56550..29dcc13a03f 100644 --- a/code/game/gamemodes/changeling/changeling_powers.dm +++ b/code/game/gamemodes/changeling/changeling_powers.dm @@ -186,6 +186,7 @@ changeling.geneticdamage = 30 src.dna = chosen_dna src.real_name = chosen_dna.real_name + src.flavor_text = "" updateappearance(src, src.dna.uni_identity) domutcheck(src, null) diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index 9366cd00523..e5be5d60a7a 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -271,21 +271,7 @@ var/list/sacrificed = list() usr << "\red You require a restless spirit which clings to this world. Beckon their prescence with the sacred chants of Nar-Sie." return fizzle() - for(var/datum/organ/external/affecting in corpse_to_raise.organs) - affecting.heal_damage(1000, 1000) - corpse_to_raise.setToxLoss(0) - corpse_to_raise.setOxyLoss(0) - corpse_to_raise.SetParalysis(0) - corpse_to_raise.SetStunned(0) - corpse_to_raise.SetWeakened(0) - corpse_to_raise.radiation = 0 -// corpse_to_raise.buckled = null -// if(corpse_to_raise.handcuffed) -// del(corpse_to_raise.handcuffed) -// corpse_to_raise.update_inv_handcuffed(0) - corpse_to_raise.stat = CONSCIOUS - corpse_to_raise.updatehealth() - corpse_to_raise.UpdateDamageIcon() + corpse_to_raise.revive() corpse_to_raise.key = ghost.key //the corpse will keep its old mind! but a new player takes ownership of it (they are essentially possessed) //This means, should that player leave the body, the original may re-enter @@ -389,7 +375,7 @@ var/list/sacrificed = list() var/chose_name = 0 for(var/obj/item/weapon/paper/P in this_rune.loc) if(P.info) - D.real_name = copytext(P.info, 1, MAX_NAME_LEN) + D.real_name = copytext(P.info, findtext(P.info,">")+1, findtext(P.info,"<",2) ) chose_name = 1 break if(!chose_name) diff --git a/code/game/gamemodes/epidemic/epidemic.dm b/code/game/gamemodes/epidemic/epidemic.dm index 0d4a20ff2fe..60701479e1a 100644 --- a/code/game/gamemodes/epidemic/epidemic.dm +++ b/code/game/gamemodes/epidemic/epidemic.dm @@ -124,14 +124,15 @@ for(var/i = 0, i < lethal_amount, i++) var/mob/living/carbon/human/H = pick(crew) - if(H.virus2) + if(lethal.uniqueID in H.virus2) i-- continue - H.virus2 = lethal.getcopy() + H.virus2["[lethal.uniqueID]"] = lethal.getcopy() infectees += H var/mob/living/carbon/human/patient_zero = pick(infectees) - patient_zero.virus2.stage = 3 + var/datum/disease2/disease/V = patient_zero.virus2["[lethal.uniqueID]"] + V.stage = 3 cruiser_arrival = world.time + (10 * 90 * 60) stage = 1 @@ -169,7 +170,7 @@ var/sick = 0 for(var/mob/living/carbon/human/H in world) if(H.key && H.stat != 2) alive++ - if(H.virus2 && H.stat != 2) sick++ + if(H.virus2.len && H.stat != 2) sick++ if(alive == 0) finished = 2 diff --git a/code/game/gamemodes/events/VirusEpidemic.dm b/code/game/gamemodes/events/VirusEpidemic.dm index 72c7b912039..f44b631a207 100644 --- a/code/game/gamemodes/events/VirusEpidemic.dm +++ b/code/game/gamemodes/events/VirusEpidemic.dm @@ -8,7 +8,7 @@ Announce() if(!virus) for(var/mob/living/carbon/human/H in world) - if((H.virus2) || (H.stat == 2) || prob(30)) + if((H.virus2.len) || (H.stat == 2) || prob(30)) continue if(prob(100)) // no lethal diseases outside virus mode! infect_mob_random_lesser(H) diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 85fdca943e9..a78e8dd8ae0 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -17,7 +17,7 @@ var/config_tag = null var/intercept_hacked = 0 var/votable = 1 - var/probability = 1 + var/probability = 0 var/station_was_nuked = 0 //see nuclearbomb.dm and malfunction.dm var/explosion_in_progress = 0 //sit back and relax var/list/datum/mind/modePlayer = new @@ -278,6 +278,7 @@ Implants; if(BE_REV) roletext="revolutionary" if(BE_CULTIST) roletext="cultist" if(BE_NINJA) roletext="ninja" + if(BE_RAIDER) roletext="raider" // Assemble a list of active players without jobbans. for(var/mob/new_player/player in player_list) diff --git a/code/game/gamemodes/heist/heist.dm b/code/game/gamemodes/heist/heist.dm new file mode 100644 index 00000000000..0f1fd97b36f --- /dev/null +++ b/code/game/gamemodes/heist/heist.dm @@ -0,0 +1,259 @@ +/* +VOX HEIST ROUNDTYPE +*/ + +#define MAX_VOX_KILLS 10 //Number of kills during the round before the Inviolate is broken. + //Would be nice to use vox-specific kills but is currently not feasible. + +var/global/vox_kills = 0 //Used to check the Inviolate. + +/datum/game_mode/ + var/list/datum/mind/raiders = list() //Antags. + +/datum/game_mode/heist + name = "heist" + config_tag = "heist" + required_players = 15 + required_players_secret = 25 + required_enemies = 4 + recommended_enemies = 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) + + var/list/raid_objectives = list() //Raid objectives. + var/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' objective. + +/datum/game_mode/heist/announce() + world << "The current game mode is - Heist!" + world << "An unidentified bluespace signature has slipped past the Icarus and is approaching [station_name()]!" + world << "Whoever they are, they're likely up to no good. Protect the crew and station resources against this dastardly threat!" + world << "Raiders: Loot [station_name()] for anything and everything you need." + world << "Personnel: Repel the raiders and their low, low prices and/or crossbows." + +/datum/game_mode/heist/can_start() + + if(!..()) + return 0 + + var/list/candidates = get_players_for_role(BE_RAIDER) + var/raider_num = 0 + + //Check that we have enough vox. + if(candidates.len < required_enemies) + return 0 + else if(candidates.len < recommended_enemies) + raider_num = candidates.len + else + raider_num = recommended_enemies + + //Grab candidates randomly until we have enough. + while(raider_num > 0) + var/datum/mind/new_raider = pick(candidates) + raiders += new_raider + candidates -= new_raider + raider_num-- + + for(var/datum/mind/raider in raiders) + raider.assigned_role = "MODE" + raider.special_role = "Vox Raider" + return 1 + +/datum/game_mode/heist/pre_setup() + return 1 + +/datum/game_mode/heist/post_setup() + + //Build a list of spawn points. + var/list/turf/raider_spawn = list() + + for(var/obj/effect/landmark/L in landmarks_list) + if(L.name == "voxstart") + raider_spawn += get_turf(L) + del(L) + continue + + //Generate objectives for the group. + raid_objectives = forge_vox_objectives() + + var/index = 1 + + //Spawn the vox! + for(var/datum/mind/raider in raiders) + + if(index > raider_spawn.len) + index = 1 + + raider.current.loc = raider_spawn[index] + index++ + + var/sounds = rand(2,8) + var/i = 0 + var/newname = "" + + while(i<=sounds) + i++ + newname += pick(list("ti","hi","ki","ya","ta","ha","ka","ya","chi","cha","kah")) + + var/mob/living/carbon/human/vox = raider.current + + vox.real_name = capitalize(newname) + vox.name = vox.real_name + vox.age = rand(12,20) + vox.dna.mutantrace = "vox" + vox.set_species("Vox") + vox.languages = list() // Removing language from chargen. + vox.flavor_text = "" + vox.add_language("Vox-pidgin") + vox.h_style = "Short Vox Quills" + vox.f_style = "Shaved" + for(var/datum/organ/external/limb in vox.organs) + limb.status &= ~(ORGAN_DESTROYED | ORGAN_ROBOT) + vox.equip_vox_raider() + vox.regenerate_icons() + + raider.objectives = raid_objectives + greet_vox(raider) + + spawn (rand(waittime_l, waittime_h)) + send_intercept() + +/datum/game_mode/heist/proc/is_raider_crew_safe() + + if(cortical_stacks.len == 0) + return 0 + + for(var/obj/stack in cortical_stacks) + if (get_area(stack) != locate(/area/shuttle/vox/station)) + return 0 + return 1 + +/datum/game_mode/heist/proc/is_raider_crew_alive() + + for(var/datum/mind/raider in raiders) + if(raider.current) + if(istype(raider.current,/mob/living/carbon/human) && raider.current.stat != 2) + return 1 + return 0 + +/datum/game_mode/heist/proc/forge_vox_objectives() + + + //Commented out for testing. + /* var/i = 1 + var/max_objectives = pick(2,2,2,3,3) + var/list/objs = list() + while(i<= max_objectives) + var/list/goals = list("kidnap","loot","salvage") + var/goal = pick(goals) + var/datum/objective/heist/O + + if(goal == "kidnap") + goals -= "kidnap" + O = new /datum/objective/heist/kidnap() + else if(goal == "loot") + O = new /datum/objective/heist/loot() + else + O = new /datum/objective/heist/salvage() + O.choose_target() + objs += O + + i++ + + //-All- vox raids have these two objectives. Failing them loses the game. + objs += new /datum/objective/heist/inviolate_crew + objs += new /datum/objective/heist/inviolate_death */ + + raid_objectives += new /datum/objective/heist/kidnap + raid_objectives += new /datum/objective/heist/loot + raid_objectives += new /datum/objective/heist/salvage + raid_objectives += new /datum/objective/heist/inviolate_crew + raid_objectives += new /datum/objective/heist/inviolate_death + + for(var/datum/objective/heist/O in raid_objectives) + O.choose_target() + + return raid_objectives + +/datum/game_mode/heist/proc/greet_vox(var/datum/mind/raider) + raider.current << "\blue You are a Vox Raider, fresh from the Shoal!" + raider.current << "\blue The Vox are a race of cunning, sharp-eyed nomadic raiders and traders endemic to Tau Ceti and much of the unexplored galaxy. You and the crew have come to the Exodus for plunder, trade or both." + raider.current << "\blue Vox are cowardly and will flee from larger groups, but corner one or find them en masse and they are vicious." + raider.current << "\blue Use :V to voxtalk, :H to talk on your encrypted channel, and don't forget to turn on your nitrogen internals!" + var/obj_count = 1 + for(var/datum/objective/objective in raider.objectives) + raider.current << "Objective #[obj_count]: [objective.explanation_text]" + obj_count++ + + +/datum/game_mode/heist/declare_completion() + + //No objectives, go straight to the feedback. + if(!(raid_objectives.len)) return ..() + + var/win_type = "Major" + var/win_group = "Crew" + var/win_msg = "" + + var/success = raid_objectives.len + + //Decrease success for failed objectives. + for(var/datum/objective/O in raid_objectives) + if(!(O.check_completion())) success-- + + //Set result by objectives. + if(success == raid_objectives.len) + win_type = "Major" + win_group = "Vox" + else if(success > 2) + win_type = "Minor" + win_group = "Vox" + else + win_type = "Minor" + win_group = "Crew" + + //Now we modify that result by the state of the vox crew. + if(!is_raider_crew_alive()) + + win_type = "Major" + win_group = "Crew" + win_msg += "The Vox Raiders have been wiped out!" + + else if(!is_raider_crew_safe()) + + if(win_group == "Crew" && win_type == "Minor") + win_type = "Major" + + win_group = "Crew" + win_msg += "The Vox Raiders have left someone behind!" + + else + + if(win_group == "Vox") + if(win_type == "Minor") + + win_type = "Major" + win_msg += "The Vox Raiders escaped the station!" + else + win_msg += "The Vox Raiders were repelled!" + + world << "\red [win_type] [win_group] victory!" + world << "[win_msg]" + feedback_set_details("round_end_result","heist - [win_type] [win_group]") + + var/count = 1 + for(var/datum/objective/objective in raid_objectives) + if(objective.check_completion()) + world << "
Objective #[count]: [objective.explanation_text] Success!" + feedback_add_details("traitor_objective","[objective.type]|SUCCESS") + else + world << "
Objective #[count]: [objective.explanation_text] Fail." + feedback_add_details("traitor_objective","[objective.type]|FAIL") + count++ + + ..() + +/datum/game_mode/heist/check_finished() + if (!(is_raider_crew_alive()) || (vox_shuttle_location && (vox_shuttle_location == "start"))) + return 1 + return ..() \ No newline at end of file diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm index 9d6e12c2223..7480555d694 100644 --- a/code/game/gamemodes/nuclear/nuclearbomb.dm +++ b/code/game/gamemodes/nuclear/nuclearbomb.dm @@ -15,6 +15,8 @@ var/bomb_set var/yes_code = 0.0 var/safety = 1.0 var/obj/item/weapon/disk/nuclear/auth = null + 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 @@ -33,14 +35,83 @@ var/bomb_set src.attack_hand(M) return -/obj/machinery/nuclearbomb/attackby(obj/item/weapon/I as obj, mob/user as mob) +/obj/machinery/nuclearbomb/attackby(obj/item/weapon/O as obj, mob/user as mob) if (src.extended) - if (istype(I, /obj/item/weapon/disk/nuclear)) + if (istype(O, /obj/item/weapon/disk/nuclear)) usr.drop_item() - I.loc = src - src.auth = I + O.loc = src + src.auth = O src.add_fingerprint(user) return + + if (src.anchored) + switch(removal_stage) + if(0) + if(istype(O,/obj/item/weapon/weldingtool)) + + var/obj/item/weapon/weldingtool/WT = O + if(!WT.isOn()) return + if (WT.get_fuel() < 5) // uses up 5 fuel. + user << "\red You need more fuel to complete this task." + return + + user.visible_message("[user] starts cutting loose the anchoring bolt covers on [src].", "You start cutting loose the anchoring bolt covers with [O]...") + + if(do_after(user,40)) + if(!src || !user || !WT.remove_fuel(5, user)) return + user.visible_message("[user] cuts through the bolt covers on [src].", "You cut through the bolt cover.") + removal_stage = 1 + return + + if(1) + if(istype(O,/obj/item/weapon/crowbar)) + user.visible_message("[user] starts forcing open the bolt covers on [src].", "You start forcing open the anchoring bolt covers with [O]...") + + if(do_after(user,15)) + if(!src || !user) return + user.visible_message("[user] forces open the bolt covers on [src].", "You force open the bolt covers.") + removal_stage = 2 + return + + if(2) + if(istype(O,/obj/item/weapon/weldingtool)) + + var/obj/item/weapon/weldingtool/WT = O + if(!WT.isOn()) return + if (WT.get_fuel() < 5) // uses up 5 fuel. + user << "\red You need more fuel to complete this task." + return + + user.visible_message("[user] starts cutting apart the anchoring system sealant on [src].", "You start cutting apart the anchoring system's sealant with [O]...") + + if(do_after(user,40)) + if(!src || !user || !WT.remove_fuel(5, user)) return + user.visible_message("[user] cuts apart the anchoring system sealant on [src].", "You cut apart the anchoring system's sealant.") + removal_stage = 3 + return + + if(3) + if(istype(O,/obj/item/weapon/wrench)) + + user.visible_message("[user] begins unwrenching the anchoring bolts on [src].", "You begin unwrenching the anchoring bolts...") + + if(do_after(user,50)) + if(!src || !user) return + user.visible_message("[user] unwrenches the anchoring bolts on [src].", "You unwrench the anchoring bolts.") + removal_stage = 4 + return + + if(4) + if(istype(O,/obj/item/weapon/crowbar)) + + user.visible_message("[user] begins lifting [src] off of the anchors.", "You begin lifting the device off the anchors...") + + if(do_after(user,80)) + if(!src || !user) return + user.visible_message("[user] crowbars [src] off of the anchors. It can now be moved.", "You jam the crowbar under the nuclear device and lift it off its anchors. You can now move it!") + anchored = 0 + removal_stage = 5 + return ..() /obj/machinery/nuclearbomb/attack_paw(mob/user as mob) @@ -69,7 +140,11 @@ var/bomb_set user << browse(dat, "window=nuclearbomb;size=300x400") onclose(user, "nuclearbomb") else if (src.deployable) - src.anchored = 1 + if(removal_stage < 5) + src.anchored = 1 + 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" src.extended = 1 @@ -81,8 +156,10 @@ var/bomb_set set src in oview(1) if (src.deployable) + usr << "\red You close several panels to make [src] undeployable." src.deployable = 0 else + usr << "\red You adjust some panels to make [src] deployable." src.deployable = 1 /obj/machinery/nuclearbomb/Topic(href, href_list) @@ -148,7 +225,18 @@ var/bomb_set src.timing = 0 bomb_set = 0 if (href_list["anchor"]) + + if(removal_stage == 5) + src.anchored = 0 + visible_message("\red \The [src] makes a highly unpleasant crunching noise. It looks like the anchoring bolts have been cut.") + return + src.anchored = !( src.anchored ) + if(src.anchored) + visible_message("\red With a steely snap, bolts slide out of [src] and anchor it to the flooring.") + else + visible_message("\red The anchoring bolts slide back into the depths of [src].") + src.add_fingerprint(usr) for(var/mob/M in viewers(1, src)) if ((M.client && M.machine == src)) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 1b3552408c5..3d154485133 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -742,3 +742,173 @@ datum/objective/absorb /*-------ENDOF CULTIST------*/ */ + +//Vox heist objectives. + +datum/objective/heist + proc/choose_target() + return + +datum/objective/heist/kidnap + choose_target() + var/list/roles = list("Chief Engineer","Research Director","Roboticist","Chemist","Station Engineer") + var/list/possible_targets = list() + var/list/priority_targets = list() + + for(var/datum/mind/possible_target in ticker.minds) + if(possible_target != owner && ishuman(possible_target.current) && (possible_target.current.stat != 2) && (possible_target.assigned_role != "MODE")) + possible_targets += possible_target + for(var/role in roles) + if(possible_target.assigned_role == role) + priority_targets += possible_target + continue + + if(priority_targets.len > 0) + target = pick(priority_targets) + else if(possible_targets.len > 0) + target = pick(possible_targets) + + if(target && target.current) + explanation_text = "The Shoal has a need for [target.current.real_name], the [target.assigned_role]. Take them alive." + else + explanation_text = "Free Objective" + return target + + check_completion() + if(target && target.current) + if (target.current.stat == 2) + return 0 // They're dead. Fail. + //if (!target.current.restrained()) + // return 0 // They're loose. Close but no cigar. + + var/area/shuttle/vox/station/A = locate() + for(var/mob/living/carbon/human/M in A) + if(target.current == M) + return 1 //They're restrained on the shuttle. Success. + else + return 0 + +datum/objective/heist/loot + + choose_target() + var/loot = "an object" + switch(rand(1,8)) + if(1) + target = /obj/structure/particle_accelerator + target_amount = 6 + loot = "a complete particle accelerator" + if(2) + target = /obj/machinery/the_singularitygen + target_amount = 1 + loot = "a gravitational generator" + if(3) + target = /obj/machinery/power/emitter + target_amount = 4 + loot = "four emitters" + if(4) + target = /obj/machinery/nuclearbomb + target_amount = 1 + loot = "a nuclear bomb" + if(5) + target = /obj/item/weapon/gun + target_amount = 6 + loot = "six guns" + if(6) + target = /obj/item/weapon/gun/energy + target_amount = 4 + loot = "four energy guns" + if(7) + target = /obj/item/weapon/gun/energy/laser + target_amount = 2 + loot = "two laser guns" + if(8) + target = /obj/item/weapon/gun/energy/ionrifle + target_amount = 1 + loot = "an ion gun" + + explanation_text = "We are lacking in hardware. Steal [loot]." + + check_completion() + + var/total_amount = 0 + + for(var/obj/O in locate(/area/shuttle/vox/station)) + if(istype(O,target)) total_amount++ + if(total_amount >= target_amount) return 1 + + var/datum/game_mode/heist/H = ticker.mode + for(var/datum/mind/raider in H.raiders) + if(raider.current) + for(var/obj/O in raider.current.get_contents()) + if(istype(O,target)) total_amount++ + if(total_amount >= target_amount) return 1 + + return 0 + +datum/objective/heist/salvage + + choose_target() + switch(rand(1,8)) + if(1) + target = "metal" + target_amount = 300 + if(2) + target = "glass" + target_amount = 200 + if(3) + target = "plasteel" + target_amount = 100 + if(4) + target = "plasma" + target_amount = 100 + if(5) + target = "silver" + target_amount = 50 + if(6) + target = "gold" + target_amount = 20 + if(7) + target = "uranium" + target_amount = 20 + if(8) + target = "diamond" + target_amount = 20 + + explanation_text = "Ransack the station and escape with [target_amount] [target]." + + check_completion() + + var/total_amount = 0 + + for(var/obj/item/O in locate(/area/shuttle/vox/station)) + if(istype(O,/obj/item/stack/sheet)) + if(O.name == target) + var/obj/item/stack/sheet/S = O + total_amount += S.amount + + var/datum/game_mode/heist/H = ticker.mode + for(var/datum/mind/raider in H.raiders) + if(raider.current) + for(var/obj/item/O in raider.current.get_contents()) + if(istype(O,/obj/item/stack/sheet)) + if(O.name == target) + var/obj/item/stack/sheet/S = O + total_amount += S.amount + + if(total_amount >= target_amount) return 1 + return 0 + + +datum/objective/heist/inviolate_crew + explanation_text = "Do not leave any Vox behind, alive or dead." + + check_completion() + var/datum/game_mode/heist/H = ticker.mode + if(H.is_raider_crew_safe()) return 1 + return 0 + +datum/objective/heist/inviolate_death + explanation_text = "Follow the Inviolate. Minimise death and loss of resources." + check_completion() + if(vox_kills>5) return 0 + return 1 \ No newline at end of file diff --git a/code/game/jobs/job/medical.dm b/code/game/jobs/job/medical.dm index cacd825d017..22dd096bcca 100644 --- a/code/game/jobs/job/medical.dm +++ b/code/game/jobs/job/medical.dm @@ -28,7 +28,7 @@ H.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(H), slot_shoes) H.equip_to_slot_or_del(new /obj/item/device/pda/heads/cmo(H), slot_belt) H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat/cmo(H), slot_wear_suit) - H.equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/regular(H), slot_l_hand) + H.equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/adv(H), slot_l_hand) H.equip_to_slot_or_del(new /obj/item/device/flashlight/pen(H), slot_s_store) if(H.backbag == 1) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) @@ -88,7 +88,7 @@ H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/labcoat(H), slot_wear_suit) H.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(H), slot_shoes) H.equip_to_slot_or_del(new /obj/item/device/pda/medical(H), slot_belt) - H.equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/regular(H), slot_l_hand) + H.equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/adv(H), slot_l_hand) H.equip_to_slot_or_del(new /obj/item/device/flashlight/pen(H), slot_s_store) if(H.backbag == 1) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index 84e96be0f3e..fc5f7df203a 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -414,15 +414,15 @@ var/global/datum/controller/occupations/job_master H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand) if(2) var/obj/item/weapon/storage/backpack/BPK = new/obj/item/weapon/storage/backpack(H) - new /obj/item/weapon/storage/box(BPK) + new /obj/item/weapon/storage/box/survival(BPK) H.equip_to_slot_or_del(BPK, slot_back,1) if(3) var/obj/item/weapon/storage/backpack/BPK = new/obj/item/weapon/storage/backpack/satchel_norm(H) - new /obj/item/weapon/storage/box(BPK) + new /obj/item/weapon/storage/box/survival(BPK) H.equip_to_slot_or_del(BPK, slot_back,1) if(4) var/obj/item/weapon/storage/backpack/BPK = new/obj/item/weapon/storage/backpack/satchel(H) - new /obj/item/weapon/storage/box(BPK) + new /obj/item/weapon/storage/box/survival(BPK) H.equip_to_slot_or_del(BPK, slot_back,1) H << "You are the [alt_title ? alt_title : rank]." diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm index 69519c585d1..7078d9df906 100644 --- a/code/game/machinery/OpTable.dm +++ b/code/game/machinery/OpTable.dm @@ -18,6 +18,7 @@ for(dir in list(NORTH,EAST,SOUTH,WEST)) computer = locate(/obj/machinery/computer/operating, get_step(src, dir)) if (computer) + computer.table = src break // spawn(100) //Wont the MC just call this process() before and at the 10 second mark anyway? // process() diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 5c53d4ce8bb..a4158218a1e 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -61,18 +61,23 @@ t1 = "*dead*" else dat += text("[]\tHealth %: [] ([])
", (occupant.health > 50 ? "" : ""), occupant.health, t1) + if(iscarbon(occupant)) + var/mob/living/carbon/C = occupant + dat += text("[]\t-Pulse, bpm: []
", (C.pulse == PULSE_NONE || C.pulse == PULSE_THREADY ? "" : ""), C.get_pulse(GETPULSE_TOOL)) dat += text("[]\t-Brute Damage %: []
", (occupant.getBruteLoss() < 60 ? "" : ""), occupant.getBruteLoss()) dat += text("[]\t-Respiratory Damage %: []
", (occupant.getOxyLoss() < 60 ? "" : ""), occupant.getOxyLoss()) dat += text("[]\t-Toxin Content %: []
", (occupant.getToxLoss() < 60 ? "" : ""), occupant.getToxLoss()) dat += text("[]\t-Burn Severity %: []
", (occupant.getFireLoss() < 60 ? "" : ""), occupant.getFireLoss()) dat += text("
Paralysis Summary %: [] ([] seconds left!)
", occupant.paralysis, round(occupant.paralysis / 4)) if(occupant.reagents) - dat += text("Inaprovaline units: [] units
", occupant.reagents.get_reagent_amount("inaprovaline")) - dat += text("Soporific: [] units
", occupant.reagents.get_reagent_amount("stoxin")) - dat += text("Dermaline: [] units
", occupant.reagents.get_reagent_amount("dermaline")) - dat += text("Bicaridine: [] units
", occupant.reagents.get_reagent_amount("bicaridine")) - dat += text("Dexalin: [] units
", occupant.reagents.get_reagent_amount("dexalin")) - dat += text("
Refresh meter readings each second
Inject Inaprovaline
Inject Soporific
Inject Dermaline
Inject Bicaridine
Inject Dexalin", src, src, src, src, src, src) + 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
" + for(var/chemical in connected.available_chemicals) + dat += "Inject [connected.available_chemicals[chemical]]: " + for(var/amount in connected.amounts) + dat += "[amount] units " + dat += "
" else dat += "The sleeper is empty." dat += text("

Close", user) @@ -85,27 +90,15 @@ return if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon/ai))) usr.set_machine(src) - if (src.connected) - if (src.connected.occupant) - if(src.connected.occupant.health > 0) - if (href_list["inap"]) - src.connected.inject_inap(usr) - if (href_list["stox"]) - src.connected.inject_stox(usr) - if (href_list["derm"]) - src.connected.inject_dermaline(usr) - if (href_list["bic"]) - src.connected.inject_bicaridine(usr) - if (href_list["dex"]) - src.connected.inject_dexalin(usr) - else - if(src.connected.occupant.health > -100) - if (href_list["inap"]) - src.connected.inject_inap(usr) - if (href_list["stox"] || href_list["derm"] || href_list["bic"] || href_list["dex"]) - usr << "\red \b this person is not in good enough condition for sleepers to be effective! Use another means of treatment, such as cryogenics!" - else + if (href_list["chemical"]) + if (src.connected) + if (src.connected.occupant) + if (src.connected.occupant.stat == DEAD) usr << "\red \b This person has no life for to preserve anymore. Take them to a department capable of reanimating them." + else if(src.connected.occupant.health > 0 || href_list["chemical"] == "inaprovaline") + 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!" if (href_list["refresh"]) src.updateUsrDialog() src.add_fingerprint(usr) @@ -139,6 +132,8 @@ anchored = 1 var/orient = "LEFT" // "RIGHT" changes the dir suffix to "-r" var/mob/living/occupant = null + var/available_chemicals = list("inaprovaline" = "Inaprovaline", "stoxin" = "Soporific", "dermaline" = "Dermaline", "bicaridine" = "Bicaridine", "dexalin" = "Dexalin") + var/amounts = list(10, 20) New() @@ -272,53 +267,13 @@ return - proc/inject_inap(mob/living/user as mob) + proc/inject_chemical(mob/living/user as mob, chemical, amount) if(src.occupant && src.occupant.reagents) - if(src.occupant.reagents.get_reagent_amount("inaprovaline") + 30 <= 60) - src.occupant.reagents.add_reagent("inaprovaline", 30) - user << text("Occupant now has [] units of Inaprovaline in his/her bloodstream.", src.occupant.reagents.get_reagent_amount("inaprovaline")) - else - user << "There's no occupant in the sleeper or the subject rejects the chemicals!" - return - - - proc/inject_stox(mob/living/user as mob) - if(src.occupant && src.occupant.reagents) - if(src.occupant.reagents.get_reagent_amount("stoxin") + 20 <= 40) - src.occupant.reagents.add_reagent("stoxin", 20) - user << text("Occupant now has [] units of soporifics in his/her bloodstream.", src.occupant.reagents.get_reagent_amount("stoxin")) - else - user << "There's no occupant in the sleeper or the subject rejects the chemicals!" - return - - - proc/inject_dermaline(mob/living/user as mob) - if(src.occupant && src.occupant.reagents) - if(src.occupant.reagents.get_reagent_amount("dermaline") + 20 <= 40) - src.occupant.reagents.add_reagent("dermaline", 20) - user << text("Occupant now has [] units of Dermaline in his/her bloodstream.", src.occupant.reagents.get_reagent_amount("dermaline")) - else - user << "There's no occupant in the sleeper or the subject rejects the chemicals!" - return - - - proc/inject_bicaridine(mob/living/user as mob) - if(src.occupant && src.occupant.reagents) - if(src.occupant.reagents.get_reagent_amount("bicaridine") + 10 <= 20) - src.occupant.reagents.add_reagent("bicaridine", 10) - user << text("Occupant now has [] units of Bicaridine in his/her bloodstream.", src.occupant.reagents.get_reagent_amount("bicaridine")) - else - user << "There's no occupant in the sleeper or the subject rejects the chemicals!" - return - - - proc/inject_dexalin(mob/living/user as mob) - if(src.occupant && src.occupant.reagents) - if(src.occupant.reagents.get_reagent_amount("dexalin") + 20 <= 40) - src.occupant.reagents.add_reagent("dexalin", 20) - user << text("Occupant now has [] units of Dexalin in his/her bloodstream.", src.occupant.reagents.get_reagent_amount("dexalin")) - else - user << "There's no occupant in the sleeper or the subject rejects the chemicals!" + if(src.occupant.reagents.get_reagent_amount(chemical) + amount <= 40) + src.occupant.reagents.add_reagent(chemical, amount) + user << "Occupant now has [src.occupant.reagents.get_reagent_amount(chemical)] units of [available_chemicals[chemical]] in his/her bloodstream." + return + user << "There's no occupant in the sleeper or the subject rejects the chemicals!" return @@ -395,4 +350,4 @@ del(O) src.add_fingerprint(usr) return - return + return \ No newline at end of file diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index 72d00d89edc..f2ad62d05e4 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -235,7 +235,7 @@ else dat += text("[]\tHealth %: [] ([])

", (occupant.health > 50 ? "" : ""), occupant.health, t1) - if(occupant.virus2) + if(occupant.virus2.len) dat += text("Viral pathogen detected in blood stream.
") dat += text("[]\t-Brute Damage %: []

", (occupant.getBruteLoss() < 60 ? "" : ""), occupant.getBruteLoss()) diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index 71906ffb3b6..ea2456cf977 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -125,6 +125,8 @@ pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24) pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0 update_icon() + if(ticker && ticker.current_state == 3)//if the game is running + src.initialize() return first_run() @@ -1477,8 +1479,7 @@ FIRE ALARM A = A.loc if (!( istype(A, /area) )) return - for(var/area/RA in A.related) - RA.firereset() + A.firereset() update_icon() return @@ -1489,8 +1490,7 @@ FIRE ALARM A = A.loc if (!( istype(A, /area) )) return - for(var/area/RA in A.related) - RA.firealert() + A.firealert() update_icon() //playsound(src.loc, 'sound/ambience/signal.ogg', 75, 0) return diff --git a/code/game/machinery/bots/cleanbot.dm b/code/game/machinery/bots/cleanbot.dm index 47b27ac54bd..d0345f60905 100644 --- a/code/game/machinery/bots/cleanbot.dm +++ b/code/game/machinery/bots/cleanbot.dm @@ -233,7 +233,8 @@ text("[src.oddbutton ? "Yes" : "No" if(target && path.len == 0) spawn(0) if(!src || !target) return - src.path = AStar(src.loc, src.target.loc, /turf/proc/AdjacentTurfs, /turf/proc/Distance, 0, 30) + src.path = AStar(src.loc, src.target.loc, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 30, id=botcard) + if (!path) path = list() if(src.path.len == 0) src.oldtarget = src.target src.target = null diff --git a/code/game/machinery/bots/ed209bot.dm b/code/game/machinery/bots/ed209bot.dm index 5e5ae744068..d71a43c083e 100644 --- a/code/game/machinery/bots/ed209bot.dm +++ b/code/game/machinery/bots/ed209bot.dm @@ -615,6 +615,7 @@ Auto Patrol: []"}, // given an optional turf to avoid /obj/machinery/bot/ed209/proc/calc_path(var/turf/avoid = null) src.path = AStar(src.loc, patrol_target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 120, id=botcard, exclude=avoid) + if (!src.path) src.path = list() // look for a criminal in view of the bot diff --git a/code/game/machinery/bots/floorbot.dm b/code/game/machinery/bots/floorbot.dm index bb984a1787b..69fc5afd3f3 100644 --- a/code/game/machinery/bots/floorbot.dm +++ b/code/game/machinery/bots/floorbot.dm @@ -241,9 +241,10 @@ if(src.target && (src.target != null) && src.path.len == 0) spawn(0) if(!istype(src.target, /turf/)) - src.path = AStar(src.loc, src.target.loc, /turf/proc/AdjacentTurfsSpace, /turf/proc/Distance, 0, 30) + src.path = AStar(src.loc, src.target.loc, /turf/proc/AdjacentTurfsSpace, /turf/proc/Distance, 0, 30, id=botcard) else - src.path = AStar(src.loc, src.target, /turf/proc/AdjacentTurfsSpace, /turf/proc/Distance, 0, 30) + src.path = AStar(src.loc, src.target, /turf/proc/AdjacentTurfsSpace, /turf/proc/Distance, 0, 30, id=botcard) + if (!src.path) src.path = list() if(src.path.len == 0) src.oldtarget = src.target src.target = null diff --git a/code/game/machinery/camera/camera_assembly.dm b/code/game/machinery/camera/camera_assembly.dm index c67a5a77b19..d5408d33308 100644 --- a/code/game/machinery/camera/camera_assembly.dm +++ b/code/game/machinery/camera/camera_assembly.dm @@ -87,6 +87,9 @@ usr << "No network found please hang up and try your call again." return + var/temptag = "[get_area(src)] ([rand(1, 999)])" + input = strip_html(input(usr, "How would you like to name the camera?", "Set Camera Name", temptag)) + state = 4 var/obj/machinery/camera/C = new(src.loc) src.loc = C @@ -94,9 +97,12 @@ C.auto_turn() - C.network = tempnetwork + C.network = uniquelist(tempnetwork) + tempnetwork = difflist(C.network,RESTRICTED_CAMERA_NETWORKS) + if(!tempnetwork.len)//Camera isn't on any open network - remove its chunk from AI visibility. + cameranet.removeCamera(C) - C.c_tag = "[get_area_name(src)] ([rand(1, 999)]" + C.c_tag = input for(var/i = 5; i >= 0; i -= 1) var/direct = input(user, "Direction?", "Assembling Camera", null) in list("LEAVE IT", "NORTH", "EAST", "SOUTH", "WEST" ) diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 124239dc82b..fd66d0c2c32 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -116,7 +116,7 @@ //Clonepod //Start growing a human clone in the pod! -/obj/machinery/clonepod/proc/growclone(var/ckey, var/clonename, var/ui, var/se, var/mindref, var/mrace) +/obj/machinery/clonepod/proc/growclone(var/ckey, var/clonename, var/ui, var/se, var/mindref, var/datum/species/mrace) if(mess || attempting) return 0 var/datum/mind/clonemind = locate(mindref) @@ -191,13 +191,11 @@ randmutb(H) //Sometimes the clones come out wrong. H.f_style = "Shaved" - if(mrace == "none") //no more xenos losing ears/tentacles + if(mrace.name == "Human") //no more xenos losing ears/tentacles H.h_style = pick("Bedhead", "Bedhead 2", "Bedhead 3") - if(H.dna) - H.dna.mutantrace = mrace - H.update_mutantrace() - H.update_mutantrace_languages() + H.species = mrace + H.update_mutantrace() H.suiciding = 0 src.attempting = 0 return 1 diff --git a/code/game/machinery/computer/HolodeckControl.dm b/code/game/machinery/computer/HolodeckControl.dm index db320be2935..50165bb36d8 100644 --- a/code/game/machinery/computer/HolodeckControl.dm +++ b/code/game/machinery/computer/HolodeckControl.dm @@ -231,8 +231,10 @@ emergencyShutdown() ..() - /obj/machinery/computer/HolodeckControl/process() + for(var/item in holographic_items) // do this first, to make sure people don't take items out when power is down. + if(!(get_turf(item) in linkedholodeck)) + derez(item, 0) if(!..()) return @@ -256,13 +258,6 @@ T.ex_act(3) T.hotspot_expose(1000,500,1) - - for(var/item in holographic_items) - if(!(get_turf(item) in linkedholodeck)) - derez(item, 0) - - - /obj/machinery/computer/HolodeckControl/proc/derez(var/obj/obj , var/silent = 1) holographic_items.Remove(obj) diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm index 2022dc79da7..f1a1f02db70 100644 --- a/code/game/machinery/computer/Operating.dm +++ b/code/game/machinery/computer/Operating.dm @@ -13,7 +13,8 @@ ..() for(dir in list(NORTH,EAST,SOUTH,WEST)) table = locate(/obj/machinery/optable, get_step(src, dir)) - if (!isnull(table)) + if (table) + table.computer = src break /obj/machinery/computer/operating/attack_ai(mob/user) @@ -55,6 +56,7 @@ Fire Damage: [src.victim.getFireLoss()]
Suffocation Damage: [src.victim.getOxyLoss()]
Patient Status: [src.victim.stat ? "Non-Responsive" : "Stable"]
+Heartbeat rate: [victim.get_pulse(GETPULSE_TOOL)]
"} else src.victim = null diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm index 2081a640d8e..7dca0ae01fb 100644 --- a/code/game/machinery/computer/buildandrepair.dm +++ b/code/game/machinery/computer/buildandrepair.dm @@ -37,6 +37,10 @@ /obj/item/weapon/circuitboard/security name = "Circuit board (Security)" build_path = "/obj/machinery/computer/security" + var/network = list("SS13") + req_access = list(access_security) + var/locked = 1 + var/emagged = 0 /obj/item/weapon/circuitboard/aicore name = "Circuit board (AI core)" origin_tech = "programming=4;biotech=2" @@ -80,6 +84,9 @@ /obj/item/weapon/circuitboard/secure_data name = "Circuit board (Security Records)" build_path = "/obj/machinery/computer/secure_data" +/obj/item/weapon/circuitboard/skills + name = "Circuit board (Employment Records)" + build_path = "/obj/machinery/computer/skills" /obj/item/weapon/circuitboard/stationalert name = "Circuit board (Station Alerts)" build_path = "/obj/machinery/computer/station_alert" @@ -166,10 +173,6 @@ name = "Circuit board (Operating Computer)" build_path = "/obj/machinery/computer/operating" origin_tech = "programming=2;biotech=2" -/obj/item/weapon/circuitboard/mining - name = "Circuit board (Outpost Status Display)" - build_path = "/obj/machinery/computer/security/mining" - origin_tech = "programming=2" /obj/item/weapon/circuitboard/comm_monitor name = "Circuit board (Telecommunications Monitor)" build_path = "/obj/machinery/computer/telecomms/monitor" @@ -238,6 +241,40 @@ user << "DERP! BUG! Report this (And what you were doing to cause it) to Agouri" return +/obj/item/weapon/circuitboard/security/attackby(obj/item/I as obj, mob/user as mob) + if(istype(I,/obj/item/weapon/card/emag)) + if(emagged) + user << "Circuit lock is already removed." + return + user << "\blue You override the circuit lock and open controls." + emagged = 1 + locked = 0 + else if(istype(I,/obj/item/weapon/card/id)) + if(emagged) + user << "\red Circuit lock does not respond." + return + if(check_access(I)) + locked = !locked + user << "\blue You [locked ? "" : "un"]lock the circuit controls." + else + user << "\red Access denied." + else if(istype(I,/obj/item/device/multitool)) + if(locked) + user << "\red Circuit controls are locked." + return + var/existing_networks = dd_list2text(network,",") + var/input = strip_html(input(usr, "Which networks would you like to connect this camera console circuit to? Seperate networks with a comma. No Spaces!\nFor example: SS13,Security,Secret ", "Multitool-Circuitboard interface", existing_networks)) + if(!input) + usr << "No input found please hang up and try your call again." + return + var/list/tempnetwork = text2list(input, ",") + tempnetwork = difflist(tempnetwork,RESTRICTED_CAMERA_NETWORKS,1) + if(tempnetwork.len < 1) + usr << "No network found please hang up and try your call again." + return + network = tempnetwork + return + /obj/item/weapon/circuitboard/rdconsole/attackby(obj/item/I as obj, mob/user as mob) if(istype(I,/obj/item/weapon/screwdriver)) if(src.build_path == "/obj/machinery/computer/rdconsole/core") @@ -353,4 +390,8 @@ var/obj/machinery/computer/supplycomp/SC = B var/obj/item/weapon/circuitboard/supplycomp/C = circuit SC.can_order_contraband = C.contraband_enabled - del(src) + if(istype(circuit,/obj/item/weapon/circuitboard/security)) + var/obj/machinery/computer/security/C = B + var/obj/item/weapon/circuitboard/security/CB = circuit + C.network = CB.network + del(src) \ No newline at end of file diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index 0e4caf97c3f..857d4169ea1 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -5,7 +5,6 @@ name = "Security Cameras" desc = "Used to access the various cameras on the station." icon_state = "cameras" - circuit = "/obj/item/weapon/circuitboard/security" var/obj/machinery/camera/current = null var/last_pic = 1.0 var/list/network = list("SS13") @@ -45,8 +44,7 @@ var/list/D = list() D["Cancel"] = "Cancel" for(var/obj/machinery/camera/C in L) - var/list/tempnetwork = C.network&network - if(tempnetwork.len) + if(can_access_camera(C)) D[text("[][]", C.c_tag, (C.status ? null : " (Deactivated)"))] = C var/t = input(user, "Which camera should you change to?") as null|anything in D @@ -61,24 +59,110 @@ return 0 if(C) - if ((get_dist(user, src) > 1 || user.machine != src || user.blinded || !( user.canmove ) || !( C.can_use() )) && (!istype(user, /mob/living/silicon/ai))) - if(!C.can_use() && !isAI(user)) - src.current = null - return 0 - else - if(isAI(user)) - var/mob/living/silicon/ai/A = user - A.eyeobj.setLoc(get_turf(C)) - A.client.eye = A.eyeobj - else - src.current = C - use_power(50) - - spawn(5) - attack_hand(user) + switch_to_camera(user, C) + spawn(5) + attack_hand(user) return + proc/can_access_camera(var/obj/machinery/camera/C) + var/list/shared_networks = src.network & C.network + if(shared_networks.len) + return 1 + return 0 + proc/switch_to_camera(var/mob/user, var/obj/machinery/camera/C) + if ((get_dist(user, src) > 1 || user.machine != src || user.blinded || !( user.canmove ) || !( C.can_use() )) && (!istype(user, /mob/living/silicon/ai))) + if(!C.can_use() && !isAI(user)) + src.current = null + return 0 + else + if(isAI(user)) + var/mob/living/silicon/ai/A = user + A.eyeobj.setLoc(get_turf(C)) + A.client.eye = A.eyeobj + else + src.current = C + use_power(50) + return 1 + + attackby(I as obj, user as mob) + if(istype(I, /obj/item/weapon/screwdriver)) + playsound(loc, 'sound/items/Screwdriver.ogg', 50, 1) + if(do_after(user, 20)) + if (stat & BROKEN) + user << "\blue The broken glass falls out." + var/obj/structure/computerframe/CF = new /obj/structure/computerframe(loc) + new /obj/item/weapon/shard(loc) + var/obj/item/weapon/circuitboard/security/CB = new /obj/item/weapon/circuitboard/security(CF) + CB.network = network + for (var/obj/C in src) + C.loc = loc + CF.circuit = CB + CF.state = 3 + CF.icon_state = "3" + CF.anchored = 1 + del(src) + else + user << "\blue You disconnect the monitor." + var/obj/structure/computerframe/CF = new /obj/structure/computerframe( loc ) + var/obj/item/weapon/circuitboard/security/CB = new /obj/item/weapon/circuitboard/security(CF) + CB.network = network + for (var/obj/C in src) + C.loc = loc + CF.circuit = CB + CF.state = 4 + CF.icon_state = "4" + CF.anchored = 1 + del(src) + else + attack_hand(user) + return + +//Camera control: moving. + proc/jump_on_click(var/mob/user,var/A) + if(user.machine != src) + return + var/obj/machinery/camera/jump_to + if(istype(A,/obj/machinery/camera)) + jump_to = A + else if(ismob(A)) + if(ishuman(A)) + jump_to = locate() in A:head + else if(isrobot(A)) + jump_to = A:camera + else if(isobj(A)) + jump_to = locate() in A + else if(isturf(A)) + var/best_dist = INFINITY + for(var/obj/machinery/camera/camera in get_area(A)) + if(!camera.can_use()) + continue + if(!can_access_camera(camera)) + continue + var/dist = get_dist(camera,A) + if(dist < best_dist) + best_dist = dist + jump_to = camera + if(isnull(jump_to)) + return + if(can_access_camera(jump_to)) + switch_to_camera(user,jump_to) +//Camera control: mouse. +/atom/DblClick() + ..() + if(istype(usr.machine,/obj/machinery/computer/security)) + var/obj/machinery/computer/security/console = usr.machine + console.jump_on_click(usr,src) +//Camera control: arrow keys. +/mob/Move(n,direct) + if(istype(machine,/obj/machinery/computer/security)) + var/obj/machinery/computer/security/console = machine + var/turf/T = get_turf(console.current) + for(var/i;i<10;i++) + T = get_step(T,direct) + console.jump_on_click(src,T) + return + ..(n,direct) /obj/machinery/computer/security/telescreen name = "Telescreen" @@ -87,7 +171,6 @@ icon_state = "telescreen" network = list("thunder") density = 0 - circuit = null /obj/machinery/computer/security/telescreen/update_icon() icon_state = initial(icon_state) @@ -100,10 +183,6 @@ desc = "Damn, they better have /tg/thechannel on these things." icon = 'icons/obj/status_display.dmi' icon_state = "entertainment" - network = list("thunder") - density = 0 - circuit = null - /obj/machinery/computer/security/wooden_tv name = "Security Cameras" @@ -116,4 +195,9 @@ desc = "Used to access the various cameras on the outpost." icon_state = "miningcameras" network = list("MINE") - circuit = "/obj/item/weapon/circuitboard/mining" + +/obj/machinery/computer/security/engineering + name = "Engineering Cameras" + desc = "Used to monitor fires and breaches." + icon_state = "engineeringcameras" + network = list("Power Alarms","Atmosphere Alarms","Fire Alarms") \ No newline at end of file diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index edb4882cd2b..e29097a0308 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -443,10 +443,7 @@ subject.dna.check_integrity() var/datum/data/record/R = new /datum/data/record( ) - if(subject.dna) - R.fields["mrace"] = subject.dna.mutantrace - else - R.fields["mrace"] = null + R.fields["mrace"] = subject.species R.fields["ckey"] = subject.ckey R.fields["name"] = subject.real_name R.fields["id"] = copytext(md5(subject.real_name), 2, 6) diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index 81f58d19d0c..c6f2f454567 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -83,6 +83,7 @@ dat += text("\n
Print Record
\nBack
", src, src) if(5.0) dat += "
Virus Database
" + /* Advanced diseases is weak! Feeble! Glory to virus2! for(var/Dt in typesof(/datum/disease/)) var/datum/disease/Dis = new Dt(0) if(istype(Dis, /datum/disease/advance)) @@ -90,6 +91,11 @@ if(!Dis.desc) continue dat += "
[Dis.name]" + */ + for (var/ID in virusDB) + var/datum/data/record/v = virusDB[ID] + dat += "
[v.fields["name"]]" + dat += "
Back" if(6.0) dat += "
Medical Robot Monitor
" @@ -121,36 +127,56 @@ /obj/machinery/computer/med_data/Topic(href, href_list) if(..()) return + if (!( data_core.general.Find(src.active1) )) src.active1 = null + if (!( data_core.medical.Find(src.active2) )) src.active2 = null + if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon))) usr.set_machine(src) + if (href_list["temp"]) src.temp = null + if (href_list["scan"]) if (src.scan) - src.scan.loc = src.loc - src.scan = null + + if(ishuman(usr)) + scan.loc = usr.loc + + if(!usr.get_active_hand()) + usr.put_in_hands(scan) + + scan = null + + else + src.scan.loc = src.loc + src.scan = null + else var/obj/item/I = usr.get_active_hand() if (istype(I, /obj/item/weapon/card/id)) usr.drop_item() I.loc = src src.scan = I + else if (href_list["logout"]) src.authenticated = null src.screen = null src.active1 = null src.active2 = null + else if (href_list["login"]) + if (istype(usr, /mob/living/silicon/ai)) src.active1 = null src.active2 = null src.authenticated = usr.name src.rank = "AI" src.screen = 1 + else if (istype(usr, /mob/living/silicon/robot)) src.active1 = null src.active2 = null @@ -158,13 +184,16 @@ var/mob/living/silicon/robot/R = usr src.rank = R.braintype src.screen = 1 + else if (istype(src.scan, /obj/item/weapon/card/id)) src.active1 = null src.active2 = null + if (src.check_access(src.scan)) src.authenticated = src.scan.registered_name src.rank = src.scan.assignment src.screen = 1 + if (src.authenticated) if(href_list["screen"]) @@ -176,20 +205,12 @@ src.active2 = null if(href_list["vir"]) - var/type = href_list["vir"] - var/datum/disease/Dis = new type(0) - var/AfS = "" - for(var/Str in Dis.affected_species) - AfS += " [Str];" - src.temp = {"Name: [Dis.name] -
Number of stages: [Dis.max_stages] -
Spread: [Dis.spread] Transmission -
Possible Cure: [(Dis.cure||"none")] -
Affected Species:[AfS] -
-
Notes: [Dis.desc] -
-
Severity: [Dis.severity]"} + var/datum/data/record/v = locate(href_list["vir"]) + src.temp = "
GNAv2 based virus lifeform V-[v.fields["id"]]
" + src.temp += "
Name: [v.fields["name"]]" + src.temp += "
Antigen: [v.fields["antigen"]]" + src.temp += "
Spread: [v.fields["spread type"]] " + src.temp += "
Details:
[v.fields["description"]]" if (href_list["del_all"]) src.temp = text("Are you sure you wish to delete all records?
\n\tYes
\n\tNo
", src, src) @@ -279,7 +300,7 @@ src.active2.fields["notes"] = t1 if("p_stat") if (istype(src.active1, /datum/data/record)) - src.temp = text("Physical Condition:
\n\t*Deceased*
\n\t*Unconscious*
\n\tActive
\n\tPhysically Unfit
", src, src, src, src) + src.temp = text("Physical Condition:
\n\t*Deceased*
\n\t*SSD*
\n\tActive
\n\tPhysically Unfit
\n\tDisabled
", src, src, src, src, src) if("m_stat") if (istype(src.active1, /datum/data/record)) src.temp = text("Mental Condition:
\n\t*Insane*
\n\t*Unstable*
\n\t*Watch*
\n\tStable
", src, src, src, src) @@ -292,6 +313,20 @@ if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || src.active1 != a1)) return src.active1.fields["dna"] = t1 + if("vir_name") + var/datum/data/record/v = locate(href_list["edit_vir"]) + if (v) + var/t1 = copytext(sanitize(input("Please input pathogen name:", "VirusDB", v.fields["name"], null) as text),1,MAX_MESSAGE_LEN) + if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || src.active1 != a1)) + return + v.fields["name"] = t1 + if("vir_desc") + var/datum/data/record/v = locate(href_list["edit_vir"]) + if (v) + var/t1 = copytext(sanitize(input("Please input information about pathogen:", "VirusDB", v.fields["description"], null) as message),1,MAX_MESSAGE_LEN) + if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || src.active1 != a1)) + return + v.fields["description"] = t1 else if (href_list["p_stat"]) @@ -299,12 +334,14 @@ switch(href_list["p_stat"]) if("deceased") src.active1.fields["p_stat"] = "*Deceased*" - if("unconscious") - src.active1.fields["p_stat"] = "*Unconscious*" + if("ssd") + src.active1.fields["p_stat"] = "*SSD*" if("active") src.active1.fields["p_stat"] = "Active" if("unfit") src.active1.fields["p_stat"] = "Physically Unfit" + if("disabled") + src.active1.fields["p_stat"] = "Disabled" if (href_list["m_stat"]) if (src.active1) @@ -466,7 +503,7 @@ if(4) R.fields["b_type"] = pick("A-", "B-", "AB-", "O-", "A+", "B+", "AB+", "O+") if(5) - R.fields["p_stat"] = pick("*Unconcious*", "Active", "Physically Unfit") + R.fields["p_stat"] = pick("*SSD*", "Active", "Physically Unfit", "Disabled") if(6) R.fields["m_stat"] = pick("*Insane*", "*Unstable*", "*Watch*", "Stable") continue diff --git a/code/game/machinery/computer/skills.dm b/code/game/machinery/computer/skills.dm new file mode 100644 index 00000000000..7613d711ce6 --- /dev/null +++ b/code/game/machinery/computer/skills.dm @@ -0,0 +1,419 @@ +//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 + +/obj/machinery/computer/skills//TODO:SANITY + name = "Employment Records" + desc = "Used to view personnel's employment records" + icon_state = "medlaptop" + req_one_access = list(access_heads) + circuit = "/obj/item/weapon/circuitboard/skills" + var/obj/item/weapon/card/id/scan = null + var/authenticated = null + var/rank = null + var/screen = null + var/datum/data/record/active1 = null + var/a_id = null + var/temp = null + var/printing = null + var/can_change_id = 0 + var/list/Perp + var/tempname = null + //Sorting Variables + var/sortBy = "name" + var/order = 1 // -1 = Descending - 1 = Ascending + + +/obj/machinery/computer/skills/attackby(obj/item/O as obj, user as mob) + if(istype(O, /obj/item/weapon/card/id) && !scan) + usr.drop_item() + O.loc = src + scan = O + user << "You insert [O]." + ..() + +/obj/machinery/computer/skills/attack_ai(mob/user as mob) + return attack_hand(user) + +/obj/machinery/computer/skills/attack_paw(mob/user as mob) + return attack_hand(user) + +//Someone needs to break down the dat += into chunks instead of long ass lines. +/obj/machinery/computer/skills/attack_hand(mob/user as mob) + if(..()) + return + if (src.z > 6) + user << "\red Unable to establish a connection: \black You're too far away from the station!" + return + var/dat + + if (temp) + dat = text("[]

Clear Screen", temp, src) + else + dat = text("Confirm Identity: []
", src, (scan ? text("[]", scan.name) : "----------")) + if (authenticated) + switch(screen) + if(1.0) + dat += {" +

"} + dat += text("Search Records
", src) + dat += text("New Record
", src) + dat += {" +

+ + + + +
Records:
+ + + + + + +"} + if(!isnull(data_core.general)) + for(var/datum/data/record/R in sortRecord(data_core.general, sortBy, order)) + for(var/datum/data/record/E in data_core.security) + var/background + dat += text("", background, src, R, R.fields["name"]) + dat += text("", R.fields["id"]) + dat += text("", R.fields["rank"]) + dat += text("", R.fields["fingerprint"]) + dat += "
NameIDRankFingerprints
[][][][]

" + dat += text("Record Maintenance

", src) + dat += text("{Log Out}",src) + if(2.0) + dat += "Records Maintenance
" + dat += "
Delete All Records

Back" + if(3.0) + dat += "
Employment Record

" + if ((istype(active1, /datum/data/record) && data_core.general.Find(active1))) + var/icon/front = new(active1.fields["photo"], dir = SOUTH) + var/icon/side = new(active1.fields["photo"], dir = WEST) + user << browse_rsc(front, "front.png") + user << browse_rsc(side, "side.png") + dat += text(" \ +
\ + Name: [active1.fields["name"]]
\ + ID: [active1.fields["id"]]
\n \ + Sex: [active1.fields["sex"]]
\n \ + Age: [active1.fields["age"]]
\n \ + Rank: [active1.fields["rank"]]
\n \ + Fingerprint: [active1.fields["fingerprint"]]
\n \ + Physical Status: [active1.fields["p_stat"]]
\n \ + Mental Status: [active1.fields["m_stat"]]

\n \ + Employment/skills summary:
[active1.fields["notes"]]
Photo:
\ +
") + else + dat += "General Record Lost!
" + dat += text("\nDelete Record (ALL)

\nPrint Record
\nBack
", src, src, src) + if(4.0) + if(!Perp.len) + dat += text("ERROR. String could not be located.

Back", src) + else + dat += {" + + "} + dat += text("", tempname) + dat += {" + +
Search Results for '[]':
+ + + + + + + "} + for(var/i=1, i<=Perp.len, i += 2) + var/crimstat = "" + var/datum/data/record/R = Perp[i] + if(istype(Perp[i+1],/datum/data/record/)) + var/datum/data/record/E = Perp[i+1] + crimstat = E.fields["criminal"] + var/background + background = "'background-color:#00FF7F;'" + dat += text("", background, src, R, R.fields["name"]) + dat += text("", R.fields["id"]) + dat += text("", R.fields["rank"]) + dat += text("", R.fields["fingerprint"]) + dat += text("", crimstat) + dat += "
NameIDRankFingerprints
[][][][][]

" + dat += text("
Return to index.", src) + else + else + dat += text("{Log In}", src) + user << browse(text("Employment Records[]", dat), "window=secure_rec;size=600x400") + onclose(user, "secure_rec") + return + +/*Revised /N +I can't be bothered to look more of the actual code outside of switch but that probably needs revising too. +What a mess.*/ +/obj/machinery/computer/skills/Topic(href, href_list) + if(..()) + return + if (!( data_core.general.Find(active1) )) + active1 = null + if ((usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon))) + usr.set_machine(src) + switch(href_list["choice"]) +// SORTING! + if("Sorting") + // Reverse the order if clicked twice + if(sortBy == href_list["sort"]) + if(order == 1) + order = -1 + else + order = 1 + else + // New sorting order! + sortBy = href_list["sort"] + order = initial(order) +//BASIC FUNCTIONS + if("Clear Screen") + temp = null + + if ("Return") + screen = 1 + active1 = null + + if("Confirm Identity") + if (scan) + if(istype(usr,/mob/living/carbon/human) && !usr.get_active_hand()) + usr.put_in_hands(scan) + else + scan.loc = get_turf(src) + scan = null + else + var/obj/item/I = usr.get_active_hand() + if (istype(I, /obj/item/weapon/card/id)) + usr.drop_item() + I.loc = src + scan = I + + if("Log Out") + authenticated = null + screen = null + active1 = null + + if("Log In") + if (istype(usr, /mob/living/silicon/ai)) + src.active1 = null + src.authenticated = usr.name + src.rank = "AI" + src.screen = 1 + else if (istype(usr, /mob/living/silicon/robot)) + src.active1 = null + src.authenticated = usr.name + var/mob/living/silicon/robot/R = usr + src.rank = R.braintype + src.screen = 1 + else if (istype(scan, /obj/item/weapon/card/id)) + active1 = null + if(check_access(scan)) + authenticated = scan.registered_name + rank = scan.assignment + screen = 1 +//RECORD FUNCTIONS + if("Search Records") + var/t1 = input("Search String: (Partial Name or ID or Fingerprints or Rank)", "Secure. records", null, null) as text + if ((!( t1 ) || usr.stat || !( authenticated ) || usr.restrained() || !in_range(src, usr))) + return + Perp = new/list() + t1 = lowertext(t1) + var/list/components = text2list(t1, " ") + if(components.len > 5) + return //Lets not let them search too greedily. + for(var/datum/data/record/R in data_core.general) + var/temptext = R.fields["name"] + " " + R.fields["id"] + " " + R.fields["fingerprint"] + " " + R.fields["rank"] + for(var/i = 1, i<=components.len, i++) + if(findtext(temptext,components[i])) + var/prelist = new/list(2) + prelist[1] = R + Perp += prelist + for(var/i = 1, i<=Perp.len, i+=2) + for(var/datum/data/record/E in data_core.security) + var/datum/data/record/R = Perp[i] + if ((E.fields["name"] == R.fields["name"] && E.fields["id"] == R.fields["id"])) + Perp[i+1] = E + tempname = t1 + screen = 4 + + if("Record Maintenance") + screen = 2 + active1 = null + + if ("Browse Record") + var/datum/data/record/R = locate(href_list["d_rec"]) + if (!( data_core.general.Find(R) )) + temp = "Record Not Found!" + else + for(var/datum/data/record/E in data_core.security) + active1 = R + screen = 3 + +/* if ("Search Fingerprints") + var/t1 = input("Search String: (Fingerprint)", "Secure. records", null, null) as text + if ((!( t1 ) || usr.stat || !( authenticated ) || usr.restrained() || (!in_range(src, usr)) && (!istype(usr, /mob/living/silicon)))) + return + active1 = null + t1 = lowertext(t1) + for(var/datum/data/record/R in data_core.general) + if (lowertext(R.fields["fingerprint"]) == t1) + active1 = R + if (!( active1 )) + temp = text("Could not locate record [].", t1) + else + for(var/datum/data/record/E in data_core.security) + if ((E.fields["name"] == active1.fields["name"] || E.fields["id"] == active1.fields["id"])) + screen = 3 */ + + if ("Print Record") + if (!( printing )) + printing = 1 + sleep(50) + var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( loc ) + P.info = "
Employment Record

" + if ((istype(active1, /datum/data/record) && data_core.general.Find(active1))) + P.info += text("Name: [] ID: []
\nSex: []
\nAge: []
\nFingerprint: []
\nPhysical Status: []
\nMental Status: []
\nEmployment/Skills Summary:[]
", active1.fields["name"], active1.fields["id"], active1.fields["sex"], active1.fields["age"], active1.fields["fingerprint"], active1.fields["p_stat"], active1.fields["m_stat"], active1.fields["notes"]) + else + P.info += "General Record Lost!
" + P.info += "" + P.name = "paper - 'Employment Record'" + printing = null +//RECORD DELETE + if ("Delete All Records") + temp = "" + temp += "Are you sure you wish to delete all Employment records?
" + temp += "Yes
" + temp += "No" + + if ("Purge All Records") + for(var/datum/data/record/R in data_core.security) + del(R) + temp = "All Employment records deleted." + + if ("Delete Record (ALL)") + if (active1) + temp = "
Are you sure you wish to delete the record (ALL)?
" + temp += "Yes
" + temp += "No" +//RECORD CREATE + if ("New Record (General)") + var/datum/data/record/G = new /datum/data/record() + G.fields["name"] = "New Record" + G.fields["id"] = text("[]", add_zero(num2hex(rand(1, 1.6777215E7)), 6)) + G.fields["rank"] = "Unassigned" + G.fields["real_rank"] = "Unassigned" + G.fields["sex"] = "Male" + G.fields["age"] = "Unknown" + G.fields["fingerprint"] = "Unknown" + G.fields["p_stat"] = "Active" + G.fields["m_stat"] = "Stable" + G.fields["species"] = "Human" + data_core.general += G + active1 = G + +//FIELD FUNCTIONS + if ("Edit Field") + var/a1 = active1 + switch(href_list["field"]) + if("name") + if (istype(active1, /datum/data/record)) + var/t1 = input("Please input name:", "Secure. records", active1.fields["name"], null) as text + if ((!( t1 ) || !length(trim(t1)) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon)))) || active1 != a1) + return + active1.fields["name"] = t1 + if("id") + if (istype(active1, /datum/data/record)) + var/t1 = copytext(sanitize(input("Please input id:", "Secure. records", active1.fields["id"], null) as text),1,MAX_MESSAGE_LEN) + if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || active1 != a1)) + return + active1.fields["id"] = t1 + if("fingerprint") + if (istype(active1, /datum/data/record)) + var/t1 = copytext(sanitize(input("Please input fingerprint hash:", "Secure. records", active1.fields["fingerprint"], null) as text),1,MAX_MESSAGE_LEN) + if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || active1 != a1)) + return + active1.fields["fingerprint"] = t1 + if("sex") + if (istype(active1, /datum/data/record)) + if (active1.fields["sex"] == "Male") + active1.fields["sex"] = "Female" + else + active1.fields["sex"] = "Male" + if("age") + if (istype(active1, /datum/data/record)) + var/t1 = input("Please input age:", "Secure. records", active1.fields["age"], null) as num + if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || active1 != a1)) + return + active1.fields["age"] = t1 + if("rank") + var/list/L = list( "Head of Personnel", "Captain", "AI" ) + //This was so silly before the change. Now it actually works without beating your head against the keyboard. /N + if ((istype(active1, /datum/data/record) && L.Find(rank))) + temp = "
Rank:
" + temp += "
    " + for(var/rank in get_all_jobs()) + temp += "
  • [rank]
  • " + temp += "
" + else + alert(usr, "You do not have the required rank to do this!") + if("species") + if (istype(active1, /datum/data/record)) + var/t1 = copytext(sanitize(input("Please enter race:", "General records", active1.fields["species"], null) as message),1,MAX_MESSAGE_LEN) + if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!in_range(src, usr) && (!istype(usr, /mob/living/silicon))) || active1 != a1)) + return + active1.fields["species"] = t1 + +//TEMPORARY MENU FUNCTIONS + else//To properly clear as per clear screen. + temp=null + switch(href_list["choice"]) + if ("Change Rank") + if (active1) + active1.fields["rank"] = href_list["rank"] + if(href_list["rank"] in get_all_jobs()) + active1.fields["real_rank"] = href_list["real_rank"] + + if ("Delete Record (ALL) Execute") + if (active1) + for(var/datum/data/record/R in data_core.medical) + if ((R.fields["name"] == active1.fields["name"] || R.fields["id"] == active1.fields["id"])) + del(R) + else + del(active1) + else + temp = "This function does not appear to be working at the moment. Our apologies." + + add_fingerprint(usr) + updateUsrDialog() + return + +/obj/machinery/computer/skills/emp_act(severity) + if(stat & (BROKEN|NOPOWER)) + ..(severity) + return + + for(var/datum/data/record/R in data_core.security) + if(prob(10/severity)) + switch(rand(1,6)) + if(1) + R.fields["name"] = "[pick(pick(first_names_male), pick(first_names_female))] [pick(last_names)]" + if(2) + R.fields["sex"] = pick("Male", "Female") + if(3) + R.fields["age"] = rand(5, 85) + if(4) + R.fields["criminal"] = pick("None", "*Arrest*", "Incarcerated", "Parolled", "Released") + if(5) + R.fields["p_stat"] = pick("*Unconcious*", "Active", "Physically Unfit") + if(6) + R.fields["m_stat"] = pick("*Insane*", "*Unstable*", "*Watch*", "Stable") + continue + + else if(prob(1)) + del(R) + continue + + ..(severity) \ No newline at end of file diff --git a/code/game/machinery/computer/vox_shuttle.dm b/code/game/machinery/computer/vox_shuttle.dm new file mode 100644 index 00000000000..fa9d05d7b90 --- /dev/null +++ b/code/game/machinery/computer/vox_shuttle.dm @@ -0,0 +1,106 @@ +#define VOX_SHUTTLE_MOVE_TIME 260 +#define VOX_SHUTTLE_COOLDOWN 460 + +//Copied from Syndicate shuttle. +var/global/vox_shuttle_location + +/obj/machinery/computer/vox_station + name = "vox skipjack terminal" + icon = 'icons/obj/computer.dmi' + icon_state = "syndishuttle" + req_access = list(access_syndicate) + var/area/curr_location + var/moving = 0 + var/lastMove = 0 + var/warning //Warning about the end of the round. + +/obj/machinery/computer/vox_station/New() + curr_location= locate(/area/shuttle/vox/station) + + +/obj/machinery/computer/vox_station/proc/vox_move_to(area/destination as area) + if(moving) return + if(lastMove + VOX_SHUTTLE_COOLDOWN > world.time) return + var/area/dest_location = locate(destination) + if(curr_location == dest_location) return + + moving = 1 + lastMove = world.time + + if(curr_location.z != dest_location.z) + var/area/transit_location = locate(/area/vox_station/transit) + curr_location.move_contents_to(transit_location) + curr_location = transit_location + sleep(VOX_SHUTTLE_MOVE_TIME) + + curr_location.move_contents_to(dest_location) + curr_location = dest_location + moving = 0 + + return 1 + + +/obj/machinery/computer/vox_station/attackby(obj/item/I as obj, mob/user as mob) + return attack_hand(user) + +/obj/machinery/computer/vox_station/attack_ai(mob/user as mob) + return attack_hand(user) + +/obj/machinery/computer/vox_station/attack_paw(mob/user as mob) + return attack_hand(user) + +/obj/machinery/computer/vox_station/attack_hand(mob/user as mob) + if(!allowed(user)) + user << "\red Access Denied" + return + + user.set_machine(src) + + var/dat = {"Location: [curr_location]
+ Ready to move[max(lastMove + VOX_SHUTTLE_COOLDOWN - world.time, 0) ? " in [max(round((lastMove + VOX_SHUTTLE_COOLDOWN - world.time) * 0.1), 0)] seconds" : ": now"]
+ Return to dark space
+ Fore port solar | + Aft port solar | + Fore starboard solar
+ Aft starboard solar | + Mining Asteroid
+ Close"} + + user << browse(dat, "window=computer;size=575x450") + onclose(user, "computer") + return + + +/obj/machinery/computer/vox_station/Topic(href, href_list) + if(!isliving(usr)) return + var/mob/living/user = usr + + if(in_range(src, user) || istype(user, /mob/living/silicon)) + user.set_machine(src) + + vox_shuttle_location = "station" + if(href_list["start"]) + if(ticker && (istype(ticker.mode,/datum/game_mode/heist))) + if(!warning) + user << "\red Returning to dark space will end your raid and report your success or failure. If you are sure, press the button again." + warning = 1 + return + vox_move_to(/area/shuttle/vox/station) + vox_shuttle_location = "start" + else if(href_list["solars_fore_starboard"]) + vox_move_to(/area/vox_station/northeast_solars) + else if(href_list["solars_fore_port"]) + vox_move_to(/area/vox_station/northwest_solars) + else if(href_list["solars_aft_starboard"]) + vox_move_to(/area/vox_station/southeast_solars) + else if(href_list["solars_aft_port"]) + vox_move_to(/area/vox_station/southwest_solars) + else if(href_list["mining"]) + vox_move_to(/area/vox_station/mining) + + add_fingerprint(usr) + updateUsrDialog() + return + +/obj/machinery/computer/vox_station/bullet_act(var/obj/item/projectile/Proj) + visible_message("[Proj] ricochets off [src]!") \ No newline at end of file diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm index 4b095488f9d..abe63412304 100644 --- a/code/game/machinery/cryo.dm +++ b/code/game/machinery/cryo.dm @@ -87,7 +87,7 @@ Current cell temperature: [temp_text]K
Cryo status: [ on ? "Off On" : "Off On"]
[beaker_text]

- Current occupant: [occupant ? "
Name: [occupant]
Health: [health_text]
Oxygen deprivation: [round(occupant.getOxyLoss(),0.1)]
Brute damage: [round(occupant.getBruteLoss(),0.1)]
Fire damage: [round(occupant.getFireLoss(),0.1)]
Toxin damage: [round(occupant.getToxLoss(),0.1)]
Body temperature: [occupant.bodytemperature]" : "None"]
+ Current occupant: [occupant ? "
Name: [occupant]
Health: [health_text]
Oxygen deprivation: [round(occupant.getOxyLoss(),0.1)]
Brute damage: [round(occupant.getBruteLoss(),0.1)]
Fire damage: [round(occupant.getFireLoss(),0.1)]
Toxin damage: [round(occupant.getToxLoss(),0.1)]
Body temperature: [occupant.bodytemperature]
Heartbeat rate: [occupant.get_pulse(GETPULSE_TOOL)]" : "None"]
"} user.set_machine(src) user << browse(dat, "window=cryo") diff --git a/code/game/machinery/doors/brigdoors.dm b/code/game/machinery/doors/brigdoors.dm index 4d634d45895..a5eb560e3c1 100644 --- a/code/game/machinery/doors/brigdoors.dm +++ b/code/game/machinery/doors/brigdoors.dm @@ -17,222 +17,287 @@ anchored = 1.0 // can't pick it up density = 0 // can walk through it. var/id = null // id of door it controls. - var/releasetime = 0 // when world.time reaches it - release the prisoneer + var/releasetime = 0 // when world.timeofday reaches it - release the prisoner var/timing = 1 // boolean, true/1 timer is on, false/0 means it's not timing var/picture_state // icon_state of alert picture, if not displaying text/numbers var/list/obj/machinery/targets = list() + var/timetoset = 0 // Used to set releasetime upon starting the timer - New() - ..() +/obj/machinery/door_timer/New() + ..() - pixel_x = ((src.dir & 3)? (0) : (src.dir == 4 ? 32 : -32)) - pixel_y = ((src.dir & 3)? (src.dir ==1 ? 24 : -32) : (0)) + pixel_x = ((src.dir & 3)? (0) : (src.dir == 4 ? 32 : -32)) + pixel_y = ((src.dir & 3)? (src.dir ==1 ? 24 : -32) : (0)) - spawn(20) - for(var/obj/machinery/door/window/brigdoor/M in world) - if (M.id == src.id) - targets += M + spawn(20) + for(var/obj/machinery/door/window/brigdoor/M in world) + if (M.id == src.id) + targets += M - for(var/obj/machinery/flasher/F in world) - if(F.id == src.id) - targets += F + for(var/obj/machinery/flasher/F in world) + if(F.id == src.id) + targets += F - for(var/obj/structure/closet/secure_closet/brig/C in world) - if(C.id == src.id) - targets += C + for(var/obj/structure/closet/secure_closet/brig/C in world) + if(C.id == src.id) + targets += C - if(targets.len==0) - stat |= BROKEN - update_icon() - return + if(targets.len==0) + stat |= BROKEN + update_icon() return + return //Main door timer loop, if it's timing and time is >0 reduce time by 1. // if it's less than 0, open door, reset timer // update the door_timer window and the icon - process() - if(stat & (NOPOWER|BROKEN)) return - if(src.timing) - if(world.time > src.releasetime) - src.timer_end() // open doors, reset timer, clear status screen - src.timing = 0 - src.updateUsrDialog() - src.update_icon() - else - timer_end() - return +/obj/machinery/door_timer/process() + + if(stat & (NOPOWER|BROKEN)) return + if(src.timing) + + // poorly done midnight rollover + // (no seriously there's gotta be a better way to do this) + var/timeleft = timeleft() + if(timeleft > 1e5) + src.releasetime = 0 -// has the door power sitatuation changed, if so update icon. - power_change() - ..() - update_icon() - return + if(world.timeofday > src.releasetime) + src.timer_end() // open doors, reset timer, clear status screen + src.timing = 0 + + src.updateUsrDialog() + src.update_icon() + + else + timer_end() + + return + + +// has the door power situation changed, if so update icon. +/obj/machinery/door_timer/power_change() + ..() + update_icon() + return // open/closedoor checks if door_timer has power, if so it checks if the // linked door is open/closed (by density) then opens it/closes it. - proc/timer_start() - if(stat & (NOPOWER|BROKEN)) return 0 - for(var/obj/machinery/door/window/brigdoor/door in targets) - if(door.density) continue - spawn(0) - door.close() +// Closes and locks doors, power check +/obj/machinery/door_timer/proc/timer_start() + if(stat & (NOPOWER|BROKEN)) return 0 - for(var/obj/structure/closet/secure_closet/brig/C in targets) - if(C.broken) continue - if(C.opened && !C.close()) continue - C.locked = 1 - C.icon_state = C.icon_locked - return 1 + // Set releasetime + releasetime = world.timeofday + timetoset + + for(var/obj/machinery/door/window/brigdoor/door in targets) + if(door.density) continue + spawn(0) + door.close() + + for(var/obj/structure/closet/secure_closet/brig/C in targets) + if(C.broken) continue + if(C.opened && !C.close()) continue + C.locked = 1 + C.icon_state = C.icon_locked + return 1 - proc/timer_end() - if(stat & (NOPOWER|BROKEN)) return 0 +// Opens and unlocks doors, power check +/obj/machinery/door_timer/proc/timer_end() + if(stat & (NOPOWER|BROKEN)) return 0 - for(var/obj/machinery/door/window/brigdoor/door in targets) - if(!door.density) continue - spawn(0) - door.open() + // Reset releasetime + releasetime = 0 - for(var/obj/structure/closet/secure_closet/brig/C in targets) - if(C.broken) continue - if(C.opened) continue - C.locked = 0 - C.icon_state = C.icon_closed + for(var/obj/machinery/door/window/brigdoor/door in targets) + if(!door.density) continue + spawn(0) + door.open() - return 1 + for(var/obj/structure/closet/secure_closet/brig/C in targets) + if(C.broken) continue + if(C.opened) continue + C.locked = 0 + C.icon_state = C.icon_closed + + return 1 - proc/timeleft() - . = (releasetime-world.time)/10 - if(. < 0) - . = 0 +// Check for releasetime timeleft +/obj/machinery/door_timer/proc/timeleft() + . = (releasetime - world.timeofday)/10 + if(. < 0) + . = 0 +// Set timetoset +/obj/machinery/door_timer/proc/timeset(var/seconds) + timetoset = seconds * 10 - proc/timeset(var/seconds) - releasetime=world.time+seconds*10 - return + if(timetoset <= 0) + timetoset = 0 + return //Allows AIs to use door_timer, see human attack_hand function below - attack_ai(var/mob/user as mob) - return src.attack_hand(user) +/obj/machinery/door_timer/attack_ai(var/mob/user as mob) + return src.attack_hand(user) //Allows humans to use door_timer //Opens dialog window when someone clicks on door timer // Allows altering timer and the timing boolean. // Flasher activation limited to 150 seconds - attack_hand(var/mob/user as mob) - if(..()) - return - var/second = round(timeleft() % 60) - var/minute = round((timeleft() - second) / 60) - user.set_machine(src) - var/dat = "" - dat += "
Timer System:" - dat += "Door [src.id] controls
" - if (src.timing) - dat += "Stop Timer and open door
" - else - dat += "Activate Timer and close door
" - - dat += "Time Left: [(minute ? text("[minute]:") : null)][second]
" - dat += "- - + +
" - - for(var/obj/machinery/flasher/F in targets) - if(F.last_flash && (F.last_flash + 150) > world.time) - dat += "
Flash Charging" - else - dat += "
Activate Flash" - - dat += "

Close" - dat += "
" - user << browse(dat, "window=computer;size=400x500") - onclose(user, "computer") +/obj/machinery/door_timer/attack_hand(var/mob/user as mob) + if(..()) return + // Used for the 'time left' display + var/second = round(timeleft() % 60) + var/minute = round((timeleft() - second) / 60) + + // Used for 'set timer' + var/setsecond = round((timetoset / 10) % 60) + var/setminute = round(((timetoset / 10) - setsecond) / 60) + + user.set_machine(src) + + // dat + var/dat = "" + + dat += "
Timer System:" + dat += " Door [src.id] controls
" + + // Start/Stop timer + if (src.timing) + dat += "Stop Timer and open door
" + else + dat += "Activate Timer and close door
" + + // Time Left display (uses releasetime) + dat += "Time Left: [(minute ? text("[minute]:") : null)][second]
" + dat += "
" + + // Set Timer display (uses timetoset) + if(src.timing) + dat += "Set Timer: [(setminute ? text("[setminute]:") : null)][setsecond] Set
" + else + dat += "Set Timer: [(setminute ? text("[setminute]:") : null)][setsecond]
" + + // Controls + dat += "- - + +
" + + // Mounted flash controls + for(var/obj/machinery/flasher/F in targets) + if(F.last_flash && (F.last_flash + 150) > world.time) + dat += "
Flash Charging" + else + dat += "
Activate Flash" + + dat += "

Close" + dat += "
" + + user << browse(dat, "window=computer;size=400x500") + onclose(user, "computer") + return + //Function for using door_timer dialog input, checks if user has permission // href_list to // "timing" turns on timer // "tp" value to modify timer // "fc" activates flasher +// "change" resets the timer to the timetoset amount while the timer is counting down // Also updates dialog window and timer icon - Topic(href, href_list) - if(..()) - return - if(!src.allowed(usr)) - return +/obj/machinery/door_timer/Topic(href, href_list) + if(..()) + return + if(!src.allowed(usr)) + return + + usr.set_machine(src) + + if(href_list["timing"]) + src.timing = text2num(href_list["timing"]) - usr.set_machine(src) - if(href_list["timing"]) - src.timing = text2num(href_list["timing"]) - else - if(href_list["tp"]) //adjust timer, close door if not already closed - var/tp = text2num(href_list["tp"]) - var/timeleft = timeleft() - timeleft += tp - timeleft = min(max(round(timeleft), 0), 3600) - timeset(timeleft) - //src.timing = 1 - //src.closedoor() - if(href_list["fc"]) - for(var/obj/machinery/flasher/F in targets) - F.flash() - src.add_fingerprint(usr) - src.updateUsrDialog() - src.update_icon() if(src.timing) src.timer_start() else src.timer_end() - return + + else + if(href_list["tp"]) //adjust timer, close door if not already closed + var/tp = text2num(href_list["tp"]) + var/addtime = (timetoset / 10) + addtime += tp + addtime = min(max(round(addtime), 0), 3600) + + timeset(addtime) + + if(href_list["fc"]) + for(var/obj/machinery/flasher/F in targets) + F.flash() + + if(href_list["change"]) + src.timer_start() + + src.add_fingerprint(usr) + src.updateUsrDialog() + src.update_icon() + + /* if(src.timing) + src.timer_start() + + else + src.timer_end() */ + + return //icon update function // if NOPOWER, display blank // if BROKEN, display blue screen of death icon AI uses // if timing=true, run update display function - update_icon() - if(stat & (NOPOWER)) - icon_state = "frame" - return - if(stat & (BROKEN)) - set_picture("ai_bsod") - return - if(src.timing) - var/disp1 = uppertext(id) - var/timeleft = timeleft() - var/disp2 = "[add_zero(num2text((timeleft / 60) % 60),2)]~[add_zero(num2text(timeleft % 60), 2)]" - spawn( 5 ) - update_display(disp1, disp2) - else - update_display("SET","TIME") +/obj/machinery/door_timer/update_icon() + if(stat & (NOPOWER)) + icon_state = "frame" return + if(stat & (BROKEN)) + set_picture("ai_bsod") + return + if(src.timing) + var/disp1 = uppertext(id) + var/timeleft = timeleft() + var/disp2 = "[add_zero(num2text((timeleft / 60) % 60),2)]~[add_zero(num2text(timeleft % 60), 2)]" + spawn( 5 ) + update_display(disp1, disp2) + else + update_display("SET","TIME") + return // Adds an icon in case the screen is broken/off, stolen from status_display.dm - proc/set_picture(var/state) - picture_state = state - overlays.Cut() - overlays += image('icons/obj/status_display.dmi', icon_state=picture_state) +/obj/machinery/door_timer/proc/set_picture(var/state) + picture_state = state + overlays.Cut() + overlays += image('icons/obj/status_display.dmi', icon_state=picture_state) //Checks to see if there's 1 line or 2, adds text-icons-numbers/letters over display // Stolen from status_display - proc/update_display(var/line1, var/line2) - if(line2 == null) // single line display - overlays.Cut() - overlays += texticon(line1, 23, -13) - else // dual line display - overlays.Cut() - overlays += texticon(line1, 23, -9) - overlays += texticon(line2, 23, -17) +/obj/machinery/door_timer/proc/update_display(var/line1, var/line2) + if(line2 == null) // single line display + overlays.Cut() + overlays += texticon(line1, 23, -13) + else // dual line display + overlays.Cut() + overlays += texticon(line1, 23, -9) + overlays += texticon(line2, 23, -17) // return an icon of a time text string (tn) // valid characters are 0-9 and : // px, py are pixel offsets @@ -240,19 +305,19 @@ //Actual string input to icon display for loop, with 5 pixel x offsets for each letter. //Stolen from status_display - proc/texticon(var/tn, var/px = 0, var/py = 0) - var/image/I = image('icons/obj/status_display.dmi', "blank") - var/len = lentext(tn) +/obj/machinery/door_timer/proc/texticon(var/tn, var/px = 0, var/py = 0) + var/image/I = image('icons/obj/status_display.dmi', "blank") + var/len = lentext(tn) - for(var/d = 1 to len) - var/char = copytext(tn, len-d+1, len-d+2) - if(char == " ") - continue - var/image/ID = image('icons/obj/status_display.dmi', icon_state=char) - ID.pixel_x = -(d-1)*5 + px - ID.pixel_y = py - I.overlays += ID - return I + for(var/d = 1 to len) + var/char = copytext(tn, len-d+1, len-d+2) + if(char == " ") + continue + var/image/ID = image('icons/obj/status_display.dmi', icon_state=char) + ID.pixel_x = -(d-1)*5 + px + ID.pixel_y = py + I.overlays += ID + return I /obj/machinery/door_timer/cell_1 diff --git a/code/game/machinery/hydroponics.dm b/code/game/machinery/hydroponics.dm index 5d187b337c7..a0f8c371e41 100644 --- a/code/game/machinery/hydroponics.dm +++ b/code/game/machinery/hydroponics.dm @@ -915,115 +915,13 @@ obj/machinery/hydroponics/attackby(var/obj/item/O as obj, var/mob/user as mob) parent.update_tray() -/obj/item/seeds/replicapod/harvest(mob/user = usr) //now that one is fun -- Urist - var/obj/machinery/hydroponics/parent = loc - var/make_podman = 0 - var/mob/ghost - if(ckey && config.revival_pod_plants) - ghost = find_dead_player("[ckey]") - if(ismob(ghost)) - if(istype(ghost,/mob/dead/observer)) - var/mob/dead/observer/O = ghost - if(istype(mind,/datum/mind)) - if(O.can_reenter_corpse) - make_podman = 1 - else - make_podman = 1 - - if(make_podman) //all conditions met! - var/mob/living/carbon/human/podman = new /mob/living/carbon/human(parent.loc) - if(realName) - podman.real_name = realName - else - podman.real_name = "Pod Person [rand(0,999)]" - var/oldactive = mind.active - mind.active = 1 - mind.transfer_to(podman) - mind.active = oldactive - // -- Mode/mind specific stuff goes here. TODO! Broken :( Should be merged into mob/living/Login - switch(ticker.mode.name) - if ("revolution") - if (podman.mind in ticker.mode:revolutionaries) - ticker.mode:add_revolutionary(podman.mind) - ticker.mode:update_all_rev_icons() //So the icon actually appears - if (podman.mind in ticker.mode:head_revolutionaries) - ticker.mode:update_all_rev_icons() - if ("nuclear emergency") - if (podman.mind in ticker.mode:syndicates) - ticker.mode:update_all_synd_icons() - if ("cult") - if (podman.mind in ticker.mode:cult) - ticker.mode:add_cultist(podman.mind) - ticker.mode:update_all_cult_icons() //So the icon actually appears - - // -- End mode specific stuff - - podman.gender = ghost.gender - if(podman.gender in list(NEUTER, PLURAL)) //Sanity check, which should never actually happen. - podman.gender = pick(MALE,FEMALE) - - if(!podman.dna) - podman.dna = new /datum/dna() - podman.dna.real_name = podman.real_name - if(ui) - podman.dna.uni_identity = ui - updateappearance(podman, ui) - if(se) - podman.dna.struc_enzymes = se - if(!prob(potency)) //if it fails, plantman! - if(podman) -// podman.dna.mutantrace = "plant" - podman.mutations.Add(PLANT) - podman.update_mutantrace() - - else //else, one packet of seeds. maybe two - var/seed_count = 1 - if(prob(yield * parent.yieldmod * 20)) - seed_count++ - for(var/i=0,i 0) - var/transfer_amount = REAGENTS_METABOLISM - if(istype(src.beaker, /obj/item/weapon/reagent_containers/blood)) - // speed up transfer on blood packs - transfer_amount = 4 - src.beaker.reagents.trans_to(src.attached, transfer_amount) - update_icon() + if(mode) + if(src.beaker.volume > 0) + var/transfer_amount = REAGENTS_METABOLISM + if(istype(src.beaker, /obj/item/weapon/reagent_containers/blood)) + // speed up transfer on blood packs + transfer_amount = 4 + src.beaker.reagents.trans_to(src.attached, transfer_amount) + update_icon() // Take blood - else if(mode == "take") + else var/amount = beaker.reagents.maximum_volume - beaker.reagents.total_volume amount = min(amount, 4) // If the beaker is full, ping @@ -134,34 +135,25 @@ usr << "\red You can't do that." return - if(mode == "give") - mode = "take" - usr << "The IV drip is now taking blood." - else if(mode == "take") - mode = "give" - usr << "The IV drip is now giving blood." + if(usr.stat) + return + + mode = !mode + usr << "The IV drip is now [mode ? "injecting" : "taking blood"]." /obj/machinery/iv_drip/examine() set src in view() ..() if (!(usr in view(2)) && usr!=src.loc) return - if(mode == "take") - usr << "The IV drip is taking blood." - else if(mode == "give") - usr << "The IV drip is injecting." + usr << "The IV drip is [mode ? "injecting" : "taking blood"]." if(beaker) - usr << "\blue Attached is \a [beaker] with:" if(beaker.reagents && beaker.reagents.reagent_list.len) - for(var/datum/reagent/R in beaker.reagents.reagent_list) - usr << "\blue [R.volume] units of [R.name]" + usr << "\blue Attached is \a [beaker] with [beaker.reagents.total_volume] units of liquid." else usr << "\blue Attached is an empty [beaker]." else usr << "\blue No chemicals are attached." - if(attached) - usr << "\blue [attached] is attached." - else - usr << "\blue No one is attached." \ No newline at end of file + usr << "\blue [attached ? attached : "No one"] is attached." \ No newline at end of file diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm index b199c79c202..af52a4e7565 100644 --- a/code/game/machinery/newscaster.dm +++ b/code/game/machinery/newscaster.dm @@ -435,7 +435,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon))) usr.set_machine(src) if(href_list["set_channel_name"]) - src.channel_name = strip_html_simple(input(usr, "Provide a Feed Channel Name", "Network Channel Handler", "")) + src.channel_name = sanitizeSQL(strip_html_simple(input(usr, "Provide a Feed Channel Name", "Network Channel Handler", ""))) while (findtext(src.channel_name," ") == 1) src.channel_name = copytext(src.channel_name,2,lentext(src.channel_name)+1) src.updateUsrDialog() diff --git a/code/game/machinery/podmen.dm b/code/game/machinery/podmen.dm new file mode 100644 index 00000000000..abf5c52aa81 --- /dev/null +++ b/code/game/machinery/podmen.dm @@ -0,0 +1,153 @@ +/* Moved all the plant people code here for ease of reference and coherency. +Injecting a pod person with a blood sample will grow a pod person with the memories and persona of that mob. +Growing it to term with nothing injected will grab a ghost from the observers. */ + +/obj/item/seeds/replicapod + name = "pack of dionaea-replicant seeds" + desc = "These seeds grow into 'replica pods' or 'dionaea', a form of strange sapient plantlife." + icon_state = "seed-replicapod" + mypath = "/obj/item/seeds/replicapod" + species = "replicapod" + plantname = "Dionaea" + productname = "/mob/living/carbon/human" //verrry special -- Urist + lifespan = 50 //no idea what those do + endurance = 8 + maturation = 5 + production = 10 + yield = 1 //seeds if there isn't a dna inside + oneharvest = 1 + potency = 30 + plant_type = 0 + growthstages = 6 + var/ckey = null + var/realName = null + var/mob/living/carbon/human/source //Donor of blood, if any. + gender = MALE + +/obj/item/seeds/replicapod/attackby(obj/item/weapon/W as obj, mob/user as mob) + + if(istype(W,/obj/item/weapon/reagent_containers)) + + user << "You inject the contents of the syringe into the seeds." + + var/datum/reagent/blood/B + + //Find a blood sample to inject. + for(var/datum/reagent/R in W:reagents.reagent_list) + if(istype(R,/datum/reagent/blood)) + B = R + break + if(B) + source = B.data["donor"] + user << "The strange, sluglike seeds quiver gently and swell with blood." + if(!source.client && source.mind) + for(var/mob/dead/observer/O in player_list) + if(O.mind == source.mind && config.revival_pod_plants) + O << "Your blood has been placed into a replica pod seed. Return to your body if you want to be returned to life as a pod person! (Verbs -> Ghost -> Re-enter corpse)" + break + else + user << "Nothing happens." + return + + if (!istype(source)) + return + + if(source.ckey) + realName = source.real_name + ckey = source.ckey + + W:reagents.clear_reagents() + return + + return ..() + +/obj/item/seeds/replicapod/harvest(mob/user = usr) + + var/obj/machinery/hydroponics/parent = loc + var/mob/ghost + var/list/candidates = list() + + user.visible_message("\blue You carefully begin to open the pod...","[user] carefully begins to open the pod...") + + //If a sample is injected (and revival is allowed) the plant will be controlled by the original donor. + if(source && source.mind && source.ckey && config.revival_pod_plants) + ghost = source + else // If no sample was injected or revival is not allowed, we grab an interested observer. + for(var/mob/dead/observer/O in player_list) + if(O.client && O.client.prefs.be_special & BE_PLANT) + var/response = alert(O, "Someone is harvesting a replica pod. Would you like to play as a Dionaea?", "Replica pod harvest", "Yes", "No", "Never for this round.") + if(response == "Yes") + candidates += O + else if(response == "Never for this round") + O.client.prefs.be_special ^= BE_PLANT + + if(!do_after(user, 100)) + return + + if(candidates.len) + ghost = pick(candidates) + + //If we don't have a ghost or the ghost is now unplayed, we just give the harvester some seeds. + if(!ghost || !(ghost.ckey) || ghost.stat != 2) + user << "The pod has formed badly, and all you can do is salvage some of the seeds." + var/seed_count = 1 + + if(prob(yield * parent.yieldmod * 20)) + seed_count++ + + for(var/i=0,iYou awaken slowly, feeling your sap stir into sluggish motion as the warm air caresses your bark." + if(source && ckey && podman.ckey == ckey) + podman << "Memories of a life as [source] drift oddly through a mind unsuited for them, like a skin of oil over a fathomless lake." + podman << "You are now one of the Dionaea, a race of drifting interstellar plantlike creatures that sometimes share their seeds with human traders." + podman << "Too much darkness will send you into shock and starve you, but light will help you heal." + + if(!realName) + var/newname = input(podman,"Enter a name, or leave blank for the default name.", "Name change","") as text + if (newname != "") + podman.real_name = newname + parent.update_tray() \ No newline at end of file diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm index 4ab483076b7..7302ed81b6c 100644 --- a/code/game/machinery/telecomms/broadcaster.dm +++ b/code/game/machinery/telecomms/broadcaster.dm @@ -341,12 +341,10 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept freq_text = "Engineering" if(1359) freq_text = "Security" -// if(1349) -// freq_text = "Mining" if(1347) freq_text = "Supply" if(1441) - freq_text = "Death Squad" + freq_text = "Special Ops" if(1443) freq_text = "Response Team" //There's probably a way to use the list var of channels in code\game\communications.dm to make the dept channels non-hardcoded, but I wasn't in an experimentive mood. --NEO @@ -365,10 +363,35 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept var/part_b = " \icon[radio]\[[freq_text]\][part_b_extra] " // Tweaked for security headsets -- TLE var/part_c = "" - if (display_freq==SYND_FREQ) + // syndies! + if (display_freq == SYND_FREQ) part_a = "" - else if (display_freq==COMM_FREQ) + + // centcomm channels (deathsquid and ert) + else if (display_freq in CENT_FREQS) + part_a = "" + + // command channel + else if (display_freq == COMM_FREQ) part_a = "" + + // department radio formatting (poorly optimized, ugh) + else if (display_freq == SEC_FREQ) + part_a = "" + + else if (display_freq == ENG_FREQ) + part_a = "" + + else if (display_freq == SCI_FREQ) + part_a = "" + + else if (display_freq == MED_FREQ) + part_a = "" + + else if (display_freq == SUP_FREQ) // cargo + part_a = "" + + // If all else fails and it's a dept_freq, color me purple! else if (display_freq in DEPT_FREQS) part_a = "" @@ -406,8 +429,6 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept blackbox.msg_deathsquad += blackbox_msg if(1213) blackbox.msg_syndicate += blackbox_msg -// if(1349) -// blackbox.msg_mining += blackbox_msg if(1347) blackbox.msg_cargo += blackbox_msg else @@ -629,8 +650,6 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept freq_text = "Engineering" if(1359) freq_text = "Security" -// if(1349) -// freq_text = "Mining" if(1347) freq_text = "Supply" //There's probably a way to use the list var of channels in code\game\communications.dm to make the dept channels non-hardcoded, but I wasn't in an experimentive mood. --NEO @@ -685,8 +704,6 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept blackbox.msg_deathsquad += blackbox_msg if(1213) blackbox.msg_syndicate += blackbox_msg -// if(1349) -// blackbox.msg_mining += blackbox_msg if(1347) blackbox.msg_cargo += blackbox_msg else diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm index 2b708ded291..914bd8c9016 100644 --- a/code/game/machinery/telecomms/presets.dm +++ b/code/game/machinery/telecomms/presets.dm @@ -142,12 +142,7 @@ id = "Supply Server" freq_listening = list(1347) autolinkers = list("supply") -/* -/obj/machinery/telecomms/server/presets/mining - id = "Mining Server" - freq_listening = list(1349) - autolinkers = list("mining") -*/ + /obj/machinery/telecomms/server/presets/common id = "Common Server" freq_listening = list() diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index d98d57de30b..9439757282a 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -312,17 +312,7 @@ if(usr.stat || usr.restrained()) return - if(istype(usr,/mob/living/silicon)) - if(istype(usr,/mob/living/silicon/robot)) - var/mob/living/silicon/robot/R = usr - if(!(R.module && istype(R.module,/obj/item/weapon/robot_module/butler) )) - usr << "\red The vending machine refuses to interface with you, as you are not in its target demographic!" - return - else - usr << "\red The vending machine refuses to interface with you, as you are not in its target demographic!" - return - - if(href_list["remove_coin"]) + if(href_list["remove_coin"] && !istype(usr,/mob/living/silicon)) if(!coin) usr << "There is no coin in this machine." return @@ -338,6 +328,16 @@ usr.set_machine(src) if ((href_list["vend"]) && (src.vend_ready) && (!currently_vending)) + if(istype(usr,/mob/living/silicon)) + if(istype(usr,/mob/living/silicon/robot)) + var/mob/living/silicon/robot/R = usr + if(!(R.module && istype(R.module,/obj/item/weapon/robot_module/butler) )) + usr << "\red The vending machine refuses to interface with you, as you are not in its target demographic!" + return + else + usr << "\red The vending machine refuses to interface with you, as you are not in its target demographic!" + return + if ((!src.allowed(usr)) && (!src.emagged) && (src.wires & WIRE_SCANID)) //For SECURE VENDING MACHINES YEAH usr << "\red Access denied." //Unless emagged of course flick(src.icon_deny,src) @@ -707,7 +707,8 @@ products = list(/obj/item/weapon/reagent_containers/glass/bottle/antitoxin = 4,/obj/item/weapon/reagent_containers/glass/bottle/inaprovaline = 4, /obj/item/weapon/reagent_containers/glass/bottle/stoxin = 4,/obj/item/weapon/reagent_containers/glass/bottle/toxin = 4, /obj/item/weapon/reagent_containers/syringe/antiviral = 4,/obj/item/weapon/reagent_containers/syringe = 12, - /obj/item/device/healthanalyzer = 5,/obj/item/weapon/reagent_containers/glass/beaker = 4, /obj/item/weapon/reagent_containers/dropper = 2) + /obj/item/device/healthanalyzer = 5,/obj/item/weapon/reagent_containers/glass/beaker = 4, /obj/item/weapon/reagent_containers/dropper = 2, + /obj/item/stack/medical/advanced/bruise_pack = 3, /obj/item/stack/medical/advanced/ointment = 3, /obj/item/stack/medical/splint = 2) contraband = list(/obj/item/weapon/reagent_containers/pill/tox = 3,/obj/item/weapon/reagent_containers/pill/stox = 4,/obj/item/weapon/reagent_containers/pill/antitox = 6) @@ -727,7 +728,7 @@ icon_deny = "wallmed-deny" req_access_txt = "5" density = 0 //It is wall-mounted, and thus, not dense. --Superxpdude - products = list(/obj/item/stack/medical/bruise_pack = 2,/obj/item/stack/medical/ointment = 2,/obj/item/weapon/reagent_containers/syringe/inaprovaline = 4,/obj/item/device/healthanalyzer = 1) + products = list(/obj/item/stack/medical/bruise_pack = 2,/obj/item/stack/medical/ointment = 2,/obj/item/weapon/reagent_containers/hypospray/autoinjector = 4,/obj/item/device/healthanalyzer = 1) contraband = list(/obj/item/weapon/reagent_containers/syringe/antitoxin = 4,/obj/item/weapon/reagent_containers/syringe/antiviral = 4,/obj/item/weapon/reagent_containers/pill/tox = 1) /obj/machinery/vending/wallmed2 @@ -737,7 +738,7 @@ icon_deny = "wallmed-deny" req_access_txt = "5" density = 0 //It is wall-mounted, and thus, not dense. --Superxpdude - products = list(/obj/item/weapon/reagent_containers/syringe/inaprovaline = 5,/obj/item/weapon/reagent_containers/syringe/antitoxin = 3,/obj/item/stack/medical/bruise_pack = 3, + products = list(/obj/item/weapon/reagent_containers/hypospray/autoinjector = 5,/obj/item/weapon/reagent_containers/syringe/antitoxin = 3,/obj/item/stack/medical/bruise_pack = 3, /obj/item/stack/medical/ointment =3,/obj/item/device/healthanalyzer = 3) contraband = list(/obj/item/weapon/reagent_containers/pill/tox = 3) diff --git a/code/game/mecha/equipment/tools/tools.dm b/code/game/mecha/equipment/tools/tools.dm index 81243486139..c877084339b 100644 --- a/code/game/mecha/equipment/tools/tools.dm +++ b/code/game/mecha/equipment/tools/tools.dm @@ -20,6 +20,8 @@ action(atom/target) if(!action_checks(target)) return if(!cargo_holder) return + if(istype(target, /obj/structure/stool)) return + if(istype(target,/obj)) var/obj/O = target if(!O.anchored) @@ -482,6 +484,7 @@ return "[..()] [mode==1?"([locked||"Nothing"])":null] \[S|P\]" Topic(href, href_list) + ..() if(href_list["mode"]) mode = text2num(href_list["mode"]) send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index 5bf46648228..7b72a5597bf 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -49,7 +49,8 @@ /obj/item/robot_parts/robot_component/radio, /obj/item/robot_parts/robot_component/actuator, /obj/item/robot_parts/robot_component/diagnosis_unit, - /obj/item/robot_parts/robot_component/camera + /obj/item/robot_parts/robot_component/camera, + /obj/item/robot_parts/robot_component/armour ), "Ripley"=list( /obj/item/mecha_parts/chassis/ripley, diff --git a/code/game/mecha/medical/odysseus.dm b/code/game/mecha/medical/odysseus.dm index 869ff5b2103..008b5d819ab 100644 --- a/code/game/mecha/medical/odysseus.dm +++ b/code/game/mecha/medical/odysseus.dm @@ -87,8 +87,11 @@ for(var/datum/disease/D in patient.viruses) if(!D.hidden[SCANNER]) foundVirus++ - if(patient.virus2) - foundVirus++ + + for (var/ID in patient.virus2) + if (ID in virusDB) + foundVirus = 1 + break holder = patient.hud_list[HEALTH_HUD] if(patient.stat == 2) diff --git a/code/game/objects/effects/barsign.dm b/code/game/objects/effects/barsign.dm index fc6278187e9..c5cc2893567 100644 --- a/code/game/objects/effects/barsign.dm +++ b/code/game/objects/effects/barsign.dm @@ -1,4 +1,4 @@ -/obj/effect/sign/barsign +/obj/effect/sign/double/barsign icon = 'barsigns.dmi' icon_state = "empty" anchored = 1 diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm index 172eca9ae97..911a63c0e4c 100644 --- a/code/game/objects/effects/decals/Cleanable/humans.dm +++ b/code/game/objects/effects/decals/Cleanable/humans.dm @@ -11,7 +11,7 @@ random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7") var/list/viruses = list() blood_DNA = list() - var/datum/disease2/disease/virus2 = null + var/list/datum/disease2/disease/virus2 = list() var/amount = 5 /obj/effect/decal/cleanable/blood/Del() @@ -144,4 +144,4 @@ icon = 'blood.dmi' icon_state = "mucus" random_icon_states = list("mucus") - var/datum/disease2/disease/virus2 = null + var/list/datum/disease2/disease/virus2 = list() diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm index 91ea8124393..cc4d766f25a 100644 --- a/code/game/objects/explosion.dm +++ b/code/game/objects/explosion.dm @@ -19,10 +19,10 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa epicenter = get_turf(epicenter) if(!epicenter) return - + playsound(epicenter, 'sound/effects/explosionfar.ogg', 100, 1, round(devastation_range*2,1) ) playsound(epicenter, "explosion", 100, 1, round(devastation_range,1) ) - + var/close = range(world.view+round(devastation_range,1), epicenter) // to all distanced mobs play a different sound for(var/mob/M in world) if(M.z == epicenter.z) if(!(M in close)) @@ -30,7 +30,7 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa if(M.ear_deaf <= 0 || !M.ear_deaf) if(!istype(M.loc,/turf/space)) M << 'explosionfar.ogg' if(adminlog) - message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z])") + message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z]) (JMP)") log_game("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ") var/lighting_controller_was_processing = lighting_controller.processing //Pause the lighting updates for a bit @@ -85,4 +85,4 @@ proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impa proc/secondaryexplosion(turf/epicenter, range) for(var/turf/tile in range(range, epicenter)) - tile.ex_act(2) + tile.ex_act(2) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 78cf9617fd3..c55684eb197 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -113,9 +113,10 @@ var/datum/organ/external/temp = user:organs_by_name["r_hand"] if (user.hand) temp = user:organs_by_name["l_hand"] - if(temp && temp.status & ORGAN_DESTROYED) - user << " Yo- wait a minute." + if(temp && !temp.is_usable()) + user << "You try to move your [temp.display_name], but cannot!" return + if (istype(src.loc, /obj/item/weapon/storage)) var/obj/item/weapon/storage/S = src.loc S.remove_from_storage(src) diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 33fc438c4ac..378d08f880d 100755 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -288,7 +288,7 @@ var/global/list/obj/item/device/pda/PDAs = list() return 0 var/mob/M = loc - if(!M.canmove) + if(M.stat || M.restrained() || M.paralysis || M.stunned || M.weakened) return 0 if((src in M.contents) || ( istype(loc, /turf) && in_range(src, M) )) return 1 @@ -306,7 +306,7 @@ var/global/list/obj/item/device/pda/PDAs = list() /obj/item/device/pda/MouseDrop(obj/over_object as obj, src_location, over_location) var/mob/M = usr - if((!istype(over_object, /obj/screen)) && !M.restrained() && !M.stat && can_use()) + if((!istype(over_object, /obj/screen)) && can_use()) return attack_self(M) return @@ -520,231 +520,226 @@ var/global/list/obj/item/device/pda/PDAs = list() //if ((src in U.contents) || ( istype(loc, /turf) && in_range(src, U) ) ) if(can_use()) //Why reinvent the wheel? There's a proc that does exactly that. - if ( !(U.stat || U.restrained()) ) - add_fingerprint(U) - U.set_machine(src) + add_fingerprint(U) + U.set_machine(src) - switch(href_list["choice"]) + switch(href_list["choice"]) //BASIC FUNCTIONS=================================== - if("Close")//Self explanatory - U.unset_machine() - U << browse(null, "window=pda") - return - if("Refresh")//Refresh, goes to the end of the proc. - if("Return")//Return - if(mode<=9) + if("Close")//Self explanatory + U.unset_machine() + U << browse(null, "window=pda") + return + if("Refresh")//Refresh, goes to the end of the proc. + if("Return")//Return + if(mode<=9) + mode = 0 + else + mode = round(mode/10) + if(mode==4)//Fix for cartridges. Redirects to hub. mode = 0 - else - mode = round(mode/10) - if(mode==4)//Fix for cartridges. Redirects to hub. - mode = 0 - else if(mode >= 40 && mode <= 49)//Fix for cartridges. Redirects to refresh the menu. - cartridge.mode = mode - cartridge.unlock() - if ("Authenticate")//Checks for ID - id_check(U, 1) - if("UpdateInfo") - ownjob = id.assignment - name = "PDA-[owner] ([ownjob])" - if("Eject")//Ejects the cart, only done from hub. - if (!isnull(cartridge)) - var/turf/T = loc - if(ismob(T)) - T = T.loc - cartridge.loc = T - scanmode = 0 - if (cartridge.radio) - cartridge.radio.hostpda = null - cartridge = null + else if(mode >= 40 && mode <= 49)//Fix for cartridges. Redirects to refresh the menu. + cartridge.mode = mode + cartridge.unlock() + if ("Authenticate")//Checks for ID + id_check(U, 1) + if("UpdateInfo") + ownjob = id.assignment + name = "PDA-[owner] ([ownjob])" + if("Eject")//Ejects the cart, only done from hub. + if (!isnull(cartridge)) + var/turf/T = loc + if(ismob(T)) + T = T.loc + cartridge.loc = T + scanmode = 0 + if (cartridge.radio) + cartridge.radio.hostpda = null + cartridge = null //MENU FUNCTIONS=================================== - if("0")//Hub - mode = 0 - if("1")//Notes - mode = 1 - if("2")//Messenger - mode = 2 - if("21")//Read messeges - mode = 21 - if("3")//Atmos scan - mode = 3 - if("4")//Redirects to hub - mode = 0 - if("chatroom") // chatroom hub - mode = 5 - if("41") //Manifest - mode = 41 + if("0")//Hub + mode = 0 + if("1")//Notes + mode = 1 + if("2")//Messenger + mode = 2 + if("21")//Read messeges + mode = 21 + if("3")//Atmos scan + mode = 3 + if("4")//Redirects to hub + mode = 0 + if("chatroom") // chatroom hub + mode = 5 + if("41") //Manifest + mode = 41 //MAIN FUNCTIONS=================================== - if("Light") - if(fon) - fon = 0 - if(src in U.contents) U.SetLuminosity(U.luminosity - f_lum) - else SetLuminosity(0) - else - fon = 1 - if(src in U.contents) U.SetLuminosity(U.luminosity + f_lum) - else SetLuminosity(f_lum) - if("Medical Scan") - if(scanmode == 1) - scanmode = 0 - else if((!isnull(cartridge)) && (cartridge.access_medical)) - scanmode = 1 - if("Reagent Scan") - if(scanmode == 3) - scanmode = 0 - else if((!isnull(cartridge)) && (cartridge.access_reagent_scanner)) - scanmode = 3 - if("Halogen Counter") - if(scanmode == 4) - scanmode = 0 - else if((!isnull(cartridge)) && (cartridge.access_engine)) - scanmode = 4 - if("Honk") - if ( !(last_honk && world.time < last_honk + 20) ) - playsound(loc, 'sound/items/bikehorn.ogg', 50, 1) - last_honk = world.time - if("Gas Scan") - if(scanmode == 5) - scanmode = 0 - else if((!isnull(cartridge)) && (cartridge.access_atmos)) - scanmode = 5 + if("Light") + if(fon) + fon = 0 + if(src in U.contents) U.SetLuminosity(U.luminosity - f_lum) + else SetLuminosity(0) + else + fon = 1 + if(src in U.contents) U.SetLuminosity(U.luminosity + f_lum) + else SetLuminosity(f_lum) + if("Medical Scan") + if(scanmode == 1) + scanmode = 0 + else if((!isnull(cartridge)) && (cartridge.access_medical)) + scanmode = 1 + if("Reagent Scan") + if(scanmode == 3) + scanmode = 0 + else if((!isnull(cartridge)) && (cartridge.access_reagent_scanner)) + scanmode = 3 + if("Halogen Counter") + if(scanmode == 4) + scanmode = 0 + else if((!isnull(cartridge)) && (cartridge.access_engine)) + scanmode = 4 + if("Honk") + if ( !(last_honk && world.time < last_honk + 20) ) + playsound(loc, 'sound/items/bikehorn.ogg', 50, 1) + last_honk = world.time + if("Gas Scan") + if(scanmode == 5) + scanmode = 0 + else if((!isnull(cartridge)) && (cartridge.access_atmos)) + scanmode = 5 //MESSENGER/NOTE FUNCTIONS=================================== - if ("Edit") - var/n = input(U, "Please enter message", name, notehtml) as message - if (in_range(src, U) && loc == U) - n = copytext(adminscrub(n), 1, MAX_MESSAGE_LEN) - if (mode == 1) - note = replacetext(n, "\n", "
") - notehtml = n - else - U << browse(null, "window=pda") - return - if("Toggle Messenger") - toff = !toff - if("Toggle Ringer")//If viewing texts then erase them, if not then toggle silent status - silent = !silent - if("Clear")//Clears messages - tnote = null - if("Ringtone") - var/t = input(U, "Please enter new ringtone", name, ttone) as text - if (in_range(src, U) && loc == U) - if (t) - if(src.hidden_uplink && hidden_uplink.check_trigger(U, lowertext(t), lowertext(lock_code))) - U << "The PDA softly beeps." - U << browse(null, "window=pda") - else - t = copytext(sanitize(t), 1, 20) - ttone = t - else - U << browse(null, "window=pda") - return - if("Message") - var/obj/item/device/pda/P = locate(href_list["target"]) - src.create_message(U, P) + if ("Edit") + var/n = input(U, "Please enter message", name, notehtml) as message + if (in_range(src, U) && loc == U) + n = copytext(adminscrub(n), 1, MAX_MESSAGE_LEN) + if (mode == 1) + note = replacetext(n, "\n", "
") + notehtml = n + else + U << browse(null, "window=pda") + return + if("Toggle Messenger") + toff = !toff + if("Toggle Ringer")//If viewing texts then erase them, if not then toggle silent status + silent = !silent + if("Clear")//Clears messages + tnote = null + if("Ringtone") + var/t = input(U, "Please enter new ringtone", name, ttone) as text + if (in_range(src, U) && loc == U) + if (t) + if(src.hidden_uplink && hidden_uplink.check_trigger(U, lowertext(t), lowertext(lock_code))) + U << "The PDA softly beeps." + U << browse(null, "window=pda") + else + t = copytext(sanitize(t), 1, 20) + ttone = t + else + U << browse(null, "window=pda") + return + if("Message") + var/obj/item/device/pda/P = locate(href_list["target"]) + src.create_message(U, P) - if("Send Honk")//Honk virus - if(istype(cartridge, /obj/item/weapon/cartridge/clown))//Cartridge checks are kind of unnecessary since everything is done through switch. - var/obj/item/device/pda/P = locate(href_list["target"])//Leaving it alone in case it may do something useful, I guess. - if(!isnull(P)) - if (!P.toff && cartridge:honk_charges > 0) - cartridge:honk_charges-- - U.show_message("\blue Virus sent!", 1) - P.honkamt = (rand(15,20)) - else - U << "PDA not found." + if("Send Honk")//Honk virus + if(istype(cartridge, /obj/item/weapon/cartridge/clown))//Cartridge checks are kind of unnecessary since everything is done through switch. + var/obj/item/device/pda/P = locate(href_list["target"])//Leaving it alone in case it may do something useful, I guess. + if(!isnull(P)) + if (!P.toff && cartridge:honk_charges > 0) + cartridge:honk_charges-- + U.show_message("\blue Virus sent!", 1) + P.honkamt = (rand(15,20)) else - U << browse(null, "window=pda") - return - if("Send Silence")//Silent virus - if(istype(cartridge, /obj/item/weapon/cartridge/mime)) - var/obj/item/device/pda/P = locate(href_list["target"]) - if(!isnull(P)) - if (!P.toff && cartridge:mime_charges > 0) - cartridge:mime_charges-- - U.show_message("\blue Virus sent!", 1) - P.silent = 1 - P.ttone = "silence" - else - U << "PDA not found." + U << "PDA not found." + else + U << browse(null, "window=pda") + return + if("Send Silence")//Silent virus + if(istype(cartridge, /obj/item/weapon/cartridge/mime)) + var/obj/item/device/pda/P = locate(href_list["target"]) + if(!isnull(P)) + if (!P.toff && cartridge:mime_charges > 0) + cartridge:mime_charges-- + U.show_message("\blue Virus sent!", 1) + P.silent = 1 + P.ttone = "silence" else - U << browse(null, "window=pda") - return + U << "PDA not found." + else + U << browse(null, "window=pda") + return //SYNDICATE FUNCTIONS=================================== - if("Toggle Door") - if(cartridge && cartridge.access_remote_door) - for(var/obj/machinery/door/poddoor/M in world) - if(M.id == cartridge.remote_door_id) - if(M.density) - M.open() - else - M.close() + if("Toggle Door") + if(cartridge && cartridge.access_remote_door) + for(var/obj/machinery/door/poddoor/M in world) + if(M.id == cartridge.remote_door_id) + if(M.density) + M.open() + else + M.close() - if("Detonate")//Detonate PDA - if(istype(cartridge, /obj/item/weapon/cartridge/syndicate)) - var/obj/item/device/pda/P = locate(href_list["target"]) - if(!isnull(P)) - if (!P.toff && cartridge:shock_charges > 0) - cartridge:shock_charges-- + if("Detonate")//Detonate PDA + if(istype(cartridge, /obj/item/weapon/cartridge/syndicate)) + var/obj/item/device/pda/P = locate(href_list["target"]) + if(!isnull(P)) + if (!P.toff && cartridge:shock_charges > 0) + cartridge:shock_charges-- - var/difficulty = 0 + var/difficulty = 0 - if(P.cartridge) - difficulty += P.cartridge.access_medical - difficulty += P.cartridge.access_security - difficulty += P.cartridge.access_engine - difficulty += P.cartridge.access_clown - difficulty += P.cartridge.access_janitor - else - difficulty += 2 + if(P.cartridge) + difficulty += P.cartridge.access_medical + difficulty += P.cartridge.access_security + difficulty += P.cartridge.access_engine + difficulty += P.cartridge.access_clown + difficulty += P.cartridge.access_janitor + else + difficulty += 2 - if(prob(difficulty * 12) || (P.hidden_uplink)) - U.show_message("\red An error flashes on your [src].", 1) - else if (prob(difficulty * 3)) - U.show_message("\red Energy feeds back into your [src]!", 1) - U << browse(null, "window=pda") - explode() - else - U.show_message("\blue Success!", 1) - P.explode() - else - U << "PDA not found." + if(prob(difficulty * 12) || (P.hidden_uplink)) + U.show_message("\red An error flashes on your [src].", 1) + else if (prob(difficulty * 3)) + U.show_message("\red Energy feeds back into your [src]!", 1) + U << browse(null, "window=pda") + explode() + else + U.show_message("\blue Success!", 1) + P.explode() else - U.unset_machine() - U << browse(null, "window=pda") - return + U << "PDA not found." + else + U.unset_machine() + U << browse(null, "window=pda") + return //pAI FUNCTIONS=================================== - if("pai") - switch(href_list["option"]) - if("1") // Configure pAI device - pai.attack_self(U) - if("2") // Eject pAI device - var/turf/T = get_turf_or_move(src.loc) - if(T) - pai.loc = T + if("pai") + switch(href_list["option"]) + if("1") // Configure pAI device + pai.attack_self(U) + if("2") // Eject pAI device + var/turf/T = get_turf_or_move(src.loc) + if(T) + pai.loc = T //LINK FUNCTIONS=================================== - else//Cartridge menu linking - mode = text2num(href_list["choice"]) - cartridge.mode = mode - cartridge.unlock() - else//If can't interact. - U.unset_machine() - U << browse(null, "window=pda") - return + else//Cartridge menu linking + mode = text2num(href_list["choice"]) + cartridge.mode = mode + cartridge.unlock() else//If not in range or not using the pda. U.unset_machine() U << browse(null, "window=pda") @@ -866,7 +861,7 @@ var/global/list/obj/item/device/pda/PDAs = list() if(issilicon(usr)) return - if ( !(usr.stat || usr.restrained()) ) + if ( can_use(usr) ) if(id) remove_id() else @@ -883,7 +878,7 @@ var/global/list/obj/item/device/pda/PDAs = list() if(issilicon(usr)) return - if ( !(usr.stat || usr.restrained()) ) + if ( can_use(usr) ) var/obj/item/weapon/pen/O = locate() in src if(O) if (istype(loc, /mob)) @@ -943,7 +938,7 @@ var/global/list/obj/item/device/pda/PDAs = list() else //Basic safety check. If either both objects are held by user or PDA is on ground and card is in hand. if(((src in user.contents) && (C in user.contents)) || (istype(loc, /turf) && in_range(src, user) && (C in user.contents)) ) - if(!(user.stat || user.restrained()) )//If they can still act. + if( can_use(user) )//If they can still act. id_check(user, 2) user << "You put the ID into \the [src]'s slot." updateSelfDialog()//Update self dialog on success. diff --git a/code/game/objects/items/devices/pipe_painter.dm b/code/game/objects/items/devices/pipe_painter.dm new file mode 100644 index 00000000000..da297fbb55b --- /dev/null +++ b/code/game/objects/items/devices/pipe_painter.dm @@ -0,0 +1,22 @@ +/obj/item/device/pipe_painter + name = "pipe painter" + icon = 'icons/obj/bureaucracy.dmi' + icon_state = "labeler1" + item_state = "flight" + var/list/modes = list("grey","red","blue","cyan","green","yellow","purple") + var/mode = "grey" + +/obj/item/device/pipe_painter/afterattack(atom/A, mob/user as mob) + if(!istype(A,/obj/machinery/atmospherics/pipe) || istype(A,/obj/machinery/atmospherics/pipe/tank) || istype(A,/obj/machinery/atmospherics/pipe/vent) || istype(A,/obj/machinery/atmospherics/pipe/simple/heat_exchanging) || istype(A,/obj/machinery/atmospherics/pipe/simple/insulated)) + return + var/obj/machinery/atmospherics/pipe/P = A + P.color = mode + user.visible_message("[user] paints \the [P] [mode].","You paint \the [P] [mode].") + P.update_icon() + +/obj/item/device/pipe_painter/attack_self(mob/user as mob) + mode = input("Which colour do you want to use?","Pipe painter") in modes + +/obj/item/device/pipe_painter/examine() + ..() + usr << "It is in [mode] mode." \ No newline at end of file diff --git a/code/game/objects/items/devices/radio/encryptionkey.dm b/code/game/objects/items/devices/radio/encryptionkey.dm index 165f6748ec5..d2d5417d6c3 100644 --- a/code/game/objects/items/devices/radio/encryptionkey.dm +++ b/code/game/objects/items/devices/radio/encryptionkey.dm @@ -121,7 +121,8 @@ desc = "An encyption key for a radio headset. Contains cypherkeys." icon_state = "cargo_cypherkey" channels = list("Supply" = 1) + /obj/item/device/encryptionkey/ert name = "NanoTrasen ERT Radio Encryption Key" desc = "An encyption key for a radio headset. Contains cypherkeys." - channels = list("Response Team" = 1, "Science" = 1, "Command" = 1, "Medical" = 1, "Engineering" = 1, "Security" = 1, "Mining" = 1, "Cargo" = 1,) + channels = list("Response Team" = 1, "Science" = 1, "Command" = 1, "Medical" = 1, "Engineering" = 1, "Security" = 1, "Supply" = 1) diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 0081954da84..422a27897c0 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -499,8 +499,6 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use freq_text = "Engineering" if(1359) freq_text = "Security" -// if(1349) -// freq_text = "Mining" if(1347) freq_text = "Supply" //There's probably a way to use the list var of channels in code\game\communications.dm to make the dept channels non-hardcoded, but I wasn't in an experimentive mood. --NEO diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index f86f38cc83a..bef800f0fa9 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -129,8 +129,13 @@ MASS SPECTROMETER if (istype(M, /mob/living/carbon)) if(M:reagents.total_volume > 0) user.show_message(text("\red Warning: Unknown substance detected in subject's blood.")) - if(M:virus2) - user.show_message(text("\red Warning: Unknown pathogen detected in subject's blood.")) + if(M:virus2.len) + var/mob/living/carbon/C = M + for (var/ID in C.virus2) + if (ID in virusDB) + var/datum/data/record/V = virusDB[ID] + user.show_message(text("\red Warning: Pathogen [V.fields["name"]] detected in subject's blood. Known antigen : [V.fields["antigen"]]")) +// user.show_message(text("\red Warning: Unknown pathogen detected in subject's blood.")) if (M.getCloneLoss()) user.show_message("\red Subject appears to have been imperfectly cloned.") for(var/datum/disease/D in M.viruses) @@ -174,6 +179,7 @@ MASS SPECTROMETER user.show_message("\red Warning: Blood Level CRITICAL: [blood_percent]% [blood_volume]cl") else user.show_message("\blue Blood Level Normal: [blood_percent]% [blood_volume]cl") + user.show_message("\blue Subject's pulse: [H.get_pulse(GETPULSE_TOOL)] bpm.") src.add_fingerprint(user) return diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index 1e8bc3891b9..5011f5346ee 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -30,9 +30,10 @@ R.uneq_all() R.hands.icon_state = "nomod" R.icon_state = "robot" + R.base_icon = "robot" del(R.module) R.module = null - R.modtype = "robot" + R.camera.network.Remove(list("Medical","MINE")) R.updatename("Default") R.status_flags |= CANPUSH R.updateicon() @@ -52,6 +53,7 @@ /obj/item/borg/upgrade/rename/action(var/mob/living/silicon/robot/R) if(..()) return 0 R.name = heldname + R.custom_name = heldname R.real_name = heldname return 1 diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index ca538c254e2..4721bcc8fe6 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -11,15 +11,6 @@ var/heal_burn = 0 /obj/item/stack/medical/attack(mob/living/carbon/M as mob, mob/user as mob) - if (M.stat == 2) - var/t_him = "it" - if (M.gender == MALE) - t_him = "him" - else if (M.gender == FEMALE) - t_him = "her" - user << "\red \The [M] is dead, you cannot help [t_him]!" - return 1 - if (!istype(M)) user << "\red \The [src] cannot be applied to [M]!" return 1 @@ -47,42 +38,16 @@ user << "\red This isn't useful at all on a robotic limb.." return 1 - if(src.heal_brute) - if(!affecting.bandage()) - user << "\red The wounds on [M]'s [affecting.display_name] have already been bandaged." - return 1 - else - for (var/datum/wound/W in affecting.wounds) - if (W.internal) - continue - if (W.current_stage <= W.max_bleeding_stage) - user.visible_message( "\blue [user] bandages [W.desc] on [M]'s [affecting.display_name].", \ - "\blue You bandage [W.desc] on [M]'s [affecting.display_name]." ) - //H.add_side_effect("Itch") - else if (istype(W,/datum/wound/bruise)) - user.visible_message( "\blue [user] places bruise patch over [W.desc] on [M]'s [affecting.display_name].", \ - "\blue You place bruise patch over [W.desc] on [M]'s [affecting.display_name]." ) - else - user.visible_message( "\blue [user] places bandaid over [W.desc] on [M]'s [affecting.display_name].", \ - "\blue You place bandaid over [W.desc] on [M]'s [affecting.display_name]." ) - - else if(src.heal_burn) - if(!affecting.salve()) - user << "\red The wounds on [M]'s [affecting.display_name] have already been salved." - return 1 - else - user.visible_message( "\blue [user] salves wounds on [M]'s [affecting.display_name].", \ - "\blue You salve wounds on [M]'s [affecting.display_name]." ) - H.UpdateDamageIcon() + else + M.heal_organ_damage((src.heal_brute/2), (src.heal_burn/2)) user.visible_message( \ "\blue [M] has been applied with [src] by [user].", \ "\blue You apply \the [src] to [M]." \ ) - - use(1) + use(1) M.updatehealth() /obj/item/stack/medical/bruise_pack @@ -90,18 +55,60 @@ singular_name = "gauze length" desc = "Some sterile gauze to wrap around bloody stumps." icon_state = "brutepack" - heal_brute = 60 origin_tech = "biotech=1" +/obj/item/stack/medical/bruise_pack/attack(mob/living/carbon/M as mob, mob/user as mob) + if(..()) + return 1 + + if (istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + var/datum/organ/external/affecting = H.get_organ(user.zone_sel.selecting) + + if(!affecting.bandage()) + user << "\red The wounds on [M]'s [affecting.display_name] have already been bandaged." + return 1 + else + for (var/datum/wound/W in affecting.wounds) + if (W.internal) + continue + if (W.current_stage <= W.max_bleeding_stage) + user.visible_message( "\blue [user] bandages [W.desc] on [M]'s [affecting.display_name].", \ + "\blue You bandage [W.desc] on [M]'s [affecting.display_name]." ) + //H.add_side_effect("Itch") + else if (istype(W,/datum/wound/bruise)) + user.visible_message( "\blue [user] places bruise patch over [W.desc] on [M]'s [affecting.display_name].", \ + "\blue You place bruise patch over [W.desc] on [M]'s [affecting.display_name]." ) + else + user.visible_message( "\blue [user] places bandaid over [W.desc] on [M]'s [affecting.display_name].", \ + "\blue You place bandaid over [W.desc] on [M]'s [affecting.display_name]." ) + use(1) + /obj/item/stack/medical/ointment name = "ointment" desc = "Used to treat those nasty burns." gender = PLURAL singular_name = "ointment" icon_state = "ointment" - heal_burn = 40 + heal_burn = 1 origin_tech = "biotech=1" +/obj/item/stack/medical/ointment/attack(mob/living/carbon/M as mob, mob/user as mob) + if(..()) + return 1 + + if (istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + var/datum/organ/external/affecting = H.get_organ(user.zone_sel.selecting) + + if(!affecting.salve()) + user << "\red The wounds on [M]'s [affecting.display_name] have already been salved." + return 1 + else + user.visible_message( "\blue [user] salves wounds on [M]'s [affecting.display_name].", \ + "\blue You salve wounds on [M]'s [affecting.display_name]." ) + use(1) + /obj/item/stack/medical/bruise_pack/tajaran name = "\improper S'rendarr's Hand leaf" singular_name = "S'rendarr's Hand leaf" @@ -126,6 +133,34 @@ heal_brute = 12 origin_tech = "biotech=1" +/obj/item/stack/medical/advanced/bruise_pack/attack(mob/living/carbon/M as mob, mob/user as mob) + if(..()) + return 1 + + if (istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + var/datum/organ/external/affecting = H.get_organ(user.zone_sel.selecting) + + if(!affecting.bandage()) + user << "\red The wounds on [M]'s [affecting.display_name] have already been treated." + return 1 + else + for (var/datum/wound/W in affecting.wounds) + if (W.internal) + continue + if (W.current_stage <= W.max_bleeding_stage) + user.visible_message( "\blue [user] cleans [W.desc] on [M]'s [affecting.display_name] and seals edges with bioglue.", \ + "\blue You clean and seal [W.desc] on [M]'s [affecting.display_name]." ) + //H.add_side_effect("Itch") + else if (istype(W,/datum/wound/bruise)) + user.visible_message( "\blue [user] places medicine patch over [W.desc] on [M]'s [affecting.display_name].", \ + "\blue You place medicine patch over [W.desc] on [M]'s [affecting.display_name]." ) + else + user.visible_message( "\blue [user] smears some bioglue over [W.desc] on [M]'s [affecting.display_name].", \ + "\blue You smear some bioglue over [W.desc] on [M]'s [affecting.display_name]." ) + affecting.heal_damage(heal_brute,0) + use(1) + /obj/item/stack/medical/advanced/ointment name = "advanced burn kit" singular_name = "advanced burn kit" @@ -134,8 +169,26 @@ heal_burn = 12 origin_tech = "biotech=1" + +/obj/item/stack/medical/advanced/ointment/attack(mob/living/carbon/M as mob, mob/user as mob) + if(..()) + return 1 + + if (istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + var/datum/organ/external/affecting = H.get_organ(user.zone_sel.selecting) + + if(!affecting.salve()) + user << "\red The wounds on [M]'s [affecting.display_name] have already been salved." + return 1 + else + user.visible_message( "\blue [user] covers wounds on [M]'s [affecting.display_name] with regenerative membrane.", \ + "\blue You cover wounds on [M]'s [affecting.display_name] with regenerative membrane." ) + affecting.heal_damage(0,heal_burn) + use(1) + /obj/item/stack/medical/splint - name = "medical splint" + name = "medical splints" singular_name = "medical splint" icon_state = "splint" amount = 5 @@ -143,3 +196,38 @@ /obj/item/stack/medical/splint/single amount = 1 + + +/obj/item/stack/medical/splint/attack(mob/living/carbon/M as mob, mob/user as mob) + if(..()) + return 1 + + if (istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + var/datum/organ/external/affecting = H.get_organ(user.zone_sel.selecting) + var/limb = affecting.display_name + if(!((affecting.name == "l_arm") || (affecting.name == "r_arm") || (affecting.name == "l_leg") || (affecting.name == "r_leg"))) + user << "\red You can't apply a splint there!" + return + if(affecting.status & ORGAN_SPLINTED) + user << "\red [M]'s [limb] is already splinted!" + return + if (M != user) + user.visible_message("\red [user] starts to apply \the [src] to [M]'s [limb].", "\red You start to apply \the [src] to [M]'s [limb].", "\red You hear something being wrapped.") + else + if((!user.hand && affecting.name == "r_arm") || (user.hand && affecting.name == "l_arm")) + user << "\red You can't apply a splint to the arm you're using!" + return + user.visible_message("\red [user] starts to apply \the [src] to their [limb].", "\red You start to apply \the [src] to your [limb].", "\red You hear something being wrapped.") + if(do_after(user, 50)) + if (M != user) + user.visible_message("\red [user] finishes applying \the [src] to [M]'s [limb].", "\red You finish applying \the [src] to [M]'s [limb].", "\red You hear something being wrapped.") + else + if(prob(25)) + user.visible_message("\red [user] successfully applies \the [src] to their [limb].", "\red You successfully apply \the [src] to your [limb].", "\red You hear something being wrapped.") + else + user.visible_message("\red [user] fumbles \the [src].", "\red You fumble \the [src].", "\red You hear something being wrapped.") + return + affecting.status |= ORGAN_SPLINTED + use(1) + return \ No newline at end of file diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm index 3671b6ce08e..42def9a2b70 100644 --- a/code/game/objects/items/stacks/sheets/mineral.dm +++ b/code/game/objects/items/stacks/sheets/mineral.dm @@ -253,4 +253,4 @@ var/global/list/datum/stack_recipe/silver_recipes = list ( \ throw_speed = 3 throw_range = 3 origin_tech = "materials=4" - perunit = 2000 \ No newline at end of file + perunit = 2000 diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm index 903bb1b1bf9..a6c3b2fede4 100644 --- a/code/game/objects/items/weapons/implants/implant.dm +++ b/code/game/objects/items/weapons/implants/implant.dm @@ -159,9 +159,14 @@ Implant Specifics:
"} return if(istype(imp_in, /mob/)) var/mob/T = imp_in + + message_admins("Explosive implant triggered in [T] ([T.key]). (JMP) ") + log_game("Explosive implant triggered in [T] ([T.key]).") + T.gib() explosion(get_turf(imp_in), 1, 3, 4, 6, 3) var/turf/t = get_turf(imp_in) + if(t) t.hotspot_expose(3500,125) @@ -455,9 +460,13 @@ the implant may become unstable and either pre-maturely inject the subject or si implanted(mob/source as mob) src.activation_emote = input("Choose activation emote:") in list("blink", "blink_r", "eyebrow", "chuckle", "twitch_s", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink") if (source.mind) - source.mind.store_memory("Freedom implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate.", 0, 0) - source << "The implanted freedom implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate." + source.mind.store_memory("Compressed matter implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate.", 0, 0) + source << "The implanted compressed matter implant can be activated by using the [src.activation_emote] emote, say *[src.activation_emote] to attempt to activate." return 1 islegal() return 0 + +/obj/item/weapon/implant/cortical + name = "cortical stack" + desc = "A fist-sized mass of biocircuits and chips." diff --git a/code/game/objects/items/weapons/manuals.dm b/code/game/objects/items/weapons/manuals.dm index f4b2a147620..cc2c284adce 100644 --- a/code/game/objects/items/weapons/manuals.dm +++ b/code/game/objects/items/weapons/manuals.dm @@ -12,7 +12,7 @@ icon_state ="bookEngineering" author = "Engineering Encyclopedia" // Who wrote the thing, can be changed by pen or PC. It is not automatically assigned title = "Station Repairs and Construction" - dat = {" + /*dat = {" @@ -23,7 +23,7 @@ - "} + "}*/ /obj/item/weapon/book/manual/engineering_particle_accelerator name = "Particle Accelerator User's Guide" @@ -32,7 +32,7 @@ title = "Particle Accelerator User's Guide" //big pile of shit below. - dat = {" + /*dat = {"