diff --git a/code/WorkInProgress/organs/implants.dm b/code/WorkInProgress/organs/implants.dm new file mode 100644 index 00000000000..98350ee7f9a --- /dev/null +++ b/code/WorkInProgress/organs/implants.dm @@ -0,0 +1,13 @@ +/*------ +SPELL IMPLANTS + + Most diverse effects + - Limited charges, failure rate + +CYBERNETIC IMPLANTS + + Easiest to make + - Require power + +GRAFTS (includes basic human bodyparts) + + Permanent effects + - Horrible side effects +*/ \ No newline at end of file diff --git a/code/WorkInProgress/organs/organs.dm b/code/WorkInProgress/organs/organs.dm new file mode 100644 index 00000000000..0af9e2eb29f --- /dev/null +++ b/code/WorkInProgress/organs/organs.dm @@ -0,0 +1,265 @@ +//TODO: Move cyber organs active/inactive stats to vars. + +//flags for organType +#define CYBER 1 +#define SPELL 2 + +/obj/organstructure //used obj for the "contents" var + name = "organs" + + var/obj/item/weapon/cell/mainPowerCell = null //for ease of refernce for installed c. implants + var/species = "mob" //for speaking in unknown languages purposes + + var/obj/organ/limb/arms/arms = null + var/obj/organ/limb/legs/legs = null + var/obj/organ/chest/chest = null + + proc/FindMainPowercell() + if(chest) //priority goes to chest implant, if there is one + if((chest.organType & CYBER) && chest.canExportPower && chest.cell) + mainPowerCell = chest.cell + return + var/list/organs = GetAllContents() + for(var/obj/organ/otherOrgan in organs) //otherwise, maybe some other organ fits the criteria? + if((otherOrgan.organType & CYBER) && otherOrgan.canExportPower && otherOrgan.cell) + mainPowerCell = otherOrgan:cell + return + mainPowerCell = null //otherwise, seems there's no main cell + return + + proc/GetSpeciesName() + var/list/speciesPresent = list() + + for(var/obj/organ/organ in src) //only external organs count, since it's judging by the appearance + if(speciesPresent[organ.species]) + speciesPresent[organ.species]++ + else + speciesPresent[organ.species] = 1 //not sure, but I think it's not initialised before that, so can't ++ + + var/list/dominantSpecies = list() + + for(var/speciesName in speciesPresent) + if(!dominantSpecies.len) + dominantSpecies += speciesName + else + if(speciesPresent[dominantSpecies[1]] == speciesPresent[speciesName]) + dominantSpecies += speciesName + else if(speciesPresent[dominantSpecies[1]] < speciesPresent[speciesName]) + dominantSpecies = list(speciesName) + + if(!dominantSpecies.len) + species = "mob" + else + species = pick(dominantSpecies) + + return + + proc/RecalculateStructure() + var/list/organs = GetAllContents() + + arms = locate(/obj/organ/limb/arms) in organs + legs = locate(/obj/organ/limb/legs) in organs + chest = locate(/obj/organ/chest) in organs + + GetSpeciesName() + FindMainPowercell() + + return + + proc/ProcessOrgans() + set background = 1 + + var/list/organs = GetAllContents() + for(var/obj/organ/organ in organs) + organ.ProcessOrgan() + + return + + New() + ..() + RecalculateStructure() + +/obj/organstructure/human + name = "human organs" + + New() + //new /obj/organ/limb/arms/human(src) + //new /obj/organ/limb/legs/human(src) + new /obj/organ/chest/human(src) + ..() + +/obj/organstructure/cyber + name = "cyborg organs" + + New() + //new /obj/organ/limb/arms/cyber(src) + //new /obj/organ/limb/legs/cyber(src) + new /obj/organ/chest/cyber(src) + ..() + +/obj/organ + name = "organ" + + //All types + var/organType = 0 //CYBER and SPELL go here + var/species = "mob" + var/obj/organstructure/rootOrganStructure = null + + New(location) + ..() + + rootOrganStructure = FindRootStructure() + + proc/FindRootStructure() + if(istype(loc,/obj/organ)) + var/obj/organ/parent = loc + return parent.FindRootStructure() + else if(istype(loc,/obj/organstructure)) + return loc + return null + + proc/ProcessOrgan() + set background = 1 + + if(organType & CYBER) + var/hasPower = DrainPower() + if(!hasPower && active) + Deactivate() + else if(hasPower && !active) + Activate() + + //CYBORG type + var/obj/item/weapon/cell/cell = null + var/canExportPower = 0 //only comes in play if it has a cell + var/active = 0 + var/powerDrainPerTick = 0 + + proc/DrainPower() + set background = 1 + + if(!powerDrainPerTick) + return 1 + if(cell) + if(cell.charge >= powerDrainPerTick) + cell.charge -= powerDrainPerTick + return 1 + if(rootOrganStructure.mainPowerCell) + if(rootOrganStructure.mainPowerCell.charge >= powerDrainPerTick) + rootOrganStructure.mainPowerCell.charge -= powerDrainPerTick + return 1 + return 0 + + proc/Activate() //depends on the organ, involves setting active to 1 and changing the organ's vars to reflect its "activated" state + rootOrganStructure.loc << "\blue Your [name] powers up!" + active = 1 + return + + proc/Deactivate() //depends on the organ, involves setting active to 0 and changing the organ's vars to reflect its "deactivated" state + rootOrganStructure.loc << "\red Your [name] powers down." + active = 0 + return + +/obj/organ/limb + name = "limb" + +/obj/organ/limb/arms + name = "arms" + + var/minDamage = 5 //punching damage + var/maxDamage = 5 +// var/strangleDelay = 1 //The code is a bit too complicated for that right now + +/obj/organ/limb/arms/human + name = "human arms" + species = "human" + minDamage = 1 + maxDamage = 9 + +/obj/organ/limb/arms/cyber + name = "cyborg arms" + species = "cyborg" + organType = CYBER + powerDrainPerTick = 5 + + Activate() + ..() + minDamage = 3 + maxDamage = 14 + + Deactivate() + ..() + minDamage = 0 + maxDamage = 3 + + +/obj/organ/limb/legs + name = "legs" + + var/moveRunDelay = 1 //not sure about how that works + var/moveWalkDelay = 7 + //var/knockdownResist = 0 + +/obj/organ/limb/legs/human + name = "human legs" + species = "human" + +/obj/organ/limb/legs/cyber + name = "cyborg legs" + species = "cyborg" + organType = CYBER + powerDrainPerTick = 5 + + Activate() + ..() + moveRunDelay = 0 + moveWalkDelay = 3 + + Deactivate() + ..() + moveRunDelay = 2 + moveWalkDelay = 10 + + +/obj/organ/chest + name = "chest" + var/maxHealth = 50 //right now, the mob's (only humans for now) health depends only on it. Will be fixed later + +/obj/organ/chest/human + name = "human chest" + species = "human" + maxHealth = 100 + + New() + ..() + new /obj/organ/limb/arms/human(src) + new /obj/organ/limb/legs/human(src) + +/obj/organ/chest/cyber + name = "cyborg chest" + species = "cyborg" + organType = CYBER + canExportPower = 1 + maxHealth = 150 + + New() + ..() + cell = new /obj/item/weapon/cell/high(src) + cell.charge = cell.maxcharge + new /obj/organ/limb/arms/cyber(src) + new /obj/organ/limb/legs/cyber(src) + + Activate() + ..() + canExportPower = 1 + maxHealth = 150 + if(rootOrganStructure.loc && istype(rootOrganStructure.loc,/mob/living)) + var/mob/living/holder = rootOrganStructure.loc + holder.updatehealth() + + Deactivate() + ..() + canExportPower = 0 + maxHealth = 120 + if(rootOrganStructure.loc && istype(rootOrganStructure.loc,/mob/living)) + var/mob/living/holder = rootOrganStructure.loc + holder.updatehealth() \ No newline at end of file diff --git a/code/defines/mob/mob.dm b/code/defines/mob/mob.dm index 282753e90ef..0e6d94265e3 100644 --- a/code/defines/mob/mob.dm +++ b/code/defines/mob/mob.dm @@ -196,4 +196,6 @@ var/update_icon = 1 // Set to 0 if you want that the mob's icon doesn't update when it moves -- Skie // This can be used if you want to change the icon on the fly and want it to stay - var/UI = 'screen1_old.dmi' // For changing the UI from preferences \ No newline at end of file + var/UI = 'screen1_old.dmi' // For changing the UI from preferences + + var/obj/organstructure/organStructure = null //for dem organs \ No newline at end of file diff --git a/code/defines/procs/helpers.dm b/code/defines/procs/helpers.dm index f38a6543412..e195ba3da53 100644 --- a/code/defines/procs/helpers.dm +++ b/code/defines/procs/helpers.dm @@ -1036,4 +1036,14 @@ proc/isemptylist(list/list) proc/clearlist(list/list) if(istype(list)) list.len = 0 - return \ No newline at end of file + return + +/atom/proc/GetAllContents(searchDepth = 5) + var/list/toReturn = list() + + for(var/atom/part in contents) + toReturn += part + if(part.contents.len && searchDepth) + toReturn += part.GetAllContents(searchDepth - 1) + + return toReturn \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index fe40924810a..2e1a7bc375f 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -59,8 +59,18 @@ src.icon = src.stand_icon update_clothing() src << "\blue Your icons have been generated!" + ..() + organStructure = new /obj/organstructure/human(src) + +/mob/living/carbon/human/cyborg + New() + ..() + if(organStructure) //hacky, but it's not supposed to be in for a long time anyway + del(organStructure) + organStructure = new /obj/organstructure/cyber(src) + /mob/living/carbon/human/Bump(atom/movable/AM as mob|obj, yes) if ((!( yes ) || src.now_pushing)) return @@ -1699,7 +1709,11 @@ if (M.a_intent == "hurt" && !(M.gloves && M.gloves.elecgen == 1)) if (src.w_uniform) src.w_uniform.add_fingerprint(M) - var/damage = rand(1, 9) + var/damage = 0 + if(organStructure && organStructure.arms) + damage = rand(organStructure.arms.minDamage,organStructure.arms.maxDamage) + else + damage = rand(1, 9) //oh boy var/datum/organ/external/affecting = src.organs["chest"] var/t = M.zone_sel.selecting if ((t in list( "eyes", "mouth" ))) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index f3d14cd0852..b846d038069 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -80,6 +80,8 @@ for(var/obj/item/weapon/grab/G in src) G.process() + ..() //for organs + /* ................................................ ..........................._,-~"¯¯"~-, .................................................. ................__„-~"¯¯:::,-~~-,_::::"- diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 3797e3beb28..d7b13222178 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -74,8 +74,11 @@ /mob/living/proc/updatehealth() - if (src.nodamage == 0) - src.health = 100 - src.oxyloss - src.toxloss - src.fireloss - src.bruteloss + if (!src.nodamage) + if(organStructure && organStructure.chest) + health = organStructure.chest.maxHealth - oxyloss - toxloss - fireloss - bruteloss + else + src.health = 100 - src.oxyloss - src.toxloss - src.fireloss - src.bruteloss else src.health = 100 src.stat = 0 diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 17643ae2d52..5ec51f915a6 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1060,6 +1060,8 @@ proc/isobserver(A) return 0 /mob/proc/Life() + if(organStructure) + organStructure.ProcessOrgans() return /mob/proc/update_clothing() @@ -1816,12 +1818,18 @@ proc/isobserver(A) if("run") if (mob.drowsyness > 0) move_delay += 6 - move_delay += 1 + if(mob.organStructure && mob.organStructure.legs) + move_delay += mob.organStructure.legs.moveRunDelay + else + move_delay += 1 if("face") mob.dir = direct return if("walk") - move_delay += 7 + if(mob.organStructure && mob.organStructure.legs) + move_delay += mob.organStructure.legs.moveWalkDelay + else + move_delay += 7 move_delay += mob.movement_delay() diff --git a/icons/mob/organs.dmi b/icons/mob/organs.dmi new file mode 100644 index 00000000000..de56c52c917 Binary files /dev/null and b/icons/mob/organs.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 2f784f9d69f..58c006701c4 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -111,6 +111,7 @@ #define FILE_DIR "code/WorkInProgress/computer2" #define FILE_DIR "code/WorkInProgress/experimental" #define FILE_DIR "code/WorkInProgress/optics" +#define FILE_DIR "code/WorkInProgress/organs" #define FILE_DIR "code/WorkInProgress/pda2" #define FILE_DIR "code/WorkInProgress/recycling" #define FILE_DIR "icons" @@ -129,6 +130,7 @@ #define FILE_DIR "icons/turf" #define FILE_DIR "interface" #define FILE_DIR "maps" +#define FILE_DIR "maps/backup" #define FILE_DIR "sound" #define FILE_DIR "sound/ambience" #define FILE_DIR "sound/announcer" @@ -791,6 +793,8 @@ #include "code\WorkInProgress\message_server.dm" #include "code\WorkInProgress\mining.dm" #include "code\WorkInProgress\NewBan.dm" +#include "code\WorkInProgress\organs\implants.dm" +#include "code\WorkInProgress\organs\organs.dm" #include "code\WorkInProgress\recycling\conveyor.dm" #include "code\WorkInProgress\recycling\disposal-construction.dm" #include "code\WorkInProgress\recycling\disposal.dm"