Sprinting, Stamina and Temporary Modifiers (#1030)

Introduces:
- Temporary modifiers process and datums for that
- A new stamina and sprinting mechanic. That is in need of further development! Weee!
This commit is contained in:
NanakoAC
2016-10-26 16:22:39 +01:00
committed by skull132
parent a3f051693d
commit c4b36a5490
32 changed files with 1097 additions and 80 deletions
+3
View File
@@ -111,6 +111,7 @@
#include "code\controllers\Processes\inactivity.dm"
#include "code\controllers\Processes\machinery.dm"
#include "code\controllers\Processes\mob.dm"
#include "code\controllers\Processes\modifier.dm"
#include "code\controllers\Processes\nanoui.dm"
#include "code\controllers\Processes\obj.dm"
#include "code\controllers\Processes\Shuttle.dm"
@@ -525,6 +526,8 @@
#include "code\game\mecha\working\hoverpod.dm"
#include "code\game\mecha\working\ripley.dm"
#include "code\game\mecha\working\working.dm"
#include "code\game\modifiers\modifiers.dm"
#include "code\game\modifiers\modifiers_chem.dm"
#include "code\game\objects\buckling.dm"
#include "code\game\objects\empulse.dm"
#include "code\game\objects\explosion.dm"
+13
View File
@@ -853,3 +853,16 @@ proc/sort_atoms_by_layer(var/list/atoms)
result.Swap(i, gap + i)
swapped = 1
return result
proc/percentage_to_colour(var/P)
//Takes a value between 0-1
//Returns a colour - pure green if 1, pure red if 0
//Inbetween values will gradiant through green, yellow, orange, red
var/green = min(1, P*2)*255
var/red = 255 - (min(1, (P-0.5)*2)*255)
//var/green = (max(0, P-0.5)*2)*255
//var/red = 255 - (min(1, P*2)*255)
return rgb(red,green,0)
+20
View File
@@ -1370,3 +1370,23 @@ var/mob/dview/dview_mob = new
// call to generate a stack trace and print to runtime logs
/proc/crash_with(msg)
CRASH(msg)
/atom/proc/find_up_hierarchy(var/atom/target)
//This function will recurse up the hierarchy containing src, in search of the target
//It will stop when it reaches an area, as areas have no loc
var/x = 0//As a safety, we'll crawl up a maximum of ten layers
var/atom/a = src
while (x < 10)
x++
if (isnull(a))
return 0
if (a == target)//we found it!
return 1
if (istype(a, /area))
return 0//Can't recurse any higher than this.
a = a.loc
return 0//If we get here, we must be buried many layers deep in nested containers. Shouldn't happen
+32 -2
View File
@@ -233,8 +233,17 @@
L.resist()
if("mov_intent")
var/list/modifiers = params2list(params)
//This is here instead of outside the switch to save adding overhead. its not used for any other UI icons right now
//If its needed in future for other UI icons, then move it up to above the switch
if(iscarbon(usr))
var/mob/living/carbon/C = usr
if (modifiers["alt"])
C.set_walk_speed()
return
if(C.legcuffed)
C << "<span class='notice'>You are legcuffed! You cannot run until you get [C.legcuffed] removed!</span>"
C.m_intent = "walk" //Just incase
@@ -243,10 +252,9 @@
switch(usr.m_intent)
if("run")
usr.m_intent = "walk"
usr.hud_used.move_intent.icon_state = "walking"
if("walk")
usr.m_intent = "run"
usr.hud_used.move_intent.icon_state = "running"
update_move_icon(usr)
if("m_intent")
if(!usr.m_int)
switch(usr.m_intent)
@@ -589,3 +597,25 @@
usr.update_inv_r_hand(0)
usr.next_move = world.time+6
return 1
//This updates the run/walk button on the hud
/obj/screen/proc/update_move_icon(var/mob/living/user)
switch(name)
if("mov_intent")
overlays.Cut()
switch(user.m_intent)
if("run")//When in run mode, the button will have a flashing coloured overlay which gives a visual indicator of stamina
icon_state = "running"
if (user.max_stamina != -1)//If max stamina is -1, this species doesnt use stamina. no overlay for them
var/image/holder = image('icons/mob/screen1.dmi', src, "run_overlay")
var/staminaportion = user.stamina / user.max_stamina
holder.color = percentage_to_colour(staminaportion)
holder.blend_mode = BLEND_MULTIPLY
overlays += holder
if("walk")
icon_state = "walking"
+22
View File
@@ -0,0 +1,22 @@
/datum/controller/process/modifier/setup()
name = "modifiers"
schedule_interval = 10
start_delay = 8
/datum/controller/process/modifier/started()
..()
if(!processing_modifiers)
processing_modifiers = list()
/datum/controller/process/modifier/doWork()
for(last_object in processing_modifiers)
var/datum/modifier/O = last_object
if(isnull(O.gcDestroyed))
O.process()
else
catchBadType(O)
processing_objects -= O
/datum/controller/process/modifier/statProcess()
..()
stat(null, "[processing_modifiers.len] modifiers")
+1 -1
View File
@@ -16,7 +16,7 @@
var/germ_level = GERM_LEVEL_AMBIENT // The higher the germ level, the more germ on the atom.
var/simulated = 1 //filter for actions - used by lighting overlays
var/fluorescent // Shows up under a UV light.
var/list/modifiers = list()
///Chemistry.
var/datum/reagents/reagents = null
+452
View File
@@ -0,0 +1,452 @@
/*
//Temporary modifiers system, by Nanako
//This system is designed to allow making non-permanant, reversible changes to variables of any atom,
//Though the system will be primarily used for altering properties of mobs, it can work on anything.
//Intended uses are to allow equipment and items that modify a mob's various stats and attributes
//As well as to replace the badly designed chem effects system
This system works through a few main procs which should be overridden:
All overridden procs should contain a call to parent at the start, before any other code
Activate: This applies the effects. its here that you change any variables.
The author is also responsible here for storing any information necessary to later revert these changes
Deactivate: This proc removes the effects. The author is responsible for writing it to reverse the changes cleanly
If using a strength var or any other kind of dynamic determinor of effects
It is very important NOT to factor that in when deactivating, because it may be changed while active
Instead, factor it in while activating and save the delta of the changed values.
that is, how much you added/subtracted
Apply that saved value in reverse when deactivating.
Both activate and deactivate are stateful. Activate will not run if active is true.
Deactivate will not run if active is false
Process: Called once every second while the effect is active. Usually this will only see if its time
to recheck validity, but it can be overridden to add extra per-tick functionality.
When created, a status effect will take the following parameters in new
Mandatory:
1. Affected atom
2. Modifier type
3. Source atom (not mandatory if type is custom)
Optional:
4. Source data
5. Strength
6. Duration
7. Check interval
//The affected atom is mandatory, without something to affect the modifier cannot exist
//Modifier type is one of a selection of constants which determines the automated validity checking.
It does not enforce anything about the changes or other functionality. A valid option is mandatory
//Source object is the thing that this modifier is based on, or anchored to.
//It is used as a point of reference in validity checks. Usually mandatory but some types do not require it
//Source data provides additional information for validity, such as a maximum range from the source.
//Only required for certain types
//Strength can be passed in by the caller and used insetting or removing the variable changes.
//It is never required for anything and not incorporated in base behaviour
//Duration can be used for any type except custom. The modifier will cease to be valid
//this long after it is created
//Duration is decremented every proc until it falls below zero.
//This is used so that duration can be refreshed or increased before the modifier expires to prolong it
//Check interval is a time, in deciseconds, between validity checks. a >0 value is required here,
//the default is 300 (every 30 seconds),
//Check interval is used to generate a world time at which the next check will run
Please note that automated validity checking is primarily as a safety, to ensure things aren't left
when they shouldn't be. If you desire something removed in a timely manner, it's recommended to manually
call the effect's end proc from your code when you're done with it. For example, if a piece of equipment
applying a modifier is taken off.
Setting the check interval very low just to cause the effect to be removed quickly is bad practise
it should be avoided in favour of manual removal where possible
*/
//Modifier types
//These are needed globally and cannot be undefined
#define MODIFIER_EQUIPMENT 1
//The status effect remains valid as long as it is worn upon the affected mob.
//Worn here means it must be held in a valid equip slot, which does not include pockets, storage, or held in hands.
//The affected atom must be a mob
#define MODIFIER_ITEM 2
//The modifier remains valid as long as the item is in the target's contents,
//no matter how many layers deep, if it can be found by recursing up, it is valid
//This is essentially a more permissable version of equipment, and works when held, in backpacks, pockets, etc
//It can also be used on non-mob targets
#define MODIFIER_REAGENT 3
//The status effect remains valid as long as the dose of this chemical in a mob's reagents is above
//a specified dose value (specified in source data).
//The default of zero will keep it valid if the chemical is in them at all
//This checks for the reagent by type, in any of a mob's reagent holders - touching, blood, ingested
//Affected atom must be a mob
#define MODIFIER_AURA 4
//The modifier remains valid as long as the target's turf is within a range of the source's turf
//The range is defined in source data
//A range of zero is still valid if source and target are on the same turf. Sub-zero range is invalid
//Works on any affected atom
#define MODIFIER_TIMED 5
//The modifier remains valid as long as the duration has not expired.
//Note that a duration can be used on any time, this type is just one that does not
//check anything else but duration.
//Does not require or use a source atom
//Duration is mandatory for this type.
//Works on any atom
#define MODIFIER_CUSTOM 6
//The validity check will always return 1. The author is expected to override
//it with custom validity checking behaviour.
//Does not require or use a source atom
//Does not support duration
//Override Modes:
//An override parameter is passed in with New, which determines what to do if a modifier of
//the same type already exists on the target
#define MODIFIER_OVERRIDE_DENY 0
//The default. If a modifier of our type already exists, the new one is discarded. It will Qdel itself
//Without adding itself to any lists
#define MODIFIER_OVERRIDE_NEIGHBOR 1
//The new modifier ignores the existing one, and adds itself to the list alongside it
//This is not recommended but you may have a specific application
//Using the strength var and updating the effects is preferred if you want to stack multiples
//of the same type of modifier on one mob
#define MODIFIER_OVERRIDE_REPLACE 2
//Probably the most common nondefault and most useful. If an old modifier of the same type exists,
//Then the old one is first stopped without suspending, and deleted.
//Then the new one will add itself as normal
#define MODIFIER_OVERRIDE_REFRESH 3
//This mode will overwrite the variables of the old one with our new values
//It will also force it to remove and reapply its effects
//This is useful for applying a lingering modifier, by refreshing its duration
#define MODIFIER_OVERRIDE_STRENGTHEN 4
//Almost identical to refresh, but it will only apply if the new modifer has a higher strength value
//If the existing modifier's strength is higher than the new one, the new is discarded
#define MODIFIER_OVERRIDE_CUSTOM 5
//Calls a custom override function to be overwritten
//This is the main proc you should call to create a modifier on a target object
/datum/proc/add_modifier(var/typepath, var/_modifier_type, var/_source = null, var/_source_data = 0, var/_strength = 0, var/_duration = 0, var/_check_interval = 0, var/override = 0)
var/datum/modifier/D = new typepath(src, _modifier_type, _source, _source_data, _strength, _duration, _check_interval)
if (D && !D.gcDestroyed)
return D.handle_registration(override)
else
return null//The modifier must have failed creation and deleted itself
/datum/modifier
//Config
var/check_interval = 300//How often, in deciseconds, we will recheck the validity
var/atom/target = null
var/atom/source = null
var/modifier_type = 0
var/source_data = 0
var/strength = 0
var/duration = null
//A list of equip slots which are considered 'worn'.
//For equipment modifier type to be valid, the source object must be in a mob's contents
//and equipped to one of these whitelisted slots
//This list can be overridden if you want a custom slot whitelist
var/list/valid_equipment_slots = list(slot_back, slot_wear_mask, slot_handcuffed, slot_belt, \
slot_wear_id, slot_l_ear, slot_glasses, slot_gloves, slot_head, slot_shoes, slot_wear_suit, \
slot_w_uniform,slot_legcuffed, slot_r_ear, slot_legs, slot_tie)
//Operating Vars
var/active = 0//Whether or not the effects are currently applied
var/next_check = 0
var/last_tick = 0
//If creation of a modifier is successful, it will return a reference to itself
//If creation fails for any reason, it will return null as well as giving some debug output
/datum/modifier/New(var/atom/_target, var/_modifier_type, var/_source = null, var/_source_data = 0, var/_strength = 0, var/_duration = 0, var/_check_interval = 0)
..()
target = _target
modifier_type = _modifier_type
source = _source
source_data = _source_data
strength = _strength
last_tick = world.time
if (_duration)
duration = _duration
if (_check_interval)
check_interval = _check_interval
if (!target || !modifier_type)
return invalid_creation("No target and/or no modifier type was submitted")
switch (modifier_type)
if (MODIFIER_EQUIPMENT)
if (!istype(target, /mob))
return invalid_creation("Equipment type requires a mob target")
if (!source || !istype(source, /obj))
return invalid_creation("Equipment type requires an object source")
//TODO: Port equip slot var
if (MODIFIER_ITEM)
if (!source || !istype(source, /obj))
return invalid_creation("Item type requires a source")
if (MODIFIER_REAGENT)
if (!istype(target, /mob) || !istype(source, /datum/reagent))
return invalid_creation("Reagent type requires a mob target and a reagent source")
if (MODIFIER_AURA)
if (!source || !istype(source, /atom))
return invalid_creation("Aura type requires an atom source")
if (MODIFIER_TIMED)
if (!duration || duration <= 0)
return invalid_creation("Timed type requires a duration")
if (MODIFIER_CUSTOM)
//No code here, just to prevent else
else
return invalid_creation("Invalid or unrecognised modifier type")//Not a valid modifier type.
return 1
/datum/modifier/proc/handle_registration(var/override = 0)
var/datum/modifier/existing = null
for (var/datum/modifier/D in target.modifiers)
if (D.type == type)
existing = D
if (!existing)
processing_modifiers += src
target.modifiers += src
activate()
return src
else
return handle_override(override, existing)
/datum/modifier/proc/activate()
if (!gcDestroyed && !active && target)
active = 1
return 1
return 0
/datum/modifier/proc/deactivate()
active = 0
return 1
/datum/modifier/proc/process()
if (!active)
last_tick = world.time
return 0
if (!isnull(duration))duration -= world.time - last_tick
if (world.time > next_check)
last_tick = world.time
return check_validity()
last_tick = world.time
return 1
/datum/modifier/proc/check_validity()
next_check = world.time + check_interval
if (!target || target.gcDestroyed)
return validity_fail("Target is gone!")
if (modifier_type == MODIFIER_CUSTOM)
if (custom_validity())
return 1
else
return validity_fail("Custom failed")
if (!isnull(duration) && duration <= 0)
return validity_fail("Duration expired")
else if (modifier_type == MODIFIER_TIMED)
return 1
if (!source || source.gcDestroyed)//If we're not timed or custom, then we need a source. If our source is gone, we are invalid
return validity_fail("Source is gone and we need one")
switch (modifier_type)
if (MODIFIER_EQUIPMENT)
if (source.loc != target)
return validity_fail("Not in contents of mob")
var/obj/item/I = source
if (!I.equip_slot || !(I.equip_slot in valid_equipment_slots))
return validity_fail("Not equipped in the correct place")
//TODO: Port equip slot var. this cant be done properly without it. This is a temporary implementation
if (MODIFIER_ITEM)
if (!source.find_up_hierarchy(target))//If source is somewhere inside target, this will be true
return validity_fail("Not found in parent hierarchy")
if (MODIFIER_REAGENT)
var/totaldose = 0
if (!istype(source, /datum/reagent))//this shouldnt happen
return validity_fail("Source is not a reagent!")
var/ourtype = source.type
for (var/datum/reagent/R in target.reagents.reagent_list)
if (istype(R, ourtype))
totaldose += R.dose
if (istype(target, /mob/living))
var/mob/living/L = target
for (var/datum/reagent/R in L.ingested.reagent_list)
if (istype(R, ourtype))
totaldose += R.dose
if (istype(target, /mob/living/carbon))
var/mob/living/carbon/C = target
for (var/datum/reagent/R in C.bloodstr.reagent_list)
if (istype(R, ourtype))
totaldose += R.dose
for (var/datum/reagent/R in C.touching.reagent_list)
if (istype(R, ourtype))
totaldose += R.dose
if (totaldose < source_data)
return validity_fail("Dose is too low!")
if (MODIFIER_AURA)
if (!(get_turf(target) in range(source_data, get_turf(source))))
return validity_fail("Target not in range of source")
return 1
//Override this without a call to parent, for custom validity conditions
/datum/modifier/proc/custom_validity()
return 1
/datum/modifier/proc/validity_fail(var/reason)
//world << "MODIFIER VALIDITY FAIL: [reason]"
qdel(src)
return 0
/datum/modifier/proc/invalid_creation(var/reason)
log_debug("ERROR: [src] MODIFIER CREATION FAILED on [target]: [reason]")
qdel(src)
return 0
//called by any object to either pause or remove the proc.
/datum/modifier/proc/stop(var/instant = 0, var/suspend = 0)
//Instant var removes us from the lists immediately, instead of waiting til next frame when qdel goes through
if (instant)
if (target)
target.modifiers -= src
processing_modifiers -= src
if (suspend)
deactivate()
else
qdel(src)
//Suspends and immediately restarts the proc, thus reapplying its effects
/datum/modifier/proc/refresh()
deactivate()
activate()
/datum/modifier/Destroy()
if (active)
deactivate()
if (target)
target.modifiers -= src
processing_modifiers -= src
..()
//Handles overriding an existing modifier of the same type.
//This function should return either src or the existing, depending on whether or not src will be kept
/datum/modifier/proc/handle_override(var/override, var/datum/modifier/existing)
switch(override)
if (MODIFIER_OVERRIDE_DENY)
qdel(src)
return existing
if (MODIFIER_OVERRIDE_NEIGHBOR)
processing_modifiers += src
target.modifiers += src
return src
if (MODIFIER_OVERRIDE_REPLACE)
existing.stop()
processing_modifiers += src
target.modifiers += src
activate()
return src
if (MODIFIER_OVERRIDE_REFRESH)
existing.strength = strength
existing.duration = duration
existing.source = source
existing.source_data = source_data
if (existing.check_validity())
existing.refresh()
qdel(src)
return existing
else
qdel(src)
return null//this should only happen if you overwrote the existing with bad values.
//It will result in both existing and src being deleted
//The null return will allow the source to see this went wrong and remake the modifier
if (MODIFIER_OVERRIDE_STRENGTHEN)
if (strength > existing.strength)
existing.strength = strength
existing.duration = duration
existing.source = source
existing.source_data = source_data
if (existing.check_validity())
existing.refresh()
qdel(src)
return existing
qdel(src)
return null
qdel(src)
return existing
if (MODIFIER_OVERRIDE_CUSTOM)
return custom_override(existing)
else
qdel(src)
return existing
//This function should be completely overwritten, without a call to parent, to specify custom override
/datum/modifier/proc/custom_override(var/datum/modifier/existing)
qdel(src)
return existing
+73
View File
@@ -0,0 +1,73 @@
//Stimulant modifier. Applied in varying strengths by hyperzine and caffienated drinks
//Increases sprinting speed, walk speed, and stamina regen
/datum/modifier/stimulant
var/sprint_speed_added = 0
var/regen_added = 0
var/delay_added = 0
/datum/modifier/stimulant/activate()
..()
if (isliving(target))
var/mob/living/L = target
sprint_speed_added = 0.2 * strength
L.sprint_speed_factor += sprint_speed_added
regen_added = L.stamina_recovery * 0.3 * strength
L.stamina_recovery += regen_added
delay_added = -1.5 * strength
L.move_delay_mod += delay_added
/datum/modifier/stimulant/deactivate()
..()
if (isliving(target))
var/mob/living/L = target
L.sprint_speed_factor -= sprint_speed_added
L.stamina_recovery -= regen_added
L.move_delay_mod -= delay_added
//Adrenaline, granted by synaptizine and inaprovaline, with different strengths for each
//Allows the body to endure more, increasing speed a little, stamina a lot, stamina regen a lot,
//and reducing sprint costs
//Synaptizine applies it at strength 1, inaprovaline applies it at strength 0.6
//Is applied using strengthen override mode, so synaptizine will replace inaprovaline if both are present
/datum/modifier/adrenaline
var/speed_added = 0
var/stamina_added = 0
var/cost_added = 0
var/regen_added = 0
/datum/modifier/adrenaline/activate()
..()
if (isliving(target))
var/mob/living/L = target
speed_added += 0.1*strength
L.sprint_speed_factor += speed_added
stamina_added = L.max_stamina * strength
L.max_stamina += stamina_added
cost_added = -0.35 * strength
L.sprint_cost_factor += cost_added
regen_added = max ((L.stamina_recovery * 0.7 * strength), 5)
L.stamina_recovery += regen_added
/datum/modifier/adrenaline/deactivate()
..()
if (isliving(target))
var/mob/living/L = target
L.stamina_recovery -= regen_added
L.max_stamina -= stamina_added
L.sprint_cost_factor -= cost_added
L.sprint_speed_factor -= speed_added
+45
View File
@@ -249,6 +249,7 @@
// note this isn't called during the initial dressing of a player
/obj/item/proc/equipped(var/mob/user, var/slot)
layer = 20
equip_slot = slot
if(user.client) user.client.screen |= src
if(user.pulling == src) user.stop_pulling()
return
@@ -656,3 +657,47 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
/obj/item/proc/pwr_drain()
return 0 // Process Kill
//a proc that any worn thing can call to update its itemstate
//Should be cheaper than calling regenerate icons on the mob
/obj/item/proc/update_worn_icon()
if (!equip_slot || !istype(loc, /mob))
return
var/mob/M = loc
switch (equip_slot)
if (slot_back)
M.update_inv_back()
if (slot_wear_mask)
M.update_inv_wear_mask()
if (slot_l_hand)
M.update_inv_l_hand()
if (slot_r_hand)
M.update_inv_r_hand()
if (slot_belt)
M.update_inv_belt()
if (slot_wear_id)
M.update_inv_wear_id()
if (slot_l_ear)
M.update_inv_ears()
if (slot_r_ear)
M.update_inv_ears()
if (slot_glasses)
M.update_inv_glasses()
if (slot_gloves)
M.update_inv_gloves()
if (slot_head)
M.update_inv_head()
if (slot_shoes)
M.update_inv_shoes()
if (slot_wear_suit)
M.update_inv_wear_suit()
if (slot_w_uniform)
M.update_inv_w_uniform()
if (slot_l_store)
M.update_inv_pockets()
if (slot_r_store)
M.update_inv_pockets()
if (slot_s_store)
M.update_inv_s_store()
+1
View File
@@ -25,6 +25,7 @@
var/list/icon_supported_species_tags //Used with icon_auto_adapt, a list of species which have differing appearances for this item
var/icon_species_in_hand = 0//If 1, we will use the species tag even for rendering this item in the left/right hand.
var/equip_slot = 0
/obj/Destroy()
processing_objects -= src
nanomanager.close_uis(src)
+4 -3
View File
@@ -145,14 +145,15 @@
if(istype(MOB) && !MOB.lying && footstep_sound)
if(istype(MOB.shoes, /obj/item/clothing/shoes) && !MOB.shoes:silent)
if(MOB.m_intent == "run")
playsound(MOB, footstep_sound, 70, 1)
else //Run and walk footsteps switched, because walk is the normal movement mode now
if(MOB.footstep >= 2)
MOB.footstep = 0
else
MOB.footstep++
if(MOB.footstep == 0)
playsound(MOB, footstep_sound, 50, 1) // this will get annoying very fast. - Tell them to mute it then -_-
else
playsound(MOB, footstep_sound, 40, 1)
playsound(MOB, footstep_sound, 40, 1)
else if(!istype(src, /turf/space))
+1
View File
@@ -8,6 +8,7 @@ var/global/obj/effect/datacore/data_core = null
var/global/list/all_areas = list()
var/global/list/machines = list()
var/global/list/processing_objects = list()
var/global/list/processing_modifiers = list()
var/global/list/processing_power_items = list()
var/global/list/active_diseases = list()
var/global/list/med_hud_users = list() // List of all entities using a medical HUD.
@@ -1176,6 +1176,12 @@
if (src.is_diona())
setup_gestalt(1)
max_stamina = species.stamina
stamina = max_stamina
sprint_speed_factor = species.sprint_speed_factor
sprint_cost_factor = species.sprint_cost_factor
stamina_recovery = species.stamina_recovery
exhaust_threshold = species.exhaust_threshold
if(species)
return 1
else
@@ -16,7 +16,7 @@
var/clone_l = getCloneLoss()
health = maxHealth - oxy_l - tox_l - clone_l - total_burn - total_brute
update_health_display()
//TODO: fix husking
if( ((maxHealth - total_burn) < config.health_threshold_dead) && stat == DEAD)
ChangeToHusk()
@@ -1,7 +1,6 @@
/mob/living/carbon/human/movement_delay()
var/tally = 0
if(species.slowdown)
tally = species.slowdown
@@ -10,8 +9,7 @@
if(embedded_flag)
handle_embedded_objects() //Moving with objects stuck in you can cause bad times.
if(CE_SPEEDBOOST in chem_effects)
return -1
var/health_deficiency = (100 - health)
if(health_deficiency >= 40) tally += (health_deficiency / 25)
@@ -49,18 +47,27 @@
if(shock_stage >= 10) tally += 3
if (drowsyness) tally += 6
if(FAT in src.mutations)
tally += 1.5
if (bodytemperature < 283.222)
tally += (283.222 - bodytemperature) / 10 * 1.75
tally += max(2 * stance_damage, 0) //damaged/missing feet or legs is slow
if(mRun in mutations)
tally = 0
tally += move_delay_mod
if(tally > 0 && (CE_SPEEDBOOST in chem_effects))
tally = max(0, tally-3)
return (tally+config.human_delay)
/mob/living/carbon/human/Process_Spacemove(var/check_drift = 0)
//Can we act?
if(restrained()) return 0
@@ -1,7 +1,9 @@
#define AE_DIZZY 5
#define AE_BUZZED_MIN 6
#define AE_SLURRING 15
#define AE_CONFUSION 18
#define AE_CLUMSY 22
#define AE_BUZZED_MAX 24
#define AE_BLURRING 25
#define AE_VOMIT 40
#define AE_DROWSY 55
@@ -70,3 +72,48 @@ var/mob/living/carbon/human/alcohol_clumsy = 0
if(intoxication > AE_BLACKOUT*SR) // Pass out
paralysis = max(paralysis, 20)
sleeping = max(sleeping, 30)
if( intoxication >= AE_BUZZED_MIN && intoxication <= AE_BUZZED_MAX && !(locate(/datum/modifier/buzzed) in modifiers))
add_modifier(/datum/modifier/buzzed, MODIFIER_CUSTOM)
//Pleasant feeling from being slightly drunk
//Makes you faster and reduces sprint cost
//Wears off if you get too drunk or too sober, a balance must be maintained
/datum/modifier/buzzed
/datum/modifier/buzzed/activate()
..()
if (ishuman(target))
var/mob/living/carbon/human/H = target
H.move_delay_mod += -0.75
H.sprint_cost_factor += -0.1
/datum/modifier/buzzed/deactivate()
..()
if (ishuman(target))
var/mob/living/carbon/human/H = target
H.move_delay_mod -= -0.75
H.sprint_cost_factor -= -0.1
/datum/modifier/buzzed/custom_validity()
if (ishuman(target))
var/mob/living/carbon/human/H = target
if (H.intoxication >= AE_BUZZED_MIN && H.intoxication <= AE_BUZZED_MAX)
return 1
return 0
#undef AE_DIZZY
#undef AE_BUZZED_MIN
#undef AE_SLURRING
#undef AE_CONFUSION
#undef AE_CLUMSY
#undef AE_BUZZED_MAX
#undef AE_BLURRING
#undef AE_VOMIT
#undef AE_DROWSY
#undef AE_OVERDOSE
#undef AE_BLACKOUT
+68 -37
View File
@@ -102,6 +102,9 @@
handle_heartbeat()
//Handles regenerating stamina if we have sufficient air and no oxyloss
handle_stamina()
if (is_diona())
diona_handle_light(DS)
@@ -559,7 +562,9 @@
failed_last_breath = 1
else
failed_last_breath = 0
adjustOxyLoss(-5)
adjustOxyLoss(-3)
// Hot air hurts :(
@@ -964,7 +969,7 @@
return 1
//UNCONSCIOUS. NO-ONE IS HOME
if((getOxyLoss() > 50) || (health <= config.health_threshold_crit))
if((getOxyLoss() > exhaust_threshold) || (health <= config.health_threshold_crit))
Paralyse(3)
if(hallucination)
@@ -1179,24 +1184,7 @@
damageoverlay.overlays += I
else
//Oxygen damage overlay
if(oxyloss)
var/image/I
switch(oxyloss)
if(10 to 20)
I = overlays_cache[11]
if(20 to 25)
I = overlays_cache[12]
if(25 to 30)
I = overlays_cache[13]
if(30 to 35)
I = overlays_cache[14]
if(35 to 40)
I = overlays_cache[15]
if(40 to 45)
I = overlays_cache[16]
if(45 to INFINITY)
I = overlays_cache[17]
damageoverlay.overlays += I
update_oxy_overlay()
// Vampire frenzy overlay.
if (mind.vampire)
@@ -1277,23 +1265,9 @@
if(equipped_glasses)
process_glasses(equipped_glasses)
if(healths)
if (analgesic > 100)
healths.icon_state = "health_numb"
else
switch(hal_screwyhud)
if(1) healths.icon_state = "health6"
if(2) healths.icon_state = "health7"
else
//switch(health - halloss)
switch(health - traumatic_shock)
if(100 to INFINITY) healths.icon_state = "health0"
if(80 to 100) healths.icon_state = "health1"
if(60 to 80) healths.icon_state = "health2"
if(40 to 60) healths.icon_state = "health3"
if(20 to 40) healths.icon_state = "health4"
if(0 to 20) healths.icon_state = "health5"
else healths.icon_state = "health6"
update_health_display()
if(nutrition_icon)
switch(nutrition)
@@ -1748,5 +1722,62 @@
restore_blood()
..()
/mob/living/carbon/human/proc/handle_stamina()
if (species.stamina == -1)//If species stamina is -1, it has special mechanics which will be handled elsewhere
return//so quit this function
if (failed_last_breath || oxyloss > exhaust_threshold)//Can't catch our breath if we're suffocating
return
if (stamina != max_stamina)
//Any suffocation damage slows stamina regen.
//This includes oxyloss from low blood levels
var/regen = stamina_recovery * (1 - min(((oxyloss*2) / exhaust_threshold), 1))
if (regen > 0)
stamina = min(max_stamina, stamina+regen)
nutrition -= stamina_recovery*0.4
hud_used.move_intent.update_move_icon(src)
/mob/living/carbon/human/proc/update_health_display()
if(!healths)
return
if (analgesic > 100)
healths.icon_state = "health_numb"
else
switch(hal_screwyhud)
if(1) healths.icon_state = "health6"
if(2) healths.icon_state = "health7"
else
//switch(health - halloss)
switch(health - traumatic_shock)
if(100 to INFINITY) healths.icon_state = "health0"
if(80 to 100) healths.icon_state = "health1"
if(60 to 80) healths.icon_state = "health2"
if(40 to 60) healths.icon_state = "health3"
if(20 to 40) healths.icon_state = "health4"
if(0 to 20) healths.icon_state = "health5"
else healths.icon_state = "health6"
/mob/living/carbon/human/proc/update_oxy_overlay()
if(oxyloss)
var/image/I
switch(oxyloss)
if(10 to 20)
I = overlays_cache[11]
if(20 to 25)
I = overlays_cache[12]
if(25 to 30)
I = overlays_cache[13]
if(30 to 35)
I = overlays_cache[14]
if(35 to 40)
I = overlays_cache[15]
if(40 to 45)
I = overlays_cache[16]
if(45 to INFINITY)
I = overlays_cache[17]
damageoverlay.overlays += I
#undef HUMAN_MAX_OXYLOSS
#undef HUMAN_CRIT_MAX_OXYLOSS
@@ -54,3 +54,8 @@
"l_foot" = list("path" = /obj/item/organ/external/foot/skeleton),
"r_foot" = list("path" = /obj/item/organ/external/foot/right/skeleton)
)
stamina = 500 //Tireless automatons
stamina_recovery = 1
sprint_speed_factor = 0.3
exhaust_threshold = 0 //No oxyloss, so zero threshold
@@ -15,6 +15,12 @@
smell.<br/><br/>Most humans will never meet a Vox raider, instead learning of this insular species through \
dealing with their traders and merchants; those that do rarely enjoy the experience."
stamina = 120 // Vox are even faster than unathi and can go longer, but recover slowly
sprint_speed_factor = 3
stamina_recovery = 1
sprint_cost_factor = 1.7
speech_sounds = list('sound/voice/shriek1.ogg')
speech_chance = 20
@@ -99,18 +99,24 @@
var/hud_type
// Body/form vars.
var/list/inherent_verbs // Species-specific verbs.
var/has_fine_manipulation = 1 // Can use small items.
var/siemens_coefficient = 1 // The lower, the thicker the skin and better the insulation.
var/darksight = 2 // Native darksight distance.
var/flags = 0 // Various specific features.
var/slowdown = 0 // Passive movement speed malus (or boost, if negative)
var/primitive_form // Lesser form, if any (ie. monkey for humans)
var/greater_form // Greater form, if any, ie. human for monkeys.
var/list/inherent_verbs // Species-specific verbs.
var/has_fine_manipulation = 1 // Can use small items.
var/siemens_coefficient = 1 // The lower, the thicker the skin and better the insulation.
var/darksight = 2 // Native darksight distance.
var/flags = 0 // Various specific features.
var/slowdown = 0 // Passive movement speed malus (or boost, if negative)
var/primitive_form // Lesser form, if any (ie. monkey for humans)
var/greater_form // Greater form, if any, ie. human for monkeys.
var/holder_type
var/gluttonous // Can eat some mobs. 1 for mice, 2 for monkeys, 3 for people.
var/rarity_value = 1 // Relative rarity/collector value for this species.
var/ethanol_resistance = 1 // How well the mob resists alcohol, lower values get drunk faster, higher values need to drink more
var/gluttonous // Can eat some mobs. 1 for mice, 2 for monkeys, 3 for people.
var/rarity_value = 1 // Relative rarity/collector value for this species.
var/ethanol_resistance = 1 // How well the mob resists alcohol, lower values get drunk faster, higher values need to drink more
var/stamina = 100 // The maximum stamina this species has. Determines how long it can sprint
var/stamina_recovery = 3 // Flat amount of stamina species recovers per proc
var/sprint_speed_factor = 0.65 // The percentage of bonus speed you get when sprinting. 0.4 = 40%
var/sprint_cost_factor = 1.0 // Multiplier on stamina cost for sprinting
var/exhaust_threshold = 50 // When stamina runs out, the mob takes oxyloss up til this value. Then collapses and drops to walk
// Determines the organs that the species spawns with and
var/list/has_organ = list( // which required-organ checks are conducted.
@@ -310,3 +316,35 @@
// Called in life() when the mob has no client.
/datum/species/proc/handle_npc(var/mob/living/carbon/human/H)
return
/datum/species/proc/handle_sprint_cost(var/mob/living/carbon/human/H, var/cost)
cost *= H.sprint_cost_factor
if (H.stamina == -1)
log_debug("Error: Species with special sprint mechanics has not overridden cost function.")
return 0
var/remainder = 0
if (H.stamina > cost)
H.stamina -= cost
H.hud_used.move_intent.update_move_icon(H)
return 1
else if (H.stamina > 0)
remainder = cost - H.stamina
H.stamina = 0
else
remainder = cost
H.adjustOxyLoss(remainder*0.4)
H.adjustHalLoss(remainder*0.3)
H.updatehealth()
H.update_oxy_overlay()
if (H.oxyloss >= exhaust_threshold)
H.Weaken(10)
H.m_intent = "walk"
H.hud_used.move_intent.update_move_icon(H)
H << span("danger", "You're too exhausted to run anymore! You collapse in a heap on the floor.")
return 0
H.hud_used.move_intent.update_move_icon(H)
return 1
@@ -33,6 +33,11 @@
death_message = "becomes completely motionless..."
stamina = 500 //Tireless automatons
stamina_recovery = 1
sprint_speed_factor = 0.3
exhaust_threshold = 0 //No oxyloss, so zero threshold
/datum/species/golem/handle_post_spawn(var/mob/living/carbon/human/H)
if(H.mind)
H.mind.assigned_role = "Golem"
@@ -13,6 +13,11 @@
flags = CAN_JOIN | HAS_SKIN_TONE | HAS_LIPS | HAS_UNDERWEAR | HAS_EYE_COLOR
stamina = 130 // Humans can sprint for longer than any other species
stamina_recovery = 5
sprint_speed_factor = 0.8
sprint_cost_factor = 0.8
/datum/species/unathi
name = "Unathi"
short_name = "una"
@@ -27,6 +32,10 @@
darksight = 3
gluttonous = 1
ethanol_resistance = 0.4
stamina = 120 // Unathi have the shortest but fastest sprint of all
sprint_speed_factor = 3
stamina_recovery = 5
sprint_cost_factor = 2
rarity_value = 3
blurb = "A heavily reptillian species, Unathi (or 'Sinta as they call themselves) hail from the \
@@ -90,6 +99,12 @@
ethanol_resistance = 0.8//Gets drunk a little faster
rarity_value = 2
stamina = 90 // Tajarans evolved to maintain a steady pace in the snow, sprinting wastes energy
stamina_recovery = 4
sprint_speed_factor = 0.55
sprint_cost_factor = 1.1
blurb = "The Tajaran race is a species of feline-like bipeds hailing from the planet of Ahdomai in the \
S'randarr system. They have been brought up into the space age by the Humans and Skrell, and have been \
influenced heavily by their long history of Slavemaster rule. They have a structured, clan-influenced way \
@@ -150,6 +165,10 @@
reagent_tag = IS_SKRELL
ethanol_resistance = 0.5//gets drunk faster
stamina = 90
sprint_speed_factor = 1.2 //Evolved for rapid escapes from predators
/datum/species/diona
name = "Diona"
short_name = "dio"
@@ -222,6 +241,41 @@
reagent_tag = IS_DIONA
stamina = -1 // Diona sprinting uses energy instead of stamina
sprint_speed_factor = 0.4 //Speed gained is minor
/datum/species/diona/handle_sprint_cost(var/mob/living/carbon/human/H, var/cost)
var/datum/dionastats/DS = H.get_dionastats()
if (!DS)
return 0 //Something is very wrong
var/remainder = cost
if (H.radiation)
if (H.radiation > (cost*0.5))//Radiation counts as double energy
H.radiation -= cost*0.5
return 1
else
remainder = cost - (H.radiation*2)
H.radiation = 0
if (DS.stored_energy > remainder)
DS.stored_energy -= remainder
return 1
else
remainder -= DS.stored_energy
DS.stored_energy = 0
H.adjustHalLoss(remainder*5, 1)
H.updatehealth()
H.m_intent = "walk"
H.hud_used.move_intent.update_move_icon(H)
H << span("danger", "We have expended our energy reserves, and cannot continue to move at such a pace. We must find light!")
return 0
/datum/species/diona/can_understand(var/mob/other)
var/mob/living/carbon/alien/diona/D = other
if(istype(D))
@@ -283,6 +337,26 @@
has_organ = list() //TODO: Positronic brain.
stamina = -1 // Machines use power and generate heat, stamina is not a thing
sprint_speed_factor = 0.8 // About as capable of speed as a human
/datum/species/machine/handle_sprint_cost(var/mob/living/carbon/human/H, var/cost)
if (H.stat == CONSCIOUS)
H.bodytemperature += cost*1.5
H.nutrition -= cost
if (H.nutrition > 0)
return 1
else
H.Weaken(30)
H.m_intent = "walk"
H.hud_used.move_intent.update_move_icon(H)
H << span("danger", "ERROR: Power reserves depleted, emergency shutdown engaged. Backup power will come online in 60 seconds, initiate charging as primary directive.")
playsound(H.loc, 'sound/machines/buzz-two.ogg', 100, 0)
return 0
/datum/species/machine/equip_survival_gear(var/mob/living/carbon/human/H)
/datum/species/machine/handle_death(var/mob/living/carbon/human/H)
@@ -332,6 +406,12 @@
flesh_color = "#E6E600"
base_color = "#575757"
stamina = 100 // Long period of sprinting, but relatively low speed gain
sprint_speed_factor = 0.5
sprint_cost_factor = 0.3
stamina_recovery = 1//slow recovery
inherent_verbs = list(
/mob/living/carbon/human/proc/bugbite, //weaker version of gut.
)
+13 -1
View File
@@ -47,4 +47,16 @@
var/eat_types = 0//This is a bitfield which must be initialised in New(). The valid values for it are in devour.dm
var/datum/reagents/metabolism/ingested = null
var/underdoor //Used for mobs that can walk through maintenance hatches - drones, pais, and spiderbots
var/life_tick = 0 // The amount of life ticks that have processed on this mob.
var/life_tick = 0 // The amount of life ticks that have processed on this mob.
//These values are duplicated from the species datum so we can handle things on a per-mob basis, allows for chemicals to affect them
var/stamina = 0
var/max_stamina = 100//Maximum stamina. We start taking oxyloss when this runs out while sprinting
var/sprint_speed_factor = 0.4
var/sprint_cost_factor = 1
var/stamina_recovery = 1
var/min_walk_delay = 0//When move intent is walk, movedelay is clamped to this value as a lower bound
var/exhaust_threshold = 50
var/move_delay_mod = 0//Added to move delay, used for calculating movement speeds. Provides a centralised value for modifiers to alter
+34 -7
View File
@@ -32,10 +32,37 @@
attempt_devour(L, eat_types, mouth_size)
/*
/mob/living/verb/devourverb(var/mob/living/victim)//For situations where species inherent verbs isnt suitable
set category = "Abilities"
set name = "Devour Creature"
set desc = "Attempt to eat a nearby creature, swallowing it whole if small enough, or eating it piece by piece otherwise"
attempt_devour(victim, eat_types, mouth_size)
*/
/mob/living/verb/set_walk_speed()
set category = "IC"
set name = "Adjust walk speed"
set desc = "Allows you to adjust your walking speed to a slower value than normal, or reset it. Does not make you faster."
//First a quick block of code to calculate our normal/best movedelay
var/delay = config.walk_speed + movement_delay()
var/speed = 1 / (delay/10)
var/newspeed
var/list/options = list("No limit",speed*0.95,speed*0.9,speed*0.85,speed*0.8,speed*0.7,speed*0.6,speed*0.5, "Custom")
var/response = input(src, "Your current walking speed is [speed] tiles per second. This menu allows you to limit it to a lower value, by applying a multiplier to that. Please choose a value, select custom to enter your own, or No limit to set your walk speed to the maximum. This menu will not make you move any faster than usual, it is only for allowing you to move at a slower pace than normal, for roleplay purposes. Values set here will not affect your sprinting speed", "Limit Walking speed") as null|anything in options
if (isnull(response))
return
else if (response == "No limit")
src << "Movement speed has now been set to normal, limits removed."
src.min_walk_delay = 0
return
else if (response == "Custom")
response = input(src, "Please enter the exact speed you want to walk at, in tiles per second. This value must be less than [speed] and greater than zero", "Limit Walking speed") as num
newspeed = response
else
newspeed = text2num(response)
if (!newspeed || newspeed >= speed || newspeed <= 0)
src << "Error, invalid value entered. Walk speed has not been changed"
return
src << "Walking speed has now been limited to [newspeed] tiles per second, which is [(newspeed/speed)*100]% of your normal walking speed."
src.min_walk_delay = (10 / newspeed)
+1 -1
View File
@@ -119,7 +119,7 @@
var/shakecamera = 0
var/a_intent = I_HELP//Living
var/m_int = null//Living
var/m_intent = "run"//Living
var/m_intent = "walk"//Living
var/lastKnownIP = null
var/obj/buckled = null//Living
var/obj/item/l_hand = null//Living
+20 -11
View File
@@ -179,7 +179,7 @@
Process_Incorpmove(direct)
return
if(moving) return 0
if(moving) return 0
if(world.time < move_delay) return
@@ -209,6 +209,8 @@
if(item.zoom)
item.zoom()
break
//TODO: REMOVE This stupid zooming stuff
/*
if(locate(/obj/item/weapon/gun/energy/sniperrifle, mob.contents)) // If mob moves while zoomed in with sniper rifle, unzoom them.
var/obj/item/weapon/gun/energy/sniperrifle/s = locate() in mob
@@ -257,14 +259,21 @@
move_delay = world.time//set move delay
mob.last_move_intent = world.time + 10
switch(mob.m_intent)
if("run")
if(mob.drowsyness > 0)
move_delay += 6
move_delay += 1+config.run_speed
if("walk")
move_delay += 7+config.walk_speed
move_delay += mob.movement_delay()
if (ishuman(mob))
var/mob/living/carbon/human/H = mob
var/tally = mob.movement_delay()+config.walk_speed
//If we're sprinting and able to continue sprinting, then apply the sprint bonus ontop of this
if (H.m_intent == "run" && H.species.handle_sprint_cost(H, tally))//This will return false if we collapse from exhaustion
tally = tally/(1+H.sprint_speed_factor)
else
tally = max(tally, H.min_walk_delay)//clamp walking speed if its limited
move_delay += tally
else
move_delay += config.walk_speed
move_delay += mob.movement_delay()
var/tickcomp = 0 //moved this out here so we can use it for vehicles
if(config.Tickcomp)
@@ -272,10 +281,11 @@
tickcomp = ((1/(world.tick_lag))*1.3) - 1.3
move_delay = move_delay + tickcomp
if(istype(mob.buckled, /obj/vehicle))
//manually set move_delay for vehicles so we don't inherit any mob movement penalties
//specific vehicle move delays are set in code\modules\vehicles\vehicle.dm
move_delay = world.time + tickcomp
move_delay = world.time
//drunk driving
if(mob.confused && prob(20))
direct = pick(cardinal)
@@ -351,7 +361,6 @@
G.adjust_position()
moving = 0
return .
return
@@ -39,6 +39,10 @@
return
if(!affects_dead && M.stat == DEAD)
return
if(!dose && volume)//If dose is currently zero, we do the first effect
initial_effect(M, alien)
if(overdose && (dose > overdose) && (location != CHEM_TOUCH))
overdose(M, alien)
var/removed = metabolism
@@ -61,6 +65,11 @@
remove_self(removed)
return
//Initial effect is called once when the reagent first starts affecting a mob.
/datum/reagent/proc/initial_effect(var/mob/living/carbon/M, var/alien)
return
/datum/reagent/proc/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
return
@@ -65,6 +65,8 @@
var/adj_temp = 0
var/targ_temp = 310
var/halluci = 0
var/datum/modifier/caffeine_mod
var/caffeine = 0
glass_icon_state = "glass_clear"
glass_name = "glass of ethanol"
@@ -103,6 +105,10 @@
if(halluci)
M.hallucination = max(M.hallucination, halluci)
if (caffeine && !caffeine_mod)
caffeine_mod = M.add_modifier(/datum/modifier/stimulant, MODIFIER_REAGENT, src, _strength = caffeine, override = MODIFIER_OVERRIDE_STRENGTHEN)
/datum/reagent/ethanol/touch_obj(var/obj/O)
if(istype(O, /obj/item/weapon/paper))
@@ -354,12 +354,17 @@
var/adj_drowsy = 0
var/adj_sleepy = 0
var/adj_temp = 0
var/caffeine = 0 // strength of stimulant effect, since so many drinks use it
var/datum/modifier/modifier = null
/datum/reagent/drink/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
M.adjustToxLoss(removed) // Probably not a good idea; not very deadly though
return
/datum/reagent/drink/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed)
if (caffeine && !modifier)
modifier = M.add_modifier(/datum/modifier/stimulant, MODIFIER_REAGENT, src, _strength = caffeine, override = MODIFIER_OVERRIDE_STRENGTHEN)
M.nutrition += nutrition * removed
M.dizziness = max(0, M.dizziness + adj_dizzy)
M.drowsyness = max(0, M.drowsyness + adj_drowsy)
@@ -586,6 +591,7 @@
adj_sleepy = -2
adj_temp = 25
overdose = 45
caffeine = 0.3
glass_icon_state = "hot_coffee"
glass_name = "cup of coffee"
@@ -606,6 +612,7 @@
M.bodytemperature = max(310, M.bodytemperature - (5 * TEMPERATURE_DAMAGE_COEFFICIENT))
/datum/reagent/drink/coffee/overdose(var/mob/living/carbon/M, var/alien)
if(alien == IS_DIONA)
return
@@ -757,6 +764,7 @@
id = "rewriter"
color = "#485000"
adj_temp = -5
caffeine = 0.4
glass_icon_state = "rewriter"
glass_name = "glass of Rewriter"
@@ -767,6 +775,7 @@
..()
M.make_jittery(5)
/datum/reagent/drink/nuka_cola
name = "Nuka Cola"
id = "nuka_cola"
@@ -774,6 +783,7 @@
color = "#100800"
adj_temp = -5
adj_sleepy = -2
caffeine = 1
glass_icon_state = "nuka_colaglass"
glass_name = "glass of Nuka-Cola"
@@ -1043,6 +1053,7 @@
description = "A widely known, Mexican coffee-flavoured liqueur. In production since 1936!"
color = "#664300"
strength = 20
caffeine = 0.25
glass_icon_state = "kahluaglass"
glass_name = "glass of RR coffee liquor"
@@ -1115,6 +1126,7 @@
color = "#102000"
strength = 10
nutriment_factor = 1
caffeine = 0.5
glass_icon_state = "thirteen_loko_glass"
glass_name = "glass of Thirteen Loko"
@@ -1390,6 +1402,7 @@
description = "It's just as effective as Dutch-Courage!"
color = "#664300"
strength = 30
caffeine = 0.2
glass_icon_state = "bravebullglass"
glass_name = "glass of Brave Bull"
@@ -1598,6 +1611,7 @@
description = "Coffee, and alcohol. More fun than a Mimosa to drink in the morning."
color = "#664300"
strength = 15
caffeine = 0.3
glass_icon_state = "irishcoffeeglass"
glass_name = "glass of Irish coffee"
@@ -1979,6 +1993,7 @@
adj_sleepy = -3
adj_temp = 30
overdose = 40
caffeine = 0.4
glass_icon_state = "blackcoffee"
glass_name = "A mug of rich Black Coffee"
@@ -1994,6 +2009,7 @@
adj_sleepy = -3
adj_temp = 30
overdose = 40
caffeine = 0.3
glass_icon_state = "whitecoffee"
glass_name = "A mug of Café Au Lait"
@@ -2013,6 +2029,7 @@
adj_sleepy = -3
adj_temp = 30
overdose = 40
caffeine = 0.3
glass_icon_state = "whitecoffee"
glass_name = "A mug of Café Mélange"
@@ -9,11 +9,15 @@
overdose = REAGENTS_OVERDOSE * 2
metabolism = REM * 0.5
scannable = 1
var/datum/modifier/modifier
/datum/reagent/inaprovaline/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
if(alien != IS_DIONA)
M.add_chemical_effect(CE_STABLE)
M.add_chemical_effect(CE_PAINKILLER, 25)
if (!modifier)
modifier = M.add_modifier(/datum/modifier/adrenaline, MODIFIER_REAGENT, src, _strength = 0.6, override = MODIFIER_OVERRIDE_STRENGTHEN)
/datum/reagent/bicaridine
name = "Bicaridine"
@@ -212,6 +216,7 @@
metabolism = REM * 0.05
overdose = REAGENTS_OVERDOSE
scannable = 1
var/datum/modifier/modifier
/datum/reagent/synaptizine/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
if(alien == IS_DIONA)
@@ -224,6 +229,10 @@
M.hallucination = max(0, M.hallucination - 10)
M.adjustToxLoss(5 * removed) // It used to be incredibly deadly due to an oversight. Not anymore!
M.add_chemical_effect(CE_PAINKILLER, 40)
if (!modifier)
modifier = M.add_modifier(/datum/modifier/adrenaline, MODIFIER_REAGENT, src, _strength = 1, override = MODIFIER_OVERRIDE_STRENGTHEN)
/datum/reagent/alkysine
name = "Alkysine"
@@ -305,6 +314,7 @@
color = "#FF3300"
metabolism = REM * 0.15
overdose = REAGENTS_OVERDOSE * 0.5
var/datum/modifier = null
/datum/reagent/hyperzine/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
if(alien == IS_DIONA)
@@ -312,7 +322,8 @@
if(prob(5))
M.emote(pick("twitch", "blink_r", "shiver"))
M.add_chemical_effect(CE_SPEEDBOOST, 1)
if (!modifier)
modifier = M.add_modifier(/datum/modifier/stimulant, MODIFIER_REAGENT, src, _strength = 1, override = MODIFIER_OVERRIDE_STRENGTHEN)
#define ETHYL_INTOX_COST 3 //The cost of power to remove one unit of intoxication from the patient
+40
View File
@@ -0,0 +1,40 @@
################################
# Example Changelog File
#
# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
#
# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
# When it is, any changes listed below will disappear.
#
# Valid Prefixes:
# bugfix
# wip (For works in progress)
# tweak
# soundadd
# sounddel
# rscadd (general adding of nice things)
# rscdel (general deleting of nice things)
# imageadd
# imagedel
# maptweak
# spellcheck (typo fixes)
# experiment
#################################
# Your name.
author: Nanako
# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
delete-after: True
# Any changes you've made. See valid prefix list above.
# INDENT WITH TWO SPACES. NOT TABS. SPACES.
# SCREW THIS UP AND IT WON'T WORK.
# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries.
# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog.
changes:
- rscadd: "Added a new sprinting mechanic. Moving in run mode is now much faster, but limited by stamina or a special species mechanic. Sprinting works slightly differently for each species."
- tweak: "Moving in walk mode is now as fast as run used to be. Walk is the new default speed."
- rscadd: "Added a walkspeed limiting feature. Use Limit Walk Speed in the IC tab, or alt+click on the walk/run button to bring up a menu. This allows limiting your walk speed very precisely to any value below normal. It can only slow you down, will not increase speed."
- tweak: "Natural recovery of suffocation damage is now slower."
- rscadd: "Alcohol, caffienated drinks, and several performance enhancing drugs now have interactions with movement, sprinting and stamina."
Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 KiB

After

Width:  |  Height:  |  Size: 166 KiB