Advertisement
dwIndex

Landscape

Mar 22nd, 2021 (edited)
259
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 17.50 KB | None | 0 0
  1. tfm.exec.disableAutoNewGame(true)
  2. tfm.exec.disableAutoShaman(true)
  3. tfm.exec.disableAutoTimeLeft(true)
  4. tfm.exec.disableAfkDeath(true)
  5.  
  6. system.disableChatCommandDisplay(nil)
  7.  
  8. modulo_name = "Landscape"
  9. modulo_creator = "Indexinel#5948"
  10.  
  11. room = {
  12.     total_players = 0,
  13.     alive_players = 0,
  14.     players = {
  15.         name = nil,
  16.         facingRight = true,
  17.         facingLeft = false,
  18.         movingRight = false,
  19.         movingLeft = false,
  20.         isAlive = false,
  21.         deathTimestamp = nil,
  22.         deathType = nil,
  23.         projectile = {
  24.             timestamp = os.time(),
  25.             offsets = {
  26.                 x = 20, y = 0          
  27.             }
  28.         },
  29.         ballon = {
  30.             id = nil,
  31.             timestamp = 0
  32.         },
  33.         trampoline = {
  34.             id = nil,
  35.             timestamp = 0
  36.         },
  37.         second_jump = {
  38.             timestamp = 0,
  39.             cooldown = 10000
  40.         }
  41.     },
  42.     map = {
  43.         current = nil,
  44.         last = nil,
  45.         height = nil,
  46.         width = nil,
  47.         grounds = nil,
  48.         shamanObjects = nil,
  49.         anchorages = {
  50.             id = nil,
  51.             x = nil,
  52.             y = nil
  53.         }
  54.     },
  55.     anvils = {
  56.         id = nil,
  57.         timestamp = 0
  58.     },
  59.     cooldown_time = 1500,
  60.     game_time = 3*60,
  61.     time_remaining = 0,
  62.     elapsed_time = 0,
  63.     killTextTimestamp = nil,
  64.     lang = "es"
  65. }
  66.  
  67. keys = {
  68.     0, -- [lArrow + A]
  69.     1, -- [uArrow + W]
  70.     2, -- [rArrow + D]
  71.     3, -- [dArrow + S]
  72.     32, -- [SPACE]
  73.     67, -- [C]
  74.     71, -- [G]
  75.     72, -- [H]
  76.     75, -- [J]
  77.     80, -- [P]
  78.     85, -- [U]
  79.     88, -- [X]
  80.     90 -- [Z]
  81. }
  82.  
  83. users = {}
  84.  
  85. projectile = {35}
  86. projspeed = 40
  87. builds = {}
  88.  
  89. despawn = {}
  90. despawn_time = 2500
  91.  
  92. maps = {7842602}
  93.  
  94. victoryControl = {
  95.     status = false,
  96.     timestamp = nil,
  97.     winner = nil,
  98.     hold = 5000
  99. }
  100.  
  101. acid = {
  102.     id = 0,
  103.     bodydef = {
  104.         type=19,
  105.         width=nil,
  106.         height=200,
  107.         foreground=true,
  108.         fiction=0.0,
  109.         restitution=0.0,
  110.         angle=0,
  111.         color=0,
  112.         miceCollision=true,
  113.         groundCollision=false,
  114.         dynamic=false,
  115.         fixedRotation=true,
  116.         mass=0,
  117.         linearDamping=0.0,
  118.         angularDamping=0.0
  119.     },
  120.     relative_height = 0,
  121.     timestamp = nil,
  122.     elevation_tick = 10,
  123.     rise_hold = 500,
  124.     start_delay = 10000
  125. }
  126.  
  127. text = {}
  128.  
  129. text["en"] = {
  130.     ui = {
  131.         help = {
  132.             title = "Help",
  133.             description = ""..modulo_name.." is a unofficial module created by "..modulo_creator.." in which there's an acid rising and you shall escape.",
  134.             desc2 = "You can shoot arrows and invoke various objects to be the last one!"
  135.         },
  136.         settings = {
  137.             title = "Settings",
  138.             description = "Configurate your settings here."
  139.         },
  140.         profile = {
  141.             title = "Profile",
  142.             description = "%s's data",
  143.             rounds_played = "Rounds Played:",
  144.             games_won = "Games Won:",
  145.         },
  146.         tclose = "Close",
  147.         controls = {
  148.             title = "Controls"
  149.         }
  150.     },
  151.     warnings = {
  152.         trampoline = {
  153.             not_available = "You can't put a <VI>trampoline</VI> right now!",
  154.             used = "<R>You used your only trampoline in this round.</R>"
  155.         },
  156.         ballon = {
  157.             not_available = "You will be able to put a ballon in <J>%0.2f</J> seconds."
  158.         },
  159.         second_jump = {
  160.             not_available = "Your second jump will be reloaded in <J>%0.2f</J> seconds."
  161.         },
  162.         command_not = "<R>The command <J>%s</J> does not exists.</R>"
  163.     },
  164.     alerts = {
  165.         acid_rising = "<CH>The</CH> <VP>acid</VP> <CH>is rising!</CH>",
  166.         touch_acid = "<R>You fall into acid!</R>",
  167.         fall_vacuum = "You fall into vacuum!",
  168.         death_causes = {
  169.             touch_acid = "<V>%s</V> fall into acid.",
  170.             fall_vacuum = "It seems that <V>%s</V> fall into vacuum.",
  171.             unknown = "Something unknown killed <V>%s</V>."
  172.         }
  173.     }
  174. }
  175.  
  176. text["es"] = {
  177.     ui = {
  178.         help = {
  179.             title = "Ayuda",
  180.             description = ""..modulo_name.." es un módulo no oficial creado por "..modulo_creator.." en el que hay un ácido subiendo y debes escapar.",
  181.             desc2 = "¡Puedes disparar flechas e invocar diversos objetos para ser el último en pie!"
  182.         },
  183.         settings = {
  184.             title = "Ajustes",
  185.             description = "Configura tus ajustes aquí."
  186.         },
  187.         profile = {
  188.             title = "Perfil",
  189.             description = "Datos de %s",
  190.             rounds_played = "Rondas Jugadas:",
  191.             games_won = "Partidas ganadas:",
  192.         },
  193.         tclose = "Cerrar",
  194.         controls = {
  195.             title = "Controles"
  196.         }
  197.     },
  198.     warnings = {
  199.         trampoline = {
  200.             not_available = "¡No puedes poner un <VI>trampolín</VI> en este momento!",
  201.             used = "<R>Has usado tu único trampolín en esta ronda.</R>"
  202.         },
  203.         ballon = {
  204.             not_available = "Podrás poner un globo en <J>%0.2f</J> segundos."
  205.         },
  206.         second_jump = {
  207.             not_available = "Tu segundo salto será recargado en <J>%0.2f</J> segundos."
  208.         },
  209.         command_not = "<R>El comando <J>%s</J> no existe</R>"
  210.     },
  211.     alerts = {
  212.         acid_rising = "<CH>¡El </CH> <VP>ácido</VP> <CH>está subiendo!</CH>",
  213.         touch_acid = "<R>¡El ácido te ha alcanzado!</R>",
  214.         fall_vacuum = "¡Te has caído al vacio!",
  215.         death_causes = {
  216.             touch_acid = "<V>%s</V> cayó en el ácido.",
  217.             fall_vacuum = "Parece ser que <V>%s</V> cayó al vacio.",
  218.             unknown = "Algo desconocido causó la muerte de <V>%s</V>."
  219.         }
  220.     }
  221. }
  222.  
  223. function startPlayer(playerName)
  224.     room.players[playerName] = {
  225.         name = playerName.name,
  226.         facingRight = true,
  227.         facingLeft = false,
  228.         movingRight = false,
  229.         movingLeft = false,
  230.         isAlive = true,
  231.         deathTimestamp = nil,
  232.         deathType = nil,
  233.         projectile = {
  234.             timestamp = os.time(),
  235.             offsets = {
  236.                 x = 20, y = 0          
  237.             }
  238.         },
  239.         ballon = {
  240.             id = nil,
  241.             timestamp = 0
  242.         },
  243.         trampoline = {
  244.             id = nil,
  245.             timestamp = 0
  246.         },
  247.         second_jump = {
  248.             timestamp = 0,
  249.             cooldown = 10000
  250.         }
  251.     }
  252. end
  253.  
  254. function eventNewPlayer(playerName)
  255.     room.total_players = room.total_players + 1
  256.     for i, key in ipairs(keys) do
  257.         system.bindKeyboard(playerName, key, true, true)
  258.         system.bindMouse(playerName, true)
  259.     end
  260.  
  261.     startPlayer(playerName)
  262. end
  263.  
  264. function eventMouse(playerName, x, y)
  265.     if room.players[playerName].isAlive then
  266.         if room.players[playerName].projectile.timestamp <= (os.time() - room.cooldown_time) then
  267.             local px = tfm.get.room.playerList[playerName].x
  268.             local py = tfm.get.room.playerList[playerName].y
  269.  
  270.             local dx = x - px
  271.             local dy = y - py
  272.             local angle = math.atan2(dy, dx)
  273.        
  274.             local vx = math.cos(angle)
  275.             local vy = math.sin(angle)
  276.        
  277.             local id
  278.             local offsets = {
  279.                 x = px + 40 * vx,
  280.                 y = py + 40 * vy
  281.             }
  282.             id = tfm.exec.addShamanObject(35, offsets.x, offsets.y, angle*180/math.pi, projspeed*vx, projspeed*vy, false)
  283.             tfm.exec.displayParticle (3, offsets.x, offsets.y)
  284.             table.insert(despawn, {os.time(), id})
  285.             room.players[playerName].projectile.timestamp = os.time()
  286.         end
  287.     end
  288. end
  289.  
  290. function eventKeyboard(playerName, key, down, xpos, ypos)
  291.     local player = room.players[playerName]
  292.     if key == 32 and player.isAlive then
  293.         if player.projectile.timestamp <= (os.time() - room.cooldown_time) then
  294.             local id
  295.             local angle
  296.             local offsets = player.projectile.offsets.x
  297.             local projectile_speed
  298.             if player.movingRight or player.movingLeft then
  299.                 offsets = offsets + 15
  300.             end
  301.             if player.facingRight then
  302.                 angle = 0
  303.                 projectile_speed = projspeed
  304.             else
  305.                 offsets = -offsets
  306.                 angle = 180
  307.                 projectile_speed = -projspeed
  308.             end
  309.             id = tfm.exec.addShamanObject(projectile[math.random(#projectile)], xpos + offsets, ypos, angle, projectile_speed, 0, false)
  310.             tfm.exec.displayParticle (3, xpos + offsets, ypos)
  311.             table.insert(despawn, {os.time(), id})
  312.             player.projectile.timestamp = os.time()
  313.         end
  314.     end
  315.     if key == 0 then
  316.         player.facingLeft = true
  317.         player.facingRight = false
  318.         if down then
  319.             player.movingLeft = true
  320.             player.movingRight = false
  321.         else
  322.             player.movingLeft = false
  323.             player.movingRight = false
  324.         end
  325.     end
  326.     if key == 2 then
  327.         player.facingLeft = false
  328.         player.facingRight = true
  329.         if down then
  330.             player.movingLeft = false
  331.             player.movingRight = true
  332.         else
  333.             player.movingLeft = false
  334.             player.movingRight = false
  335.         end
  336.     end
  337.     if key == 90 and player.isAlive then
  338.         if player.ballon.timestamp <= (os.time() - 10000) then
  339.             if player.ballon.id then
  340.                 tfm.exec.removeObject(player.ballon.id)
  341.             end
  342.             player.ballon.id = tfm.exec.addShamanObject(math.random(29, 31), xpos, ypos + 40, 0, 0, 0, false)
  343.             player.ballon.timestamp = os.time()
  344.         else
  345.             print(string.format(text[room.lang].warnings.ballon.not_available, ((os.time() - 10000)/1000))) -- (os.time() - 10000))/1000)
  346.         end
  347.     end
  348.     if key == 88 and player.isAlive and room.elapsed_time >= acid.start_delay then
  349.         if player.trampoline.id then
  350.             print(text[room.lang].warnings.trampoline.used)
  351.         else
  352.             player.trampoline.id = tfm.exec.addShamanObject(7, xpos, ypos + 30, 0, 0, 0, false)
  353.             player.trampoline.timestamp = os.time()
  354.         end
  355.     end
  356.     if key == 67 and player.isAlive then -- c
  357.         if player.second_jump.timestamp <= (os.time() - player.second_jump.cooldown) then
  358.             tfm.exec.movePlayer(playerName, 0, 0, true, 0, -100, true)
  359.             player.second_jump.timestamp = os.time()
  360.         else
  361.             print(string.format(text[room.lang].warnings.second_jump.not_available, ((os.time() - 10000)/1000)))
  362.         end
  363.     end
  364.     if key == 72 then -- h
  365.         eventTextAreaCallback(2, playerName, "help")
  366.     end
  367.     if key == 71 then -- g
  368.         eventTextAreaCallback(2, playerName, "settings")
  369.     end
  370.     if key == 80 then -- p
  371.         eventTextAreaCallback(2, playerName, "profile")
  372.     end
  373. end
  374.  
  375. function eventChatCommand(playerName, command)
  376.     local arguments = {}
  377.     for arg in command:gmatch("[^%s]+") do
  378.         table.insert(arguments, arg)
  379.     end
  380.     if command == "help" then
  381.         eventTextAreaCallback(2, playerName, "help")
  382.     elseif command == "exit" and playerName == modulo_creator then
  383.         system.exit()
  384.     elseif command == "settings" then
  385.         eventTextAreaCallback(2, playerName, "settings")
  386.     elseif command == "profile" then
  387.         eventTextAreaCallback(2, playerName, "profile")
  388.     else
  389.         print(text[room.lang].warnings.command_not)
  390.     end
  391. end
  392.  
  393. function eventNewGame()
  394.     updateMapInfo()
  395.  
  396.     room.alive_players = room.total_players
  397.     for player in pairs(tfm.get.room.playerList) do
  398.         startPlayer(player)
  399.     end
  400.  
  401.     victoryControl = {
  402.         timestamp = nil,
  403.         status = false,
  404.         winner = nil,
  405.         hold = 5000
  406.     }
  407.  
  408.     acid.id = 1
  409.     acid.timestamp = nil
  410.     acid.relative_height = 0
  411.     acid.bodydef.width = room.map.width
  412.    
  413.     local rise_ticks = (2 * (room.game_time - 60 - (acid.start_delay/1000))) / (acid.rise_hold/500)
  414.     acid.elevation_tick = (room.map.height - 200) / rise_ticks
  415.     print(acid.elevation_tick)
  416.     if acid.elevation_tick < 1 then
  417.         acid.elevation_tick = 1
  418.     end
  419.    
  420.     ui.removeTextArea(1)
  421.     ui.setMapName(modulo_name)
  422.    
  423.     started = false
  424.     tfm.exec.setGameTime(room.game_time)
  425. end
  426.  
  427. function updateMapInfo()
  428.     local height
  429.     local width
  430.  
  431.     room.map.last = room.map.current
  432.     room.map.current = 0 -- tfm.get.room.xmlMapInfo.mapCode
  433.  
  434.     room.map.height = tonumber(mapTagMatch("H"))
  435.     room.map.width = tonumber(mapTagMatch("L"))
  436. end
  437.  
  438. function mapTagMatch(tag)
  439.     local obj
  440.     obj = (tfm.get.room.xmlMapInfo or {}).xml or '' obj = obj:match("%W"..tag.."=\"(.-)\"")
  441.  
  442.     if not obj or obj == "" then
  443.         if tag == "H" then
  444.             return 400
  445.         end
  446.         if tag == "L" then
  447.             return 800
  448.         end
  449.     end
  450.     return obj
  451. end
  452.  
  453. function eventLoop(time, timeRemaining)
  454.     room.time_remaining = timeRemaining
  455.     room.elapsed_time = time
  456.     if time >= 5000 and not started then
  457.         started = true
  458.     end
  459.     if timeReamining == 60000 then
  460.         for player in pairs(room.players) do
  461.             if player.isAlive then
  462.                 tfm.exec.giveMeep (player, true)
  463.             end
  464.         end
  465.     end
  466.     if timeRemaining <= 30000 and room.alive_players > 1 then
  467.         local i
  468.         local id = tfm.exec.addShamanObject(10, math.random(1, room.map.width), 0, 0, 0, 10, false)
  469.         table.insert(room.anvils, {id, os.time()})
  470.         for i, anvil in ipairs(room.anvils) do
  471.             if anvil[2] <= (os.time() - 5000) then
  472.                 tfm.exec.removeObject(anvil[1])
  473.                 table.remove(room.anvils, i)
  474.             end
  475.         end
  476.     end
  477.     if timeRemaining <= 0 then
  478.         tfm.exec.newGame(maps[math.random(#maps)])
  479.     end
  480.  
  481.     if acid.timestamp then
  482.         if acid.timestamp <= (os.time() - acid.rise_hold) and room.alive_players >= 1 then
  483.             if acid.relative_height < (room.map.height - 200) then
  484.                 if acid.relative_height >= ((acid.bodydef.height*acid.id) - (acid.id*acid.elevation_tick)) then
  485.                     tfm.exec.addPhysicObject(acid.id, room.map.width / 2, math.ceil((room.map.height - acid.relative_height) + (acid.bodydef.height / 2) + (acid.id*acid.elevation_tick)), acid.bodydef)
  486.                     acid.id = acid.id + 1
  487.                 end
  488.                 tfm.exec.addPhysicObject(0, room.map.width / 2, math.floor((room.map.height + acid.bodydef.height/2) - acid.relative_height), acid.bodydef)
  489.                 acid.relative_height = acid.relative_height + acid.elevation_tick
  490.                 acid.timestamp = os.time()
  491.             end
  492.         end
  493.     elseif (not acid.timestamp) and (time >= acid.start_delay) and (room.alive_players >= 1) and (room.time_remaining > 10) then
  494.         acid.timestamp = os.time()
  495.         ui.addTextArea (0, "<font size='36' align='center'>"..(text[room.lang].alerts.acid_rising).."</p>", targetPlayer, 200, 150, 600, 200, 0x000000, 0x000000, 1, true)
  496.     end
  497.     if time >= acid.start_delay + 3000 then
  498.         ui.removeTextArea(0)
  499.     end
  500.  
  501.     if victoryControl.timestamp then
  502.         if victoryControl.timestamp <= (os.time() - victoryControl.hold) then
  503.             tfm.exec.playerVictory(victoryControl.winner)
  504.             acid.timestamp = nil
  505.         end
  506.     end
  507.  
  508.     for i, cannon in ipairs(despawn) do
  509.         if cannon[1] <= (os.time() - despawn_time) then
  510.             tfm.exec.removeObject(cannon[2])
  511.             table.remove(despawn, i)
  512.         end
  513.     end
  514.  
  515.     if room.killTextTimestamp then
  516.         if room.killTextTimestamp <= (os.time() - 3000) then
  517.             ui.removeTextArea(10)
  518.             room.killTextTimestamp = nil
  519.         end
  520.     end
  521. end
  522.  
  523. function eventPlayerDied(playerName)
  524.     if acid.timestamp then
  525.         -- if then
  526.         -- else
  527.         room.players[playerName].deathType = "acid"
  528.         ui.addTextArea (1, "<a href='event:clear'><font size='36' align='center'><R>"..(string.format(text[room.lang].alerts.touch_acid)).."</R></p></a>", playerName, 225, 150, 600, 200, 0x000000, 0x000000, 1, true)
  529.         -- end
  530.     elseif not acid.timestamp then
  531.         room.players[playerName].deathType = "vacuum"
  532.         ui.addTextArea (1, "<a href='event:clear'><font size='36' align='center'>"..(string.format(text[room.lang].alerts.fall_vacuum)).."</p></a>", playerName, 225, 150, 600, 200, 0x000000, 0x000000, 1, true)
  533.     end
  534.     room.players[playerName].isAlive = false
  535.     room.players[playerName].deathTimestamp = os.time()
  536.     if room.players[playerName].deathType then
  537.         if room.players[playerName].deathType == "acid" then
  538.             ui.addTextArea(10, string.format(text[room.lang].alerts.death_causes.touch_acid, playerName), targetPlayer, 10, 380, 0, 0, 0x000000, 0x000000, 1, true)
  539.         elseif room.players[playerName].deathType == "vacuum" then
  540.             ui.addTextArea(10, string.format(text[room.lang].alerts.death_causes.fall_vacuum, playerName), targetPlayer, 10, 380, 0, 0, 0x000000, 0x000000, 1, true)
  541.         else
  542.             ui.addTextArea(10, string.format(text[room.lang].alerts.death_causes.unknown, playerName), targetPlayer, 10, 380, 0, 0, 0x000000, 0x000000, 1, true)
  543.         end
  544.         room.killTextTimestamp = os.time()
  545.     end
  546.     room.alive_players = room.alive_players - 1
  547.     if room.alive_players == 0 then
  548.         if room.time_remaining > 10 then
  549.             if not victoryControl.status then
  550.                 tfm.exec.setGameTime(10)
  551.             end
  552.             acid.timestamp = nil
  553.         end
  554.     elseif room.alive_players == 1 then
  555.         victoryControl.status = true
  556.         for player in pairs(room.players) do
  557.             if player.isAlive then
  558.                 victoryControl.winner = player
  559.                 victoryControl.timestamp = os.time()
  560.                 tfm.exec.playEmote(player, 0, nil)
  561.                 tfm.exec.giveCheese(room.players[player])
  562.                 break
  563.             end
  564.         end
  565.         tfm.exec.setGameTime(7)
  566.     end
  567. end
  568.  
  569. function eventTextAreaCallback(id, player, event)
  570.     if event == "clear" then
  571.         ui.removeTextArea(id, player)
  572.     end
  573.     if id == 2 then
  574.         if event == "help" then
  575.             ui.addTextArea(20, "<font size='24'><T>"..(text[room.lang].ui.help.title).."</T></font>\n\n"..(text[room.lang].ui.help.description).."\n\n"..(text[room.lang].ui.help.desc2).."\n\n\n<a href='event:control'>"..(text[room.lang].ui.controls.title).."</a> | <a href='event:clear'><R>"..(text[room.lang].ui.tclose).."</R></a>", player, 200, 50, 400, 300, 0x010101, 0x010101, 0.5, true)
  576.         end
  577.         if event == "settings" then
  578.             ui.addTextArea(20, "<font size='24'><T>"..(text[room.lang].ui.settings.title).."</T></font>\n\n"..(text[room.lang].ui.settings.description).."\n\n\n<a href='event:clear'><R>"..(text[room.lang].ui.tclose).."</R></a>", player, 200, 50, 400, 300, 0x010101, 0x010101, 0.5, true)
  579.         end
  580.         if event == "profile" then
  581.             local title = tfm.get.room.playerList[player].title
  582.             local gender = tfm.get.room.playerList[player].gender
  583.             local cheeses = tfm.get.room.playerList[player].cheeses
  584.             ui.addTextArea(20, "<font size='24'><T>"..(text[room.lang].ui.profile.title).."</T></font>\n\n"..(string.format(text[room.lang].ui.profile.description, player)).."\n\nTítulo: "..title.."\n\nGénero: "..gender.."\n\nQuesos: "..cheeses.."\n\n\n<a href='event:clear'><R>"..(text[room.lang].ui.tclose).."</R></a>", player, 200, 50, 400, 300, 0x010101, 0x010101, 0.5, true)
  585.         end
  586.     end
  587.     if id == 20 then
  588.         if event == "control" then
  589.             ui.addTextArea(200, "<font size='24'><T>"..(text[room.lang].ui.controls.title).."</T></font>\n\n[ Espacio ] Disparar\n[Z] Invocar globo (10s cooldown)\n[X] Invocar trampolín (uno por ronda)\n[C] Doble Salto (10s cooldown)\n\n\n<a href='event:clear'><R>"..(text[room.lang].ui.tclose).."</R></a>", player, 200, 50, 400, 300, 0x010101, 0x010101, 1, true)
  590.         end
  591.     end
  592. end
  593.  
  594. function main()
  595.     for name, player in pairs(tfm.get.room.playerList) do
  596.         eventNewPlayer(name)
  597.     end
  598.  
  599.     ui.addTextArea (2, "<font size='16' ><a href='event:profile'>"..(text[room.lang].ui.profile.title).."</a> | <a href='event:settings'>"..(text[room.lang].ui.settings.title).."</a> | <a href='event:help'>"..(text[room.lang].ui.help.title).."</a></p>", targetPlayer, 600, 375, 0, 0, 0x000000, 0x000000, 0.75, true)
  600.  
  601.     tfm.exec.newGame(maps[math.random(#maps)])
  602. end
  603.  
  604. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement