-
Content count
96 -
Joined
-
Last visited
-
Raffle Tickets
0
Content Type
Profiles
Forums
Calendar
Everything posted by mouseboyx
-
DLL that can be loaded and used to perform mysql queries from a sapp lua script https://github.com/mouseboyx/sapp_mysql_client I had fun learning from ChatGPT to try to make this work. I learned a little bit about thread safety and how to use a C++ mutex to lock a function. And how to return a pointer to an instance of a C++ class to lua's strictly C ffi implementation by casting it as a void pointer. The C++ sources for this dll are a great resource to learn from to implement other functionality like this in the future.
-
Scripts that play a custom notification sound when a player leaves or joins the server that you are currently playing on. I made this because I thought it would be nice to be able to join an empty server, then minimize halo and be able to be notified if a player joins, rather than needing to wait in the game for a player to join. May require Visual C++ 2019 redistributable Instructions in the readme.txt player_join_leave_notify.7z
-
Of course this script doesn't actually work, but it's crazy how it can pull this out of thin air, among all the other language it can produce. I first asked it if it was familiar with Halo combat evolved, asked it if it knew of the 3rd party extensions to halo, etc... If this is an early model, I'm interested to see where this type of tech goes from here. Prompt: "Using sapp lua scripting can you write a script that replaces the assault rifle with the sniper rifle, using onobjectspawn" ChatGPT: Yes, here's an example script in SAPP Lua that replaces the assault rifle with the sniper rifle using the onObjectSpawn callback: api_version = "1.10.0" function OnScriptLoad() register_callback(cb['EVENT_OBJECT_SPAWN'], "OnObjectSpawn") end function OnObjectSpawn(PlayerIndex, MapID, ParentID, ObjectID) if MapID == 3 and ObjectID == 45 then -- Check for assault rifle spawn local new_object = spawn_object("weap", "weapons\\sniper rifle\\sniper rifle", 0, 0, 0) -- Spawn sniper rifle if new_object ~= nil then return new_object -- Return the new object's ID to replace the spawned assault rifle end end end This script checks for the spawn of an assault rifle (MapID 3, ObjectID 45) and replaces it with a sniper rifle by spawning a new sniper rifle object and returning its ID to replace the spawned assault rifle. Keep in mind that this script may not work in multiplayer games with anti-cheat measures.
-
A collection of tests that might help someone with event_warp in lua scripting. Put 'antiwarp 3' without quotes into the sapp init.txt to enable the firing of the EVENT_WARP callback. While continuously moving, on the 3rd time that a player warps, with 'antiwarp 3', event_warp is fired. If the player stands still for a moment, there's a cooldown effect where they must move and warp 3 times again to trigger event_warp. Adding 200-300ms of latency then restoring a normal connection every 0.5-1.0 seconds is enough to trigger a warp event, but somewhere in the 180-220ms range and below the player can still warp, but the warp is very subtle and doesn't always trigger event_warp. Adding and subtracting a network delay above 300ms will surely trigger event_warp if it's applied continuously. I was using this quick and dirty linux bash script to simulate warp through the localhost, there is a tool called clumsy for windows on github that can simulate delayed, dropped, etc, packets that can also be useful for testing. for i in {0..10000} do sudo tc qdisc del dev lo root netem delay 150ms sleep 0.5 sudo tc qdisc add dev lo root netem delay 150ms sleep 0.5 done Run: sudo tc qdisc del dev lo root netem delay 150ms after testing to restore normal latency. Pushing a player with a vehicle can trigger EVENT_WARP even if both players have a perfect connection. I included an lua script that attempts to find warping distance of players who aren't in vehicles. It works ok, but doesn't take into account all the variables of what can happen in a game, like gravity, falling, player speed, being pushed by a vehicle, walking up an incline, or other things like that. The main motivation for testing is, players who apply a warp cheat, then do flag runs, I was hoping there might be a way to auto-kick abusive players like that. It may be possible, taking into account how many warp events happen in a time period, how far the player is warping each time, etc... My main concern is that I wouldn't want a script solution to auto kick an innocent player. event_warp.lua
-
When first doing wiring I got a 5 pack of 25ft Cat 6 ethernet cable from microcenter, but every one of these from the 5 pack would eventually drop connection at 1gbps, so I had to manually set all my devices to 100mbps, so that the connection wouldn't drop out and auto-negotiate to 100mbps anyway. I replaced the ethernet cable for my main desktop quite a while ago and haven't had any issues since, but I just got around to getting some Cat 6a for my 2nd desktop, hoping this will work. https://www.amazon.com/dp/B077H4KPD7?th=1
-
So this is probably a really old thing with the halo client, seems to happen in both FV/CE. When the frame rate is locked to 30fps, the client/server doesn't update the players ping as often as when the frame rate is vsync or novsync. And the player's ping can read 0 for a long period of time upon joining until it is finally updated. I'm wondering if there could be another method to determine a player's latency, other than reading from get_var(PlayerIndex,"$ping")?
-
I like the idea, it seems difficult to do a seek feature with that though. For each piece of data that didn't change it's true value could be any arbitrary length from the desired tick that's animating. It becomes easier if there's an ID associated with each object that didn't change, then seek backward through the file until you find each piece of data that you need. I can see how it would work, like if some float didn't change from the previous tick then write a single character in place of the float indicating to look to the previous tick, and do that every time it doesn't change. It seems like a necessary tradeoff, the file size will be smaller, but PHP will have to work harder, rewinding the file, parsing each line, checking if the data is there until it finds everything, then sending it off to js. js could then see that certain data hasn't changed from the seek position tick and fill that in as necessary. It gets a little complicated while buffering the animation data too, as well as buffering data while the animation is playing in reverse. Lmao the optimization never ends, in all seriousness though I'm glad I'm getting feedback to improve this. In other news I figured out an ok method of latency compensation while using SJ. Only have to set the camera's aim to a certain number of ticks in the future based on that player's ping. Ended up having a toggle to switch to use either average ping or instantaneous ping from each tick (seems like it might be necessary for certain warping conditions) Edit (Progress): Added a simple yet effective way to save space, vehicles, and flags and oddballs are the main culprit for bloating the file, because they can sit idle for long periods of time. An example string of how a vehicle was saved previously: ObjectID,tag_name,obj_x_coord,obj_y_coord,obj_z_coord,obj_front_x,obj_front_y,obj_front_z,obj_up_x,obj_up_y,obj_up_z,player_in_vehicle 3800236052,mp_warthog,46.338062286377,-64.705101013184,1.4689781665802,0.64794391393661,-0.758948802948,-0.064540214836597,-0.04084175080061,-0.11922907084227,0.99202638864517,-1 If none of that data changes in the next tick it's reduced to: 3799056386,p,69 ObjectID, the character 'p' to indicate to look to previous data, and 69 as the line number of it's last known data change. PHP then finds all of the 'p' occurrences and fills in the the first and last line of buffer data with the appropriate true values, then echos out the same 3799056386,p,69 like data for the rest of the stuff that doesn't change, and JavaScript fills in the spaces based on the first and last line. (I think this should work for reverse buffering because the last line true values are found based on the line numbers from the last line) With the latency compensation I'm going to add another toggle to compensate all player cameras and not only the SJ view. As long as the positions and rotations of objects remains true to the current tick, then all player cameras can be set into the future by an individual compensation factor to show where any player is currently aiming via a 3D object.
-
This project is currently unfinished, there's a few more things I need to add and also figure out how to work out the logistics of how things will work server side with the vps. I wouldn't have made it this far without Pirate's hlm.lua library, sunstriker7's help, and also a few lua functions from Enclusion and pROPs. The way it works is that an lua script saves halo's tick data in plaintext to a file with the current unix time (1670292207.txt) that's created when a map loads. The first line of the file is the map name, mode data, and all of the scenery info, names,x,y,z and rotational vectors. After that, each tick it saves data for players, vehicles, projectiles, and I'm working on adding objectives like flags and oddballs. It writes out to that file every tick, it could very well be above 1GB per hour of data depending on how much is going on in the game. But a lot of that data is redundant (compressing the file with 7z makes it a fraction of the filesize). The render application is written in PHP and JavaScript, it buffers 1000 ticks of data at a time so that it can be animated. You can Sight Jack any player in the animation. I'm soon going to implement something so you could send a link to someone like: http://localhost/halo_game_replay/render.php?file=1670292207&start=1234&sj=5 if the application was hosted publicly, it would start on tick 1234 and begin sight jacking player index 5. Something like that could help with server administration, you wouldn't necessarily need to be there to catch someone in the act of using an aimbot. I was trying to think of a way to save the float data as binary rather than plaintext which would probably reduce the file size significantly, but so far haven't come up with a solution. Because each tick is separated by newline in the data structure, binary data could contain a newline character and break the data. I'll release the code when I get this to a more complete state. I also have no experience with animation of 3D models so all the models are just static placeholders to mimic whats going on. I'm going to extract the bsp and scenery from all the default maps and include that with the project. The script should technically work with custom maps, but you would have to provide all the models for the vehicles, bsp, and players in wavefront obj format. I've put a lot of work into this, but I'm getting to a point where I'm slowing down on development. More info: You can tell lua to only save data if there's a minimum of X number of players in the server, for this reason it would probably be best to setup afk_kick, alternatively the lua script could be setup to only record data on command. In the renderer vehicle models are loaded dynamically, so you could technically spawn 50 warthogs at any time in the game, and it should be able to accommodate it. For the vps side of things, I was considering maybe a 2 vps setup one vps for the halo server, and one as a web host for the renderer, I was thinking if you had both at the same time it might lag a game in progress. Or you could use this only as an administrative tool and save the recordings without ever having them be public. Possibly thinking about multiple cron jobs on the vps where it could compress and upload the data to another vps, or delete the oldest recording if the vps was running out of storage. The last line of the file is written on game end, it writes `game_end,1670292207` to help with writing cron jobs on what to do with the data at the end.
-
I think the data collection is going to influenced by latency, here's a video of an aimbot that does horizontal aiming only, on the aimbot client the horizontal aim is always spot on, but the data collected is late, and this is through the localhost so it might be an even greater difference over the internet. Not sure if there's a way to account for this in the code, or if the person viewing the render will have to assume and compensate for latency. It's definitely possible to do a realtime render, but would take some extra work to make it possible. Edit: It might be possible using get_var(PlayerIndex,"$ping") and using that data to account for latency. Edit2: It looks like the data is late independent from sapp's custom_sleep command, or at least the data seems to be late relative to tick. For the player being sightjacked if their ping is anywhere from 1-33ish then their aim needs to be 2 ticks ahead of the current animation, then add 1 tick for every 33ms of ping-ish. For the rest of the players not being sightjacked their data needs to be 2 ticks behind the current animation from 1-33 then minus 1 extra tick for every 33ms. It may be challenging to find each "tick slot" a player falls into based on ping, then apply that delay in the render, lots of testing to be done...
-
It would take me a while and some motivation to figure out how to make it work, but mysql has a C/C++ api that could be used to create an ffi dll for sapp so that you could call a mysql_query() function directly from an lua script. https://dev.mysql.com/doc/c-api/8.0/en/ I thought about the real time option, if it was a public service I was worried about players using it to cheat, but if it was a private setup, that wouldn't be as much of an issue, the renderer code is built around a fixed recording file size but with a bit of tinkering it could work in near real time, there's currently a sync issue where the js animation runs slightly faster than halo's ticks. The issue is probably due to using the js setInterval() function for animation frame increments which technically isn't supposed to be used for timing precise events. Switching to using a timer like performance.now() might solve the issue. I've had bad experiences with vps hosts in the past where I feel like I can't trust their connection enough not to lag a halo game in progress, I should probably do some testing beforehand to see what happens in different circumstances.
-
My first car was a 1988 Honda Accord, it had a manual transmission, really fun to drive. I remember driving it home in a blizzard after taking it in for servicing. It eventually developed problems where if you shifted into neutral the rpm's would drop dangerously low and it would start sputtering while it was idling, so I would keep one half of my foot on the accelerator to prevent it from dying. The fix was to increase it's idling idling speed, I think that may have been a slow torturous death for that engine, it was still running when it was finally retired, but the torque was nowhere near it's original state. Having a manual transmission car as a teenager probably contributed to my delinquency, being able to rev up a carbonated 4 cylinder at the high school parking area seemed fun at the time. Dumping the clutch was also fun, doing mini burnouts or squeals. Even when I had acquired a newer Nissan Altima I still prefered to drive the '88 Honda to go places that were in town.
-
m_object=get_object_memory(vehicle_object_id) obj_front_x = read_float(m_object + 0x74) obj_front_y = read_float(m_object + 0x78) obj_front_z = read_float(m_object + 0x7C) obj_up_x = read_float(m_object + 0x80) obj_up_y = read_float(m_object + 0x84) obj_up_z = read_float(m_object + 0x88) The offsets above give two 3D vectors, a front vector which is essentially pointing down the vehicles nose or front, and an up vector which always points towards the vehicles roof. Video for helping visualize the vectors (up vector in red, front vector in blue): It seems like one of the euler angles can be calculated using math.atan2() (correct me if I'm wrong), but I'm unsure about the other two: euler_z=math.atan2(obj_front_Y,obj_front_x) --this seems to be correct --euler_x=? --euler_y=? I'm looking for the complete math that would be used to calculate these angles, I've searched for this problem here and the answers are helpful, like how the vectors have been mislabeled in an offsets list, and how to calculate these vectors from the starting point of euler angles, but not this specific question. From what I'm reading a rotation matrix would help in solving this problem, but I'm uneducated on that topic. A hacky workaround that I've done out of ignorance is to calculate the euler angles on vehicle spawn, (since mostly but not always a vehicle spawns with only one dimensional rotation) then each game tick add the pitch,yaw,roll velocity values to those euler angles, because the velocity values are in radians. --Unsure if this will always work but I'd rather have a math based solution rather than relying on something like this. Edit: @Sunstriker7 Helped me find a solution to the underlying problem as well as a possibility finding the other two angles, and the condition of gimbal lock. I should have mentioned that the end result of wanting to know euler angles was to apply them to a library called three.js. However three.js has a lookAt() method that can be supplied with an up vector and a vector to look at. That method essentially solves the problem without having to know the angles, or work around gimbal locking.
-
I used an optic pack by Devieth for some of the functionality in script.lua. The default melody is the intro to Cannon in D. I've included a JavaScript app that will convert guitar tabs to be used within the script.lua. Convert the tab and replace melody={...} in script.lua with the line generated by the converter. The sound samples are simple square waves generated by audacity, starting at 82hz then incrementing by semitone up to 2637hz, using this pattern you can replace the samples with your own if you want to. I would recommend a sample length of 0.150 seconds to 0.250 seconds. The lower the better to avoid backing up the sound playing api. release_melody.zip
-
I'm looking for a way to get the object id of newly created projectiles that could be passed to get_object() within a chimera script for both FV and CE, specifically grenades, but if it's possible for any projectile that would be a bonus. I saw the below line in an offsets list, but trying to access this on game tick, the dword value is always 0 before a player throws any grenades and always 0xFFFFFFFF after any grenade has been thrown. unit_thrown_grenade_obj_id = readident(m_unit + 0x294) -- Confirmed. 0xFFFFFFFF when grenade leaves hand Does the chimera scripting api have something similar to sapp's EVENT_OBJECT_SPAWN? Or is there another way to do this sort of thing? Any help would be appreciated.
-
This script itself does nothing to extend the client. If you're not looking for a development example I would not recommend downloading and running this script. The code is really only a boilerplate of basic calls for someone to use as a starting point if they want to learn or figure out how to call C functions from a chimera lua script. I spent days trying to figure out how to do this, so I wanted to share the fruits of my labor in case someone else wants or needs this example. I still don't fully understand how it works, but I know that the code runs. The instructions for calling C from lua are included in the readme.txt in the zip. https://www.lua.org/pil/24.htm Is a good starting point to learn more about how to call C from lua. chimeralib.zip
-
If someone has an ip address that changes following a pattern like: 123.123.123.123 123.123.123.124 123.123.123.125 123.123.122.111 123.123.120.122 123.123.124.222 Where the first 2 numbers are always the same, the 3rd number only changes by 2 or 4 digits and the last number could be anything. What's the appropriate CIDR notation for banning this range? From wikipedia, I'm gathering somewhere from 123.123.123.123/23 -- 123.123.123.123/16 seems like it should work, but /16 seems like too many and /23 seems like too few. I don't really understand how masks like 255.255.192.0 or 255.255.128.0 translate to a specific range when paired with an ip address. A mask like 255.255.255.0 makes perfect sense it would be 123.123.123.xxx and 255.255.0.0 would be 123.123.xxx.xxx but the others don't make sense.
-
Thanks for testing it, I assumed it would work after it kicked 127.0.0.1 based on the range {'127.0.0.0','127.0.0.255'}, but for some reason it was failing with other ip address ranges. I ended up wrapping all of the comparison statements within lua's tonumber() and it should work now I think. It worked at kicking a 192.168.x.x address based on the range {'192.168.0.0','192.168.255.255'} where as before the fix it failed to do that. Probably some strange quirk of lua, because it failed at the 3rd digit of banning 192.168.86.61, based on the rangeban of {'192.168.0.0','192.168.255.255'} I printed the strings encapsulated in quotes to makes sure there wasn't any whitespace or something funky with the strings cprint('"'..from_ip[3]..'","'..ip_digits[3]..'","'..to_ip[3]..'"') and it gave me "0","86","255", my assumption was that lua could compare these strings as numbers, but I guess not. (But it worked for the first 2 digits so it's strange) I'm probably spoiled by JavaScript and PHP where you can compare two strings like "12">"10" and it evaluates to true, then I write some lua and step into a string/number pitfall. basic_rangeban_fixed.lua
-
With the unpredictability of the built in range banning feature of sapp, this seems like a good opportunity for someone to write an lua script to implement range bans differently or more correctly than sapp does. I'm thinking using EVENT_PREJOIN to execute the detection/kick logic, however it would be limited because it wouldn't work like a full ip ban. Also might be able to introduce a different syntax to the range ban, like start and end ip addresses. Like start at "123.123.120.0" and end at "123.123.124.255", I don't know if that's a good idea though but it seems like it would work. I went ahead and made the range ban lua script. I don't know if this will work for every possible range condition, because it checks starting at the leftmost ip address digit to the rightmost to see if it is in the range. I don't even know if this is the correct way to implement the idea but here you go basic_rangeban.lua
-
Thanks ipinfo.io makes this a lot easier to understand, I totally get what you mean with the range ban having unintended consequences, I thought it could be narrowed down to mitigate that, but it seems even then it's not going to be bulletproof. I did my own testing and I'm unsure whether it's even applicable to how the real division of the internet works, and how sapp is interpreting that. I used "ifconfig lo xxx.xxx.xxx.xxx" to set my loopback interface to several different ip addresses and attempted to see whether the client could join with different cidr settings in the ipbans.txt I'm starting to think this test is pretty much useless though: 127.127.127.127/17:ban:0 EVEN: yes ODD: no 127.127.128.127 yes 127.127.129.127 no 127.127.130.127 yes 127.127.254.127 yes 127.127.192.127 yes 127.127.253.127 no 127.127.126.127 yes 127.127.125.127 no 127.127.124.127 yes 127.127.123.127 no 127.127.122.127 yes 127.127.121.127 no 127.127.120.127 yes 127.127.119.127 no 127.127.118.127 yes 127.127.127.127/18:ban:0 127.127.0.127 yes 127.127.1.127 yes 127.127.2.127 yes 127.127.3.127 no 127.127.4.127 yes 127.127.5.127 yes 127.127.6.127 yes 127.127.7.127 no 127.127.11.127 no 127.127.127.127/19:ban:0 127.127.0.127 yes 127.127.1.127 yes 127.127.2.127 yes 127.127.3.127 no 127.127.4.127 yes 127.127.5.127 yes 127.127.6.127 yes 127.127.7.127 no
-
There are things that might be viewed as cheating, probably playing on public servers it's not that big of a deal, but if you were playing in a tournament it would be viewed as client modding or cheating. But these are in a gray area to me of whether or not they are cheating. These are from the point of view of a map that doesn't have these features by default, but if the map were made to have these features then it's all fine. Removing Camera Shake -- If a map uses camera shake on weapons (most prominent when firing a rocket launcher) is it cheating to remove all camera shake? With a weapon like the pistol I've done this before in my early days when I was 16-17 before I realized that it's somewhat dishonest to remove it. I did feel like I could get better aim and accuracy when removing it, and soon reverted the changes because I felt like I was cheating. Is it even possible to detect whether a client does this from server side? Changing the FOV -- Could be changed to give yourself either narrowed or widened peripheral vision. Once again I think this is fine on public servers, but it could be changed to something ridiculous to give 180 degree vision. Changing Textures/Light/Shaders -- Something like giving a hog a paint job or rims on a map that doesn't have that by default is a benign example, but making frag grenades more visible by turning them green or pink falls in a questionable area. Of course making walls transparent would give relatively the same cheat as a wall hack. Turning off Particles -- Since this is an option in the video settings and it has pros and cons I don't think this could be considered cheating unless it was established beforehand that it was against the rules. If particles were changed to be still visible yet lessened or semi-transparent through mods or map tools I think that would fall under something sinister because it wouldn't be readily available to everyone. These are obvious cheats where there is no question that it is cheating: Wall Hack -- Various methods probably exist, the basic idea is that it brings the z index of all players to be in front of everything else and highlights them with a color. Aim Bot -- Using a tool to gain perfect aim for head shots without ever needing to aim much yourself. Auto Shot -- I'm less familiar with this but I believe it is used in combination with an aim bot or wall hack to fire a weapon automatically if someone is within range and is in line of sight within the reticle. Lag or Speed Hack -- Using a speed hack program to simulate a client/server mismatch causing a warp, or purposely installing a lag switch, or introducing drops in a connection through software to warp. But this could be easily mistaken for a bad connection to the server. If someone lags every time when they take cover from fire and never lags at any other point it could be relatively save to assume they are using a lag switch of some kind. HAC2 -- Using Halo Anti Cheat for the purpose of screen watching instead of sight jacking. For example sight jacking someone to find their location rather than using it to spectate looking for aimbot, wallhack, or other cheats of a player. (I don't know if this is gray area, but it sure does seem dishonest to me) I'm interested to know what the opinions are on the "gray area" or other things that could be added to the list. Sorry if this post is not allowed, but the problem of cheaters on CE and Retail is a persistent one and it's good to have information out there. Edit: Sorry this probably doesn't belong here it might be more suitable to be put in off-topic or somewhere else.
-
Replace starting weapons with different weapons. The script must be made aware of what the actual starting weapons for the mode/map are in order for it to work. The script comes with an example of replacing generic starting equipment with sniper and rocket. It can also swap weapon slots by replacement, for example generic equipment is assault rifle as primary and pistol as secondary, you can set the replacements so that the pistol is primary and assault rifle is secondary. You can dynamically load this script or multiple different versions in the events.txt based on custom modes: event_start $mode:custom_mode_123 'lua_load "replace_starting_equipment"' event_end $mode:custom_mode_123 'lua_unload "replace_starting_equipment"' I used a function in this script from one of hrshaft's scripts from his pastebin get_tag_info() replace_starting_equipment.lua
-
I made what you wanted, it does everything except change the player color, and can be configured to behave within ranges. It also has the option to spawn random weapons on the map, but this script only works with stock maps, because I don't know how to traverse tags, you can make it work with a custom map if you edit the weapon lists. randomize_stuff.lua
-
I'm not going to release or make public the code that was used to create this. It's more of a demonstration of what is possible. It's a pretty roundabout way to accomplish it though, placing a 3D render of halo camera and player data as a transparent window on top of halo in windowed mode. The methods are hacky at best and that introduces latency into the cheat window, I'm sure if it was created using faster 3D rendering techniques rather than using JavaScript the latency would be reduced. I'm somewhat regretting creating this because it possibly introduces more dishonesty into the game, although I'm uncertain whether something like this already exists. I was more interested in whether it could work than whether it should be created.
-
Is it safe to use os.clock() in an lua script for timing a recurring event in a script? If the server runs constantly will os.clock() have an overflow point? Could it keep counting seconds or milliseconds similar to the unix timestamp? Obviously this would be a pain to test, I didn't see information on this through a few google searches. I have this weapons spawning script where every 30 seconds the weapons are spawned again. It would make more sense to count the ticks and reset a variable rather than depend on os.clock() so it's easy to fix the problem if there is one, I'm just curious about os.clock() I had this script fail, due to an undetermined cause, although I'm unsure whether any of the other scripts were also still working. The information I could find about os.clock() says that it's mostly used for script benchmarking purposes. api_version = "1.12.0.0" items={ { "weap", "weapons\\sniper rifle\\sniper rifle", 90.899, -159.633, 1.704, 1.587 ,0}, } function OnScriptLoad() register_callback(cb['EVENT_TICK'],"OnTick") register_callback(cb["EVENT_GAME_START"], "OnGameStart") end function OnGameStart() if (items) then for i = 1,#items,1 do spawn_object(items[i][1], items[i][2], items[i][3], items[i][4], items[i][5], items[i][6]) items[i][7]=tonumber(os.clock())+30 end end end function OnTick() time = os.clock() for i = 1,#items,1 do if (time>=items[i][7]) then spawn_object(items[i][1], items[i][2], items[i][3], items[i][4], items[i][5], items[i][6]) items[i][7]=tonumber(os.clock())+30 end end end