diff --git a/.travis.yml b/.travis.yml index 872a91ccdd..64f2dcd9fa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,24 +1,31 @@ #pretending we're C because otherwise ruby will initialize, even with "language: dm". language: c +sudo: false env: BYOND_MAJOR="508" BYOND_MINOR="1287" - -before_install: - - sudo apt-get update -qq - - sudo apt-get install libc6:i386 libgcc1:i386 libstdc++6:i386 -qq - - sudo apt-get install python -qq - - sudo apt-get install python-pip -qq - - sudo pip install PyYaml -q - - sudo pip install beautifulsoup4 -q - + +cache: + directories: + - $HOME/BYOND-${BYOND_MAJOR}.${BYOND_MINOR} + +addons: + apt: + packages: + - libc6-i386 + - libgcc1:i386 + - libstdc++6:i386 + - python + - python-pip + install: - - curl "http://www.byond.com/download/build/${BYOND_MAJOR}/${BYOND_MAJOR}.${BYOND_MINOR}_byond_linux.zip" -o byond.zip - - unzip byond.zip - - cd byond - - sudo make install - - cd .. + - pip install --user PyYaml -q + - pip install --user beautifulsoup4 -q + +before_script: + - chmod +x ./install-byond.sh + - ./install-byond.sh script: - shopt -s globstar @@ -29,4 +36,6 @@ script: - md5sum -c - <<< "88490b460c26947f5ec1ab1bb9fa9f17 *html/changelogs/example.yml" - python tools/TagMatcher/tag-matcher.py ../.. - python tools/GenerateChangelog/ss13_genchangelog.py html/changelog.html html/changelogs + - source $HOME/BYOND-${BYOND_MAJOR}.${BYOND_MINOR}/byond/bin/byondsetup - DreamMaker baystation12.dme + diff --git a/code/_helpers/maths.dm b/code/_helpers/maths.dm index 2e20370f8f..0c1653b42a 100644 --- a/code/_helpers/maths.dm +++ b/code/_helpers/maths.dm @@ -1,15 +1,6 @@ // Macro functions. #define RAND_F(LOW, HIGH) (rand()*(HIGH-LOW) + LOW) -// List of square roots for the numbers 1-100. -var/list/sqrtTable = list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10) - -/proc/Clamp(val, min, max) - return max(min, min(val, max)) - // min is inclusive, max is exclusive /proc/Wrap(val, min, max) var/d = max - min @@ -136,4 +127,4 @@ var/list/sqrtTable = list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, return (val & (val-1)) == 0 /proc/RoundUpToPowerOfTwo(var/val) - return 2 ** -round(-log(2,val)) \ No newline at end of file + return 2 ** -round(-log(2,val)) diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm index e44a60ebc2..62d67ab18e 100644 --- a/code/_helpers/unsorted.dm +++ b/code/_helpers/unsorted.dm @@ -550,23 +550,6 @@ proc/GaussRand(var/sigma) proc/GaussRandRound(var/sigma,var/roundto) return round(GaussRand(sigma),roundto) -proc/anim(turf/location as turf,target as mob|obj,a_icon,a_icon_state as text,flick_anim as text,sleeptime = 0,direction as num) -//This proc throws up either an icon or an animation for a specified amount of time. -//The variables should be apparent enough. - var/atom/movable/overlay/animation = new(location) - if(direction) - animation.set_dir(direction) - animation.icon = a_icon - animation.layer = target:layer+1 - if(a_icon_state) - animation.icon_state = a_icon_state - else - animation.icon_state = "blank" - animation.master = target - flick(flick_anim, animation) - sleep(max(sleeptime, 15)) - qdel(animation) - //Will return the contents of an atom recursivly to a depth of 'searchDepth' /atom/proc/GetAllContents(searchDepth = 5) var/list/toReturn = list() @@ -1306,7 +1289,29 @@ var/list/WALLITEMS = list( colour += temp_col return colour +//Version of view() which ignores darkness, because BYOND doesn't have it. +/proc/dview(var/range = world.view, var/center, var/invis_flags = 0) + if(!center) + return + + var/global/mob/dview/DV + if(!DV) + DV = new + + DV.loc = center + + DV.see_in_dark = range + DV.see_invisible = invis_flags + + . = view(range, DV) + DV.loc = null + +/mob/dview + invisibility = 101 + density = 0 + /atom/proc/get_light_and_color(var/atom/origin) if(origin) color = origin.color set_light(origin.light_range, origin.light_power, origin.light_color) + diff --git a/code/controllers/voting.dm b/code/controllers/voting.dm index 7a4d10fc88..54f59204fb 100644 --- a/code/controllers/voting.dm +++ b/code/controllers/voting.dm @@ -381,7 +381,9 @@ datum/controller/vote if(usr.client.holder) initiate_vote("custom",usr.key) else - submit_vote(usr.ckey, round(text2num(href_list["vote"]))) + var/t = round(text2num(href_list["vote"])) + if(t) // It starts from 1, so there's no problem + submit_vote(usr.ckey, t) usr.vote() diff --git a/code/game/antagonist/_antagonist_setup.dm b/code/game/antagonist/_antagonist_setup.dm index ebf22a21c9..ecfe15a237 100644 --- a/code/game/antagonist/_antagonist_setup.dm +++ b/code/game/antagonist/_antagonist_setup.dm @@ -69,4 +69,11 @@ var/global/list/antag_names_to_ids = list() var/datum/antagonist/antag = all_antag_types[atype] if(antag && islist(antag.current_antagonists)) return antag.current_antagonists - return list() \ No newline at end of file + return list() + +/proc/player_is_antag(var/datum/mind/player) + for(var/antag_type in all_antag_types) + var/datum/antagonist/antag = all_antag_types[antag_type] + if(player in antag.current_antagonists) + return 1 + return 0 diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm index 11431682a1..efe744174b 100644 --- a/code/game/antagonist/antagonist.dm +++ b/code/game/antagonist/antagonist.dm @@ -70,6 +70,8 @@ candidates -= player else if(!can_become_antag(player)) candidates -= player + else if(player_is_antag(player)) + candidates -= player return candidates /datum/antagonist/proc/attempt_random_spawn() diff --git a/code/game/antagonist/outsider/ninja.dm b/code/game/antagonist/outsider/ninja.dm index 5af82ff05d..a29cfc44fa 100644 --- a/code/game/antagonist/outsider/ninja.dm +++ b/code/game/antagonist/outsider/ninja.dm @@ -11,6 +11,7 @@ var/datum/antagonist/ninja/ninjas flags = ANTAG_OVERRIDE_JOB | ANTAG_CLEAR_EQUIPMENT | ANTAG_CHOOSE_NAME | ANTAG_RANDSPAWN | ANTAG_VOTABLE | ANTAG_SET_APPEARANCE max_antags = 1 max_antags_round = 1 + id_type = /obj/item/weapon/card/id/syndicate /datum/antagonist/ninja/New() ..() @@ -101,18 +102,15 @@ var/datum/antagonist/ninja/ninjas player.equip_to_slot_or_del(R, slot_l_ear) player.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(player), slot_w_uniform) player.equip_to_slot_or_del(new /obj/item/device/flashlight(player), slot_belt) - var/obj/item/weapon/rig/light/ninja/ninjasuit = new(player) + create_id("Infiltrator", player) + + var/obj/item/weapon/rig/light/ninja/ninjasuit = new(get_turf(player)) + ninjasuit.seal_delay = 0 + player.put_in_hands(ninjasuit) player.equip_to_slot_or_del(ninjasuit,slot_back) - if(ninjasuit) - // Make sure the ninja can actually equip the suit. - if(player.dna && player.dna.unique_enzymes) - ninjasuit.locked_dna = player.dna.unique_enzymes - player << "Suit hardware locked to your DNA hash." - else - ninjasuit.req_access = list() - ninjasuit.toggle_seals(src,1) + ninjasuit.seal_delay = initial(ninjasuit.seal_delay) if(istype(player.back,/obj/item/weapon/rig)) var/obj/item/weapon/rig/rig = player.back diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index 8b039a580a..e1a768f7f8 100755 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -26,7 +26,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station icon = 'icons/turf/areas.dmi' icon_state = "unknown" layer = 10 - luminosity = 1 + luminosity = 0 mouse_opacity = 0 var/lightswitch = 1 @@ -518,6 +518,7 @@ area/space/atmosalert() name = "\improper Wizard's Den" icon_state = "yellow" requires_power = 0 + lighting_use_dynamic = 0 /area/skipjack_station/transit diff --git a/code/game/gamemodes/cult/cultify/obj.dm b/code/game/gamemodes/cult/cultify/obj.dm index 4306182eaf..405ea6b29c 100644 --- a/code/game/gamemodes/cult/cultify/obj.dm +++ b/code/game/gamemodes/cult/cultify/obj.dm @@ -63,19 +63,10 @@ ..() /obj/machinery/door/cultify() - icon_state = "null" - density = 0 - c_animation = new /atom/movable/overlay(src.loc) - c_animation.name = "cultification" - c_animation.density = 0 - c_animation.anchored = 1 - c_animation.icon = 'icons/effects/effects.dmi' - c_animation.layer = 5 - c_animation.master = src.loc - c_animation.icon_state = "breakdoor" - flick("cultification",c_animation) - spawn(10) - qdel(c_animation) + if(invisibility != INVISIBILITY_MAXIMUM) + invisibility = INVISIBILITY_MAXIMUM + density = 0 + anim(target = src, a_icon = 'icons/effects/effects.dmi', a_icon_state = "breakdoor", sleeptime = 10) qdel(src) /obj/machinery/door/firedoor/cultify() diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index 32e75ea50b..0e26be38a8 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -474,19 +474,23 @@ var/list/turret_icons if(!L) return TURRET_NOT_TARGET - // If emagged not even the dead get a rest - if(emagged) - return L.stat ? TURRET_SECONDARY_TARGET : TURRET_PRIORITY_TARGET - - if(issilicon(L)) // Don't target silica + if(!emagged && issilicon(L)) // Don't target silica return TURRET_NOT_TARGET - if(L.stat) //if the perp is dead/dying, no need to bother really + if(L.stat && !emagged) //if the perp is dead/dying, no need to bother really return TURRET_NOT_TARGET //move onto next potential victim! - var/dst = get_dist(src, L) //if it's too far away, why bother? - if(dst > 7) - return 0 + if(get_dist(src, L) > 7) //if it's too far away, why bother? + return TURRET_NOT_TARGET + + if(!check_trajectory(L, src)) //check if we have true line of sight + return TURRET_NOT_TARGET + + if(emagged) // If emagged not even the dead get a rest + return L.stat ? TURRET_SECONDARY_TARGET : TURRET_PRIORITY_TARGET + + if(lethal && locate(/mob/living/silicon/ai) in get_turf(L)) //don't accidentally kill the AI! + return TURRET_NOT_TARGET if(check_synth) //If it's set to attack all non-silicons, target them! if(L.lying) @@ -498,6 +502,7 @@ var/list/turret_icons if(isanimal(L) || issmall(L)) // Animals are not so dangerous return check_anomalies ? TURRET_SECONDARY_TARGET : TURRET_NOT_TARGET + if(isxenomorph(L) || isalien(L)) // Xenos are dangerous return check_anomalies ? TURRET_PRIORITY_TARGET : TURRET_NOT_TARGET @@ -605,7 +610,6 @@ var/list/turret_icons if(!raised) //the turret has to be raised in order to fire - makes sense, right? return - update_icon() var/obj/item/projectile/A if(emagged || lethal) diff --git a/code/game/machinery/wall_frames.dm b/code/game/machinery/wall_frames.dm index 60867d1c2a..b7f98667dc 100644 --- a/code/game/machinery/wall_frames.dm +++ b/code/game/machinery/wall_frames.dm @@ -7,6 +7,7 @@ var/build_machine_type var/refund_amt = 2 var/refund_type = /obj/item/stack/material/steel + var/reverse = 0 //if resulting object faces opposite its dir (like light fixtures) /obj/item/frame/attackby(obj/item/weapon/W as obj, mob/user as mob) if (istype(W, /obj/item/weapon/wrench)) @@ -22,7 +23,12 @@ if (get_dist(on_wall,usr)>1) return - var/ndir = get_dir(on_wall,usr) + var/ndir + if(reverse) + ndir = get_dir(usr,on_wall) + else + ndir = get_dir(on_wall,usr) + if (!(ndir in cardinal)) return @@ -61,6 +67,7 @@ icon = 'icons/obj/lighting.dmi' icon_state = "tube-construct-item" build_machine_type = /obj/machinery/light_construct + reverse = 1 /obj/item/frame/light/small name = "small light fixture frame" diff --git a/code/game/objects/effects/chem/chemsmoke.dm b/code/game/objects/effects/chem/chemsmoke.dm index c579bd5317..3fa93e7e46 100644 --- a/code/game/objects/effects/chem/chemsmoke.dm +++ b/code/game/objects/effects/chem/chemsmoke.dm @@ -55,8 +55,10 @@ targetTurfs = new() - for(var/turf/T in view(range, location)) //build affected area list - if(cheap_pythag(T.x - location.x, T.y - location.y) <= range) //cull turfs to circle + //build affected area list + for(var/turf/T in view(range, location)) + //cull turfs to circle + if(sqrt((T.x - location.x)**2 + (T.y - location.y)**2) <= range) targetTurfs += T wallList = new() diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm index 6ad69f099b..1b32185ace 100644 --- a/code/game/objects/explosion.dm +++ b/code/game/objects/explosion.dm @@ -1,11 +1,5 @@ //TODO: Flash range does nothing currently -//A very crude linear approximatiaon of pythagoras theorem. -/proc/cheap_pythag(var/dx, var/dy) - dx = abs(dx); dy = abs(dy); - if(dx>=dy) return dx + (0.5*dy) //The longest side add half the shortest side approximates the hypotenuse - else return dy + (0.5*dx) - ///// Z-Level Stuff proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, z_transfer = 1) ///// Z-Level Stuff diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index d39d0e187e..9420704559 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -71,6 +71,8 @@ if(ismob(loc)) var/mob/m = loc m.unEquip(src, 1) + m.update_inv_r_hand() + m.update_inv_l_hand() return ..() /obj/item/device diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm index 6b6e0edc4e..8f9fa27093 100644 --- a/code/game/objects/items/devices/flash.dm +++ b/code/game/objects/items/devices/flash.dm @@ -2,9 +2,9 @@ name = "flash" desc = "Used for blinding and being an asshole." icon_state = "flash" - item_state = "flash" + item_state = "flashtool" throwforce = 5 - w_class = 2.0 + w_class = 2 throw_speed = 4 throw_range = 10 flags = CONDUCT diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 3b1e18f851..62d31185db 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -141,7 +141,11 @@ desc = "There are 0 caps left. Looks almost like the real thing! Ages 8 and up. Please recycle in an autolathe when you're out of caps!" icon = 'icons/obj/gun.dmi' icon_state = "revolver" - item_state = "gun" + item_state = "revolver" + item_icons = list( + icon_l_hand = 'icons/mob/items/lefthand_guns.dmi', + icon_r_hand = 'icons/mob/items/righthand_guns.dmi', + ) flags = CONDUCT slot_flags = SLOT_BELT|SLOT_HOLSTER w_class = 3.0 @@ -220,6 +224,10 @@ icon = 'icons/obj/gun.dmi' icon_state = "crossbow" item_state = "crossbow" + item_icons = list( + icon_l_hand = 'icons/mob/items/lefthand_guns.dmi', + icon_r_hand = 'icons/mob/items/righthand_guns.dmi', + ) w_class = 2.0 attack_verb = list("attacked", "struck", "hit") var/bullets = 5 diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm index 245f9201a0..2941e617fd 100644 --- a/code/game/objects/items/weapons/RCD.dm +++ b/code/game/objects/items/weapons/RCD.dm @@ -155,9 +155,7 @@ icon = 'icons/obj/ammo.dmi' icon_state = "rcd" item_state = "rcdammo" - opacity = 0 - density = 0 - anchored = 0.0 + w_class = 2 origin_tech = list(TECH_MATERIAL = 2) matter = list(DEFAULT_WALL_MATERIAL = 30000,"glass" = 15000) @@ -182,7 +180,7 @@ /obj/item/weapon/rcd/mounted/useResource(var/amount, var/mob/user) - var/cost = amount*30 + var/cost = amount*130 //so that a rig with default powercell can build ~2.5x the stuff a fully-loaded RCD can. if(istype(loc,/obj/item/rig_module)) var/obj/item/rig_module/module = loc if(module.holder && module.holder.cell) diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm index 95e1875d40..610536f4d0 100644 --- a/code/game/objects/items/weapons/grenades/chem_grenade.dm +++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm @@ -1,7 +1,7 @@ /obj/item/weapon/grenade/chem_grenade name = "grenade casing" icon_state = "chemg" - item_state = "flashbang" + item_state = "grenade" desc = "A hand made chemical grenade." w_class = 2.0 force = 2.0 diff --git a/code/game/objects/items/weapons/grenades/emgrenade.dm b/code/game/objects/items/weapons/grenades/emgrenade.dm index f8c2a12d2f..25e65f924d 100644 --- a/code/game/objects/items/weapons/grenades/emgrenade.dm +++ b/code/game/objects/items/weapons/grenades/emgrenade.dm @@ -1,7 +1,7 @@ /obj/item/weapon/grenade/empgrenade name = "classic emp grenade" icon_state = "emp" - item_state = "emp" + item_state = "empgrenade" origin_tech = list(TECH_MATERIAL = 2, TECH_MAGNET = 3) prime() diff --git a/code/game/objects/items/weapons/grenades/grenade.dm b/code/game/objects/items/weapons/grenades/grenade.dm index 1565d321b6..16d8a620f9 100644 --- a/code/game/objects/items/weapons/grenades/grenade.dm +++ b/code/game/objects/items/weapons/grenades/grenade.dm @@ -4,7 +4,7 @@ w_class = 2.0 icon = 'icons/obj/grenade.dmi' icon_state = "grenade" - item_state = "flashbang" + item_state = "grenade" throw_speed = 4 throw_range = 20 flags = CONDUCT diff --git a/code/game/objects/items/weapons/material/kitchen.dm b/code/game/objects/items/weapons/material/kitchen.dm index 78d8e3ad11..d0e81e9548 100644 --- a/code/game/objects/items/weapons/material/kitchen.dm +++ b/code/game/objects/items/weapons/material/kitchen.dm @@ -61,7 +61,7 @@ attack_verb = list("attacked", "poked") edge = 0 sharp = 0 - force_divisor = 0.25 //5 when wielded with weight 20 (steel) + force_divisor = 0.1 //2 when wielded with weight 20 (steel) /obj/item/weapon/material/kitchen/utensil/spoon/plastic default_material = "plastic" @@ -71,9 +71,9 @@ */ /obj/item/weapon/material/kitchen/utensil/knife name = "knife" - desc = "Can cut through any food." + desc = "A knife for eating with. Can cut through any food." icon_state = "knife" - force_divisor = 0.2 // 12 when wielded with hardness 60 (steel) + force_divisor = 0.1 // 6 when wielded with hardness 60 (steel) /obj/item/weapon/material/kitchen/utensil/knife/attack(target as mob, mob/living/user as mob) if ((CLUMSY in user.mutations) && prob(50)) @@ -100,7 +100,7 @@ name = "rolling pin" desc = "Used to knock out the Bartender." icon_state = "rolling_pin" - attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked") //I think the rollingpin attackby will end up ignoring this anyway. + attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked") default_material = "wood" force_divisor = 0.7 // 10 when wielded with weight 15 (wood) thrown_force_divisor = 1 // as above diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index bdbb7d3f4c..bee9c69485 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -29,6 +29,7 @@ var/holy = 0 var/dynamic_lighting = 1 + luminosity = 1 /turf/New() ..() @@ -37,7 +38,6 @@ src.Entered(AM) return turfs |= src - return /turf/Destroy() turfs -= src @@ -225,6 +225,7 @@ var/old_opacity = opacity var/old_dynamic_lighting = dynamic_lighting var/list/old_affecting_lights = affecting_lights + var/old_lighting_overlay = lighting_overlay //world << "Replacing [src.type] with [N]" @@ -276,6 +277,7 @@ W.levelupdate() . = W + lighting_overlay = old_lighting_overlay affecting_lights = old_affecting_lights if((old_opacity != opacity) || (dynamic_lighting != old_dynamic_lighting) || force_lighting_update) reconsider_lights() diff --git a/code/game/turfs/turf_flick_animations.dm b/code/game/turfs/turf_flick_animations.dm index b1bccd51bc..9bcd5caaa9 100644 --- a/code/game/turfs/turf_flick_animations.dm +++ b/code/game/turfs/turf_flick_animations.dm @@ -19,3 +19,24 @@ if(c_animation) qdel(c_animation) c_animation = null + +proc/anim(turf/location as turf,target as mob|obj,a_icon,a_icon_state as text,flick_anim as text,sleeptime = 0,direction as num) +//This proc throws up either an icon or an animation for a specified amount of time. +//The variables should be apparent enough. + if(!location && target) + location = get_turf(target) + if(location && !target) + target = location + var/atom/movable/overlay/animation = PoolOrNew(/atom/movable/overlay, location) + if(direction) + animation.set_dir(direction) + animation.icon = a_icon + animation.layer = target:layer+1 + if(a_icon_state) + animation.icon_state = a_icon_state + else + animation.icon_state = "blank" + animation.master = target + flick(flick_anim, animation) + spawn(max(sleeptime, 15)) + qdel(animation) diff --git a/code/modules/clothing/spacesuits/rig/modules/ninja.dm b/code/modules/clothing/spacesuits/rig/modules/ninja.dm index 8b4a30d389..3d61048563 100644 --- a/code/modules/clothing/spacesuits/rig/modules/ninja.dm +++ b/code/modules/clothing/spacesuits/rig/modules/ninja.dm @@ -115,6 +115,10 @@ H << "You cannot teleport into solid walls." return 0 + if(T.z in config.admin_levels) + H << "You cannot use your teleporter on this Z-level." + return 0 + phase_out(H,get_turf(H)) H.loc = T phase_in(H,get_turf(H)) diff --git a/code/modules/clothing/spacesuits/rig/rig.dm b/code/modules/clothing/spacesuits/rig/rig.dm index 8fc7ce9cb7..83b2be5413 100644 --- a/code/modules/clothing/spacesuits/rig/rig.dm +++ b/code/modules/clothing/spacesuits/rig/rig.dm @@ -64,8 +64,8 @@ var/malfunction_delay = 0 var/electrified = 0 var/locked_down = 0 - var/locked_dna = null + var/seal_delay = SEAL_DELAY var/sealing // Keeps track of seal status independantly of canremove. var/offline = 1 // Should we be applying suit maluses? var/offline_slowdown = 3 // If the suit is deployed and unpowered, it sets slowdown to this. @@ -205,7 +205,7 @@ if(!instant) M.visible_message("[M]'s suit emits a quiet hum as it begins to adjust its seals.","With a quiet hum, the suit begins running checks and adjusting components.") - if(!do_after(M,SEAL_DELAY)) + if(seal_delay && !do_after(M,seal_delay)) if(M) M << "You must remain still while the suit is adjusting the components." failed_to_seal = 1 @@ -229,9 +229,8 @@ if(!failed_to_seal && M.back == src && piece == compare_piece) - if(!instant) - if(!do_after(M,SEAL_DELAY,needhand=0)) - failed_to_seal = 1 + if(seal_delay && !instant && !do_after(M,seal_delay,needhand=0)) + failed_to_seal = 1 piece.icon_state = "[initial(icon_state)][!seal_target ? "_sealed" : ""]" switch(msg_type) @@ -500,10 +499,6 @@ return 0 if(user.back != src) return 0 - if(locked_dna) - if(!user.dna || user.dna.unique_enzymes != locked_dna) - user << "DNA scan mismatch. Access denied." - return 0 else if(!src.allowed(user)) user << "Unauthorized user. Access denied." return 0 @@ -563,10 +558,9 @@ /obj/item/weapon/rig/equipped(mob/living/carbon/human/M) ..() - if(istype(M) && M.back == src) + if(seal_delay > 0 && istype(M) && M.back == src) M.visible_message("[M] starts putting on \the [src]...", "You start putting on \the [src]...") - - if(!do_after(M,SEAL_DELAY)) + if(!do_after(M,seal_delay)) if(M && M.back == src) M.back = null M.drop_from_inventory(src) diff --git a/code/modules/customitems/item_spawning.dm b/code/modules/customitems/item_spawning.dm index b6a8cac9f1..c99fe6936d 100644 --- a/code/modules/customitems/item_spawning.dm +++ b/code/modules/customitems/item_spawning.dm @@ -20,6 +20,7 @@ /datum/custom_item var/assoc_key var/character_name + var/inherit_inhands = 1 //if unset, and inhands are not provided, then the inhand overlays will be invisible. var/item_icon var/item_desc var/name @@ -44,9 +45,20 @@ if(item_desc) item.desc = item_desc if(item_icon) - item.icon = CUSTOM_ITEM_OBJ - item.icon_state = item_icon - if(istype(item, /obj/item)) + if(!istype(item)) + item.icon = CUSTOM_ITEM_OBJ + item.icon_state = item_icon + return + else + if(inherit_inhands) + apply_inherit_inhands(item) + else + item.item_state_slots = null + item.item_icons = null + + item.icon = CUSTOM_ITEM_OBJ + item.icon_state = item_icon + item.item_state = null item.icon_override = CUSTOM_ITEM_MOB // Kits are dumb so this is going to have to be hardcoded/snowflake. @@ -66,6 +78,48 @@ return item +/datum/custom_item/proc/apply_inherit_inhands(var/obj/item/item) + var/list/new_item_icons = list() + var/list/new_item_state_slots = list() + + var/list/available_states = icon_states(CUSTOM_ITEM_MOB) + + //If l_hand or r_hand are not present, preserve them using item_icons/item_state_slots + //Then use icon_override to make every other slot use the custom sprites by default. + //This has to be done before we touch any of item's vars + if(!("[item_icon]_l" in available_states)) + new_item_state_slots[slot_l_hand_str] = get_state(item, slot_l_hand_str, "_l") + new_item_icons[slot_l_hand_str] = get_icon(item, slot_l_hand_str, 'icons/mob/items/lefthand.dmi') + if(!("[item_icon]_r" in available_states)) + new_item_state_slots[slot_r_hand_str] = get_state(item, slot_r_hand_str, "_r") + new_item_icons[slot_r_hand_str] = get_icon(item, slot_r_hand_str, 'icons/mob/items/righthand.dmi') + + item.item_state_slots = new_item_state_slots + item.item_icons = new_item_icons + +//this has to mirror the way update_inv_*_hand() selects the state +/datum/custom_item/proc/get_state(var/obj/item/item, var/slot_str, var/hand_str) + var/t_state + if(item.item_state_slots && item.item_state_slots[slot_str]) + t_state = item.item_state_slots[slot_str] + else if(item.item_state) + t_state = item.item_state + else + t_state = item.icon_state + if(item.icon_override) + t_state += hand_str + return t_state + +//this has to mirror the way update_inv_*_hand() selects the icon +/datum/custom_item/proc/get_icon(var/obj/item/item, var/slot_str, var/icon/hand_icon) + var/icon/t_icon + if(item.icon_override) + t_icon = item.icon_override + else if(item.item_icons && (slot_str in item.item_icons)) + t_icon = item.item_icons[slot_str] + else + t_icon = hand_icon + return t_icon // Parses the config file into the custom_items list. /hook/startup/proc/load_custom_items() @@ -107,6 +161,8 @@ current_data.name = field_data if("item_icon") current_data.item_icon = field_data + if("inherit_inhands") + current_data.inherit_inhands = text2num(field_data) if("item_desc") current_data.item_desc = field_data if("req_access") diff --git a/code/modules/lighting/_lighting_defs.dm b/code/modules/lighting/_lighting_defs.dm index a913c97e21..57e6cc22d2 100644 --- a/code/modules/lighting/_lighting_defs.dm +++ b/code/modules/lighting/_lighting_defs.dm @@ -4,7 +4,7 @@ #define LIGHTING_LAMBERTIAN 1 // use lambertian shading for light sources #define LIGHTING_HEIGHT 1 // height off the ground of light sources on the pseudo-z-axis, you should probably leave this alone #define LIGHTING_TRANSITIONS 1 // smooth, animated transitions, similar to /tg/station +#define LIGHTING_ROUND_VALUE (1 / 128) //Value used to round lumcounts, values smaller than 1/255 don't matter (if they do, thanks sinking points), greater values will make lighting less precise, but in turn increase performance, VERY SLIGHTLY. -#define LIGHTING_RESOLUTION 1 // resolution of the lighting overlays, powers of 2 only, max of 32 #define LIGHTING_LAYER 10 // drawing layer for lighting overlays #define LIGHTING_ICON 'icons/effects/lighting_overlay.dmi' // icon used for lighting shading effects diff --git a/code/modules/lighting/light_source.dm b/code/modules/lighting/light_source.dm index 1897272118..a71550268c 100644 --- a/code/modules/lighting/light_source.dm +++ b/code/modules/lighting/light_source.dm @@ -60,13 +60,16 @@ if(top_atom != source_atom) if(!top_atom.light_sources) top_atom.light_sources = list() top_atom.light_sources += src - lighting_update_lights += src - needs_update = 1 + + if(!needs_update) + lighting_update_lights += src + needs_update = 1 /datum/light_source/proc/force_update() - needs_update = 1 force_update = 1 - lighting_update_lights += src + if(!needs_update) + lighting_update_lights += src + needs_update = 1 /datum/light_source/proc/check() if(!source_atom || !light_range || !light_power) @@ -113,11 +116,7 @@ /datum/light_source/proc/falloff(atom/movable/lighting_overlay/O) #if LIGHTING_FALLOFF == 1 // circular - #if LIGHTING_RESOLUTION == 1 . = (O.x - source_turf.x)**2 + (O.y - source_turf.y)**2 + LIGHTING_HEIGHT - #else - . = (O.x - source_turf.x + O.xoffset)**2 + (O.y - source_turf.y + O.yoffset)**2 + LIGHTING_HEIGHT - #endif #if LIGHTING_LAMBERTIAN == 1 . = CLAMP01((1 - CLAMP01(sqrt(.) / light_range)) * (1 / (sqrt(. + 1)))) @@ -126,11 +125,7 @@ #endif #elif LIGHTING_FALLOFF == 2 // square - #if LIGHTING_RESOLUTION == 1 . = abs(O.x - source_turf.x) + abs(O.y - source_turf.y) + LIGHTING_HEIGHT - #else - . = abs(O.x - source_turf.x + O.xoffset) + abs(O.y - source_turf.y + O.yoffset) + LIGHTING_HEIGHT - #endif #if LIGHTING_LAMBERTIAN == 1 . = CLAMP01((1 - CLAMP01(. / light_range)) * (1 / (sqrt(.)**2 + ))) @@ -142,26 +137,36 @@ /datum/light_source/proc/apply_lum() applied = 1 if(istype(source_turf)) - for(var/atom/movable/lighting_overlay/O in view(light_range, source_turf)) - var/strength = light_power * falloff(O) + for(var/turf/T in dview(light_range, source_turf, INVISIBILITY_LIGHTING)) + if(T.lighting_overlay) + var/strength = light_power * falloff(T.lighting_overlay) + if(!strength) //Don't add turfs that aren't affected to the affected turfs. + continue - effect_r[O] = lum_r * strength - effect_g[O] = lum_g * strength - effect_b[O] = lum_b * strength + effect_r[T.lighting_overlay] = round(lum_r * strength, LIGHTING_ROUND_VALUE) + effect_g[T.lighting_overlay] = round(lum_g * strength, LIGHTING_ROUND_VALUE) + effect_b[T.lighting_overlay] = round(lum_b * strength, LIGHTING_ROUND_VALUE) + + T.lighting_overlay.update_lumcount( + round(lum_r * strength, LIGHTING_ROUND_VALUE), + round(lum_g * strength, LIGHTING_ROUND_VALUE), + round(lum_b * strength, LIGHTING_ROUND_VALUE) + ) + + if(!T.affecting_lights) + T.affecting_lights = list() - O.update_lumcount(lum_r * strength, lum_g * strength, lum_b * strength) - for(var/turf/T in view(light_range, source_turf)) - if(!T.affecting_lights) T.affecting_lights = list() T.affecting_lights += src effect_turf += T /datum/light_source/proc/remove_lum() applied = 0 - for(var/atom/movable/lighting_overlay/O in effect_r) - O.update_lumcount(-effect_r[O], -effect_g[O], -effect_b[O]) - for(var/turf/T in effect_turf) - if(T.affecting_lights) T.affecting_lights -= src + if(T.affecting_lights) + T.affecting_lights -= src + + if(T.lighting_overlay) + T.lighting_overlay.update_lumcount(-effect_r[T.lighting_overlay], -effect_g[T.lighting_overlay], -effect_b[T.lighting_overlay]) effect_r.Cut() effect_g.Cut() diff --git a/code/modules/lighting/lighting_overlay.dm b/code/modules/lighting/lighting_overlay.dm index b75d8aec7f..a0bba14eeb 100644 --- a/code/modules/lighting/lighting_overlay.dm +++ b/code/modules/lighting/lighting_overlay.dm @@ -5,6 +5,7 @@ anchored = 1 icon = LIGHTING_ICON + icon_state = "light1" layer = LIGHTING_LAYER invisibility = INVISIBILITY_LIGHTING blend_mode = BLEND_MULTIPLY @@ -14,24 +15,42 @@ var/lum_g var/lum_b - #if LIGHTING_RESOLUTION != 1 - var/xoffset - var/yoffset - #endif - var/needs_update /atom/movable/lighting_overlay/New() . = ..() verbs.Cut() + var/turf/T = loc //If this runtimes atleast we'll know what's creating overlays in things that aren't turfs. + T.luminosity = 0 + /atom/movable/lighting_overlay/proc/update_lumcount(delta_r, delta_g, delta_b) + if(!delta_r && !delta_g && !delta_b) //Nothing is being changed all together. + return + + var/should_update = 0 + + if(!needs_update) //If this isn't true, we're already updating anyways. + if(max(lum_r, lum_g, lum_b) < 1) //Any change that could happen WILL change appearance. + should_update = 1 + + else if(max(lum_r + delta_r, lum_g + delta_g, lum_b + delta_b) < 1) //The change would bring us under 1 max lum, again, guaranteed to change appearance. + should_update = 1 + + else //We need to make sure that the colour ratios won't change in this code block. + var/mx1 = max(lum_r, lum_g, lum_b) + var/mx2 = max(lum_r + delta_r, lum_g + delta_g, lum_b + delta_b) + + if(lum_r / mx1 != (lum_r + delta_r) / mx2 || lum_g / mx1 != (lum_g + delta_g) / mx2 || lum_b / mx1 != (lum_b + delta_b) / mx2) //Stuff would change. + should_update = 1 + lum_r += delta_r lum_g += delta_g lum_b += delta_b - needs_update = 1 - lighting_update_overlays += src + if(!needs_update && should_update) + needs_update = 1 + lighting_update_overlays += src /atom/movable/lighting_overlay/proc/update_overlay() var/mx = max(lum_r, lum_g, lum_b) @@ -46,3 +65,43 @@ #else color = rgb(lum_r * 255 * ., lum_g * 255 * ., lum_b * 255 * .) #endif + + var/turf/T = loc + + if(istype(T)) //Incase we're not on a turf, pool ourselves, something happened. + if(color != "#000000") + T.luminosity = 1 + else //No light, set the turf's luminosity to 0 to remove it from view() + #if LIGHTING_TRANSITIONS == 1 + spawn(LIGHTING_INTERVAL - 1) + T.luminosity = 0 + #else + T.luminosity = 0 + #endif + + else + warning("A lighting overlay realised its loc was NOT a turf (actual loc: [loc][loc ? ", " + loc.type : ""]) in update_overlay() and got pooled!") + qdel(src) + +/atom/movable/lighting_overlay/ResetVars() + loc = null + + lum_r = 0 + lum_g = 0 + lum_b = 0 + + color = "#000000" + + needs_update = 0 + +/atom/movable/lighting_overlay/Destroy() + lighting_update_overlays -= src + + var/turf/T = loc + if(istype(T)) + T.lighting_overlay = null + + for(var/datum/light_source/D in T.affecting_lights) //Remove references to us on the light sources affecting us. + D.effect_r -= src + D.effect_g -= src + D.effect_b -= src diff --git a/code/modules/lighting/lighting_process.dm b/code/modules/lighting/lighting_process.dm index 28e1f1fa5e..1571c6e388 100644 --- a/code/modules/lighting/lighting_process.dm +++ b/code/modules/lighting/lighting_process.dm @@ -1,27 +1,31 @@ -/datum/controller/process/lighting/setup() - name = "lighting" - schedule_interval = LIGHTING_INTERVAL - - create_lighting_overlays() - -/datum/controller/process/lighting/doWork() - for(var/datum/light_source/L in lighting_update_lights) - if(L.needs_update) - if(L.destroyed || L.check() || L.force_update) - L.remove_lum() - if(!L.destroyed) L.apply_lum() - L.force_update = 0 - L.needs_update = 0 - - scheck() - - lighting_update_lights.Cut() - - for(var/atom/movable/lighting_overlay/O in lighting_update_overlays) - if(O.needs_update) - O.update_overlay() - O.needs_update = 0 - - scheck() - - lighting_update_overlays.Cut() +/datum/controller/process/lighting/setup() + name = "lighting" + schedule_interval = LIGHTING_INTERVAL + + create_lighting_overlays() + +/datum/controller/process/lighting/doWork() + var/list/lighting_update_lights_old = lighting_update_lights //We use a different list so any additions to the update lists during a delay from scheck() don't cause things to be cut from the list without being updated. + lighting_update_lights = null //Nulling it first because of http://www.byond.com/forum/?post=1854520 + lighting_update_lights = list() + + for(var/datum/light_source/L in lighting_update_lights_old) + if(L.needs_update) + if(L.destroyed || L.check() || L.force_update) + L.remove_lum() + if(!L.destroyed) L.apply_lum() + L.force_update = 0 + L.needs_update = 0 + + scheck() + + var/list/lighting_update_overlays_old = lighting_update_overlays //Same as above. + lighting_update_overlays = null //Same as above + lighting_update_overlays = list() + + for(var/atom/movable/lighting_overlay/O in lighting_update_overlays_old) + if(O.needs_update) + O.update_overlay() + O.needs_update = 0 + + scheck() diff --git a/code/modules/lighting/lighting_system.dm b/code/modules/lighting/lighting_system.dm index 6177c81f8f..0c84294f35 100644 --- a/code/modules/lighting/lighting_system.dm +++ b/code/modules/lighting/lighting_system.dm @@ -5,26 +5,15 @@ // duplicates lots of code, but this proc needs to be as fast as possible. /proc/create_lighting_overlays(zlevel = 0) - var/state = "light[LIGHTING_RESOLUTION]" var/area/A if(zlevel == 0) // populate all zlevels for(var/turf/T in world) if(T.dynamic_lighting) A = T.loc if(A.lighting_use_dynamic) - #if LIGHTING_RESOLUTION == 1 - var/atom/movable/lighting_overlay/O = new(T) - O.icon_state = state - #else - for(var/i = 0; i < LIGHTING_RESOLUTION; i++) - for(var/j = 0; j < LIGHTING_RESOLUTION; j++) - var/atom/movable/lighting_overlay/O = new(T) - O.pixel_x = i * (32 / LIGHTING_RESOLUTION) - O.pixel_y = j * (32 / LIGHTING_RESOLUTION) - O.xoffset = (((2*i + 1) / (LIGHTING_RESOLUTION * 2)) - 0.5) - O.yoffset = (((2*j + 1) / (LIGHTING_RESOLUTION * 2)) - 0.5) - O.icon_state = state - #endif + var/atom/movable/lighting_overlay/O = PoolOrNew(/atom/movable/lighting_overlay, T) + T.lighting_overlay = O + else for(var/x = 1; x <= world.maxx; x++) for(var/y = 1; y <= world.maxy; y++) @@ -32,16 +21,5 @@ if(T.dynamic_lighting) A = T.loc if(A.lighting_use_dynamic) - #if LIGHTING_RESOLUTION == 1 - var/atom/movable/lighting_overlay/O = new(T) - O.icon_state = state - #else - for(var/i = 0; i < LIGHTING_RESOLUTION; i++) - for(var/j = 0; j < LIGHTING_RESOLUTION; j++) - var/atom/movable/lighting_overlay/O = new(T) - O.pixel_x = i * (32 / LIGHTING_RESOLUTION) - O.pixel_y = j * (32 / LIGHTING_RESOLUTION) - O.xoffset = (((2*i + 1) / (LIGHTING_RESOLUTION * 2)) - 0.5) - O.yoffset = (((2*j + 1) / (LIGHTING_RESOLUTION * 2)) - 0.5) - O.icon_state = state - #endif + var/atom/movable/lighting_overlay/O = PoolOrNew(/atom/movable/lighting_overlay, T) + T.lighting_overlay = O diff --git a/code/modules/lighting/lighting_turf.dm b/code/modules/lighting/lighting_turf.dm index 266e4b1d79..0a438b047c 100644 --- a/code/modules/lighting/lighting_turf.dm +++ b/code/modules/lighting/lighting_turf.dm @@ -1,29 +1,18 @@ /turf var/list/affecting_lights + var/atom/movable/lighting_overlay/lighting_overlay /turf/proc/reconsider_lights() for(var/datum/light_source/L in affecting_lights) L.force_update() /turf/proc/lighting_clear_overlays() - for(var/atom/movable/lighting_overlay/L in src) - L.loc = null + if(lighting_overlay) + qdel(lighting_overlay) /turf/proc/lighting_build_overlays() - if(!locate(/atom/movable/lighting_overlay) in src) - var/state = "light[LIGHTING_RESOLUTION]" + if(!lighting_overlay) var/area/A = loc if(A.lighting_use_dynamic) - #if LIGHTING_RESOLUTION == 1 - var/atom/movable/lighting_overlay/O = new(src) - O.icon_state = state - #else - for(var/i = 0; i < LIGHTING_RESOLUTION; i++) - for(var/j = 0; j < LIGHTING_RESOLUTION; j++) - var/atom/movable/lighting_overlay/O = new(src) - O.pixel_x = i * (32 / LIGHTING_RESOLUTION) - O.pixel_y = j * (32 / LIGHTING_RESOLUTION) - O.xoffset = (((2*i + 1) / (LIGHTING_RESOLUTION * 2)) - 0.5) - O.yoffset = (((2*j + 1) / (LIGHTING_RESOLUTION * 2)) - 0.5) - O.icon_state = state - #endif + var/atom/movable/lighting_overlay/O = PoolOrNew(/atom/movable/lighting_overlay, src) + lighting_overlay = O diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm index c414f50cec..390d4f1601 100644 --- a/code/modules/mining/mine_turfs.dm +++ b/code/modules/mining/mine_turfs.dm @@ -340,8 +340,8 @@ R.amount = rand(5,25) if(2) - var/obj/item/stack/tile/R = new(src) - R.amount = rand(1,5) + var/obj/item/stack/material/plasteel/R = new(src) + R.amount = rand(5,25) if(3) var/obj/item/stack/material/steel/R = new(src) diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index f9c1779547..dfbfaa1673 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -852,11 +852,11 @@ var/global/list/damage_icon_parts = list() //determine icon to use var/icon/t_icon - if(r_hand.icon_override) + if(r_hand.item_icons && (slot_r_hand_str in r_hand.item_icons)) + t_icon = r_hand.item_icons[slot_r_hand_str] + else if(r_hand.icon_override) t_state += "_r" t_icon = r_hand.icon_override - else if(r_hand.item_icons && (slot_r_hand_str in r_hand.item_icons)) - t_icon = r_hand.item_icons[slot_r_hand_str] else t_icon = INV_R_HAND_DEF_ICON @@ -884,11 +884,11 @@ var/global/list/damage_icon_parts = list() //determine icon to use var/icon/t_icon - if(l_hand.icon_override) + if(l_hand.item_icons && (slot_l_hand_str in l_hand.item_icons)) + t_icon = l_hand.item_icons[slot_l_hand_str] + else if(l_hand.icon_override) t_state += "_l" t_icon = l_hand.icon_override - else if(l_hand.item_icons && (slot_l_hand_str in l_hand.item_icons)) - t_icon = l_hand.item_icons[slot_l_hand_str] else t_icon = INV_L_HAND_DEF_ICON diff --git a/code/modules/mob/living/carbon/metroid/life.dm b/code/modules/mob/living/carbon/metroid/life.dm index 21f5302f2a..7e487269aa 100644 --- a/code/modules/mob/living/carbon/metroid/life.dm +++ b/code/modules/mob/living/carbon/metroid/life.dm @@ -200,9 +200,12 @@ if(hungry == 2 && !client) // if a slime is starving, it starts losing its friends if(Friends.len > 0 && prob(1)) var/mob/nofriend = pick(Friends) - --Friends[nofriend] - if (Friends[nofriend] <= 0) - Friends -= nofriend + if(nofriend && Friends[nofriend]) + Friends[nofriend] -= 1 + if (Friends[nofriend] <= 0) + Friends[nofriend] = null + Friends -= nofriend + Friends -= null if(!Target) if(will_hunt(hungry) || attacked || rabid) // Only add to the list if we need to diff --git a/code/modules/mob/living/carbon/metroid/powers.dm b/code/modules/mob/living/carbon/metroid/powers.dm index b5fd583ade..8b8e875aec 100644 --- a/code/modules/mob/living/carbon/metroid/powers.dm +++ b/code/modules/mob/living/carbon/metroid/powers.dm @@ -21,7 +21,7 @@ return "I cannot feed on other slimes..." if (!Adjacent(M)) return "This subject is too far away..." - if (istype(M, /mob/living/carbon) && M.getCloneLoss() > 150 || istype(M, /mob/living/simple_animal) && M.stat == DEAD) + if (istype(M, /mob/living/carbon) && M.getCloneLoss() >= M.maxHealth * 1.5 || istype(M, /mob/living/simple_animal) && M.stat == DEAD) return "This subject does not have an edible life energy..." for(var/mob/living/carbon/slime/met in view()) if(met.Victim == M && met != src) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index c8d34a62f8..2a64304401 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -215,7 +215,7 @@ return /mob/living/proc/adjust_fire_stacks(add_fire_stacks) //Adjusting the amount of fire_stacks we have on person - fire_stacks = Clamp(fire_stacks + add_fire_stacks, min = FIRE_MIN_STACKS, max = FIRE_MAX_STACKS) + fire_stacks = Clamp(fire_stacks + add_fire_stacks, FIRE_MIN_STACKS, FIRE_MAX_STACKS) /mob/living/proc/handle_fire() if(fire_stacks < 0) diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 8e29e21008..405386a827 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -212,6 +212,7 @@ /mob/living/simple_animal/hostile/proc/check_horde() + return 0 if(emergency_shuttle.shuttle.location) if(!enroute && !target_mob) //The shuttle docked, all monsters rush for the escape hallway if(!shuttletarget && escape_list.len) //Make sure we didn't already assign it a target, and that there are targets to pick diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index 9da1030225..ad4021adf3 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -1,6 +1,12 @@ /**************************************************** EXTERNAL ORGANS ****************************************************/ + +//These control the damage thresholds for the various ways of removing limbs +#define DROPLIMB_THRESHOLD_EDGE 5 +#define DROPLIMB_THRESHOLD_TEAROFF 2 +#define DROPLIMB_THRESHOLD_DESTROY 1 + /obj/item/organ/external name = "external" min_broken_damage = 30 @@ -233,6 +239,7 @@ //If we can't inflict the full amount of damage, spread the damage in other ways //How much damage can we actually cause? var/can_inflict = max_damage * config.organ_health_multiplier - (brute_dam + burn_dam) + var/spillover = 0 if(can_inflict) if (brute > 0) //Inflict all burte damage we can @@ -244,16 +251,17 @@ //How much mroe damage can we inflict can_inflict = max(0, can_inflict - brute) //How much brute damage is left to inflict - brute = max(0, brute - temp) + spillover += max(0, brute - temp) if (burn > 0 && can_inflict) //Inflict all burn damage we can createwound(BURN, min(burn,can_inflict)) //How much burn damage is left to inflict - burn = max(0, burn - can_inflict) + spillover += max(0, burn - can_inflict) + //If there are still hurties to dispense - if (burn || brute) - owner.shock_stage += (brute+burn) * config.organ_damage_spillover_multiplier + if (spillover) + owner.shock_stage += spillover * config.organ_damage_spillover_multiplier // sync the organ's damage with its wounds src.update_damages() @@ -262,26 +270,30 @@ //If limb took enough damage, try to cut or tear it off if(owner && loc == owner) if(!cannot_amputate && config.limbs_can_break && (brute_dam + burn_dam) >= (max_damage * config.organ_health_multiplier)) - var/threshold = max_damage - var/dropped - if((burn >= threshold) && prob(burn/3)) - dropped = 1 - droplimb(0,DROPLIMB_BURN) - if(!dropped && prob(brute)) - var/edge_eligible = 0 - if(edge) - if(istype(used_weapon,/obj/item)) - var/obj/item/W = used_weapon - if(W.w_class >= w_class) - edge_eligible = 1 - else + //organs can come off in three cases + //1. If the damage source is edge_eligible and the brute damage dealt exceeds the edge threshold, then the organ is cut off. + //2. If the damage amount dealt exceeds the disintegrate threshold, the organ is completely obliterated. + //3. If the organ has already reached or would be put over it's max damage amount (currently redundant), + // and the brute damage dealt exceeds the tearoff threshold, the organ is torn off. + + //Check edge eligibility + var/edge_eligible = 0 + if(edge) + if(istype(used_weapon,/obj/item)) + var/obj/item/W = used_weapon + if(W.w_class >= w_class) edge_eligible = 1 + else + edge_eligible = 1 - if(brute >= threshold || (edge_eligible && brute >= threshold/3)) - if(edge) - droplimb(0,DROPLIMB_EDGE) - else - droplimb(0,DROPLIMB_BLUNT) + if(edge_eligible && brute >= max_damage / DROPLIMB_THRESHOLD_EDGE && prob(brute)) + droplimb(0, DROPLIMB_EDGE) + else if(burn >= max_damage / DROPLIMB_THRESHOLD_DESTROY && prob(burn/3)) + droplimb(0, DROPLIMB_BURN) + else if(brute >= max_damage / DROPLIMB_THRESHOLD_DESTROY && prob(brute)) + droplimb(0, DROPLIMB_BLUNT) + else if(brute >= max_damage / DROPLIMB_THRESHOLD_TEAROFF && prob(brute/3)) + droplimb(0, DROPLIMB_EDGE) return update_icon() @@ -709,11 +721,7 @@ Note that amputating the affected organ does in fact remove the infection from t wounds.Cut() if(parent) - var/datum/wound/W - if(clean || max_damage < 50) - W = new/datum/wound/lost_limb/small(max_damage/2) - else - W = new/datum/wound/lost_limb(max_damage) + var/datum/wound/lost_limb/W = new (src, disintegrate, clean) parent.children -= src if(clean) parent.wounds |= W @@ -752,7 +760,7 @@ Note that amputating the affected organ does in fact remove the infection from t I.loc = get_turf(src) qdel(src) if(DROPLIMB_BLUNT) - var/obj/effect/decal/cleanable/blood/gibs/gore = new owner.species.single_gib_type(get_turf(victim)) + var/obj/effect/decal/cleanable/blood/gibs/gore = new victim.species.single_gib_type(get_turf(victim)) if(victim.species.flesh_color) gore.fleshcolor = victim.species.flesh_color if(victim.species.blood_color) diff --git a/code/modules/organs/wound.dm b/code/modules/organs/wound.dm index 1d34ed7284..8f39b91555 100644 --- a/code/modules/organs/wound.dm +++ b/code/modules/organs/wound.dm @@ -315,12 +315,32 @@ datum/wound/cut/massive /** EXTERNAL ORGAN LOSS **/ /datum/wound/lost_limb - damage_type = CUT - stages = list("ripped stump" = 65, "bloody stump" = 50, "clotted stump" = 25, "scarred stump" = 0) - max_bleeding_stage = 3 - can_merge(var/datum/wound/other) - return 0 //cannot be merged +/datum/wound/lost_limb/New(var/obj/item/organ/external/lost_limb, var/losstype, var/clean) + var/damage_amt = lost_limb.max_damage + if(clean) damage_amt /= 2 + + switch(losstype) + if(DROPLIMB_EDGE, DROPLIMB_BLUNT) + damage_type = CUT + max_bleeding_stage = 3 + stages = list( + "ripped stump" = damage_amt*1.3, + "bloody stump" = damage_amt, + "clotted stump" = damage_amt*0.5, + "scarred stump" = 0 + ) + if(DROPLIMB_BURN) + damage_type = BURN + max_bleeding_stage = 1 + stages = list( + "ripped charred stump" = damage_amt*1.3, + "charred stump" = damage_amt, + "scarred stump" = damage_amt*0.5, + "scarred stump" = 0 + ) + + ..(damage_amt) -/datum/wound/lost_limb/small - stages = list("ripped hole" = 40, "bloody hole" = 30, "clotted hole" = 15, "scarred hole" = 0) +/datum/wound/lost_limb/can_merge(var/datum/wound/other) + return 0 //cannot be merged \ No newline at end of file diff --git a/code/modules/projectiles/effects.dm b/code/modules/projectiles/effects.dm index d765e353da..7874eeb383 100644 --- a/code/modules/projectiles/effects.dm +++ b/code/modules/projectiles/effects.dm @@ -11,8 +11,8 @@ if(istype(M)) transform = M -/obj/effect/projectile/proc/activate() - spawn(3) +/obj/effect/projectile/proc/activate(var/kill_delay = 3) + spawn(kill_delay) qdel(src) //see effect_system.dm - sets loc to null and lets GC handle removing these effects return diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index d7c14829d9..73ca2b7476 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -37,7 +37,7 @@ var/dispersion = 0.0 var/damage = 10 - var/damage_type = BRUTE //BRUTE, BURN, TOX, OXY, CLONE are the only things that should be in here + var/damage_type = BRUTE //BRUTE, BURN, TOX, OXY, CLONE, HALLOSS are the only things that should be in here var/nodamage = 0 //Determines if the projectile will skip any damage inflictions var/taser_effect = 0 //If set then the projectile will apply it's agony damage using stun_effect_act() to mobs it hits, and other damage will be ignored var/check_armour = "bullet" //Defines what armor to use when it hits things. Must be set to bullet, laser, energy,or bomb //Cael - bio and rad are also valid @@ -296,25 +296,26 @@ before_move() Move(location.return_turf()) - if(first_step) - muzzle_effect(effect_transform) - first_step = 0 - else - tracer_effect(effect_transform) - if(!bumped && !isturf(original)) if(loc == get_turf(original)) if(!(original in permutated)) if(Bump(original)) return + if(first_step) + muzzle_effect(effect_transform) + first_step = 0 + else if(!bumped) + tracer_effect(effect_transform) + if(!hitscan) sleep(step_delay) //add delay between movement iterations if it's not a hitscan weapon /obj/item/projectile/proc/process_step(first_step = 0) - + return /obj/item/projectile/proc/before_move() + return /obj/item/projectile/proc/setup_trajectory() // trajectory dispersion @@ -332,6 +333,8 @@ effect_transform.Scale(trajectory.return_hypotenuse(), 1) effect_transform.Turn(-trajectory.return_angle()) //no idea why this has to be inverted, but it works + transform = turn(transform, -(trajectory.return_angle() + 90)) //no idea why 90 needs to be added, but it works + /obj/item/projectile/proc/muzzle_effect(var/matrix/T) if(silenced) return @@ -353,7 +356,10 @@ P.set_transform(M) P.pixel_x = location.pixel_x P.pixel_y = location.pixel_y - P.activate() + if(!hitscan) + P.activate(step_delay) //if not a hitscan projectile, remove after a single delay + else + P.activate() /obj/item/projectile/proc/impact_effect(var/matrix/M) if(ispath(tracer_type)) @@ -379,7 +385,7 @@ return //cannot shoot yourself if(istype(A, /obj/item/projectile)) return - if(istype(A, /mob/living)) + if(istype(A, /mob/living) || istype(A, /obj/mecha) || istype(A, /obj/vehicle)) result = 2 //We hit someone, return 1! return result = 1 @@ -418,15 +424,14 @@ if(istype(M)) return 1 -/proc/check_trajectory(atom/target as mob, var/mob/living/user as mob, var/pass_flags=PASSTABLE|PASSGLASS|PASSGRILLE, flags=null) //Checks if you can hit them or not. - if(!istype(target) || !istype(user)) +/proc/check_trajectory(atom/target as mob|obj, atom/firer as mob|obj, var/pass_flags=PASSTABLE|PASSGLASS|PASSGRILLE, flags=null) //Checks if you can hit them or not. + if(!istype(target) || !istype(firer)) return 0 - var/obj/item/projectile/test/trace = new /obj/item/projectile/test(get_step_to(user,target)) //Making the test.... + var/obj/item/projectile/test/trace = new /obj/item/projectile/test(get_turf(firer)) //Making the test.... trace.target = target if(!isnull(flags)) trace.flags = flags //Set the flags... trace.pass_flags = pass_flags //And the pass flags to that of the real projectile... - trace.firer = user var/output = trace.process() //Test it! qdel(trace) //No need for it anymore return output //Send it back to the gun! diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index eb515298ef..8aa493404a 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -8,6 +8,7 @@ eyeblur = 4 var/frequency = 1 hitscan = 1 + invisibility = 101 //beam projectiles are invisible as they are rendered by the effect engine muzzle_type = /obj/effect/projectile/laser/muzzle tracer_type = /obj/effect/projectile/laser/tracer diff --git a/code/modules/projectiles/targeting.dm b/code/modules/projectiles/targeting.dm index 3bda5319d7..cc91ae0424 100644 --- a/code/modules/projectiles/targeting.dm +++ b/code/modules/projectiles/targeting.dm @@ -261,6 +261,7 @@ //These are called by the on-screen buttons, adjusting what the victim can and cannot do. /client/proc/add_gun_icons() + if(!usr) return 1 // This can runtime if someone manages to throw a gun out of their hand before the proc is called. screen += usr.item_use_icon screen += usr.gun_move_icon screen += usr.radio_use_icon diff --git a/code/modules/recycling/conveyor2.dm b/code/modules/recycling/conveyor2.dm index 2244e98bf1..32d6652e9d 100644 --- a/code/modules/recycling/conveyor2.dm +++ b/code/modules/recycling/conveyor2.dm @@ -95,8 +95,9 @@ // attack with item, place item on conveyor /obj/machinery/conveyor/attackby(var/obj/item/I, mob/user) if(isrobot(user)) return //Carn: fix for borgs dropping their modules on conveyor belts - user.drop_item() - if(I && I.loc) I.loc = src.loc + if(I.loc != user) return // This should stop mounted modules ending up outside the module. + + user.drop_item(src) return // attack with hand, move pulled object onto conveyor diff --git a/code/modules/tables/tables.dm b/code/modules/tables/tables.dm index 1ee34e9d80..11f2f033b7 100644 --- a/code/modules/tables/tables.dm +++ b/code/modules/tables/tables.dm @@ -176,6 +176,10 @@ user << "Plate \the [src] before reinforcing it!" return + if(flipped) + user << "Put \the [src] back in place before reinforcing it!" + return + reinforced = common_material_add(S, user, "reinforc") if(reinforced) update_desc() diff --git a/code/modules/vehicles/cargo_train.dm b/code/modules/vehicles/cargo_train.dm index b539dde039..c6ff870988 100644 --- a/code/modules/vehicles/cargo_train.dm +++ b/code/modules/vehicles/cargo_train.dm @@ -79,6 +79,13 @@ return ..() +//cargo trains are open topped, so there is a chance the projectile will hit the mob ridding the train instead +/obj/vehicle/train/cargo/bullet_act(var/obj/item/projectile/Proj) + if(buckled_mob && prob(70)) + buckled_mob.bullet_act(Proj) + return + ..() + /obj/vehicle/train/cargo/update_icon() if(open) icon_state = initial(icon_state) + "_open" diff --git a/code/modules/virus2/disease2.dm b/code/modules/virus2/disease2.dm index 62bd4153f5..0aa60d02e5 100644 --- a/code/modules/virus2/disease2.dm +++ b/code/modules/virus2/disease2.dm @@ -124,7 +124,7 @@ //uniqueID = rand(0,10000) var/datum/disease2/effectholder/holder = pick(effects) holder.minormutate() - infectionchance = min(50,infectionchance + rand(0,10)) + //infectionchance = min(50,infectionchance + rand(0,10)) /datum/disease2/disease/proc/majormutate() uniqueID = rand(0,10000) diff --git a/code/modules/virus2/helpers.dm b/code/modules/virus2/helpers.dm index d2671b7933..7dbd556679 100644 --- a/code/modules/virus2/helpers.dm +++ b/code/modules/virus2/helpers.dm @@ -51,7 +51,7 @@ proc/infection_check(var/mob/living/carbon/M, var/vector = "Airborne") if (vector == "Airborne") var/obj/item/I = M.wear_mask if (istype(I)) - protection = max(protection, round(0.06*I.armor["bio"])) + protection = max(protection, I.armor["bio"]) return prob(protection) @@ -148,12 +148,12 @@ proc/airborne_can_reach(turf/source, turf/target) // log_debug("Could not reach target") if (vector == "Contact") - if (in_range(src, victim)) + if (Adjacent(victim)) // log_debug("In range, infecting") infect_virus2(victim,V) //contact goes both ways - if (victim.virus2.len > 0 && vector == "Contact") + if (victim.virus2.len > 0 && vector == "Contact" && Adjacent(victim)) // log_debug("Spreading [vector] diseases from [victim] to [src]") var/nudity = 1 diff --git a/code/setup.dm b/code/setup.dm index 3e7277acfd..b701be28bc 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -957,7 +957,9 @@ var/list/be_special_flags = list( #define WALL_CAN_OPEN 1 #define WALL_OPENING 2 -#define CLAMP01(x) max(0, min(1, x)) +#define Clamp(x, y, z) (x <= y ? y : (x >= z ? z : x)) + +#define CLAMP01(x) (Clamp(x, 0, 1)) #define DEFAULT_WALL_MATERIAL "steel" #define DEFAULT_TABLE_MATERIAL "plastic" diff --git a/html/changelog.html b/html/changelog.html index ba2ba8c0c8..9cd97d800c 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -56,6 +56,24 @@ -->
+

11 July 2015

+

HarpyEagle updated:

+ +

Loganbacca updated:

+ + +

10 July 2015

+

Zuhayr updated:

+ +

06 July 2015

GinjaNinja32 updated: