This site will work and look better in a browser that supports web standards, but should be accessible to any browser or Internet device.

Copper Quake

Copper

Mapping

Overview

You'll need copper.def or copper.fgd, which are included with the mod. See documentation for your editor of choice for instructions on loading one of these. As a result of restrictions of the two formats, the Worldcraft-format .fgd contains more field metadata, but less descriptive text, while the QuakeEd/Radiant-format .def is the opposite. For human-readable tutorial text, searching copper.def for an entity classname will generally tell you everything you need to know.

There is no exhaustive documentation of spawnflags and keyvalues to be found here - copper.def/fgd loaded in your editor accomplish that better where you actually need such information. I have tried instead to provide a practical guide to what new tools are available to mappers and what new things they make possible, which is the sort of information that can't be easily gleaned from scanning technical specs.

Ideally, perusing this document will give you ideas. Tools for smoothing the act of play and the act of construction are common. Thematic sugar for worldbuilding is not, nor are means of taking direct control of the experience.


Philosophy

Copper makes things better for mappers primarily by making things better for players, not the other way around. What this means is that by polishing and deepening the core gameplay, Copper amplifies the mapper's power to create fun, dangerous challenges using the game's core elements: enemies, resources, and 3D space. Therefore, before you continue reading, understand that the most important things you need to know about Copper as a level designer are here.

Style

The hallmark of "gamey" or "arcadey" level design is a conversational style. While the best levels aren't lacking competent visuals, the world the player finds themself in doesn't fully pretend to be a real setting, a chapter in a story, or anything other than a handcrafted clockwork machine designed to make them pay for every inch of progress. The designer builds an escalating arc out of challenges arranged using game rules and elements, but more importantly the player knows it, letting their understanding of how to exploit those same elements guide them past the threats. It's a lot more like a puzzle than a world in this regard. As first person games move ever further towards tightly-authored roleplaying experiences, this type of honest level design is increasingly forgotten.

While players can get better at a shooter by aiming better and reacting faster, there's a low ceiling for improvement there, and playing games that test only those skills can be downright painful. It's much better when a player has room to improve through learning mechanics and the interactions between them. For example, to a low-level player, infighting is just a funny thing that happens sometimes, but to a skilled player it's a tool on their belt for saving resources and managing the scale of a fight.

When players can't counter a greater challenge with better play, the outcome of play is more dependent on conditions set by the designer, and thus if a player dies in a certain place, there's little they can do to ensure they don't die there again. In other words, the difficulty spike is insurmountable and the level is imbalanced and wrong, usually for not having "enough" health or ammo.

When that skill ceiling is higher, however, "enough" ceases to be a meaningful term. Doom E4M1 famously provides exactly 5 points of health on Ultraviolence - it's a damn hard level, but still beatable without relying on luck, and (critically) small enough to encourage the experimental repeat attempts necessary to rise to the occasion.

Feel free to think of your design in these terms. Copper provides more of that depth for players to understand so that mappers like you can squeeze more excitement out of them.

Balance

Don't let the above convince you that Copper doesn't facilitate adventure level design, or that it values only shooting gameplay above all else. Doomworld's excellent retrospective of 25 years of Doom level design highlights two major threads in Doom's custom mapping history: hard-as-nails combat puzzle maps and more thematic, atmospheric adventure maps. More to the point, it highlights how the two threads have been fused in recent years. While Copper, for simplicity's sake, may not provide some atmospheric level design tools like breakables, that's not to say that exploration and discovery aren't supported. Learning your way around an environment that doesn't lead you by the hand is an important player skill for games of Quake's era, and there's still a million ways to hide a secret.

This has ramifications for difficulty balance. The two schools of level attract two types of player. Some players will prefer to go full run-and-gun, but are terrible secret hunters, while others aren't professional monster killers but love to investigate every corner and clue, relying on the extra spoils they uncover to keep them afloat. Since secrets are by nature optional, it isn't normally fair to balance your level such that it's impossible without finding some or all secrets ... at least on the first three difficulty levels. For the proverbial player that wants a tough challenge even with most or all secrets found (or known in advance), Nightmare is just the skill for them. Balance accordingly.

General Additions

Monster Spawning

Every monster can be configured as a spawner, rendering exterior teleboxes obsolete. Set the TRIGGERED spawnflag on a monster, and it will spawn when triggered instead of at map start. Set the INSTAWAKE flag to make the monster spawn angry at its activator. To make this a multi-use spawner, set count to the limit you want, or -1 for infinite spawns.

If the limit is positive, that many kills will be added to the total at map start, but if the spawner is unlimited, a new kill will be added to the total each time a monster is spawned.

A pre-spawn delay can be built into any monster spawner with the wait and rand keyvalues, if you'd like to raggedly stagger an ambush without a lot of extra trigger_relays or thought. After being triggered, a spawner will not produce a monster (or the teleport flash) for wait seconds, plus anywhere up to rand additional seconds. Note that this is different from delay, which causes a monster not to fire its targets upon death until after that many seconds have elapsed.

Set the NO_TFOG flag to supress the teleport particle flash and sound effect when a monster is spawned this way. There's no need to stress the particle limit if a bunch of monsters are being spawned out of sight of any players.

Triggered monsters with the NO_TELEFRAG flag set will wait to spawn after being triggered until doing so will not telefrag any other monster. Useful for trickling monsters into a room (emulating Doom-style teleport ambushes) without comedy gib collisions. They will still spawn and self-gib if the player is in the way, regardless of this spawnflag. If a monster is blocked in this fashion it will automatically try again on its own, so from a level scripting point of view it is safe to fire and forget such monsters.

A monster with a movedir set to a valid vector will be launched with that velocity upon awakening the first time (or upon spawning, if trigger-spawned), to save on excess trigger_monsterjumps. This vector always has to be bigger than you think it does. A trigger-spawned monster or a monster with a movedir will never do the drop-to-floor test before spawning, and will appear exactly where you put it. rmovedir (with an 'r') will specify velocity relative to the monster's facing angle instead of absolute to the world - the format is (forward right up).

Monsters created by a spawner will directly inherit all of the following keyvalues:

spawnflags, deathtype, message, delay, movedir, rmovedir, alpha, skin, effects, armortype, armorvalue, items, invincible_finished, invisible_finished, super_damage_finished, radsuit_finished, lip, state, gravity

Spawned monsters also inherit all the target keyvalues (including killtarget) from the spawner, but not its targetname, to avoid interfering with the spawner itself. If you need to spawn a monster with a targetname, set the spawner's netname to the string you want to become its targetname.

Keyvalues

Many more keyvalues are hackable than vanilla Quake, in that they will not be set at spawn time if they already have a keyvalue of that name specified in the map. This can be used for a great deal of new nefarious things, the most immediately useful of which are documented here as well as in copper.def/fgd. For example, the deathtype keyvalue can be universally overridden, so any monster, bottomless pit, or crushing mover can provide a unique obituary message, should you feel inspired to fill your level with King's Quest-style death puns.

Many keyvalues that default to something other than zero (and therefore cannot otherwise be set to zero without defaulting to something else) can be set to -1 to force a zero. This logic was applied inconsistently in vanilla Quake on a case by case basis, but was made as universal as possible in Copper. This does not apply to keyvalues where -1 would itself be a valid setting (such as lip on movers like func_doors), in which case alternate methods are often available to achieve the same effect (in the prior example, using the distance keyvalue instead).

Creature Clip

Any skip-textured solid entity can be effective as "creatureclip" by setting the notrace keyvalue to 1. This makes gunshots, line of sight checks, and projectiles (including gibs but not heads) treat this entity as nonsolid, but all other entities (anything with a bounding box) will see it as solid. This is very useful for making monsters walk over grates or other fancy holey floors without preventing players from shooting up at them or monsters seeing the player and returning fire. Use fancy runemetal floors over exposed lava without fear that your monsters will refuse to navigate over them.

Care should be taken when creating tandem invisible creatureclip movers to encourage monsters to walk onto func_door- or func_plat-based lifts. Monsters tend to 'bounce' when riding these double-platforms, since the game can't decide which mover the monster is standing on from one frame to the next. Shrinking the skip-notrace mover by a few units alleviates this, but can cause its own problems with the two movers becoming desynchronized if something blocks one, causing it to reverse, but not the other. Use an entity that doesn't reverse when blocked if at all possible, like a func_train, and test heavily.

Cheats and Impulses

Noclip mode has been improved to match noclipping in other Quakes, and prevents all interaction with the level. The player is nonsolid to everything when noclipping, including items and triggers, as well as invisible to monsters, so you can fly around without accidentally touching and activating stuff.

Turning on God mode while dead will function as an in-place resurrection, respawning the player in place with their inventory intact and health restored (but still vulnerable).

The following impulses have been added as development aids. (Most are aliased as commands by Copper for easier reference.)



The nomonsters cvar actually works now, but if your map has monsters that fire triggers on death which are necessary for completing the level, it will break for obvious reasons. Use the exterminate cheat instead to avoid this.

Cooperative

Cooperative support in singleplayer levels is quite often an afterthought. Rarely played thanks to the poor IP performance of Netquake and by being left out in the cold by Quakeworld's competitive focus, and thus rarely considered by mappers building for singleplayer beyond placing four coop spawnpoints behind the player start and adding "Cooperative: Yes" to the readme. This is a shame, since reasoning about how differently a level can play when the player can be in more than one place at once can add a fun and rewarding extra dimension to the 'design puzzle' a mapper might discover within their map as it unfolds.

Spawnflags

All entities support the additional Quoth spawnflags for COOPONLY (4096) and NOTINCOOP (8192). These only examine the status of the coop cvar, so they can still be tested with one player. This allows you to make small coop adjustments, like to ensure players don't get trapped outside sealed arenas, or to completely reconfigure a level's progression and combat.

Trenchbroom should display these flags automatically, but NetRadiant might have trouble with this.

Adjusting for Player Count

The new spawnflags provide a way to react to coop status at map load, but this can be ineffective for tuning difficulty since it treats all coop games the same, regardless of the actual number of players. If you're willing to take on the testing challenge of so many permutations of the same map, Copper provides a few mechanisms to make per-player-count adjustment possible.

While unused spawnflags above 8192 certainly exist, using them to filter entities by player count isn't possible, since like all spawnflags, these would evaluate at map load before any clients connect. Therefore, player count reactivity has to be evaluated during gameplay, and since clients can technically join or leave at any time this is really the only method that's feasible.

A new entity, target_playercount, can be used to selectively trigger entities based on the number of players in game at the moment it's triggered. This acts like a trigger_relay, but is the only entity that treats the four target keyvalues separately: the keyvalue which corresponds to the number of players connected is the one fired. For example, in a 3-player game, only target3 is fired, and the other targets are ignored. The LT_EQUAL spawnflag will change this behavior to fire all target keyvalues up to the current player count. In that case, in a 3-player game, the entity would fire target, target2, and target3, disregarding only target4.

Be cautious when using target_playercount to trigger-spawn monsters. Monsters which aren't activated by a target_playercount because the number of clients isn't right will still exist unspawned. This is a problem because they will have added themselves to the total killcount anyway, unless their 'count' is -1 (see Monster Spawning), making it impossible for players to get 100% kills and potentially leaving them to wander your level in frustration looking for monsters that will never appear.

Other entities can be configured to react to player count on their own. Any entity with its count keyvalue set to the magic value -4 will make it adopt the number of players as its count when first triggered. This provides a great shorthand method for making trigger-spawned monsters or respawning items repeat themselves once for each player, as a lazy but effective way of saying "here, have more of these" without diverging too much from the singleplayer design.

When a monster with count -4 is detected at map start when the coop cvar isn't set, it defaults to 1 immediately rather than waiting until triggered, so the kill count doesn't change during gameplay when it doesn't have to.

Count -4 scaling is limited to prevent things becoming too unpredictable/insane when playing with what we'll call a "novel" number of players. The count increases by one each for the first 4 players, one for every other player above 4, and for every fourth player above 12, reaching a hard cap of 10 at 20 players. We may not be able to make Quake's gameplay work with 100 clients, but at least we can keep the server from dying.

Impulses 80 and 81 will add and remove dummy extra players for manipulating the current client count, to solo test entity setups using the above features without having to gather a bunch of warm bodies. A nonsolid player model will appear at the level start for each one spawned, to serve as a visual placeholder.

Triggers

The standard behavior for trigger_multiple is to disable itself for its wait period after evaluating a single touch. This is all that's needed with one player or for triggers that cause one-time world events like doors opening. It can be a problem in cooperative mode if, for example, you wish to create a healing pool with a trigger that fires a target_heal at intervals. If more than one player stands in the pool (ie touches the trigger) at the same time, the first client to evaluate in a hostframe will activate the heal and then the trigger will go to sleep, skipping the additional players each and every time. The ALL_CLIENTS spawnflag has been added to trigger_multiple and trigger_multiple_box to make them respond to every player standing in them per active frame instead of just the first client before going dormant.

Staggered Starts

Coop player starts can be marked as disabled with the TRIGGER_FIRST spawnflag, and no coop player will spawn there until it's been triggered. This allows the mapper to move the coop starts forward as the players make progress, so a respawning player doesn't have to trek all the way back from the start to get back to the action. The old set of coop starts can simply be nuked with a killtarget at the same time a new set in a more convenient spot is activated. As many coop spawn point groups as your map needs can be placed and activated in staggered fashion this way.

With the five second respawn delay added to cooperative mode, shortening the return trip at regular intervals thoughtfully avoids making players suffer a double penalty for dying.

Moving start points forward in waves works in most cases, but if you require more complexity, coop starts can also be disabled and reenabled with a target_lock.

Items

Spawning

All items support respawning natively without use of the SUB_Regen hack (although this still works, for compatibility with maps that used it). Simply set a wait keyvalue on an item to make it reappear after that many seconds. It will respawn indefinitely, but it can be limited to a certain number of respawns by setting count.

Items can also be inhibited from spawning until triggered. This is automatic, and only requires giving the item a targetname. Entities which cannot fire targets are safe to target items with, such as lights using items as spotlight destinations.

Rotating

Any items that don't already spin in place (ie ammo, health) can be safely rotated using the angle key. They will always stay visually centered within their bounding boxes wherever you placed them. Nothing else is required to make this work.

Items that are rotated very diagonally were found to 'feel' smaller than normal due to the tilted corners sticking out of their bounding boxes, allowing players to get closer to the visual representation of the items than usual before touching them. Angled items therefore have their bounds puffed outwards slightly to include most of the axially larger item. This is done after item floor placement and has not been observed to cause items to be too sensitive to nearby brushwork.

Floating

All items have a SUSPENDED spawnflag to skip the droptofloor test when they spawn, forcing them to remain exactly where they're placed in the source map. This can be used to create items that hover in midair, but it's also a useful hackaround for items that insist on falling out of the world and vanishing because they don't like where you placed them. This also provides a handy solution to the irritating problem that a monster and an item cannot overlap without pushing the item out of the world.

Even if items don't fall out of the world when you test your map in your Quake engine port of choice, inconsistent droptofloor() results are not unheard of across ports. Consider it best practice to always mark as SUSPENDED any progression-critical items like keys, or any other item that fires a necessary targetname, even when placed on the ground.

A suspended item can be caused to fall by activating a target_drop that targets the item. A target_drop is on the 'invalid triggerer' list, so it can target an item without inducing delayed-spawn behavior.

Armor

Here is some helpful reference for how much damage you can expect a player to withstand when wearing each type of armor, assuming a player with 100 health grabs an armor, then takes enough continuous damage to lose all 100 HP without grabbing any health items:

item_backpack

A small ammo reward for those little hideaways that aren't really full secrets. Comes in two flavors.

Backpacks

Exact amounts of shells and nails are chosen at spawn time, so players can't regressively minmax by quicksaving before touching every backpack.

Specifying custom amounts of ammo is not supported, so that players always receive what they expect to when grabbing it (and thus can make informed choices about wasting ammo like they can with normal ammo boxes). Note that there is a spillover mechanic in Copper, where ammo that would be wasted is converted into armor points (from these backpacks only, making them special), so that the player's informed choice is not about wasting ammo so much as managing a tradeoff between more ammo and more HP.

item_sigil

Each of the four end-of-episode runes sets a single bit in the serverflags variable when acquired, which is continuous across a game of Quake (this is how the game tracks episode completion.) There are up to 18 more bits unused, however, and an item_sigil can be made to set any of them with the svflags keyvalue. It can also have its model, pickup sound, and pickup message overridden, to turn a 'rune' into whatever macguffin you want.

You can then use a target_items to test for this flag before firing triggers, to act as a crude inventory system, or use the now-more-highly-configurable (func_episodegate across level transitions.

Yes, 22 is a strange number of bits if you're at all used to programming. Quake stores this value as floating point (yep), and above 2^23, imprecision grows larger than 1 and starts to eat the low bits.

target_items

This entity is a catch-all device for interacting with the player's inventory. By default, when triggered it will give a player that activates it whatever items and goods it's specified to (ranging from ammo, health, and armor to weapons and items and even arbitrary serverflags - see the in-editor documentation for exact keyvalues). Several spawnflags enable alternate functionality.

If the TAKE flag is set, it will attempt to subtract all specified amounts instead of adding them. If all items can be successfully taken, this entity will fire its targets; if not, it will print its message at the player if it has one. Use this to create an elder god that demands the player sacrifice their rocket launcher before proceeding, or anything else you can think of.

If OVERRIDE is set, the activator's inventory is overwritten rather than added to or subtracted from. Use this to drain the player of shells at map start, give yourself better starting gear to test continuous play in an episode with estimated starting inventory, or force a shotgun start instead.

The FLASH flag is there to make the screen blink as if the player had picked up an item when his inventory is altered by this entity. You might want this to be stealthy, or you might not.

If TEST is set, it behaves as TAKE above but doesn't actually remove the inventory. Maybe that elder god just wants to make sure you're prepared. Setting both TEST and TAKE acts as a not operator on the test: targets will be fired if the player's inventory fails the test, and any message will print if it passes. This makes it behave as a trigger_relay predicated on whether or not the player has a certain item or an amount of a certain resource.

One of many very useful applications of target_items: in TEST mode, it can be used to make any trigger ignore invisible players.

Important safety tip: think carefully about how you want your items test to work in Coop. Does every player have to pass the test? Or any? Will the setup break with multiple players if the trigger isn't set to ALL_CLIENTS?

Utilities

Targets

There are a number of other triggerable point entities, some of which have effects which formerly required volume triggers:

trigger_monsterjump

Monsterjump triggers are now highly configurable and can be made very selective about when to launch a monster and when not to. New spawnflags:

If that's not specific enough, the include and exclude keyvalues can be used to selectively add or remove a monster by classname or targetname from jump candidacy.

trigger_hurt

Hurt triggers can have their damage and frequency customized with dmg and delay, for infrequent pulses that hurt real bad or a slow steady drain.

In vanilla Quake, tiny damages would always round to armor when the armor strength was yellow or red, stripping it away too fast, and always round to health when green, defeating the purpose of armor. This was very apparent with a trigger_hurt set to do 1 damage many times a second. Copper fixes this by randomly applying the last fractional point of any damage to either armor or health to remain statistically balanced.

The vanilla bug that caused all but one player to be immune to a trigger_hurt if more than one player was touching it at a time has also been fixed.

Two spawnflags have been added that add a lot of gameplay potential: trigger_hurts can be set to ignore monsters (subjecting players to movement limitations the baddies can ignore) and to ignore players wearing a biosuit (allowing you to make the biosuit useful against any number of new environmental hazards you might create).

trigger_push

Push triggers can be set to act more like gusty wind or flowing water than an inescapable wind tunnel with the ADD_VEL spawnflag. This will add the trigger's push velocity to the player's velocity, rather than override it, allowing them to retain control and push against the current. Since this could cause the player to endlessly accelerate up to ludicrous speed, the impulse can be limited to a maximum velocity with the speed2 key. Note that ADD_VEL will not cancel out gravity like a normal trigger_push, unless it pushes vertically at least as strong as gravity (the default is 800), and can be counted on to behave differently depending on whether the player's feet are touching the ground and causing friction.

The default whooshing-wind sound can be overriden with a .wav of your choice by specifying noise.

ADD_VEL with a reasonable speed limit, and a rushing water noise, is ideal for water currents.

If you are creating a wind tunnel, you're probably used to how difficult it is to get entrances or corners to behave without catching the corner of the player's refrigerator-sized bounding box on your brushwork. The TUNNEL spawnflag makes this a lot easier by pulling the player towards the center of the trigger in the direction of motion, eliminating almost all snags.

If you get lost in the pitch/yaw/mangle/angles values like I do, you'll appreciate that push triggers will aim themselves at their target, if they have one.

info_teleport_target

When this entity is triggered, it acts as if the activator just touched a teleport trigger, with this entity as its destination. Thus a trigger_multiple targeting one of these behaves the same as a trigger_teleport targeting a teleport destination (the trigger won't emit the teleport whisper sound, however). This is not what makes them useful; there may be times when you want to teleport the player or monster to a certain spot, as part of some gameplay contrivance or a scripted sequence, regardless of where they're coming from. If it's not convenient or feasible to blanket the entire area in a teleport trigger, using this as the destination and triggering it via any other means will solve your problem.

This allows neat new things like shootable buttons that teleport you to them, or anything else you can think of (that you can illustrate to the player sensibly, of course).

Teleport targets have the added benefit that they can be locked with a target_lock, allowing a trigger_multiple to serve as a teleporter with a switchable destination. Multiple teleport triggers could be stacked in one place and selectively locked instead, but the former method is a bit cleaner.

What if you don't want to teleport a player? Teleport targets can be used to simplify the trigger volume out of monster teleports too, by setting the ACT_ON_TARGETS spawnflag, which will let you directly specify the entity to be teleported with a targetname. (Targeting more than one monster will make them telefrag each other. This might be what you want.)

target_heal

Heals its activator for healamount when triggered, up to an optional lifetime limit of count hit points. Use for healing pools, first aid dispensers, etc.

If it has any targets, it heals them instead. This applies to anything with health: monsters, buttons, secret doors, exploboxes, you name it. This will not reset 'dead' doors/buttons with a wait of -1, or bring anything else back from the dead.

This was used to create the reinforced meatwall in the UDOB Shub level - it was implemented as a shootable func_button being constantly healed by a target_heal at a rate that only quad damage weapons could overtake.

While it's a bit against the spirit of classic Quake and that of Copper, target_heal has a "smart" mode (enabled with the AUTO_AMOUNT spawnflag) that can react to the amount of health the player needs and decide on its lifetime limit on first use, as a means of dynamically wishing more hit points into your level for players who are getting their asses kicked versus for those who aren't in dire need of medkits. See the in-editor documentation for exact use.

target_autosave

This is an optional little helper for the player. When triggered, all it does is save the current game in auto.sav, notifying the activator of this with a print in the corner of the screen (just like quicksaving). Players have to load it manually, however, so in the event they haven't quicksaved they do have to remember to try 'load auto' - it's not perfect but it's better than nothing, and it's easy to implement. Just make sure you trigger it when it's unlikely the player could be a half second from death ...

An attempt to make the last autosave load on death led to uncovering a frustrating set of impossibilities. Within the walls of progs.dat, it just can't be done reliably without bad edge cases - namely, it's impossible to know if the auto.sav on disk is actually from the current playthrough or even the current map.

A bigger problem is that demo recording and playback is ruined because the 'load auto' command is recorded into the demo. For the recording player, this stops the recording (unless your engine is special) where the normal restart-on-death functionality wouldn't. For the player watching the demo, the autoload in the demo causes that person's auto.sav to suddenly load. Not good.

Or, you can play Quake with Ironwail.

Versioning

All entities support the version keyvalue. Entities with this key will not spawn if the player is running a version of Copper that is at least equal to the value set (ie, "1.16"). This enables you to shut players out of the level with a func_wall sealing the start room, or print a helpful message encouraging players to upgrade Copper with a trigger_multiple, which will only appear when players load the map in older versions of the mod (or the wrong mod entirely, including vanilla id1) and therefore not waste all our time reporting non-bugs caused by using old versions with new maps.

This was implemented in version 1.16, because hindsight is 20/20, and therefore specifying the version number of any earlier Copper release will not have the intended effect. (You should be targeting the latest release anyway.)

Movers and Solids

Many movers now support a variety of ways to set movement angle and direction. The distance keyvalue works for all movers, so the guesswork of figuring out the right lip for angled doors and buttons can be skipped.

Many also support setting their A and B positions directly using the pos1 and pos2 keyvalues. Movers can translate along any arbitrary non-planar vector, plats can be made that drop when stepped on rather than rise, and so on. Bearing in mind that these coordinates are local, and that the position where a mover is constructed is always [0 0 0], more effects can be achieved by setting both pos1 and pos2, causing the mover to be lit where it is built but move between two other positions. With careful calculation of offsets, movers that are problematic to light can be built and lit in the position with most ideal lighting (including in special purpose boxes outside the map), and shifted into position at spawn time.

If either pos1 or pos2 are set, the other will default to [0 0 0]. Use of pos1 and pos2 will override angle and distance. distance likewise always overrides 'lip'.

You may override noise through noise4 on func_ entities that otherwise require you to choose from the hard-coded menu of sound sets, enabling the use of any sound (including new wav files you create and include with your map) for any event that makes noise. This is exploited in UDOB, for example, to make secret doors emit that characteristic clockwork trundling sound even when they aren't implemented using an actual func_door_secret classname, or to disguise func_trains with complex path logic as simple doors or plats with non-simple movement patterns.

A number of func entities have an equivalent func_*_point entity, allowing you to specify an external .bsp file to use via the model keyvalue.

As of version 1.30, nearly every func_ entity has a START_INVISIBLE spawnflag, to require it to be triggered into existence before behaving normally.

func_bobbing

Moves back and forth along a line following a sine wave, similar to the entities of the same name in Arcane Dimensions and Quake3. Does not require or utilize a speed value; specify wait for the total period of the sine and either angle and distance or pos1 and pos2 to determine the track, and the correct speed will be determined per frame.

Triggering a func_bobbing will freeze it in place or reactivate it, but they have keyvalues for directing the entity to keep moving to the high, low, or center position before stopping. Will deal its damage (if any) once and reverse motion if blocked, but the CRUSHER spawnflag will change this behavior to deal damage every frame without reversing.

In cases where it's important where a bobber stops when toggled, three spawnflags for HIGH, LOW, and CENTER will make the mover wait until it has reached any of the specified positions on its travel. For example, checking only 'Center' will cause the bobber to stop at its midpoint, coming from either direction. Checking both 'High' and 'Low' will cause it to come to a stop at whichever endpoint it reaches first after being toggled.

func_door

Aside from all the general additions above, doors support a handful of specific new things:

func_train

Trains are more dynamic now, and can be used for more than simple endless loops.

Upon arriving at a path_corner with a wait value of -1 (meaning stop forever), the train will revert to waiting until triggered, allowing you to start and stop trains in multiple locations, even at every pathcorner if you desire. Trains with a pausetime value will use that as their default wait period at any pathcorners that do not specify a wait. This defaults to 0.1 seconds to match vanilla, but can be set to -1 to make a train move continuously without pausing (except at path_corners that do specify a wait). Trains can also be made to stop immediately wherever they are when triggered with the TOGGLE spawnflag. They will resume their motion if triggered again.

Trains fire all of a path_corner's targets upon arrival. (If a path_corner's only target is the next path_corner, nothing happens.) If you want a train to always cause doors in its path to open for it, for example, this is the way to go, since having the player ride through a trigger doesn't work if the player has fallen off. This is important for making events relative to the movement of a train responsive to potential starts and stops.

Upon arriving at a path_corner with a nonzero speed value set, it will inherit that speed and forget its own. Besides variable speeds along a path, this can also be used to make the same train move at different speeds on different skill levels by having it pass through a skill-specific path_corner. This could be automatic but unfortunately requires setting the PATH_SPEED spawnflag, due to some path_corners in the original episodes with stale speed values that will break progression if inherited automatically.

When leaving a path_corner, trains search the map for the first path_corner with a targetname matching the prior path_corner's target, followed by target2, target3, and target4, stopping in place if none is found. It will otherwise always accept the first path_corner it finds, even if more than one path_corner would be a match if it kept searching. This means a train's looping path can be branched or altered by means such as removing a path_corner via killtargeting, or selectively disabling it with a target_lock.

func_trains with a health value can be shot or damaged to trigger them. When they're in a state where they can't be triggered (ie in motion), they won't bleed when hit. This interacts with the Toggle spawnflag.

func_flytrain

A flytrain is controlled in exactly the same way as a func_train, with the same keyvalues on itself and on path_corners doing the same jobs, with a key difference: it drifts gently around, orbiting the point where a comparable func_train would be located, rather than moving linearly from corner to corner. When waiting at a path_corner, it will drift gently in place, hugging the path_corner at a short distance. This distance can be controlled by setting width to the horizontal distance (x/y) and height to the vertical distance (z) you want as the outer limit. Setting both of these keys to -1 will eliminate all drifty motion, in which case you've made a func_train with extra steps.

Flytrains are implemented under the hood as a pair of entities: one hidden func_train doing its normal thing, and the visible flytrain that shadows its position at all times, with a little bit of lag so the motion always appears smooth.

When inheriting a speed from a path_corner, it will smoothly accelerate or decelerate on its way to the corner rather than immediately changing speeds on arrival. It also uses the center of the func as its origin, and not the minimum corner like a normal train, making it easier to visualize the path it will take in the editor.

Curving Trains

As of version 1.30, trains and flytrains support smooth curved motion via a spawnflag on path_corners labeled BEZIER. This will cause a train on this path to treat this corner as the control point for a Bezier curve formed by the corners before and after it in the chain. Each curved segment of the path does not know about the path before and after it, so it can still be bookended by hard corners (and usually will be if you don't line up subsequent curve points right).

If a train inherits speed from its path_corners, and the two endpoints have different 'speed' keys, the train will smoothly accelerate as it follows the curve. Flytrains do this automatically.

Everything set on the path_corner marked 'Bezier' is ignored, however. Its location is only used to define the curve, so the train will technically not pass through this corner. None of its targets are fired, its 'speed' key is ignored if it has one, and you can't make the train stop halfway along the curve by putting a 'wait' key on it. (The solution you're looking for there is "two curves".)

Only one control point is supported between endpoints. The Bezier flag is ignored on the path_corner that follows the control point, so placing multiple Bezier path_corners in a row between endpoints will not make a higher degree Bezier curve. (Since all 3rd degree and higher curves can be expressed as multiple 2nd degree curves, the solution you're looking for there is "two curves".)

func_plat

A plat can have its activation zone overridden manually by targeting it at a trigger_once or trigger_multiple (which is then absorbed and ceases to function as a regular trigger). This is useful for plats with unusual (ie not axis-aligned rectangular) shapes, when a trigger generated from the bounds of the plat sticks out too far.

func_explobox

Copper doesn't support full breakables, but misc_explobox has been generalized into a func entity, allowing you to create exploding brushmodels of any size and appearance. Their health and damage are customizable, they can be set off by triggering, and they fire their targets when they blow. Pairs well with target_debris.

func_wall

Walls can be toggled on or off by triggering them. This can toggle either +0/+a texture state (like on button faces) or outright hide/reveal the entire brushmodel, toggling both visibility and solidity.

func_void

A func_void simulates an infinite abyss like a bottomless pit or the bottom of a space map. Comes with Quoth trigger_void levels of utility plus Honey's pit-death levels of polish, including a nice scream, an even better meaty splat, and integrated "punishment teleporter" alternate functionality.

Your func_void should be a solid brush covering the bottom of your death pit, ideally textured with sky or solid black. This brush will be nonsolid in-game, and serves to hide all the dead scrags and fiend heads that can collect at the bottom of a pit or skybox. It also hides any lightmapped surface you have to put down there to ensure your Scrags are lit.

It also generates a trigger of the same dimensions height units above it, which is necessary for initiating the fade-to-black and triggering the scream effect when the player starts falling in. This trigger height must be set high enough above the bottom for a decent fade time, but not so high that it's possible for the player to touch it without having gone irretrievably over the edge (meaning, ensure it's below any walkable space).

When a client touches this trigger, their fall begins. The func_void's targets will be fired when a player touches this trigger. When they touch the solid at the bottom, their view will have fully faded out, and their entity is removed. They don't receive the red flash and the splat noise until a few moments later (the interval can be specified with delay), which makes the pit feel deeper than it really is, so you don't have to drag the brushes down too far.

Living monsters that get flung into the pit will disappear on contact with the bottom, rather than spraying gibs and blood back up out of the pit. They still count as killed for all purposes, including firing their targets.

If you don't want to kill players outright for taking one wrong step, the func_void can also be targeted at an info_teleport_destination. Players will take dmg damage when they "hit bottom" and if they survive that will be teleported to this spot instead.

The color to fade to defaults to black, but can be overridden to anything by setting fadecolor. Matching the level's fog or the average color of the bottom of your skybox looks nice.

As of version 1.30, should you need a void to exist conditionally (such as the boss pillar in Dwell 2, which you ascend from the bottom but then cannot fall off of), hitting it with a target_lock will show/hide the solid base and enable/disable the fall trigger.

func_episodegate

The two start map gate entities, which selectively do or do not appear depending on the player's rune selection at spawn, have received a small but powerful addition: they fire any targets they have at map start if they are not inhibited by the player having the wrong runes. This can be exploited to alter triggers and scripting in your start map, beyond just turning walls on and off. (target_items can be used to similar effect.)

Episodegates are highly configurable with the svflags keyvalue to respond to any combination of serverflags, not just the first four (ie the episode runes). They can be made to spawn or not spawn if the player has any one rune (or serverflag set), any of several, or all of several.

This means an episodegate can be made to, for example, always spawn unless the player has all four runes - in other words, function as a func_bossgate.

Dynamic Lighting

Several brush entities provide automated control of lightmap channels by setting their style key. Any lights with a matching style will be manipulated in brightness based on the behavior of the entity. In general, use lights with this style to provide the illumination you would get when the brush entity would not block light, and the entity will darken the light on its own when it would.

Other brush entities, such as func_plats and func_trains, have too broad a range of motion to encode light and shadow information in static lightmaps (doors are already pushing it) and are not supported.

As always with light style manipulation, choose an integer that won't collide with any other lights' styles, including triggered lights. If the above general-case shortcuts do not support your specific needs, use a target_lightstyle for direct lightmap channel control.

What if you want the light to fade the opposite way? A quick shortcut for that: make the style a negative number, and it will use the corresponding positive one with inverted behavior.

Switchable shadows from ericw-light are supported on all of the above entities and will behave the same way, either separately or in combination with your own light channels. Adding the appropriate compiler keys is all that is necessary (but good lighting doesn't hurt). A target_lightstyle that targets a brush entity with these switchable shadows will operate on the lightmap channel containing the switched shadow data, should you need more control.

Control Flow

The expansion of the target keyvalue to support target2/3/4 values has been included from Quoth, AD, progs_dump, and others. Any entity that uses a target - either the usual trigger firing or a special case - will check all four keyvalues, and they can be safely considered equivalent for all purposes.

The targetname keyvalue has not been similarly expanded. The combinatorial problem of searching for matching targets grows from 4 searches to 16 when this is done, raising the potential of game-crashing progs stack overflows or loop timeouts in huge maps. Four targets cuts down the trigger_relay spaghetti significantly, but four targetnames on top of that suffers diminished returns not worth the added code complexity and performance cost.

Nearly everything can be accomplished cleanly with four targets, and the rare cases that can't, can be with one or two extra trigger_relays.

Triggers

All triggers have a TRIGGER_FIRST spawnflag, enabling them to spawn unusable and be activated at a later time by themselves being triggered. Reversible toggling can be accomplished with a target_lock.

A reminder: delayed trigger functionality with the delay keyvalue, despite being documented only as a feature of trigger_relay, actually took place in vanilla Quake within UseTargets(), so any entity that fires a target (buttons, doors, dying monsters, and so on) can do so with a delay without requiring an intervening relay.

Many triggers have accompanying trigger_*_box point variants, to save on brushmodels if you're near the limit (or just for keeping your maps tidy). Place the point entity in the center of where you want the trigger's volume, and set size to the full x, y, and z size you want the bounds of the trigger to be. (Before version 1.30 the mangle key was used for this purpose, for some reason. It still works for backwards compatibility.)

Alt Target Pattern

Entities which fire targets always do so when spurred by one specific event: a monster when it dies, a door when it begins opening, a button when it finishes pressing.

As of version 1.30, some entities support an optional alternate pattern of target events. By setting ther ALT_TARGET spawnflag (one higher than the Coop spawnflags), they will fire their target/2/3/4 targets each at different times depending on class.

Monsters will fire target when awakened/angered, target2 the first time they take damage from any source, target3 when their health drops below 50%, and target4 on death. The last three are reliable: if you oneshot a grunt with a rocket, for example, each of target2/3/4 will fire at once, in that order (because the grunt has taken damage, dropped below half health, and died). Each of these targets is also fired only once: if a monster drops below half health, then is healed by something, target3 will not be fired a second time when it drops below that threshold again.

Want a simple way to do the "monster teleports behind you when it wakes up" trick? Set the monster to use the alternate target pattern, and point its target at an info_teleport_target. (Maybe set 'delay' to a little above 0 to give the player time to notice the monster.)

Three entities have a very similar pattern of behavior: func_button, func_door, and func_plat. Each will fire target when its movement begins, target2 when that first movement ends and the wait begins, target3 when its return motion starts, and target4 when return motion completes and the mover has returned to its rest position. This can be very useful for ensuring that the state of entities triggered by the mover (like buttons at the top and bottom of an elevator) remain synchronized with it even if a door is blocked or a player remains standing on a plat. target_state is also capable of this kind of introspection, but requires some external trigger to cause it to check on its buddy.

An important interaction: when a target_lock locks a door or a button, they move to the closed position automatically. When a locked button does this, it will never fire any of its four targets. When a locked door does this, however, it will reliably fire all four, in case you have special sound/light effects tied to the movement of the door that you don't want falling out of sync. This decision was made out of concern for the idea that a button's entire purpose is to fire targets, and locking it is intended to prevent that, while the purpose of a door is simply to bar passage, and its targets are usually secondary.

A func_train using the alternate target pattern will use target to select the starting pathcorner, but will fire target2 every time it arrives at a path_corner, target3 every time it departs from a path_corner, and target4 when it runs out of path_corners and terminates.

target_lock

This is a very powerful entity that selectively enables and disables many other entities. A target_lock will set a LOCKED flag on all entities it targets when triggered. The exact effect is specific to the entity being locked, but a good rule of thumb is to consider a locked entity inert and disabled. (Compare to the Arcane Dimensions ESTATE system.)

A great deal of complex things can be accomplished this way:

Locking and unlocking is never permanent, and any lockable entity can be unlocked and locked again any number of times. A target_lock can be set to toggle the locked status of its targets each time it's triggered, always lock them, or always unlock them. If the wait or rand keys are set, this entity will automatically undo itself (regardless of being set to 'always lock' or 'always unlock') after a pause of between 'wait' and 'wait + rand' seconds.

If there's a way to accomplish something without a target_lock that's more clear to the player, it's probably the right way to do it. A button behind bars makes a lot more sense to the player than a mysteriously dead button that just doesn't respond to being touched. Or, consider the existing form language of a wind tunnel blocked with an octagonal plug door before locking the trigger_push itself.

target_state

This entity can hold an integer variable, similar to a counter, and alters that variable when triggered. Defaults to cycling between 0 and 1, but setting count will make it cycle through all integers up to the given maximum before looping back to 0. Set state to the desired starting value.

If the RELAY spawnflag is set, things get interesting. This will make it act as a trigger_relay when fired rather than storing its own variable. It will compare its own (static) state value to that of the entity with a targetname matching this entity's include keyvalue, and only fire targets if these two values match. The included entity can be another target_state holding a value, but a number of other entities already use the state field to store their present condition:

This enables you to allow or block any trigger event based on the state of a number of entities that are otherwise unreliable or impossible to synchronize. Timing something to match the movement of doors and plats can't be done rigidly when either can be unpredictably blocked by players or monsters and reverse their course, for instance. With a target_state, your map's scripting can react to these entities directly.

The elevator at the beginning of the UDOB Start map, for instance, has triggers at the top and bottom that fire target_states checking the position of the elevator, which trigger the elevator only if it isn't at that floor, creating an automatic return system that summons the elevator to the player's level when they approach.

Combining target_lock and target_state can yield extremely powerful programming possibilities, leading to map scripting that is highly dynamic and reactive to player actions while remaining difficult for a player to break.

trigger_relay

Relays support a few new things in Copper. They can make noise when triggered, either by setting sounds to something from the same menu as triggers, or by specifying any wav file with the noise keyvalue. Any relay can serve as a sound emitter, even if it doesn't fire any targets of its own.

The RANDOM spawnflag will cause the relay to randomly select one entity that it targets to trigger each time it is used. The selection is made from all entities across all four target keyvalues, and is recalculated on each use so it's resilient to targets being removed or destroyed. (If the relay only has one target, this naturally has no effect.)

Relays support the count keyvalue to limit the number of times they can be used. They remove themselves permanently when their count is exhausted.

trigger_timer

Similar to the Quake2 entity of the same name, a timer just fires its targets on its own once every wait seconds. Can be limited with count. Set rand to add a random extra delay to the wait interval. Can be triggered to enable and disable it.

Fog

Copper includes smoothly blending fog functionality similar to Honey & Arcane Dimensions. The fog control mechanics are designed around making the map appear to be divided into separate zones with different local fog. Thinking of your fog triggers as the boundaries between zones will help you conceptualize how to use them well.

To begin with, fog values (the fog_color and fog_density keyvalues) can be set on every player start, teleport destination, and intermission camera, so any way that a player might enter a fog zone without passing through a trigger can still set their fog to the desired local values. Unless you're just using one global fog for your whole map, set appropriate fog values on all of these entities. (Creative license can be taken with intermission cameras, since they're one-way.)

An important thing to remember: the fog keyvalue that goes on Worldspawn doesn't interact with this system. It is a feature of various engines (such as those in the Fitzquake family) and isn't interpreted by game code. The reason for this is that it's interpreted as four values (one for density and three for color) and set by the engine at load time. The numeric fields that are passed on to the game code (ie Copper), however, can only be one value (a float) or three (a vector). If you set fog in your world with a fog parameter on worldspawn, and never bother with fog_color and fog_density on any entities, you'll get the usual static global fog the way it's always worked. Color and density on a player start will be evaluated on the first frame of gameplay, and will override any fog set by the engine.

As of version 1.20, the amount that fog affects the sky can also be changed and blended with the fog_sky keyvalue on all the same entities.

Fog blends are achieved by issuing a dozen or more 'stuffcmd' calls, 24 times per second. This is probably fine!

A bug in most Quake engine ports will reset the eye position smoothing that happens when climbing stairs or riding a plat on every frame that a 'stuffcmd' is sent, so fog transitions during upwards motion will cause noticeable stuttering. There is unfortunately nothing that can be done within Copper to fix this.

target_fogblend

To fire a one-time smooth fog transition, have any entity trigger one of these. The activating client will see their fog blend from the values specified in the keyvalues for fog_color/fog_density to those in fog_color2/fog_density2, over speed seconds. Triggering this again will cause them to transition back again over the same length of time (unless speed2 is set, in which case the reverse blend will take that much time instead).

The GLOBAL spawnflag will cause this to happen for all clients, not just the activator. Care should be taken that the fog values being blended from are the values clients are already set to, or they'll see their fog snap to the start values before blending to the final values.

trigger_fogblend

Putting a trigger that fires a target_fogblend at either end of a hallway or transitional space does a decent job of separating fog zones, but they have to transition fast enough that a player can't race back and forth between them and cause one transition to cut off the other. Doing this also results in players only getting a fog transition when they reach the end of the hall, meaning they see a new area with the old fog suddenly blend into new fog.

A trigger_fogblend solves this by acting as a smoothly transitioning fog portal. Any client touching it will have their fog set to a smooth interpolation between fog_color/fog_density and fog_color2/fog_density2 proportional to their position within the trigger. As they move from one end to the other, their fog is adjusted between the two extremes so that when they exit on either side, their fog has already fully transitioned to the appropriate values. This hides the transition in the middle of the hall where it won't stand out, and with careful adjustment you can make the fog blend almost invisibly.

The axis of motion on which the blend happens is defined by angle, pointing to whatever zone has color2 and density2. The distance is taken from the size of the trigger on that angle, so the full range of the trigger's volume is used for the transition. This distance can be overridden by setting distance if you don't think Copper is getting it right (which is possible for diagonal transitions).

Care should be taken that a player arriving at a fogblend already has their fog set to the values the fogblend will transition them away from on that side, or they'll see their fog snap to the fogblend trigger's values the moment they touch it.

Effects

While these aren't strictly gameplay-focused, and fall under the category of 'thematic sugar' mentioned above, they had already been implemented for other reasons in the less strictly gameplay-focused mod that Copper's codebase evolved from, so in Copper they remain. There wasn't much reason to cut them other than maintaining ideological purity, and while these pages are honest about Copper's development goals, it isn't that prescriptive.

Explosions and Gibs

Several entities are provided for activating point-based special effects at their origins when triggered.

All four support the same configuration options.

Version 1.30 added a solid-based counterpart to meat fireworks named target_debris, for blowing chunks of your map around. The speed, mangle, and size keys all work the same way, but this entity doesn't support repeated emission like the other four, since the use case for debris is usually throwing it out of an explosion. Instead, count will scale the number of chunks tossed at once. A set of one-size-fits-most debris models are included, with three sizes (selectable by setting frame) and eight textures (selectable by setting skin), but you can override your own with the model, model2, and model3 keys. (If you do, frame and skin will be passed along to all spawned debris.)

target_lightstyle

Quake uses lightstyles for both flickering/animated lights and lights that can be triggered on and off. In vanilla, this means the two effects cannot be used in tandem. target_lightstyle gives the mapper direct control over the pattern of any of the 64 lightstyles when triggered. Styles 1-31 are the preset lightstyles, and 32-64 are assigned by the compiler to triggered lights, and both can be overridden. Set style to the lightstyle you want to override, and set message to the brightness pattern you want to set it to. If style is not set, and this entity targets any triggerable lights, it sets the brightness pattern of those lights when triggered instead. (Note that targeting anything at a light makes it a triggerable light with its own style automatically.) This is compatible with any Quake map compiler, because light.exe only cares about the style number - the pattern is only applied in-game.

Setting style to -1 will override the style of all static, unstyled lights in the level (style 0).

Multiple additional stylestrings can be specified in order using the noise and noise1-noise4 keyvalues. The target_lightstyle will cycle to the next unused one each time it is triggered.

Quake's light patterns are sequences of characters where each letter represents a brightness from 0-200% lasting 0.1 seconds, allowing long animations to be packed into an editable string. a represents total darkness, m is normal brightness, and z is double brightness. For example, the painful disco strobe in the Fiend-filled corridor in E3M5, The Wind Tunnels, is "mamamamamama". Implementing a standard on/off toggle would use a message of "a" and a noise of "m" or "z".

Some brush entities which could be expected to block light provide shorthand behavior for affecting a light style based on their physical state. See Dynamic Lighting for more.

target_fade

Smoothly blends the alpha of targeted entities between two values. The default mode is to blend from alpha to alpha2 over speed seconds when triggered, then blend back if triggered a second time (exactly like a target_fogblend).

If set to By Distance mode with the appropriate spawnflag, alpha will instead be proportional to the activating player's distance from the target_fade, blending from an initial alpha when triggered from outside the range of distance units to alpha2 when within lip units. This requires repeat triggering, so fire it from a trigger_multiple encompassing the relevant area and a short wait time. (This will make it behave almost exactly like a trigger_fogblend.) angle can be set on the target_fade to constrain the distance check to measuring the player's position along a line rather than in space.

If a target_fade has a style key, or targets any triggered lights, it will smoothly(ish) blend the brightness of those lights exactly as it would alpha on a visible entity. What's more, target_fade interacts with the automatic dynamic lighting of walls and doors, so fading a func_wall with a switchable cast shadow will fade the shadow away as well.

This is a very neat tool for implementing things like In The Shadows-style fading cubby secrets, or quietly hiding fake volumetric light brushes when the player approaches to keep the view from clipping through the plane.

While effort was taken to make this play nice with as much existing behavior as possible, the alpha-blink effect of an item or func_explobox about to respawn will clash with target_fade's attempts to change its alpha. Also, remember that alpha is not private to each client in a coop game, so what fades for one will fade for all.

misc_fireball

Now expanded with configurable launch speed, damage, direction (with mangle and movedir), and interval (with wait and rand). Can be turned on and off with a trigger, or be made to emit a lavaball on demand with the BURST spawnflag.

The lavaballs can also, with the appropriately named EXPLODE spawnflag set on the emitter, be made to explode on contact like rockets. The dmg keyvalue still applies - your two best options are either 40 to match an Ogre grenade, or 120 to match a rocket or a Ch'thon ball, for consistent gamefeel with the rest of Quake.

misc_particlefield

Emits quakedots within its bounds. It can sprinkle them continuously, toggled on and off by triggering, or it can dump all its particles at once with the BURST spawnflag. Color, quantity, and velocity are all configurable as well; see the in-editor documentation for exact use. Useful for forcefields, the bases of waterfalls, or lending a little bit of magic to important map features. Has an accompanying misc_particlefield_box.

Specifying a velocity will cause a wave of particles to sweep through the bounds of the field instead (moving at the specified velocity), to reproduce the typical forcefield effect from other maps and mods. This can be combined with BURST to cause one wave only when triggered.

If a particlefield has a target, it will center the effect on that target rather than itself. Make a Shambler sparkle.

If you're exceeding Quake's particle limit of 2048, you can restrict a particlefield from generating dots with the distance keyvalue. Particles will not be generated unless at least one player is within that distance.

target_screenshake

Shakes the screen when triggered. Jostles the view of all clients, but doesn't physically move their bounding boxes or apply velocities. Set its intensity with strength. 1 is a hearty rumble, 10 is spasmodic bordering on hilarious.

Follows an attack-sustain-release curve: it builds for delay seconds, holds at full strength for length seconds, then fades back toward zero for wait seconds. Total quake duration is therefore delay + length + wait. All three have defaults, but any of them can be forced to 0 by setting them to -1. (You might want a quake with no delay to be caused by a sudden blast, for example.)

Environment

misc_model

For .mdl decorations like the obligatory dead ranger bodies. Specify with model, orient with mangle (remember: pitch, yaw, then roll), and select a frame and skin if necessary. For a randomly rotated prop on the cheap, set ideal_yaw to 1.

If a single frame isn't enough, the pos1 keyvalue can be used to specify an animation range: the format is [firstframe startframe lastframe] (and don't forget frame numbers are 0-ordinal). A second animation range can be specified the same way with pos2, and the misc_model will swap between them when triggered.

Wronged in a bad way dude

If your models aren't animating the way you expect, double-check that your frame numbers aren't off by 1. Also verify with your model editor of choice if the animation you're looking for is actually a framegroup and not a sequence of individual frames, in which case specifying only one frame should be enough.

ambient_sound

A generic ambient sound entity that supports custom sounds, similar to ambient_generic in other mods. Provides control of volume and attenuation range (within Quake engine limits). Otherwise self-explanatory. Is always on and cannot be toggled (which is a Quake engine limitation Copper cannot fix.)

target_sound

A triggerable audio emitter, with configurable volume and attenuation just like its ambient cousin. Specify any wav file you want with the noise keyvalue.

If a target_sound has a target, it will play its sounds on that entity rather than at its own location. It can also be made to play its sound on the activating player instead of from its own location with the ON_PLAYER flag.

This entity is overloaded to play up to five sounds. Specify additional wav files with noise1-4, and the entity will cycle through them in order upon successive triggerings. The SHUFFLE spawnflag will cause it to shuffle the list instead (never playing the same sound twice in a row.) Like many others, this entity can self destruct after a limited number of triggers with the count key

With a little custom sound design, a trigger_timer causing a target_sound to cycle through a few similar noises makes a robust replacement for continuous ambient sound that can be turned on and off.