Lua Help - Sides and Lines

Questions about the content creation procedure go here, including using Forge, Anvil, or other editors, or operating emulators like Basilisk II.
Post Reply
User avatar
Zott
Vidmaster
Posts: 1666
Joined: Jul 1st '06, 21:14
Location: Earth
Contact:

I want to change some specific walls to a different texture in-game via Lua.

Right now, I have a list of the wall's numbered lines from Weland - this code works, but it changes the wrong walls.

Thank you for the help.

Code: Select all

function spaceMode()

    arenaLines = {
        97, 85, 100, 101, 102, 106, 32, 33, 25, 35, 36, 87, 82, 81, 77, 80, 79,
        86, 50, 51, 45, 41, 40
    }
    for b in Sides() do
        for i in pairs(arenaLines) do
            Player:print(b.line)
            if b.line == Lines[i] then
                b.primary.collection = 29
                b.primary.texture_index = 0
                b.primary.transfer_mode = TransferModes["landscape"]
            end
        end
    end
end
User avatar
The Man
Vidmaster
Posts: 1203
Joined: Aug 6th '08, 05:23
Location: Sarasota, FL
Contact:

first off: never, ever, ever use pairs() in an Aleph One script. it’s horrifically broken and will fuck up network games, film playback, and probably more (its biggest problem being that there’s no guarantee it will ever sort its data the same way on two machines or twice in a row, which to my understanding is because it depends on the ordering of data in memory, and there’s absolutely nothing deterministic about that. it is a horrible, horrible, cursed iterator that probably shouldn’t even exist. it is used for indexing tables that have non-numeric keys, or keys that start with values lower than 1, or non-consecutive keys, but... that’s also cursed. if it were up to me, aleph one would print a warning every time someone used pairs()). ipairs() at least won’t do the former two (because it actually is deterministic), so if you have to use either of them, use that. and if for some cursed reason you need an iterator function that doesn’t iterate over consecutive integers, write your own rather than ever using pairs().

secondly, there’s no need to iterate through all sides for every line; Lines[x].cw_side and Lines[x].ccw_side will get you the only possible sides the line could have.

third, Player:print won’t work; you want Players.print

fourth, there’s no need to write TransferModes["landscape"]; you can just write "landscape" (with the quotes).

fifth, never, ever tie any script that’s meant for more than onetime use to specific index numbers, because those will change whenever you delete lines/sides/polygons/points with smaller indices. that’s a good way to doom yourself to having to rewrite your script over and over, and ain’t nobody got time for that. for what you’re trying to do, it’s better to set a specific texture that will be replaced globally throughout the map, iterate through all sides, and change anything that uses that texture. however, if your map is sufficiently large, that could cause noticeable lag, so i’d recommend doing it over a second or so. one easy way to do this is to set an iterator, which i’ll label as i, to 0 when you start running this part of the script. (before this point, you’d want to set it as nil, or simply not bother defining it.) define this function:

Code: Select all

function retexture(x)
    if x.texture_index == FROM_TEXTURE and x.collection == FROM_COLLECTION then
        x.texture_index = TO_TEXTURE
        x.collection = TO_COLLECTION
        x.transfer_mode = "landscape"
    end
end
then run this somewhere in Triggers.idle():

Code: Select all

if i and i < 30 then
    for s in Sides() do
        if s.index % 30 == i then
	    retexture(s.primary)
	    retexture(s.secondary)
	    retexture(s.transparent)
        end
    end
    i = i + 1
end
(the i and part of if i and i < 30 is necessary to prevent the game from printing a warning about comparing nil with a number. this should not be necessary with the == operator, since that means “if (variable) exists and is equal to (number)”, but < and > aren’t so sophisticated.)

and obviously, you’ll want to define FROM_TEXTURE, FROM_COLLECTION, TO_TEXTURE, and TO_COLLECTION at the start of your script. convention is to write constants in all caps so that they stand out and can be easily changed to facilitate code reuse.

lastly, you’ll probably want to do something similar for polygon floors and ceilings, just for completeness’ sake.

i haven’t tested this because i don’t know for sure what you’re planning to use the script for, so let me know if there are any problems. i’ve written similar retexture scripts before that worked fine, though.
“People should not be afraid of their governments. Governments should be afraid of their people.” —V, V for Vendetta (Alan Moore)

“The trouble is that we have a bad habit, encouraged by pedants and sophisticates, of considering happiness as something rather stupid. Only pain is intellectual, only evil interesting. This is the treason of the artist: a refusal to admit the banality of evil and the terrible boredom of pain. If you can’t lick ’em, join ’em. If it hurts, repeat it. But to praise despair is to condemn delight, to embrace violence is to lose hold of everything else. We have almost lost hold; we can no longer describe happy man, nor make any celebration of joy.” —Ursula K. Le Guin, “The Ones Who Walk Away from Omelas”

“If others had not been foolish, we should be so.” —William Blake, The Marriage of Heaven and Hell

“The law cannot protect anyone unless it binds everyone; and it cannot bind anyone unless it protects everyone.” —Frank Wilhoit

Last.fm · Marathon Chronicles · Marathon Eternal 1.2 · Where Monsters Are in Dreams · YouTube Vidmaster’s Challenge
User avatar
Zott
Vidmaster
Posts: 1666
Joined: Jul 1st '06, 21:14
Location: Earth
Contact:

Thank you for the response!

1) Noted about ipairs vs pairs. This will be solo only, so it won't matter, but I'll switch it.
3) I define Player somewhere else, but I meant to remove that anyways.
5) So the workaround is to 'tag' a side with a specific texture to change it later via Lua. It's a good idea, but I might want to use those textures in places that I do not want to be changed.
Is there a better way to specify a side specifically without the texture replacement method? What I'm guessing is the line numbers are not consistent between Weland->Aleph One, or possibly not consistent between game reloads? I could probably get the side numbers via lua in-game if atleast the in-game side numbering is consistent.

The script is to change some walls to the space texture at a certain point in-game. Currently the texture replacement workaround is suitable on the small map, though I am interested in the feasibility of the direct approach.
User avatar
The Man
Vidmaster
Posts: 1203
Joined: Aug 6th '08, 05:23
Location: Sarasota, FL
Contact:

No problem.

1. pairs() breaks film replays even for single-player maps, so you should still avoid it. Basically, there are non-Aleph One uses for which it might be acceptable to use pairs(), but you should never do it in an Aleph One script.

5. If you don't ever change the map, you'll get the same results each time. However, anytime you delete a line or remove texturing from a side in Weland that has an index number below the line or side you've removed, you'll have to redo the numbering. This is objectively horrible, and I can tell you from personal experience that you should avoid it at all costs. You’ll lock yourself into either never editing your map or into rewriting the script half the times you need to change it. I wound up rewriting several of Eternal’s scripts to avoid exactly this problem.

One possibility, if you’re making a standalone scenario, is to just duplicate the texture (by importing the bitmap again and adding a frame for it). If you’re making a map for vanilla Infinity, that won’t be an option unless you want to use a shapes patch (which carries its own problems), but you have some other options.

Perhaps you can place a particular media on all the polygons that contain sides you want to replace. Since Weland doesn’t provide any options to delete media, this is far less likely to break. (If you need more than one media, you can of course adjust the script to look for multiple media.)

Another possibility is to place goal objects on whichever polygons you’re going to change sides on, then iterating through all goal objects and editing all sides on said objects’ polygons that match whatever texture you’ve set aside to replace. The following loop will print all polygons that contain goal objects:

Code: Select all

for g in Goals() do
    Players.print(g.polygon)
end
Adjust as needed.

Note that either of these approaches will also prevent you from needing to iterate through all of the level’s sides; you can just use Polygons[index]:sides() to iterate through a given polygon’s sides. As a result, you probably won’t have to use the iterator approach I suggested above when I assumed we’d be iterating through all of the level’s sides.

(For what it’s worth, I went with goal objects for some of Eternal and Tempus Irae Redux’s scripts, media for others, and probably something else in a few specific cases that aren’t coming to mind right now. One nice thing about using goal objects is that you can specify different checkpoints if you need the goals to perform different functions; however, in such cases, you need to make sure each checkpoint is unique. I think there’s a limit to how many checkpoints you can use, but I have no idea what it is. I’ve never bumped into Aleph One’s limit on media either, but I know it’s well above 128; my guess is either 255, 256, 32,767, or 65,535.)
“People should not be afraid of their governments. Governments should be afraid of their people.” —V, V for Vendetta (Alan Moore)

“The trouble is that we have a bad habit, encouraged by pedants and sophisticates, of considering happiness as something rather stupid. Only pain is intellectual, only evil interesting. This is the treason of the artist: a refusal to admit the banality of evil and the terrible boredom of pain. If you can’t lick ’em, join ’em. If it hurts, repeat it. But to praise despair is to condemn delight, to embrace violence is to lose hold of everything else. We have almost lost hold; we can no longer describe happy man, nor make any celebration of joy.” —Ursula K. Le Guin, “The Ones Who Walk Away from Omelas”

“If others had not been foolish, we should be so.” —William Blake, The Marriage of Heaven and Hell

“The law cannot protect anyone unless it binds everyone; and it cannot bind anyone unless it protects everyone.” —Frank Wilhoit

Last.fm · Marathon Chronicles · Marathon Eternal 1.2 · Where Monsters Are in Dreams · YouTube Vidmaster’s Challenge
Post Reply