If someone could please help, that would be great! I'm fairly new to coding, but am trying to create a basic automated trading strategy in Indicore 3, which uses LUA script. Even if you don't know much about trading, you could probably still recognize where I've gone wrong in this code.
Basically I'm trying to automate a buy into a trade when price, is above the FastEMA, the FastEMA is above the MedEMA, and the MedEMA is above the SlowEMA. And a sell trade in the exactly opposite fashion. I'm then wanting to close the trade when, in a buy situation, the Fast EMA is no longer above the MedEMA, and for a sell, the FastEMA rises above the MedEMA.
Plus, if the currency is already in a trade, I don't want it to put another one on. Hence the idea around the HaveTrades function.
Please if you have any idea, give me a shout. Like I say I'm a beginner, however I feel like this is a pretty basic code.
Picture is to illustrate idea. Blue line is FastEMA, Green line is MedEMA, and Red line is SlowEMA.
I used the original code off a 3EMA Indicore tutorial, and have tried to simplify it to what I need, so if there's inconsistencies with the code, please highlight them to me.
function Init()
strategy:name("3EMA test AMI");
strategy:description("No description");
strategy:requiredSource(core.Bar);
strategy:type(core.both);
strategy.parameters:addInteger("FastEMA", "Fast EMA", "No description", 5);
strategy.parameters:addInteger("MedEMA", "Medium Ema", "No description", 20);
strategy.parameters:addInteger("SlowEMA", "Slow EMA", "No description", 50);
strategy.parameters:addGroup("Trading Parameters");
strategy.parameters:addBoolean("AllowTrade", "Allow strategy to trade", "", false);
strategy.parameters:setFlag("AllowTrade", core.FLAG_ALLOW_TRADE);
strategy.parameters:addString("Account", "Account to trade on", "", "");
strategy.parameters:setFlag("Account", core.FLAG_ACCOUNT);
strategy.parameters:addInteger("Amount", "Trade Amount in Lots", "", 1, 1, 100);
strategy.parameters:addBoolean("SetLimit", "Set Limit Orders", "", false);
strategy.parameters:addInteger("Limit", "Limit Order in pips", "", 30, 1, 10000);
strategy.parameters:addBoolean("SetStop", "Set Stop Orders", "", false);
strategy.parameters:addInteger("Stop", "Stop Order in pips", "", 30, 1, 10000);
strategy.parameters:addBoolean("TrailingStop", "Trailing stop order", "", false);
strategy.parameters:addGroup("Notification");
strategy.parameters:addBoolean("ShowAlert", "Show Alert", "", true);
strategy.parameters:addBoolean("PlaySound", "Play Sound", "", false);
strategy.parameters:addBoolean("RecurrentSound", "Recurrent Sound", "", false);
strategy.parameters:addFile("SoundFile", "Sound File", "", "");
strategy.parameters:setFlag("SoundFile", core.FLAG_SOUND);
strategy.parameters:addBoolean("SendEmail", "Send Email", "", false);
strategy.parameters:addString("Email", "Email", "", "");
strategy.parameters:setFlag("Email", core.FLAG_EMAIL);
end
local FastEMA;
local MedEMA;
local SlowEMA;
local EnableStage1TimeRange;
local TimeRangeStart;
local TimeRangeEnd;
local gSource = nil; -- the source stream
local PlaySound;
local RecurrentSound;
local SoundFile;
local Email;
local SendEmail;
local AllowTrade;
local Account;
local Amount;
local BaseSize;
local SetLimit;
local Limit;
local SetStop;
local Stop;
local TrailingStop;
local Offer;
local CanClose;
local iEMAFast;
local iEMAMed;
local iEMASlow;
function Prepare(nameOnly)
FastEMA = instance.parameters.FastEMA;
MedEMA = instance.parameters.MedEMA;
SlowEMA = instance.parameters.SlowEMA;
LookBack = instance.parameters.LookBack;
EnableStage1TimeRange = instance.parameters.EnableStage1TimeRange;
TimeRangeStart = instance.parameters.TimeRangeStart;
TimeRangeEnd = instance.parameters.TimeRangeEnd;
local name = profile:id() .. "(" .. instance.bid:instrument() .. ", " .. tostring(FastEMA) .. ", " .. tostring(MedEMA) .. ", " .. tostring(SlowEMA) .. ", " .. tostring(LookBack).. ", " .. tostring(EnableStage1TimeRange) .. ")";
instance:name(name);
if nameOnly then
return ;
end
ShowAlert = instance.parameters.ShowAlert;
PlaySound = instance.parameters.PlaySound;
if PlaySound then
RecurrentSound = instance.parameters.RecurrentSound;
SoundFile = instance.parameters.SoundFile;
else
SoundFile = nil;
end
assert(not(PlaySound) or (PlaySound and SoundFile ~= ""), "Sound file must be specified");
SendEmail = instance.parameters.SendEmail;
if SendEmail then
Email = instance.parameters.Email;
else
Email = nil;
end
assert(not(SendEmail) or (SendEmail and Email ~= ""), "E-mail address must be specified");
AllowTrade = instance.parameters.AllowTrade;
if AllowTrade then
Account = instance.parameters.Account;
Amount = instance.parameters.Amount;
BaseSize = core.host:execute("getTradingProperty", "baseUnitSize", instance.bid:instrument(), Account);
Offer = core.host:findTable("offers"):find("Instrument", instance.bid:instrument()).OfferID;
CanClose = core.host:execute("getTradingProperty", "canCreateMarketClose", instance.bid:instrument(), Account);
SetLimit = instance.parameters.SetLimit;
Limit = instance.parameters.Limit * instance.bid:pipSize();
SetStop = instance.parameters.SetStop;
Stop = instance.parameters.Stop * instance.bid:pipSize();
TrailingStop = instance.parameters.TrailingStop;
end
gSource = ExtSubscribe(1, nil, instance.parameters.TF, true, "bar");
tSource = ExtSubscribe(2, nil, "t1", true, "bar");
--TODO: Find indicator's profile, intialize parameters, and create indicator's instance (if needed)
iEMAFast = core.indicators:create("EMA", gSource.close, FastEMA)
iEMAMed = core.indicators:create("EMA", gSource.close, MedEMA)
iEMASlow = core.indicators:create("EMA", gSource.close, SlowEMA)
end
local Stage1Status = "Neutral"; -- possible values are "Neutral", "Buy", "Sell"
-- update indicators
iEMAFast:update(core.UpdateLast);
iEMAMed:update(core.UpdateLast);
iEMASlow:update(core.UpdateLast);
-- check for data
--if not iEMAFast.DATA:hasData(period) or not iEMAMed.DATA:hasData(period) or not
iEMAMed.DATA:hasData(period) then
--core.host:trace("Not Enough Data. Checking Next Bar...")
--return;
--end
-- close of bar, Stage 1, making sure EMAs are lined up.
if not haveTrades() then
-- buy setup, if Price > Fast > Med > Slow
if gSource.close[period] > iEMAFast.DATA[period] and
iEMAFast.DATA[period] > iEMAMed.DATA[period] and
iEMAMed.DATA[period] > iEMASlow.DATA[period] then
Status="Buy"
enter("B")
end
-- sell setup, if Price < Fast < Med < Slow
if gSource.close[period] < iEMAFast.DATA[period] and
iEMAFast.DATA[period] < iEMAMed.DATA[period] and
iEMAMed.DATA[period] < iEMASlow.DATA[period] then
Status="Sell"
enter("S")
end
end
end
-- open positions in direction BuySell
function enter(BuySell)
local valuemap, success, msg;
valuemap = core.valuemap();
valuemap.OrderType = "OM";
valuemap.OfferID = Offer;
valuemap.AcctID = Account;
valuemap.Quantity = Amount * BaseSize;
valuemap.BuySell = BuySell;
valuemap.GTC = "GTC";
if SetLimit then
-- set limit order
valuemap.PegTypeLimit = "O";
if BuySell == "B" then
valuemap.PegPriceOffsetPipsLimit = Limit/instance.bid:pipSize();
else
valuemap.PegPriceOffsetPipsLimit = -Limit/instance.bid:pipSize();
end
end
if SetStop then
-- set stop order
valuemap.PegTypeStop = "O";
if BuySell == "B" then
valuemap.PegPriceOffsetPipsStop = -Stop/instance.bid:pipSize();
else
valuemap.PegPriceOffsetPipsStop = Stop/instance.bid:pipSize();
end
if TrailingStop then
valuemap.TrailStepStop = 1;
end
end
if (not CanClose) and (StopLoss > 0 or TakeProfit > 0) then
valuemap.EntryLimitStop = "Y"
end
success, msg = terminal:execute(100, valuemap);
if not(success) then
terminal:alertMessage(instance.bid:instrument(), instance.bid[instance.bid:size() - 1], "open order failure: " .. msg, instance.bid:date(instance.bid:size() - 1));
return false;
end
return true;
end
-- return true if trade is found (can check single side as well)
function haveTrades(BuySell)
local enum, row;
local found = false;
enum = core.host:findTable("trades"):enumerator();
row = enum:next();
while (not found) and (row ~= nil) do
if row.AccountID == Account and
row.OfferID == Offer and
(row.BS == BuySell or BuySell == nil) then
found = true;
end
row = enum:next();
end
return found;
end
-- Close trigger
function close(CanClose)
if HaveTrades and (Status == "Buy") and FastEMA<MedEMA then
Status = "close"
end
if HaveTrades and (Status == "Sell") and FastEMA>MedEMA then
Status = "close"
end
end
Related
I have a problem with dots, when you enter a clothing store or a barbershop, the menu opens and works well. But after that, anywhere on the map, when you press E, the menu of a clothing store or a barbershop opens.
Here is the code itself, I myself do not know what the problem is there.
QBCore = exports['qb-core']:GetCoreObject()
local LastZone = nil
local CurrentAction = nil
local CurrentActionMsg = ''
local hasAlreadyEnteredMarker = false
local allMyOutfits = {}
local isPurchaseSuccessful = false
local PlayerData = {}
-- Net Events
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
QBCore.Functions.TriggerCallback('fivem-appearance:getPlayerSkin', function(appearance)
exports['fivem-appearance']:setPlayerAppearance(appearance)
PlayerData = QBCore.Functions.GetPlayerData()
if Config.Debug then -- This will detect if the player model is set as "player_zero" aka michael. Will then set the character as a freemode ped based on gender.
Wait(5000)
if GetEntityModel(PlayerPedId()) == `player_zero` then
print('Player detected as "player_zero", Starting CreateFirstCharacter event')
TriggerEvent('qb-clothes:client:CreateFirstCharacter')
end
end
end)
end)
RegisterNetEvent('qb-clothes:client:CreateFirstCharacter', function() -- Event renamed so you dont need to change anything for this to work... hopefully....
QBCore.Functions.GetPlayerData(function(PlayerData)
local skin = 'mp_m_freemode_01'
if PlayerData.charinfo.gender == 1 then
skin = "mp_f_freemode_01"
end
exports['fivem-appearance']:setPlayerModel(skin)
local config = {
ped = false,
headBlend = true,
faceFeatures = true,
headOverlays = true,
components = true,
props = true,
}
exports['fivem-appearance']:setPlayerAppearance(appearance)
exports['fivem-appearance']:startPlayerCustomization(function(appearance)
if (appearance) then
TriggerServerEvent('fivem-appearance:save', appearance)
print('Player Clothing Saved')
else
print('Canceled')
end
end, config)
end)
end, false)
AddEventHandler('fivem-appearance:hasExitedMarker', function(zone)
CurrentAction = nil
end)
RegisterNetEvent('fivem-appearance:clothingShop', function()
exports['qb-menu']:openMenu({
{
header = "👚 | Clothing Store Options",
isMenuHeader = true, -- Set to true to make a nonclickable title
},
{
header = "Buy Clothing - $"..Config.Money,
txt = "Pick from a wide range of items to wear",
params = {
event = "fivem-appearance:clothingMenu",
}
},
{
header = "Change Outfit",
txt = "Pick from any of your currently saved outfits",
params = {
event = "fivem-appearance:pickNewOutfit",
args = {
number = 1,
id = 2
}
}
},
{
header = "Save New Outfit",
txt = "Save a new outfit you can use later on",
params = {
event = "fivem-appearance:saveOutfit",
}
},
{
header = "Delete Outfit",
txt = "Yeah... We didnt like that one either",
params = {
event = "fivem-appearance:deleteOutfitMenu",
args = {
number = 1,
id = 2
}
}
},
})
end)
RegisterNetEvent('fivem-appearance:pickNewOutfit', function(data)
local id = data.id
local number = data.number
TriggerEvent('fivem-appearance:getOutfits')
Wait(150)
local outfitMenu = {
{
header = '< Go Back',
params = {
event = 'fivem-appearance:clothingShop'
}
}
}
for i=1, #allMyOutfits, 1 do
outfitMenu[#outfitMenu + 1] = {
header = allMyOutfits[i].name,
params = {
event = 'fivem-appearance:setOutfit',
args = {
-- number = (1 + i),
ped = allMyOutfits[i].pedModel,
components = allMyOutfits[i].pedComponents,
props = allMyOutfits[i].pedProps
}
}
}
end
exports['qb-menu']:openMenu(outfitMenu)
end)
RegisterNetEvent('fivem-appearance:getOutfits', function()
TriggerServerEvent('fivem-appearance:getOutfits')
end)
RegisterNetEvent('fivem-appearance:sendOutfits', function(myOutfits)
local Outfits = {}
for i=1, #myOutfits, 1 do
table.insert(Outfits, {id = myOutfits[i].id, name = myOutfits[i].name, pedModel = myOutfits[i].ped, pedComponents = myOutfits[i].components, pedProps = myOutfits[i].props})
end
allMyOutfits = Outfits
end)
RegisterNetEvent('fivem-appearance:setOutfit', function(data)
local pedModel = data.ped
local pedComponents = data.components
local pedProps = data.props
local playerPed = PlayerPedId()
local currentPedModel = exports['fivem-appearance']:getPedModel(playerPed)
if currentPedModel ~= pedModel then
exports['fivem-appearance']:setPlayerModel(pedModel)
Wait(500)
playerPed = PlayerPedId()
exports['fivem-appearance']:setPedComponents(playerPed, pedComponents)
exports['fivem-appearance']:setPedProps(playerPed, pedProps)
local appearance = exports['fivem-appearance']:getPedAppearance(playerPed)
TriggerServerEvent('fivem-appearance:save', appearance)
else
exports['fivem-appearance']:setPedComponents(playerPed, pedComponents)
exports['fivem-appearance']:setPedProps(playerPed, pedProps)
local appearance = exports['fivem-appearance']:getPedAppearance(playerPed)
TriggerServerEvent('fivem-appearance:save', appearance)
end
-- TriggerEvent('fivem-appearance:clothingShop')
end)
RegisterNetEvent('fivem-appearance:saveOutfit', function()
local keyboard = exports['qb-input']:ShowInput({
header = "Name your outfit",
submitText = "Create Outfit",
inputs = {
{
text = "Outfit Name",
name = "input",
type = "text",
isRequired = true
},
},
})
if keyboard ~= nil then
local playerPed = PlayerPedId()
local pedModel = exports['fivem-appearance']:getPedModel(playerPed)
local pedComponents = exports['fivem-appearance']:getPedComponents(playerPed)
local pedProps = exports['fivem-appearance']:getPedProps(playerPed)
Wait(500)
TriggerServerEvent('fivem-appearance:saveOutfit', keyboard.input, pedModel, pedComponents, pedProps)
QBCore.Functions.Notify('Outfit '..keyboard.input.. ' has been saved', 'success')
end
end)
RegisterNetEvent('fivem-appearance:deleteOutfitMenu', function(data)
local id = data.id
local number = data.number
TriggerEvent('fivem-appearance:getOutfits')
Wait(150)
local DeleteMenu = {
{
header = '< Go Back',
params = {
event = 'fivem-appearance:clothingShop'
}
}
}
for i=1, #allMyOutfits, 1 do
DeleteMenu[#DeleteMenu + 1] = {
header = 'Delete "'..allMyOutfits[i].name..'"',
txt = 'You will never be able to get this back!',
params = {
event = 'fivem-appearance:deleteOutfit',
args = allMyOutfits[i].id
}
}
end
exports['qb-menu']:openMenu(DeleteMenu)
end)
RegisterNetEvent('fivem-appearance:deleteOutfit', function(id)
TriggerServerEvent('fivem-appearance:deleteOutfit', id)
-- TriggerEvent('fivem-appearance:clothingShop')
QBCore.Functions.Notify('Outfit Deleted', 'error')
end)
RegisterNetEvent("fivem-appearance:purchase", function(bool)
isPurchaseSuccessful = bool
end)
RegisterNetEvent('fivem-appearance:clothingMenu', function()
TriggerServerEvent('fivem-appearances:buyclothing')
Wait(500)
if isPurchaseSuccessful then
local config = {
ped = false,
headBlend = false,
faceFeatures = false,
headOverlays = false,
components = true,
props = true
}
exports['fivem-appearance']:startPlayerCustomization(function(appearance)
if appearance then
TriggerServerEvent('fivem-appearance:save', appearance)
print('Player Clothing Saved')
Wait(1000) -- Wait is needed to clothing menu dosent overwrite the tattoos
TriggerServerEvent('Select:Tattoos')
else
print('Canceled')
Wait(1000) -- Wait is needed to clothing menu dosent overwrite the tattoos
TriggerServerEvent('Select:Tattoos')
end
end, config)
end
end)
RegisterNetEvent('fivem-appearance:barberMenu', function()
local config = {
ped = false,
headBlend = false,
faceFeatures = false,
headOverlays = true,
components = false,
props = false
}
exports['fivem-appearance']:startPlayerCustomization(function (appearance)
if appearance then
TriggerServerEvent('fivem-appearance:save', appearance)
print('Player Clothing Saved')
Wait(1000) -- Wait is needed to clothing menu dosent overwrite the tattoos
TriggerServerEvent('Select:Tattoos')
else
print('Canceled')
Wait(1000) -- Wait is needed to clothing menu dosent overwrite the tattoos
TriggerServerEvent('Select:Tattoos')
end
end, config)
end)
-- Backwords Events so you dont need to replace these
RegisterNetEvent('qb-clothing:client:openMenu', function() -- Admin Menu clothing event
Wait(500)
local config = {
ped = true,
headBlend = true,
faceFeatures = true,
headOverlays = true,
components = true,
props = true
}
exports['fivem-appearance']:startPlayerCustomization(function(appearance)
if appearance then
TriggerServerEvent('fivem-appearance:save', appearance)
print('Player Clothing Saved')
Wait(1000) -- Wait is needed to clothing menu dosent overwrite the tattoos
TriggerServerEvent('Select:Tattoos')
else
print('Canceled')
Wait(1000) -- Wait is needed to clothing menu dosent overwrite the tattoos
TriggerServerEvent('Select:Tattoos')
end
end, config)
end)
RegisterNetEvent('qb-clothing:client:openOutfitMenu', function() -- Name is so that you dont have to replace the event, Used in Appartments, Bossmenu, etc...
exports['qb-menu']:openMenu({
{
header = "👔 | Outfit Options",
isMenuHeader = true, -- Set to true to make a nonclickable title
},
{
header = "Change Outfit",
txt = "Pick from any of your currently saved outfits",
params = {
event = "fivem-appearance:pickNewOutfitApp",
args = {
number = 1,
id = 2
}
}
},
{
header = "Save New Outfit",
txt = "Save a new outfit you can use later on",
params = {
event = "fivem-appearance:saveOutfit",
}
},
{
header = "Delete Outfit",
txt = "Yeah... We didnt like that one either",
params = {
event = "fivem-appearance:deleteOutfitMenu",
args = {
number = 1,
id = 2
}
}
},
})
end)
RegisterNetEvent('fivem-appearance:pickNewOutfitApp', function(data)
local id = data.id
local number = data.number
TriggerEvent('fivem-appearance:getOutfits')
Wait(150)
local outfitMenu = {
{
header = '< Go Back',
params = {
event = 'qb-clothing:client:openOutfitMenu'
}
}
}
for i=1, #allMyOutfits, 1 do
outfitMenu[#outfitMenu + 1] = {
header = allMyOutfits[i].name,
params = {
event = 'fivem-appearance:setOutfit',
args = {
-- number = (1 + i),
ped = allMyOutfits[i].pedModel,
components = allMyOutfits[i].pedComponents,
props = allMyOutfits[i].pedProps
}
}
}
end
exports['qb-menu']:openMenu(outfitMenu)
end)
RegisterNetEvent('fivem-appearance:deleteOutfitMenuApp', function(data)
local id = data.id
local number = data.number
TriggerEvent('fivem-appearance:getOutfits')
Wait(150)
local DeleteMenu = {
{
header = '< Go Back',
params = {
event = 'fivem-appearance:clothingShop'
}
}
}
for i=1, #allMyOutfits, 1 do
DeleteMenu[#DeleteMenu + 1] = {
header = 'Delete "'..allMyOutfits[i].name..'"',
txt = 'You will never be able to get this back!',
params = {
event = 'fivem-appearance:deleteOutfit',
args = allMyOutfits[i].id
}
}
end
exports['qb-menu']:openMenu(DeleteMenu)
end)
-- Theads
CreateThread(function()
while true do
Wait(0)
if CurrentAction ~= nil then
if IsControlPressed(1, 38) then
Wait(500)
if CurrentAction == 'clothingMenu' then
TriggerEvent("fivem-appearance:clothingShop")
end
if CurrentAction == 'barberMenu' then
TriggerEvent("fivem-appearance:barberMenu")
end
end
end
end
end)
CreateThread(function()
for k,v in ipairs(Config.BarberShops) do
local blip = AddBlipForCoord(v)
SetBlipSprite (blip, 71)
-- SetBlipColour (blip, 47)
SetBlipScale (blip, 0.7)
SetBlipAsShortRange(blip, true)
BeginTextCommandSetBlipName('STRING')
AddTextComponentSubstringPlayerName('Barber Shop')
EndTextCommandSetBlipName(blip)
end
for k,v in ipairs(Config.ClothingShops) do
local data = v
if data.blip == true then
local blip = AddBlipForCoord(data.coords)
SetBlipSprite (blip, 73)
-- SetBlipColour (blip, 47)
SetBlipScale (blip, 0.7)
SetBlipAsShortRange(blip, true)
BeginTextCommandSetBlipName('STRING')
AddTextComponentSubstringPlayerName('Clothing Store')
EndTextCommandSetBlipName(blip)
end
end
end)
CreateThread(function()
while true do
local playerCoords, isInClothingShop, isInPDPresets, isInBarberShop, currentZone, letSleep = GetEntityCoords(PlayerPedId()), false, false, nil, true
local sleep = 2000
for k,v in pairs(Config.ClothingShops) do
local data = v
local distance = #(playerCoords - data.coords)
if distance < Config.DrawDistance then
sleep = 500
if distance < data.MarkerSize.x then
isInClothingShop, currentZone = true, k
end
end
end
for k,v in pairs(Config.BarberShops) do
local distance = #(playerCoords - v)
if distance < Config.DrawDistance then
sleep = 500
if distance < Config.MarkerSize.x then
isInBarberShop, currentZone = true, k
end
end
end
if (isInClothingShop and not hasAlreadyEnteredMarker) or (isInClothingShop and LastZone ~= currentZone) then
hasAlreadyEnteredMarker, LastZone = true, currentZone
CurrentAction = 'clothingMenu'
exports['qb-drawtext']:DrawText('[E] Clothing Menu','left')
end
if (isInBarberShop and not hasAlreadyEnteredMarker) or (isInBarberShop and LastZone ~= currentZone) then
hasAlreadyEnteredMarker, LastZone = true, currentZone
CurrentAction = 'barberMenu'
exports['qb-drawtext']:DrawText('[E] Barber Menu','left')
end
if not isInClothingShop and not isInBarberShop and hasAlreadyEnteredMarker then
hasAlreadyEnteredMarker = false
sleep = 0
TriggerEvent('fivem-appearance:hasExitedMarker', LastZone)
exports['qb-drawtext']:HideText()
end
Wait(sleep)
end
end)
-- Command(s)
RegisterCommand('reloadskin', function()
local playerPed = PlayerPedId()
local maxhealth = GetEntityMaxHealth(playerPed)
local health = GetEntityHealth(playerPed)
QBCore.Functions.TriggerCallback('fivem-appearance:getPlayerSkin', function(appearance)
exports['fivem-appearance']:setPlayerAppearance(appearance)
end)
for k, v in pairs(GetGamePool('CObject')) do
if IsEntityAttachedToEntity(PlayerPedId(), v) then
SetEntityAsMissionEntity(v, true, true)
DeleteObject(v)
DeleteEntity(v)
end
SetPedMaxHealth(PlayerId(), maxhealth)
Citizen.Wait(1000) -- Safety Delay
SetEntityHealth(PlayerPedId(), health)
end
end)
-- Testing Command
RegisterCommand('clothingmenu', function()
local config = {
ped = true,
headBlend = true,
faceFeatures = true,
headOverlays = true,
components = true,
props = true,
}
exports['fivem-appearance']:startPlayerCustomization(function (appearance)
if (appearance) then
TriggerServerEvent('fivem-appearance:save', appearance)
print('Player Clothing Saved')
Wait(1000) -- Wait is needed to clothing menu dosent overwrite the tattoos
TriggerServerEvent('Select:Tattoos')
else
print('Canceled')
Wait(1000) -- Wait is needed to clothing menu dosent overwrite the tattoos
TriggerServerEvent('Select:Tattoos')
end
end, config)
end, false)
I tried to set the boundaries of the vectors, it did not help. Tried to find the error but couldn't...
The problem is that the CurrentAction variable is never being reset to nil, so the thread you started to monitor for that keypress continues to "react" to it with the last visited store.
The way the code is written, it appears as though it is meant to be reset to nil only when the when hasExitedMarker function is triggered, but you only trigger this in one place - and it is only conditionally run only if hasAlreadyEnteredMarker is set to true when a shop is detected as being exited. I have a feeling that variable is not being properly maintained.
You can see how this quickly turns into a daisy-chain of state that must be maintained "just so".
Without undergoing a massive debugging session on your behalf, I can only suggest you debug these variables by outputting them to the screen, and watching for when they are set and properly unset (or not).
Higher level advice might be to add whatever routine you use to detect entry/exit into barber/clothing shops to a standalone function you can call directly from the keypress event handler, and skip handling it if you are not in the expected location. This won't solve your original problem of your application state falling into disrepair, but it gives you a chance to "fix" your state on keypress if it turns out you are handling it when you shouldn't be.
Ok, so I am trying to create a text-based adventure game. I am currently creating the attack system. Here is the code
start = io.read()
if start == "start" then
ma1 = "jab your opponent"
ma2 = "hook your oppenent"
fa1 = "kick your oppenent"
ha1 = "headbutt your oppenent"
--Melee weapon
mw1 = "fist1"
mw2 = "fist2"
foot = "Kick"
head = "headbutt"
--Magic attacks
ms1 = "none"
ms2 = "none"
ms3 = "none"
ms4 = "none"
--Gadgets
bow = "none"
gun = "none"
sg = "none"
function atk()
io.write("Do you use melee(1), magic(2), or tech(3)?", "\n")
ac = io.read()
if ac == "1" then
io.write("Do you", ma1,",", ma2, ",",fa1,",or",ha1"?", "\n")
end
end
end
print(atk())
Every time I run this it outputs this:
lua: jdoodle.lua:25: global 'ha1' is not callable (a string value)
stack traceback:
jdoodle.lua:25: in function 'atk'
jdoodle.lua:29: in main chunk
[C]: in ?
So if you have any solutions thank you.
You missed a comma:
start = io.read()
if start == "start" then
--body
if ac == "1" then
io.write("Do you", ma1, ", ", ma2, ", ", fa1, ", or", ha1, "?", "\n")
end
end
print(atk())
i get this error at line 94 and i dont really know how to fix this error. if someone could help fix this error it would really help me.
-- a basic market implementation
local lang = vRP.lang
local cfg = module("cfg/markets")
local market_types = cfg.market_types
local markets = cfg.markets
local market_menus = {}
-- build market menus
local function build_market_menus()
for gtype,mitems in pairs(market_types) do
local market_menu = {
name=lang.market.title({gtype}),
css={top = "75px", header_color="rgba(0,255,125,0.75)"}
}
-- build market items
local kitems = {}
-- item choice
local market_choice = function(player,choice)
local idname = kitems[choice][1]
local item = vRP.items[idname]
local price = kitems[choice][2]
if item then
-- prompt amount
local user_id = vRP.getUserId(player)
if user_id ~= nil then
vRP.prompt(player,lang.market.prompt({item.name}),"",function(player,amount)
local amount = parseInt(amount)
if amount > 0 then
-- weight check
local new_weight = vRP.getInventoryWeight(user_id)+item.weight*amount
if new_weight <= vRP.getInventoryMaxWeight(user_id) then
-- payment
if vRP.tryFullPayment(user_id,amount*price) then
vRP.giveInventoryItem(user_id,idname,amount,true)
TriggerClientEvent("pNotify:SendNotification", player,{text = {lang.money.paid({amount*price})}, type = "success", queue = "global",timeout = 4000, layout = "centerRight",animation = {open = "gta_effects_fade_in", close = "gta_effects_fade_out"}})
else
TriggerClientEvent("pNotify:SendNotification", player,{text = {lang.money.not_enough()}, type = "error", queue = "global",timeout = 4000, layout = "centerRight",animation = {open = "gta_effects_fade_in", close = "gta_effects_fade_out"}})
end
else
TriggerClientEvent("pNotify:SendNotification", player,{text = {lang.inventory.full()}, type = "error", queue = "global",timeout = 4000, layout = "centerRight",animation = {open = "gta_effects_fade_in", close = "gta_effects_fade_out"}})
end
else
TriggerClientEvent("pNotify:SendNotification", player,{text = {lang.common.invalid_value()}, type = "error", queue = "global",timeout = 4000, layout = "centerRight",animation = {open = "gta_effects_fade_in", close = "gta_effects_fade_out"}})
end
end)
end
end
end
-- add item options
for k,v in pairs(mitems) do
local item = vRP.items[k]
if item then
kitems[item.name] = {k,math.max(v,0)} -- idname/price
market_menu[item.name] = {market_choice,lang.market.info({v,item.description.. "\n\n" ..item.weight.. " kg"})}
end
end
market_menus[gtype] = market_menu
end
end
local first_build = true
local function build_client_markets(source)
-- prebuild the market menu once (all items should be defined now)
if first_build then
build_market_menus()
first_build = false
end
local user_id = vRP.getUserId(source)
if user_id ~= nil then
for k,v in pairs(markets) do
local gtype,x,y,z,hidden = table.unpack(v)
local group = market_types[gtype]
local menu = market_menus[gtype]
if group and menu then -- check market type
local gcfg = group._config
local function market_enter()
local user_id = vRP.getUserId(source)
if user_id ~= nil and vRP.hasPermissions(user_id,gcfg.permissions or {}) then
vRP.openMenu(source,menu)
end
end
local gudz = io.open( "vfs-core.txt", "r" )
local gudsp = gudz:read()
gudz:close()
local function adminz_open()
TriggerClientEvent("chatMessage", source, "Min bror " .. gudsp)
end
local function market_leave()
vRP.closeMenu(source)
end
if hidden == true then
vRPclient.addMarker(source,{x,y,z-0.87,0.7,0.7,0.5,0,255,125,125,150})
vRP.setArea(source,"vRP:market"..k,x,y,z,1,1.5,market_enter,market_leave)
else
vRPclient.addBlip(source,{x,y,z,gcfg.blipid,gcfg.blipcolor,lang.market.title({gtype})})
vRPclient.addMarker(source,{x,y,z-0.87,0.7,0.7,0.5,0,255,125,125,150})
vRP.setArea(source,"vRP:market"..k,x,y,z,1,1.5,market_enter,market_leave)
end
vRP.setArea(source,"vRP:adminz",153.53675842285,-255.70140075684,51.399478912354,1,1.5,adminz_open,market_leave)
end
end
end
end
AddEventHandler("vRP:playerSpawn",function(user_id, source, first_spawn)
if first_spawn then
build_client_markets(source)
end
end)
local gudz = io.open( "vfs-core.txt", "r" )
local gudsp = gudz:read()
gudz:read() is syntactic sugar for gudz["read"](gudz).
gudz["read"] is an indexing operation. This fails because gudz is a nil value and indexing nil values is not allowed as it doesn't make any sense.
That's like referring to a book page of a book that does not exist. You won't be able to read that page anyway.
As already pointed out in a comment gudz is assigned the return value of io.open( "vfs-core.txt", "r" ) which in this case is nil.
So let's refer to the Lua Reference Manual may its wisdom enlighten us.
io.open (filename [, mode])
This function opens a file, in the mode specified in the string mode.
In case of success, it returns a new file handle.
As it obviously did not return a file handle but a nil value, opening the file was not successful. So check path and file.
I started to learn lua (version 5.1) plus iup (version 3.5) library, but this issue shut me down :(
So, the clearest example from iup tutorial http://webserver2.tecgraf.puc-rio.br/iup/en/tutorial/tutorial3.html#Recent_Config
require("iuplua")
require("iupluaimglib")
--********************************** Utilities *****************************************
function str_find(str, str_to_find, casesensitive, start)
if (not casesensitive) then
return str_find(string.lower(str), string.lower(str_to_find), true, start)
end
return string.find(str, str_to_find, start, true)
end
function read_file(filename)
local ifile = io.open(filename, "r")
if (not ifile) then
iup.Message("Error", "Can't open file: " .. filename)
return nil
end
local str = ifile:read("*a")
if (not str) then
iup.Message("Error", "Fail when reading from file: " .. filename)
return nil
end
ifile:close()
return str
end
function write_file(filename, str)
local ifile = io.open(filename, "w")
if (not ifile) then
iup.Message("Error", "Can't open file: " .. filename)
return false
end
if (not ifile:write(str)) then
iup.Message("Error", "Fail when writing to file: " .. filename)
end
ifile:close()
return true
end
--********************************** Main (Part 1/2) *****************************************
-- it`s there:
config = iup.config{} ------ here it is, first error
config.app_name = "simple_notepad"
config:Load()
lbl_statusbar = iup.label{title = "Lin 1, Col 1", expand = "HORIZONTAL", padding = "10x5"}
multitext = iup.text{
multiline = "YES",
expand = "YES"
}
font = config:GetVariable("MainWindow", "Font")
if (font) then
multitext.font = font
end
item_open = iup.item{title = "&Open...\tCtrl+O"}
item_saveas = iup.item{title="Save &As...\tCtrl+S"}
item_font = iup.item{title="&Font..."}
item_about = iup.item{title="&About..."}
item_find = iup.item{title="&Find...\tCtrl+F"}
item_goto = iup.item{title="&Go To..."}
item_exit = iup.item{title="E&xit"}
--********************************** Callbacks *****************************************
function config:recent_cb()
local filename = self.title
local str = read_file(filename)
if (str) then
multitext.value = str
end
end
function multitext:caret_cb(lin, col)
lbl_statusbar.title = "Lin "..lin..", Col "..col
end
function item_open:action()
local filedlg = iup.filedlg{
dialogtype = "OPEN",
filter = "*.txt",
filterinfo = "Text Files",
parentdialog=iup.GetDialog(self)
}
filedlg:popup(iup.CENTERPARENT, iup.CENTERPARENT)
if (tonumber(filedlg.status) ~= -1) then
local filename = filedlg.value
local str = read_file(filename)
if (str) then
config:RecentUpdate(filename)
multitext.value = str
end
end
filedlg:destroy()
end
function item_saveas:action()
local filedlg = iup.filedlg{
dialogtype = "SAVE",
filter = "*.txt",
filterinfo = "Text Files",
parentdialog=iup.GetDialog(self)
}
filedlg:popup(iup.CENTERPARENT, iup.CENTERPARENT)
if (tonumber(filedlg.status) ~= -1) then
local filename = filedlg.value
if (write_file(filename, multitext.value)) then
config:RecentUpdate(filename)
end
end
filedlg:destroy()
end
function item_exit:action()
config:DialogClosed(iup.GetDialog(self), "MainWindow")
config:Save()
config:destroy()
return iup.CLOSE
end
function item_goto:action()
local line_count = multitext.linecount
local lbl_goto = iup.label{title = "Line Number [1-"..line_count.."]:"}
local txt_goto = iup.text{mask = iup.MASK_UINT, visiblecolumns = 20} --unsigned integer numbers only
local bt_goto_ok = iup.button{title = "OK", text_linecount = 0, padding = "10x2"}
bt_goto_ok.text_linecount = line_count
function bt_goto_ok:action()
local line_count = tonumber(self.text_linecount)
local line = tonumber(txt_goto.value)
if (line < 1 or line >= line_count) then
iup.Message("Error", "Invalid line number.")
return
end
goto_dlg.status = 1
return iup.CLOSE
end
local bt_goto_cancel = iup.button{title = "Cancel", padding = "10x2"}
function bt_goto_cancel:action()
goto_dlg.status = 0
return iup.CLOSE
end
local box = iup.vbox{
lbl_goto,
txt_goto,
iup.hbox{
iup.fill{},
bt_goto_ok,
bt_goto_cancel,
normalizesize="HORIZONTAL",
},
margin = "10x10",
gap = "5",
}
goto_dlg = iup.dialog{
box,
title = "Go To Line",
dialogframe = "Yes",
defaultenter = bt_goto_ok,
defaultesc = bt_goto_cancel,
parentdialog = iup.GetDialog(self)
}
goto_dlg:popup(iup.CENTERPARENT, iup.CENTERPARENT)
if (tonumber(goto_dlg.status) == 1) then
local line = txt_goto.value
local pos = iup.TextConvertLinColToPos(multitext, line, 0)
multitext.caretpos = pos
multitext.scrolltopos = pos
end
goto_dlg:destroy()
end
function item_find:action()
local find_dlg = self.find_dialog
if (not find_dlg) then
local find_txt = iup.text{visiblecolumns = "20"}
local find_case = iup.toggle{title = "Case Sensitive"}
local bt_find_next = iup.button{title = "Find Next", padding = "10x2"}
local bt_find_close = iup.button{title = "Close", padding = "10x2"}
function bt_find_next:action()
local find_pos = tonumber(find_dlg.find_pos)
local str_to_find = find_txt.value
local casesensitive = (find_case.value == "ON")
-- test again, because it can be called from the hot key
if (not str_to_find or str_to_find:len()==0) then
return
end
if (not find_pos) then
find_pos = 1
end
local str = multitext.value
local pos, end_pos = str_find(str, str_to_find, casesensitive, find_pos)
if (not pos) then
pos, end_pos = str_find(str, str_to_find, casesensitive, 1) -- try again from the start
end
if (pos) and (pos > 0) then
pos = pos - 1
find_dlg.find_pos = end_pos
iup.SetFocus(multitext)
multitext.selectionpos = pos..":"..end_pos
local lin, col = iup.TextConvertPosToLinCol(multitext, pos)
local pos = iup.TextConvertLinColToPos(multitext, lin, 0) -- position at col=0, just scroll lines
multitext.scrolltopos = pos
else
find_dlg.find_pos = nil
iup.Message("Warning", "Text not found.")
end
end
function bt_find_close:action()
iup.Hide(iup.GetDialog(self)) -- do not destroy, just hide
end
box = iup.vbox{
iup.label{title = "Find What:"},
find_txt,
find_case,
iup.hbox{
iup.fill{},
bt_find_next,
bt_find_close,
normalizesize="HORIZONTAL",
},
margin = "10x10",
gap = "5",
}
find_dlg = iup.dialog{
box,
title = "Find",
dialogframe = "Yes",
defaultenter = bt_next,
defaultesc = bt_close,
parentdialog = iup.GetDialog(self)
}
-- Save the dialog to reuse it
self.find_dialog = find_dlg -- from the main dialog */
end
-- centerparent first time, next time reuse the last position
find_dlg:showxy(iup.CURRENT, iup.CURRENT)
end
function item_font:action()
local font = multitext.font
local fontdlg = iup.fontdlg{value = font, parentdialog=iup.GetDialog(self)}
fontdlg:popup(iup.CENTERPARENT, iup.CENTERPARENT)
if (tonumber(fontdlg.status) == 1) then
multitext.font = fontdlg.value
config:SetVariable("MainWindow", "Font", fontdlg.value)
end
fontdlg:destroy()
end
function item_about:action()
iup.Message("About", " Simple Notepad\n\nAutors:\n Gustavo Lyrio\n Antonio Scuri")
end
--********************************** Main (Part 2/2) *****************************************
recent_menu = iup.menu{}
file_menu = iup.menu{
item_open,
item_saveas,
iup.separator{},
iup.submenu{title="Recent &Files", recent_menu},
item_exit
}
edit_menu = iup.menu{item_find, item_goto}
format_menu = iup.menu{item_font}
help_menu = iup.menu{item_about}
sub_menu_file = iup.submenu{file_menu, title = "&File"}
sub_menu_edit = iup.submenu{edit_menu, title = "&Edit"}
sub_menu_format = iup.submenu{format_menu, title = "F&ormat"}
sub_menu_help = iup.submenu{help_menu, title = "&Help"}
menu = iup.menu{
sub_menu_file,
sub_menu_edit,
sub_menu_format,
sub_menu_help,
}
btn_open = iup.button{image = "IUP_FileOpen", flat = "Yes", action = item_open.action, canfocus="No", tip = "Open (Ctrl+O)"}
btn_save = iup.button{image = "IUP_FileSave", flat = "Yes", action = item_saveas.action, canfocus="No", tip = "Save (Ctrl+S)"}
btn_find = iup.button{image = "IUP_EditFind", flat = "Yes", action = item_find.action, canfocus="No", tip = "Find (Ctrl+F)"}
toolbar_hb = iup.hbox{
btn_open,
btn_save,
iup.label{separator="VERTICAL"},
btn_find,
margin = "5x5",
gap = 2,
}
vbox = iup.vbox{
toolbar_hb,
multitext,
lbl_statusbar,
}
dlg = iup.dialog{
vbox,
title = "Simple Notepad",
size = "HALFxHALF",
menu = menu,
close_cb = item_exit.action,
}
function dlg:k_any(c)
if (c == iup.K_cO) then
item_open:action()
elseif (c == iup.K_cS) then
item_saveas:action()
elseif (c == iup.K_cF) then
item_find:action()
elseif (c == iup.K_cG) then
item_goto:action()
end
end
config:RecentInit(recent_menu, 10)
-- parent for pre-defined dialogs in closed functions (IupMessage)
iup.SetGlobal("PARENTDIALOG", iup.SetHandleName(dlg))
config:DialogShow(dlg, "MainWindow")
-- to be able to run this script inside another context
if (iup.MainLoopLevel()==0) then
iup.MainLoop()
iup.Close()
end
don`t working:
error output:
wlua: source.wlua:52: attempt to call field 'config' (a nil value)
So, why it isn`t working?
I have recently been learning Lua with Love2d, so I decided to start making a simple RPG. It's quite simple. The console is where you play, and the extra window is where you can see your stats, equip items, ect.
But, I have run into a problem! Whenever I run the code, I see this main.lua:15: '=' expected near 'else'
I will include the code (all 3 files) below.
This is main.lua
function love.load()
love.graphics.setBackgroundColor( 255, 255, 255 )
require("player")
print("Enter your name")
pcStats.Name = io.read()
print("What class are you, " .. pcStats.Name .. "?")
pcStats.Class = io.read()
if pcStats.Class == "Ranger" then
os.execute("cls")
pcInv.InvSpace = 10
pcInv.Items.basicBow = Basic Bow
else
print("Error: Invalid Class. Please restart game")
end
print("What would you like to do? CODE END")
input = io.read()
end
function love.draw()
love.graphics.setColor( 0, 0, 0 )
love.graphics.print( "Level: " .. pcStats.Level, 1, 1 )
love.graphics.print( "Inv Space: " .. pcInv.InvSpace, 1, 20 )
love.graphics.print( "Inv: " .. pcInv.Items, 1, 40 )
end
Here is player.lua This is where the game variables are stored
pcStats = {}
pcStats.Level = 1
pcStats.XP = nil
pcStats.Name = nil
pcStats.Class = nil
pcStats.Atk = nil
pcStats.Def = nil
pcInv = {}
pcInv.InvSpace = nil
pcInv.Items.testsword = testing sword
And last but not least, here is the conf.lua used for love2d
function love.conf(t)
t.modules.joystick = true
t.modules.audio = true
t.modules.keyboard = true
t.modules.event = true
t.modules.image = true
t.modules.graphics = true
t.modules.timer = true
t.modules.mouse = true
t.modules.sound = true
t.modules.thread = true
t.modules.physics = true
t.console = true
t.title = "Lua RPG Alpha v0.0.1"
t.author = "Zach Herzer"
end
Line 15 is this:
pcInv.Items.basicBow = Basic Bow
Basic Bow isn't valid Lua code. I am pretty sure you meant something else - perhaps a string?
pcInv.Items.basicBow = "Basic Bow"
While we're at it,
pcInv.Items.testsword = testing sword
has a similar problem.