diff --git a/baystation12.dme b/baystation12.dme index b50088fab11..ab997343539 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -78,6 +78,7 @@ #include "code\controllers\autotransfer.dm" #include "code\controllers\configuration.dm" #include "code\controllers\failsafe.dm" +#include "code\controllers\hooks.dm" #include "code\controllers\lighting_controller.dm" #include "code\controllers\master_controller.dm" #include "code\controllers\shuttle_controller.dm" @@ -176,8 +177,8 @@ #include "code\game\area\ai_monitored.dm" #include "code\game\area\areas.dm" #include "code\game\area\Space Station 13 areas.dm" -#include "code\game\dna\dna.dm" -#include "code\game\dna\dna_misc.dm" +#include "code\game\dna\dna2.dm" +#include "code\game\dna\dna2_helpers.dm" #include "code\game\dna\dna_modifier.dm" #include "code\game\gamemodes\events.dm" #include "code\game\gamemodes\factions.dm" @@ -223,6 +224,7 @@ #include "code\game\gamemodes\malfunction\malfunction.dm" #include "code\game\gamemodes\meteor\meteor.dm" #include "code\game\gamemodes\meteor\meteors.dm" +#include "code\game\gamemodes\ninja\ninja.dm" #include "code\game\gamemodes\nuclear\nuclear.dm" #include "code\game\gamemodes\nuclear\nuclearbomb.dm" #include "code\game\gamemodes\nuclear\pinpointer.dm" @@ -264,6 +266,7 @@ #include "code\game\machinery\cloning.dm" #include "code\game\machinery\constructable_frame.dm" #include "code\game\machinery\cryo.dm" +#include "code\game\machinery\cryopod.dm" #include "code\game\machinery\deployable.dm" #include "code\game\machinery\door_control.dm" #include "code\game\machinery\doppler_array.dm" @@ -651,7 +654,6 @@ #include "code\modules\admin\holder2.dm" #include "code\modules\admin\IsBanned.dm" #include "code\modules\admin\NewBan.dm" -#include "code\modules\admin\newbanjob.dm" #include "code\modules\admin\player_notes.dm" #include "code\modules\admin\player_panel.dm" #include "code\modules\admin\topic.dm" @@ -820,6 +822,7 @@ #include "code\modules\maps\reader.dm" #include "code\modules\maps\swapmaps.dm" #include "code\modules\maps\writer.dm" +#include "code\modules\mining\abandonedcrates.dm" #include "code\modules\mining\machine_input_output_plates.dm" #include "code\modules\mining\machine_processing.dm" #include "code\modules\mining\machine_stacking.dm" @@ -831,6 +834,7 @@ #include "code\modules\mining\money_bag.dm" #include "code\modules\mining\ores_coins.dm" #include "code\modules\mining\satchel_ore_boxdm.dm" +#include "code\modules\mob\abilities.dm" #include "code\modules\mob\death.dm" #include "code\modules\mob\emote.dm" #include "code\modules\mob\inventory.dm" diff --git a/code/WorkInProgress/Cib/MedicalSideEffects.dm b/code/WorkInProgress/Cib/MedicalSideEffects.dm index 15580c4bd2e..62f9cf75f80 100644 --- a/code/WorkInProgress/Cib/MedicalSideEffects.dm +++ b/code/WorkInProgress/Cib/MedicalSideEffects.dm @@ -83,7 +83,7 @@ /datum/medical_effect/headache name = "Headache" triggers = list("cryoxadone" = 10, "bicaridine" = 15, "tricordrazine" = 15) - cures = list("alkysine", "tramadol") + cures = list("alkysine", "tramadol", "paracetamol", "oxycodone") cure_message = "Your head stops throbbing..." /datum/medical_effect/headache/on_life(mob/living/carbon/human/H, strength) diff --git a/code/ZAS/FEA_gas_mixture.dm b/code/ZAS/FEA_gas_mixture.dm index 3eccad7e913..9a829633e2b 100644 --- a/code/ZAS/FEA_gas_mixture.dm +++ b/code/ZAS/FEA_gas_mixture.dm @@ -14,6 +14,20 @@ 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 +/hook/startup/proc/createGasOverlays() + plmaster = new /obj/effect/overlay() + plmaster.icon = 'icons/effects/tile_effects.dmi' + plmaster.icon_state = "plasma" + plmaster.layer = FLY_LAYER + plmaster.mouse_opacity = 0 + + slmaster = new /obj/effect/overlay() + slmaster.icon = 'icons/effects/tile_effects.dmi' + slmaster.icon_state = "sleeping_agent" + slmaster.layer = FLY_LAYER + slmaster.mouse_opacity = 0 + return 1 + /datum/gas/sleeping_agent/specific_heat = 40 //These are used for the "Trace Gases" stuff, but is buggy. /datum/gas/oxygen_agent_b/specific_heat = 300 diff --git a/code/ZAS/Plasma.dm b/code/ZAS/Plasma.dm index 9f0e95f6617..716ea216403 100644 --- a/code/ZAS/Plasma.dm +++ b/code/ZAS/Plasma.dm @@ -118,12 +118,12 @@ obj/var/contaminated = 0 /mob/living/carbon/human/proc/burn_eyes() //The proc that handles eye burning. if(prob(20)) src << "\red Your eyes burn!" - eye_stat += 2.5 + var/datum/organ/internal/eyes/E = internal_organs["eyes"] + E.damage += 2.5 eye_blurry = min(eye_blurry+1.5,50) - if (prob(max(0,eye_stat - 20) + 1) &&!eye_blind) + if (prob(max(0,E.damage - 15) + 1) &&!eye_blind) src << "\red You are blinded!" eye_blind += 20 - eye_stat = 0 /mob/living/carbon/human/proc/pl_head_protected() //Checks if the head is adequately sealed. diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index ce8d788f25f..07a22f56932 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -42,7 +42,7 @@ var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Al /////Initial Building///// ////////////////////////// -/proc/make_datum_references_lists() +/hook/startup/proc/makeDatumRefLists() var/list/paths //Hair - Initialise all /datum/sprite_accessory/hair into an list indexed by hair-style name @@ -97,6 +97,8 @@ var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Al if(S.flags & WHITELISTED) whitelisted_species += S.name + return 1 + /* // Uncomment to debug chemical reaction list. /client/verb/debug_chemical_list() diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index e180f2092d6..20eb15d6af0 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -261,4 +261,5 @@ proc/tg_list2text(list/list, glue=",") switch(ui_style) if("old") return 'icons/mob/screen1_old.dmi' if("Orange") return 'icons/mob/screen1_Orange.dmi' - else return 'icons/mob/screen1_Midnight.dmi' + if("Midnight") return 'icons/mob/screen1_Midnight.dmi' + else return 'icons/mob/screen1_White.dmi' diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index 618858d5438..88ac1b70e2c 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -166,9 +166,11 @@ datum/hud/New(mob/owner) if(!ismob(mymob)) return 0 if(!mymob.client) return 0 var/ui_style = ui_style2icon(mymob.client.prefs.UI_style) + var/ui_color = mymob.client.prefs.UI_style_color + var/ui_alpha = mymob.client.prefs.UI_style_alpha if(ishuman(mymob)) - human_hud(ui_style) // Pass the player the UI style chosen in preferences + human_hud(ui_style, ui_color, ui_alpha) // Pass the player the UI style chosen in preferences else if(ismonkey(mymob)) monkey_hud(ui_style) else if(isbrain(mymob)) diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index 3d97018352a..ca053f86e6b 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -1,4 +1,4 @@ -/datum/hud/proc/human_hud(var/ui_style='icons/mob/screen1_old.dmi') +/datum/hud/proc/human_hud(var/ui_style='icons/mob/screen1_White.dmi', var/ui_color = "#ffffff", var/ui_alpha = 255) src.adding = list() src.other = list() @@ -73,6 +73,8 @@ using.icon_state = (mymob.m_intent == "run" ? "running" : "walking") using.screen_loc = ui_movi using.layer = 20 + using.color = ui_color + using.alpha = ui_alpha src.adding += using move_intent = using @@ -82,6 +84,8 @@ using.icon_state = "act_drop" using.screen_loc = ui_drop_throw using.layer = 19 + using.color = ui_color + using.alpha = ui_alpha src.hotkeybuttons += using inv_box = new /obj/screen/inventory() @@ -92,6 +96,8 @@ inv_box.icon_state = "center" inv_box.screen_loc = ui_iclothing inv_box.layer = 19 + inv_box.color = ui_color + inv_box.alpha = ui_alpha src.other += inv_box inv_box = new /obj/screen/inventory() @@ -102,6 +108,8 @@ inv_box.icon_state = "equip" inv_box.screen_loc = ui_oclothing inv_box.layer = 19 + inv_box.color = ui_color + inv_box.alpha = ui_alpha src.other += inv_box inv_box = new /obj/screen/inventory() @@ -114,6 +122,9 @@ inv_box.screen_loc = ui_rhand inv_box.slot_id = slot_r_hand inv_box.layer = 19 + inv_box.color = ui_color + inv_box.alpha = ui_alpha + src.r_hand_hud_object = inv_box src.adding += inv_box @@ -127,6 +138,8 @@ inv_box.screen_loc = ui_lhand inv_box.slot_id = slot_l_hand inv_box.layer = 19 + inv_box.color = ui_color + inv_box.alpha = ui_alpha src.l_hand_hud_object = inv_box src.adding += inv_box @@ -137,6 +150,8 @@ using.icon_state = "hand1" using.screen_loc = ui_swaphand1 using.layer = 19 + using.color = ui_color + using.alpha = ui_alpha src.adding += using using = new /obj/screen/inventory() @@ -146,6 +161,8 @@ using.icon_state = "hand2" using.screen_loc = ui_swaphand2 using.layer = 19 + using.color = ui_color + using.alpha = ui_alpha src.adding += using inv_box = new /obj/screen/inventory() @@ -156,6 +173,8 @@ inv_box.screen_loc = ui_id inv_box.slot_id = slot_wear_id inv_box.layer = 19 + inv_box.color = ui_color + inv_box.alpha = ui_alpha src.adding += inv_box inv_box = new /obj/screen/inventory() @@ -166,6 +185,8 @@ inv_box.screen_loc = ui_mask inv_box.slot_id = slot_wear_mask inv_box.layer = 19 + inv_box.color = ui_color + inv_box.alpha = ui_alpha src.other += inv_box inv_box = new /obj/screen/inventory() @@ -176,6 +197,8 @@ inv_box.screen_loc = ui_back inv_box.slot_id = slot_back inv_box.layer = 19 + inv_box.color = ui_color + inv_box.alpha = ui_alpha src.adding += inv_box inv_box = new /obj/screen/inventory() @@ -185,6 +208,8 @@ inv_box.screen_loc = ui_storage1 inv_box.slot_id = slot_l_store inv_box.layer = 19 + inv_box.color = ui_color + inv_box.alpha = ui_alpha src.adding += inv_box inv_box = new /obj/screen/inventory() @@ -194,6 +219,8 @@ inv_box.screen_loc = ui_storage2 inv_box.slot_id = slot_r_store inv_box.layer = 19 + inv_box.color = ui_color + inv_box.alpha = ui_alpha src.adding += inv_box inv_box = new /obj/screen/inventory() @@ -204,6 +231,8 @@ inv_box.screen_loc = ui_sstore1 inv_box.slot_id = slot_s_store inv_box.layer = 19 + inv_box.color = ui_color + inv_box.alpha = ui_alpha src.adding += inv_box using = new /obj/screen() @@ -212,6 +241,8 @@ using.icon_state = "act_resist" using.screen_loc = ui_pull_resist using.layer = 19 + using.color = ui_color + using.alpha = ui_alpha src.hotkeybuttons += using using = new /obj/screen() @@ -220,6 +251,8 @@ using.icon_state = "other" using.screen_loc = ui_inventory using.layer = 20 + using.color = ui_color + using.alpha = ui_alpha src.adding += using using = new /obj/screen() @@ -228,6 +261,8 @@ using.icon_state = "act_equip" using.screen_loc = ui_equip using.layer = 20 + using.color = ui_color + using.alpha = ui_alpha src.adding += using inv_box = new /obj/screen/inventory() @@ -237,6 +272,8 @@ inv_box.screen_loc = ui_gloves inv_box.slot_id = slot_gloves inv_box.layer = 19 + inv_box.color = ui_color + inv_box.alpha = ui_alpha src.other += inv_box inv_box = new /obj/screen/inventory() @@ -246,6 +283,8 @@ inv_box.screen_loc = ui_glasses inv_box.slot_id = slot_glasses inv_box.layer = 19 + inv_box.color = ui_color + inv_box.alpha = ui_alpha src.other += inv_box inv_box = new /obj/screen/inventory() @@ -255,6 +294,8 @@ inv_box.screen_loc = ui_l_ear inv_box.slot_id = slot_l_ear inv_box.layer = 19 + inv_box.color = ui_color + inv_box.alpha = ui_alpha src.other += inv_box inv_box = new /obj/screen/inventory() @@ -264,6 +305,8 @@ inv_box.screen_loc = ui_r_ear inv_box.slot_id = slot_r_ear inv_box.layer = 19 + inv_box.color = ui_color + inv_box.alpha = ui_alpha src.other += inv_box inv_box = new /obj/screen/inventory() @@ -273,6 +316,8 @@ inv_box.screen_loc = ui_head inv_box.slot_id = slot_head inv_box.layer = 19 + inv_box.color = ui_color + inv_box.alpha = ui_alpha src.other += inv_box inv_box = new /obj/screen/inventory() @@ -282,6 +327,8 @@ inv_box.screen_loc = ui_shoes inv_box.slot_id = slot_shoes inv_box.layer = 19 + inv_box.color = ui_color + inv_box.alpha = ui_alpha src.other += inv_box inv_box = new /obj/screen/inventory() @@ -291,6 +338,8 @@ inv_box.screen_loc = ui_belt inv_box.slot_id = slot_belt inv_box.layer = 19 + inv_box.color = ui_color + inv_box.alpha = ui_alpha src.adding += inv_box mymob.throw_icon = new /obj/screen() @@ -298,6 +347,8 @@ mymob.throw_icon.icon_state = "act_throw_off" mymob.throw_icon.name = "throw" mymob.throw_icon.screen_loc = ui_drop_throw + mymob.throw_icon.color = ui_color + mymob.throw_icon.alpha = ui_alpha src.hotkeybuttons += mymob.throw_icon mymob.oxygen = new /obj/screen() @@ -382,6 +433,8 @@ mymob.zone_sel = new /obj/screen/zone_sel( null ) mymob.zone_sel.icon = ui_style + mymob.zone_sel.color = ui_color + mymob.zone_sel.alpha = ui_alpha mymob.zone_sel.overlays.Cut() mymob.zone_sel.overlays += image('icons/mob/zone_sel.dmi', "[mymob.zone_sel.selecting]") diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 21ea21b2013..b5b6cf74233 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -43,6 +43,8 @@ var/Tickcomp = 0 var/socket_talk = 0 // use socket_talk to communicate with other processes var/list/resource_urls = null + var/antag_hud_allowed = 0 // Ghosts can turn on Antagovision to see a HUD of who is the bad guys this round. + var/antag_hud_restricted = 0 // Ghosts that turn on Antagovision cannot rejoin the round. var/list/mode_names = list() var/list/modes = list() // allowed modes var/list/votable_modes = list() // votable modes @@ -387,6 +389,11 @@ if("ticklag") Ticklag = text2num(value) + if("allow_antag_hud") + config.antag_hud_allowed = 1 + if("antag_hud_restricted") + config.antag_hud_restricted = 1 + if("socket_talk") socket_talk = text2num(value) diff --git a/code/controllers/hooks.dm b/code/controllers/hooks.dm new file mode 100644 index 00000000000..5045da75925 --- /dev/null +++ b/code/controllers/hooks.dm @@ -0,0 +1,39 @@ +/** + * @file hooks.dm + * Implements hooks, a simple way to run code on pre-defined events. + */ + +/** @page hooks Code hooks + * @section hooks Hooks + * A hook is defined under /hook in the type tree. + * + * To add some code to be called by the hook, define a proc under the type, as so: + * @code + /hook/foo/proc/bar() + if(1) + return 1 //Sucessful + else + return 0 //Error, or runtime. + * @endcode + * All hooks must return nonzero on success, as runtimes will force return null. + */ + +/** + * Calls a hook, executing every piece of code that's attached to it. + * @param hook Identifier of the hook to call. + * @returns 1 if all hooked code runs successfully, 0 otherwise. + */ +/proc/callHook(hook) + var/hook_path = text2path("/hook/[hook]") + if(!hook_path) + error("Invalid hook '/hook/[hook]' called.") + return 0 + + var/caller = new hook_path + var/status = 1 + for(var/P in typesof("[hook_path]/proc")) + if(!call(caller, P)()) + error("Hook '[P]' failed or runtimed.") + status = 0 + + return status diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index 1a7d97e99cf..1e141a2ac20 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -1,3 +1,6 @@ +/hook/startup/proc/createDatacore() + data_core = new /obj/effect/datacore() + return 1 /obj/effect/datacore/proc/manifest(var/nosleep = 0) spawn() @@ -109,8 +112,8 @@ L.fields["sex"] = H.gender L.fields["b_type"] = H.b_type L.fields["b_dna"] = H.dna.unique_enzymes - L.fields["enzymes"] = H.dna.struc_enzymes - L.fields["identity"] = H.dna.uni_identity + L.fields["enzymes"] = H.dna.SE + L.fields["identity"] = H.dna.UI L.fields["image"] = getFlatIcon(H,0) //This is god-awful locked += L return diff --git a/code/datums/diseases/dna_spread.dm b/code/datums/diseases/dna_spread.dm index c7c5f812122..69a8eb6500f 100644 --- a/code/datums/diseases/dna_spread.dm +++ b/code/datums/diseases/dna_spread.dm @@ -39,13 +39,13 @@ //Save original dna for when the disease is cured. src.original_dna["name"] = affected_mob.real_name - src.original_dna["UI"] = affected_mob.dna.uni_identity - src.original_dna["SE"] = affected_mob.dna.struc_enzymes + src.original_dna["UI"] = affected_mob.dna.UI + src.original_dna["SE"] = affected_mob.dna.SE affected_mob << "\red You don't feel like yourself.." - affected_mob.dna.uni_identity = strain_data["UI"] - updateappearance(affected_mob, affected_mob.dna.uni_identity) - affected_mob.dna.struc_enzymes = strain_data["SE"] + affected_mob.UpdateAppearance(strain_data["UI"]) + affected_mob.dna.SE = strain_data["SE"] + affected_mob.dna.UpdateSE() affected_mob.real_name = strain_data["name"] domutcheck(affected_mob) @@ -56,9 +56,9 @@ /datum/disease/dnaspread/Del() if ((original_dna["name"]) && (original_dna["UI"]) && (original_dna["SE"])) - affected_mob.dna.uni_identity = original_dna["UI"] - updateappearance(affected_mob, affected_mob.dna.uni_identity) - affected_mob.dna.struc_enzymes = original_dna["SE"] + affected_mob.UpdateAppearance(original_dna["UI"]) + affected_mob.dna.SE = original_dna["SE"] + affected_mob.dna.UpdateSE() affected_mob.real_name = original_dna["name"] affected_mob << "\blue You feel more like yourself." diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 511731195e4..7cebf4f6bac 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -726,7 +726,7 @@ datum/mind else current.dna = changeling.absorbed_dna[1] current.real_name = current.dna.real_name - updateappearance(current, current.dna.uni_identity) + current.UpdateAppearance() domutcheck(current, null) else if (href_list["nuclear"]) diff --git a/code/datums/sun.dm b/code/datums/sun.dm index 9ce8a73cb72..82acfa0cff0 100644 --- a/code/datums/sun.dm +++ b/code/datums/sun.dm @@ -14,6 +14,10 @@ if(prob(50)) rate = -rate +/hook/startup/proc/createSun() + sun = new /datum/sun() + return 1 + // calculate the sun's position given the time of day /datum/sun/proc/calc_position() diff --git a/code/defines/obj/hydro.dm b/code/defines/obj/hydro.dm index 7cb2439cc68..2b57dbeffa5 100644 --- a/code/defines/obj/hydro.dm +++ b/code/defines/obj/hydro.dm @@ -132,6 +132,40 @@ plant_type = 0 growthstages = 1 +/obj/item/seeds/shandseed + name = "pack of s'rendarr's hand seeds" + desc = "These seeds grow into a helpful herb called S'Rendarr's Hand, native to Ahdomai." + icon_state = "seed-shand" + mypath = "/obj/item/seeds/shandseed" + species = "shand" + plantname = "S'Rendarr's Hand" + productname = "/obj/item/stack/medical/bruise_pack/tajaran" + lifespan = 50 + endurance = 25 + maturation = 3 + production = 5 + yield = 4 + potency = 10 + plant_type = 0 + growthstages = 3 + +/obj/item/seeds/mtearseed + name = "pack of messa's tear seeds" + desc = "These seeds grow into a helpful herb called Messa's Tear, native to Ahdomai." + icon_state = "seed-mtear" + mypath = "/obj/item/seeds/mtearseed" + species = "mtear" + plantname = "Messa's Tear" + productname = "/obj/item/stack/medical/ointment/tajaran" + lifespan = 50 + endurance = 25 + maturation = 3 + production = 5 + yield = 4 + potency = 10 + plant_type = 0 + growthstages = 3 + /obj/item/seeds/berryseed name = "pack of berry seeds" desc = "These seeds grow into berry bushes." diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index b27f10b6e00..9c04d5b672d 100755 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -56,7 +56,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station /*I am far too lazy to make it a proper list of areas so I'll just make it run the usual telepot routine at the start of the game*/ var/list/teleportlocs = list() -proc/process_teleport_locs() +/hook/startup/proc/setupTeleportLocs() for(var/area/AR in world) if(istype(AR, /area/shuttle) || istype(AR, /area/syndicate_station) || istype(AR, /area/wizard_station)) continue if(teleportlocs.Find(AR.name)) continue @@ -65,20 +65,13 @@ proc/process_teleport_locs() teleportlocs += AR.name teleportlocs[AR.name] = AR - var/not_in_order = 0 - do - not_in_order = 0 - if(teleportlocs.len <= 1) - break - for(var/i = 1, i <= (teleportlocs.len - 1), i++) - if(sorttext(teleportlocs[i], teleportlocs[i+1]) == -1) - teleportlocs.Swap(i, i+1) - not_in_order = 1 - while(not_in_order) + teleportlocs = sortAssoc(teleportlocs) + + return 1 var/list/ghostteleportlocs = list() -proc/process_ghost_teleport_locs() +/hook/startup/proc/setupGhostTeleportLocs() for(var/area/AR in world) if(ghostteleportlocs.Find(AR.name)) continue if(istype(AR, /area/turret_protected/aisat) || istype(AR, /area/derelict) || istype(AR, /area/tdome)) @@ -89,17 +82,9 @@ proc/process_ghost_teleport_locs() ghostteleportlocs += AR.name ghostteleportlocs[AR.name] = AR - var/not_in_order = 0 - do - not_in_order = 0 - if(ghostteleportlocs.len <= 1) - break - for(var/i = 1, i <= (ghostteleportlocs.len - 1), i++) - if(sorttext(ghostteleportlocs[i], ghostteleportlocs[i+1]) == -1) - ghostteleportlocs.Swap(i, i+1) - not_in_order = 1 - while(not_in_order) + ghostteleportlocs = sortAssoc(ghostteleportlocs) + return 1 /*-----------------------------------------------------------------------------*/ diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index fbf80014836..6695fe44027 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -179,23 +179,18 @@ /area/proc/updateicon() if ((fire || eject || party) && ((!requires_power)?(!requires_power):power_environ))//If it doesn't require power, can still activate this proc. if(fire && !eject && !party) - icon_state = "red" - blend_mode = BLEND_MULTIPLY + icon_state = "blue" /*else if(atmosalm && !fire && !eject && !party) icon_state = "bluenew"*/ else if(!fire && eject && !party) icon_state = "red" - blend_mode = BLEND_MULTIPLY else if(party && !fire && !eject) icon_state = "party" - blend_mode = BLEND_MULTIPLY else icon_state = "blue-red" - blend_mode = BLEND_MULTIPLY else // new lighting behaviour with obj lights icon_state = null - blend_mode = BLEND_DEFAULT /* diff --git a/code/game/communications.dm b/code/game/communications.dm index 32d8ca69348..4f13277a31d 100644 --- a/code/game/communications.dm +++ b/code/game/communications.dm @@ -103,16 +103,16 @@ var/list/radiochannels = list( "Medical" = 1355, "Engineering" = 1357, "Security" = 1359, - "Response Team" = 1443, - "Deathsquad" = 1441, + "Response Team" = 1345, + "Deathsquad" = 1341, "Syndicate" = 1213, "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, 1345, 1341, 1347) // central command channels, i.e deathsquid & response teams -var/list/CENT_FREQS = list(1441, 1443) +var/list/CENT_FREQS = list(1345, 1341) var/const/COMM_FREQ = 1353 //command, colored gold in chat window var/const/SYND_FREQ = 1213 @@ -140,6 +140,10 @@ var/const/RADIO_MAGNETS = "9" var/global/datum/controller/radio/radio_controller +/hook/startup/proc/createRadioController() + radio_controller = new /datum/controller/radio() + return 1 + datum/controller/radio var/list/datum/radio_frequency/frequencies = list() diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm new file mode 100644 index 00000000000..9102ee87801 --- /dev/null +++ b/code/game/dna/dna2.dm @@ -0,0 +1,333 @@ +/** +* DNA 2: The Spaghetti Strikes Back +* +* @author N3X15 +*/ + +// What each index means: +#define DNA_OFF_LOWERBOUND 0 +#define DNA_OFF_UPPERBOUND 1 +#define DNA_ON_LOWERBOUND 2 +#define DNA_ON_UPPERBOUND 3 + +// Define block bounds (off-low,off-high,on-low,on-high) +// Used in setupgame.dm +#define DNA_DEFAULT_BOUNDS list(1,2049,2050,4095) +#define DNA_HARDER_BOUNDS list(1,3049,3050,4095) +#define DNA_HARD_BOUNDS list(1,3490,3500,4095) + +// Defines which values mean "on" or "off". +// This is to make some of the more OP superpowers a larger PITA to activate, +// and to tell our new DNA datum which values to set in order to turn something +// on or off. +var/global/list/dna_activity_bounds[STRUCDNASIZE] + +// Used to determine what each block means (admin hax and species stuff on /vg/, mostly) +var/global/list/assigned_blocks[STRUCDNASIZE] + +// UI Indices (can change to mutblock style, if desired) +#define DNA_UI_HAIR_R 1 +#define DNA_UI_HAIR_G 2 +#define DNA_UI_HAIR_B 3 +#define DNA_UI_BEARD_R 4 +#define DNA_UI_BEARD_G 5 +#define DNA_UI_BEARD_B 6 +#define DNA_UI_SKIN_TONE 7 +#define DNA_UI_EYES_R 8 +#define DNA_UI_EYES_G 9 +#define DNA_UI_EYES_B 10 +#define DNA_UI_GENDER 11 +#define DNA_UI_BEARD_STYLE 12 +#define DNA_UI_HAIR_STYLE 13 +#define DNA_UI_LENGTH 13 // Update this when you add something, or you WILL break shit. + + +/* Note RE: unassigned blocks + + Many genes in baycode are currently sitting unused + (compare setupgame.dm to the number of *BLOCK variables). + + This datum will return 0 (or equivalent) if asked about + a block 0 (which means the gene was unassigned). Setters + will silently return without performing any action. + + I have code to assign these genes in a streamlined manner, + but in order to avoid breaking things, I've left the + existing setupgame.dm intact. Please let me know if you + need this behavior changed. + */ + +/datum/dna + // READ-ONLY, GETS OVERWRITTEN + // DO NOT FUCK WITH THESE OR BYOND WILL EAT YOUR FACE + var/uni_identity="" // Encoded UI + var/struc_enzymes="" // Encoded SE + var/unique_enzymes="" // MD5 of player name + + // Internal dirtiness checks + var/dirtyUI=0 + var/dirtySE=0 + + // Okay to read, but you're an idiot if you do. + // BLOCK = VALUE + var/list/SE[STRUCDNASIZE] + var/list/UI[DNA_UI_LENGTH] + + // From old dna. + var/b_type = "A+" // Should probably change to an integer => string map but I'm lazy. + var/mutantrace = null // The type of mutant race the player is, if applicable (i.e. potato-man) + var/real_name // Stores the real name of the person who originally got this dna datum. Used primarily for changelings, +/////////////////////////////////////// +// UNIQUE IDENTITY +/////////////////////////////////////// + +// Create random UI. +/datum/dna/proc/ResetUI(var/defer=0) + for(var/i=1,i<=DNA_UI_LENGTH,i++) + UI[i]=rand(0,4095) + if(!defer) + UpdateUI() + +/datum/dna/proc/ResetUIFrom(var/mob/living/carbon/human/character) + // INITIALIZE! + ResetUI(1) + // Hair + // FIXME: Species-specific defaults pls + if(!character.h_style) + character.h_style = "Skinhead" + var/hair = hair_styles_list.Find(character.h_style) + + // Facial Hair + if(!character.f_style) + character.f_style = "Shaved" + var/beard = facial_hair_styles_list.Find(character.f_style) + + SetUIValueRange(DNA_UI_HAIR_R, character.r_hair, 255, 1) + SetUIValueRange(DNA_UI_HAIR_G, character.g_hair, 255, 1) + SetUIValueRange(DNA_UI_HAIR_B, character.b_hair, 255, 1) + + SetUIValueRange(DNA_UI_BEARD_R, character.r_facial, 255, 1) + SetUIValueRange(DNA_UI_BEARD_G, character.g_facial, 255, 1) + SetUIValueRange(DNA_UI_BEARD_B, character.b_facial, 255, 1) + + SetUIValueRange(DNA_UI_BEARD_R, character.r_eyes, 255, 1) + SetUIValueRange(DNA_UI_BEARD_G, character.g_eyes, 255, 1) + SetUIValueRange(DNA_UI_BEARD_B, character.b_eyes, 255, 1) + + SetUIValueRange(DNA_UI_SKIN_TONE, character.s_tone, 220, 1) + + SetUIState(DNA_UI_GENDER, character.gender!=MALE, 1) + + SetUIValueRange(DNA_UI_HAIR_STYLE, hair, hair_styles_list.len, 1) + SetUIValueRange(DNA_UI_BEARD_STYLE, beard, facial_hair_styles_list.len,1) + + UpdateUI() + +// Set a DNA UI block's raw value. +/datum/dna/proc/SetUIValue(var/block,var/value,var/defer=0) + if (block<=0) return + ASSERT(value>=0) + ASSERT(value<=4095) + UI[block]=value + dirtyUI=1 + if(!defer) + UpdateUI() + +// Get a DNA UI block's raw value. +/datum/dna/proc/GetUIValue(var/block) + if (block<=0) return 0 + return UI[block] + +// Set a DNA UI block's value, given a value and a max possible value. +// Used in hair and facial styles (value being the index and maxvalue being the len of the hairstyle list) +/datum/dna/proc/SetUIValueRange(var/block,var/value,var/maxvalue) + if (block<=0) return + ASSERT(maxvalue<=4095) + var/range = round(4095 / maxvalue) + if(value) + SetUIValue(block,value * range - rand(1,range-1)) + +// Getter version of above. +/datum/dna/proc/GetUIValueRange(var/block,var/maxvalue) + if (block<=0) return 0 + var/value = GetUIValue(block) + return round(1 +(value / 4096)*maxvalue) + +// Is the UI gene "on" or "off"? +// For UI, this is simply a check of if the value is > 2050. +/datum/dna/proc/GetUIState(var/block) + if (block<=0) return + return UI[block] > 2050 + + +// Set UI gene "on" (1) or "off" (0) +/datum/dna/proc/SetUIState(var/block,var/on,var/defer=0) + if (block<=0) return + var/val + if(on) + val=rand(2050,4095) + else + val=rand(1,2049) + SetUIValue(block,val,defer) + +// Get a hex-encoded UI block. +/datum/dna/proc/GetUIBlock(var/block) + return EncodeDNABlock(GetUIValue(block)) + +// Do not use this unless you absolutely have to. +// Set a block from a hex string. This is inefficient. If you can, use SetUIValue(). +// Used in DNA modifiers. +/datum/dna/proc/SetUIBlock(var/block,var/value,var/defer=0) + if (block<=0) return + return SetUIValue(block,hex2num(value),defer) + +// Get a sub-block from a block. +/datum/dna/proc/GetUISubBlock(var/block,var/subBlock) + return copytext(GetUIBlock(block),subBlock,subBlock+1) + +// Do not use this unless you absolutely have to. +// Set a block from a hex string. This is inefficient. If you can, use SetUIValue(). +// Used in DNA modifiers. +/datum/dna/proc/SetUISubBlock(var/block,var/subBlock, var/newSubBlock, var/defer=0) + if (block<=0) return + var/oldBlock=GetUIBlock(block) + var/newBlock="" + for(var/i=1, i<=length(oldBlock), i++) + if(i==subBlock) + newBlock+=newSubBlock + else + newBlock+=copytext(oldBlock,i,i+1) + SetUIBlock(block,newBlock,defer) + +/////////////////////////////////////// +// STRUCTURAL ENZYMES +/////////////////////////////////////// + +// "Zeroes out" all of the blocks. +/datum/dna/proc/ResetSE() + for(var/i = 1, i <= STRUCDNASIZE, i++) + SetSEValue(i,rand(1,1024),1) + UpdateSE() + +// Set a DNA SE block's raw value. +/datum/dna/proc/SetSEValue(var/block,var/value,var/defer=0) + //testing("SetSEBlock([block],[value],[defer]): [value] -> [nval]") + if (block<=0) return + ASSERT(value>=0) + ASSERT(value<=4095) + SE[block]=value + dirtySE=1 + if(!defer) + UpdateSE() + +// Get a DNA SE block's raw value. +/datum/dna/proc/GetSEValue(var/block) + if (block<=0) return 0 + return SE[block] + +// Set a DNA SE block's value, given a value and a max possible value. +// Might be used for species? +/datum/dna/proc/SetSEValueRange(var/block,var/value,var/maxvalue) + if (block<=0) return + ASSERT(maxvalue<=4095) + var/range = round(4095 / maxvalue) + if(value) + SetSEValue(block, value * range - rand(1,range-1)) + +// Is the block "on" (1) or "off" (0)? (Un-assigned genes are always off.) +/datum/dna/proc/GetSEState(var/block) + if (block<=0) return 0 + var/list/BOUNDS=GetDNABounds(block) + var/value=GetSEValue(block) + return (value > BOUNDS[DNA_ON_LOWERBOUND]) + +// Set a block "on" or "off". +/datum/dna/proc/SetSEState(var/block,var/on,var/defer=0) + if (block<=0) return + var/list/BOUNDS=GetDNABounds(block) + var/val + if(on) + val=rand(BOUNDS[DNA_ON_LOWERBOUND],BOUNDS[DNA_ON_UPPERBOUND]) + else + val=rand(BOUNDS[DNA_OFF_LOWERBOUND],BOUNDS[DNA_OFF_UPPERBOUND]) + SetSEValue(block,val,defer) + +// Get hex-encoded SE block. +/datum/dna/proc/GetSEBlock(var/block) + return EncodeDNABlock(GetSEValue(block)) + +// Do not use this unless you absolutely have to. +// Set a block from a hex string. This is inefficient. If you can, use SetUIValue(). +// Used in DNA modifiers. +/datum/dna/proc/SetSEBlock(var/block,var/value,var/defer=0) + if (block<=0) return + var/nval=hex2num(value) + //testing("SetSEBlock([block],[value],[defer]): [value] -> [nval]") + return SetSEValue(block,nval,defer) + +/datum/dna/proc/GetSESubBlock(var/block,var/subBlock) + return copytext(GetSEBlock(block),subBlock,subBlock+1) + +// Do not use this unless you absolutely have to. +// Set a sub-block from a hex character. This is inefficient. If you can, use SetUIValue(). +// Used in DNA modifiers. +/datum/dna/proc/SetSESubBlock(var/block,var/subBlock, var/newSubBlock, var/defer=0) + if (block<=0) return + var/oldBlock=GetSEBlock(block) + var/newBlock="" + for(var/i=1, i<=length(oldBlock), i++) + if(i==subBlock) + newBlock+=newSubBlock + else + newBlock+=copytext(oldBlock,i,i+1) + //testing("SetSESubBlock([block],[subBlock],[newSubBlock],[defer]): [oldBlock] -> [newBlock]") + SetSEBlock(block,newBlock,defer) + + +/proc/EncodeDNABlock(var/value) + return add_zero2(num2hex(value,1), 3) + +/datum/dna/proc/UpdateUI() + src.uni_identity="" + for(var/block in UI) + uni_identity += EncodeDNABlock(block) + //testing("New UI: [uni_identity]") + dirtyUI=0 + +/datum/dna/proc/UpdateSE() + //var/oldse=struc_enzymes + struc_enzymes="" + for(var/block in SE) + struc_enzymes += EncodeDNABlock(block) + //testing("Old SE: [oldse]") + //testing("New SE: [struc_enzymes]") + dirtySE=0 + +// BACK-COMPAT! +// Just checks our character has all the crap it needs. +/datum/dna/proc/check_integrity(var/mob/living/carbon/human/character) + if(character) + if(UI.len != DNA_UI_LENGTH) + ResetUIFrom(character) + + if(length(struc_enzymes)!= 3*STRUCDNASIZE) + ResetSE() + + if(length(unique_enzymes) != 32) + unique_enzymes = md5(character.real_name) + else + if(length(uni_identity) != 3*DNA_UI_LENGTH) + uni_identity = "00600200A00E0110148FC01300B0095BD7FD3F4" + if(length(struc_enzymes)!= 3*STRUCDNASIZE) + struc_enzymes = "43359156756131E13763334D1C369012032164D4FE4CD61544B6C03F251B6C60A42821D26BA3B0FD6" + +// BACK-COMPAT! +// Initial DNA setup. I'm kind of wondering why the hell this doesn't just call the above. +/datum/dna/proc/ready_dna(mob/living/carbon/human/character) + ResetUIFrom(character) + + ResetSE() + + unique_enzymes = md5(character.real_name) + reg_dna[unique_enzymes] = character.real_name + diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm new file mode 100644 index 00000000000..08d07ab2e1f --- /dev/null +++ b/code/game/dna/dna2_helpers.dm @@ -0,0 +1,478 @@ +///////////////////////////// +// Helpers for DNA2 +///////////////////////////// + +// Pads 0s to t until length == u +/proc/add_zero2(t, u) + var/temp1 + while (length(t) < u) + t = "0[t]" + temp1 = t + if (length(t) > u) + temp1 = copytext(t,2,u+1) + return temp1 + +// DNA Gene activation boundaries, see dna2.dm. +// Returns a list object with 4 numbers. +/proc/GetDNABounds(var/block) + var/list/BOUNDS=dna_activity_bounds[block] + if(!istype(BOUNDS)) + return DNA_DEFAULT_BOUNDS + return BOUNDS + +// Give Random Bad Mutation to M +/proc/randmutb(var/mob/living/M) + if(!M) return + M.dna.check_integrity() + var/block = pick(GLASSESBLOCK,COUGHBLOCK,FAKEBLOCK,NERVOUSBLOCK,CLUMSYBLOCK,TWITCHBLOCK,HEADACHEBLOCK,BLINDBLOCK,DEAFBLOCK,HALLUCINATIONBLOCK) + M.dna.SetSEState(block, 1) + +// Give Random Good Mutation to M +/proc/randmutg(var/mob/living/M) + if(!M) return + M.dna.check_integrity() + var/block = pick(HULKBLOCK,XRAYBLOCK,FIREBLOCK,TELEBLOCK,NOBREATHBLOCK,REMOTEVIEWBLOCK,REGENERATEBLOCK,INCREASERUNBLOCK,REMOTETALKBLOCK,MORPHBLOCK,BLENDBLOCK,NOPRINTSBLOCK,SHOCKIMMUNITYBLOCK,SMALLSIZEBLOCK) + M.dna.SetSEState(block, 1) + +// Random Appearance Mutation +/proc/randmuti(var/mob/living/M) + if(!M) return + M.dna.check_integrity() + M.dna.SetUIValue(rand(1,UNIDNASIZE),rand(1,4095)) + +// Scramble UI or SE. +/proc/scramble(var/UI, var/mob/M, var/prob) + if(!M) return + M.dna.check_integrity() + if(UI) + for(var/i = 1, i <= DNA_UI_LENGTH-1, i++) + if(prob(prob)) + M.dna.SetUIValue(i,rand(1,4095),1) + M.dna.UpdateUI() + M.UpdateAppearance() + + else + for(var/i = 1, i <= STRUCDNASIZE-1, i++) + if(prob(prob)) + M.dna.SetSEValue(i,rand(1,4095),1) + M.dna.UpdateSE() + domutcheck(M, null) + return + +// I haven't yet figured out what the fuck this is supposed to do. +/proc/miniscramble(input,rs,rd) + var/output + output = null + if (input == "C" || input == "D" || input == "E" || input == "F") + output = pick(prob((rs*10));"4",prob((rs*10));"5",prob((rs*10));"6",prob((rs*10));"7",prob((rs*5)+(rd));"0",prob((rs*5)+(rd));"1",prob((rs*10)-(rd));"2",prob((rs*10)-(rd));"3") + if (input == "8" || input == "9" || input == "A" || input == "B") + output = pick(prob((rs*10));"4",prob((rs*10));"5",prob((rs*10));"A",prob((rs*10));"B",prob((rs*5)+(rd));"C",prob((rs*5)+(rd));"D",prob((rs*5)+(rd));"2",prob((rs*5)+(rd));"3") + if (input == "4" || input == "5" || input == "6" || input == "7") + output = pick(prob((rs*10));"4",prob((rs*10));"5",prob((rs*10));"A",prob((rs*10));"B",prob((rs*5)+(rd));"C",prob((rs*5)+(rd));"D",prob((rs*5)+(rd));"2",prob((rs*5)+(rd));"3") + if (input == "0" || input == "1" || input == "2" || input == "3") + output = pick(prob((rs*10));"8",prob((rs*10));"9",prob((rs*10));"A",prob((rs*10));"B",prob((rs*10)-(rd));"C",prob((rs*10)-(rd));"D",prob((rs*5)+(rd));"E",prob((rs*5)+(rd));"F") + if (!output) output = "5" + return output + +// HELLO I MAKE BELL CURVES AROUND YOUR DESIRED TARGET +// So a shitty way of replacing gaussian noise. +// input: YOUR TARGET +// rs: RAD STRENGTH +// rd: DURATION +/proc/miniscrambletarget(input,rs,rd) + var/output = null + switch(input) + if("0") + output = pick(prob((rs*10)+(rd));"0",prob((rs*10)+(rd));"1",prob((rs*10));"2",prob((rs*10)-(rd));"3") + if("1") + output = pick(prob((rs*10)+(rd));"0",prob((rs*10)+(rd));"1",prob((rs*10)+(rd));"2",prob((rs*10));"3",prob((rs*10)-(rd));"4") + if("2") + output = pick(prob((rs*10));"0",prob((rs*10)+(rd));"1",prob((rs*10)+(rd));"2",prob((rs*10)+(rd));"3",prob((rs*10));"4",prob((rs*10)-(rd));"5") + if("3") + output = pick(prob((rs*10)-(rd));"0",prob((rs*10));"1",prob((rs*10)+(rd));"2",prob((rs*10)+(rd));"3",prob((rs*10)+(rd));"4",prob((rs*10));"5",prob((rs*10)-(rd));"6") + if("4") + output = pick(prob((rs*10)-(rd));"1",prob((rs*10));"2",prob((rs*10)+(rd));"3",prob((rs*10)+(rd));"4",prob((rs*10)+(rd));"5",prob((rs*10));"6",prob((rs*10)-(rd));"7") + if("5") + output = pick(prob((rs*10)-(rd));"2",prob((rs*10));"3",prob((rs*10)+(rd));"4",prob((rs*10)+(rd));"5",prob((rs*10)+(rd));"6",prob((rs*10));"7",prob((rs*10)-(rd));"8") + if("6") + output = pick(prob((rs*10)-(rd));"3",prob((rs*10));"4",prob((rs*10)+(rd));"5",prob((rs*10)+(rd));"6",prob((rs*10)+(rd));"7",prob((rs*10));"8",prob((rs*10)-(rd));"9") + if("7") + output = pick(prob((rs*10)-(rd));"4",prob((rs*10));"5",prob((rs*10)+(rd));"6",prob((rs*10)+(rd));"7",prob((rs*10)+(rd));"8",prob((rs*10));"9",prob((rs*10)-(rd));"A") + if("8") + output = pick(prob((rs*10)-(rd));"5",prob((rs*10));"6",prob((rs*10)+(rd));"7",prob((rs*10)+(rd));"8",prob((rs*10)+(rd));"9",prob((rs*10));"A",prob((rs*10)-(rd));"B") + if("9") + output = pick(prob((rs*10)-(rd));"6",prob((rs*10));"7",prob((rs*10)+(rd));"8",prob((rs*10)+(rd));"9",prob((rs*10)+(rd));"A",prob((rs*10));"B",prob((rs*10)-(rd));"C") + if("10")//A + output = pick(prob((rs*10)-(rd));"7",prob((rs*10));"8",prob((rs*10)+(rd));"9",prob((rs*10)+(rd));"A",prob((rs*10)+(rd));"B",prob((rs*10));"C",prob((rs*10)-(rd));"D") + if("11")//B + output = pick(prob((rs*10)-(rd));"8",prob((rs*10));"9",prob((rs*10)+(rd));"A",prob((rs*10)+(rd));"B",prob((rs*10)+(rd));"C",prob((rs*10));"D",prob((rs*10)-(rd));"E") + if("12")//C + output = pick(prob((rs*10)-(rd));"9",prob((rs*10));"A",prob((rs*10)+(rd));"B",prob((rs*10)+(rd));"C",prob((rs*10)+(rd));"D",prob((rs*10));"E",prob((rs*10)-(rd));"F") + if("13")//D + output = pick(prob((rs*10)-(rd));"A",prob((rs*10));"B",prob((rs*10)+(rd));"C",prob((rs*10)+(rd));"D",prob((rs*10)+(rd));"E",prob((rs*10));"F") + if("14")//E + output = pick(prob((rs*10)-(rd));"B",prob((rs*10));"C",prob((rs*10)+(rd));"D",prob((rs*10)+(rd));"E",prob((rs*10)+(rd));"F") + if("15")//F + output = pick(prob((rs*10)-(rd));"C",prob((rs*10));"D",prob((rs*10)+(rd));"E",prob((rs*10)+(rd));"F") + + if(!input || !output) //How did this happen? + output = "8" + + return output + +// /proc/updateappearance has changed behavior, so it's been removed +// Use mob.UpdateAppearance() instead. + +// Simpler. Don't specify UI in order for the mob to use its own. +/mob/proc/UpdateAppearance(var/list/UI=null) + if(istype(src, /mob/living/carbon/human)) + if(UI!=null) + src.dna.UI=UI + src.dna.UpdateUI() + dna.check_integrity() + var/mob/living/carbon/human/H = src + H.r_hair = dna.GetUIValueRange(DNA_UI_HAIR_R, 255) + H.g_hair = dna.GetUIValueRange(DNA_UI_HAIR_G, 255) + H.b_hair = dna.GetUIValueRange(DNA_UI_HAIR_B, 255) + + H.r_facial = dna.GetUIValueRange(DNA_UI_BEARD_R, 255) + H.g_facial = dna.GetUIValueRange(DNA_UI_BEARD_G, 255) + H.b_facial = dna.GetUIValueRange(DNA_UI_BEARD_B, 255) + + H.r_eyes = dna.GetUIValueRange(DNA_UI_EYES_R, 255) + H.g_eyes = dna.GetUIValueRange(DNA_UI_EYES_G, 255) + H.b_eyes = dna.GetUIValueRange(DNA_UI_EYES_B, 255) + + H.s_tone = dna.GetUIValueRange(DNA_UI_SKIN_TONE, 220) + + if (dna.GetUIState(DNA_UI_GENDER)) + H.gender = FEMALE + else + H.gender = MALE + + //Hair + var/hair = dna.GetUIValueRange(DNA_UI_HAIR_STYLE,hair_styles_list.len) + if((0 < hair) && (hair <= hair_styles_list.len)) + H.h_style = hair_styles_list[hair] + + //Facial Hair + var/beard = dna.GetUIValueRange(DNA_UI_BEARD_STYLE,facial_hair_styles_list.len) + if((0 < beard) && (beard <= facial_hair_styles_list.len)) + H.f_style = facial_hair_styles_list[beard] + + H.update_body(0) + H.update_hair() + + return 1 + else + return 0 + +// Used below, simple injection modifier. +/proc/probinj(var/pr, var/inj) + return prob(pr+inj*pr) + +// (Re-)Apply mutations. +// TODO: Turn into a /mob proc, change inj to a bitflag for various forms of differing behavior. +// M: Mob to mess with +// connected: Machine we're in, type unchecked so I doubt it's used beyond monkeying +// inj: 1 for if we're checking this from an injector, screws with manifestation probability calc. +/proc/domutcheck(mob/living/M as mob, connected, inj) + if (!M) return + + M.dna.check_integrity() + + M.disabilities = 0 + M.sdisabilities = 0 + var/old_mutations = M.mutations + M.mutations = list() + M.pass_flags = 0 +// M.see_in_dark = 2 +// M.see_invisible = 0 + + if(PLANT in old_mutations) + M.mutations.Add(PLANT) + if(SKELETON in old_mutations) + M.mutations.Add(SKELETON) + if(FAT in old_mutations) + M.mutations.Add(FAT) + if(HUSK in old_mutations) + M.mutations.Add(HUSK) + + ///////////////////////////////////// + // IMPORTANT REMINDER + // IF A BLOCK IS SET TO 0 (unused) + // GetSEState(block) WILL RETURN 0 + ///////////////////////////////////// + + if(M.dna.GetSEState(NOBREATHBLOCK)) + if(probinj(45,inj) || (mNobreath in old_mutations)) + M << "\blue You feel no need to breathe." + M.mutations.Add(mNobreath) + if(M.dna.GetSEState(REMOTEVIEWBLOCK)) + if(probinj(45,inj) || (mRemote in old_mutations)) + M << "\blue Your mind expands" + M.mutations.Add(mRemote) + M.verbs += /mob/living/carbon/human/proc/remoteobserve + if(M.dna.GetSEState(REGENERATEBLOCK)) + if(probinj(45,inj) || (mRegen in old_mutations)) + M << "\blue You feel better" + M.mutations.Add(mRegen) + if(M.dna.GetSEState(INCREASERUNBLOCK)) + if(probinj(45,inj) || (mRun in old_mutations)) + M << "\blue Your leg muscles pulsate." + M.mutations.Add(mRun) + if(M.dna.GetSEState(REMOTETALKBLOCK)) + if(probinj(45,inj) || (mRemotetalk in old_mutations)) + M << "\blue You expand your mind outwards" + M.mutations.Add(mRemotetalk) + M.verbs += /mob/living/carbon/human/proc/remotesay + if(M.dna.GetSEState(MORPHBLOCK)) + if(probinj(45,inj) || (mMorph in old_mutations)) + M.mutations.Add(mMorph) + M << "\blue Your skin feels strange" + M.verbs += /mob/living/carbon/human/proc/morph + if(M.dna.GetSEState(HALLUCINATIONBLOCK)) + if(probinj(45,inj) || (mHallucination in old_mutations)) + M.mutations.Add(mHallucination) + M << "\red Your mind says 'Hello'" + if(M.dna.GetSEState(NOPRINTSBLOCK)) + if(probinj(45,inj) || (mFingerprints in old_mutations)) + M.mutations.Add(mFingerprints) + M << "\blue Your fingers feel numb" + if(M.dna.GetSEState(SHOCKIMMUNITYBLOCK)) + if(probinj(45,inj) || (mShock in old_mutations)) + M.mutations.Add(mShock) + M << "\blue Your skin feels strange" + if(M.dna.GetSEState(SMALLSIZEBLOCK)) + if(probinj(45,inj) || (mSmallsize in old_mutations)) + M << "\blue Your skin feels rubbery" + M.mutations.Add(mSmallsize) + M.pass_flags |= 1 + + + + if (M.dna.GetSEState(HULKBLOCK)) + if(probinj(5,inj) || (HULK in old_mutations)) + M << "\blue Your muscles hurt." + M.mutations.Add(HULK) + if (M.dna.GetSEState(HEADACHEBLOCK)) + M.disabilities |= EPILEPSY + M << "\red You get a headache." + if (M.dna.GetSEState(FAKEBLOCK)) + M << "\red You feel strange." + if (prob(95)) + if(prob(50)) + randmutb(M) + else + randmuti(M) + else + randmutg(M) + if (M.dna.GetSEState(COUGHBLOCK)) + M.disabilities |= COUGHING + M << "\red You start coughing." + if (M.dna.GetSEState(CLUMSYBLOCK)) + M << "\red You feel lightheaded." + M.mutations.Add(CLUMSY) + if (M.dna.GetSEState(TWITCHBLOCK)) + M.disabilities |= TOURETTES + M << "\red You twitch." + if (M.dna.GetSEState(XRAYBLOCK)) + if(probinj(30,inj) || (XRAY in old_mutations)) + M << "\blue The walls suddenly disappear." +// M.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS) +// M.see_in_dark = 8 +// M.see_invisible = 2 + M.mutations.Add(XRAY) + if (M.dna.GetSEState(NERVOUSBLOCK)) + M.disabilities |= NERVOUS + M << "\red You feel nervous." + if (M.dna.GetSEState(FIREBLOCK)) + if(probinj(30,inj) || (COLD_RESISTANCE in old_mutations)) + M << "\blue Your body feels warm." + M.mutations.Add(COLD_RESISTANCE) + if (M.dna.GetSEState(BLINDBLOCK)) + M.sdisabilities |= BLIND + M << "\red You can't seem to see anything." + if (M.dna.GetSEState(TELEBLOCK)) + if(probinj(15,inj) || (TK in old_mutations)) + M << "\blue You feel smarter." + M.mutations.Add(TK) + if (M.dna.GetSEState(DEAFBLOCK)) + M.sdisabilities |= DEAF + M.ear_deaf = 1 + M << "\red Its kinda quiet.." + if (M.dna.GetSEState(GLASSESBLOCK)) + M.disabilities |= NEARSIGHTED + M << "Your eyes feel weird..." + + /* If you want the new mutations to work, UNCOMMENT THIS. + if(istype(M, /mob/living/carbon)) + for (var/datum/mutations/mut in global_mutations) + mut.check_mutation(M) + */ + +//////////////////////////////////////////////////////////// Monkey Block + if (M.dna.GetSEState(MONKEYBLOCK) && istype(M, /mob/living/carbon/human)) + // human > monkey + var/mob/living/carbon/human/H = M + H.monkeyizing = 1 + var/list/implants = list() //Try to preserve implants. + for(var/obj/item/weapon/implant/W in H) + implants += W + W.loc = null + + if(!connected) + for(var/obj/item/W in (H.contents-implants)) + if (W==H.w_uniform) // will be teared + continue + H.drop_from_inventory(W) + M.monkeyizing = 1 + M.canmove = 0 + M.icon = null + M.invisibility = 101 + var/atom/movable/overlay/animation = new( M.loc ) + animation.icon_state = "blank" + animation.icon = 'icons/mob/mob.dmi' + animation.master = src + flick("h2monkey", animation) + sleep(48) + del(animation) + + + var/mob/living/carbon/monkey/O = null + 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) + O.dna = M.dna + M.dna = null + + if (M.suiciding) + O.suiciding = M.suiciding + M.suiciding = null + + + for(var/datum/disease/D in M.viruses) + O.viruses += D + D.affected_mob = O + M.viruses -= D + + + for(var/obj/T in (M.contents-implants)) + del(T) + + O.loc = M.loc + + if(M.mind) + M.mind.transfer_to(O) //transfer our mind to the cute little monkey + + if (connected) //inside dna thing + var/obj/machinery/dna_scannernew/C = connected + O.loc = C + C.occupant = O + connected = null + O.real_name = text("monkey ([])",copytext(md5(M.real_name), 2, 6)) + O.take_overall_damage(M.getBruteLoss() + 40, M.getFireLoss()) + O.adjustToxLoss(M.getToxLoss() + 20) + O.adjustOxyLoss(M.getOxyLoss()) + O.stat = M.stat + O.a_intent = "hurt" + for (var/obj/item/weapon/implant/I in implants) + I.loc = O + I.implanted = O +// O.update_icon = 1 //queue a full icon update at next life() call + del(M) + return + + if (!M.dna.GetSEState(MONKEYBLOCK) && !istype(M, /mob/living/carbon/human)) + // monkey > human, + var/mob/living/carbon/monkey/Mo = M + Mo.monkeyizing = 1 + var/list/implants = list() //Still preserving implants + for(var/obj/item/weapon/implant/W in Mo) + implants += W + W.loc = null + if(!connected) + for(var/obj/item/W in (Mo.contents-implants)) + Mo.drop_from_inventory(W) + M.monkeyizing = 1 + M.canmove = 0 + M.icon = null + M.invisibility = 101 + var/atom/movable/overlay/animation = new( M.loc ) + animation.icon_state = "blank" + animation.icon = 'icons/mob/mob.dmi' + animation.master = src + flick("monkey2h", animation) + sleep(48) + del(animation) + + var/mob/living/carbon/human/O = new( src ) + if(Mo.greaterform) + O.set_species(Mo.greaterform) + + if (M.dna.GetUIState(DNA_UI_GENDER)) + O.gender = FEMALE + else + O.gender = MALE + + if (M) + if (M.dna) + O.dna = M.dna + M.dna = null + + if (M.suiciding) + O.suiciding = M.suiciding + M.suiciding = null + + for(var/datum/disease/D in M.viruses) + O.viruses += D + D.affected_mob = O + M.viruses -= D + + //for(var/obj/T in M) + // del(T) + + O.loc = M.loc + + if(M.mind) + M.mind.transfer_to(O) //transfer our mind to the human + + if (connected) //inside dna thing + var/obj/machinery/dna_scannernew/C = connected + O.loc = C + C.occupant = O + connected = null + + var/i + while (!i) + var/randomname + if (O.gender == MALE) + randomname = capitalize(pick(first_names_male) + " " + capitalize(pick(last_names))) + else + randomname = capitalize(pick(first_names_female) + " " + capitalize(pick(last_names))) + if (findname(randomname)) + continue + else + O.real_name = randomname + i++ + O.UpdateAppearance() + O.take_overall_damage(M.getBruteLoss(), M.getFireLoss()) + O.adjustToxLoss(M.getToxLoss()) + O.adjustOxyLoss(M.getOxyLoss()) + O.stat = M.stat + for (var/obj/item/weapon/implant/I in implants) + I.loc = O + I.implanted = O +// O.update_icon = 1 //queue a full icon update at next life() call + del(M) + return +//////////////////////////////////////////////////////////// Monkey Block + if(M) + M.update_icon = 1 //queue a full icon update at next life() call + return null +/////////////////////////// DNA MISC-PROCS \ No newline at end of file diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm index 28598b175bb..37ad94e3f5e 100644 --- a/code/game/dna/dna_modifier.dm +++ b/code/game/dna/dna_modifier.dm @@ -302,19 +302,19 @@ return return -/obj/machinery/computer/scan_consolenew/proc/all_dna_blocks(var/buffer) +/obj/machinery/computer/scan_consolenew/proc/all_dna_blocks(var/list/buffer) var/list/arr = list() - for(var/i = 1, i <= length(buffer)/3, i++) - arr += "[i]:[copytext(buffer,i*3-2,i*3+1)]" + for(var/i = 1, i <= buffer.len, i++) + arr += "[i]:[EncodeDNABlock(buffer[i])]" return arr -/obj/machinery/computer/scan_consolenew/proc/setInjectorBlock(var/obj/item/weapon/dnainjector/I, var/blk, var/buffer) +/obj/machinery/computer/scan_consolenew/proc/setInjectorBlock(var/obj/item/weapon/dnainjector/I, var/blk, var/list/buffer) var/pos = findtext(blk,":") if(!pos) return 0 var/id = text2num(copytext(blk,1,pos)) if(!id) return 0 I.block = id - I.dna = copytext(buffer,id*3-2,id*3+1) + I.dna = list(buffer[id]) return 1 /obj/machinery/computer/scan_consolenew/attackby(obj/item/W as obj, mob/user as mob) @@ -571,10 +571,7 @@ return 1 // return 1 forces an update to all Nano uis attached to src if (href_list["pulseUIRadiation"]) - var/block - var/newblock - var/tstructure2 - block = getblock(getblock(src.connected.occupant.dna.uni_identity,src.selected_ui_block,DNA_BLOCK_SIZE),src.selected_ui_subblock,1) + var/block = src.connected.occupant.dna.GetUISubBlock(src.selected_ui_block,src.selected_ui_subblock) irradiating = src.radiation_duration var/lock_state = src.connected.locked @@ -590,13 +587,8 @@ if (prob((80 + (src.radiation_duration / 2)))) block = miniscrambletarget(num2text(selected_ui_target), src.radiation_intensity, src.radiation_duration) - newblock = null - if (src.selected_ui_subblock == 1) newblock = block + getblock(getblock(src.connected.occupant.dna.uni_identity,src.selected_ui_block,DNA_BLOCK_SIZE),2,1) + getblock(getblock(src.connected.occupant.dna.uni_identity,src.selected_ui_block,DNA_BLOCK_SIZE),3,1) - if (src.selected_ui_subblock == 2) newblock = getblock(getblock(src.connected.occupant.dna.uni_identity,src.selected_ui_block,DNA_BLOCK_SIZE),1,1) + block + getblock(getblock(src.connected.occupant.dna.uni_identity,src.selected_ui_block,DNA_BLOCK_SIZE),3,1) - if (src.selected_ui_subblock == 3) newblock = getblock(getblock(src.connected.occupant.dna.uni_identity,src.selected_ui_block,DNA_BLOCK_SIZE),1,1) + getblock(getblock(src.connected.occupant.dna.uni_identity,src.selected_ui_block,DNA_BLOCK_SIZE),2,1) + block - tstructure2 = setblock(src.connected.occupant.dna.uni_identity, src.selected_ui_block, newblock,DNA_BLOCK_SIZE) - src.connected.occupant.dna.uni_identity = tstructure2 - updateappearance(src.connected.occupant,src.connected.occupant.dna.uni_identity) + src.connected.occupant.dna.SetUISubBlock(src.selected_ui_block,src.selected_ui_subblock,block) + src.connected.occupant.UpdateAppearance() src.connected.occupant.radiation += (src.radiation_intensity+src.radiation_duration) else if (prob(20+src.radiation_intensity)) @@ -604,7 +596,7 @@ domutcheck(src.connected.occupant,src.connected) else randmuti(src.connected.occupant) - updateappearance(src.connected.occupant,src.connected.occupant.dna.uni_identity) + src.connected.occupant.UpdateAppearance() src.connected.occupant.radiation += ((src.radiation_intensity*2)+src.radiation_duration) src.connected.locked = lock_state return 1 // return 1 forces an update to all Nano uis attached to src @@ -635,12 +627,7 @@ return 1 // return 1 forces an update to all Nano uis attached to src if (href_list["pulseSERadiation"]) - var/block - var/newblock - var/tstructure2 - var/oldblock - - block = getblock(getblock(src.connected.occupant.dna.struc_enzymes,src.selected_se_block,DNA_BLOCK_SIZE),src.selected_se_subblock,1) + var/block = src.connected.occupant.dna.GetSESubBlock(src.selected_se_block,src.selected_se_subblock) irradiating = src.radiation_duration var/lock_state = src.connected.locked @@ -653,40 +640,26 @@ if(src.connected.occupant) if (prob((80 + (src.radiation_duration / 2)))) - if ((src.selected_se_block != 2 || src.selected_se_block != 12 || src.selected_se_block != 8 || src.selected_se_block || 10) && prob (20)) - oldblock = src.selected_se_block - block = miniscramble(block, src.radiation_intensity, src.radiation_duration) - newblock = null + // FIXME: Find out what these corresponded to and change them to the WHATEVERBLOCK they need to be. + //if ((src.selected_se_block != 2 || src.selected_se_block != 12 || src.selected_se_block != 8 || src.selected_se_block || 10) && prob (20)) + var/real_SE_block=selected_se_block + block = miniscramble(block, src.radiation_intensity, src.radiation_duration) + if(prob(20)) if (src.selected_se_block > 1 && src.selected_se_block < STRUCDNASIZE/2) - src.selected_se_block++ + real_SE_block++ else if (src.selected_se_block > STRUCDNASIZE/2 && src.selected_se_block < STRUCDNASIZE) - src.selected_se_block-- - if (src.selected_se_subblock == 1) newblock = block + getblock(getblock(src.connected.occupant.dna.struc_enzymes,src.selected_se_block,DNA_BLOCK_SIZE),2,1) + getblock(getblock(src.connected.occupant.dna.struc_enzymes,src.selected_se_block,DNA_BLOCK_SIZE),3,1) - if (src.selected_se_subblock == 2) newblock = getblock(getblock(src.connected.occupant.dna.struc_enzymes,src.selected_se_block,DNA_BLOCK_SIZE),1,1) + block + getblock(getblock(src.connected.occupant.dna.struc_enzymes,src.selected_se_block,DNA_BLOCK_SIZE),3,1) - if (src.selected_se_subblock == 3) newblock = getblock(getblock(src.connected.occupant.dna.struc_enzymes,src.selected_se_block,DNA_BLOCK_SIZE),1,1) + getblock(getblock(src.connected.occupant.dna.struc_enzymes,src.selected_se_block,DNA_BLOCK_SIZE),2,1) + block - tstructure2 = setblock(src.connected.occupant.dna.struc_enzymes, src.selected_se_block, newblock,DNA_BLOCK_SIZE) - src.connected.occupant.dna.struc_enzymes = tstructure2 - domutcheck(src.connected.occupant,src.connected) - src.connected.occupant.radiation += (src.radiation_intensity+src.radiation_duration) - src.selected_se_block = oldblock - else - // - block = miniscramble(block, src.radiation_intensity, src.radiation_duration) - newblock = null - if (src.selected_se_subblock == 1) newblock = block + getblock(getblock(src.connected.occupant.dna.struc_enzymes,src.selected_se_block,DNA_BLOCK_SIZE),2,1) + getblock(getblock(src.connected.occupant.dna.struc_enzymes,src.selected_se_block,DNA_BLOCK_SIZE),3,1) - if (src.selected_se_subblock == 2) newblock = getblock(getblock(src.connected.occupant.dna.struc_enzymes,src.selected_se_block,DNA_BLOCK_SIZE),1,1) + block + getblock(getblock(src.connected.occupant.dna.struc_enzymes,src.selected_se_block,DNA_BLOCK_SIZE),3,1) - if (src.selected_se_subblock == 3) newblock = getblock(getblock(src.connected.occupant.dna.struc_enzymes,src.selected_se_block,DNA_BLOCK_SIZE),1,1) + getblock(getblock(src.connected.occupant.dna.struc_enzymes,src.selected_se_block,DNA_BLOCK_SIZE),2,1) + block - tstructure2 = setblock(src.connected.occupant.dna.struc_enzymes, src.selected_se_block, newblock,DNA_BLOCK_SIZE) - src.connected.occupant.dna.struc_enzymes = tstructure2 - domutcheck(src.connected.occupant,src.connected) - src.connected.occupant.radiation += (src.radiation_intensity+src.radiation_duration) + real_SE_block-- + + connected.occupant.dna.SetSESubBlock(real_SE_block,selected_se_subblock,block) + domutcheck(src.connected.occupant,src.connected) + src.connected.occupant.radiation += (src.radiation_intensity+src.radiation_duration) else if (prob(80-src.radiation_duration)) randmutb(src.connected.occupant) domutcheck(src.connected.occupant,src.connected) else randmuti(src.connected.occupant) - updateappearance(src.connected.occupant,src.connected.occupant.dna.uni_identity) + src.connected.occupant.UpdateAppearance() src.connected.occupant.radiation += ((src.radiation_intensity*2)+src.radiation_duration) src.connected.locked = lock_state return 1 // return 1 forces an update to all Nano uis attached to src @@ -724,8 +697,8 @@ return src.disk.loc = get_turf(src) src.disk = null - return 1 - + return 1 + // All bufferOptions from here on require a bufferId if (!href_list["bufferId"]) return 0 @@ -738,7 +711,7 @@ if (bufferOption == "saveUI") if(src.connected.occupant && src.connected.occupant.dna) src.buffers[bufferId]["ue"] = 0 - src.buffers[bufferId]["data"] = src.connected.occupant.dna.uni_identity + src.buffers[bufferId]["data"] = src.connected.occupant.dna.UI if (!istype(src.connected.occupant,/mob/living/carbon/human)) src.buffers[bufferId]["owner"] = src.connected.occupant.name else @@ -749,7 +722,7 @@ if (bufferOption == "saveUIAndUE") if(src.connected.occupant && src.connected.occupant.dna) - src.buffers[bufferId]["data"] = src.connected.occupant.dna.uni_identity + src.buffers[bufferId]["data"] = src.connected.occupant.dna.UI if (!istype(src.connected.occupant,/mob/living/carbon/human)) src.buffers[bufferId]["owner"] = src.connected.occupant.name else @@ -762,7 +735,7 @@ if (bufferOption == "saveSE") if(src.connected.occupant && src.connected.occupant.dna) src.buffers[bufferId]["ue"] = 0 - src.buffers[bufferId]["data"] = src.connected.occupant.dna.struc_enzymes + src.buffers[bufferId]["data"] = src.connected.occupant.dna.SE if (!istype(src.connected.occupant,/mob/living/carbon/human)) src.buffers[bufferId]["owner"] = src.connected.occupant.name else @@ -801,10 +774,10 @@ if (src.buffers[bufferId]["ue"]) src.connected.occupant.real_name = src.buffers[bufferId]["owner"] src.connected.occupant.name = src.buffers[bufferId]["owner"] - src.connected.occupant.dna.uni_identity = src.buffers[bufferId]["data"] - updateappearance(src.connected.occupant,src.connected.occupant.dna.uni_identity) + src.connected.occupant.UpdateAppearance(src.buffers[bufferId]["data"]) else if (src.buffers[bufferId]["type"] == "se") - src.connected.occupant.dna.struc_enzymes = src.buffers[bufferId]["data"] + src.connected.occupant.dna.SE = src.buffers[bufferId]["data"] + src.connected.occupant.dna.UpdateSE() domutcheck(src.connected.occupant,src.connected) src.connected.occupant.radiation += rand(20,50) return 1 @@ -856,7 +829,7 @@ src.disk.owner = src.buffers[bufferId]["owner"] src.disk.name = "data disk - '[src.buffers[bufferId]["owner"]]'" //src.temphtml = "Data saved." - return 1 + return 1 /////////////////////////// DNA MACHINES diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm index e66aed88b87..96deb59554d 100644 --- a/code/game/gamemodes/changeling/changeling_powers.dm +++ b/code/game/gamemodes/changeling/changeling_powers.dm @@ -187,7 +187,7 @@ src.dna = chosen_dna src.real_name = chosen_dna.real_name src.flavor_text = "" - updateappearance(src, src.dna.uni_identity) + src.UpdateAppearance() domutcheck(src, null) src.verbs -= /mob/proc/changeling_transform @@ -314,7 +314,7 @@ W.layer = initial(W.layer) var/mob/living/carbon/human/O = new /mob/living/carbon/human( src ) - if (isblockon(getblock(C.dna.uni_identity, 11,3),11)) + if (C.dna.GetUIState(DNA_UI_GENDER)) O.gender = FEMALE else O.gender = MALE @@ -327,7 +327,7 @@ O.loc = C.loc - updateappearance(O,O.dna.uni_identity) + O.UpdateAppearance() domutcheck(O, null) O.setToxLoss(C.getToxLoss()) O.adjustBruteLoss(C.getBruteLoss()) @@ -719,7 +719,7 @@ var/list/datum/dna/hivemind_bank = list() T.visible_message("[T] transforms!") T.dna = chosen_dna T.real_name = chosen_dna.real_name - updateappearance(T, T.dna.uni_identity) + T.UpdateAppearance() domutcheck(T, null) feedback_add_details("changeling_powers","TS") return 1 diff --git a/code/game/gamemodes/events.dm b/code/game/gamemodes/events.dm index b9f68fb143c..5b1b1494b59 100644 --- a/code/game/gamemodes/events.dm +++ b/code/game/gamemodes/events.dm @@ -163,8 +163,8 @@ continue var/datum/disease/dnaspread/D = new D.strain_data["name"] = H.real_name - D.strain_data["UI"] = H.dna.uni_identity - D.strain_data["SE"] = H.dna.struc_enzymes + D.strain_data["UI"] = H.dna.UI + D.strain_data["SE"] = H.dna.SE D.carrier = 1 D.holder = H D.affected_mob = H diff --git a/code/game/gamemodes/events/holidays/Christmas.dm b/code/game/gamemodes/events/holidays/Christmas.dm index 2ee79e7c65b..72d42318e60 100644 --- a/code/game/gamemodes/events/holidays/Christmas.dm +++ b/code/game/gamemodes/events/holidays/Christmas.dm @@ -4,8 +4,8 @@ for(var/turf/simulated/floor/T in orange(1,xmas)) for(var/i=1,i<=rand(1,5),i++) new /obj/item/weapon/a_gift(T) - for(var/mob/living/simple_animal/corgi/Ian/Ian in mob_list) - Ian.place_on_head(new /obj/item/clothing/head/helmet/space/santahat(Ian)) + //for(var/mob/living/simple_animal/corgi/Ian/Ian in mob_list) + // Ian.place_on_head(new /obj/item/clothing/head/helmet/space/santahat(Ian)) /proc/ChristmasEvent() for(var/obj/structure/flora/tree/pine/xmas in world) diff --git a/code/game/gamemodes/events/holidays/Holidays.dm b/code/game/gamemodes/events/holidays/Holidays.dm index d2481eae441..2cd06199bd8 100644 --- a/code/game/gamemodes/events/holidays/Holidays.dm +++ b/code/game/gamemodes/events/holidays/Holidays.dm @@ -12,6 +12,10 @@ var/global/Holiday = null ////////////////////////////////////////////////////////////////////////////////////////////////////////// // ~Carn +/hook/startup/proc/updateHoliday() + Get_Holiday() + return 1 + //sets up the Holiday global variable. Shouldbe called on game configuration or something. /proc/Get_Holiday() if(!Holiday) return // Holiday stuff was not enabled in the config! diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm index ea9fbaec4a7..a834a3cc0b3 100644 --- a/code/game/gamemodes/gameticker.dm +++ b/code/game/gamemodes/gameticker.dm @@ -118,6 +118,7 @@ var/global/datum/controller/gameticker/ticker data_core.manifest() current_state = GAME_STATE_PLAYING + callHook("roundstart") //here to initialize the random events nicely at round start setup_economy() @@ -309,6 +310,8 @@ var/global/datum/controller/gameticker/ticker declare_completion() spawn(50) + callHook("roundend") + if (mode.station_was_nuked) feedback_set_details("end_proper","nuke") if(!delay_end) diff --git a/code/game/gamemodes/heist/heist.dm b/code/game/gamemodes/heist/heist.dm index e98d128559f..4dfff4fc4cf 100644 --- a/code/game/gamemodes/heist/heist.dm +++ b/code/game/gamemodes/heist/heist.dm @@ -139,10 +139,8 @@ var/global/vox_kills = 0 //Used to check the Inviolate. /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/i = 1 + var/max_objectives = pick(2,2,2,2,3,3,3,4) var/list/objs = list() while(i<= max_objectives) var/list/goals = list("kidnap","loot","salvage") @@ -163,13 +161,7 @@ var/global/vox_kills = 0 //Used to check the Inviolate. //-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 + objs += new /datum/objective/heist/inviolate_death for(var/datum/objective/heist/O in raid_objectives) O.choose_target() @@ -181,6 +173,7 @@ var/global/vox_kills = 0 //Used to check the Inviolate. 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!" + raider.current << "\red IF YOU HAVE NOT PLAYED A VOX BEFORE, REVIEW THIS THREAD: http://baystation12.net/forums/viewtopic.php?f=6&t=8657." var/obj_count = 1 for(var/datum/objective/objective in raider.objectives) raider.current << "Objective #[obj_count]: [objective.explanation_text]" @@ -252,6 +245,28 @@ var/global/vox_kills = 0 //Used to check the Inviolate. feedback_add_details("traitor_objective","[objective.type]|FAIL") count++ + var/text = "The vox raiders were:" + + for(var/datum/mind/vox in raiders) + text += "
[vox.key] was [vox.name] (" + var/obj/stack = raiders[vox] + if(get_area(stack) != locate(/area/shuttle/vox/station)) + text += "left behind)" + continue + else if(vox.current) + if(vox.current.stat == DEAD) + text += "died" + else + text += "survived" + if(vox.current.real_name != vox.name) + text += " as [vox.current.real_name]" + else + text += "body destroyed" + text += ")" + + world << text + return 1 + ..() datum/game_mode/proc/auto_declare_completion_heist() diff --git a/code/game/gamemodes/ninja/ninja.dm b/code/game/gamemodes/ninja/ninja.dm index 8dd3c45e19d..026253a73bf 100644 --- a/code/game/gamemodes/ninja/ninja.dm +++ b/code/game/gamemodes/ninja/ninja.dm @@ -26,18 +26,22 @@ ninja.assigned_role = "MODE" //So they aren't chosen for other jobs. ninja.special_role = "Ninja" ninja.original = ninja.current - if(ninjastart.len == 0) + + /*if(ninjastart.len == 0) ninja.current << "\red A proper starting location for you could not be found, please report this bug!" - ninja.current << "\red Attempting to place at a carpspawn." - for(var/obj/effect/landmark/L in landmarks_list) - if(L.name == "carpspawn") - ninjastart.Add(L) - if(ninjastart.len == 0 && latejoin.len > 0) - ninja.current << "\red Still no spawneable locations could be found. Defaulting to latejoin." - return 1 - else if (ninjastart.len == 0) - ninja.current << "\red Still no spawneable locations could be found. Aborting." - return 0 + ninja.current << "\red Attempting to place at a carpspawn."*/ + + //Until such a time as people want to place ninja spawn points, carpspawn will do fine. + for(var/obj/effect/landmark/L in landmarks_list) + if(L.name == "carpspawn") + ninjastart.Add(L) + if(ninjastart.len == 0 && latejoin.len > 0) + ninja.current << "\red No spawneable locations could be found. Defaulting to latejoin." + return 1 + else if (ninjastart.len == 0) + ninja.current << "\red No spawneable locations could be found. Aborting." + return 0 + return 1 /datum/game_mode/ninja/pre_setup() @@ -50,7 +54,7 @@ /datum/game_mode/ninja/post_setup() for(var/datum/mind/ninja in ninjas) if(ninja.current && !(istype(ninja.current,/mob/living/carbon/human))) return 0 - //forge_ninja_objectives(ninja) + forge_ninja_objectives(ninja) var/mob/living/carbon/human/N = ninja.current N.internal = N.s_store N.internals.icon_state = "internal1" @@ -78,7 +82,8 @@ return 1 /datum/game_mode/ninja/proc/forge_ninja_objectives(var/datum/mind/ninja) - var/objective_list[] = list(1,2,3,4,5) + + var/objective_list = list(1,2,3,4,5) for(var/i=rand(2,4),i>0,i--) switch(pick(objective_list)) if(1)//Kill diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index 3c9b606439b..c8c50fd09ba 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -217,9 +217,7 @@ synd_mob.equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(synd_mob), slot_w_uniform) synd_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(synd_mob), slot_shoes) - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/armor/vest(synd_mob), slot_wear_suit) synd_mob.equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(synd_mob), slot_gloves) - synd_mob.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/swat(synd_mob), slot_head) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/card/id/syndicate(synd_mob), slot_wear_id) if(synd_mob.backbag == 2) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(synd_mob), slot_back) if(synd_mob.backbag == 3) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_norm(synd_mob), slot_back) @@ -229,6 +227,26 @@ synd_mob.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/pill/cyanide(synd_mob), slot_in_backpack) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/automatic/c20r(synd_mob), slot_belt) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(synd_mob.back), slot_in_backpack) + + if(synd_mob.species) + var/race = synd_mob.species.name + + if(race == "Unathi") + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/space/rig/syndi/unathi(synd_mob), slot_wear_suit) + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/rig/syndi/unathi(synd_mob), slot_head) + else if(race == "Tajaran") + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/space/rig/syndi/tajara(synd_mob), slot_wear_suit) + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/rig/syndi/tajara(synd_mob), slot_head) + else if(race == "Skrell") + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/space/rig/syndi/skrell(synd_mob), slot_wear_suit) + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/rig/syndi/skrell(synd_mob), slot_head) + else + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/space/rig/syndi/human(synd_mob), slot_wear_suit) + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/rig/syndi/human(synd_mob), slot_head) + else + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/space/rig/syndi/human(synd_mob), slot_wear_suit) + synd_mob.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/rig/syndi/human(synd_mob), slot_head) + var/obj/item/weapon/implant/explosive/E = new/obj/item/weapon/implant/explosive(synd_mob) E.imp_in = synd_mob E.implanted = 1 diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm index 5d770346d5e..a58e8b553ff 100644 --- a/code/game/gamemodes/nuclear/nuclearbomb.dm +++ b/code/game/gamemodes/nuclear/nuclearbomb.dm @@ -8,6 +8,8 @@ var/bomb_set density = 1 var/deployable = 0.0 var/extended = 0.0 + var/lighthack = 0 + var/opened = 0.0 var/timeleft = 60.0 var/timing = 0.0 var/r_code = "ADMIN" @@ -15,15 +17,36 @@ var/bomb_set var/yes_code = 0.0 var/safety = 1.0 var/obj/item/weapon/disk/nuclear/auth = null + var/list/wires = list() + var/light_wire + var/safety_wire + var/timing_wire var/removal_stage = 0 // 0 is no removal, 1 is covers removed, 2 is covers open, // 3 is sealant open, 4 is unwrenched, 5 is removed from bolts. flags = FPRINT use_power = 0 + + /obj/machinery/nuclearbomb/New() ..() r_code = "[rand(10000, 99999.0)]"//Creates a random code upon object spawn. + src.wires["Red"] = 0 + src.wires["Blue"] = 0 + src.wires["Green"] = 0 + src.wires["Marigold"] = 0 + src.wires["Fuschia"] = 0 + src.wires["Black"] = 0 + src.wires["Pearl"] = 0 + var/list/w = list("Red","Blue","Green","Marigold","Black","Fuschia","Pearl") + src.light_wire = pick(w) + w -= src.light_wire + src.timing_wire = pick(w) + w -= src.timing_wire + src.safety_wire = pick(w) + w -= src.safety_wire + /obj/machinery/nuclearbomb/process() if (src.timing) bomb_set = 1 //So long as there is one nuke timing, it means one nuke is armed. @@ -36,6 +59,34 @@ var/bomb_set return /obj/machinery/nuclearbomb/attackby(obj/item/weapon/O as obj, mob/user as mob) + + if (istype(O, /obj/item/weapon/screwdriver)) + src.add_fingerprint(user) + if (src.auth) + if (src.opened == 0) + src.opened = 1 + overlays += image(icon, "npanel_open") + user << "You unscrew the control panel of [src]." + + else + src.opened = 0 + overlays -= image(icon, "npanel_open") + user << "You screw the control panel of [src] back on." + else + if (src.opened == 0) + user << "The [src] emits a buzzing noise, the panel staying locked in." + if (src.opened == 1) + src.opened = 0 + overlays -= image(icon, "npanel_open") + user << "You screw the control panel of [src] back on." + flick("nuclearbombc", src) + + return + if (istype(O, /obj/item/weapon/wirecutters) || istype(O, /obj/item/device/multitool)) + if (src.opened == 1) + nukehack_win(user) + return + if (src.extended) if (istype(O, /obj/item/weapon/disk/nuclear)) usr.drop_item() @@ -119,11 +170,13 @@ var/bomb_set /obj/machinery/nuclearbomb/attack_hand(mob/user as mob) if (src.extended) - if (!ishuman(user)) usr << "\red You don't have the dexterity to do this!" return 1 + if (!ishuman(user)) + usr << "\red You don't have the dexterity to do this!" + return 1 user.set_machine(src) var/dat = text("Nuclear Fission Explosive
\nAuth. Disk: []
", src, (src.auth ? "++++++++++" : "----------")) if (src.auth) @@ -150,11 +203,23 @@ var/bomb_set visible_message("\red With a steely snap, bolts slide out of [src] and anchor it to the flooring!") else visible_message("\red \The [src] makes a highly unpleasant crunching noise. It looks like the anchoring bolts have been cut.") - flick("nuclearbombc", src) - src.icon_state = "nuclearbomb1" + if(!src.lighthack) + flick("nuclearbombc", src) + src.icon_state = "nuclearbomb1" src.extended = 1 return +obj/machinery/nuclearbomb/proc/nukehack_win(mob/user as mob) + var/dat as text + dat += "Nuclear Fission Explosive
\nNuclear Device Wires:
" + for(var/wire in src.wires) + dat += text("[wire] Wire: [src.wires[wire] ? "Mend" : "Cut"] Pulse
") + dat += text("
The device is [src.timing ? "shaking!" : "still"]
") + dat += text("The device is [src.safety ? "quiet" : "whirring"].
") + dat += text("The lights are [src.lighthack ? "static" : "functional"].
") + user << browse("Bomb Defusion[dat]","window=nukebomb_hack") + onclose(user, "nukebomb_hack") + /obj/machinery/nuclearbomb/verb/make_deployable() set category = "Object" set name = "Make Deployable" @@ -172,16 +237,57 @@ var/bomb_set else usr << "\red You adjust some panels to make [src] deployable." src.deployable = 1 + return + /obj/machinery/nuclearbomb/Topic(href, href_list) ..() if (!usr.canmove || usr.stat || usr.restrained()) return - if (!ishuman(usr)) - usr << "\red You don't have the dexterity to do this!" - return 1 if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf)))) usr.set_machine(src) + if(href_list["act"]) + var/temp_wire = href_list["wire"] + if(href_list["act"] == "pulse") + if (!istype(usr.get_active_hand(), /obj/item/device/multitool)) + usr << "You need a multitool!" + else + if(src.wires[temp_wire]) + usr << "You can't pulse a cut wire." + else + if(src.light_wire == temp_wire) + src.lighthack = !src.lighthack + spawn(100) src.lighthack = !src.lighthack + if(src.timing_wire == temp_wire) + if(src.timing) + explode() + if(src.safety_wire == temp_wire) + src.safety = !src.safety + spawn(100) src.safety = !src.safety + if(src.safety == 1) + visible_message("\blue The [src] quiets down.") + if(!src.lighthack) + if (src.icon_state == "nuclearbomb2") + src.icon_state = "nuclearbomb1" + else + visible_message("\blue The [src] emits a quiet whirling noise!") + if(href_list["act"] == "wire") + if (!istype(usr.get_active_hand(), /obj/item/weapon/wirecutters)) + usr << "You need wirecutters!" + else + wires[temp_wire] = !wires[temp_wire] + if(src.safety_wire == temp_wire) + if(src.timing) + explode() + if(src.timing_wire == temp_wire) + if(!src.lighthack) + if (src.icon_state == "nuclearbomb2") + src.icon_state = "nuclearbomb1" + src.timing = 0 + bomb_set = 0 + if(src.light_wire == temp_wire) + src.lighthack = !src.lighthack + if (href_list["auth"]) if (src.auth) src.auth.loc = src.loc @@ -222,14 +328,16 @@ var/bomb_set return src.timing = !( src.timing ) if (src.timing) - src.icon_state = "nuclearbomb2" + if(!src.lighthack) + src.icon_state = "nuclearbomb2" if(!src.safety) bomb_set = 1//There can still be issues with this reseting when there are multiple bombs. Not a big deal tho for Nuke/N else bomb_set = 0 else - src.icon_state = "nuclearbomb1" bomb_set = 0 + if(!src.lighthack) + src.icon_state = "nuclearbomb1" if (href_list["safety"]) src.safety = !( src.safety ) if(safety) @@ -277,7 +385,8 @@ var/bomb_set src.timing = -1.0 src.yes_code = 0 src.safety = 1 - src.icon_state = "nuclearbomb3" + if(!src.lighthack) + src.icon_state = "nuclearbomb3" playsound(src,'sound/machines/Alarm.ogg',100,0,5) if (ticker && ticker.mode) ticker.mode.explosion_in_progress = 1 diff --git a/code/game/gamemodes/setupgame.dm b/code/game/gamemodes/setupgame.dm index 53d90a7e98c..c72f56f8cf2 100644 --- a/code/game/gamemodes/setupgame.dm +++ b/code/game/gamemodes/setupgame.dm @@ -1,10 +1,27 @@ +///////////////////////// +// (mostly) DNA2 SETUP +///////////////////////// + +// Randomize block, assign a reference name, and optionally define difficulty (by making activation zone smaller or bigger) +// The name is used on /vg/ for species with predefined genetic traits, +// and for the DNA panel in the player panel. +/proc/getAssignedBlock(var/name,var/list/blocksLeft, var/activity_bounds=DNA_DEFAULT_BOUNDS) + var/assigned = pick(blocksLeft) + blocksLeft.Remove(assigned) + assigned_blocks[assigned]=name + dna_activity_bounds[assigned]=activity_bounds + //testing("[name] assigned to block #[assigned].") + return assigned + /proc/setupgenetics() if (prob(50)) + // Currently unused. Will revisit. - N3X BLOCKADD = rand(-300,300) if (prob(75)) DIFFMUT = rand(0,20) + /* Old, for reference (so I don't accidentally activate something) - N3X var/list/avnums = new/list() var/tempnum @@ -41,11 +58,50 @@ tempnum = pick(avnums) avnums.Remove(tempnum) BLINDBLOCK = tempnum + */ + var/list/numsToAssign=new() + for(var/i=1;i