[Tutorial] Free For All |
Shamousey « Consul » 1380725460000
| 2 | ||
In this tutorial we're going to cover making a FFA/Deathmatch minigame, and the different aspects that should have. This includes shooting cannons, despawning them, stopping people from firing constantly, and each player having their own custom offsets. We'll start off by binding the keys that we need for every user that's in the room and that joins. To do this effectively we'll put the code in eventNewPlayer, then run that function for everyone in the room as it starts. The key codes that will be used are 32, 40, and 83, which are space, down, and S respectively. These keys will shoot a cannon when someone presses them. Looping through these keys with a for loop saves from having to write tfm.exec.bindKeyboard once for each key. a dit : Now that the keys are bound, they need to be used, a cannon to be shot in the direction the user is facing. Checking if the key is one of the ones we specified will be useful if the script ever has any more keys bound in the future. The playerList table has a variable called "isFacingRight". This boolean is true if the player is facing right at the time, and false if they're not. Using this can determine the direction the user is facing and which direction to shoot cannons. When spawning the cannons, ID 17 will create an upwards facing cannon. To make it shoot in the direction the player is facing, we'll need to use the fourth argument of the tfm.exec.addShamanObject function, which controls the angle. They need to be spawned at the co-ordinates of the player as they press the key, which eventKeyboard kindly returns for us as a player presses the key. An additional thing to remember is that players shouldn't be able to shoot when they're dead, so checking the boolean for each player stored in playerList to detect if they're dead or not will help prevent that. a dit : By this point we have a basic working free-for-all script so that anyone can shoot cannons when they like. The next step is stopping players from shooting so fast. To do this, we're going to check os.time() whenever a player presses a key - this function gives the current system time in milliseconds, for example 1380530062. If the time has risen by 1000, one second will have passed, so we can use this to determine how frequently the player can shoot. Every player will need to have this value stored individually, so a table can store this, we'll name it "players". Every player will need to have their own table within this to store the information we need, so we can add that to eventNewPlayer(). a dit : As you can see, the variable named "timestamp" inside this table will be used to keep the needed time. Now that the value is stored, when os.time() is checked again on a key press it can be compared with the stored value and if it's 1000 higher than before, we'll know a second has passed, so we can allow players to shoot. We'll check this with "players[name].timestamp < os.time()-1000" and only spawning a cannon if it's true. Once a player has successfully shot, the value stored in the table will have to be set to the current time to make sure the player can't shoot for another second, so we'll redefine that by running the line "players[name].timestamp=os.time()". a dit : Cannons staying on the map can have several issues; they keep getting added to objectList, they can get stuck on maps, there can be hundreds on screen at any given time which gets extremely laggy. They need to be removed. There are several possible ways to remove cannons; using timers, deleting on the player's next shot, checking os.time() again, or many other things. For this example we'll be comparing os.time() to the time since the cannon was shot. Certain information about the cannon will need to be available until it's despawned; both it's spawn time and ID of the object. This will be kept in another table. a dit : Luckily tfm.exec.addShamanObject returns the ID of the object it spawns, so setting a variable to this will keep the ID in the variable, ready to use elsewhere. The current time will also need to be stored, to be checked and compared at a later date - just like what was done with the player's timestamp. Both of these things will be inserted into the toDespawn table when a player shoots a cannon. a dit : Now that the table stores information about each cannon, they need to be removed. Using timers would be the most accurate method of determining when to despawn a cannon, although they can be resource intensive and are limited to only 40. The next best thing would be to remove them on eventLoop, which gets excecuted every 500ms. Inside this function we're going to loop through every object inside the toDespawn table. Firstly we need to check the time of the cannons just like before. To make every cannon last roughly 3 seconds, the time stored at the time of the cannon being shot can be compared to the current time minus 3000 milliseconds, then the cannon removed. The entry in toDespawn also needs to be removed whenever a cannon is successfully despawned, so using the table.remove() function to get rid of the key it's currently looping through can perform this action. Bare in mind that removing an item from a table as it's being looped through can cause an error as it fails to loop through that item, but using the ipairs() function helps as it increments the number keys it loops through, meaning it won't break. a dit : All together, we now have a working minigame where players can shoot 1 cannon a second, and the cannons get removed roughly 3 seconds after being shot. There needs to be an end-game for each round, and in FFA this is usually that the last player alive gets cheese. Doing this means that you need to know how many players are currently alive - if only one player is alive they can be given cheese. This can be done by looping through the playerList and incrementing a number for every "not isDead", the resulting number will be the number of people alive. The number of alive players will only ever change when a player dies (or is respawned, but our minigame doesn't have that feature), so it only needs to be checked in eventPlayerDied. The name of the player can be stored in a variable to be used - if there is only one player alive then that will be the only one that sets the variable, giving you the name of the winner. We also will need to set the game time lower or start a new round in order to ensure that rounds don't continue even if everyone has died. a dit : An issue that may occur when shooting cannons is that they can be shot during the countdown of new rounds, meaning that cannons spawn and can move players before they can move themselves. A way this can be solved is setting a global boolean that decides whether the current round has started or not. This'll be set to false on eventNewGame, and players can only shoot if it's true. eventLoop returns how many milliseconds have passed in the current round, which can be used to determine when the 3 second countdown is over. a dit : Baffler's #deathmatch game allows players to set their own offsets that cannons shoot at relative to their mouse co-ordinates, allowing people to customise them to their own liking. Players will need to have their own offset variables for both the X and Y axis, which we can store inside the previously made players table, adding it to eventNewPlayer to ensure everyone has default offsets. a dit : These offsets can easily be used by adding these values to the spawn co-ordinates of the cannons. a dit : So that this is useful, players will need access to a custom command such as "!off [x] [y]" so that both the X and Y can be set independantly of onenaother. Firstly each individual argument needs to be separated so that they can be detected independantly, so we'll insert each argument into a table, splitting them at every space. a dit : Next these arguments need to be used. Typing "!off 10 20" will make the following arguments in a table: arg[1] = "off" arg[2] = "10" arg[3] = "20" We need to check if arg[1] is actually "off", incase the module uses other commands in the future too. In the event that a player types "!off text", the script would crash when they try to shoot a cannon as it tries to add the string and the co-ordinates they spawned at together. We can check if they type numbers for both arguments by using the tonumber() function, if they don't then it will skip that block. To add a bit of additional functionality, if people give invalid arguments for the command in this example, it'll reset them to the default offsets. To notify players that they've successfully changed their offsets, tfm.exec.chatMessage can also be used to give a message saying "Offsets changed to X:2 Y:10" for example. a dit : We now have a working version of Free For All! Note that other tweaks should be made too, such as adding tfm.exec.disableAutoShaman(true) to the script to remove shamans from spawning in the maps. Using the map rotation from this thread Topic-457950 and giving it a list of maps built for the game, the minigame is complete. a dit : I hope this tutorial has helped you to learn some basic concepts such as individual player settings, using timestamps, and looping through tables. There may be more efficient and effective methods to do things, but hopefully you've learned some basic concepts that you can use when developing your own modules. Dernière modification le 1416013020000 |
0 | ||
ooo thanks |
0 | ||
Great tutorial Shamousey! |
Hakureimouse « Citoyen » 1380731100000
| 0 | ||
Shamousey a dit : Oh, that explains why I wasn't having a very good time trying to keep track of objects and deleting and removing them from a table, I was using pairs ): Great tutorial, everything is so well explained and in great detail, thank you :) ! I wonder what method does deathmatch use for despawning the cannons, is it the same shown in this tutorial, just with timers? |
Shamousey « Consul » 1380733440000
| 0 | ||
I noticed a few small things I'd missed out with the tutorial (shooting when dead and starting a new round once everyone's won) that I've now added in. Hakureimouse a dit : That can be a pain to remember when doing some other things, especially without an indexed table. Still, there are ways around it, like this! Hakureimouse a dit : Thanks, I'm glad it helped you and I hope it can help anyone else that wants to learn too. If you have any ideas of other tutorials I could write, or things to add to this one, please feel free to tell me! :) Hakureimouse a dit : Baffler told me that he doesn't use timers for removing cannons in #deathmatch. |
0 | ||
good job |
Issey 1380822120000
| | ||
[Modéré par Takumisyn, raison : Unnecessary] |
Juliiien « Citoyen » 1380826440000
| 0 | ||
Do you want a french translation Sham' ? :p Nice thread ♥ |
Shamousey « Consul » 1380826980000
| 0 | ||
Juliiien a dit : Go ahead and translate it if you want, that'd be great! *-* |
Xxninjazxx « Citoyen » 1380835800000
| 0 | ||
I thought this was a tutorial about learning lua that you didn't have to pay for. anyways I found a few things useful |
0 | ||
PRO !!!!!!!!!! |
0 | ||
Thanks for help, Mousey. |
Storzl « Citoyen » 1382286540000
| 0 | ||
Hi, when the map has loaded (after the 321 thing), mice can start instantly shooting, how would we be able to make it so that mice may only shoot 3 seconds after the map has loaded? |
Shamousey « Consul » 1382287740000
| 0 | ||
Storzl a dit : You can change the number on the "if time >= 3000 and not started then" line to be however long you want, 6000 milliseconds would be 3 seconds after the map has loaded. |
Storzl « Citoyen » 1382287860000
| 0 | ||
Shamousey a dit : Thank you! |
Toasty « Citoyen » 1382305260000
| 0 | ||
This is useful! Thanks Shamousey ^-^ |
Sandermr « Citoyen » 1384382160000
| 0 | ||
Nice tutorial Sham! I was wondering, by changing the Shaman item ID to another object we could change the object that mice actually shoot, so I added to your amazing FFA code a simple way that mice can choose their weapon of choice however, most objects like Sheep and Anvil only spawn below the mice and don't actually "shoot". How would we change (this code) so it would these items would shoot? (Like pewpew) |
Safwanrockz « Censeur » 1384416360000
| 0 | ||
Sandermr a dit : tfm.exec.addShamanObject(19,x+players[name].offsets.x,y+players[name].offsets.y,nil,20) < Increase the "20" for more speed. |
Sandermr « Citoyen » 1384454400000
| 0 | ||
Safwanrockz a dit : Ah thank you so much! |
0 | ||
thanks |