Background

Well, I've been working on a script for Annals of Ea, designed to give a gradually reducing radius of vision past a certain time, to give a slightly better feeling of dawn and dusk (and to give me Lua practice ;) ). Here it is (very incomplete as yet):

add_loadsave("turns", 0)

function time()
        -- 1 day is 11520 turns, so...
        local hour = bst(11520/24, turn)
        if (hour >= 18) or (hour <= 6) and (player.wild_mode == FALSE) then
                -- keep turns timer active, or reset if not yet done
                if (turns >= 1) and (turns <= 200) then
                        turns = turns
                else
                        turns = 0
                end
                turns = turns + 1
                local hgt = ((cur_hgt/2) - turns/2)
                local wid = ((cur_wid/2) - turns/2)
                local y = (hgt + player.py)
                local x = (wid + player.px)
                if (y <= (x*x)) and (y >= -(x*x)) and (x <= (y*y)) and (x >= -(y*y)) and (hgt > 0) and (wid > 0) then
                        for x = 0, (cur_wid - 1) do
                                for y = 0, (cur_hgt - 1) do
                                        cave(y,x).info = bor((cave(y,x).info), (CAVE_GLOW), (CAVE_MARK))
                        end
                        end
                else
                        for x = 0, (cur_wid - 1) do
                                for y = 0, (cur_hgt - 1) do
                                        cave(y,x).info = band((cave(y,x).info), bnot(CAVE_GLOW), bnot(CAVE_MARK))
                        end
                        end
                end
                msg_print(10, format("turns = %s ", turns))
        elseif (player.wild_mode == FALSE) then
        end
end

add_hook_script (HOOK_END_TURN, "time", "time")

Now, as i'm posting it here, you can probably guess it doesn't work. The idea is that after a certain time, a "turns" counter starts ticking, and that is taken away from the cur_hgt and cur_wid to give a decreasing lit area. (Defined by the "if..." line, which hopefully should produce a kind of circle. However, the problem is that while it kind of works, AFAICT, the cave(y,x).info needs to "scan" an area. I suspect it scans outside the "if..." area defined in x and y, and so does not light simply the defined area. I can't seem to find a way to get it to confine its scanning. It also slows down the game considerably, and produces funny trails upon occasions.

Is there a better way of doing things?

P.S. The lighting code was taken from BlackSmurf's aws_lite.lua script, for the aWESoME module. I do not actually understand what the band and bnot and bor mean, but it seemed to be the only way of doing things without producing lua errors or just crashing the game.

Have I got it all wrong? Am I chasing a lost cause? or is there a simple solution to this problem?

Thanks, TheFalcon.


NerdanelVampire: I'm not a lua programmer, but I think band, bor, and bnot are highly likely to be the bitwise and, or, and not, the equivalents of &, |, and ! in C.

Notice that your little effect needs to function only at dawn and dusk. You can increase the counter at dawn and decrease it at dusk. You can increase the efficiency a lot by checking for these two times right in the beginning and not doing anything if the time is wrong. (You don't need to do an useless empty elseif either.) The current situation cycles the counter the whole night, which is clearly wrong. You also shouldn't need to insert a variable into itself, which slows things down for no reason. Once again, this is just on the basis of general coding and not specifically ToME or lua.

TheFalcon: Yes, I guess you're right. It was just rather easier to test if it kept on going, otherwise I'd have to wait half a day each time. I'll put in the proper "timings" and see what happens. Thanks for the suggestions.

[later] I just found this topic over on the forum: http://forum.t-o-m-e.net/viewtopic.php?p=47856 . It should make things rather easier I hope, though it's still not ideal as the light is not exactly from the correct source.

TheFury: This is a good idea. It reminds me a lot of Ultima V. Now all you need are the ships and the lighthouses... :)

TheFalcon: I have plans for ships (at least as a means for transportation from town to town). Lighthouses huh? hmmm.... *wonders about how to code a moving beam of lit terrain*. ;)

[later]... Well, I think the dawn and dusk script is (finally) complete. It has definite limitations, since player.cur_lite seems to have a maximum of 20, but it still gives quite a good effect. I still have a bit of testing to do, but other than that it's done. Still an awful lot to do before the next release of Annals though.

Update

TheFalcon: I redid the script, as I got better at lua since then. It works very nicely. Unfortunately, it is very slow; about like having base delay factor set to 40. :( If anyone can see any way to optimise it further to speed it up that would be great.

Here it is:

-- How it works: From the hours of 5 to 6 in the morning, and from 6 to 7 in the evening, a timer is active which counts up
-- at the end of each turn. Another timer is also active, which we shall come to later. So long as the player is in the right
-- place (wilderness, not dungeon), the actual script kicks in to change which grids are lit:
-- Firstly, the whole of the wilderness area is darkened, to refresh it from the previous time, mainly because if the player
-- has moved, they will otherwise drag a trail of light with them.
-- Next, the lighting of the specific area occurs. This uses an equation based on the fact that a squared term will produce 
-- a curve. The i values for this go from negative to positive, so that both sides of the curve are generated. This curve is 
-- then raised, or lowered in proportion to the counter value, so that the higher the counter, the more of the curve will be
-- seen 'above' the 'axis' of the player's y coordinates. The player's coordinates are then added to the value to make the 
-- curve appear in the right place.
-- After this, the curve is 'filled in' down to the player's coordinates by the 'while' clause. This effectively draws a series
-- of lines from the first line, defined by the actual y value, to the player's y 'axis'.
-- These steps are repeated for the second half of the lit area.
-- Lastly the area is redrawn t oshow the changes using player.redraw.
-- At dusk the script needs an extra clause to remove the last patch of light when the script has finished, and the counters 
-- reset when not in use.

-- The second counter is used to prevent excessive redrawing of the screen. This is because HOOK_END_TURN seems to call any
-- script 10 times, rather than once, so in effect 10 is added to the main counter every turn, rather than 1. (This also 
-- explains the large value of 4800 for the counter maximum. One hour actually takes 480 turns.) Thus the second counter 
-- limits the script to being called every 10 counts, so once per turn. (This idea was gained from Neil Steven's automagic
-- stat gain script).

add_loadsave("light_count", 0)
add_loadsave("last_light_count", 0)

function w_light()
        local hour = bst(11520/24, turn)
        if (hour >= 5) and (hour < 6) then
                if (light_count <= 4800) then
                        light_count = light_count + 1
                end
                if (last_light_count >480) then
                        last_light_count = 0
                end
                if player.wild_mode == TRUE then
                        last_light_count = light_count/10
                end
                if (player.wild_mode == FALSE) and (dun_level == 0) and (light_count/10 > (last_light_count + 240)) and (light_count >2400) then
                        last_light_count = last_light_count + 1
--                      msg_print("last_light_count == "..last_light_count.."   light_count== "..light_count.."    ")
                        local i, j
                        for i = 0, 198 do
                                for j = 0, 67 do
                                        if (j<66) and (j>0) and (i>0) and (i<198) then
                                                cave(j,i).info = band(cave(j,i).info, bnot(CAVE_GLOW), bnot(CAVE_MARK))
                                        end
                                end
                        end
                        local y, x, i
                        for i = -198, 198 do
                                y = (-i*i)/45 + (198*(light_count-2400)/7700) + player.py
                                x = i + player.px
                                while y >= player.py do
                                        if (y>=player.py) and (y<66) and (x>0) and (x<198) and (los(player.py, player.px, y, x) == TRUE) then
                                                cave(y,x).info = bor(cave(y,x).info, CAVE_GLOW, CAVE_MARK)
                                        end
                                        y = y-1
                                end
                                y = (i*i)/45 - ((198*(light_count-2400))/7700) + player.py
                                x = i + player.px
                                while y < player.py do
                                        if (y<player.py) and (y>0) and (x>0) and (x<198) and (los(player.py, player.px, y, x) == TRUE) then
                                                cave(y,x).info = bor(cave(y,x).info, CAVE_GLOW, CAVE_MARK)
                                        end
                                        y = y+1
                                end
                        end
                player.redraw = bor(player.redraw, PR_MAP)
                end
        elseif (hour >= 18) and (hour < 19) then
                if (light_count <= 4800) then
                        light_count = light_count + 1
                end
                if (last_light_count >240) then
                        last_light_count = 0
                end
                if player.wild_mode == TRUE then
                        last_light_count = light_count/10
                end
                if (player.wild_mode == FALSE) and (dun_level == 0) and (light_count/10 > last_light_count) and (light_count <2400) then
                        last_light_count = last_light_count + 1
--                      msg_print("last_light_count == "..last_light_count.."   light_count== "..light_count.."    ")
                        local i, j
                        for i = 0, 198 do
                                for j = 0, 67 do
                                        if (j<66) and (j>0) and (i>0) and (i<198) then
                                                cave(j,i).info = band(cave(j,i).info, bnot(CAVE_GLOW), bnot(CAVE_MARK))
                                        end
                                end
                        end
                        local y, x, i
                        for i = -198, 198 do
                                y = (-i*i)/45 + 62 - (198*(light_count)/7700) + player.py
                                x = i + player.px
                                while y >= player.py do
                                        if (y>=player.py) and (y<66) and (x>0) and (x<198) and (los(player.py, player.px, y, x) == TRUE) then
                                                cave(y,x).info = bor(cave(y,x).info, CAVE_GLOW, CAVE_MARK)
                                        end
                                        y = y-1
                                end
                                y = (i*i)/45 - 62 + ((198*(light_count))/7700) + player.py
                                x = i + player.px
                                while y < player.py do
                                        if (y<player.py) and (y>0) and (x>0) and (x<198) and (los(player.py, player.px, y, x) == TRUE) then
                                                cave(y,x).info = bor(cave(y,x).info, CAVE_GLOW, CAVE_MARK)
                                        end
                                        y = y+1
                                end
                        end
                        player.redraw = bor(player.redraw, PR_MAP)
                elseif (light_count == 2400) then
                        local i, j
                        for i = (player.px-10), (player.px+10) do
                                for j = (player.py-5), (player.py+5) do
                                        if (j<66) and (j>0) and (i>0) and (i<198) then
                                                cave(j,i).info = band(cave(j,i).info, bnot(CAVE_GLOW), bnot(CAVE_MARK))
                                        end
                                end
                        end
                player.redraw = bor(player.redraw, PR_MAP)
                end
        else
                last_light_count = 0
                light_count = 0
        end
end

add_hook_script(HOOK_END_TURN, "w_light", "w_light")

Module Developers Discussion/Dawn and Dusk (last edited 2005-09-23 11:57:03 by TheFalcon)