News | Forum | People | FAQ | Links | Register | Log in
Teaching Old Progs.dat New Tricks.
You know about the info_notnull explosion hack. You know about making monsters drop weapons or alternate ammo using the .weapon and .ammo_whatever hacks. You know about making items float in the air by spawning them on a temporary platform. Let's have a thread where we talk about new ways to use existing behavior and get novel gameplay. If you're a "retired" mapper, this is a great time to do some armchair level design and suggest ideas you'll never have a chance to use yourself.
First | Previous | Next | Last
Rotating Objects Hack! 
GREETZ hax fans! Let's make things spin right round like a record baby.

This entity hack is actually pretty easy, it lets you make a rotating object in stock /id1/ quake, but is somewhat limited in what you can do. What we are going to do is make some non-solid, non-interactive rotating objects. Good for things like a ceiling fan that you will never interact with and just spins forever. I've actually used it before in my sm170 speedmap quite awhile ago, but it seems went unnoticed (negke hadn't heard of this method when I told him about it last night).


Ok, so first off, you need to make a func_wall fan object at the origin of the world. Make it's center at (0, 0, 0) in the world, this defines where it will rotate around. You'll need this entity's modelindex, so it may be best to make sure it's the first object in your .map file. As explained by some other hacks in this thread, the modelindex is a number given by Quake to each model in a level and lets us instance those models to other entities. The command 'edicts' in Quakespasm/Fitz/etc will help you find this number on entities in your level.

Now, where ever you want to have a rotating fan, place an info_notnull with the following properties:
"classname" "info_notnull"
"avelocity" "0 256 0"
"movetype" "8"
"model" "*1"
"modelindex" "2"

That's it! Obviously, use the modelindex of the func_wall fan you made. avelocity is the part that makes it spin, is the same thing that makes weapon items spin. Here we are spinning around the Y axis at 256 somethingspeed, this is good for a ceiling fan but you'll want to experiment with what is right for you! You can use negative values if you want to spin in the opposite direction.

Another key aspect is the movetype key being set to 8, this means MOVETYPE_NOCLIP in .qc, which is a movetype that allows objects to be rotated with avelocity.

Example .map and .bsp Enjoy! 
Thanks! We need fans in these hot, hellish environments! 
Really Cool! 
That Is Genius Scampie 
You better believe I'm gonna abuse that hack. 
Cool Stuff 
I just fiddled around with the rotation thing and you can totally have multiple objects, as long as they do not necessarily need to be shadowed. Even if you need 2 shadowed objects you can still do it with a bit of a caveat.

The source func_wall does not need to be at 0 0 0.

If it will only rotate on the z axis (world, which is y for the object, why is this shit mixed up, btw?) you can move it up and down on the world axis ( and if we want rotation on another axis of course that would work too, just move on the according axis) so that it does not overlap with another object there that needs to be lit.

Now you only need to move the info_notnull up or down counter the direction you moved the func_wall. For this to work the properly the info_notnull still has to be inside the world and ideally visible from all the points to the player where it would be would it not be shifted around. If that happens the object might disappear. That in itself could be used for some weird effects too though.

I was wondering if it might be possible somehow to give the info_notnull or the func_wall some kind of offset modifier so that the info_notnull can actually be at where the object should appear, without being shifted if the origin is not 0 0 0. 
is it possible to use it in conjunction with a func train to make a moving spinning blade trap thing? 
No :( 
the rotation values are odd because I'm pretty sure it's using Pitch, Yaw, and Roll, so rotation around the Z ends up as the second value. 
Yeah, I think that is right. 
I just made a clock in my map using this method. I noticed that the further away from 0 0 0 your func walls are the bigger the arc they travel in.

Also, there are other movetypes that also work, some that rotate as the object falls to the ground. Could be interesting to play with on a low gravity map.

Some more ideas for this, moon / sun / planets orbiting your map. A scale model of the solar system. Gears, or clockwork in maps. A fully sick car with spinning wheels. A spinning leek... I'm sure there are more. 
Back To The Future!? 
Here's a "hack"... in the id maps!

I was zooming around e1m4 when I noticed a funny looking block with an Ogre walking into it... Using sock's mod with path's visualized to show what is up:

Turns out, that block is a func_door on top of the first path_corner in a sequence the Ogre is trying to walk to... so it can never reach it and ends up sitting there forever!...

Until a trigger lowers the block out of the way. The Ogre can continue to walk out the door and eventually gets placed into a path_corner loop on the dock over the water. The end result is like a scripted sequence of triggering the ogre to walk out of the door on demand!


It's odd because it's very unlikely a player will ever notice this happen, the ogre walks so slow and the trigger that lowers the block is right at the edge of the water... In all honesty, if this were me, I would've just teleported that Ogre onto the dock when the player was out of view. But what id did here was make a basic scripted sequence with their primitive tools that only a few % of people might notice... But you might just hear the door open, and see the ogre lazily walk out and it makes the world so much more alive. It's wonderful :D 
That's Pretty Cool 
and the way monster teleporting works in vanilla is only slightly less of a goofy "hack" really. 
yeah, and mods as early as zerstorer 'unhacked' it and added progs functionality to just trigger a monster to make it appear.

id may have just never bothered developing anything better than teleport boxes because that's what they had in Doom. You built a long tiny tunnel to propagate sound into a room full of monsters to get them angry, then tagged a door in the room to open and reveal a teleport linedef and then just hope all the monsters eventually crossed it as they wandered angrily around said room. id probably thought having the 3rd dimension on their side to make monsters fall directly into the teleport brush was high technology. 
High Framerate Animated Textures 
Has it really been more than 3 months since the last hack? Well, good things come to those who wait.

Today's hack offers a trick to upgrade the 5 fps animated textures into 10 fps animated textures instead. This should benefit maps with waterfalls and lava flows a great deal... 
Notnull Hack? 
Im not sure I know this one, can someone explain it or point to a resource that explains it? 
A Primer On Info_notnull 
My intro to map hacks post uses info_notnull and mentions why we like it so much 
Awesome Preach! 
Thanks for posting this Preach! It will be interesting to look into at some point. Your waterfalls are already at a pretty high fps so I take it this wouldn't' do much/anything for them correct? 
abutton1, bbutton1, cbutton1....mind blown!

Whoa! func_wall.use changes texture...mind blown again!

Double wammy there Preach. 
Don't Go Chasing Waterfalls 
Thanks for posting this Preach! It will be interesting to look into at some point. Your waterfalls are already at a pretty high fps so I take it this wouldn't' do much/anything for them correct?

This trick is really for animations on BSP object, things made out of brushes. My waterfalls are in .mdl format so they aren't applicable to this trick. However, I think this will be great for making waterfalls in places where my model can't be used, e.g. in vanilla maps or spots where the waterfall has to be made to fit. 
I'll Stick To The Mdls I'm Used To. 
Ah okay I was figuring that was the case. Always excited to get a new map hack from you. I already have numerous ones from the past implemented in my current project! 
That's Deviously Clever 
Nice one! 
Could Make It Even Higher Framerate 
In theory you could go higher framerate and double it again for the framerate hack. just need to add another 2 layers of meshes switching at .25 and .75 seconds delay. I think I will have to give this a go at one point as well :) 
Monster Only Teleports 
Neat trick I found. If you place a trigger push with a velocity of 100 right in front of a teleport the player won't be able to use it (if its angles are right, you could always suck the player in for a neat trap!). If you then place a trigger_monsterjump a hair bit in front of it and give it the same forward velocity of 100 but an up velocity of only 1, it will negate the push and let the monster teleport. You could reinforce the concept by putting a func_illusionary in front of it with a unique teleport texture. If you want to make the teleport useable later such as after a fight, you can killtarget the trigger_push and the func_illusionary. 
Sort of a neat trick as opposed to TE_TELEPORT effect at either side of the ent being teleported is if your engine has a .alpha field you could "fade" him out while non solid, hijack his think to be the fade function until hes perfectly transparent, then transport him, and fade him in using the same function in reverse. If done with the right timing it could look pretty good, and you could throw in a EF_BRIGHTFIELD at the end for maybe the last few frames while transporting, and the first few while "rematerializing"....

If the engine has EF_ADDITIVE for blending, I think it looks even better. 
Invisible Teleport Randomizer 

targetname movingteleportdest1
target path1wp1
speed 200
avelocity "100 200 300"
solid | 0
movetype | 7
use train_use
nextthink 0.2
think func_train_find

Borrows code from the misc_teleporttrain to create a moving teleport destination that is invisible. Use in combination with a monster teleport box whose targetname is movingteleportdest1. Give a nice path above an area to drop in monster in a randomized locations. Put multiple monsters in the same long teleport box with only one teleport and you can cut down on trigger_teleport requirements, and add randomization. 
Oh And... 
make sure something targets it or else it won't move.

As an extension of this idea, you could have a teleport that changes destination by having it target this entity and giving the 2nd path_corner a wait of -1. 
You can teleport to monsters, even dead ones. :) 
And Items 
Fiends Hatching From Grunts 
So you give a grunt 'effects 8' and when he dies, he trigger spawns a fiend into his own location. 
Too bad you cant gib corpses this way... have a grunt spawn a zombie or fiend in a spray of gore! 
You Could 
Spawn a zombie, then after 0.05 seconds spawn a fiend at the zombie's position.

Best way would just be to use qc though so as not to inflate the monster count. 
Would be unwise to spawn large monster from small monster due to bbox Size difference. 
Yeah, qc would be good again to check for !walkmove. 
Public Polling 
So, which hack should I write up next:

a) A trigger which randomly selects between triggering "event_a" and "event_b"


b) A trigger_counter which can be reset and used over and over again.

I mean, eventually I'll get round to both, but which one should I do first? 
a, though b sounds more interesting. 
i can do a) myself already VERY hacky, i'm most interested in hearing your solution. 
A Is Just A Logic Gate Shooter With A Func_train Oscillating Rapidly 
Do b) 
You'd Think That 
but im sure there is a much more clever solution to it. 
Preach us probably accessing the video buffer for the screen and using the pixel colours as random numbers with 3 info_notnull entities. 
I Vote B! 
For I Have Touched The World..... 
// Try it...jump around on any map

void () test_touch =
if (other.flags & FL_CLIENT) bprint ("OUCH !n");

void () worldspawn =

world.touch = test_touch; 
Reusable Trigger_counter It Is 
From what I can see, there's been more discussion about the randomised trigger, but more explicit votes for the reusable counter. Since we live on a democratic message board, we will ignore the prevailing enthusiasm and go for the winner instead.

I've been playing around with the idea over the past week, trying to come up with the simplest implementation of a reusable counter. I think I'm basically there now, but one of the features requires a logic gate, and a flaw in my previous article on those has become apparent, so I will fix that first, and then the new hack will follow. 
Oh Goody 
Another two-fer! 
The Ol' One-two 
So the fixed logic gates are up at

The updated portion is highlighted in yellow. I've also updated the example .map at both to incorporate the update to the article, and to make the example map playable. All four gates are hooked up to example entity systems and can be tested in-game.

Now for the new stuff...
Not only featuring reusable triggers, but also triggers which you can interrupt to reset during their count.

Bonus content: What went so wrong in the original logic gate post to make Preach miss out a vital entity? I often use a "clean" copy of the QC source to test things out. Unfortunately, this clean copy is not quite 100% identical to the basic Quake source, and W_FireAxe is one place they differ. My "clean" version has a call to makevectors which the original Quake progs is missing. This doesn't affect the player code which has some redundancy, but the axe hack entity is not so lucky and started firing in a random direction. The changes to the article work around this. 
When you ask a question and then answer it before anyone had a chance to say something, that's usually a rhetorical device. Not today though, I just happened to crack the puzzle I set myself last time, and made the reusable counter work without a logic gate. Read the follow up article here:

Still not enticing enough? Well, the post links to an example .map file, so you can copy-paste the hack without the need to understand it! You want more? Well, the article even invents the anti-counter - an entity which acts like a trigger_relay until you've used it n times, rather than one which only acts like a trigger_relay after you've used it n times. If you want a crusher or trap the player can only activate a few times before recharging it, this does the job. 
Preach You Mad Man! 
All shall bow to the Quake hacks of the one they call Preach. This is Preach's world full of logic gates, high framerate clocks, and waterfalls (That only spawn on nightmare.)

Countless possibilities with this addition, thank you sir. 
Preach, I am in awe. 
I can't even comprehend any of this madness... You're basically the gandalf of map hacks 
or the map hack of gandalfs. 
or the enemy of compatibility... 
This Is A Public Service Announcement... 
or the enemy of compatibility...

Oh believe me, I spent a long time working round map hacks in Quoth - there are specific "shims" for maps which use hacks that subsequent version broke. It's also something that I do bear in mind when making changes to the code base - e.g. renaming OgreGrenadeExplode to MonsterGrenadeExplode would be appropriate in Quoth because Defenders fire the same grenades, but that would break a basic map hack which outweighs the benefit.

For everyone else I think it's worth repeating the standard reminder: Map hacks are for standard Quake only. There is no compatibility guarantee for any other mod. Do not use them in Quoth or AD or anything else. 
Sock had a strict rule that we couldn't use map hacks in AD. Made sense 
Very Fair 
I figured it was for vanilla Quake. The only hack that I currently readily use is the nightmare hack. I am currently mapping using AD and the hack works wonderfully. Actually, with triggers like monsterkill I can fix the kill count totals when playing on hard!

I know I use them at my own risk though. ;) 
Well, if you are mapping for a mod in development, that makes sense since you could just code up whatever you needed. Map hacks are cool to add surprises to standard quake. 
I am currently mapping using AD and the hack works wonderfully.

What happens when sock releases a patch that fixes a long standing bug in the lightning gun and as a byproduct breaks the hack? There are a multitude of ways that could happen: renaming the function, checking the current ammo rather than the cells or adding a new parameter to the function to name but three. All perfectly innocent changes which happen to break your map.

The issue is that the map hacks are not forward compatible - new versions of the mod might break the hack even if it works on current and past versions. This isn't theoretical, it happened in practice on maps between Quoth 1 and Quoth 2. The safety of the hacks in vanilla Quake also depends on iD never releasing another patch, it's just that after 14 years it seems a fairly safe bet... 
A Fair Point 
Would the example be the same with the Shambler magic lightning?

Either way, I suppose if a patch came out and it broke the NM hack and I was fully invested in my current project...I'd remove the nm hack components.

I fully understand the risks good sir. :) 
The only real thing to say in this instance is that you'll have to package your project with your version of AD to retain the functionality. Or figure out a way to implement your ideas without resorting to map hacks, if possible. 
Cause And Effect 
Either way, I suppose if a patch came out and it broke the NM hack and I was fully invested in my current project...I'd remove the nm hack components.

But if the patch comes out after you release your map, you're stuck. Unless you want to keep patching your map.

For their part, mods ought to look at the most popular map hacks and see them as features they ought to offer in a supported way. I'd guess that was part of what the no-map-hacks rule for AD was about - code the needed feature instead for all to use. 
Sock didn't want us relying on map hacks as patches and stuff could break the maps. If the mappers wanted a feature in their map then Sock would just code it into the mod. 
Something To Ponder 
I appreciate the advice. I may remove the NM hack. Luckily, the current project I am on I have yet to implement it...and this particular project I hope to publicly release someday.

Hell, I could always make a seperate version of the map that supports the NM hack. For now, I'll worry about Easy, Normal, and Hard.

Thanks FifthElephant and Preach again. 
Thats a doosey of hack Preach (and another two-fer no less). I see more awesomer puzzles in the future. 
Random Numbers 
Now, I'm more into my stats than most people, I know that. So for my upcoming random switcher hack, I decided to check just how random it was. I made sure that the hack generated some loggable messages I could parse, ran with -condebug, generated 10,000 random events and loaded them into R.

The results were disappointing. Although the number of "Choice A" and "Choice B" generated were nearly identical, the chance of getting "AA" (an A followed by an A) or "BB" was higher than getting "AB" or "BA" (all four should be 25% probability if the system was fair).

I had spent several nights trying to fix this with various reconfigurations of the entities, but never managed to make significant headway. Then I decided to knock up a quick mod which would spit out A and B into the console using the random() function directly, just to check. And of course it turns out to have this same issue but worse. So I will be releasing this map hack shortly... 
The Most Unpredictible Follow-up Post 
Here's the hack:

Whatever will happen next? It's impossible to predict, because I haven't hyped it for months or even thought of it yet! 
QC support for Notepad++, including Function List support and syntax highlighting: Tutorial & download
Have A Semi-working Hack That I Need A Little Assistance With 
I am making a false train using func_wall and info_null. The purpose is to get a couple of overlapping entities that behave like a train (follow a path).

I have a func wall for the model, 2 path_corners with each other as their targets, a trigger triggering it and an info_null with the following values.

use train_use
think func_train_find
speed 20
modelindex 8
model *1
movetype 8
nextthink 1
target stop_1
targetname me

the odd behaviour is, that when it gets to the first stop, it spazzes out and jumps forward and back among the path corner locations, without traversing them first.

any ideas? 
Possible Tweak 
Hi Shamblernaut, can you try something for me and see if it helps? Change the movetype from 8 to 7. It's a hunch, and it'll take a lot of explaining which I'd rather only type up if it's the correct fix. Thanks, let me know how it goes! 
how just about trying to use a true train?..

and yeah, the SUB_CalcMove function, which is responsible for setting up velocities and nextthink for the various pushers to use, is explicitly tied to MOVETYPE_PUSH(7) on account of its use of 'self.ltime' rather than 'time'.

movetype_push and solid_bsp(4) are kinda tied together in many engines too, so be aware that separating the two will often give engine-specific results. 
That worked a treat, thanks preach. I still need to sort out the sound not being precached, but any victory is a victory and I'll take it.

@Spike, using a true train doesn't allow me to overlap my geometry, which is necessary for what I'm trying to do. Also, thanks for the headsup about engine pushtype handling, I guess I'll just require people to run the map in quakespasm =P 
Existing Practice 
movetype_push and solid_bsp(4) are kinda tied together in many engines too, so be aware that separating the two will often give engine-specific results.

Don't all engines need to handle it already because of misc_teleporttrain, which does exactly this? I mean, yeah, it probably shouldn't be written like this, but we work with what we have... 
Teaching Old Preach New Tricks 
Mankrip - Thanks! 
Static Entity Shooting Scrag Projectiles 
is this a thing that's possible? I want to use it as an acid drop in my mapjam 7 map (quoth). 
Post #14 
Cheers Man 
Please use info_trap instead of a hack that we will unintentionally break with a future patch to Quoth. 
the scrag / wizard stuff doesn't work with info_trap :( 
Trap Sprung 
Holy Shit 

"modelpath" "progs/w_spike.mdl"

I thought that wizard / scrag magic was a particle effect.

my bad.
To Elaborate 
I was using the scrag shooting function like one would with a info_null as in post #14.

Didn't even consider using the trap function as intended. 
Invisible Water? 
has anybody made water with invisible(transparent) texture, just wondering because that might have some interesting uses. 
Just Try It. 
I'm interested of the outcome. 
But using q3map2, so probably not what you're looking for.

*waterskip Texture 
fuck, I misunderstood.

I feel like fiddling around in the progs could get what you want fairly painlessly. 
I asked in mapping help but maybe here would be better for my question.

In AD I want the Golem to only have melee attacks, no projectiles. This is listed in his mon_golem.qc right before the range attack code:

if (!self.enemy) return;
if ( < 1) return;

Now if either of those are true he will skip the code for firing projectiles.

I tested a modified AD progs by the simple addition of a return; above the "if" statements and got a melee only Golem. But that's not really an option.

The function is called void() golem_rockstorm =

Any progs.dat tricks for this? Even if it's not an "old" progs :-P

Could he fire the doggie's attack instead!!! I still need him to STOMP though... 
Don't Trick The Mods 
It's a bad idea to use map hacks against a mod which is in development. In effect you're trying to apply a hack to a moving target - the mod may change that code in the next version and break your hack. The reason that id1 hacks are acceptable is because id aren't ever going to release another patch for Quake, so all behaviours (even unintended ones) are unchanging... 
I bet plenty of custom engines break certain map hacks. I don't have any examples to hand tho - know of any? 
You write: "I want the Golem to only have melee attacks."
Then you edited the code and write: "I got a melee only Golem."
That was what you want. So what is wrong?

If you want to give him a different behaviour for ranged distance, then all you have to do is edit his ranged attack code. There is no TRICK needed. Just do it.
The Golem code works like any other monster code.
You first have to know what you want. Then do it. Yes, its that easy. 
I don't think I should "fork" the AD progs. I'd see that as a nightmare for a map(s) release.

Requiring players to duplicate their AD directory, replace the progs.dat with "my" version and then install maps and not get confused is it a bit much, yes?

That's why I was looking for an alternate solution.

I'll just put it on the backburner for now.. 
In Theory Or Practice? 
I mean, in theory almost anything could be broken by a determined custom engine. One that I worry about in theory but haven't ever seen break is the high frame-rate animation from
This relies on a global timer on .bsp animations. Given that some engines have removed the global timer on looping .mdl animations (much to my irritation) it doesn't seem impossible that the same might befall the .bsp ones.

The thing with a lot of the map hacks is that they involve tricking the QuakeC - and engines tend to preserve QuakeC behaviour pretty well. Most of the stuff that happens in a map hack is legitimate QuakeC, just unintended. I suppose any hack which involves the order of the list of entities would be vulnerable to an engine which changed the order to be non-deterministic, but again I've not seen it in practice. 
Was intended as a toolkit. That includes making your own stuff 
You mind if I send you an email with the map setup and why I want this?

No worries if you don't ant to bother. 
Go For It 
@FifthElephant, Sent 
My email addy is strange, begins with uw_ Don't ask, hehe 
Fun Fact 
The function trigger_reactivate is defined in standard QC but not actually used anywhere. In full the function reads:

void() trigger_reactivate =
   self.solid = SOLID_TRIGGER;

Can you think of an interesting hack to perform with the unused function? 
Kinn was complaining that you can't have disabled triggers in id1.

Couldn't you have a trigger with SOLID_NOT (SOLID_NONE?) and then come up with a way to use the above to activate a trigger that started disabled? 
The sophisticated 'super logic gate' idea Preach is about to come up with!

Or perhaps at least an easier way to do things like the switchable push hack and the like? 
First | Previous | Next | Last
Post A Reply:
Website copyright © 2002-2017 John Fitzgibbons. All posts are copyright their respective authors.