News | Forum | People | FAQ | Links | Search | Register | Log in
Mapping Help
This is the place to ask about mapping problems, techniques, and bug fixing, and pretty much anything else you want to do in the level editor.

For questions about coding, check out the Coding Help thread: https://www.celephais.net/board/view_thread.php?id=60097
First | Previous | Next | Last
Trigger Hack 
info_notnull (brush)
use trigger_once
touch SUB_Null
targetname
target

See progs.dat thread. 
Yeah 
Negke describes the only way to do it in the current version. It's not actually a bad way of doing it, the only thing that I feel is slightly dodgy about it is that the entity never ends up with the correct classname, but it's unavoidable. A more sophisticated method of doing this kind of thing(activating triggers /entities when other events fire) will be in the next version of Quoth, but that's a long way off.

I was hoping to be able to finish this with a short snippet of code to add to a clear quake source, which would make the "simplest way" work with all triggers. Sadly this isn't really possible, the only function which is called on all triggers is InitTrigger, but you can't do enough with it. It doesn't know what function calls it, so you'd need to hide all the possibly relevant fields like touch/use/health/etc, and create a use function
which restores all of these values. But even then you get ruined by trigger_teleport, which overwrites the "use" field after the call to InitTrigger. Bah! 
RickyT23 / Negke / Preach 
RickyT23: I'm using metlslime skip for glasses, and I'm not sure it will help me with my issue :P

OKnegke: I'm not sure to clearly understand, well, I'll give it a try, and I will have a look in te progs.dat thread in anyway..

Preach: Thanks for the infos... ;)

So globally except the method negke described, there's no other way to do what I would like... or I will have to wait for Quoth3 :P

Anyway, thanks alot for the help: you rock ! 
On How It Works (the Nth In A Series Of Overly Long Posts By Preach) 
I think it's about time there was a good post on why that particular info_notnull trick works, because it's a bit complicated why you move the classname to the use field to make it work.

What is a classname?

The classname field is a qc field which stores a string. From the point of view of the QC, it isn't any different to the message field. There is only one thing which is special about classname, which happens when the map starts.

When the engine loads a map, one of the last things it does is load the list of entities, which looks a little like this:

...
{
"classname" "misc_fireball"
"delay" "15"
"target" "drawtrap"
"targetname" "draw"
"origin" "-352 -1168 160"
"use" "trigger_once"
"model" "*2"
}
...

You can see that all the fields you enter are stored as pairs of keys and values. What the quake engine does for each one of those entries is:
1. Creates a new entity with all of it's fields set to 0.
2. Fills in any of the fields listed in between the {...} with the value given.
3. Sets the "self" entity in the QC code to be this newly formed entity.
4. (this is the important bit) Searches for a function in the qc code with the same name as the classname of the entity, and then runs that function.

The function with the same name as an entity's classname is usually called the class "spawn function". There is technically nothing special about the QC in a "spawn function" - any valid function name is allowed as a classname. But usually "spawn functions" are designed to do important things to "self", like making it solid, giving it an appropriate model, and starting the ai functions in the case of a monster.

What is the use field?
In the example misc_fireball entity above we see the use key has been added. It looks like the use key follows the same format as the classname key, but this is misleading. In QC, use describes a function, not a string. When the quake engine carries out step 2 on the use key, it looks for a function whose name matches that string. Once it finds that function, it stores the function location for the QC and discards the string.

In the (very contrived) example entity I have invented above, use is set to "trigger_once". We are used to trigger_once being a classname, but as we learnt above classnames are always the name of a function. So when we trigger the event "draw", the QC finds every entity with a targetname of "draw". It then calls the function stored in use.

In this case, this gives the entity all the properties of a trigger_once, on top of whatever fields were filled out when it became a misc_fireball.

The thing to remember is that running the function doesn't change it's classname to trigger_once. Sometimes the classname matters (see http://www.celephais.net/board/view_thread.php?id=4&start=6068&end=6068 for the classic example). However, I can assure you that trigger_once is not like that, the classname is never checked once the entity is spawned. So the hack is in fact safe.


What is an info_notnull?
So why are all the hacks obsessed with info_notnull? Well, it's because info_notnull is an entirely empty "spawn function", it does nothing to the entity at all. One of the challenges of making entity hacks is finding a function which does just enough. If you make the classname "trigger_multiple" then it does all the work of making a trigger for you. But that function also overwrites any custom value for use or th_die(a function like use, but called when you kill an entity). Sometimes doing nothing is exactly what you want, in which case you choose info_notnull.

Bringing it all back home
So using all that knowledge, we create a brush based entity with these fields:
{
"classname" "info_notnull" //do nothing on spawn
"use" "trigger_once" //do what the spawn function for trigger once does once we fire the event
"target" "spawn01" //the event which makes use happen
"targetname" "newevent" //what the trigger sets off
}


Hope that was enlightening.

ps: The difference between classname and use is why mutliple-spawning entities in hipnotic/quoth/quake-mods always have two fields you need to fill out: spawnclassname and spawnfunction. The former is a string which is copied to classname, the latter is a function field which is called to replicate the engine function of looking up the classname function. You could of course mess with the program by setting the spawnfunction to monster_ogre and the spawnclassname to monster_shambler

Extra Credit Assignment: describe what you would see if you did set "spawnfunction" "monster_ogre" and "spawnclassname" "monster_shambler". Creating a test map to find out is cheating... 
 
"Hope that was enlightening. "

It really, really was. Thanks a ton for those overly long posts, Preach. They are ridiculously enlightening and useful. 
I'll Hazard A Guess 
The monster will function as an ogre, except that it will infight with orges and not infight with shamblers. It will also take half damage from explosions, which is probably just as well, as it will be somewhat careless about how he shoots his grenades... 
Ok, Just Tried It 
And I forgot something... 
Yeah 
I'd say you got all the important differences, the shambler alert sound and death messages are also used(although the former isn't precached). But yeah, very good work! 
Preach 
The explanation is really complete and detailed, but I'm still not sure how to implement it: Would you please consider to provide me a short and simple map example (.map / .bsp) that would enlight my spoor mapping skill... 
 
It's a info_notnull brush entity. Just create a regular trigger and change the classname field. 
Preach 
Suggestion for Quoth3: customizable light styles, e.g. with "message" "abcdedcba", if that's easily feasible. 
Preach 
Forget the example, I think I understood the idea thank to negke precision, I missed this important point: The info_notnull shall be a brush !
Thanks a lot for your support guys ! You rock ! 
Ok! 
Explore the world of Fodrian! Operate arcane machinery! Defeat your foes to earn your right to return! Source .map included.
http://www.btinternet.com/~chapterhonour/summon.zip 
Arrgh 
Oh well, it's a nice pretty map for the next person who asks.

re: Custom light styles. Yeah, that's possible. The best way I can see to do it is have an info_lightstyle where you set style to some number between 20 and 31(32 onwards are reserved for switchable styles, and for purposes of this example I'm reserving 14 to 19 for potential quoth standard light styles) and message to the custom light style. Then you just give any lights you want the corresponding style.

It should also be possible to make these entities targetable. If one was given a targetname, then it would not define the light style when it spawns, but instead when it is triggered. This would allow for dynamic control of light styles, and could possibly be extended to the regular defined styles(although it would still be a bad idea to let styles above 32 be controlled in this way). Possibilities this would open up include:
Switchable flickering lights.
Event triggered lightning flashes across a level.
Day to night transition(if you can figure out what to do about the sky). 
Pretty Map Indeed 
Day to night transition(if you can figure out what to do about the sky).
Nothing easier than that. Quoth's trigger_command with "loadsky skybox_\n". Just do it while the player does not see the sky. It will give a short load freeze though.

More engines need Ogg Vorbis soundtrack support and then also allow the "cd <command>" commands to control it. trigger_command with "cd play 123\n" is just great.


It would be great if the information that \n is needed would be added to the Quoth documentation, I just now remembered and it (once again) gave me a headache yesterday. ;) 
 
It would be great if all 25% of missing information would be added to the Quoth documentation as well. 
Schaweet 
Sky 
Yeah, changing the skybox works until you have to worry about engines which don't have skyboxes! I think a daytime sky texture with a non-solid func_ brush covered in scaled up black texture which is removed on daybreak/spawned for nightfall is the way to go. I think that's what we did for travail, anyway... 
Terrainmap 
I'm trying a terrain map with brushes in shape of triangles.
They all have one toppoint en three corners.
As I managed to get them well fit without warnings I've come to the lightning problem.

Most of the triangles get a bad dark shape, as others come through well.
I've read aguire's tool tips but I can't find a way to avoid them. 
 
I've seen that as well. I think it's just that the BSP compiler can't handle it. I've never had a ton of success with triangular terrain. Even if it lights correctly and looks good, you still get weird collision snags. 
As For That 
ive terrain-mapped using triangles quite a lot in Quake, (well since slave anyway):

if you get errors in hull 1 (clipping errors) try making the area simpler - make the bad "join" 0, 90, 180 or 270 degrees in a straight line.

Also dont make the triangles too small.
And try to stick to a 16x16 grid at the smallest.

All seem to help me!

Hope this helps.

Also try Tyrlite to do the lighting... 
Errorshades 
Do your triangles have 4 or 6 corners?

I used primary geocomponents for Quark, triangle brushes of width 6x 64, and I have no warnings, all brushes aligned within 0.1 and integer centers.

First I tried the light with wait function as it gives a more egal lightning. But it looks as if the area's on the floor give the most shade.
If I use brushes with a butom, ie. 7 corners the effect seems less.

Both versions of Tyrlight reach the same results. 
6 Corners 
64 units deep. when it was flat. all aligned to 1 unit. the triangles are on the horizontal axis.

They look like three-sided triangles when you look at them from the top down.

the whole effect can be transposed onto another axis too, though. 
Well 
I tried with 4 corners, but it seems then the floorcount in the lightning starts to behave like _not lighted from downside_ what creates the blackouts.

With 6 corners this floorcount is out of order, and they indeed light better.

Thanks for your answer! 
MadFox 
Use Nemesis's terrain generator... and import the resulting .map file. Change the texture and you are done ;) 
First | Previous | Next | Last
You must be logged in to post in this thread.
Website copyright © 2002-2024 John Fitzgibbons. All posts are copyright their respective authors.