-- it is up to user to ensure that total breached volume is lower -- than the total volume class Fluid new: (opts={}) => @volume = opts.volume or 1 @pressure = opts.pressure or 1 @contents = opts.contents or {} -- breaches stored on high pressure side of Fluids @breaches = {} update: (dt) => leak = 0 -- total leak rate (pressure) for breach in *@breaches -- difference in pressure * relative size of hole rate = (@pressure - breach.pressure) * (breach.size / @volume) * dt leak += rate breach.pressure += rate * (@volume / breach.volume) breach.pressure = 0 if breach.pressure < 0 amount = breach.pressure * breach.volume modifier = 1 - @volume * rate / amount for item, percentage in pairs breach.contents breach.contents[item] = percentage * modifier for item, percentage in pairs @contents percentage = (@volume * rate * percentage) / amount if breach.contents[item] breach.contents[item] += percentage else breach.contents[item] = percentage @pressure -= leak for i = 1, #@breaches if @breaches[i].pressure > @pressure other = table.remove @breaches, i other\breach(@, other.size) i -= 1 amount: (key) => if key if @contents[key] return @volume * @pressure * @contents[key] else return 0 else return @volume * @pressure remove: (key, amount=1) => total = @amount key if total >= amount percentage = amount / total @contents[key] -= @contents[key] * percentage percentage = amount / @amount! @pressure -= @pressure * percentage for item, p in pairs @contents @contents[item] += p * percentage return true else return false breach: (other, size) => if other.pressure > @pressure other\breach(@, size) else other.size = size or 1 table.insert @breaches, other print: => print "Volume", @volume, "Pressure", @pressure, "#", @amount! percentage, amount = 0, 0 for k,v in pairs @contents x = @amount k print k, v, x percentage += v amount += x print "", "Total:", percentage, amount