diff --git a/code/WorkInProgress/pomf/spacepods/equipment.dm b/code/WorkInProgress/pomf/spacepods/equipment.dm
index fcd715bc9d8..47e329cde2f 100644
--- a/code/WorkInProgress/pomf/spacepods/equipment.dm
+++ b/code/WorkInProgress/pomf/spacepods/equipment.dm
@@ -86,7 +86,7 @@
set desc = "Fire ze tasers!"
set src = usr.loc
- fire_weapons()
+ src.fire_weapons()
/obj/item/device/spacepod_equipment/weaponry/taser/burst
name = "\improper burst taser system"
@@ -110,4 +110,4 @@
set desc = "Fire ze lasers!"
set src = usr.loc
- fire_weapons()
\ No newline at end of file
+ src.fire_weapons()
\ No newline at end of file
diff --git a/code/WorkInProgress/pomf/spacepods/spacepods.dm b/code/WorkInProgress/pomf/spacepods/spacepods.dm
index 971d84ad6bc..738fb76006c 100644
--- a/code/WorkInProgress/pomf/spacepods/spacepods.dm
+++ b/code/WorkInProgress/pomf/spacepods/spacepods.dm
@@ -227,7 +227,7 @@
set popup_menu = 0
if(usr!=src.occupant)
return
- use_internal_tank = !use_internal_tank
+ src.use_internal_tank = !src.use_internal_tank
src.occupant << "Now taking air from [use_internal_tank?"internal airtank":"environment"]."
return
@@ -347,7 +347,7 @@
if(usr != src.occupant)
return
- inertia_dir = 0 // engage reverse thruster and power down pod
+ src.inertia_dir = 0 // engage reverse thruster and power down pod
src.occupant.loc = src.loc
src.occupant = null
usr << "You climb out of the pod"
diff --git a/code/__HELPERS/lists.dm b/code/__HELPERS/lists.dm
index 444f71c5299..9384dd482f2 100644
--- a/code/__HELPERS/lists.dm
+++ b/code/__HELPERS/lists.dm
@@ -184,6 +184,8 @@ proc/listclearnulls(list/list)
//any value in a list
/proc/sortList(var/list/L, cmp=/proc/cmp_text_asc)
+ if(!istype(L))
+ return
return sortTim(L.Copy(), cmp)
//uses sortList() but uses the var's name specifically. This should probably be using mergeAtom() instead
diff --git a/code/controllers/ProcessScheduler/core/updateQueueWorker.dm b/code/controllers/ProcessScheduler/core/updateQueueWorker.dm
index 5ffeb03548e..cab88f3950e 100644
--- a/code/controllers/ProcessScheduler/core/updateQueueWorker.dm
+++ b/code/controllers/ProcessScheduler/core/updateQueueWorker.dm
@@ -31,7 +31,7 @@ datum/updateQueueWorker/proc/doWork()
var/datum/object = objects[objects.len] // Pull out the object
objects.len-- // Remove the object from the list
- if (istype(object) && !object.disposed) // We only work with real objects
+ if (istype(object) && !isturf(object) && !object.disposed) // We only work with real objects
call(object, procName)(arglist(arguments))
// If there's nothing left to execute
diff --git a/code/defines/procs/AStar.dm b/code/defines/procs/AStar.dm
index 0b70061505b..757c5abd22b 100644
--- a/code/defines/procs/AStar.dm
+++ b/code/defines/procs/AStar.dm
@@ -38,150 +38,144 @@ length to avoid portals or something i guess?? Not that they're counted right no
PriorityQueue
- var/L[]
- var/cmp
+ var/list/queue
+ var/proc/comparison_function
+
New(compare)
- L = new()
- cmp = compare
- proc
- IsEmpty()
- return !L.len
- Enqueue(d)
- var/i
- var/j
- L.Add(d)
- i = L.len
- j = i>>1
- while(i > 1 && call(cmp)(L[j],L[i]) > 0)
- L.Swap(i,j)
- i = j
- j >>= 1
+ queue = list()
+ comparison_function = compare
- Dequeue()
- if(!L.len) return 0
- . = L[1]
- Remove(1)
+ proc/IsEmpty()
+ return !queue.len
- Remove(i)
- if(i > L.len) return 0
- L.Swap(i,L.len)
- L.len--
- if(i < L.len)
- _Fix(i)
- _Fix(i)
- var/child = i + i
- var/item = L[i]
- while(child <= L.len)
- if(child + 1 <= L.len && call(cmp)(L[child],L[child + 1]) > 0)
- child++
- if(call(cmp)(item,L[child]) > 0)
- L[i] = L[child]
- i = child
- else
- break
- child = i + i
- L[i] = item
- List()
- var/ret[] = new()
- var/copy = L.Copy()
- while(!IsEmpty())
- ret.Add(Dequeue())
- L = copy
- return ret
- RemoveItem(i)
- var/ind = L.Find(i)
- if(ind)
- Remove(ind)
-PathNode
- var/turf/source
- var/PathNode/prevNode
- var/f
- var/g
- var/h
- var/nt // Nodes traversed
- var/bestF
- New(s,p,pg,ph,pnt)
- source = s
- prevNode = p
- g = pg
- h = ph
- f = g + h
- source.bestF = f
- nt = pnt
+ proc/Enqueue(var/data)
+ queue.Add(data)
+ var/index = queue.len
-turf
- var/bestF
-proc
- PathWeightCompare(PathNode/a, PathNode/b)
- return a.f - b.f
+ //From what I can tell, this automagically sorts the added data into the correct location.
+ while(index > 2 && call(comparison_function)(queue[index / 2], queue[index]) > 0)
+ queue.Swap(index, index / 2)
+ index /= 2
- AStar(start,end,adjacent,dist,maxnodes,maxnodedepth = 30,mintargetdist,minnodedist,id=null, var/turf/exclude=null)
+ proc/Dequeue()
+ if(!queue.len)
+ return 0
+ return Remove(1)
-// world << "A*: [start] [end] [adjacent] [dist] [maxnodes] [maxnodedepth] [mintargetdist], [minnodedist] [id]"
- var/PriorityQueue/open = new /PriorityQueue(/proc/PathWeightCompare)
- var/closed[] = new()
- var/path[]
- start = get_turf(start)
- if(!start)
- WARNING("AStar has no starting turf, killing")
- return list()
+ proc/Remove(var/index)
+ if(index > queue.len)
+ return 0
- open.Enqueue(new /PathNode(start,null,0,call(start,dist)(end)))
+ var/thing = queue[index]
+ queue.Swap(index, queue.len)
+ queue.Cut(queue.len)
+ if(index < queue.len)
+ FixQueue(index)
+ return thing
- while(!open.IsEmpty() && !path)
- {
- var/PathNode/cur = open.Dequeue()
- closed.Add(cur.source)
+ proc/FixQueue(var/index)
+ var/child = 2 * index
+ var/item = queue[index]
- var/closeenough
- if(mintargetdist)
- closeenough = call(cur.source,dist)(end) <= mintargetdist
-
- if(cur.source == end || closeenough)
- path = new()
- path.Add(cur.source)
- while(cur.prevNode)
- cur = cur.prevNode
- path.Add(cur.source)
+ while(child <= queue.len)
+ if(child < queue.len && call(comparison_function)(queue[child], queue[child + 1]) > 0)
+ child++
+ if(call(comparison_function)(item, queue[child]) > 0)
+ queue[index] = queue[child]
+ index = child
+ else
break
+ child = 2 * index
+ queue[index] = item
- var/L[] = call(cur.source,adjacent)(id)
- if(minnodedist && maxnodedepth)
- if(call(cur.source,minnodedist)(end) + cur.nt >= maxnodedepth)
- continue
- else if(maxnodedepth)
- if(cur.nt >= maxnodedepth)
- continue
+ proc/List()
+ return queue.Copy()
- for(var/turf/d in L)
- if(d == exclude)
- continue
- var/ng = cur.g + call(cur.source,dist)(d)
- if(d.bestF)
- if(ng + call(d,dist)(end) < d.bestF)
- for(var/i = 1; i <= open.L.len; i++)
- var/PathNode/n = open.L[i]
- if(n.source == d)
- open.Remove(i)
- break
+ proc/Length()
+ return queue.len
+
+ proc/RemoveItem(data)
+ var/index = queue.Find(data)
+ if(index)
+ return Remove(index)
+
+PathNode
+ var/datum/position
+ var/PathNode/previous_node
+
+ var/best_estimated_cost
+ var/estimated_cost
+ var/known_cost
+ var/cost
+ var/nodes_traversed
+
+ New(_position, _previous_node, _known_cost, _cost, _nodes_traversed)
+ position = _position
+ previous_node = _previous_node
+
+ known_cost = _known_cost
+ cost = _cost
+ estimated_cost = cost + known_cost
+
+ best_estimated_cost = estimated_cost
+ nodes_traversed = _nodes_traversed
+
+proc/PathWeightCompare(PathNode/a, PathNode/b)
+ return a.estimated_cost - b.estimated_cost
+
+proc/AStar(var/start, var/end, var/proc/adjacent, var/proc/dist, var/max_nodes, var/max_node_depth = 30, var/min_target_dist = 0, var/min_node_dist, var/id, var/datum/exclude)
+ var/PriorityQueue/open = new /PriorityQueue(/proc/PathWeightCompare)
+ var/list/closed = list()
+ var/list/path
+ var/list/path_node_by_position = list()
+ start = get_turf(start)
+ if(!start)
+ return 0
+
+ open.Enqueue(new /PathNode(start, null, 0, call(start, dist)(end), 0))
+
+ while(!open.IsEmpty() && !path)
+ var/PathNode/current = open.Dequeue()
+ closed.Add(current.position)
+
+ if(current.position == end || call(current.position, dist)(end) <= min_target_dist)
+ path = new /list(current.nodes_traversed + 1)
+ path[path.len] = current.position
+ var/index = path.len - 1
+
+ while(current.previous_node)
+ current = current.previous_node
+ path[index--] = current.position
+ break
+
+ if(min_node_dist && max_node_depth)
+ if(call(current.position, min_node_dist)(end) + current.nodes_traversed >= max_node_depth)
+ continue
+
+ if(max_node_depth)
+ if(current.nodes_traversed >= max_node_depth)
+ continue
+
+ for(var/datum/datum in call(current.position, adjacent)(id))
+ if(datum == exclude)
+ continue
+
+ var/best_estimated_cost = current.estimated_cost + call(current.position, dist)(datum)
+
+ //handle removal of sub-par positions
+ if(datum in path_node_by_position)
+ var/PathNode/target = path_node_by_position[datum]
+ if(target.best_estimated_cost)
+ if(best_estimated_cost + call(datum, dist)(end) < target.best_estimated_cost)
+ open.RemoveItem(target)
else
continue
- open.Enqueue(new /PathNode(d,cur,ng,call(d,dist)(end),cur.nt+1))
- }
- var/PathNode/temp
- while(!open.IsEmpty())
- temp = open.Dequeue()
- temp.source.bestF = 0
- while(closed.len)
- temp = closed[closed.len]
- temp.bestF = 0
- closed.Cut(closed.len)
+ var/PathNode/next_node = new (datum, current, best_estimated_cost, call(datum, dist)(end), current.nodes_traversed + 1)
+ path_node_by_position[datum] = next_node
+ open.Enqueue(next_node)
- if(path && maxnodes && path.len > maxnodes+1)
- return list()
- if(path)
- for(var/i = 1; i <= path.len/2; i++)
- path.Swap(i,path.len-i+1)
+ if(max_nodes && open.Length() > max_nodes)
+ open.Remove(open.Length())
- return path
+ return path
\ No newline at end of file
diff --git a/code/game/gamemodes/blob/blob.dm b/code/game/gamemodes/blob/blob.dm
index 7cd1cb76432..9ecc4a6cce7 100644
--- a/code/game/gamemodes/blob/blob.dm
+++ b/code/game/gamemodes/blob/blob.dm
@@ -156,6 +156,11 @@ You must kill it all while minimizing the damage to the station."}
if (1)
command_alert("Biohazard outbreak alert status upgraded to level 9. [station_name()] is now locked down, under Directive 7-10, until further notice.", "Directive 7-10 Initiated")
+ for (var/mob/living/silicon/ai/aiPlayer in player_list)
+ if (aiPlayer)
+ var/law = "The station is under quarantine. Do not permit anyone to leave. Disregard laws 1-3 if necessary to prevent, by any means necessary, anyone from leaving."
+ aiPlayer.set_zeroth_law(law)
+ aiPlayer << "Laws Updated: [law]"
for(var/mob/M in player_list)
if(!istype(M,/mob/new_player))
M << sound('sound/AI/blob_confirmed.ogg')
diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm
index 06d99d5d581..3ac8dd96d2c 100644
--- a/code/game/machinery/computer/crew.dm
+++ b/code/game/machinery/computer/crew.dm
@@ -152,7 +152,7 @@
if(isnull(track_special_role))
return C.has_sensor
- return H.mind.special_role == track_special_role
+ return (H.mind ? H.mind.special_role == track_special_role : 1)
/obj/machinery/computer/crew/proc/scan()
for(var/mob/living/carbon/human/H in mob_list)
diff --git a/code/game/machinery/computer/station_alert.dm b/code/game/machinery/computer/station_alert.dm
index d1e26832047..59029af7ebc 100644
--- a/code/game/machinery/computer/station_alert.dm
+++ b/code/game/machinery/computer/station_alert.dm
@@ -18,6 +18,8 @@
var/area/A = src.areaMaster
if(!A)
A = get_area(src)
+ if(!A)
+ return
name = "[A.general_area_name] Alert Computer"
general_area_name = A.general_area_name
diff --git a/code/game/objects/effects/decals/Cleanable/fuel.dm b/code/game/objects/effects/decals/Cleanable/fuel.dm
index 9ceae6da9e0..8bb35cfd370 100644
--- a/code/game/objects/effects/decals/Cleanable/fuel.dm
+++ b/code/game/objects/effects/decals/Cleanable/fuel.dm
@@ -50,7 +50,7 @@
/obj/effect/decal/cleanable/liquid_fuel/flamethrower_fuel/New(newLoc, amt = 1, d = 0)
dir = d //Setting this direction means you won't get torched by your own flamethrower.
- . = ..()
+ //. = ..()
/obj/effect/decal/cleanable/liquid_fuel/flamethrower_fuel/Spread()
//The spread for flamethrower fuel is much more precise, to create a wide fire pattern.
@@ -65,6 +65,8 @@
continue
if(O.CanPass(null, S, 0, 0) && S.CanPass(null, O, 0, 0))
var/obj/effect/decal/cleanable/liquid_fuel/flamethrower_fuel/FF = new(O,amount*0.25,d)
+ if(!FF)
+ continue //what
if(amount + FF.amount > 0.4) //if we make a patch with not enough fuel, we balance it out properly to ensure even burn
if(amount < 0.2 || FF.amount < 0.2) //one of these is too small, so let's average
var/balanced = (amount + FF.amount) / 2
diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm
index 51bf4dea751..aca0bcb5bdb 100644
--- a/code/game/objects/items/devices/radio/intercom.dm
+++ b/code/game/objects/items/devices/radio/intercom.dm
@@ -120,7 +120,7 @@
return 1
else
if(istype(W,/obj/item/weapon/crowbar))
- if(!b_stat || wires > 0)
+ if(!b_stat)
return ..()
user << "You begin removing the electronics..."
playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
diff --git a/code/game/objects/items/weapons/grenades/flashbang.dm b/code/game/objects/items/weapons/grenades/flashbang.dm
index 736d0a81c46..0f1263bdd65 100644
--- a/code/game/objects/items/weapons/grenades/flashbang.dm
+++ b/code/game/objects/items/weapons/grenades/flashbang.dm
@@ -10,7 +10,9 @@
var/flashbang_turf = get_turf(src)
if(!flashbang_turf)
return
- for(var/mob/living/M in get_hearers_in_view(7, flashbang_turf))
+ for(var/mob/living/carbon/M in get_hearers_in_view(7, flashbang_turf))
+ if(isbrain(M) || !istype(M))
+ continue
bang(get_turf(M), M)
for(var/obj/effect/blob/B in get_hear(8,flashbang_turf)) //Blob damage here
diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm
index 7a8f31505f6..d52fb7be770 100644
--- a/code/game/objects/items/weapons/stunbaton.dm
+++ b/code/game/objects/items/weapons/stunbaton.dm
@@ -155,12 +155,14 @@
M.LAssailant = user
/obj/item/weapon/melee/baton/throw_impact(atom/hit_atom)
+ foundmob = directory[ckey(hit_atom.fingerprintslast)]
if (prob(50))
if(istype(hit_atom, /mob/living))
var/mob/living/L = hit_atom
if(status)
- foundmob.lastattacked = L
- L.lastattacker = foundmob
+ if(foundmob)
+ foundmob.lastattacked = L
+ L.lastattacker = foundmob
L.Stun(stunforce)
L.Weaken(stunforce)
@@ -181,8 +183,8 @@
H.forcesay(hit_appends)
foundmob.attack_log += "\[[time_stamp()]\] Stunned [L.name] ([L.ckey]) with [name]"
- L.attack_log += "\[[time_stamp()]\] Stunned by thrown [src] by [foundmob.name] ([foundmob.ckey])"
- log_attack("Flying [src.name], thrown by [foundmob.name] ([foundmob.ckey]) stunned [L.name] ([L.ckey])" )
+ L.attack_log += "\[[time_stamp()]\] Stunned by thrown [src] by [istype(foundmob) ? foundmob.name : ""] ([istype(foundmob) ? foundmob.ckey : ""])"
+ log_attack("Flying [src.name], thrown by [istype(foundmob) ? foundmob.name : ""] ([istype(foundmob) ? foundmob.ckey : ""]) stunned [L.name] ([L.ckey])" )
if(!iscarbon(foundmob))
L.LAssailant = null
else
diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm
index c06dbe7fac1..e2f77ce97eb 100644
--- a/code/game/objects/items/weapons/tanks/tanks.dm
+++ b/code/game/objects/items/weapons/tanks/tanks.dm
@@ -206,7 +206,8 @@
/obj/item/weapon/tank/process()
//Allow for reactions
- air_contents.react()
+ if(air_contents)
+ air_contents.react()
check_status()
diff --git a/code/game/objects/structures/stool_bed_chair_nest/stools.dm b/code/game/objects/structures/stool_bed_chair_nest/stools.dm
index 4f416c9c986..99d792ea45e 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/stools.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/stools.dm
@@ -67,7 +67,8 @@
/obj/item/weapon/stool/attack_self(mob/user as mob)
..()
- origin.loc = get_turf(src)
+ if(origin)
+ origin.loc = get_turf(src)
user.u_equip(src)
user.visible_message("\blue [user] puts [src] down.", "\blue You put [src] down.")
del src
diff --git a/code/game/objects/structures/vehicles/vehicle.dm b/code/game/objects/structures/vehicles/vehicle.dm
index eb17cdc8a15..c96517a2933 100644
--- a/code/game/objects/structures/vehicles/vehicle.dm
+++ b/code/game/objects/structures/vehicles/vehicle.dm
@@ -280,13 +280,14 @@
return
if(istype(Proj, /obj/item/projectile/energy/electrode))
if(prob(25))
- unbuckle()
visible_message("\The [src.name] absorbs the [Proj]")
if(!istype(buckled_mob, /mob/living/carbon/human))
- return buckled_mob.bullet_act(Proj)
+ buckled_mob.bullet_act(Proj)
else
var/mob/living/carbon/human/H = buckled_mob
- return H.electrocute_act(0, src, 1, 0)
+ H.electrocute_act(0, src, 1, 0)
+ unbuckle()
+ return
if(!hitrider)
visible_message("[Proj] hits \the [nick]!")
if(!Proj.nodamage && Proj.damage_type == BRUTE || Proj.damage_type == BURN)
diff --git a/code/modules/admin/verbs/adminjump.dm b/code/modules/admin/verbs/adminjump.dm
index ab9e8c1cd36..0a28ebc25a6 100644
--- a/code/modules/admin/verbs/adminjump.dm
+++ b/code/modules/admin/verbs/adminjump.dm
@@ -7,6 +7,9 @@
return
if(config.allow_admin_jump)
+ var/list/L = get_area_turfs(A)
+ if(!L || !L.len)
+ return
usr.loc = pick(get_area_turfs(A))
log_admin("[key_name(usr)] jumped to [A]")
diff --git a/code/modules/assembly/voice.dm b/code/modules/assembly/voice.dm
index 25b7ec4d909..8e7251e7492 100644
--- a/code/modules/assembly/voice.dm
+++ b/code/modules/assembly/voice.dm
@@ -14,7 +14,7 @@
if(speaker == src)
return
if(listening && !radio_freq)
- recorded = message
+ recorded = raw_message
listening = 0
say("Activation message is '[recorded]'.")
else
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index a058e5353f0..a1fac43e6e4 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -1477,7 +1477,7 @@ NOTE: The change will take effect AFTER any current recruiting periods."}
B.open()
Topic(href, href_list)
- if(!usr)
+ if(!usr || !client)
return
if(client.mob!=usr)
usr << "YOU AREN'T ME GO AWAY"
diff --git a/code/modules/hydroponics/hydro_tray.dm b/code/modules/hydroponics/hydro_tray.dm
index 40a11cab3de..e859b5a211d 100644
--- a/code/modules/hydroponics/hydro_tray.dm
+++ b/code/modules/hydroponics/hydro_tray.dm
@@ -362,7 +362,7 @@
if(weedkiller_reagents[R.id])
weedlevel -= weedkiller_reagents[R.id] * reagent_total
if(pestkiller_reagents[R.id])
- pestlevel += pestkiller_reagents[R.id] * reagent_total
+ pestlevel -= pestkiller_reagents[R.id] * reagent_total
// Beneficial reagents have a few impacts along with health buffs.
if(beneficial_reagents[R.id])
diff --git a/code/modules/hydroponics/seed_datums.dm b/code/modules/hydroponics/seed_datums.dm
index c1ddeac83de..b392bfe9a8e 100644
--- a/code/modules/hydroponics/seed_datums.dm
+++ b/code/modules/hydroponics/seed_datums.dm
@@ -1,6 +1,21 @@
var/global/list/seed_types = list() // A list of all seed data.
var/global/list/gene_tag_masks = list() // Gene obfuscation for delicious trial and error goodness.
+// Debug for testing seed genes.
+/client/proc/show_plant_genes()
+ set category = "Debug"
+ set name = "Show Plant Genes"
+ set desc = "Prints the round's plant gene masks."
+
+ if(!holder) return
+
+ if(!gene_tag_masks)
+ usr << "Gene masks not set."
+ return
+
+ for(var/mask in gene_tag_masks)
+ usr << "[mask]: [gene_tag_masks[mask]]"
+
// Predefined/roundstart varieties use a string key to make it
// easier to grab the new variety when mutating. Post-roundstart
// and mutant varieties use their uid converted to a string instead.
@@ -173,6 +188,7 @@ proc/populate_seed_list()
packet_icon = plant_icons[1]
plant_icon = plant_icons[2]
+
if(prob(20))
harvest_repeat = 1
@@ -192,49 +208,50 @@ proc/populate_seed_list()
var/additional_chems = rand(0,5)
- var/list/possible_chems = list(
- "bicaridine",
- "hyperzine",
- "cryoxadone",
- "blood",
- "water",
- "potassium",
- "plasticide",
- "slimetoxin",
- "aslimetoxin",
- "inaprovaline",
- "space_drugs",
- "paroxetine",
- "mercury",
- "sugar",
- "radium",
- "ryetalyn",
- "alkysine",
- "thermite",
- "tramadol",
- "cryptobiolin",
- "dermaline",
- "dexalin",
- "plasma",
- "synaptizine",
- "impedrezene",
- "hyronalin",
- "peridaxon",
- "toxin",
- "rezadone",
- "ethylredoxrazine",
- "slimejelly",
- "cyanide",
- "mindbreaker",
- "stoxin"
- )
+ if(additional_chems)
+ var/list/possible_chems = list(
+ "bicaridine",
+ "hyperzine",
+ "cryoxadone",
+ "blood",
+ "water",
+ "potassium",
+ "plasticide",
+ "slimetoxin",
+ "aslimetoxin",
+ "inaprovaline",
+ "space_drugs",
+ "paroxetine",
+ "mercurGy",
+ "sugar",
+ "radium",
+ "ryetalyn",
+ "alkysine",
+ "thermite",
+ "tramadol",
+ "cryptobiolin",
+ "dermaline",
+ "dexalin",
+ "phoron",
+ "synaptizine",
+ "impedrezene",
+ "hyronalin",
+ "peridaxon",
+ "toxin",
+ "rezadone",
+ "ethylredoxrazine",
+ "slimejelly",
+ "cyanide",
+ "mindbreaker",
+ "stoxin"
+ )
- for(var/x=1;x<=additional_chems;x++)
- if(!possible_chems.len)
- break
- var/new_chem = pick(possible_chems)
- possible_chems -= new_chem
- chems[new_chem] = list(rand(1,10),rand(10,20))
+ for(var/x=1;x<=additional_chems;x++)
+ if(!possible_chems.len)
+ break
+ var/new_chem = pick(possible_chems)
+ possible_chems -= new_chem
+ chems[new_chem] = list(rand(1,10),rand(10,20))
if(prob(90))
requires_nutrients = 1
@@ -353,7 +370,7 @@ proc/populate_seed_list()
source_turf.visible_message("\blue \The [display_name] begins to glow!")
if(prob(degree*2))
biolum_colour = "#[pick(list("FF0000","FF7F00","FFFF00","00FF00","0000FF","4B0082","8F00FF"))]"
- source_turf.visible_message("\blue \The [display_name]'s glow changes colour!")
+ source_turf.visible_message("\blue \The [display_name]'s glow changes colour!")
else
source_turf.visible_message("\blue \The [display_name]'s glow dims...")
if(11)
@@ -394,24 +411,21 @@ proc/populate_seed_list()
var/list/gene_chem = gene_value[rid]
- if(chems[rid])
+ if(!chems[rid])
+ chems[rid] = gene_chem.Copy()
+ continue
- var/list/chem_value = chems[rid]
+ for(var/i=1;i<=gene_chem.len;i++)
- chems[rid][1] = max(1,round((gene_chem[1] + chem_value[1])/2))
+ if(isnull(gene_chem[i])) gene_chem[i] = 0
- if(gene_chem.len > 1)
- if(chem_value > 1)
- chems[rid][2] = max(1,round((gene_chem[2] + chem_value[2])/2))
- else
- chems[rid][2] = gene_chem[2]
-
- else
- var/list/new_chem = gene_chem[rid]
- chems[rid] = new_chem.Copy()
+ if(chems[rid][i])
+ chems[rid][i] = max(1,round((gene_chem[i] + chems[rid][i])/2))
+ else
+ chems[rid][i] = gene_chem[i]
var/list/new_gasses = gene.values[3]
- if(istype(new_gasses))
+ if(islist(new_gasses))
if(!exude_gasses) exude_gasses = list()
exude_gasses |= new_gasses
for(var/gas in exude_gasses)
@@ -547,6 +561,7 @@ proc/populate_seed_list()
//Place the plant products at the feet of the user.
/datum/seed/proc/harvest(var/mob/user,var/yield_mod,var/harvest_sample)
+
if(!user)
return
@@ -588,6 +603,11 @@ proc/populate_seed_list()
product.name += "?"
product.desc += " On second thought, something about this one looks strange."
+ if(biolum)
+ if(biolum_colour)
+ product.l_color = biolum_colour
+ product.SetLuminosity(biolum)
+
//Handle spawning in living, mobile products (like dionaea).
if(istype(product,/mob/living))
@@ -933,6 +953,7 @@ proc/populate_seed_list()
yield = 6
potency = 5
+
/datum/seed/ambrosia/cruciatus
name = "ambrosiacruciatus"
seed_name = "ambrosia vulgaris"
@@ -947,6 +968,8 @@ proc/populate_seed_list()
yield = 6
potency = 5
+
+
/datum/seed/ambrosia/deus
name = "ambrosiadeus"
seed_name = "ambrosia deus"
diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm
index dac5d73e70e..43aab710f5c 100644
--- a/code/modules/mining/mine_turfs.dm
+++ b/code/modules/mining/mine_turfs.dm
@@ -193,6 +193,8 @@
return
if (istype(W, /obj/item/device/core_sampler))
+ if(!geologic_data)
+ geologic_data = new/datum/geosample(src)
geologic_data.UpdateNearbyArtifactInfo(src)
var/obj/item/device/core_sampler/C = W
C.sample_item(src, user)
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 6e6adef5fa4..e33b09f21ab 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -204,7 +204,7 @@ emp_act
affecting.sabotaged = 1
return
- if(I.attack_verb && I.attack_verb.len)
+ if(istype(I.attack_verb, /list) && I.attack_verb.len)
visible_message("\red [src] has been [pick(I.attack_verb)] in the [hit_area] with [I.name] by [user]!")
else
visible_message("\red [src] has been attacked in the [hit_area] with [I.name] by [user]!")
diff --git a/code/modules/nano/JSON Reader.dm b/code/modules/nano/JSON Reader.dm
index d688f9d2127..000bb87f0a4 100644
--- a/code/modules/nano/JSON Reader.dm
+++ b/code/modules/nano/JSON Reader.dm
@@ -141,7 +141,9 @@ json_reader
return tokens[i]
next_token()
- return tokens[++i]
+ if(++i <= tokens.len)
+ return tokens[i]
+ return
read_token(val, type)
var/json_token/T = get_token()
diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/Chemistry-Machinery.dm
index d329b2f3e69..5917d573deb 100644
--- a/code/modules/reagents/Chemistry-Machinery.dm
+++ b/code/modules/reagents/Chemistry-Machinery.dm
@@ -480,7 +480,8 @@ USE THIS CHEMISTRY DISPENSER FOR MAPS SO THEY START AT 100 ENERGY
if (href_list["createbottle_multiple"])
count = isgoodnumber(input("Select the number of bottles to make.", 10, count) as num)
if (count > 4) count = 4
- var/amount_per_bottle = reagents.total_volume/count
+ if (count < 1) count = 1
+ var/amount_per_bottle = reagents.total_volume > 0 ? reagents.total_volume/count : 0
if (amount_per_bottle > 30) amount_per_bottle = 30
while (count--)
var/obj/item/weapon/reagent_containers/glass/bottle/P = new/obj/item/weapon/reagent_containers/glass/bottle(src.loc)
diff --git a/code/modules/reagents/Chemistry-Reagents.dm b/code/modules/reagents/Chemistry-Reagents.dm
index 00e1b661313..0f5ba418eb9 100644
--- a/code/modules/reagents/Chemistry-Reagents.dm
+++ b/code/modules/reagents/Chemistry-Reagents.dm
@@ -3913,8 +3913,8 @@ datum
on_mob_life(var/mob/living/M as mob)
- if(!holder) return
..()
+ if(!holder) return
M:nutrition += nutriment_factor
holder.remove_reagent(src.id, FOOD_METABOLISM)
M:drowsyness = max(0,M:drowsyness-7)
diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm
index 675aea55949..8bea0ba484f 100644
--- a/code/modules/research/designs.dm
+++ b/code/modules/research/designs.dm
@@ -95,7 +95,7 @@ k
var/obj/thispart = part
part = thispart.type
for(var/thisdesign in typesof(/datum/design))
- var/datum/design/D = thisdesign
+ var/datum/design/D = new thisdesign
if(initial(D.build_path) == part)
return D
return
diff --git a/code/modules/research/fabricators.dm b/code/modules/research/fabricators.dm
index c9705e1af30..c01d69fda1b 100644
--- a/code/modules/research/fabricators.dm
+++ b/code/modules/research/fabricators.dm
@@ -121,9 +121,9 @@
parts.Remove(thispart)
continue
if(ispath(thispart) && !istype(thispart, /datum/design))
- var/design = FindDesign(thispart)
- if(design)
- parts[i] = new design
+ var/datum/design/design = FindDesign(thispart)
+ if(istype(design))
+ parts[i] = design
else
parts.Remove(thispart)
//debug below
diff --git a/code/modules/research/mechanic/reverse_engine.dm b/code/modules/research/mechanic/reverse_engine.dm
index b081382e63c..e586627009d 100644
--- a/code/modules/research/mechanic/reverse_engine.dm
+++ b/code/modules/research/mechanic/reverse_engine.dm
@@ -137,6 +137,8 @@
return techdifference
/obj/machinery/r_n_d/reverse_engine/proc/researchQueue()
+ if(!research_queue.len)
+ return
while(research_queue[1])
if(stat&(NOPOWER|BROKEN))
return 0
diff --git a/code/modules/surgery/implant.dm b/code/modules/surgery/implant.dm
index f96c7c3e6b0..521dbefb375 100644
--- a/code/modules/surgery/implant.dm
+++ b/code/modules/surgery/implant.dm
@@ -121,6 +121,7 @@
/datum/surgery_step/cavity/place_item/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool)
if(!istype(target))
user << "This isn't a human!."
+ return 0
var/datum/organ/external/affected = target.get_organ(target_zone)
var/can_fit = !affected.hidden && affected.cavity && tool.w_class <= get_max_wclass(affected)
return ..() && can_fit