Window/global variable in JavaScript returning a NaN value early? - global

NOTE: I have attached a link here to a (semi) working version of my program.
I am programming a stock charting program using the Finnhub and P5.js libraries.
I am encountering a problem debugging the code for generating the Y-axis values based on the total range of values of a stock. When calling a window/global variable (window.yAxisRange), the for loop the variable is called within appears to be running before anything is written to said variable.
Specifically, the console shows that the console.log() code that I wrote to check the value of the yAxisRange variable displays twice (once per each iteration of that particular loop). The first instance shows a returned NaN value. The graph within the browser views gives a good example of the problem, in that there appears to be viable numbers being generated, but a NaN value is overlayed on top of them for some reason.
I am perplexed as to why I am receiving a NaN value, as well as why the loop in which the window.yAxisRange is called is running so early.
My code is below (I apologize for any discrepancies as I have spent some time adjusting it):
import finnhub from 'https://cdn.skypack.dev/finnhub';
// Finance API Function Call Below
const api_key = finnhub.ApiClient.instance.authentications['api_key'];
api_key.apiKey = "c5cam0iad3ib55bb0ajg"
const finnhubClient = new finnhub.DefaultApi()
let stockTicker = prompt("Please enter the symbol of the stock to chart:");
var yAxisAutoRange = 0
finnhubClient.stockCandles(
stockTicker, "D", ((Math.trunc(Date.now() / 1000)) - 8640000), Date.now(),
(error, data, response) => {
console.log("The maximum stock value of the timeframe is: " + max(Object.values(data.h)));
console.log("The minimum stock value of the timeframe is: " + min(Object.values(data.l)));
console.log("The values of the stock's highs are: " + (Object.values(data.h)))
console.log("The values of the stock's lows are: " + (Object.values(data.l)))
let yAxisRangeUpper = (max(Object.values(data.h))) + (max(Object.values(data.h)) - min(Object.values(data.l)))
let yAxisRangeLower = (min(Object.values(data.l))) - (max(Object.values(data.h)) - min(Object.values(data.l)))
let yAxisRange = (max(Object.values(data.h)) - min(Object.values(data.l))) / 2
window.yAxisRange = Math.trunc(yAxisRange)
console.log("yAxis Range: " + window.yAxisRange);
console.log("range maximum value : " + yAxisRangeUpper);
console.log("range minimum value : " + yAxisRangeLower);
window.yAxisAutoRange = Math.trunc(yAxisRangeUpper / 23);
console.log("yAxisAutoRange: " + yAxisRange);
let xAxisDayArray = []
let dayArrayLoop = data.t.length
let dayArrayLoop2 = data.t.length
window.xAxisDayArray = []
window.dayArrayLoop = data.t.length
window.dayArrayLoop2 = data.t.length
for (dayArrayLoop = dayArrayLoop; dayArrayLoop > dayArrayLoop2 - 44; dayArrayLoop = dayArrayLoop - 1) {
xAxisDayArray[dayArrayLoop] = JSON.stringify(new Date(data.t[dayArrayLoop - 1] * 1000));
xAxisDayArray[dayArrayLoop] = parseInt(xAxisDayArray[dayArrayLoop].slice(9, 11))
window.xAxisDayArray[dayArrayLoop] = xAxisDayArray[dayArrayLoop]
//console.log("Data point " + dayArrayLoop + "for date " + xAxisDayArray[dayArrayLoop])
}
}
);
var month = 0
// P5 Chart Background Below
globalThis.setup = function() {
createCanvas(1080, 768);
background(220);
const months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
const d = new Date();
window.month = months[d.getMonth()];
console.log(month)
const day = new Date();
day.getDate();
textSize(18)
text(window.month.slice(0, 3), 1030, 755);
}
globalThis.draw = function() {
// rect(yAxisAutoRange, 300, 10, 100);
let i = 20;
for (i = 20; i < 1020; i = i + 25) {
let y = 0;
for (line(1025, 0, 1025, 768), y = 0; y < 730; y = y + 15) {
stroke(140, 25);
line(i, y, (i + 10), y)
};
}
let z = 10;
for (z = 10; z < 730; z = z + 15) {
let x = 25;
for (line(0, 730, 1080, 730), x = 25; x < 1026; x = x + 25) {
line(x, z, x, (z + 10))
}
}
let yAxisLine = 730
let yAxisIndLocate = 710
let yAxisMultiple = 1
let yAxisNum = String(parseInt(window.yAxisAutoRange * yAxisMultiple))
// May need to simplify loop structure so as to cancel recurring drawing functions
for (yAxisLine = 705, yAxisIndLocate = 710, yAxisMultiple = 1; yAxisLine > 14, yAxisIndLocate > 14, yAxisMultiple < 24; yAxisLine = yAxisLine - 30, yAxisIndLocate = yAxisIndLocate - 30, yAxisMultiple = yAxisMultiple + 1) {
console.log("Y Axis Auto Range = " + window.yAxisAutoRange);
stroke(51)
line(1025, yAxisLine, 1040, yAxisLine);
textSize(18);
//console.log("Endless Loop Test " + yAxisNum) //window.yAxisAutoRange not registerring
//console.log("Y Axis Ind = " + window.yAxisRange);
text(window.yAxisRange / 23 * yAxisMultiple, 1045, yAxisIndLocate);
}
let xAxisLine = 1000
let xAxisIndLocate = 0
for (xAxisLine = 1000, window.dayArrayLoop = window.dayArrayLoop; xAxisLine > 24, window.dayArrayLoop > window.dayArrayLoop2 - 41; xAxisLine = xAxisLine - 25, window.dayArrayLoop = window.dayArrayLoop - 1) {
stroke(51)
line(xAxisLine, 730, xAxisLine, 745);
//console.log(xAxisLine);
text(parseInt(window.xAxisDayArray[dayArrayLoop]), xAxisLine - 5, 760)
noLoop()
}
}

First off, here's how you get this code running as a snippet on stack overflow (with added debugging):
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
<script type="module">
import finnhub from 'https://cdn.skypack.dev/finnhub';
// Finance API Function Call Below
const api_key = finnhub.ApiClient.instance.authentications['api_key'];
api_key.apiKey = "c5cam0iad3ib55bb0ajg"
const finnhubClient = new finnhub.DefaultApi()
let stockTicker = prompt("Please enter the symbol of the stock to chart:");
var yAxisAutoRange = 0;
console.log('module scope yAxisAutoRange: ' + yAxisAutoRange);
console.log('window.yAxisAutoRange: ' + window.yAxisAutoRange);
console.log("Requesting data for " + stockTicker);
finnhubClient.stockCandles(
stockTicker, "D", ((Math.trunc(Date.now() / 1000)) - 8640000), Date.now(),
(error, data, response) => {
console.log("The maximum stock value of the timeframe is: " + max(Object.values(data.h)));
console.log("The minimum stock value of the timeframe is: " + min(Object.values(data.l)));
console.log("The values of the stock's highs are: " + (Object.values(data.h)))
console.log("The values of the stock's lows are: " + (Object.values(data.l)))
let yAxisRangeUpper = (max(Object.values(data.h))) + (max(Object.values(data.h)) - min(Object.values(data.l)))
let yAxisRangeLower = (min(Object.values(data.l))) - (max(Object.values(data.h)) - min(Object.values(data.l)))
let yAxisRange = (max(Object.values(data.h)) - min(Object.values(data.l))) / 2
window.yAxisRange = Math.trunc(yAxisRange)
console.log("yAxis Range: " + window.yAxisRange);
console.log("range maximum value : " + yAxisRangeUpper);
console.log("range minimum value : " + yAxisRangeLower);
window.yAxisAutoRange = Math.trunc(yAxisRangeUpper / 23);
console.log("yAxisAutoRange: " + yAxisRange);
let xAxisDayArray = []
let dayArrayLoop = data.t.length
let dayArrayLoop2 = data.t.length
window.xAxisDayArray = []
window.dayArrayLoop = data.t.length
window.dayArrayLoop2 = data.t.length
for (dayArrayLoop = dayArrayLoop; dayArrayLoop > dayArrayLoop2 - 44; dayArrayLoop = dayArrayLoop - 1) {
xAxisDayArray[dayArrayLoop] = JSON.stringify(new Date(data.t[dayArrayLoop - 1] * 1000));
xAxisDayArray[dayArrayLoop] = parseInt(xAxisDayArray[dayArrayLoop].slice(9, 11))
window.xAxisDayArray[dayArrayLoop] = xAxisDayArray[dayArrayLoop]
//console.log("Data point " + dayArrayLoop + "for date " + xAxisDayArray[dayArrayLoop])
}
}
);
var month = 0
console.log("Declaring p5.js sketch");
// P5 Chart Background Below
globalThis.setup = function() {
console.log("p5.js sketch setup");
createCanvas(1080, 768);
background(220);
const months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
const d = new Date();
window.month = months[d.getMonth()];
console.log(month)
const day = new Date();
day.getDate();
textSize(18)
text(window.month.slice(0, 3), 1030, 755);
// Slow down the framerate so we don't spam the logs during debugging
frameRate(5);
}
globalThis.draw = function() {
console.log('p5.js draw');
// rect(yAxisAutoRange, 300, 10, 100);
let i = 20;
for (i = 20; i < 1020; i = i + 25) {
let y = 0;
for (line(1025, 0, 1025, 768), y = 0; y < 730; y = y + 15) {
stroke(140, 25);
line(i, y, (i + 10), y)
};
}
let z = 10;
for (z = 10; z < 730; z = z + 15) {
let x = 25;
for (line(0, 730, 1080, 730), x = 25; x < 1026; x = x + 25) {
line(x, z, x, (z + 10))
}
}
let yAxisLine = 730
let yAxisIndLocate = 710
let yAxisMultiple = 1
let yAxisNum = String(parseInt(window.yAxisAutoRange * yAxisMultiple))
console.log("Y Axis Auto Range = " + window.yAxisAutoRange);
// May need to simplify loop structure so as to cancel recurring drawing functions
for (yAxisLine = 705, yAxisIndLocate = 710, yAxisMultiple = 1; yAxisLine > 14, yAxisIndLocate > 14, yAxisMultiple < 24; yAxisLine = yAxisLine - 30, yAxisIndLocate = yAxisIndLocate - 30, yAxisMultiple = yAxisMultiple + 1) {
stroke(51)
line(1025, yAxisLine, 1040, yAxisLine);
textSize(18);
//console.log("Endless Loop Test " + yAxisNum) //window.yAxisAutoRange not registerring
//console.log("Y Axis Ind = " + window.yAxisRange);
text(window.yAxisRange / 23 * yAxisMultiple, 1045, yAxisIndLocate);
}
let xAxisLine = 1000
let xAxisIndLocate = 0
for (xAxisLine = 1000, window.dayArrayLoop = window.dayArrayLoop; xAxisLine > 24, window.dayArrayLoop > window.dayArrayLoop2 - 41; xAxisLine = xAxisLine - 25, window.dayArrayLoop = window.dayArrayLoop - 1) {
stroke(51)
line(xAxisLine, 730, xAxisLine, 745);
//console.log(xAxisLine);
text(parseInt(window.xAxisDayArray[dayArrayLoop]), xAxisLine - 5, 760)
noLoop()
}
}
</script>
Because you are using a top level import, and Stack Snippets don't support that, you have to move all of your JavaScript into the HTML (which is kind of a bummer and StackOverflow should fix this).
That being said, the fundamental issue here is that you are making an asynchronous request for data, and then immediately initializing a p5.js sketch that depends on that data (or at least on a value calculated from it). Consider the following console log output:
Requesting data for tsla
Declaring p5.js sketch
p5.js sketch setup
You just changed the value of "month", which was a p5 function. This could cause problems later if you're not careful.
0
p5.js draw
Y Axis Auto Range = undefined
... repeatedly
p5.js draw
Y Axis Auto Range = undefined
The maximum stock value of the timeframe is: 1243.49
The minimum stock value of the timeframe is: 813.35
The values of the stock's highs are: 820.25,843.21,...
The values of the stock's lows are: 813.35,822.35,...
yAxis Range: 215
range maximum value : 1673.63
range minimum value : 383.21
yAxisAutoRange: 215.07
p5.js draw
Y Axis Auto Range = 72
Hopefully it is self evident from this that it is only natural that yAxisAutoRange is initially undefined and thus window.yAxisRange / 23 * yAxisMultiple is NaN: because the code that computes it hasn't run yet!
Also, be careful using the , operator in the condition expression for for loops! false, true is true and true, false is false. I'm not sure that is what you meant to do (perhaps you should be using either || for logical or, or && for logical and.

Related

increasing the displayed indicator value by a percentage

i'm trying to find a way to make a indicator like rsi or stochastic but be able to adjust the output by a percentage. For example RSI signal that is increased by a percentage of what i would output by default. So it normally show 70 but is increased to 80 e.g.
Is there a way to do this? I've been scrolling through the manual for hours but couldnt find it.
Any help is appreciated
//#version=4
study(title="RSI", shorttitle="RSI", format=format.price, precision=2, resolution="")
len = input(14, minval=1, title="Length")
src = input(close, "Source", type = input.source)
rsiValue = rsi(src, len)
i_perc = input(10, title = "Percentage", type = input.float) * 0.01
up = rma(max(change(src), 0), len)
down = rma(-min(change(src), 0), len)
rsi = down == 0 ? 100 : up == 0 ? 0 : 100 - (100 / (1 + up / down))
rsi_increase_conditon = rsiValue >= rsiValue[1] * (1 + i_perc)
rsi_decrease_conditon = rsiValue <= rsiValue[1] * (1 - i_perc)
plot(rsi, "RSI", color=color.white)
hline(70, "OBBand", color=color.red, linestyle=hline.style_solid)
hline(20, "XOSBand", color=color.blue, linestyle=hline.style_solid)
hline(50, "Mid", color=color.gray, linestyle=hline.style_solid)
hline(80, "XOBBand", color=color.blue, linestyle=hline.style_solid)
hline(30, "OSBand", color=color.red, linestyle=hline.style_solid)
i_perc = input(10, title = "Percentage", type = input.float) * 0.01
...
rsi_increase_conditon = rsiValue >= rsiValue[1] * (1 + i_perc)
rsi_decrease_conditon = rsiValue <= rsiValue[1] * (1 - i_perc)
plotshape(rsi_increase_conditon and not rsi_increase_conditon[1], title = "RSI Increase %", style = shape.triangleup, location = location.belowbar, size = size.normal)
plotshape(rsi_decrease_conditon and not rsi_decrease_conditon[1], title = "RSI Decrease %", style = shape.triangledown, location = location.abovebar, size = size.normal)

Setting A Multiple Ticker Alert On Barstate.islast in Pine Script

Good Day! I am trying to emulate a script I created that provides alerts on multiple tickers for the various conditions I have set up. This works as it should and have been happy with it. Although it is not pretty, it is the first section of code posted below. The end of the code is where I input the action_alerts for the multiple tickers.
The new code I am trying to create deals with a label that shows if the relative strength reach a new high over a 28 day span. I am looking to create an alert of that new high on the same tickers as the first code to tell me once that new high is reached. That is the second code below. I also added a picture showing that label.new is a tiny green circle every time the new high is reached.
Any help with this will be greatly appreciated!
First Code (working)
indicator('Daily Screener #1', overlay=true)
//Backtest start date with inputs
startDate = input.int(title='Start Date', defval=1, minval=1, maxval=31)
startMonth = input.int(title='Start Month', defval=5, minval=1, maxval=12)
startYear = input.int(title='Start Year', defval=2021, minval=2000, maxval=2100)
//See if the bar's time happened on/after start date
afterStartDate = time >= timestamp(syminfo.timezone, startYear, startMonth, startDate, 0, 0)
//Inputs
ts_bars = input.int(10, minval=1, title='Tenkan-Sen Bars')
ks_bars = input.int(20, minval=1, title='Kijun-Sen Bars')
ssb_bars = input.int(50, minval=1, title='Senkou-Span B Bars')
sma_bars = input.int(50, minval=1, title='SMA Bars')
sec_sma_bars = input.int(5, minval=1, title='Second SMA Bars')
cs_offset = input.int(20, minval=1, title='Chikou-Span Offset')
ss_offset = input.int(20, minval=1, title='Senkou-Span Offset')
long_entry = input(true, title='Long Entry')
short_entry = input(true, title='Short Entry')
wait_for_cloud = input(true, title='Wait for Cloud Confirmation')
//values
avgvalue = input(defval=20, title='Avg Vol Period')
avgvolfac = input(defval=2, title='Rvol Factor')
maxvol = input(defval=5, title='Max Vol')
minvol = input(defval=10000, title='Required Min Vol')
color bo = color.white
color suy = color.black
avgvola = ta.sma(volume, avgvalue)
volcheck = volume > avgvola * avgvolfac and volume > minvol and volume > volume[1] * .75
maxvolcheck = volume > avgvola * maxvol and volume > minvol and volume > volume[1] * .75
// RSI Inputs
use_rsi_tp = input(false, title='Use RSI for Take Profit')
use_rsi_entry = input(false, title='Use RSI for Entry')
seq_rsi = input(defval=1, title='Alert TP after X Sequential bars past RSI')
rsi_period = input(defval=7, title='RSI Period')
overbought_rsi = input(defval=80, title='RSI Overbought Level')
oversold_rsi = input(defval=20, title='RSI Oversold Level')
middle(len) =>
ta.sma(close, len)
//Stoch RSI Inputs
smoothK = input.int(3, 'K', minval=1)
smoothD = input.int(3, 'D', minval=1)
lengthRSI = input.int(14, 'RSI Length', minval=1)
lengthStoch = input.int(14, 'Stochastic Length', minval=1)
src = input(close, title='RSI Source')
//Stoch RSI Components
rsi1 = ta.rsi(src, lengthRSI)
k = ta.sma(ta.stoch(rsi1, rsi1, rsi1, lengthStoch), smoothK)
d = ta.sma(k, smoothD)
//MACD Inputs
fast_length = input(title='Fast Length', defval=12)
slow_length = input(title='Slow Length', defval=26)
src2 = input(title='Source', defval=close)
signal_length = input.int(title='Signal Smoothing', minval=1, maxval=50, defval=9)
sma_source = input(title='Simple MA (Oscillator)', defval=false)
sma_signal = input(title='Simple MA (Signal Line)', defval=false)
//MACD Components
fast_ma = sma_source ? ta.sma(src2, fast_length) : ta.ema(src2, fast_length)
slow_ma = sma_source ? ta.sma(src2, slow_length) : ta.ema(src2, slow_length)
macd = fast_ma - slow_ma
signal = sma_signal ? ta.sma(macd, signal_length) : ta.ema(macd, signal_length)
hist = macd - signal
// Ichimoku Components
tenkan = middle(ts_bars)
kijun = middle(ks_bars)
mid_sma = middle(sma_bars)
sec_sma = middle(sec_sma_bars)
senkouA = math.avg(tenkan, kijun)
senkouB = middle(ssb_bars)
// Plot Ichimoku Kinko Hyo
plot(tenkan, color=color.new(#0496ff, 0), title='Tenkan-Sen')
plot(kijun, color=color.new(#991515, 0), title='Kijun-Sen')
plot(mid_sma, color=color.new(color.white, 0), title='50 SMA')
plot(sec_sma, color=color.new(color.orange, 0), title='5 SMA')
plot(close, offset=-cs_offset + 1, color=color.new(color.gray, 0), title='Chikou-Span')
sa = plot(senkouA, offset=ss_offset - 1, color=color.new(color.green, 0), title='Senkou-Span A')
sb = plot(senkouB, offset=ss_offset - 1, color=color.new(color.red, 0), title='Senkou-Span B')
fill(sa, sb, color=senkouA > senkouB ? color.green : color.red, title='Cloud color', transp=90)
ss_high = math.max(senkouA[ss_offset - 1], senkouB[ss_offset - 1])
ss_low = math.min(senkouA[ss_offset - 1], senkouB[ss_offset - 1])
// Entry/Exit Signals
tk_cross_bull = tenkan > kijun
tk_cross_bear = tenkan < kijun
cs_cross_bull = ta.mom(close, cs_offset - 1) > 0
cs_cross_bear = ta.mom(close, cs_offset - 1) < 0
price_above_kumo = close > ss_high
price_below_kumo = close < ss_low
price_between_kumo = close < ss_high and close > ss_low
senkou_green = senkouA > senkouB ? true : false
rsi_value = ta.rsi(close, rsi_period)
trend_midentry_T = close < tenkan or open < tenkan
trend_midentry_K = close > kijun or open > kijun
pp_t = close > tenkan or open > tenkan
pp_k = close < kijun or open < kijun
open_trend_reentry_T = open < tenkan
open_trend_reentry_K = open > kijun
close_trend_reentry_T = close < tenkan
close_trend_reentry_K = close > kijun
kumo_open_trend_reentry_T = open > tenkan
kumo_open_trend_reentry_K = open < kijun
kumo_close_trend_reentry_T = close > tenkan
kumo_close_trend_reentry_K = close < kijun
rsi_positive = k > d
rsi_negative = d > k
rsi_cross = ta.crossover(k, d)
macd_positive = macd > signal and macd > 0
macd_exit = ta.crossover(signal, macd)
macd_entry = ta.crossover(macd, signal)
hist_positive = hist >= 0
higherOrSameClose = close >= close[1]
two_day_higherOrSameClose = close >= close[1] and close[1] >= close[2]
five_day_lowerOrSameClose = close < close[7]
macd_greater_zero = fast_ma > 0
first_exit = ta.crossover(tenkan, close)
avgVol = ta.ema(volume, 50)
support = ta.lowest(close, 25)
five_ten_cross = ta.crossunder(sec_sma, tenkan)
bullish = tk_cross_bull and cs_cross_bull and price_above_kumo
bearish = tk_cross_bear and cs_cross_bear and price_below_kumo
if wait_for_cloud
bullish := bullish and senkou_green
bearish := bearish and not senkou_green
bearish
if use_rsi_entry
bullish := bullish and rsi_value < overbought_rsi
bearish := bearish and rsi_value > oversold_rsi
bearish
in_long = false
in_long := in_long[1]
open_long = bullish and long_entry and not in_long
open_short = bearish and short_entry and in_long
ish_long_entry = tk_cross_bull and cs_cross_bull and price_below_kumo
ish_2nd_long_entry = price_above_kumo and trend_midentry_T and trend_midentry_K
ish_sell_in_trend = price_above_kumo and ta.crossunder(tenkan, kijun)
ish_buy_in_trend = price_above_kumo and ta.crossover(tenkan, kijun) and higherOrSameClose
early_exit_bear = price_below_kumo and ta.crossunder(tenkan, kijun) or first_exit and price_below_kumo
best_entry = rsi_positive and macd_positive and ish_long_entry or ish_buy_in_trend and rsi_positive and macd_positive
best_exit = macd_exit and rsi_negative and ish_2nd_long_entry or first_exit and price_above_kumo
trend_reentry = price_above_kumo and (open_trend_reentry_T or close_trend_reentry_T) and (open_trend_reentry_K or close_trend_reentry_K) and rsi_positive and higherOrSameClose and macd_entry
in_kumo_trend_reentry = price_between_kumo and (kumo_open_trend_reentry_T or kumo_close_trend_reentry_T) and (kumo_open_trend_reentry_K or kumo_close_trend_reentry_K) and rsi_positive and higherOrSameClose and macd_entry
better_entry = price_above_kumo and rsi_cross and macd_greater_zero and higherOrSameClose
in_kumo_trend_reentry1 = price_between_kumo and kumo_open_trend_reentry_T and kumo_open_trend_reentry_K and rsi_positive and higherOrSameClose and macd_entry
in_kumo_trend_reentry2 = price_between_kumo and kumo_close_trend_reentry_T and kumo_close_trend_reentry_K and rsi_positive and higherOrSameClose and macd_entry
better_entry_pos = price_above_kumo and rsi_cross and macd_positive and higherOrSameClose
pre_party = price_below_kumo and (trend_midentry_T and trend_midentry_K or pp_t and pp_k) and two_day_higherOrSameClose and not five_day_lowerOrSameClose and cs_cross_bull
test = cs_cross_bull and price_below_kumo and two_day_higherOrSameClose
trend_breakout_close = not price_below_kumo and ta.crossover(close, tenkan) and rsi_positive and close > open[3]
quick_test = not price_above_kumo and close > tenkan and rsi_positive and higherOrSameClose and close[1] > close[2] and close > close[1] * 1.05
//reversal = price_below_kumo and close > close[1] and close[1] > close[2] and close > support and macd_entry
sell_off = open_short or ish_sell_in_trend
buy_up = open_long or (trend_breakout_close and ish_buy_in_trend) or (better_entry_pos and trend_breakout_close) or (trend_reentry and trend_breakout_close) or (trend_reentry and better_entry_pos) or (in_kumo_trend_reentry and trend_breakout_close) or (pre_party and test) or (quick_test and test)
sell_all = sell_off and volcheck
buy_all = buy_up and volcheck
voliskey = higherOrSameClose and maxvolcheck
all_volcheck = higherOrSameClose and volcheck and open>mid_sma
fifty_bo = trend_breakout_close and volcheck and ta.crossover(close,mid_sma)
show_me = ((ta.crossover(close,tenkan) and ta.crossover(close,kijun)) or (ta.crossover(close,sec_sma) and ta.crossover(close,tenkan))) and close<mid_sma and sec_sma>=tenkan*.99 and (volume > avgvola*.5)
bull_trend = price_above_kumo and close > sec_sma and tenkan>sec_sma and sec_sma>kijun and close>close[1] and close[1] >close[2]
chikcross = ta.crossover(close,mid_sma[20]) and open>mid_sma
ten_chikcross = ta.crossover(close,tenkan[20]) and volume > (avgvola * .75)
upside = low<low[1] and close>close[1] and ((close-low)/(high-low))>.55 and volume>avgvola*1.33 and sec_sma>tenkan
grab_it = voliskey
dump_it = sell_all
ybbo = (trend_breakout_close and better_entry_pos)
olretrace = (open_long and ish_buy_in_trend)
hvretrace = (volcheck and ish_buy_in_trend)
earbuy = quick_test
below_earbuy = (quick_test and test)
sbreak= fifty_bo
ebreak = (trend_breakout_close and quick_test)
olyb = better_entry_pos
if open_long
in_long := true
in_long
if open_short
in_long := false
in_long
rsi_count = 0
arm_tp = false
if use_rsi_tp
rsi_count := rsi_count[1]
if in_long and rsi_value > overbought_rsi or not in_long and rsi_value < oversold_rsi
rsi_count += 1
rsi_count
else
rsi_count := 0
rsi_count
if rsi_count >= seq_rsi
arm_tp := true
arm_tp
//Function Definition
action_alert(_ticker) =>
agrab_it = voliskey
adump_it = sell_all
aybbo = better_entry_pos
aearbuy = quick_test
asbreak= fifty_bo
awatch = show_me
[_grab_it, _ybbo, _earbuy, _sbreak, good_vol, _watch, _bull_trend,_ten_chikcross, _upside] = request.security(_ticker, timeframe.period, [ agrab_it, aybbo, aearbuy, asbreak, all_volcheck, awatch, bull_trend,ten_chikcross, upside])
_msg = _ticker + ',' + timeframe.period + ': '
if _grab_it
_msg += 'Big Volume Buy'
alert(_msg, alert.freq_once_per_bar)
if _ybbo
_msg += 'Yellow Buy'
alert(_msg, alert.freq_once_per_bar_close)
if _earbuy
_msg += 'Early Buy'
alert(_msg, alert.freq_once_per_bar_close)
if _sbreak
_msg += 'Super Breakout'
alert(_msg, alert.freq_once_per_bar_close)
if _bull_trend
_msg += 'Trend'
alert(_msg, alert.freq_once_per_bar_close)
if good_vol
_msg += 'Good Vol'
alert(_msg, alert.freq_once_per_bar_close)
if chikcross
_msg += 'Chikou Cross'
alert(_msg, alert.freq_once_per_bar_close)
if _ten_chikcross
_msg += '10 Chikou Cross'
alert(_msg, alert.freq_once_per_bar_close)
if _upside
_msg += 'Upside Reversal'
alert(_msg, alert.freq_once_per_bar_close)
barcolor(sell_all ? bo : na, editable=false)
barcolor(buy_all ? suy : na, editable=false)
barcolor(voliskey ? color.yellow : na, editable=false)
barcolor(all_volcheck ? suy : na, editable=false)
//Alert Plots
plotshape(open_short, text='Open Short', style=shape.triangledown, location=location.abovebar, color=color.new(color.red, 0), textcolor=color.new(color.red, 0))
plotshape(better_entry_pos, text='Buy', style=shape.arrowup, location=location.belowbar, color=color.new(#FFC803, 0), textcolor=color.new(#FFC803, 0))
plotshape(bull_trend, text='Trend', style=shape.arrowup, location=location.belowbar, color=color.new(#00BFFF, 0), textcolor=color.new(#00BFFF, 0))
plotshape(quick_test, text='Early Buy', style=shape.arrowup, location=location.belowbar, color=color.new(color.orange, 0), textcolor=color.new(color.orange, 0))
plotshape(chikcross, text='Chikou Cross', style=shape.arrowup, location=location.belowbar, color=color.new(#00FFFF, 0), textcolor=color.new(#00FFFF, 0))
plotshape(voliskey, text= "Big Vol", style=shape.arrowup, location=location.belowbar, color=color.new(color.yellow, 0), textcolor=color.new(color.yellow, 0))
plotshape(fifty_bo, text= "Super Breakot", style=shape.arrowup, location=location.belowbar, color=color.new(color.white, 0), textcolor=color.new(color.white, 0))
plotshape(ybbo, text='Good Buy Breakout', style=shape.arrowup, location=location.belowbar, color=color.new(#66FF00, 0), textcolor=color.new(#66FF00, 0))
plotshape(all_volcheck, text='Good Volume', style=shape.arrowup, location=location.belowbar, color=color.new(color.lime, 0), textcolor=color.new(color.lime, 0))
plotshape(hvretrace, text="Retrace", style=shape.arrowup, location=location.belowbar, color=color.new(color.aqua, 0), textcolor=color.new(color.aqua, 0))
plotshape(ten_chikcross, text='10 Chikou Cross', style=shape.arrowup, location=location.belowbar, color=color.new(#00BFFF, 0), textcolor=color.new(#00BFFF, 0))
plotshape(upside, text='Upside Reversal', style=shape.arrowup, location=location.belowbar, color=color.new(#C3CDE6, 0), textcolor=color.new(#C3CDE6, 0))
//Position Alert
action_alert("AMEX:DRIP")
action_alert("AMEX:DUG")
action_alert("AMEX:EQX")
action_alert("AMEX:ERY")
action_alert("AMEX:NGD")
action_alert("AMEX:TZA")
Second Code (not working)
//#version=5
indicator("Ish's Relative Strength")
length = 20
five_sma=ta.sma(close,5)
var prevRatio = 0.0
//Save each ratio so we can look for RS line new high
var array=array.new_float(0)
// RS - IBD
ThreeMonthRS = 0.4 * (close / close[13])
SixMonthRS = 0.2 * (close / (close[26] * 2))
NineMonthRS = 0.2 * (close / (close[39] * 3))
TwelveMonthRS = 0.2 * (close / (close[52] * 4))
RatingRS = (ThreeMonthRS + SixMonthRS + NineMonthRS + TwelveMonthRS) * 100
rsText = "RS Rating \n" + str.tostring(RatingRS, "0.00")
//Gather Compared Index/Stock
comparedSymbol = input.symbol(title="Benchmark RS Line", defval="QQQ", group="Relative Strength")
comparedClose = request.security(comparedSymbol, timeframe.period, close)
cThreeMonthRS = 0.4 * (comparedClose / comparedClose[13])
cSixMonthRS = 0.2 * (comparedClose / (comparedClose[26] * 2))
cNineMonthRS = 0.2 * (comparedClose / (comparedClose[39] * 3))
cTwelveMonthRS = 0.2 * (comparedClose / (comparedClose[52] * 4))
cRatingRS = (cThreeMonthRS + cSixMonthRS + cNineMonthRS + cTwelveMonthRS) * 100
crsText = "Comp RS \n" + str.tostring(cRatingRS, "0.00")
compratio = "RS Ratio \n" + str.tostring(RatingRS/cRatingRS, "0.00")
compratioNUM = RatingRS/cRatingRS
posslope= (compratioNUM-compratioNUM[2])/2
posfive=five_sma-five_sma[1]
slope=ta.sma(compratioNUM,5)
getin=ta.crossover(compratioNUM,slope) and posslope>0 and posfive>0
//Color of line to show up or down
ColorUp = color.new(color.green,0)
ColorDown = color.new(color.red,0)
linecolor = (posslope>.02 and posfive>.02)? ColorUp: ColorDown
//plot(RatingRS, color=color.new(color.white, 0), title='50 SMA')
//plot(cRatingRS, color=color.new(color.white, 0), title='Test')
plot(compratioNUM, color=linecolor, linewidth=2, title="Got It")
//plot(slope, color=color.new(color.lime,0),title="Please Work")
//plotshape(getin, title="Get In", style=shape.arrowup, location=location.belowbar, color=color.new(#C3CDE6,0), textcolor=color.new(#C3CDE6,0))
//Show high dot based on time
if (barstate.islast)
newHigh=true
for i=0 to 27
if(array.get(array, i)>compratioNUM)
newHigh:=false
break
if (newHigh)
label.new(bar_index, compratioNUM, color=color.new(color.green,40), style=label.style_circle, size=size.tiny)
if (barstate.islast)
newLow=true
for i=0 to 27
if(array.get(array, i)<compratioNUM)
newLow:=false
break
if (newLow)
label.new(bar_index, compratioNUM, color=color.new(color.red, 40), style=label.style_circle, size=size.tiny)
prevRatio:=compratioNUM
array.unshift(array, compratioNUM)
action_alert(_ticker) =>
test= newHigh
[_test] = request.security(_ticker, timeframe.period, [newHigh])
_msg = _ticker + ',' + timeframe.period + ': '
if _test
_msg += 'New High'
alert(_msg, alert.freq_once_per_bar)
//Position Alert
action_alert("AMEX:DRIP")
action_alert("AMEX:DUG")
action_alert("AMEX:EQX")
action_alert("AMEX:ERY")
action_alert("AMEX:NGD")
action_alert("AMEX:TZA")
Green dot showing new high value of relative strength reached over the last 28 days

How to find the first value of Bollinger Bands when bar open

Actually, the Bollinger Bands code is:
//#version=4
study(title="AAAA", shorttitle="AAAA", overlay=true)
len = 5
multi = 2
bb5med = sma(close, len)
devBB5 = mult2 * stdev(close, len)
bb5top = bb5med + devBB5
bb5bot = bb5med - devBB5
I would want to find the first value of those 3 lines when the new bar comes, means, when close==open.
Also, I need it to work when I change the len to 20, 50 and/or when I change the multi to 3
Please help me. Thank you.
//#version=5
indicator("BB Open", overlay = true)
len = input.int(20)
mult = input.float(2.000)
basis = (math.sum(close, len - 1)[1] + open) / len
float dev_sum = 0.0
for i = 1 to len - 1
dev_sum += math.pow(basis - close[i], 2)
dev_sum += math.pow(basis - open, 2)
stdev = math.sqrt(dev_sum / len)
up = basis + stdev * mult
dn = basis - stdev * mult
plot(basis, color = color.yellow)
plot(up)
plot(dn)
Function :
f_BBopen(_close, _open, _len, _mult) =>
_basis = (math.sum(_close, _len - 1)[1] + _open) / _len
float _dev_sum = 0.0
for i = 1 to _len - 1
_dev_sum += math.pow(_basis - _close[i], 2)
_dev_sum += math.pow(_basis - _open, 2)
_stdev = math.sqrt(_dev_sum / _len)
_up = _basis + _stdev * _mult
_dn = _basis - _stdev * _mult
[_basis, _up, _dn]
[basis, up, dn] = f_BBopen(close, open, len, mult)

Why is TIC-80 giving me the attempt to index a nil value error?

So I am building a game for a game jam over at itch.io, and I'm using this really neat Fantasy Console called TIC-80, found at tic80.com. My issue is that while I understand what the error message is and what it means, I don't understand as to why it's giving me this error.
Error Message (In the TIC-80 console):
>[string "-- title: The Clone
Wars..."]:144: attempt to index a nil
value (field '?')
stack traceback:
[string "-- title: The Clone
Wars..."]:144: in function 'TIC'
The Code in question:
-- title: The Clone Wars
-- author: DinoNuggies
-- desc: Help the jedi destroy the clones!
-- script: lua
--Functions
function sign(n) return n>0 and 1 or n<0 and -1 or 0 end
function lerp(a,b,t) return (1-t)*a + t*b end
function tablelength(T)
local count = 0
for _ in pairs(T) do count = count + 1 end
return count
end
--End of Functions
--Variables
player = {
spr = 256,
sprMod = 0,
x = 1,
y = 1,
vx = 0,
vy = 0,
dirX = 0,
dirY = 0,
flip = 0,
shoot = false,
}
gun = {
t = 0,
spr = 258,
sprMod = 0,
x = 0,
y = 0,
modX = 0,
modY = 0,
flip = 0,
rot = 0,
}
tile = {
r0 = 0,
r1 = 0,
l0 = 0,
l1 = 0,
u0 = 0,
u1 = 0,
d0 = 0,
d1 = 0,
m = 0,
}
m = {
x = 0,
y = 0,
left = false,
right = false,
middle = false,
}
cam = {
activate = true,
x = 120,
y = 64,
}
--Bullet Class & Functions
bulletMod = 0
bullet = {}
function bullet:new()
local this = {
spr = 260,
x = player.x,
y = player.y,
vx = 0,
vy = 0,
mx = m.x - (player.x + cam.x),
my = m.y - (player.y + cam.y),
t = 0,
}
return this
end
function bullet:remove()
local this = {
spr = nil,
x = nil,
y = nil,
vx = nil,
vy = nil,
mx = nil,
my = nil,
t = nil,
}
return this
end
--End of Variables
function TIC()
cls()
--Camera
if cam.activate then
cam.x = math.min(120, lerp(cam.x, 120-player.x, 0.05))
cam.y = math.min(64, lerp(cam.y, 64-player.y, 0.05))
ccx = cam.x / 8 + (cam.x % 8 == 0 and 1 or 0)
ccy = cam.y / 8 + (cam.y % 8 == 0 and 1 or 0)
end
map(15 - ccx, 8 - ccy, 31, 18, (cam.x % 8) - 8, (cam.y % 8) - 8, 0)
--End of Camera
--Gun Physics
m.x, m.y, m.left, m.middle, m.right = mouse()
gun.x = player.x + cam.x
gun.y = player.y + cam.y
bullets = tablelength(bullet) - 2
flick = (time() // 16) % 16 == 0
if m.left then m.leftp = flick else m.leftp = false end
--Gun Display
if m.x > player.x + cam.x + 4 then
gun.flip = 0
gun.modX = 4
else
gun.flip = 1
gun.modX = -4
end
--Gun Firing
if m.leftp == true then
bullet[bullets] = bullet:new()
if m.x > player.x + cam.x + 4 then
bullet[bullets].vx = 8
else
bullet[bullets].vx = -8
end
end
--End of Gun Physics
--Bullet Physics
if bullets > 0 then
for i=0,bullets-1 do
bullet[i].x = bullet[i].x + bullet[i].vx --LINE 144, THE ONE IN QUESTION
bullet[i].y = bullet[i].y + bullet[i].vy
spr(bullet[i].spr, bullet[i].x + cam.x, bullet[i].y + cam.y, 0, 1)
bullet[i].t = bullet[i].t + 1
if bullet[i].t > 16 then
bullet[i] = bullet:remove()
bullet[i] = nil
end
end
end
bullets = tablelength(bullet) - 2
--End of Bullet Physics
--Drawing
--Sprites
spr(player.spr + player.sprMod, player.x + cam.x, player.y + cam.y, 0, 1, player.flip)
spr(gun.spr + gun.sprMod, gun.x + gun.modX, gun.y + gun.modY, 0, 1, gun.flip, gun.rot)
--Debug
print("Debug:", 1, 1, 11)
print("X: " .. (player.x // 8) + 15 .. " Y: " .. (player.y // 8) + 9, 1, 8, 11)
print("BLTs: " .. bullets .. " ", 1, 16, 11)
--End of Drawing
--Player Movement
player.x = player.x + player.vx
player.y = player.y + player.vy
if key(1) and player.x > -120 then
player.vx = -1
player.sprMod = 1
player.dirX = 0
elseif key(4) then
player.vx = 1
player.sprMod = 0
player.dirX = 1
else
player.vx = 0
end
if key(23) and player.y > -64 then
player.vy = -1
player.dirY = 0
elseif key(19) then
player.vy = 1
player.dirY = 1
else
player.vy = 0
end
if btnp(0) then player.y = player.y - 1
elseif btnp(1) then player.y = player.y + 1
elseif btnp(2) then player.x = player.x - 1
elseif btnp(3) then player.x = player.x + 1
end
--End of Movement
--Player Collision
tile.r0 = mget(((player.x + 7) // 8) + 15, ((player.y - 9) // 8) + 9)
tile.r1 = mget(((player.x + 7) // 8) + 15, ((player.y - 2) // 8) + 9)
tile.l0 = mget(((player.x - 2) // 8) + 15, ((player.y - 9) // 8) + 9)
tile.l1 = mget(((player.x - 2) // 8) + 15, ((player.y - 2) // 8) + 9)
tile.u0 = mget(((player.x - 1) // 8) + 15, ((player.y - 10) // 8) + 9)
tile.u1 = mget(((player.x + 6) // 8) + 15, ((player.y - 10) // 8) + 9)
tile.d0 = mget(((player.x - 1) // 8) + 15, ((player.y - 1) // 8) + 9)
tile.d1 = mget(((player.x + 6) // 8) + 15, ((player.y - 1) // 8) + 9)
if player.dirX == 1 then
if fget(tile.r0, 0) or fget(tile.r1, 0) then
player.vx = 0
end
elseif player.dirX == 0 then
if fget(tile.l0, 0) or fget(tile.l1, 0) then
player.vx = 0
end
end
if player.dirY == 0 then
if fget(tile.u0, 0) or fget(tile.u1, 0) then
player.vy = 0
end
elseif player.dirY == 1 then
if fget(tile.d0, 0) or fget(tile.d1, 0) then
player.vy = 0
end
end
--End of Player Collision
--Misc
if keyp(3) then
if cam.activate then
cam.activate = false
else
cam.activate = true
end
end
--End of Misc
end
--DON'T WORRY ABOUT ANYTHING PAST THIS POINT, IT'S ONLY SPRITE AND TILE DEFINITIONS FOR TIC-80 VISUALS
-- <TILES>
-- 000:6666666666666666666666666666666666666666666666666666666666666666
-- 001:6666666666566566666666656666666665665666666665666566666666666666
-- 002:6668666666898566666866656666666665665866686689868986686668666666
-- 003:6656556666555556555556555555556555555555665555556556555666655566
-- 016:dddddddeddddddefddeeeeffddeeeeffddeeeeffddeeeeffdeffffffefffffff
-- 017:6226622661266126222222221121112161266126612661265126512665266525
-- 018:6228622661298126222222221121112161266126612681268126512668266525
-- 019:6226522661255126222222221121112151255125612551255126512665255525
-- </TILES>
-- <SPRITES>
-- 000:00cccc000cccccd00cbbbbb0ccbbcbbdcccfefcd0dddddd000ceec0000c00c00
-- 001:00cccc000cccccd00bbbbbd0cbbcbbcdccfefccd0dddddd000ceec0000c00c00
-- 002:000000000000000000000000000eeeed000efff0000ef0000000000000000000
-- 003:0000ed00000eef0000eef0000eef000000eef000000ee0000000000000000000
-- 004:0000000000000000000000000aaaaaa00aaaaaa0000000000000000000000000
-- </SPRITES>
-- <MAP>
-- 000:010101010101010101010101010101010101010101010101010101010101010000000000000000000000101010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
-- 001:010000000000000000000000000000101000101000001000000010101001010000000000100000000000101010000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
-- 002:010001000100010000000000000010000000100010001000100010001001010000000010100000000000101010000000000000001010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
-- 003:010001000100000000000000000000101000100010001000100010100001010000000010000000000000101000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
-- 004:010001010100010000000000000000001000100010001000100010000001010000000010000000000000101010000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
-- 005:010001000100010000000000000010100000001010000010100010000001010000000010000000000000101010000000000000000000101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
-- 006:010000000000000000000000000101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
-- 007:010000000000000000000000000101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
-- 008:010000000000000000000000000101301010000000000000000000000000000000000000101010000000101000000000000000000010101000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
-- 009:010000000000000000000000000101101010100000000000000000000000000000001010101000000000101000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
-- 010:010000000000000000000000000101101010000000000001111101000000001111111121211111110000101000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
-- 011:010000000000000000000000000101000000000000001000000001000000000000001020101000000000101000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
-- 012:010000000000000000000000000101000000000000011111111101010001010000101010000000000010101000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
-- 013:010000000000000000000000000101000000000010101000000001011101010000101000000000000010100000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
-- 014:010000000000000000000000000101000000000010101010000000000000010000000000000000000010100000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
-- 015:010000000000000000000000000101000000000000000000000000000000010000000000000000001010000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
-- 016:010101010101010101010101010101000000000000000000000000000000010000000000000000001010000000000000001010000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
-- 017:010101010101010101010101010101000000000000000000000000000000000000000000000000101010000000000010102000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
-- 018:000000000000000000000000000101000000000000000000000010100000000000000000000000101000000000001010000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 019:000000000000000000001010000101000000000000000000000000100000000000000000000010101000001111211110000000001010000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 020:000000001000000000001000000101000000000000000000000000101000000000000000001010101000000010101011111100000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 021:000000000000000000001010100101101010000000000000000000000000000000000000101000000000001010200000000011110000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 022:000000000000000000000000000101001010100000000000000000000000000000000010101000000010101010100000000000001111000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 023:000000000000000000000000000101000000000000000000000000000000000000001010100000000010101010000000000000000000110000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 024:000000000000000000000000000101000000000000000000000000000000000000001010100000001020201000000000000000100000001100102001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 025:000000000000000000000000000101000000000000000000000000000000000000101010000000001020100000000000000000100000000011212101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 026:000000101000000000000000000101000000000000000000000000000000001010100010000000001010100000000010000000100010100010101001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 027:000000101010000000000000100101000000000000000010101010101010101010000010000000001010000000000000101010000000001010000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 028:000000100010000000000000100101000000000000000000000000001010101000101010000000001010000010101010000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 029:000000001010000000000000000101000000000000000000000000000010100000000000000000001010000000000000000000100010000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 030:000000001010000000000000000101100000000000000000000000000000000000000000000000001000000000001000000000100000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 031:000000001010000000000000000101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 032:000000000000000000000000000101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 033:000000000000000000000000000101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- 135:010101010101010101010101010101010101010101010101010101010101010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
-- </MAP>
-- <WAVES>
-- 000:00000000ffffffff00000000ffffffff
-- 001:0123456789abcdeffedcba9876543210
-- 002:0123456789abcdef0123456789abcdef
-- </WAVES>
-- <SFX>
-- 000:020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200304000000000
-- 001:020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200307000000000
-- 002:02000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020002000200020030b000000000
-- </SFX>
-- <FLAGS>
-- 000:00000000000000000000000000000000101010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- </FLAGS>
-- <PALETTE>
-- 000:1a1c2c5d2810814428ca9581ffcd7575ae442495482571793c55c22c9dfae20000000000f4f4f494b0c2566c86333c57
-- </PALETTE>
What triggers the error, is after the player fires the second bullet. After firing one, the bullet is created, displayed, and despawned on queue, but after the second bullet starts existing, it stops and gives me the error. I've switched things around quite a bit, and it seems like every time I reference to one of the bullet objects values when more then one exists, it sends me the error, which is what I don't understand, as i thought I had already solved that problem with the for loops.
So if you noticed anything right off the bat that doesn't look quite right, let me know, and if you don't know anything about TIC-80 or what the API does, I'm sure the TIC-80 website can explain it way better then me.
If you want to run the game, to see the issue in action and mess around with the code, download TIC-80 from the website and run this file:
https://drive.google.com/file/d/18ti0NboNNN9Yog6l_n73usF_eX_86EN4/view?usp=sharing
Let's take a look at your bullet handling
First call to TIC:
bullets is 0. We add one bullet into bullet[0]
Second call:
bullets is 1. We add one bullet into bullet[1].
Now, as bullets > 0 we enter the bullet physics if statement.
We do some calculations to that bullet and increment bullet[0].t
The following calls we do the same. We add a bullet and process all but the new bullet as we did above.
When a bullet's t field becomes > 16 we remove it from bullet.
So first we remove the oldest bullet bullet[0]. But in the following call we again start our loop at i = 0. so bullet[i] is nil and hence indexing it in bullet[i].x causes the observed error.
Side note:
This makes no sense.
function bullet:remove()
local this = {
spr = nil,
x = nil,
y = nil,
vx = nil,
vy = nil,
mx = nil,
my = nil,
t = nil,
}
return this
end
A table with all nil values is just an empty table. So simply return an empty table.
On top of that you don't need that function as it does nothing useful.
bullet[i] = bullet:remove()
bullet[i] = nil
The first line is non necessary. You don't have to assign an emtpy table and then nil. Just assign nil.
If you'd just keep the bullets in the array part of the table you wouldn't need your own tablelength function and then subtract 2 btw.
Then you could also use table.remove to remove bullets without creating unexpected gaps in your bullet list.

whenever I try to run the code with Lua I get the error :Error Map.lua:107: attempt to call method 'makepyramid' (a nil value)

Map = Class{}
TILE_BRICK = 1
TILE_EMPTY = -1
POLE_TOP = 8
POLE_MIDDLE = 12
POLE_BOTTOM = 16
FLAG_TILE = 13
local SCROLL_SPEED = 62
function Map:init()
self.spritesheet = love.graphics.newImage('graphics/spritesheet.png')
self.sprites = generateQuads(self.spritesheet, 16, 16)
self.music = love.audio.newSource('sounds/music.wav', 'static')
self.tileWidth = 16
self.tileHeight = 16
self.mapWidth = 30
self.mapHeight = 28
self.tiles = {}
self.flag = self.mapWidth - 3
self.pyramid = self.mapWidth - 4
self.pyramidHeight = 8
self.gravity = 15
-- associate player with map
self.player = Player(self)
-- camera offsets
self.camX = 0
self.camY = -3
self.mapWidthPixels = self.mapWidth * self.tileWidth
self.mapHeightPixels = self.mapHeight * self.tileHeight
for y = 1, self.mapHeight do
for x = 1, self.mapWidth do
self:setTile(x, y, TILE_EMPTY)
end
end
local x = 1
while x < self.mapWidth do
if x == self.flag then
self:setTile(x, (self.mapHeight / 2) - 3, POLE_TOP)
self:setTile(x, (self.mapHeight / 2) - 2, POLE_MIDDLE)
self:setTile(x, (self.mapHeight / 2) - 1, POLE_BOTTOM)
self:setTile(x+1, (self.mapHeight / 2) - 3, FLAG_TILE)
for y = self.mapHeight / 2, self.mapHeight do
self:makepyramid(x, y, TILE_BRICK)
end
self:setTile(self.flag)
x = x+1
end
This the code that I have written it does require other files to work but the core problem exists within this code: most probably with "makepyramid" in "map init()"
please suggest some possible changes that I can make to make this code work properly. comment down if you need more chunks of code to try some solutions.