Files
goonstation-2016/code/datums/genetics/baseBioeffect.dm
2016-03-06 20:52:14 +01:00

326 lines
11 KiB
Plaintext

//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<owner.blockGaps, i++)
var/datum/basePair/bp = pick(blockListCurr - gapList)
gapList.Add(bp)
bp.bpp1 = "X"
bp.bpp2 = "X"
for(var/i=0, i<owner.lockedGaps, i++)
if (!prob(owner.lockProb))
continue
var/datum/basePair/bp = pick(blockListCurr - gapList)
gapList.Add(bp)
bp.lockcode = ""
for (var/c = owner.lockedDiff, c > 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, "<span style=\"color:red\">Oh christ something's gone completely batshit. Report this to a coder.</span>")
return
if (!owner.cooldowncheck())
boutput(user, "<span style=\"color:red\">That ability is on cooldown for [round((owner.last_cast - world.time) / 10)] seconds.</span>")
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, "<span style=\"color:red\">That ability is on cooldown for [round((last_cast - world.time) / 10)] seconds.</span>")
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