//Defines don't work correctly here because FUCK BYOND ARGH //#define effectTypeMutantRace 1 //#define effectTypeDisability 2 //#define effectTypePower 3 //SO INSTEAD , GLOBAL VARS. GEE THANKS BYOND. var/const/effectTypeMutantRace = 1 var/const/effectTypeDisability = 2 var/const/effectTypePower = 3 /datum/bioEffect var/name = "" //Name of the effect. var/id = "goddamn_it" //Internal ID of the effect. var/desc = "" //Visible description of the effect. var/researched_desc = null // You get this in mutation research if you've activated the effect var/datum/bioEffect/global_instance = null // bioeffectlist version of this effect var/research_level = 0 // 0 = not, 1 = in progress, 2 = done, 3 = activated var/research_finish_time = 0 var/effectType = effectTypeDisability //Used to categorize effects. Mostly used for MutantRaces to prevent the mob from getting more than one. var/mutantrace_option = null var/isBad = 0 //Is this a bad effect? Used to determine which effects to use for certain things (radiation etc). var/probability = 100 //The probability that this will be selected when building the effect pool. Works like the weights in pick() var/blockCount = 2 //Amount of blocks generated. More will make this take longer to activate. var/blockGaps = 2 //Amount of gaps in the sequence. More will make this more difficult to activate since it will require more guessing or cross-referencing. var/lockProb = 5 //How likely each block is to be locked when there's locks present var/lockedGaps = 1 //How many base pairs in this sequence will need unlocking var/lockedDiff = 2 //How many characters in the code? var/lockedTries = 3 //How many attempts before it rescrambles? var/list/lockedChars = list("G","C") // How many different characters are used var/occur_in_genepools = 1 var/scanner_visibility = 1 var/secret = 0 // requires a specific research tech to see in genepools var/list/mob_exclusion = list() // this bio-effect won't occur in the pools of mob types in this list var/mob_exclusive = null // bio-effect will only occur in this mob type var/mob/owner = null //Mob that owns this effect. var/datum/bioHolder/holder = null //Holder that contains this effect. var/msgGain = "" //Message shown when effect is added. var/msgLose = "" //Message shown when effect is removed. var/timeLeft = -1//Time left for temporary effects. var/variant = 1 //For effects with different variants. var/cooldown = 0 //For effects that come with verbs var/can_reclaim = 1 // Can this gene be turned into mats with the reclaimer? var/can_scramble = 1 // Can this gene be scrambled with the emitter? var/can_copy = 1 //Is this gene copied over on bioHolder transfer (i.e. cloning?) var/can_research = 1 // If zero, it must be researched via brute force var/can_make_injector = 1 // Guess. var/req_mut_research = null // If set, need to research the mutation before you can do anything w/ this one var/reclaim_mats = 10 // Materials returned when this gene is reclaimed var/reclaim_fail = 5 // Chance % for a reclamation of this gene to fail var/curable_by_mutadone = 1 var/stability_loss = 0 var/activated_from_pool = 0 var/altered = 0 var/add_delay = 0 var/wildcard = 0 var/datum/dnaBlocks/dnaBlocks = null var/data = null //Should be used to hold custom user data or it might not be copied correctly with injectors and all these things. var/image/overlay_image = null New(var/for_global_list = 0) if (!for_global_list) global_instance = bioEffectList[src.id] dnaBlocks = new/datum/dnaBlocks(src) return ..() proc/OnAdd() //Called when the effect is added. if(overlay_image) if(isliving(owner)) var/mob/living/L = owner L.UpdateOverlays(overlay_image, id) return proc/OnRemove() //Called when the effect is removed. if(overlay_image) if(isliving(owner)) var/mob/living/L = owner L.UpdateOverlays(null, id) return proc/OnMobDraw() //Called when the overlays for the mob are drawn. return proc/OnLife() //Called when the life proc of the mob is called. return proc/GetCopy() //Gets a copy of this effect. Used to build local effect pool from global instance list. //Please don't use this for anything else as it might not work as you think it should. var/datum/bioEffect/E = new src.type() E.dnaBlocks.blockList = src.dnaBlocks.blockList //Since we assume that the effect being copied is the one in the global pool we copy //a REFERENCE to its correct sequence into the new instance. return E proc/get_global_instance() if (istype(global_instance)) return global_instance else var/datum/bioEffect/BE = bioEffectList[src.id] if (istype(BE)) return BE else return null return null /datum/dnaBlocks var/datum/bioEffect/owner = null var/list/blockList = new/list() //List of CORRECT blocks for this mutation. This is global and should not be modified since it represents the correct solution. var/list/blockListCurr = new/list() // List of CURRENT blocks for this mutation. This is local and represents the research people are doing. New(var/holder) owner = holder return ..() proc/sequenceCorrect() if(blockList.len != blockListCurr.len) //Things went completely and entirely wrong and everything is broken HALP. //Some dickwad probably messed with the global sequence. return 0 for(var/i=0, i < blockList.len, i++) var/datum/basePair/correct = blockList[i+1] var/datum/basePair/current = blockListCurr[i+1] if(correct.bpp1 != current.bpp1 || correct.bpp2 != current.bpp2) //NOPE return 0 return 1 proc/pairCorrect(var/pair_index) if(blockList.len != blockListCurr.len || !pair_index) return 0 var/datum/basePair/correct = blockList[pair_index] var/datum/basePair/current = blockListCurr[pair_index] if(correct.bpp1 != current.bpp1 || correct.bpp2 != current.bpp2) //NOPE return 0 return 1 proc/ModBlocks() //Gets the normal sequence for this mutation and then "corrupts" it locally. for(var/datum/basePair/bp in blockList) var/datum/basePair/bpNew = new() bpNew.bpp1 = bp.bpp1 bpNew.bpp2 = bp.bpp2 blockListCurr.Add(bpNew) for(var/datum/basePair/bp in blockListCurr) if(prob(33)) if(prob(50)) bp.bpp1 = "X" else bp.bpp2 = "X" var/list/gapList = new/list() //Make sure you don't have more gaps than basepairs or youll get an error. //But at that point the mutation would be unsolvable. for(var/i=0, i 0, c--) bp.lockcode += pick(owner.lockedChars) bp.locktries = owner.lockedTries var/diff = 1 if (owner.req_mut_research) diff = 0 else var/difficulty = round((owner.lockedDiff ** owner.lockedChars.len) / owner.lockedTries) switch(difficulty) if(11 to 20) diff = 2 if(21 to 30) diff = 3 if(31 to 50) diff = 4 if(51 to INFINITY) diff = 5 bp.bpp1 = "Unk[diff]" bp.bpp2 = "Unk[diff]" bp.marker = "locked" return sequenceCorrect() proc/GenerateBlocks() //Generate DNA blocks. This sequence will be used globally. for(var/i=0, i < owner.blockCount, i++) for(var/a=0, a < 4, a++) //4 pairs per block. var/S = pick("G", "T", "C" , "A") var/datum/basePair/B = new() B.bpp1 = S switch(S) if("G") B.bpp2 = "C" if("C") B.bpp2 = "G" if("T") B.bpp2 = "A" if("A") B.bpp2 = "T" blockList.Add(B) return proc/ChangeAllMarkers(var/sprite_state) if(!istext(sprite_state)) sprite_state = "white" for(var/datum/basePair/bp in blockListCurr) bp.marker = sprite_state return /datum/basePair var/bpp1 = "" var/bpp2 = "" var/marker = "green" var/lockcode = "" var/locktries = 0 /obj/screen/ability/topBar/genetics tens_offset_x = 19 tens_offset_y = 7 secs_offset_x = 23 secs_offset_y = 7 clicked(parameters) var/mob/living/user = usr if (!istype(user) || !istype(owner)) boutput(user, "Oh christ something's gone completely batshit. Report this to a coder.") return if (!owner.cooldowncheck()) boutput(user, "That ability is on cooldown for [round((owner.last_cast - world.time) / 10)] seconds.") return if (!owner.targeted) owner.handleCast() return else user.targeting_spell = owner user.update_cursor() get_controlling_mob() if (!istype(owner,/datum/targetable/geneticsAbility/)) return null var/datum/targetable/geneticsAbility/GA = owner var/mob/M = GA.owner if (!istype(M) || !M.client) return null return M /datum/targetable/geneticsAbility icon = 'icons/mob/genetics_powers.dmi' icon_state = "template" last_cast = 0 targeted = 1 target_anything = 1 var/can_act_check = 1 var/datum/bioEffect/power/linked_power = null var/mob/living/owner = null New() var/obj/screen/ability/topBar/genetics/B = new /obj/screen/ability/topBar/genetics(null) B.icon = src.icon B.icon_state = src.icon_state B.name = src.name B.desc = src.desc B.owner = src src.object = B doCooldown() if (istype(owner,/mob/living/carbon/human/)) var/mob/living/carbon/human/H = owner last_cast = world.time + linked_power.cooldown if (linked_power.cooldown > 0) spawn(linked_power.cooldown) if(src) H.hud.update_ability_hotbar() tryCast(atom/target) if (can_act_check && !can_act(owner)) return 999 if (last_cast > world.time) boutput(holder.owner, "That ability is on cooldown for [round((last_cast - world.time) / 10)] seconds.") return 999 . = cast(target) handleCast(atom/target) var/result = tryCast(target) if (result && result != 999) last_cast = 0 // reset cooldown else if (result != 999) doCooldown() afterCast() cast(atom/target) if (!owner) return 1 if (!linked_power) return 1 if (ismob(target)) logTheThing("combat", owner, target, "used the [linked_power.name] power on %target%.") else if (target) logTheThing("combat", owner, null, "used the [linked_power.name] power on [target].") else logTheThing("combat", owner, null, "used the [linked_power.name] power.") return 0 afterCast() if (istype(owner,/mob/living/carbon/human/)) var/mob/living/carbon/human/H = owner H.hud.update_ability_hotbar() return 0