Author Topic: List of problems/solutions I've had while making levels, some unresolved  (Read 4521 times)

annikk.exe

  • Achiever
  • Ent
  • ****
  • Thank You
  • -Given: 0
  • -Receive: 4
  • Posts: 1,809
I had a few problems that took AGES to figure out.  Thought I would post them up here for others to benefit from.
NB: I am still a n00b coder so take my coding advice with caution.. :p

I don't have solutions for all of my annoying problems yet.  Any help with the unsolved ones is much appreciated!


1.  The level seems to load, but as soon as you click the initial "OK" button, the entire game "freezes" and needs to be closed.

This turned out to be caused by a lack of a "coroutine.yield" line in my While statement.
That is, you normally have a "While" loop somewhere in your Level Logic function, and you need to put a "coroutine.yield" before you End the While statement, otherwise this crash will be the result.
Look in any working custom map and you will see coroutine.yield in the while statements - usually near the bottom of the code.


2.  Naming your asteroids doesn't seem to work - the LUA coding reference indicates you can use a.Name = "Fluffy Land" to set the name of a given asteroid a to a string of your choice, but when I try to load the level it errors on me claiming there is no Name method available, or something.

Unresolved..


3.  My level has an error, but I can't find out what it is because the error box is hidden behind the Main Menu.

Just get a working custom level, and load that instead.  Then once it has loaded you will be able to see what the error message was.


4.  The game reaches a certain point then crashes, or crashes immedietely upon the level loading.

Check your Function Level Logic thingy.  Look at the If statements that are being triggered around the time of the crash.  At least one of them will contain an infinite loop.  For example, if you set Timer = 30 and then have an If GetGameTime() > Timer then MessageBox("Hallo fluffy") WaitDialog() end, what is going to happen is that the game time reaches 30 seconds, which is greater than Timer, and so the If statement is triggered and displays a message box.  Then, in the next "tick" of time it checks the If statement again, and yep, game time is still greater than Timer.... so it tries to display another message box.  And another, and another, and so on.  The result - game crash.
To fix the example above, you would add Timer = Timer + 30 just before the End, and that means that the If will only be triggered once per 30 seconds.


5.  The game won't load, and complains that it was expecting an "=" somewhere.

It will tell you in the error message what line the error is on - if you're using a decent code editor such as Notepad++ then it will show the line numbers so you can quickly find where the problem is.
This error is caused by mixing up = and == in your If statements.  Between "If" and "then", you always use ==.  Between "then" and "end" - and everywhere else, it seems - you always use =.  I have no clue why this is btw, it's just the language convention i guess.


6.  I want to script a mine to move from one asteroid to another, for example to attack the player's asteroid.

no idea...  halp anyone ?

**Update** in the level I'm working on right now, I actually managed to get a surprise mine attack on the go.  The way I did it is, I picked an asteroid that I know the player will own at a certain point during the game, and added two named Defensive trees on it.  Then, at the appointed time, the asteroids's owner is change to Empire 2.  Then "addflower" is used in reference to the named defensive trees, which actually causes named mines to start growing.  Using GrowToMax and Pluck in reference to the name mines, and they instantly are plucked from the tree and start orbiting the asteroid.  Then the asteroid's owner is changed back to player 1.
This all happens in the blink of an eye during the game, and the net effect is that 2 hostile laser mines spawn at the player's asteroid, and starts owning any of the player's nearby seeds.

Not quite the functionality I was hoping for, but pretty nifty nevertheless :>


7.  I want to destroy an asteroid, how can I do this?

Two methods.
My current preferred method, which I think is the most elegant, is to use GetAsteroid(0):SetRadius = 0
Scripted seed movements and AI can still use the asteroid, the player cannot use the asteroid unless it is theirs (so use ChangeOwner if you want it to be impassable).
The asteroid's radius is arbitrarily small and so is impossible to click on.  :>


My old method works less well, but produces a totally different effect.
The roid will be "dead", so stop producing seedlings, it will become invisible to the player, any seeds left orbiting it will become unusable (although you can script them to move elsewhere if you want to save them), and the player won't be able to use that asteroid for warping anymore.

Code: [Select]
--replace "0" with whatever number of asteroid you want to destroy.
GetAsteroid(0):Die()


--Hides the asteroid from view, otherwise the player sees the dead husk
GetAsteroid(0):Hide(1)


--The owner change means the player loses warp rights for the asteroid so they can't warp in and rediscover it after the Hide() above
--player 9 is just a high-ish number that hopefully isnt used for anything.
GetAsteroid(0):ChangeOwner(9)

Please note this bug is applicable here.  Use with caution.



8.  I try to set the camera to zoom to a location, but for some reason it zooms to the middle of empty space instead.  Why?

Camera positions are inverted relative to asteroid positions.  So for example, you are probably doing it like this:

Code: [Select]
a = AddAsteroidWithAttributes(1000,1000,0.5,0.5,0.5)
SetCameraTarget(1000,1000)

This causes the camera to zoom to empty space.
What you should use instead is:

Code: [Select]
a = AddAsteroidWithAttributes(1000,1000,0.5,0.5,0.5)
SetCameraTarget(-1000,-1000)

It's inverted, see?
This will cause the camera to zoom in on the asteroid.  :>


9.  I want to make an impassable barrier - an asteroid with a send distance too small for the player to continue - and then bridge the gap later by increasing the Send Distance of the asteroid.  But when I set the asteroid's initial send distance to a low number, the game "corrects" it up for me, so that the asteroids are traversable.  How can I prevent this behaviour?

Currently it seems like you can't.  However, I did figure out a way to do this.... it's not very elegant, but it will work.
What you do is you create an asteroid in the middle of the gap, and you set the asteroid's radius to zero.  The player will be able to see that there is something there because of the behaviour of the Green Arrow you see when click-dragging seeds to a target, but they won't be able to actually click on the asteroid because it's arbitrarily small.  :>
The game on the other hand now accepts that there is a valid route between all the roids, and won't artificially enlarge your Frontline roid's send distance.
This solution is ugly because it leaves a faction icon hanging apparently in empty space, and the player will be able to guess something funky is going on.  But it does the job, and leaves you free to increase the send distance of your frontline asteroid at the time of your choosing, in your Function Level Logic.


10.  PULSAR RECIPE!!

I just finished this.  Now I'm going to bed.  Enjoy.

In Function Level Logic:
Code: [Select]
while GameRunning() do
roidsize = 300 + (math.sin(GetGameTime()) * 400)
GetAsteroid(0):SetRadius(roidsize)
coroutine.yield()
end


11.  [string "chunk"]:1:bad argument #1 to 'create' (Lua function expected)

This obscure-looking error turned out to be the lack of a Function LevelLogic() section.
You HAVE to have a function level logic, even if it's empty.  Otherwise the level will not load.



12.  (more when i think of them..)
« Last Edit: February 07, 2010, 06:05:27 AM by annikk.exe »

njursten

  • Seedling
  • **
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 31
Re: List of problems/solutions I've had while making levels, some unresolved
« Reply #1 on: January 31, 2010, 11:26:09 PM »
Regarding number 5, it's a very common convention. '==' is for comparing, '=' is for assignment. If you only had one of them you wouldn't be able to do something like this:
isSameFaction = (factionNoA == factionNoB)

To see old errors you can also check the console, accessible by pressing '~' (left of the '1' key).
« Last Edit: January 31, 2010, 11:28:26 PM by njursten »