Jump to content

Lord Henry

Other Languages Moderators
  • Posts

    4,005
  • Joined

  • Last visited

  • Days Won

    184

Everything posted by Lord Henry

  1. Olá Não é possível. A não ser que você execute um vídeo da cutscene na tela do player a partir de um navegador. Você pode usar a função útil playVideo que executa um vídeo do youtube na tela do jogador.
  2. Você pode simplesmente remover a função que seta skin aleatória no player quando ele nasce. Essa função fica no gamemode Play, no script broph.lua
  3. Cara, copiei seu código e aqui funcionou normal. Mesmo na formatação ANSI e UTF-8 (sem BOM). Tudo normal. Também mudei a interface do MTA para inglês para ver se bugava os acentos mas também funcionou normal. O problema não está no seu código.
  4. O que é? Pra que serve? Um banco de dados é onde ficam salvos diversos tipos de dados que são usados entre as sessões dos jogadores e do servidor, isto significa que mesmo se o jogador relogar no servidor ou até mesmo o servidor reiniciar, os dados salvos no banco de dados não são perdidos. (se o script que salvou lá foi feito corretamente). O que posso salvar neles? O MTA já cria 2 bancos de dados padrão quando vc cria seu servidor, são eles: internal.db - Onde são salvos todos os dados das contas dos jogadores, login, senha, grana do bolso, posição do jogador quando deslogou, vida, colete, skin, armas, munição, etc. registry.db - Onde são salvos todos os dados que são utilizados pelos resources, como por exemplo melhores pontuações das corridas (race gamemode), proprietários das casas, dados bancários dos jogadores, saldo bancário dos jogadores, carros comprados pelos jogadores, roupas compradas pelos jogadores, empresas adquiridas pelos jogadores, etc. Onde eles estão? Estes dois bancos de dados estão na pasta deathmatch do seu servidor, estão na linguagem SQLite. Você ainda pode criar outros bancos de dados externos, para serem usados pelos resources, mas na minha opinião isso não é recomendável, uma vez que vc usaria MySQL, que é mais complexo e exige certos cuidados de acesso e domínio, mas alguns servidores profissionais precisam fazer assim pois fizeram os bancos de dados ficarem fora do servidor em outro IP por segurança, dai é necessário ter bancos de dados externos. Nesse tutorial vamos tratar somente dos bancos de dados nativos do MTA, por serem mais fáceis de entender. Como mexo neles? Para salvar alguma coisa na conta do jogador, isto é, no internal.db, você usa setAccountData, e para obter esses dados depois, use getAccountData. É extremamente simples, funciona da mesma forma que um setElementData, mas em vez de salvar uma data temporária em um elemento, salva uma data permanente numa conta. Porém, para salvar alguma coisa no registry.db, é um pouco mais complicado, uma vez que vc vai precisar criar uma tabela nova para cada resource. Por exemplo, vc acabou de criar um resource de ranking por kills/deaths e você deseja salvar esse ranking no banco de dados para que ao reiniciar o resource ou o servidor, o ranking não seja perdido. Para isso vc vai precisar primeiramente criar uma tabela no banco de dados registry.db, essa tabela será acessada pelo resource, que irá salvar os dados dele lá. Para fazer qualquer coisa neste banco de dados (criar tabelas, inserir, alterar, remover, deletar, inserir colunas em determinada tabela, etc) vc vai precisar usar isso: executeSQLQuery. Aqui, será necessário conhecimento em SQL para fazer isso, mas é mais fácil do que aprender uma linguagem de programação nova, pois suas opções e sintaxes são menores do que uma linguagem inteira de programação, você não vai inventar nenhum sistema novo aqui, apenas criar e gerenciar tabelas e dados. Criar tabela nova no banco de dados: (o Caps Lock não é uma regra, mas é melhor para entender o que é código e o que é nome) [Os seguintes códigos só funcionam server-side] executeSQLQuery ("CREATE TABLE IF NOT EXISTS nomedatabela (nomecoluna1 TEXT, nomecoluna2 REAL, nomecoluna3 INTEGER)") TEXT = Valores desta coluna serão textos. Podem ter símbolos, números e espaços. REAL = Valores desta coluna serão numéricos reais. (números decimais, positivos, negativos e 0.0) INTEGER = Valores desta coluna serão numéricos inteiros. (positivos, negativos e 0) (não existe tipo BOOLEAN, use TEXT e insira valor "false" ou "true") (existe valor NULL, é diferente de vazio e diferente de 0. NULL significa ausência de dados. O NULL aparece quando você cria uma linha ou coluna nova sem atribuir valores a elas.) Deletar tabela do banco de dados: executeSQLQuery ("DROP TABLE nomedatabela") Todas as linhas, colunas, células e valores desta tabela são deletados junto. Deletar linhas da tabela: (as células não ficarão NULL) executeSQLQuery ("DELETE FROM nomedatabela WHERE colunaespecífica=?", valorDaCelulaEspecifica) O ? indica que o valor está após a declaração do SQL. Você poderia colocar o valor direto no lugar do ?. Mas por alguma razão, as vezes isso gera erro. Além disso, se o valor da célula estiver em uma variável no seu script, você não pode declarar a variável no lugar do ?. Ali só pode ser o valor direto, pois a declaração SQL inteira se trata de uma string. Por isso o uso do ?, que está recebendo o valor da variável que está depois da vírgula. Obs: Para verificar se uma célula tem valor nulo, não se usa os operadores lógicos de ==, <= >=. Para isso, usa-se IS NULL ou IS NOT NULL. Ex: executeSQLQuery ("DELETE nomecoluna1,nomecoluna2 FROM nomedatabela WHERE nomecoluna3 IS NULL") Isso vai deletar todas as células da coluna 1 e coluna 2 onde a coluna 3 tem uma célula de valor NULL. Se a coluna 3 não tiver nenhuma célula de valor NULL, nada acontece. Inserir nova linha de valores: (ele vai criar automaticamente uma nova linha com novas células) executeSQLQuery ("INSERT INTO nomedatabela(nomecoluna1,nomecoluna2,nomecoluna3) VALUES(?,?,?)", valorCelulaColuna1, valorCelulaColuna2, valorCelulaColuna3) Neste caso, ele está inserindo 3 novos valores, cada valor em uma coluna. Se você não declarar os nomes das colunas, ele vai preencher na ordem das colunas automaticamente. Você pode deixar de declarar uma coluna se não quiser atribuir valor na célula daquela coluna. Se o tipo de valor da variável não for do tipo de dado daquela coluna, dará erro. Atualizar valores de células que já existem em uma tabela: (não é possível alterar os tipos de valores, é necessário editar o tipo da coluna se quiser fazer isso) executeSQLQuery ("UPDATE nomedatabela SET nomecoluna2=?,nomecoluna3=? WHERE nomecoluna1=?", valorCelulaColuna2, valorCelulaColuna3, valorCelulaColuna1) No caso acima, ele vai atualizar as células das colunas 2 e 3 onde o valor da célula da coluna 1 for igual ao valor de valorColunaCelula1. OBS: Nada impede que você coloque as primeiras variáveis junto à declaração SQL, mas para fazer isso você deve "cortar" a string, inserir as variáveis e depois continuar a string, Ex: executeSQLQuery ("UPDATE nomedatabela SET nomecoluna2= '".. valorCelulaColuna2 .."',nomecoluna3='".. valorCelulaColuna2 .."' WHERE nomecoluna1=?", valorCelulaColuna1) Lembrando que o valor destas variáveis também são strings na declaração, portanto use aspas simples antes e depois de cada corte para transformar os valores em string. Os dois pontos (..) significam que estes valores fazem parte do argumento SQL. Da mesma forma, se vc usar "1" .. "1", será igual a "11". (Por isso acho muito mais fácil deixar tudo ? na declaração SQL e colocar as variáveis todas após a string.) Selecionar determinadas células da tabela: (usado geralmente para obter os valores destas células para usar no script, você pode selecionar somente 1 célula ou várias) executeSQLQuery ("SELECT nomecoluna1,nomecoluna2 FROM nomedatabela WHERE nomecoluna3=?", valorCelulaColuna3) Neste exemplo, ele vai selecionar a célula da coluna 1 e a célula da coluna 2, na linha onde a célula da coluna 3 for igual a valorCelulaColuna3. Alterar a tabela (adicionar coluna nova) [SQLite não suporta deletar coluna nem editar tipo de coluna] executeSQLQuery ("ALTER TABLE nomedatabela ADD nomecoluna4 REAL") Devido a limitações do SQLite, ALTER TABLE não pode ser usado para deletar uma coluna nem para editar seu tipo. Para fazer isso é necessário recriar a tabela inteira com as novas alterações. No exemplo acima, ele vai adicionar uma nova coluna chamada "nomecoluna4". Tá, mas como ficaria tudo isso dentro de um script? Fiz um código com vários testes de banco de dados. Cada comando faz alguma coisa. É possível mexer em um banco de dados manualmente sem usar scripts? Sim, é possível. Eu mesmo costumo fazer isso para corrigir algumas coisas rápidas sem precisar programar mais nada. Para poder abrir os bancos de dados (internal.db e registry.db) você deve usar um programa chamado DB Browser for SQLite. Um programa gratuito, leve e bem fácil de entender. Nele você consegue acessar todas as tabelas do banco de dados e editar os valores como se fosse em uma planilha do Excel. Basta ir na aba Navegar dados, selecionar a tabela que deseja modificar, clicar em cima da célula cujo valor deseja atualizar, digitar o novo valor, clicar em Aplicar e depois clicar em Escrever modificações (salvar banco de dados). Pronto! E tem mais! Se você já tiver conhecimento avançado com a linguagem SQL, você também pode fazer alterações avançadas via código dentro do programa. Basta acessar a aba Executar SQL, escrever o comando SQL corretamente e depois clicar no botão de Play. Espero ter ajudado.
  5. Sempre vai existir os espertinhos pra tentar burlar seu sistema. E isso é ótimo, pois você se obriga a estudar melhor seu script em busca de novas proteções e isso faz você melhorar na programação. Eu por exemplo, depois que os meus resources postados no community do MTA foram roubados e repostados em sites de terceiros sem minha autorização, eu parei de publicar meus resources e inventei um sistema de proteção por IP + Senha. Cada resource possui uma senha própria que é verificada por outro resource que eu criei. E esse outro resource verifica o IP do servidor, se for um IP diferente do IP que o resource está pedindo, cancela a ativação daquele resource. E se por acaso o cara for espertinho e tirar a permissão de stopResource dele, então o próprio resource nem vai iniciar e dará erro de inicialização. Os resources não precisam de permissão para cancelar sua própria ativação. O esquema das senhas eu criei pois se o cara for um programador experiente, ele pode tentar criar um resource que sempre retorne um IP válido, mesmo não sendo o IP real do servidor. Mas sem a senha correta do resource, não vai adiantar. Eu pensei em tudo e claro, está tudo compilado e somente os desenvolvedores do MTA possuem o descompilador. (perdão por desviar do assunto do tópico)
  6. Tirando o fato de não estudar lógica de programação? Huahauahauhaua zoas. Estávamos apenas discutindo um jeito melhor de resolver seu problema sem usar setElementData no player.
  7. -------------------------------- Eu fiz algo assim pois precisei bloquear o uso do realdriveby em Las Venturas, pois lá eu criei zonas de domínio e portanto fica abusivo atirar de dentro de veículos. Mas em vez de eu criar um colShape gigante, apenas peguei a posição do player e usei getZoneName, se ela for igual a "Las Venturas", bloqueia e cancela tudo, caso contrário, funciona normalmente.
  8. A verificação funcionaria. Mas precisaria cancelar a ação de mirar e atirar do realdriveby. Por exemplo: O player inicia o realdriveby fora da zona, entra com o veículo dentro da zona ainda mirando e começa a atirar. Ao atirar é necessário outra verificação para cancelar o realdriveby do jogador se ele estiver dentro da zona.
  9. -- (No realdriveby) function disableOnShot (weapon, ammo, ammoInClip, hitX, hitY, hitZ, hitElement) -- Executa essa função quando o player atira usando o realdriveby. if isPedDoingGangDriveby (source) then -- Se o jogador está fazendo realdriveby, então: local allZones = getElementsByType ("colshape") -- allZones recebe todas as as zonas de colisão do server, incluindo as que não são áreas verdes. for i, shape in ipairs (allZones) do -- Para cada zona de colisão, faz o seguinte: if getElementData (shape, "areaverde") then -- Se essa zona for uma área verde, então: if isElementWithinColShape (localPlayer, shape) then -- Se o jogador estiver dentro dessa área verde, então: outputChatBox ("Não atire em Áreas Verdes com veículo!", 255, 0, 0) -- Manda isso pro jogador. setTimer (function () -- Depois de 100 milisegundos, faz o seguinte: (precisa de um timer pra não bugar a animação) setPedDoingGangDriveby (localPlayer, false) -- Cancela o realdriveby e o jogador volta a dirigir normalmente. (mas o primeiro tiro foi dado) setPedWeaponSlot (localPlayer, 0) -- Daqui pra baixo é tudo igual ao que acontece quando o player sai do realdriveby por conta própria. limitDrivebySpeed (switchToWeapon) toggleControl ("vehicle_look_left", true) toggleControl ("vehicle_look_right", true) toggleControl ("vehicle_secondary_fire", true) toggleTurningKeys (vehicleID, true) -- fadeOutHelp() removeEventHandler ("onClientPlayerVehicleExit", localPlayer, removeKeyToggles) end, 100, 1) end end end end end addEventHandler ("onClientPlayerWeaponFire", localPlayer, disableOnShot) function toggleDriveby() -- Executa essa função quando o player clica com o botão direito do mouse. if not isPedInVehicle (localPlayer) then return end -- Se o jogador não está em um veículo, ignora essa função e nem funciona. local vehicleID = getElementModel (getPedOccupiedVehicle (localPlayer)) if settings.blockedVehicles[vehicleID] then return end -- Se for um veículo proibido, ignora essa função e nem funciona. local equipedWeapon = getPedWeaponSlot (localPlayer) if equipedWeapon == 0 then -- Se o jogador está sem arma na mão (ou com o soco inglês), então: local allZones = getElementsByType ("colshape") -- allZones recebe todas as as zonas de colisão do server, incluindo as que não são áreas verdes. for i, shape in ipairs (allZones) do -- Para cada zona de colisão, faz o seguinte: if getElementData (shape, "areaverde") then -- Se essa zona for uma área verde, então: if isElementWithinColShape (localPlayer, shape) then -- Se o jogador estiver dentro dessa área verde, então: outputChatBox ("Não é permitido realdriveby em Áreas Verdes!", 255, 0, 0) -- Manda isso pro jogador. return -- Cancela essa função e o driveby nem inicia. end end end -- Daqui pra baixo é tudo igual, faz o realdriveby funcionar. if ( driver ) then weaponsTable = settings.driver else weaponsTable = settings.passenger end --We need to get the switchTo weapon by finding any valid IDs local switchTo local switchToWeapon local lastSlotAmmo = getPedTotalAmmo ( localPlayer, lastSlot ) if not lastSlotAmmo or lastSlotAmmo == 0 or getSlotFromWeapon(getPedWeapon (localPlayer,lastSlot)) == 0 then for key,weaponID in ipairs(weaponsTable) do local slot = getSlotFromWeapon ( weaponID ) local weapon = getPedWeapon ( localPlayer, slot ) if weapon == 1 then weapon = 0 end --If its a brass knuckle, set it to a fist to avoid confusion --if the weapon the player has is valid if weapon == weaponID then --If the ammo isn't 0 if getPedTotalAmmo ( localPlayer, slot ) ~= 0 then --If no switchTo slot was defined, or the slot was 4 (SMG slot takes priority) if not switchTo or slot == 4 then switchTo = slot switchToWeapon = weaponID end end end end else local lastSlotWeapon = getPedWeapon ( localPlayer, lastSlot ) for key,weaponID in ipairs(weaponsTable) do --If our last used weapon is a valid weapon if weaponID == lastSlotWeapon then switchTo = lastSlot switchToWeapon = lastSlotWeapon break end end end --If a valid weapon was not found, dont set anything. if not switchTo then return end setPedDoingGangDriveby ( localPlayer, true ) setPedWeaponSlot( localPlayer, switchTo ) --Setup our driveby limiter limitDrivebySpeed ( switchToWeapon ) --Disable look left/right keys, they seem to become accelerate/decelerate (carried over from PS2 version) toggleControl ( "vehicle_look_left",false ) toggleControl ( "vehicle_look_right",false ) toggleControl ( "vehicle_secondary_fire",false ) toggleTurningKeys(vehicleID,false) addEventHandler ( "onClientPlayerVehicleExit",localPlayer,removeKeyToggles ) local prevw,nextw = next(getBoundKeys ( "Previous driveby weapon" )),next(getBoundKeys ( "Next driveby weapon" )) if prevw and nextw then if animation then Animation:remove() end helpText:text( "Press '"..prevw.."' or '"..nextw.."' to change weapon" ) fadeInHelp() setTimer ( fadeOutHelp, 10000, 1 ) end else --If so, unequip it setPedDoingGangDriveby ( localPlayer, false ) setPedWeaponSlot( localPlayer, 0 ) limitDrivebySpeed ( switchToWeapon ) toggleControl ( "vehicle_look_left",true ) toggleControl ( "vehicle_look_right",true ) toggleControl ( "vehicle_secondary_fire",true ) toggleTurningKeys(vehicleID,true) fadeOutHelp() removeEventHandler ( "onClientPlayerVehicleExit",localPlayer,removeKeyToggles ) end end addCommandHandler ( "Toggle Driveby", toggleDriveby ) -- Tem o resto do código do realdriveby pra baixo, esse código acima não é o script inteiro. Então isso deve resolver.
  10. No lugar do print ("3"), coloque print (getPlayerName(v)) e nos diga o que aparece.
  11. Quando o player receber uma mensagem, seta uma data nele com o nome do jogador que enviou. Dai quando o player usar o comando /r <resposta>, funciona como um PM normal, mas em vez dele digitar o nome do cara pra responder, pega automaticamente o nome que estiver na data e envia a resposta pra ele.
  12. Como vc quer ajudar se vc é novato? Se vc tivesse experiência e tivesse feito um bom tutorial, dai beleza.
  13. Não entendi nada. E você criou um post que já existe.
  14. Cara. Isso é básico de ser feito. Vou fazer esse exemplo genérico: addEventHandler ("onColShapeHit", getRootElement(), function (hitElement) if getElementData (source, "areaverde") then -- Se a zona que o jogador colidiu for uma área verde, então: if hitElement and getElementType (hitElement) == "player" then setElementData (hitElement, "protegido", true) end end end) addEventHandler ("onColShapeLeave", getRootElement(), function (leaveElement) if getElementData (source, "areaverde") then -- Se a zona que o jogador saiu for uma área verde, então: if leaveElement and getElementType (leaveElement) == "player" then setElementData (leaveElement, "protegido", false) end end end)
  15. Se sua área verde já está setando uma data no player, então só colocar a verificação no realdriveby.
  16. Eu fiz uma que seta uma data no jogador quando ele entra na área verde e remove essa data quando ele sai. Dai editei o realdriveby para não funcionar se o jogador estiver com essa data. -- É mais ou menos isso que eu coloquei no realdriveby. if getElementData (thePlayer, "protected") then -- Se o jogador tem uma data "protected", então: return end -- Cancela tudo e nada acontece. O jogador não faz o realdriveby. end
  17. Pq vc não cria o pickup de dinheiro em vez de um marker? Dai vc usa um onPickupHit.
  18. Então amigo. Provavelmente não foi você quem fez esse script, senão saberia do motivo dele estar por ElementData em vez de ACL.
  19. Sim. É uma função de outro resource.
  20. Não tem nenhum outputMessage na minha concessionária. Mas no seu, ele usa a função "scr-Lib" exportada de outro resource. Para fazer isso verifique se o correspondente resource existe e se está ativado.
  21. Só vc baixar aquela concessionária que eu mandei no começo. Eu que fiz aquela. -------------------------------------------- No caso, o marker foi criado no client. Mas no client não tem como verificar se a conta do player é Guest ou não. Para contornar isso, usei um setElementData pelo server.lua no jogador quando ele faz login e removo essa data quando ele desloga. Dai a única coisa que o client faz é verificar se o jogador tem essa data, se tiver então ele está logado e permite o acesso. Se não tiver essa data então bloqueia o acesso. Caso seja muito difícil pra vc procurar pelo script, a parte do setElementData que está no server.lua é a partir da linha 408 e a parte que permite/bloqueia o acesso na concessionária do client.lua está a partir da linha 615.
×
×
  • Create New...