/* -- atom.changeStatus(statusId, duration, optional) If atom has status with [statusId], change by [duration]. (The change is relative to the current value, think +=) If atom does not have status, add it with given [duration]. In both cases [optional] will be passed into either .onAdd or .onChange on the status effect. Useful for custom behaviour. Returns: The changed/added status effect or null on errors. -- atom.setStatus(statusId, duration, optional) If atom has status with [statusId], set it to [duration]. (The change is absolute, think =) If atom does not have status, add it with given [duration]. In both cases [optional] will be passed into either .onAdd or .onChange on the status effect. Useful for custom behaviour. Returns: The changed/added status effect or null on errors. -- atom.getStatusDuration(statusId) Returns duration of status with given [statusId], or null if not found. -- atom.hasStatus(statusId, optionalArgs = null) Returns first status with given [statusId] or null if not found. [optionalArgs] can be passed in for additional checks that are handled in the effects .onCheck proc. Useful if you want to check some custom conditions on status effects -- atom.delStatus(var/status) Deletes the given status from the atom. [status] can either be a reference to a status effect or a status effect ID. Additional notes: Non-unique status effects (effects that can be applied several times to the same atom) can not be changed by normal means after they are added. Keep a reference if you need to change them. Status effect procs have comments in their base definition below. Check there if you want to know more about what they do. Status effects with a duration of null last indefinitely. (Shows as a duration of * in the UI) ((Keep in mind that null is distinct from 0)) */ var/list/globalStatusPrototypes = list() var/list/globalStatusInstances = list() //Simple global list of groupname : amount, that tells the system how many effects of a group we can have active at most. See exclusiveGroup. Buffs above the max will not be applied. var/list/statusGroupLimits = list("Food"=4) /proc/testStatus() var/inp = input(usr,"Which status?","Test status","airrit") as text SPAWN_DBG(0) for(var/datum/statusEffect/status in usr.statusEffects) usr.delStatus(status) usr.changeStatus(inp, 15 MINUTES) return /obj/screen/statusEffect name = "Status effect" desc = "" icon = 'icons/ui/statussystem.dmi' icon_state = "statusbg" layer = HUD_LAYER+1 plane = PLANE_HUD var/datum/statusEffect/ownerStatus = null var/image/overImg = null New() overImg = image('icons/ui/statussystem.dmi') src.maptext_y = -12 maptext_width = 16 maptext_height = 16 //filters += filter(type="outline", size=1, color="#000000") filters += filter(type="outline", size=0.7,color=rgb(0,0,0)) filters += filter(type="drop_shadow", size=1.5, color=rgb(0,0,0)) ..() proc/init(var/mob/living/C, var/datum/statusEffect/S) if(!S) throw "STATUS EFFECT UI INITIALIZED WITHOUT INSTANCE" ownerStatus = S src.name = S.name overImg.icon_state = S.icon_state pooled() src.name = "null" ownerStatus = 0 ..() clicked(list/params) if (ownerStatus) ownerStatus.clicked(params) MouseEntered(location, control, params) if (usr.client.tooltipHolder && ownerStatus) usr.client.tooltipHolder.showHover(src, list( "params" = params, "title" = ownerStatus.name, "content" = ownerStatus.getTooltip() + "
[ownerStatus.duration != null ? "[round(ownerStatus.duration/10)] sec.":""]", "theme" = "stamina" )) MouseExited() if (usr.client.tooltipHolder) usr.client.tooltipHolder.hideHover() proc/update_value() if(!ownerStatus) return src.overlays.Cut() overImg.icon_state = ownerStatus.icon_state src.overlays += overImg if (ownerStatus.duration <= 50 && !isnull(ownerStatus.duration)) src.alpha = 175 else src.alpha = 255 var/str = "??" if(isnull(ownerStatus.duration)) //Null means infinite. str = "*" else if(ownerStatus.duration >= 1 HOURS) //Hours if(ownerStatus.duration > 10 HOURS) //10 hours fuck this str = "+H" else str = "[round(ownerStatus.duration / (1 HOURS))]H" else if(ownerStatus.duration >= 1 MINUTES) //1+ min if(ownerStatus.duration >= 10 MINUTES) //10+ min fuck that str = "+M" else str = "[round(ownerStatus.duration / (1 MINUTES))]M" else if(ownerStatus.duration < 10 SECONDS) str = "0[round(ownerStatus.duration / (1 SECOND))]" else str = "[round(ownerStatus.duration / (1 SECOND))]" maptext = "[str]" return /atom var/list/statusEffects = null //List of status effects. proc/updateStatusUi() //Stub. Override for objects that need to update their ui with status information. return proc/changeStatus(statusId, duration, optional) var/datum/statusEffect/globalInstance = null for(var/datum/statusEffect/status in globalStatusPrototypes) if(status.id == statusId) globalInstance = status break if(!globalInstance) throw EXCEPTION("Unknown status type passed: [statusId]") return null if(!globalInstance.preCheck(src)) return null if(hasStatus(statusId)) var/datum/statusEffect/S = hasStatus(statusId) setStatus(statusId, (isnull(S.maxDuration) ? (S.duration + duration):(min(S.duration + duration, S.maxDuration))), optional) return S else if(duration > 0) return setStatus(statusId, (isnull(globalInstance.maxDuration) ? (duration):(min(duration, globalInstance.maxDuration))), optional) return null proc/setStatus(statusId, duration, optional) if(statusEffects == null) statusEffects = list() var/datum/statusEffect/globalInstance = null for(var/datum/statusEffect/status in globalStatusPrototypes) if(status.id == statusId) globalInstance = status break if(globalInstance != null) if(!globalInstance.preCheck(src)) return null var/groupFull = 0 var/groupCount = 0 if(globalInstance.exclusiveGroup != "" && statusGroupLimits.Find(globalInstance.exclusiveGroup)) for(var/datum/statusEffect/status in statusEffects) if(status.exclusiveGroup == globalInstance.exclusiveGroup && status.id != statusId) groupCount++ if(groupCount >= statusGroupLimits[globalInstance.exclusiveGroup]) groupFull = 1 if(globalInstance.unique) //unique, easy. if(hasStatus(statusId)) //Update it if(duration > 0 || isnull(duration)) var/datum/statusEffect/localInstance = hasStatus(statusId) if (duration) duration = localInstance.duration + localInstance.modify_change(duration - localInstance.duration) localInstance.duration = (isnull(localInstance.maxDuration) ? (duration):(min(duration, localInstance.maxDuration))) localInstance.onChange(optional) src.updateStatusUi() return localInstance else delStatus(statusId) else if((duration > 0 || isnull(duration)) && !groupFull) //Add it var/datum/statusEffect/localInstance = new globalInstance.type() localInstance.owner = src if (duration) duration = localInstance.duration + localInstance.modify_change(duration - localInstance.duration) localInstance.duration = (isnull(localInstance.maxDuration) ? (duration):(min(duration, localInstance.maxDuration))) localInstance.archivedOwnerInfo = "OwnerName:[src.name] - OwnerType:[src.type] - ContLen:[src.contents.len] - StatusLen:[src.statusEffects.len]" localInstance.onAdd(optional) if(!statusEffects.Find(localInstance)) statusEffects.Add(localInstance) if(!globalStatusInstances.Find(localInstance)) globalStatusInstances.Add(localInstance) src.updateStatusUi() return localInstance else return null else //Not unique, no changing it. Only adding supported. //Add it if((duration > 0 || isnull(duration)) && !groupFull) var/datum/statusEffect/localInstance = new globalInstance.type() localInstance.owner = src if (duration) duration = localInstance.duration + localInstance.modify_change(duration - localInstance.duration) localInstance.duration = (isnull(localInstance.maxDuration) ? (duration):(min(duration, localInstance.maxDuration))) localInstance.archivedOwnerInfo = "OwnerName:[src.name] - OwnerType:[src.type] - ContLen:[src.contents.len] - StatusLen:[src.statusEffects.len]" localInstance.onAdd(optional) if(!statusEffects.Find(localInstance)) statusEffects.Add(localInstance) if(!globalStatusInstances.Find(localInstance)) globalStatusInstances.Add(localInstance) src.updateStatusUi() return localInstance else return null else throw EXCEPTION("Unknown status type passed: [statusId]") return null proc/getStatusDuration(statusId) .= null if(statusEffects) var/datum/statusEffect/status = 0 for(var/S in statusEffects) //dont typecheck as we loop through StatusEffects - Assume everything inside must be a statuseffect status = S if(status.id == statusId) .= status.duration break proc/hasStatus(statusId, optionalArgs = null) .= null if(statusEffects) var/datum/statusEffect/status = 0 for(var/S in statusEffects) //dont typecheck as we loop through StatusEffects - Assume everything inside must be a statuseffect status = S if(status.id == statusId && ((optionalArgs && status.onCheck(optionalArgs)) || (!optionalArgs))) .= status break proc/delStatus(var/status) if(statusEffects == null) return null if(istext(status)) //ID was passed in. for(var/datum/statusEffect/statcurr in statusEffects) if(statcurr.id == status) if(globalStatusInstances.Find(statcurr)) globalStatusInstances.Remove(statcurr) statusEffects.Remove(statcurr) statcurr.onRemove() else if(istype(status, /datum/statusEffect)) //Instance was passed in. if(statusEffects.Find(status)) if(globalStatusInstances.Find(status)) globalStatusInstances.Remove(status) statusEffects.Remove(status) var/datum/statusEffect/S = status S.onRemove() src.updateStatusUi() return null /datum/statusEffect var/id = "" var/name = "" var/icon_state = "" var/desc = "" //Tooltip desc var/duration = 0 //In deciseconds (tenths of a second, same as ticks just sane). A duration of NULL is infinite. (This is distinct from 0) var/atom/owner = null //Owner of the status effect var/archivedOwnerInfo = "" var/unique = 1 //If true, this status effect can only have one instance on any given object. var/visible = 1 //Is this visible in the status effect bar? var/exclusiveGroup = "" //optional name of a group of buffs. players can only have a certain number of buffs of a given group - any new applications fail. useful for food buffs etc. var/maxDuration = null //If non-null, duration of the effect will be clamped to be max. this amount. var/move_triggered = 0 //has an on-move effect proc/preCheck(var/atom/A) //Used to run a custom check before adding status to an object. For when you want something to be flat out immune or something. ret = 1 allow, 0 = do not allow return 1 proc/modify_change(var/change) .= change proc/onAdd(var/optional=null) //Called when the status is added to an object. owner is already set at this point. Has the optional arg from setStatus passed in. return proc/onRemove() //Called when the status is removed from the object. owner is still set at this point. return proc/onUpdate(var/timedPassed) //Called every tick by the status controller. Argument is the actual time since the last update call. return proc/onChange(var/optional=null) //Called when the status is changed using setStatus. Called after duration is updated etc. Has the optional arg from setStatus passed in. return proc/onCheck(var/optional=null) //Called by hasStatus. Used to handle additional checks with the optional arg in that proc. return 1 proc/getTooltip() //Used to generate tooltip. Can be changed to have dynamic tooltips. return desc proc/getExamine() //Information that should show up when an object has this effect and is examined. return null proc/clicked(list/params) .= 0 proc/move_trigger(var/mob/user, var/ev) .=0 disposing() if (owner) owner.statusEffects -= src ..() maxhealth id = "maxhealth" name = "" desc = "" icon_state = "" unique = 1 var/change = 1 //Effective change to maxHealth onAdd(var/optional=null) //Optional is change. if(ismob(owner) && optional != 0) var/mob/M = owner change = optional M.max_health += change return onRemove() if(ismob(owner)) var/mob/M = owner M.max_health -= change return onUpdate(var/timedPassed) icon_state = "[change > 0 ? "heart+":"heart-"]" name = "Max. health [change > 0 ? "increased":"reduced"]" return //causes max health to stack up to thousands on repeat calls //THEN DONT REPEATEDLY CALL IT. Don't just comment shit out. The value can't be changed without this. I've changed it to make the change value absolute. onChange(var/optional=null) if(ismob(owner) && optional != 0) var/mob/M = owner M.max_health -= change change = optional M.max_health += change return getTooltip() return "Your max. health has been [change > 0 ? "increased":"reduced"] by [abs(change)]." //Technically the base class can handle either but we need to separate these. increased id = "maxhealth+" onUpdate(var/timedPassed) if(change < 0) //Someone fucked this up; remove effect. duration = 1 return ..(timedPassed) decreased id = "maxhealth-" onUpdate(var/timedPassed) if(change > 0) //Someone fucked this up; remove effect. duration = 1 return ..(timedPassed) simplehot //Simple heal over time. var/tickCount = 0 var/tickSpacing = 1 SECOND //Time between ticks. var/heal_brute = 0 var/heal_tox = 0 var/heal_burn = 0 icon_state = "+" onUpdate(var/timedPassed) tickCount += timedPassed var/times = (tickCount / tickSpacing) if(times >= 1 && ismob(owner)) tickCount -= (round(times) * tickSpacing) for(var/i = 0, i < times, i++) var/mob/M = owner M.HealDamage("All", heal_brute, heal_burn, heal_tox) return simpledot //Simple damage over time. var/tickCount = 0 var/tickSpacing = 1 SECOND //Time between ticks. var/damage_brute = 0 var/damage_tox = 0 var/damage_burn = 0 var/damage_type = DAMAGE_STAB icon_state = "-" onUpdate(var/timedPassed) tickCount += timedPassed var/times = (tickCount / tickSpacing) if(times >= 1 && ismob(owner)) tickCount -= (round(times) * tickSpacing) for(var/i = 0, i < times, i++) var/mob/M = owner M.TakeDamage("All", damage_brute, damage_burn, damage_tox, damage_type) return simpledot/radiation id = "radiation" name = "Irradiated" desc = "" icon_state = "radiation1" unique = 1 tickSpacing = 3 SECONDS damage_tox = 1 damage_type = DAMAGE_BURN var/howMuch = "" var/stage = 0 var/counter = 0 var/stageTime = 10 SECONDS getTooltip() return "You are [howMuch]irradiated.
Taking [damage_tox] toxin damage every [tickSpacing/10] sec.
Damage reduced by radiation resistance on gear." preCheck(var/atom/A) if(issilicon(A)) return 0 return 1 onAdd(var/optional=null) if(!isnull(optional) && optional >= stage) stage = optional else stage = 5 icon_state = "radiation[stage]" return onChange(var/optional=null) if(!isnull(optional) && optional >= stage) stage = optional else stage = 5 icon_state = "radiation[stage]" return onUpdate(var/timedPassed) counter += timedPassed if(counter >= stageTime) counter -= stageTime stage = max(stage-1, 1) var/prot = 1 if(istype(owner, /mob/living/carbon/human)) var/mob/living/carbon/human/H = owner prot = (1 - (H.get_rad_protection() / 100)) switch(stage) if(1) damage_tox = (1 * prot) howMuch = "" if(2) damage_tox = (2 * prot) howMuch = "significantly " var/chance = (2 * prot) if(prob(chance) && ismob(owner)) var/mob/M = owner if (M.bioHolder && !M.bioHolder.HasEffect("revenant")) M.changeStatus("weakened", 3 SECONDS) boutput(M, "You feel weak.") M.emote("collapse") if(3) damage_tox = (3 * prot) howMuch = "very much " if (ismob(owner)) var/mob/M = owner var/mutChance = (1 * prot) if (M.traitHolder && M.traitHolder.hasTrait("stablegenes")) mutChance = 0 if (mutChance < 1) mutChance = 0 if (prob(mutChance) && (M.bioHolder && !M.bioHolder.HasEffect("revenant"))) boutput(M, "You mutate!") M:bioHolder:RandomEffect("either") if(4) damage_tox = (4 * prot) howMuch = "extremely " if (ismob(owner)) var/mob/M = owner var/mutChance = (2 * prot) if (M.traitHolder && M.traitHolder.hasTrait("stablegenes")) mutChance = (1 * prot) if (mutChance < 1) mutChance = 0 if (prob(mutChance) && (M.bioHolder && !M.bioHolder.HasEffect("revenant"))) boutput(M, "You mutate!") M:bioHolder:RandomEffect("either") if(5) damage_tox = (4.5 * prot) howMuch = "horribly " if (ismob(owner)) var/mob/M = owner var/mutChance = (3 * prot) if (M.traitHolder && M.traitHolder.hasTrait("stablegenes")) mutChance = (2 * prot) if (mutChance < 1) mutChance = 0 if (prob(mutChance) && (M.bioHolder && !M.bioHolder.HasEffect("revenant"))) boutput(M, "You mutate!") M:bioHolder:RandomEffect("either") icon_state = "radiation[stage]" return ..(timedPassed) simpledot/n_radiation id = "neutron_radiation" name = "Neutron Irradiated" desc = "" icon_state = "radiation1" unique = 1 tickSpacing = 1.5 SECONDS damage_tox = 2 damage_brute = 2 damage_type = DAMAGE_STAB | DAMAGE_BURN var/howMuch = "" var/stage = 0 var/counter = 0 var/stageTime = 10 SECONDS getTooltip() return "You are [howMuch]irradiated by neutrons.
Taking [damage_tox] toxin damage every [tickSpacing/10] sec and [damage_brute] brute damage every [tickSpacing/10] sec." preCheck(var/atom/A) if(issilicon(A)) return 0 return 1 onAdd(var/optional=null) if(!isnull(optional) && optional >= stage) stage = optional else stage = 5 icon_state = "radiation[stage]" return onChange(var/optional=null) if(!isnull(optional) && optional >= stage) stage = optional else stage = 5 icon_state = "radiation[stage]" return onUpdate(var/timedPassed) counter += timedPassed if(counter >= stageTime) counter -= stageTime stage = max(stage-1, 1) var/prot = 1 if(istype(owner, /mob/living/carbon/human)) prot = (1 - (0 / 100)) switch(stage) if(1) damage_tox = (1 * prot) damage_brute = (1 * prot) howMuch = "" if(2) damage_tox = (2 * prot) damage_brute = (2 * prot) howMuch = "significantly " if(3) damage_tox = (3 * prot) damage_brute = (3 * prot) howMuch = "very much " if(4) damage_tox = (4 * prot) damage_brute = (4 * prot) howMuch = "extremely " if(5) damage_tox = (5 * prot) damage_brute = (5 * prot) howMuch = "horribly " icon_state = "radiation[stage]" return ..(timedPassed) simpledot/burning id = "burning" name = "Burning" desc = "" icon_state = "fire1" unique = 1 maxDuration = 100 SECONDS damage_burn = 1 damage_type = DAMAGE_BURN var/howMuch = "" var/stage = -1 var/counter = 1 var/mob/living/carbon/human/H var/image/onfire = null getTooltip() return "You are [howMuch]on fire.
Taking [damage_burn] burn damage every [tickSpacing/10] sec.
Damage reduced by heat resistance on gear. Click this statuseffect to resist." clicked(list/params) if (H) H.resist() preCheck(var/atom/A) if(issilicon(A)) return 0 return 1 onAdd(var/optional = BURNING_LV1) if(!isnull(optional) && optional >= stage) counter = optional switchStage(getStage()) if(istype(owner, /mob/living)) var/mob/living/L = owner L.update_burning_icon(0, src) // pass in src because technically our owner does not have us as a status effect yet (this happens immediately after onAdd()) if (ishuman(owner)) H = owner else onfire = image('icons/effects/effects.dmi', null, EFFECTS_LAYER_1) onfire.icon_state = "onfire[getStage()]" onfire.filters += filter(type="alpha", icon=icon(owner.icon, owner.icon_state)) owner.UpdateOverlays(onfire, "onfire") return onChange(var/optional = BURNING_LV1) if(!isnull(optional) && optional >= stage) counter = optional switchStage(getStage()) return onRemove() if(!owner) return //owner got in our del queue if(istype(owner, /mob/living)) var/mob/living/L = owner L.update_burning_icon(1) else owner.UpdateOverlays(null, "onfire") return proc/getStage() if(counter < BURNING_LV2) return 1 else if (counter >= BURNING_LV2 && counter < BURNING_LV3) return 2 else if (counter >= BURNING_LV3) return 3 return 1 proc/switchStage(var/toStage) if(stage != toStage) stage = toStage switch(stage) if(1) icon_state = "fire1" if(2) icon_state = "fire2" if(3) icon_state = "fire3" if(istype(owner, /mob/living)) var/mob/living/L = owner L.update_burning_icon() else onfire.icon_state = "onfire[getStage()]" owner.UpdateOverlays(onfire, "onfire") return move_trigger(var/mob/user, var/ev) if (ishuman(user)) var/mob/living/carbon/human/H = user if (ev == "run" || ev == "walk") H.resist() .=1 .=0 onUpdate(var/timedPassed) counter += timedPassed switchStage(getStage()) var/prot = 1 if(istype(owner, /mob/living/carbon/human)) var/mob/living/carbon/human/H = owner prot = (1 - (H.get_heat_protection() / 100)) if(ismob(owner) && owner:is_heat_resistant()) prot = 0 switch(stage) if(1) damage_burn = 0.9 * prot howMuch = "" if(2) damage_burn = 2 * prot howMuch = "very much " if(3) damage_burn = 3.5 * prot howMuch = "extremely " return ..(timedPassed) stuns modify_change(var/change) . = change if (owner && ismob(owner)) var/mob/M = owner var/percent_protection = M.get_stun_resist_mod() percent_protection = 1 - (percent_protection/100) //scale from 0 to 1 . *= percent_protection onRemove() ..() if(!owner) return if (!owner.hasStatus("stunned") && !owner.hasStatus("weakened") && !owner.hasStatus("paralysis") && !owner.hasStatus("pinned")) //consider later : a way to group effects to check a bunch in one proc call and save sonme cpu if (isliving(owner)) var/mob/living/L = owner L.force_laydown_standup() stunned id = "stunned" name = "Stunned" desc = "You are stunned.
Unable to take any actions." icon_state = "stunned" unique = 1 maxDuration = 30 SECONDS weakened id = "weakened" name = "Knocked-down" desc = "You are knocked-down.
Unable to take any actions, prone." icon_state = "weakened" unique = 1 maxDuration = 30 SECONDS pinned id = "pinned" name = "Pinned" desc = "You are pinned. Click this status effect to resist.
Unable to take any actions, prone." icon_state = "pin" unique = 1 maxDuration = null clicked(list/params) if (ishuman(owner)) var/mob/living/carbon/human/H = owner H.resist() onUpdate() if (ismob(owner)) var/mob/M = owner var/found = 0 if (M.grabbed_by) for (var/obj/item/grab/G in M.grabbed_by) if (G.state == GRAB_PIN) found = 1 if (!found) owner.delStatus("pinned") .=..() paralysis id = "paralysis" name = "Unconscious" desc = "You are unconcious.
Unable to take any actions, blinded." icon_state = "paralysis" unique = 1 maxDuration = 30 SECONDS dormant id = "dormant" name = "Dormant" desc = "You are dormant.
Unable to take any actions, until you power yourself." icon_state = "paralysis" unique = 1 duration = null staggered id = "staggered" name = "Staggered" desc = "You have been staggered by a melee attack.
Slowed slightly, unable to sprint." icon_state = "staggered" unique = 1 maxDuration = 5 SECONDS slowed id = "slowed" name = "Slowed" desc = "You are slowed.
Movement speed is reduced." icon_state = "slowed" unique = 1 var/howMuch = 10 onAdd(var/optional=null) if(optional) howMuch = optional return ..(optional) onChange(var/optional=null) if(optional) howMuch = optional return ..(optional) disorient id = "disorient" name = "Disoriented" desc = "You are disoriented.
Movement speed is reduced. You may stumble or drop items." icon_state = "disorient" unique = 1 maxDuration = 15 SECONDS var/counter = 0 var/sound = "sound/effects/electric_shock_short.ogg" var/count = 7 onUpdate(var/timedPassed) counter += timedPassed if (counter >= count && owner && !owner.hasStatus("weakened") && !owner.hasStatus("paralysis")) counter -= count playsound(get_turf(owner), sound, 17, 1, 0.4, 1.6) violent_twitch(owner) .=..(timedPassed) drunk id = "drunk" name = "Drunk" desc = "You are drunk." icon_state = "drunk" unique = 1 duration = null maxDuration = null var/how_drunk = 0 onAdd(var/optional=null) changeState() return ..(optional) onUpdate(var/timedPassed) changeState() return ..(timedPassed) proc/changeState() if(owner?.reagents) var/amt = owner.reagents.get_reagent_amount("ethanol") if (amt >= 110) how_drunk = 3 else if (amt > 50) how_drunk = 2 else if (amt <= 50) how_drunk = 1 else if (amt <= 0) how_drunk = 0 return icon_state = "drunk[how_drunk]" getTooltip() return "You are [how_drunk == 2 ? "very": ""][how_drunk == 3 ? ", very" : ""] drunk." blinded id = "blinded" name = "Blinded" desc = "You are blinded.
Visibility drastically reduced." icon_state = "blinded" unique = 1 hastened id = "hastened" name = "Hastened" desc = "You are hastened.
Movement speed is increased." icon_state = "hastened" unique = 1 cloaked id = "cloaked" name = "Cloaked" desc = "You are cloaked.
You are less visible." icon_state = "cloaked" unique = 1 var/wait = 0 onAdd(var/optional=null) animate(owner, alpha=30,flags=ANIMATION_PARALLEL, time=30) return onRemove() animate(owner,alpha=255,flags=ANIMATION_PARALLEL, time=30) return onUpdate(var/timedPassed) wait += timedPassed if(owner.alpha > 33 && wait > 40) animate(owner, alpha=30,flags=ANIMATION_PARALLEL, time=30) wait = 0 return fitness_staminaregen id = "fitness_stam_regen" name = "Pumped" desc = "" icon_state = "muscle" exclusiveGroup = "Food" maxDuration = 500 SECONDS unique = 1 var/change = 2 getTooltip() return "Your stamina regen is increased by [change]." onAdd(var/optional=null) if(hascall(owner, "add_stam_mod_regen")) owner:add_stam_mod_regen("fitness_regen", change) return onRemove() if(hascall(owner, "remove_stam_mod_regen")) owner:remove_stam_mod_regen("fitness_regen") return fitness_staminamax id = "fitness_stam_max" name = "Buff" desc = "" icon_state = "muscle" exclusiveGroup = "Food" maxDuration = 500 SECONDS unique = 1 var/change = 10 getTooltip() return "Your stamina max is increased by [change]." onAdd(var/optional=null) if(hascall(owner, "add_stam_mod_max")) owner:add_stam_mod_max("fitness_max", change) return onRemove() if(hascall(owner, "remove_stam_mod_max")) owner:remove_stam_mod_max("fitness_max") return handcuffed id = "handcuffed" name = "Handcuffed" desc = "You are handcuffed.
You cannot use your hands. Click this statuseffect to resist." icon_state = "handcuffed" unique = 1 duration = null maxDuration = null var/mob/living/carbon/human/H onAdd(var/optional=null) if (ishuman(owner)) H = owner else owner.delStatus("handcuffed") clicked(list/params) H.resist() onUpdate() if (!H.handcuffed) owner.delStatus("handcuffed") .=..() buckled id = "buckled" name = "Buckled" desc = "You are buckled.
You cannot walk. Click this statuseffect to unbuckle." icon_state = "buckled" unique = 1 duration = null maxDuration = null var/mob/living/carbon/human/H onAdd(var/optional=null) if (ishuman(owner)) H = owner else owner.delStatus("buckled") clicked(list/params) H.resist() onUpdate() if (H && !H.buckled) owner.delStatus("buckled") .=..() ganger id = "ganger" name = "Gang Member" desc = "You are a gang member wearing your uniform. You get health and stamina bonuses." icon_state = "ganger" unique = 1 duration = null maxDuration = null var/const/max_health = 30 var/const/max_stam = 60 var/const/regen_stam = 5 var/mob/living/carbon/human/H onAdd(var/optional=null) if (ishuman(owner)) H = owner else owner.delStatus("ganger") H.max_health += max_health H.add_stam_mod_max("ganger_max", max_stam) H.add_stam_mod_regen("ganger_regen", regen_stam) onRemove() H.max_health -= max_health H.remove_stam_mod_max("ganger_max") H.remove_stam_mod_regen("ganger_regen") getTooltip() return "Your max health, max stamina, and stamina regen have been increased because of the pride you feel while wearing your uniform." janktank id = "janktank" name = "janktank" desc = "You're \"high\" on some sorta stimulant" icon_state = "janktank" duration = 9 MINUTES maxDuration = 18 MINUTES unique = 1 var/change = 1 //Effective change to maxHealth onAdd(var/optional=null) //Optional is change. if(ismob(owner)) //var/mob/M = owner owner.delStatus("janktank_withdrawl") var/mob/M = owner M.add_stun_resist_mod("janktank", 40) else owner.delStatus("janktank") return onRemove() if(ismob(owner)) //var/mob/M = owner owner.setStatus("janktank_withdrawl", 25 MINUTES) var/mob/M = owner M.remove_stun_resist_mod("janktank") return onUpdate(var/timedPassed) var/mob/living/carbon/human/H if(ishuman(owner)) H = owner H.take_oxygen_deprivation(-1) H.HealDamage("All", 2, 0, 0) if (prob(60)) H.HealDamage("All", 1, 1, 1) if (prob(10)) H.make_jittery(2) if (H.bleeding) repair_bleeding_damage(H, 10, 1) if (H.misstep_chance) H.change_misstep_chance(-5) H.updatehealth() return gang_drug_withdrawl id = "janktank_withdrawl" name = "janktank withdrawl" desc = "You're going through withrawl of Janktank" icon_state = "janktank-w" duration = 9 MINUTES maxDuration = 18 MINUTES unique = 1 var/change = 1 //Effective change to maxHealth onAdd(var/optional=null) //Optional is change. if(ismob(owner) && optional != 0) //var/mob/M = owner change = optional return onUpdate(var/timedPassed) var/mob/living/carbon/human/M if(ishuman(owner)) M = owner if (prob(15)) M.TakeDamage("All", 0, 0, 1) if (prob(10)) owner.changeStatus("stunned", 2 SECONDS) if (prob(20)) violent_twitch(owner) M.make_jittery(rand(6,9)) M.updatehealth() return mutiny id = "mutiny" name = "Mutiny" desc = "You can sense the aura of revolutionary activity! Your bossy attitude grants you health and stamina bonuses." icon_state = "mutiny" unique = 1 maxDuration = 1 MINUTES var/const/max_health = 60 var/const/max_stam = 30 var/const/regen_stam = 5 var/mob/living/carbon/human/H onAdd(var/optional=null) if (ishuman(owner)) H = owner else owner.delStatus("mutiny") H.max_health += max_health H.add_stam_mod_max("mutiny_max", max_stam) H.add_stam_mod_regen("mutiny_regen", regen_stam) onRemove() H.max_health -= max_health H.remove_stam_mod_max("mutiny_max") H.remove_stam_mod_regen("mutiny_regen") getTooltip() return "Your max health, max stamina, and stamina regen have been increased because of your bossy attitude." revspirit id = "revspirit" name = "Revolutionary Spirit" desc = "Your saw your revolution leaders holding some great signs. The cameraderie motivating you to fight harder!" icon_state = "revspirit" unique = 1 maxDuration = 20 SECONDS var/const/max_health = 20 var/const/max_stam = 15 var/const/regen_stam = 3 var/mob/living/carbon/human/H onAdd(var/optional=null) if (ishuman(owner)) H = owner else owner.delStatus("revspirit") H.max_health += max_health H.add_stam_mod_max("revspirit_max", max_stam) H.add_stam_mod_regen("revspirit_regen", regen_stam) onRemove() H.max_health -= max_health H.remove_stam_mod_max("revspirit_max") H.remove_stam_mod_regen("revspirit_regen") getTooltip() return "Your max stamina and stamina regen have been increased slightly." /datum/statusEffect/bloodcurse id = "bloodcurse" name = "Cursed" desc = "You have been cursed." icon_state = "bleeding" unique = 1 duration = null maxDuration = null var/mob/living/carbon/human/H var/units = 5 getTooltip() return "You are losing blood at rate of [units] per second ." preCheck(var/atom/A) if(issilicon(A)) return 0 return 1 onAdd(var/optional=null) if (ishuman(owner)) H = owner else owner.delStatus("bloodcurse") onUpdate() if (H.blood_volume > 400 && H.blood_volume > 0) H.blood_volume -= units if (prob(5)) var/damage = rand(1,5) var/bleed = rand(3,5) H.visible_message("[H] [damage > 3 ? "vomits" : "coughs up"] blood!", "You [damage > 3 ? "vomit" : "cough up"] blood!") playsound(H.loc, "sound/impact_sounds/Slimy_Splat_1.ogg", 50, 1) H.TakeDamage(zone="All", brute=damage) bleed(H, damage, bleed)