-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcopper_v1_20.txt
996 lines (805 loc) · 93.5 KB
/
copper_v1_20.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
================================================================================
COPPER
a single-player refinement mod
for id software's QUAKE
http://www.lunaran.com/copper/
File : copper_v1_20.zip
Version : 1.20
Date : November 27th, 2022
Author : Matthew "Lunaran" Breit
Email : [email protected]
Website : http://www.lunaran.com/
================================================================================
ABOUT COPPER
============
We all like Quake, but if we're being honest, its gameplay isn't as tight as it could be. By the end of its development in 1996, id were burned out and just wanted to ship something and take a break (something I came to understand quite a bit as a game developer), and a hurried Doom clone sewn together from dark fantasy was what we got. Over the years since, several high-profile single-player mods have sought to expand Quake's breadth, perceiving problems in its design as gaps that need to be filled and new content as the solution. I wanted to instead polish Quake's existing gameplay the way id might have if they'd taken the time to do so, to improve its depth and clarity as much as possible before considering what could be built on its foundation.
Copper is therefore meant to be "Vanilla+", targeted at being a drop-in improvement to stock /id1/ gameplay and an equally suitable basis for new mods. It neither adds nor replaces any items, weapons, or monsters. It is not intended to be a kitchen-sink supermod like Quoth or Arcane Dimensions, nor move Quake towards some new 'vision' other than what it already is (or, at best, is trying to be).
A summary, if you'd like to just get the broad strokes and go play:
- Weapons fire is not blocked by monsters in death animations
- Ring of Shadows makes enemies less accurate in combat
- Vore missiles have a less-than-perfect turn rate
- Ogres are 'partially' Z-aware
- Zombie edge cases are fixed
- Nightmare skill is 50 max HP instead of turret-monsters
- Cooperative limits respawns and makes death dangerous
INSTALLATION
============
Unzip the contents of the zip file into your /quake/ directory, so that the /copper/ folder is alongside, not in, the /id1/ folder. If you already have a previous version of Copper installed, go ahead and overwrite everything.
Start your favorite Quake engine port with '-game copper' appended to the command line. Fitzquake-derived engines such as Quakespasm or MarkV are recommended, but any flavor of GLQuake should do. Play with GL_NEAREST texture filtering, like the dark elders intended.
Please note: running the game with a different -game prefix, or none, and changing the mod to Copper via the console in such engines that support this may lead to unwanted config state being carried over from other mods, leading to potentially unpredictable results. Bite the bullet and make a new shortcut. (Especially before reporting bugs.)
Start a new game and play through any (or all!) of the original episodes, the additional new episode Underdark Overbright, or try out any custom Quake single player map that doesn't require another mod. Retry old favorites!
CHANGE LOG
==========
1.20: November 27th, 2022
- Added Quake2-style armor stacking/accumulation, ONLY in cases where players have more points of
a weaker armor type than what they're trying to pick up (players can amass 200+ green armor from
backpacks or playing ctsj2_mazu and be locked out of picking up better armor, and it seems unfair
to just lose the excess) (thx mazu/fw)
- Weapons
- Fixed nailgun aim angle not quite matching the crosshair (thx jugador/luigio)
- Fixed being able to fire the thunderbolt while falling into a func_void
- Fixed crash when using weaponcycle (impulse 10/12) after subtracting weapons with target_items
- Moved axe attack trace to eye height
- Monsters
- Fixed anemic fiend leap aggression - fiends feel unhinged and crazy again \o/
- Added a little random motion to vorepods (not enough to affect dodging them), so a large group
of pursuing pods don't converge into a single unquantifiable burr
- Fixed vorepods not switching to bad homing if the vore died by func_void
- Fixed rotfish not nibbling on a player treading water with eyes above the surface (thx 4LT)
- Fixed hell knights and fiends entering zombie state if they happen to die to liquid while in
their charging states (thx fw/mazu)
- Fixed not-yet-triggered monsters being removed when 'developer' is 1 but not 0 (sry fw)
- Fixed decorative crucified monster_zombie being removed in deathmatch/nomonsters
- Fixed trigger-spawned scrags disappearing if they had a "wait" or "rand" spawn delay and were
sufficiently low above a func_void
- Fixed monsters rarely still being telefragged by a spawner with "no telefrag" set
- Fixed targets that require a player as activator sometimes not firing when monsters that fire
them are killed during infighting
- Fixed coop-only crash when a monster would teleport on top of a player
- Triggers
- Added "Tunnel" spawnflag to trigger_push, which sucks players towards the center of the trigger
in the direction of travel while pushing them, so they don't get hung up on bends and corners
in wind tunnels
- 'mangle' key on box triggers and particlefields changed to 'size' because that actually makes
sense ('mangle' still supported for backwards compatibility, just no longer documented)
- 'distance' key on triggers (for specifying tolerance on facing angle) now supports degrees
instead of apparently arcane math concepts (-1 to 1 values still work in older maps)
- 'count' key on triggers once and multiple works like on relays
- monsterjump's 'include' and 'exclude' keys now work on both classname and targetname
- monsterjumps will no longer jump a patrolling monster with no enemy if the "Only if Enemy In
Front" or "Only if Enemy Below" flags are set
- 'sounds -1' will specifically mute the default doot-doot sound that still plays if printing
a message from a trigger that would otherwise be silent (thx Esrael)
- Fixed 'no touch' spawnflag on trigger_secret (will now just spawn as a target_secret instead)
- monster_boss
- Improved telefraggability of shootable Chthons
- Fixed shootable Chthons not firing targets on death (sry zigi)
- Fixed shootable Chthons crashing to console instead of infighting (sry colossus)
- Fixed entity-hack shootable Chthons going docile after being shot (jam6_scampie bug) (thx 'enry)
- monster_oldone
- Killing a Shub now ends the map by default again regardless of being in end.bsp (sm77)
- Shubs not ending the map on death is now opt-in with a spawnflag
- Fixed classic teleporttrain sometimes hanging up on geometry (sm77_rpg bug) (thx markie)
- Fixed idiot monsters spawning a frame after shub dies and photobombing the end scene
- Fixed backpack clutter not being removed in end scene
- Doors and movers
- Generally cleaned up linked door behavior, now sensible and predictable
- Added 'toggle' spawnflag to func_trains to start and stop their motion at any time
- Fixed triggering func_trains while in motion causing them to skip corners (thx 4LT)
- Fixed off-by-one movement error on func_doors_secret that use path_corners (thx ptoing)
- Fixed func_bobbing starting too early and screwing up monsters/items placed on them (thx fw)
- Fixed timing of func_bobbing slowly wandering over time
- Added flags to func_bobbing to make them continue to a low, center, or high position before
stopping
- Fixed texture state inverting on func_doors that were triggered too rapidly (thx fw)
- Fixed target_lock interaction with targeted doors (thx porglezomp)
- Fixed movers with solid -1 phantom-touching things (ctsj2_fw lightning 'pushing' bodies bug)
- Fixed touching doors with different targetnames getting linked anyway (COMPACT.bsp bars bug)
- Effects
- Added spawnflags to target_explosion and func_explobox for tarbaby and weak-to-shambler-puff
blast styles
- Added support to target_explosion and target_telefog for random offset
- Added support to air_bubbles for burst emission and random offset
- Fixed activator not counting as attacker when activating target_explosion (thx Esrael)
- Fixed ogre and vore projectiles not doing the weak puff style explosion when hitting Shamblers
despite still doing half damage
- Sigils and func_episodegate
- Episodegates now support the same .svflags field as item_sigils, and interoperate with them
- Added 'reverse' option to episodegates, to create a bmodel that disappears when the player has
the matching rune
- Support multiple runes on episodegates, which can be configured to require the player have or
not have any or all of multiple runes
- Fixed objerror on an item_sigil when using svflags instead of one of the EP* spawnflags
- Candles
- Unsynchronized and randomized their flickering
- Reversed flame normals to look nonsolid
- Sprinkled a few more polygons for roundness
- Added lavender scented version
- Fixed groups of triggerable candles sometimes toggling incompletely
- Fog
- Added support for setting and blending the skyfog cvar through fog entities
- Added support for both 0-1 and 0-255 format on fog colors
- info_teleport_target
- Added 'act on targets' spawnflag, to teleslam a dozen shamblers into one spot the easy way
- Fixed 'trigger first' spawnflag not working
- Fixed not firing its own targets when triggered (thx fw)
- Developer cheats
- impulse 100 (invoke) defaults to .use if there's no special case function
- Removed impulse 100 eprint spam
- Fixed impulse 66 (exterminate) missing trigger-spawned monsters between triggering and spawning
- Fixed impulse 104 (serverflags) printing that all of Quake was complete if you had any rune
- Fixed armor hud icon breaking after using 'give A' cheat in Fitzquake/Quakespasm for red or
yellow armor, then taking damage
- Items
- Key carry limit raised from 15 to 16
- Rerandomize the ammo amounts from backpacks if they respawn
- Fixed backpacks respawning with corrupt amounts if any ammo was converted to armor
- Fixed killing the player with target_items not letting them restart (thx mazu)
- Raised respawn particle effect on hovering items to hover height
- Tried to improve powerup and water sounds cutting off related sounds (thx zungryware)
- Added deathmatch 3 (thx porglezomp)
- Fixed visibility toggle on misc_model again (thx bal)
- Fixed respawning with carryover velocity from your last death in multiplayer (thx mazu)
- Fixed toggleable func_walls crashing very large maps, hopefully (sry mazu)
- Big pass on most .fgd definitions, adding longer and more useful descriptions (and colors)
- Fixed appearflags missing from func_bobbing in .fgd (thx echo)
- Changed "Help" in the main menu to "Copper Info" (stfu fw ok)
- Removed 'private backpacks in coop' from help screen 6
1.19: July 1, 2022
- Reverted private backpacks in coop - it just created mystery untouchable backpacks for friends, and trips
down dead ends for you to parts of the level that might already be clear
- Fixed Shamblers not firing lightning as aggressively as vanilla (thx Zungryware/Mazu)
- Fixed late-spawned suspended backpacks appearing at the wrong height (thx bal)
- Fixed precache errors caused by late-spawn notnull "use" hacks on all item classnames (thx plaw)
- Fixed key pickup print not calling it the Runekey or Keycard in worldtype 1 and 2 maps (thx fw)
- Changed target_multiprint to send to players even if activated by a monster
- Added func_plat, func_train, and func_flytrain to dev invoke cheat
- Added support for non-solid trains ("solid" "-1")
- Added support to func_door_secret for using path_corners to define the movements
- trap_shooter and trap_spikeshooter
- Added "Aim At Activator" spawnflag to shooters to match trap_lightning
- Fixed ogre grenade shooter launch speed, supports 'speed' key for override
- Fixed shooters tracking brush entities incorrectly, now matches trap_lightning
- Tweaked pixel art on the 6 Help pages by sven "ptoing" ruthner
- Changed "Help/Ordering" in the main menu to just "Help" (stfu fw ok)
1.18: November 15, 2021
- Gibbed Grunts and Ogres now drop the same ammo they do when killed regularly
- Added base-specific non-key locked door clunk sound, switched by worldspawn worldtype
- Restored monster_hell_knight being called 'Death Knight' in def/fgd/obituary messages
- Vore projectiles no longer vanish when their target enemy dies
- Added customizable intermission text to changelevel triggers, so you don't require a custom progs.dat to bore
the player with your end-of-episode lore dump. Limited to 1 page of text.
- Added 'distance' key to misc_particlefield to skip emitting particles if players are too far away
- Liquids
- Fixed taking fall damage landing in knee-high water introduced in 1.16
- Fixed taking fall damage landing in knee-high slime or lava from vanilla, for consistency
- Fixed diving sounds overriding the slime hiss and lava ... blurp? on entering those liquids
- Fixed recovering health you didn't lose when drowning with a pentagram
- Fixed being able to gib a player hard enough to blast their head through solid geo into the void
- Undid code that fixed coop centerprint in KEXQuake, because the centerprint format was itself reverted in
'major update 1'
- Fixed 'version' requirement key on entities having the opposite sign - as of 1.18 this feature actually works
as intended hooray
- Flytrains
- fixed func_flytrain never working properly unless you built it at the origin
- fixed all flytrains acting wierd if they start exactly on their first pathcorner
- Fixed visibility not toggling on triggered misc_model
1.17: August 25, 2021
- The 'KEXQuake' Update - append "in the rerelease engine" to all of the following:
- Fixed crash on level transition
- Fixed axe vanishing randomly when using the enhanced models
- Fixed wonky Vore shrinking to a point whilst walking (the solution is omitting Seven's shalrath.mdl with
added idle animation - a better fix involves new md5anims that won't happen very quickly)
- Included mapdb.json for selecting UDOB maps from the menu (you do have UDOB, don't you?)
- The next update to KEXQuake will probaly fix the coop centerprint warning when another player dies
- Added 'impulse 210' to disable autosaves on a per-map basis since they're perma-broken and take forever
- Already-very-close grenade and rocket contact damage unified so that grenades aren't slightly weaker when
shooting ogres in their extreme bounding box corners (thx fw/Markie)
- Limited how 'count -4' scales with coop player count
- Count increases by one for the first four players, for every second player above 4, and every fourth
player above 12
- Hard-capped at 10 above 20 players
- Only tested "theoretically", so we'll see how this works in 2046 when decino has a 1000-player coop
stream for Quake's 50th birthday probably
- Water
- Added sound cues when the viewpoint dips below water, one for sinking and one for splashing
- Splashing into water hard enough spawns bubbles
- Fixed bubbles sometimes floating up into new contents
- target_sound
- Added "count" flag to auto self destruct after limited uses
- Added flag to play the sound on the activating player (to make the sound follow them)
- trigger_fogblend
- Will limit spamming of stuffcmd() to only those frames where it would change the fog significantly
enough to be noticeable, to be friendlier to whatever is harmed by spamming stuffcmd()
- Fixed riding a mover through a fog trigger not snapping to the final fog values
- Mostly fixed rare occasions when leaving a fog trigger on foot does not snap to final values either
- Func_trains and func_flytrains leaving a path_corner with a 'speed' of -1 will teleport to the next corner,
then behave normally from there
- Improved the subtlety of target_screenshake with low (<0.5) strengths
- Spawning fixes
- Fixed coop telefrag protection counting player bodies and heads as players (thx spike)
- Fixed running out of spawn points in very popular Copper Deathmatch (thx solipsist)
- Fixed info_player_start_test not actually being used
- Zombies
- Zombies with both the 'lying' and 'triggered' spawnflags no longer telefrag other monsters on spawn
- Fixed zombies navigating to their old enemy's corpse if they were killed while the zombie was knocked down
- Fixed secret doors throwing precache warnings when "sounds" is set to -1
- Fixed trap_lightning not tracking its target unless set to "oneshot"
- Fixed trigger-spawned scrags and fish dropping to floor on spawn if they had a "wait" or "rand" spawn delay
- Fixed impulse-100-invoked key doors still playing the locked clank noise on touch
1.16: June 21, 2021
- SSG fire rate had been set in experimentation to 0.75 seconds in tweaking years ago and it accidentally
snuck through - reverted to vanilla rate of 0.7 (good eye aDaya)
- Enabling god mode after dying will resurrect the player in place, for lazy playtesting
- 'netname' on a trigger-spawned monster will be converted to the targetname on the spawned monster after
triggering, so monsters can be spawned and awakened with two separate trigger events without resorting to
a telebox
- Added 'style' key to several brush entities for paired light toggles/fades
- on func_wall: toggling visibility will toggle their light styles
- on func_bossgate and func_episodegate: light style will be switched on if the gates do not spawn
- on func_door: shadows will fade across the motion of the door as it opens and closes. doesn't look that
great, and is prone to breakage if you make the doors too 'interesting' (several linked doors with
different speeds). respects the 'start open' spawnflag and creatures blocking the door.
- on func_door_secret: will behave as func_door above during the *second* move
- using ericw-light switchable shadows on the above entities works as well, even in combination
- a target_lightstyle targeting an entity with a switched shadow will act on the shadow's lightstyle. use
this if the above pre-packaged solutions do not support your wild and crazy vision.
- please read the ericw-light documentation (https://ericwa.github.io/ericw-tools/doc/light.html) on how
switchable shadows are implemented to understand that this is a narrow and fragile feature
- trigger_counter
- Added 'eager reset' spawnflag to reset its count if not retriggered quickly enough
- Fixed custom completion messages being silenced by the 'nomessage' spawnflag, which should only
mute the countdown
- Added 'version' key to all entities to inhibit spawning on a minimum version of Copper, to gate access
to the level and fix users reporting bugs in old versions
- Fixed multiple sight sounds playing when a lying zombie is aggroed for the first time
- Fixed idle sound cutting off the sight sound on several monsters
- Fixed noclipping out of a func_void instantly turning noclip off and dropping you back in
- Fixed func_plats with overridden trigger volumes failing if the trigger doesn't spawn before the plat (thx
Juzley)
- Fixed target_lightstyle crashing when it can't find any targets instead of printing a sensible message
- Fixed screenshake resetting the view angle of intermission cameras
- 'testplayerstart' renamed to 'info_player_start_test' to be more OCD-compliant
- Renamed tasteless 'genocide' cheat code to 'exterminate'
- light_candle
- Randomly sized/oriented candles remain consistent across plays and reloads
- Fixed candles confusing their models with other models after loading a savegame if you aren't lunaran
(thx Zothique)
- Fixed candle with targetname destroying items later in the spawn order (!) (thx Markie)
- fgd & def
- Fixed 'volume' description missing from ambient sounds in .def file and 'distance' selection missing
from .fgd file - both work on all ambient sounds and always have
- Fixed oversized bounds on light_candle
- Added model/frame/skin 3d preview support to misc_model
- Fixed every instance of 'wait' requiring an integer and not a decimal
1.15: November 20, 2020
- Armor
- Reverted degrading armor changes: strong flavors no longer degrade to weak ones
- Protection percentages for yellow and red reduced from 60/80 to 50/70
- The cutoff amounts where a stronger armor can be replaced with a greater amount of a weaker one are
rounded to whole multiples of ten (100 for Y>R, 60 for G>Y, 40 for G>R)
- Ring of Shadows
- Backed off 1.1 change making invisible players entirely non-solid to ranged attacks
- Ranged attacks against invisible players are now tested against a target half as wide as a player
- Monsters
- Reverted spawns having all-around vision when idle
- Added "impulse 200" for listing all unkilled monsters and undepleted monster spawners left in the level
- Monster spawners can now have built in pre-spawn delay using 'wait' and 'rand' keyvalues
- Triggered monsters with a movedir will jump on spawn regardless of whether or not they wake up angry
(static monsters with a movedir will still jump only on awakening)
- Added 'rmovedir' for setting a monster's jump velocity relative to its facing angle
- Many keyvalues for monster hacks now properly transferred by monster spawners to spawnees: alpha, skin,
items, armortype, armorvalue, invincible_finished, invisible_finished, super_damage_finished,
radsuit_finished, and gravity (see mon_spawner_use() in monsters.qc for complete list)
- Effort has been made to keep monster-kill-based map scripting functioning when "nomonsters" is set to 1,
but it is still by no means foolproof - consider nomonsters a semi-supported tourist mode
- Exaggerated the vertical spread on Hell Knight spray a tiny bit, to increase the chance that one of the
bolts can be jumped over at middle range
- Crammed the most salient parts of the gameplay changelist into six new help screen images
- Adopted Arcane Dimensions' method of illustrating Shambler blast resistance with a weaker grey explosion
- Quake won't switch to an explosive weapon on pickup when invisible, since you can't see the viewmodel
- The Thunderbolt's beam spreads at a wider angle when arcing between two enemies who are at least waist-deep
in water or slime
- Added trap_lightning for shooting various kinds of lightning in various directions
- Added Ogre grenade option to trap_shooter/trap_spikeshooter
- Added light_candle to shut markie up
- Added a spawnflag to target_items that will divide the 'health' keyvalue by 2 on Skill 3
- func_door_secret can finally be set to move at speeds other than 50
- target_sound now supports up to five .wavs, which can be cycled or shuffled
- func_void now finds a salvation teleport spot the moment it's needed, not at map start, so spots can be
switched with target_lock
- func_void properly cleans up all of its triggers and parts if killtargeted
- misc_particlefield
- Added optional sweep effect, for base forcefield or metmon walkway effects
- Added control over timing interval
- Fixes to target_lock behavior
- toggle doors stay in whatever position they're in when locked, rather than always 'closing'
- fixed toggle doors targeted by both a target_lock and something else still being approach-activated
- shootable doors cannot be harmed when locked
- shootable buttons cannot be harmed when locked
- locking a button depresses it and makes it non-interactive, but its friends still support it
- QSS handholding
- Fixed flashes of monsters wildly lerping across the level when spawners are triggered
- Fixed player gasping at the start of every level
- Fixed Quad axe not gibbing zombies (thx fairweather/Markie)
- Fixed the respawn lockout misbehaving after a client disconnects while dead
- Fixed monster_oldone not dying when too many trigger events are stacked in one frame
- Fixed monsters waking up when triggered by a noclip or notarget player (consistency with instawake-spawning)
- Fixed func_doors that mix triggering and health still being shootable while moving after being triggered
- Fixed movers like func_door playing their move sound forever if killtargeted while in motion
- Fixed func_trains not checking target2/3/4 for valid unlocked pathcorners (thx Juzley)
- Fixed not being able to trigger a func_train to start moving early from a pathcorner with a positive wait
- Fixed a func_train that would run off the end of its path and despawn disappearing one path_corner early
- Fixed threshold for an "only below" monsterjump being +16 units and not -16 (thx 4LT)
- Fixed func_wall erasing its .alpha when toggled (thx Pinchy)
- Custom 'noise' fields on func_button and func_door_secret now precached correctly if the 'sounds' key
doesn't override them
- Monsters that trigger-spawn or activate another monster via a monsters-only trigger now bestow their
enemy to it (thx TheSolipsist)
- Fixed a shootable (ie with health) trigger-first trigger getting the wrong solid type on reactivation (thx
TheSolipsist)
- Fixed target_state debug print happening outside developer mode (thx TheSolipsist)
- Fixed target_heal ignoring monsters who didn't have a max_health field (because now they all do)
- Fixed grenades resting on a large shootable brush entity not doing damage to it when they explode
- Keys and runes will defensively auto-suspend if they would fall out of the world at map start and despawn
- copper.fgd
- fixed target_sound missing the targetname key
- removed 'mangle' from trap_shooter/trap_spikeshooter
- added 'dmg' to func_void
- fixed description of 'mangle' on trigger push implying it was a vector and not rotations
- added 'testplayerstart'
- added a sky & fog fields to worldspawn
- etc
1.11: July 15, 2020
- Additions
- Autosaves are now signaled by a subtle sound since lunaran doesn't notice autosaves happen in maps other
than his own
- monster_boss now has a 'shootable' spawnflag, for BeyondBelief/Koohoo-style damage sponge Chthons
- target_lightstyle can cycle multiple styles (set using additional noise-noise4 keyvalues)
- A func_explobox with 'health -1' cannot be harmed and will only explode if triggered
- The undocumented Nightmare-only quick-refire behavior on Ogres and Grunts has been disabled for
philosophical reasons
- Bugfixes
- Players will fall into a func_void for the same length of time regardless of whether they will be killed
or teleported to the salvation spot
- Health and ammo pickup sounds no longer cut each other off
- Angled items no longer shrink to points when too close to walls
- Fixed monsters sometimes firing in crazy vertical directions when their target is invisible
- Fixed more cases that would sometimes cause monsters to shoot behind them
- Fixed monsters choosing not to fire up or down at targets with large height differences (thx PoolboyQ)
- Threshold for an "only below" monsterjump changed from 0 units to -16 (step height)
- 'wait -1' on trigger_monsterjump now works as expected (thx McClone)
- 'delay -1' on trigger_hurt properly sets the frequency to 0 (ie framerate-dependent as fast as possible)
- Fixed trigger_hurt ALWAYS hurting monsters regardless of the NO_MONSTERS spawnflag (thx grome)
- Fixed monsters not being hurt by a trigger_hurt if they aren't moving around in it (thx grome)
- Stepping off a func_plat after it reaches top will not shorten the delay to less than 'wait' seconds
after it reached top (thx fairweather)
- copper.fgd
- Added func_detail_fence
- Reference to the health item models no longer broken
- Certain entities no longer missing difficulty spawnflags
- Fixed func_bobbing missing the 'angle' key
- misc other things i didn't note, there will always be something wrong with this goddamn file
1.1: June 20, 2020
- Cooperative
- An improved coop mode that makes death and resources more meaningful:
- Every player death triggers a 5-second respawn lockout. If all players are dead at the same time, it's
game over: no one can respawn and the level restarts.
- Killed players respawn with only starting health and ammo, but keep their weapons
- Weapons vanish on pickup, but are immediately granted (with ammo) to all players
- The Megahealth heals all other players to full when grabbed (100 E/N/H, 50 NM)
- Backpacks dropped when players die cannot be picked up by teammates
- Vanilla coop can still be played with 'coop 2'
- Monsters no longer fixate on one player at a time, and will seamlessly attack the most convenient player if
not infighting. An attack that triggers a pain animation will also now pull aggro for a while.
- Players will be pushed off a teleport destination or spawn point if they're about to be telefragged
- Func_plats don't leave right away if another player is near to give them a chance to hop on
- Friendly fire is always disabled with 'teamplay' regardless of team or pants color
- Player backpacks do not expire in coop
- Set 'timelimit N' to allow N seconds between the first player exiting and the level actually ending
- Frag count shows monster kills instead of how many of your friends you've murdered
- Added 'target_playercount' for selectively triggering entities based on number of players
- Setting an entity's 'count' keyvalue to -4 will make it use the number of players as its count
- Trigger_multiples have an 'all clients' spawnflag to make them respond to every player standing in them per
active frame instead of just the first client, for activator-specific targets like target_heal
- Gameplay
- Ranged attacks will now pass directly through a player with the Ring of Shadows without doing harm, but
melee attacks do full damage once again. Don't get cornered.
- Enemies confused by the Ring will now misfire by a wider margin
- The Thunderbolt beam now leaps from one enemy to another in a more or less straight line, doing diminishing
damage to each additional enemy, up to three times
- Fixed the strange 'three beams' bug that causes lightning attacks to be invisibly duplicated elsewhere in
the level with an unpredictable offset. (Speedrunners will have to find another way to kill the Vores
through that wall in E2M6.)
- Shambler lightning now stops at the entity it hurts rather than continuing harmlessly through to world
- Fiends are better at aiming their leap at enemies that aren't level with them, and are now threatening from
more effective angles
- Adjusted Perforator spread and movetype to stay effective at close to mid ranges but better fall behind
the Nailgun at mid to long range
- Voreball homing turn rate raised from 224 degrees/second to 270. Still dodgeable, more threatening, easier
to lead into other enemies, but harder to ignore.
- Voreballs now home in on an invisible player just as tightly as a visible one
- All explosions strong enough to gib nearby standing zombies will properly find and gib downed zombies too
(Chthon lavaballs, exploding spawns, exploboxen), not just a player's GL/RL
- Monsters lower than their targets will shift their aim from the center of their target toward the top, to
try and clear the ledge the target is standing on more effectively
- Holding +jump while underwater propels the player upward at the same speed as holding +moveup
- Grunts deal full damage to each other again
- Assets
- Converted health/ammo items from .bsp to .mdl so they're lit by the environment like weapons and powerups
- Included seven's shalrath.mdl with added idle animation
- Fixed texture alignment on Shambler lightning bolt, replaced MSPaint-scribble skin with proper texture
- Mapping
- Monsters set to 'no telefrag' that fail to spawn do not need to be retriggered now, and will try again on
their own every half second
- trigger_push
- can have its default sound overridden, for water currents or etc
- ADD_VELOCITY mode is no longer framerate dependent
- ADD_VELOCITY can limit the player's maximum speed so it doesn't keep accelerating you to infinity
- pushes gibs now
- Added target_lightstyle: sets any style to any string at any time. Much less limited than the crummy
'oldstyle' system.
- trigger_inventory deprecated, since the same functionality is better accomplished with a target_items and
an ALL_CLIENTS trigger. the trigger_inventory spawnfunction will now create the above setup for backwards
compatibility and print a warning in developer mode.
- Added CRUSHER spawnflag to func_door
- Added misc_particlefield for a trigger brush-based version of misc_particlefield_box
- Added trigger_once_box
- Added 'mangle' keyvalue to target_meat_fireworks. still defaults to up if left blank.
- Added 'rand' keyvalue to target_explosion/telefog/meat for randomly staggering them
- Added support to target_state for < > <= >= comparisons
- Moved checks for untargeted trigger-spawned monsters to "developer 1" mode only, to reduce pressure on
SUB_VerifyTriggerable
- Removed KILL_LAST trigger_relay spawnflag from copper.def/fgd (was never implemented, flag did nothing)
- Removed CHANGE_SKIN func_door spawnflag as well (was default behavior, flag did nothing)
- fixes in copper.fgd:
- delay not showing up on all entities with targets
- renamed incorrect 'teleport fog' spawnflag on monsters to 'no teleport fog'
- trigger_secret_box was duplicate target_secret
- func_explobox was brush class named misc_explobox2
- func_flytrain was point class
- target_setskill was duplicate pointclass named trigger_setskill
- target_changelevel was named trigger_changelevel
- targets/targetname/angle not showing up on func_button or path_corner
- targets/targetname being valid properties of trigger_hurt, trigger_monsterjump, trigger_push, and
misc_meat_fireworks
- removed unhelpful direct pastes of the 'nmmonmnomasdfjketc' light style strings
- Bugs
- Hacked info_nulls that call barrel_explode no longer explode at the origin, and can be triggered more than
once to match vanilla again
- Fixed trigger_multiple/trigger_once/func_wall notnull maphacks causing disallowed-precache errors; sound and
model precaches are now wrapped in a guard function in many places to prevent a late precache from killing
the server
- Fixed 'players only' on target_heal causing it to heal nobody
- Eyeballs no longer visible when two players are looking through the same intermission camera
- Fixed keys being duped in coop when dying while holding some
- Suiciding at the console in coop now properly transfers keys to other players
- Fixed gnarly coop-only bug that caused zombies that spawn lying down to skip the standing animation and be
nonsolid and invincible forever (searching for new targets when they shouldn't)
- Fixed telefragging another player leaving behind a standing ghost
- Fixed nailgun not respecting 'sv_aim' (supernailgun left alone)
- Firing the supernailgun with only 1 nail left will not fire the lesser nailgun if the player doesn't have
one - likewise for the super shotgun (vanilla bug)
- Fixed grunts not lagging their shots if their target is standing still on a moving brushmodel (vanilla bug)
- Bounds and origin of Rotfish adjusted vertically by 8 units to help them get stuck less (thx ijed)
- Fixed trains firing their pathcorner targets not setting an activator; will use whatever player is touching
the train at that moment, and default to player 1 if none are
- Fixed monsters turning east when stopping at the last pathcorner if the corner specifies no angle
- Fixed view not fading to the fadecolor if your dead body or head gib falls into a func_void after you die
- Made func_void plunge triggers 64 units thicker on z by default to make it harder to clear the whole thing in
one hostframe if already falling very fast
- Fixed func_void with a custom deathtype string not deducting a frag from players who fall in
- -1 converts to 0 for func_void 'lip' and 'delay'
- Fixed -1 not universally signalling 0 for the 'dmg' keyvalue (a func_void with a 'dmg' of -1 no longer gives
the player +1 HP)
- Fixed being able to immediately fire a weapon after picking one up or switching due to being out of ammo,
regardless of firing rate of previous weapon
- Fixed -1 not converting to 0 for 'distance' on doors and buttons
- Fixed delay, deathtype, and message not being copied to triggered monsters from their original
- Fixed sigils overriding custom .message (zendar/bakstein start rune)
- Fixed missing 'spikeshooter_use' function (1000cuts crash)
- Bubbles now disappear when crossing any two content types, not when outside water, to emulate weird vanilla
behavior again (1000cuts health pool bubbs)
- Changed trigger message print behavior back to id1, ie fire targets and print messages both after 'delay'
(jumbled/failed message prints in dm456sp)
- Fixed monsters that were supposed to spawn on doors sometimes being stuck embedded slightly in them
(dm456sp ogre platform over the nailgun)
- func_doors with noise1/noise2 override sounds set now use them regardless of the 'sounds' value (dm456sp red
plumber's tie prop making a clunking noise)
- Fixed teleporting a monster to a misc_teleporttrain screwing up the train's path and triggering the train's
targets (SMEJ fix)
- Fixed misc_teleporttrain starting at its second pathcorner instead of its first (SMEJ fix)
- Fixed trap_spikeshooter still being stupid with delay (spawning spikes at the origin, not firing with the
right timing, etc)
- Fixed brushwork func_explobox simply never appearing
- Fixed misc_models with pos1 animations but no targetname sometimes refusing to animate
- Fixed multiple linked key doors still playing the locked noise on touch after being opened
- Fixed a trigger_relay with RANDOM not respecting its 'target2', 'target3', or 'target4'
- Fixed trigger_hurt never hurting monsters regardless of the NO_MONSTERS spawnflag
- Fixed a target_items that changes your current weapon's ammo not updating the hud until you swap weapons
- Fixed dog pain animation always being instantly resettable (vanilla bug)
- Fixed ogre idle sound sometimes immediately canceling its wakeup bark (vanilla bug)
1.05: Jul 16, 2019
- Enforcer laser damage reduced from 15 to 12, to help compensate for their more aggressive firing pattern
- PAK0.PAK renamed to pak0.pak to play nice with case-sensitive operating systems
- Shamblers no longer fire lightning at cockeyed angles when their target is invisible
- Downed zombies who've had doors or crushers invade their personal space no longer become non-solid (id1 bug)
- Projectiles no longer have a random chance of nullifying a Fiend's leap in midair (id1 bug)
- The land-on-head protection delay of Fiends, Dogs, and Spawns will no longer cause them to fail to damage a
player on impact if they've just glanced off of something else
- False positives related to the Ring of Shadows in monster attack checks fixed, so monsters always infer the
player's presence from his real origin while always trying to attack his fake one
- Weapon pickups fire their targets the first time they're touched in Coop, then forget them, so maps which
fire important triggers from weapon pickups aren't broken if everyone already has the weapon
- Chthon should be less likely to instantly snipe the player when they teleport the moment a lavaball is thrown
- Quad axe no longer corrupts monster flags or sends Shub flying (thanks to Ian 'iw' Walshaw for these fixes)
- func_trains now require a spawnflag to inherit speed from their pathcorners, and the keyvalue for setting
default corner wait time has changed from 'wait' to 'pausetime' to avoid conflicts with stale 'wait' keys
on various id and custom maps (e3m3, e4m5, k1m3) (thanks again to iw for running interference on this
issue and patching all my mistakes)
- Added a developer warning when a trigger spawned monster can't be triggered by anything (more thanks to iw)
- Player can now jump while standing in the same depth of water as /id1 (iw again)
- Door wait times are no longer set improperly in the -1 case (E3M7 zombie pit platform) (iw)
- Intentionally prevented use of boss_death10 killcount hack, as it was only ever used to balance the rotfish
killcount bug, which was already fixed (iw)
- Trigger_relay no longer objerror()s if not targeted (is a warning in Fitz+ but an error in stock engines,
which caused them to crash e1m5 & e1m6) (iw)
- Items which are targeted and killtargeted by the same entity no longer fail to spawn (E4M2 'fake' items) (iw)
- Fixed some monsters (Enforcers, Scrags) being able to see and attack the player while in water, caused
by arcane conditional failures in engine trace behavior. is this the last bug in traceline2? only the
shadow knows ... (found by iw)
- Spikeshooters that are triggered more frequently than their 'delay' no longer fail to ever fire (iw)
- Changed late monster/secret stat updates to MSG_ALL (iw)
- Monsters do their drop to floor test late enough to be properly positioned on movers that don't start at
their zero point, important if the movers start in lava/slime (iw for president)
- Fixed runaway loop error in bbin1 caused by item spawn code (iw is now my husband)
- Biosuit lava protection max depth changed to 16 units (used to be 24, which seemed too deep, and the above
water jump fix made it grow to 28)
- 'light_lev is not a field' spam in developer mode silenced
- Powerup sounds are now always precached so sounds aren't broken when using powerup impulses (registered
Quake has fewer total sounds in it than the original .exe's MAX_SOUNDS limit, and memory is free right?)
- Monster backpacks make the original ammo pickup sound, and the extended pickup noise is only for pre-placed
item_backpacks
- Doors with a +0/+a animated texture don't desync animation state when blocked or triggered repeatedly
- Fog change entities now work for all clients, not just player 1
- Gibbing a fish no longer makes bubbles
- dev_trigger and dev_invoke cheats no longer work in multiplayer
- Added 'trigger_inventory' to address the fact that a trigger_multiple targeting a target_items to test for
a player's stats/inventory only works for the first client due to default trigger touch logic
- Numerous .fgd errors fixed (monster spawnflags, etc) (thanks fairweather)
- Fixed typo in Chthon death notification
1.0: Jun 20, 2019
- Initial release
DEVELOPER COMMENTARY
====================
All of my changes to Quake's single-player and the rationale behind them are explained below. Each has been carefully weighed and tested, from the points of view of both a player and a mapper. (If you want to know what neat stuff has been added for mappers to use, scroll to the end.) In all cases I preferred a light touch, looking for ways to gain maximum benefit by applying minimal pressure to the design. They don't really change the game, and yet they really do.
Over time, my reasons for changes coalesced around a very clearly motivated "spirit" to Copper, summed up in the form of a list of goals:
- Introduce no new major mechanics; only tweak existing mechanics and their interactions
- Ensure that any changed or adjusted mechanics are clearly legible through gameplay (no
invisible fudging of outcomes while hiding causes)
- Fix the "gameplay bugs" we've all just gotten used to since 1996, without sacrificing
what value or charm they may have
- Incorporate players' existing expectations and Quake instincts (don't set the player up
to feel like their old instincts "betrayed" them)
- Expand, never reduce, opportunity for skill-based play at high levels
- Give level designers more options and flexibility to build compelling gameplay and not
just pretty rooms
- Maintain backwards compatibility with Quake's original four episodes and as many custom
maps as feasible
Detailed descriptions of every change, as well as the rationale behind each one, follow.
SHOOT-THROUGH
-------------
The bug where monsters in death animations act as solid walls to bullets and projectiles has been fixed. Shotguns now feel much more effective at crowd control, especially against large amounts of weak monsters. As individual shotgun pellets add their damage to a target, once enough damage to kill it has been totaled up, further pellets will do 50% damage to that target and continue their trace beyond it at full damage. This works similarly to the Doom shotguns, giving Quake's shotguns the same satisfying feeling of room-clearing penetration, while retaining (albeit reducing) the chance of Quake's trademark shotgun-gibbing. Now, on average, it pays off for the player to maneuver to line up targets in rows when shotgunning, and to use the SSG on crowds.
Nails no longer 'plink' against dying monsters, and grenades do not bounce off of them, passing through instead. Dying monsters are still solid to players and other monsters until the same times in the animations as before.
RING OF SHADOWS
---------------
The Ring of Shadows now protects the player in combat: monsters no longer know exactly where the player is once awakened. They will shoot or melee randomly into an invisible player's general area, hoping to get lucky, usually missing, and sometimes even hitting other monsters. In exchange, the Ring no longer makes all monsters deaf to your gunfire. This makes the Ring function much the same as the Invisibility powerup in Doom/Doom II, but with this addition: ranged attacks miss the player if they would be grazing hits (but dead-on attacks still land). Getting boxed into a corner in melee is as deadly as ever, so players should take advantage of the confusion to stay light on their feet. The protection against ranged attacks does not extend to splash damage from nearby explosions, or leaping melee attacks.
Dogs are known to be able to hunt using an otherworldly power of perception known as "smell" and are unaffected by the Ring of Shadows once awakened. Fiends are affected just like every other monster, because they have eyes. (To be less facetious about it, it's more fun to watch deadly Fiends dive hard into other monsters by mistake, or over cliff edges, than it is to imagine they can 'just sense' you.)
Mappers almost never bother to place a Ring of Shadows in their levels, and when they do, players are never excited to find one, because the power to merely delay engagement with monsters is of very limited value. The improved Ring is now a very good 'soft' powerup for mappers to place in their levels, especially when hidden before nasty ambushes, when granting the extreme power of a Quad or a Pentagram is too much. Players also enjoy watching the chaos that ensues.
Importing Doom-style invisibility also imported the reasons for Doom players' perception of invisibility as a "powerdown." The Ring originally blunted melee damage in Copper, but not ranged attacks. It was expected that monsters' confused random shots would make for adequate ranged protection for invisible players, but it created an upside-down situation. Average-skill players who didn't have exact muscle memory for anticipating and dodging attacks perfectly were hit a lot less and liked it, but the unpredictability robbed high-skill players of the ability to consistently avoid hits, sometimes being tricked into dodging into a projectile that "should" have missed.
Copper adds a little extra for skilled players to alleviate this downside: monsters regain their normal accuracy for a second after a player shoots them. This lets players manipulate monster accuracy to a degree, letting them use their weapons to force an individual enemy back to the state where its projectiles can be dodged reliably, as well as adding a strong method for directing infights.
VORES
-----
Vore missiles have been given a limited turn rate. They will still follow the player aggressively, but sidestepping them is now a skill-based option to buy a few seconds of safety before they loop around again (or to swing them into walls or other targets). Their maneuverability is reduced once their parent Vore has been killed, providing the player another option for shaking them that encourages staying in combat rather than fleeing.
Vanilla Vores are hard for the mapper to use well because the player response to them is almost always excessive caution, leading to a hard stop on combat. The minigame of "Hide From The Voreball" is so high priority because of their perfect homing that it overrides all other gameplay rather than adding to it, and often forces the player to backtrack through lots of empty map. Fighting a Vore in the open is also a time-delayed death sentence rather than a unique challenge. Mappers therefore tend to deploy Vores alone, frequently as nothing more than turrets. Making Vore missiles home tightly but not perfectly gives the mapper more flexibility to challenge players with Vores in more situations, overlapping in new ways with other monsters, making for more fun level design and combat.
OGRES
-----
Ogres are "semi-Z-aware." An Ogre is now much better at getting grenades near their target, no longer mindlessly firing far over the target's head or at walls beneath them, but without gaining pinpoint in-your-face Z-accuracy, so the player retains some of the expected advantage from large height differences. The Ogre feels more threatening from more angles, but not unfairly so.
The typical Z-aware Ogre implementation makes for Ogres that dead-eye the player unexpectedly from any angle, but vanilla Ogres are of limited utility to the mapper because they have a hard-coded firing arc, requiring that architecture be customized to accomodate them. The Copper approach is simple: average the hard-coded angle and the perfect-solution angle. This yields an Ogre which is much more effective at localizing the "bouncing grenade chaos" to the player's vicinity, but still feels like the old Ogre, so the player's existing instincts for fighting them don't need to be relearned. The mapper can therefore use Ogres more flexibly and with greater confidence.
This is the only kind of Ogre in Copper. Z-accuracy is not a mapper-selectable option on Ogres, to maintain consistency and predictability for the player.
ZOMBIES
-------
Zombies can be killed by any explosion, not just rocket-strength blasts. Ogre grenades were formerly too weak to do more than knock Zombies down even on a direct hit; they now do extra damage vs. Zombies, enough to gib them. This gives players a few sneaky extra ways to eliminate them by exploiting other monsters.
Zombies still require explosions to kill. The "axe kills downed Zombies" feature from Honey was not adopted. It makes chopping up Zombies a slow chore just to save a rocket, and defuses the tension that comes from encountering Zombies before the player has a way to kill them, which robs the mapper of a whole family of potential designed scenarios.
As a helpful quality-of-life improvement for the player, one hit from the Axe instantly knocks a Zombie over without having to "wear it down" first.
Zombies no longer need to be standing to be gibbed by an explosion. Grenades will still not collide against a downed Zombie and explode (this would lead to too many accidental blasts), but a grenade that comes to rest on or next to one before exploding, or explodes against something else that's close enough, will still reduce a Zombie to chunks. The Rocket Launcher works the same way. To be gibbed by Quad Damage shotgun or nailgun fire, however, Zombies must still be standing.
Monsters no longer get stuck eternally infighting with a Zombie they can't kill. They will attack it until they knock it down, then consider it dead and revert to their previous target. The Zombie will also not resume infighting with that monster when it stands back up.
SHAMBLERS
---------
After a Shambler's first two melee attacks in a row, a chance of making a lightning attack in place of the next melee will gradually build. The "Shambler Dance" of moving in and out to induce but avoid melee attacks remains a viable strategy for a few seconds at a time, but attempting to exploit it continuously is now a more dangerous gamble. Coincidentally, the length of two melee attacks is almost exactly as long as a Shambler can survive sustained fire from the Perforator before dropping.
Players have been heard to complain that once they became skilled at the Dance, Shamblers ceased to be scary. This change still lets players briefly mitigate a Shambler with a practiced series of fake-outs, but infuses the act with a new tension: doing so without an exit plan is as dangerous as it ought to be. Making the strategy less reliable for players makes Shamblers more reliable for mappers: they can now count on a Shambler being a frightening, in-your-face rush monster that forces the player to dance on the move, and not in place.
Shamblers no longer try to fire lightning from beyond the maximum range of their lightning. This bug was largely unnoticeable at the typical scale of Quake's original maps, but became clear as custom Quake levels grew in scope. There is no longer an envelope at the edge of their range within which the charging-up animation is a false signal. (The other potential fix, extending the range of the lightning instead, was rejected out of a desire not to muddy the role of a Shambler as a frightening, in-your-face rush monster with what would amount to the power to snipe the player at a distance.)
ENFORCERS
---------
Enforcers, rather than firing twice in a salvo, begin firing continuously like a turret until they lose line of sight or are interrupted by pain. When encountered in groups or at range, it places greater emphasis on using movement, pain-juggling, and selectively breaking line of sight to manage their threat, which helps all Enforcers feel less like speed bumps and more like a unique threat. To avoid unbalancing the game too excessively in their presence, their laser bolt damage has been reduced from 15 each to 12.
Enforcers have long and likely pain animations, and most only live long enough to fire twice anyway, so this doesn't introduce inordinate difficulty to most maps. It does add one more axis of micro-decisionmaking for players when an Enforcer is on the field, which is one more tool for designers to use to craft gameplay. It also helps differentiate the Enforcer into a more unique role than "better Grunt" or "non-flying Scrag" for both parties. There is an open in space in Quake's menagerie for (to borrow more parlance from Doom2) a Chaingunner/Arachnotron-style enemy, and the Enforcer's lack of a strong role and existing style of attack makes them an ideal fit.
OTHER MONSTERS
--------------
The bug where players could be instantly killed by a Fiend, Spawn, or Dog landing on their head has been fixed. Fiends also have a better sense of when their leap path is clear, and will no longer bounce spastically back and forth across a doorway or at the bottoms of stairs.
Knights have had their health reduced from 75 to 72, enough to make it possible to kill them with three careful and complete shotgun blasts instead of always requiring a fourth.
A Hell Knight's magic spreadfire projectiles have been sped up from 300 to 425. This helps make them less of a spammy non-entity at medium to long ranges, while not making the projectile too fast to outrun at close range or dodge at middle range.
Fixes for the various problems with Rotfish (double kill count, being solid too long after death, shrunken head in death frames, getting stuck at the surface of the water) have all been included. They also swim just a little faster and bite just a little harder, so they're not just fodder.
A Spawn that loses sight of its enemy will, eventually, stop leaping around, giving the player another chance to find and kill it in its sluggish state. This mostly preserves the fun-panic unpredictability of Spawns without them being a never-ending crap shoot, making it easier for the mapper to predict how much health or ammo a player might expend fighting them. This behavior interacts with the Ring of Shadows.
Ch'thon still leads his shots to a degree modulated by skill, a necessary component of his balance when there's only so much that can be done with the level around him. His projectiles now travel faster for each time he's been zapped, to add increasing danger and mounting tension to Ch'thon encounters. The hissing bomb-in-flight sound they now make as they narrowly miss the player is pretty good for that, too.
All monsters (except Grunts) already refuse to infight with other monsters of the same classname, but they now take half damage from attacks by such monsters as well. Vores and Ogres are immune to their own splash damage (but not others'), so they can no longer slowly bomb themselves to death.
Infighting monsters who fail to successfully damage their target for 15 seconds will give up on the infight and revert to their previous enemy, so Ogres on plinths no longer accumulate permanent fan clubs milling around their feet. Monsters who do not have a ranged attack will give up after 10 seconds.
Some monsters' bounding boxes have been shortened vertically, so you can't shoot them by firing into empty space above their heads. This does not fix 64x64 monsters getting stuck in rooms with ceilings lower than the height of a Shambler, which requires engine and .bsp support.
SKILL LEVELS
------------
Monster behavior in Copper is consistent across all four skill levels, and attack frequency is no longer used to artifically inflate the difficulty of Nightmare skill. Nightmare is now distinguished from Hard by reducing the player's maximum health from 100 to 50. This simulates the way that players lean forward and begin playing for keeps only when their health is unusually low, requiring the player to stay in low-health clutch mode to survive. Easy, Medium, and Hard skill levels are still distinguished from each other by the level design.
The highest difficulty level in the game should reward system mastery and high-level play. Monsters in vanilla Nightmare are aggressive to the point of becoming exploitably broken, forced to stand in place and fire continuously when the player is in sight like mindless turrets. This robs the game of an important source of unpredictability, that of monster movements and actions, which in turn only encourages degenerate cheesy tactics from players that aren't valid on any other skill level, so it has been eliminated.
Very few things in Quake's game code (or, for that matter, Doom's) changed with skill level, and this style of design has been scrupulously maintained. The only things that should vary between skill levels are things which are readily apparent and instantly understood. If a map has more monsters and fewer health items, the player understands the harder situation at a glance. If instead the monsters have more health and the health items give less, the difficulty is increased in an opaque and hidden way, because the player's learned expectations are now wrong. Thus instincts developed on Normal would be useless or even detrimental when trying a map on Hard or Nightmare, and vice versa. Since lowered max health is clearly reflected on the HUD, it is immediately understood by the player and instantly teaches them that playing differently is necessary.
The additional Nightmare-only exceptions that make Voreballs 40% faster and Shambler lightning last for 33% longer (and thus do an extra 10 damage) were found to be unnecessary to the new Nightmare gameplay and have been removed. Skill and muscle memory developed on other difficulties for reacting to Shamblers and Vores will serve the player equally well on Nightmare, and are all the more valuable for it.
COOPERATIVE MODE
----------------
Version 1.1 added a great deal of polish and features aimed at improving Coop gameplay for players and expanding possibilities for mappers interested in supporting Coop mode. The main goal was to reintroduce fear of death, a constant in singleplayer but entirely absent from Coop. With no real way to lose, owing to players always being able to respawn and keep going no matter what, vanilla Coop is a hectic but tension-free shooting gallery.
A level is now considered failed in Cooperative mode if all players are dead at the same time. Killed players can only respawn as long as there is at least one player currently alive. If the last player dies before anyone has had a chance to respawn, the level resets and must be reattempted from the start. (Singleplayer works this way too, in a manner of speaking, just with a maximum player count of one.) Since this circumstance is vanishingly rare even in a two-player game, a player is now prevented from respawing for five seconds after dying. If another player dies in that window, the cutoff is pushed back a little more, and so on, accelerating the possibility of a Total Party Kill. Death is now dangerous.
Furthermore, unless the level has reset after wiping out, respawned players don't come back with all the ammo and armor they entered the level with. They retain their weapons (since there's no guarantee a level or episode will continue to provide duplicates), but otherwise return to play with nothing to their name but the typical 25 shells. They can have their ammo back, of course - if they can return to the backpack they dropped. Falling into lava or a void thus has the potential to waste vital resources. If this might make finishing the level impossible, players can always try, and start over if they fail - this outcome at least gets them playing again right away rather than degrading to a war of attrition with axes.
Other players are now prevented from snagging each other's backpacks, to prevent accidental deprivation or intentional malice.
Rather than weapons hovering non-solidly and refusing to interact with any player who already has one, weapons can always be picked up, and will vanish as soon as they do, as in singleplayer. To prevent other players from missing out on having the weapon, Copper considers the party as a whole to have acquired it, and it is immediately granted (along with its ammo) to all players. Finding a secret lightning gun when you've already got one should at least be worth some cells, after all.
One more item has seen a party-friendly modification: when a player picks up a Megahealth, in addition to receiving +100 overhealing, all their teammates are restored to full health. (Saving a Megahealth for a well-timed moment in the midst of a tough fight can make a world of difference.)
All of the above changes are siloed to 'coop 1'. The instant and well-supplied respawns and weapons-stay behavior of vanilla are still available as 'coop 2' if you miss that kind of thing. All changes that follow are universal upgrades to both Cooperative modes.
The frag count displayed on the HUD in Coop now sensibly shows monster kills instead of player kills. Teammate kills, suicides and self-owns like visiting the volcano god are worth -5. Friendly fire can also now be disabled in Coop entirely by setting the 'teamplay' cvar to 1.
There is no longer need for players to be delicate around teleporters and spawnpoints out of fear of someone being telefragged. If the sudden appearance of a player would gib another, that player is safely pushed off the destination instead. The teleporting or respawning player appears as soon as the destination is clear. If the other player is prevented from being pushed away by something, or is being intentionally cheeky, the waiting player can avoid being trapped in teleport limbo by pressing jump or fire to force a telefrag.
This fixes the unfortunate side effect of two players falling into a void at the same time telefragging each other when they're teleported back to solid ground. Sorry about that.
Monsters' attention spans are now wide enough to include multiple players, or rather, they no longer make rigid distinctions about which player they're angry with. They will no longer single-mindedly ignore an easy target just because the last player who harmed them is playing hard-to-get. Get too close, or get in their way, and expect to become their new target. Aggro can still be drawn, just not exploited, so no matter what your buddies are up to, you aren't safe from any monster that can see you. This does mean that a Ring of Shadows is a great way to let your allies take more than their share of the heat. (Announcing your presence with the glowing power of a Quad Damage has an effect, too...)
Monsters will still fixate, for a little while, on any player who hurts them badly enough to trigger a pain animation, something experienced Quake players already have muscle-memory for on a monster-by-monster basis. This adds a dimension of battlefield control to Coop that isn't present in singleplayer, making monsters that are easy to stun (like Ogres) easy to manipulate, and monsters which don't stun so easily (Shamblers) more bullish.
A change of enemy is never random. Choice of player to attack is based solely on a simple assessment of range, forwardness-vs-behindness, and visibility. This makes it easy to develop a 'feel' for when you'll pull a monster's attention and how you can lose it, allowing players to make informed split-second decisions with intent to control a fight, rather than only reacting to the unpredictable.
The dreaded func_plat elevator, which begins rising as soon as anyone steps onto it, works fine with one player but is almost guaranteed to split multiple players apart unless they time their movements very carefully. Now, when a player steps onto a plat, it will automatically check a narrow radius for other players who might be about to hop on, and delay movement for about a second to give anyone it finds a chance. Otherwise, it behaves normally.
The 'timelimit' cvar now has a Coop function. If set, once any player exits the level, the intermission won't be triggered for that many seconds, allowing other players to finish grabbing supplies or anything else they might be doing. Everyone who exits before then still gets to peer through the intermission cameras, and can even pan them around.
HEALTH
------
One-point-per-second health degradation when overhealed is now something that simply always happens to every player's health (above 100, or 50 on Nightmare), and is no longer tied to recent Megahealth pickups. Grabbing two Megahealths no longer leads to your health ticking down at twice the rate, and should anyone venture into Copper multiplayer, their health will no longer stop rotting if someone else picks up the same Megahealth after it respawns.
Some health pickups have been given a visual pass. By popular request, +15s are now a little smaller than +25s, to more clearly distinguish them. Megahealths now look a little more ornate (only a little - they're still adorably cubic) and have a unique top texture, so they're no longer generic brown boxes when viewed from above. While this is a break with the "canon" that +15s are rotten +25s, and thus should look similar, too many players seemed unable to tell the existing pickups apart even with extra rot smeared on.
The 50 HP 'safety buffer' that players are healed up to if they finished a prior map with low health is disabled on Nightmare.
ARMOR
-----
The percentage of damage diverted from the player's health by Yellow and Red armor has been reduced to 50% and 70%, from 60%/80%. The minimum amounts of armor of a given color a player must have in order to be able to pick up an armor of a different color have been rounded to whole multiples of ten (100 Red for Yellow, 60 Yellow for Green, and 40 Red for Green) to make armor pickup outcomes easier to learn and anticipate.
'armorvalue'/'armortype' keyvalue hacks still work as normal on monsters.
Armor is now shielded by the Pentagram of Protection, just like health. While the old behavior of still losing armor while invulnerable was something that players were probably used to (those who noticed, at least), it never quite fit the concept of invulnerability, and may very well have simply been a bug. The stylish 666 on the HUD also prevented the player from even knowing how much armor they were losing until the Pent had expired, so this removes the mystery.
NAILGUNS
--------
To help distinguish the two nailguns from each other, so that the Perforator is less of a straight upgrade, the velocity of nails from the Nailgun has been doubled, while the Perforator has been given a little spread (comparable to the Shotgun). This makes the Nailgun better at long-range needling (to reduce the necessity of efficient-but-boring shotgun sniping), while the Perforator is just as good as always at close DPS but potentially wasteful at range. Their damage outputs are unchanged.
The Perforator now fires two regular nails at once, rather than one nail that is "better", to better leverage the aforementioned shoot-through. When the player uses the Perforator with a Quad, the two spikes' damages are always combined against one target, to ensure there is no reduction in ludicrous gibs compared to vanilla Quake.
THE AXE
-------
Players no longer alert monsters by swinging the axe without hitting anything.
The axe view model has been reanimated at 20fps. This makes the axe feel a lot more responsive and satisfying, as the damage frame now lags less behind the attack impulse. Axe damage has also been raised slightly (from 20 to 24), so that it takes exactly as many hits from the Axe to kill any given monster as it takes complete hits from the Shotgun.
The axe now makes sounds when hitting monsters or damageable brushmodels.
AMMO DROPS
----------
Ogre ammo drops have been reduced to 1 rocket each (from 2). Vanilla Ogres were 'ammo neutral' in that it took two grenades (or two grenades worth of shotgun or nail damage) to kill them, and two grenades were dropped in return, so each Ogre was effectively a means of converting other ammo into rockets. The level designer could not then give the player a grenade launcher or rocket launcher without making them instantly overpowered thanks to all the rockets they'd saved up, due to what a bread and butter monster the Ogre is. This change improves the mapper's ability to make rockets rare if they choose, without having to so severely limit use of Ogres.
Enforcers no longer drop any cells for the same reason.
Small and large rocket ammo pickups have been reduced to 4 and 8 (from 5 and 10) to give the mapper slightly finer control over the quantity of rockets they dish out. This doesn't actually seem to affect the balance of most existing maps too badly, because a perception that rockets are more rare causes players to maximize their value by using them more on groups and big bads, rather than casually spamming grenades around corners or using the rocket launcher to frag one Knight at a time. The CanDamage() bugfix has also been applied, making explosions less likely to skip targets within their blast radius, so rockets and grenades should compensate in application by feeling a bit more powerful against groups.
All small ammo pickups are now centered on their bounding boxes. The rocket ammo pickups have been redone to match the scale and style of the other ammo boxes, and no longer depict weird fat & skinny rockets.
LIQUIDS
-------
Monsters now take damage from immersion in lava or slime. They can wade in it without issue, but if they should get in "over their heads" in a place they can't get out of, they won't run around hidden under the surface forever. Monsters pre-placed in lava or slime remain immune to both so as to not break backwards compatibility with existing maps that hide them there on purpose, but they lose their immunity once they fully leave the liquid. Zombies and Scrags are always immune to slime; Zombies because you can't poison the dead, and Scrags because they spit slime and there's no good way to stop them flying into it anyway. Zombies which take damage from lava are gibbed, because that's the only damage that's meaningful.
The bug that caused drowning damage to be partially subtracted from armor has been fixed. The speed at which drowning damage escalates has been cut back a little instead, so that water is still only proportionately as deadly as before. It's about making the player panic so they drown themselves, after all.
The player recovers most of the damage they took from drowning once they're above water again (or if they find themselves a biosuit while drowning). Short choking episodes do no permanent damage, but the longer the player goes without air, the more health is lost permanently. If they dive below the surface before the recovery is complete (in other words, before they get their wind back) the onset of drowning damage comes sooner and harder the next time. This makes players feel a bit more free to explore underwater just a little too long for only short-term risk but no permanent penalty, which should in turn help mappers feel more comfortable with use of swimming gameplay (especially to make the player feel uncomfortable ...).
Drowning damage and recovery (and only those two things) are reduced by half on Nightmare, to stay in proportion with the player's maximum health. Otherwise, shortening the drowning timer so severely may make long underwater segments in some maps not just more scary and deadly, but physically impossible to complete.
A biosuit's protection against lava reduces the player's effective depth in lava by one step (ie if immersed in lava, damage is taken as if chest-deep, and so on). This makes a biosuit effectively proof against lava that is only ankle deep.
KEYS & RUNES
------------
Players can carry more than one key of the same type, should they happen across any. Quake reminds players how many they have with an upper-right-corner print when they grab or use one, and the icon only disappears from the HUD once the last key has been used.
This required a change to how keys work in cooperative play. Keys now disappear when picked up in coop just like in single-player, meaning whichever player grabbed it is the one who has to open the door with it. If that player dies or disconnects, held keys are automatically transferred to a different living player to ensure a map is never made impossible to finish by "losing" a key in an unreachable place. If all other players are dead when a keyholder dies in 'coop 2', that player simply respawns with their keys.
This opens up a family of nonlinear level layout possibilities that use duplicate keys to grant the player some choice in which progression gates to unlock in what order, or to promote certain other gating mechanisms to a higher 'tier' than buttons, without the awkwardness of players being unable to pick up a key when they already have one.
Preach's fix for the "restarting after dying loses your runes" bug has been gratefully incorporated. Players can now safely hero it through all the haunted lands of Quake without resorting to quicksaving if they so desire.
MISCELLANY
----------
The explobox recursion crash fix has been applied, so barrels-o-fun style usage is possible. Explobox solidity type has been changed to BSP, so the small explobox no longer has a strange tall bounding box, and players can stand and jump up and down on top of both small and large exploboxes (including suicidally barrel-jumping off the tops of them and not just the sides).
Splash damage indirectly activating shootable doors and buttons has been curtailed. Splash radius is reduced by two thirds vs damageable brush entities, so explosions must happen closely enough to be intentional. This preserves the player's ability to use rockets and grenades to activate such entities (and thus the mapper's ability to use them that way), while preventing players or monsters with splash weapons from doing so accidentally.
The flying teleport ball from the final Shub level has custom movement code rather than using func_train functionality, so while it moves the same as it used to, it can no longer cause the onerous MOVETYPE_PUSH crash if you touch it wrong.
Intermission cameras will slowly cycle automatically, or can be cycled by players, to ogle every view of the nice level art they didn't notice while deep in skill-based high-level play. Since whichever of 'Jump' or 'Fire' is rebound to cycle the cameras is guaranteed to annoy the 50% of players who use that button, and never the other button, to exit the intermission, intermission cameras in Copper are instead cycled using Impulse 10 & 12 (the next weapon/previous weapon impulses), which most players will likely have bound to the mousewheel.
STUFF FOR MAPPERS
=================
A non-exhaustive list:
Smoothly blending fog functionality from Honey/AD, and fog control/transition entities (both a one-time blend entity, and a trigger volume that transitions the fog based on the player's position inside it, so moving back and forth in a hallway doesn't lead to the fog swapping mysteriously at either end). Fog values can also be set on every player start, teleport destination, and intermission camera, so the player's fog can always be set to desired local values.
Plenty of mapper quality-of-life additions have been adapted from Quoth and other places, such as:
- every monster can be configured as a spawner
- four targetN keys on all entities (targetnameN keys were not found to be worth the code complexity)
- bounding-box point triggers
- func_everything support for external bsp/mdl models
- auto-spawning or respawning items
- toggleable func_walls (either solidity & visibility, or +0/+a texture state)
- a generic ambient_sound entity
- 'not in coop' and 'coop only' spawnflags 4096 & 8192 supported on all entities
- misc_model for .mdl decorations and obligatory dead bodies and candles
- override obituary messages with the deathtype keyvalue on all entities
- angle keys work on ammo and health - without the need for special ammo models or a worldspawn key
- impulse 205 kills all monsters without breaking level scripting
- worldspawn gravity key
- smooth movement for flying/swimming monsters, including z-axis path walking fix
Useful new entities:
- func_void: for 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.
- target_items: Add/subtract/override/check for item/weapon/inventory/stat loadouts on players through an entity. Do useful stuff like test mid-episode maps with an estimated set of starting gear, without having to play through the previous maps.
- target_lock: selectively enable and disable other entities, including triggers, trigger_relays, and path_corners.
- func_flytrain: smooth, curvy motion along a chain of path_corners.
- target_autosave: saves the game to auto.sav when triggered, can be loaded from console.
- info_teleport_target: teleports the activator to it when triggered, for complex scripting where using teleport volumes won't do
- target_explosion/target_telefog/target_meat_fireworks: configurable effects on demand without barrel_explode5 think hacks
- item_backpack: a small ammo reward for those little hideaways that aren't really full secrets (okay, one new item)
- and more
Quake2- & Quake3-style noclip mode which prevents all interaction with the level, so you can fly around without waking monsters and touching stuff.
Override and customize light stylestrings through keyvalues, to create any custom flicker/pulse/discoteque you desire. Triggerable lights can also be toggled between off and a lightstyle.
The most configurable monsterjump trigger ever: include a monster by classname, exclude a monster by classname, plus spawnflags to only allow 32x32 or 64x64 monsters, only melee monsters, as well as "only if my enemy is below me" and "only if my enemy is in front of the trigger."
Coop starting spots can spawn disabled and be enabled by trigger during gameplay, so you can gradually move the coop starts forward to keep them close to the action (or on the correct side of backward-progression blocks).
Trigger_hurt can be set to ignore monsters and/or biosuited players. Target_items can be used to, among many other things, make any trigger ignore invisible players.
Any skip-textured func_ entity can be effective as "creatureclip" with the 'notrace 1' keyvalue. Note: creatureclip is still solid to players, and is used primarily for making monsters walk over grates or other fancy holey floors without blocking line of sight or weapons fire like normal solid skip.
nomonsters cvar is functional.
All of the above was implemented while paying careful attention to backwards compatibility with existing /id1 maps, both stock and custom. Even some of negke's maps.
STUFF FOR MOD AUTHORS
=====================
Full QuakeC source is included. You may, and are encouraged to, use it as a base for additional mods, adopting or adapting features, or merely to learn from. Compiling it requires FTEQCC (any version from at least 2018), by Spike, available as of the writing of this document here: [ http://fte.triptohell.info/ ]. Other compilers may work, provided they support a few syntax upgrades (such as field masking and not requiring the 'local' keyword) as well as #pragma autoproto. If you're unsure if your compiler will work, try it and it should tell you. :)
When extending Copper for your own mod, I strongly encourage you to use the complete corpus of gameplay tweaks described above if you use any, rather than sampling what may be your favorites. This will avoid fracturing for players the 'gameplay base' that Copper strives to provide. Copper touches many aspects of the game in small but significant ways. If every mod were to include a different subset of these, the play experience for each player would be muddled by a trepidatious series of accidental discoveries of which way the player should expect them all to function *this* time, rather than being able to take the entire package as a given *every* time.
Consider the conventional Z-aware Ogres, the ones with perfect aim. When you play a Quake add-on that includes them, how do you learn they're there? Is it in the readme? Does the game warn you? Or do you find out the hard way, the first time one shoots you in the face from an angle you thought safe? Now consider this problem of relearning part of the game as you play, but multiplied across every alteration in Copper. Players could no longer take the presence of any one Copper feature as an indicator of the presence of any other, and while your mod may be that little bit more like the Quake you want others to play, such subtle but constant confusion would, I feel, make Quake a little worse for everyone.
Kell released Quoth closed-source, and cited as a reason a desire to avoid such fracturing caused by "everyone compiling their own interpretations of Quoth." While I feel that's a little too protective, I understand the sentiment. However, a great deal of the mapper features in Copper originate from Quoth, and had to be re-engineered from scratch on my part without any source code to work from, and I won't let any of my personal (and possibly selfish) reservations lead me to do the same to you. The source is provided happily, because this is still better for Quake overall no matter what people may do with it. Everything will work out okay in the end.
ENTITY DEFINITIONS
------------------
id's original means of generating editor entity definitions was to overload block comments. Every comment block that opened with "/*QUAKED" was considered an entity class definition, whose first line was treated as a formatted metadata definition of name, size, color, and spawnflag names (point/brush status was inferred from presence or absence of a defined size). Everything else in the comment was treated as a descriptive docstring. QuakeEd itself simply scanned the QuakeC game source for these comments directly and built its definition library from there. /*QUAKED*/ definitions could thus be kept alongside the code for the very entities they described, making it easy to keep them updated and accurate.
Future Radiant map editors that built on QuakeEd moved toward loading them all from one file, with a .def extension, but not changing or extending the syntax at all. The far more common format in use now for entity definitions is Worldcraft's FGD format, now used most prominently by Kristian 'sleepwalkr' Duske's Trenchbroom editor, because it supports quite a bit more metadata regarding keyvalues and their required types, while the QuakeEd/def system only supports this insofar as there's a large block of text in which developers can describe them in plain English.
I have chosen to support entity definition maintenance for FGD in the same way that the QuakeC source originally supported it for QuakeEd: by using comments within the source itself. The Copper source code still includes /*QUAKED*/ comments, adding and updating them wherever relevant to keep them up to date, because while Radiant and QuakeEd users are rare today, they do still exist. :) You will commonly find these paired with comment blocks beginning with "/*FGD" now as well. While editors like Trenchbroom do not scan multiple files looking for such comments, the notation made it easy for me to automate extracting the two types of comment blocks and compiling their contents into respective .def and .fgd files.
The Python scripts I used for these two tasks are included with the QuakeC source. They should Just Work(tm) provided Python 3+ is installed correctly, which is left as an exercise for the reader.
CODE REFERENCE
--------------
Here are some handy notes on important functions:
enemy_vispos(), ai.qc
---------------------
Any time a monster would use the vector stored as self.enemy.origin, be it for a line of sight test, launching a projectile or some other attack, or any other purpose, enemy_vispos() is called instead. Normally it simply returns self.enemy.origin anyway, but if self.enemy has a Ring of Shadows, it instead returns an origin offset in a standardized noisy way, so that the Ring confuses all monsters identically for gameplay purposes. Be aware that any time you bypass this function and use self.enemy.origin directly, the code in question will not be affected by invisibility unless you check the IT_INVISIBILITY flag manually (the most obvious example being ShalHome() in m_shalrath.qc).
traceline2(), projectiles.qc
----------------------------
traceline() can only ignore one entity at a time. To support the 'notrace 1' keyvalue for creatureclip, secondary traces have to be made to continue the trace through any hit notrace 'bmodels' which should be skipped by the trace. traceline2 is a wrapper for this functionality, and will perform any necessary extra traces automatically for you, modifying all the output trace_* global variables to contain accurate unified results as if a single trace had been performed. Thus you can use it exactly the same way you would traceline(), and in fact, you probably should pretty much everywhere.
Note that this is not the same code that enables shotgun penetration, although it is similar. That code is in FireBullets() in w_shotguns.qc (because it needs to apply the special case of adding damage to each TAKEDAMAGE target it passes through). You will notice that even this function still uses traceline2(), because players should be able to fire shotguns through both dying monsters and notrace bmodels at the same time.
CheckProjectilePassthru() & etc, projectiles.qc
-----------------------------------------------
traceline2() may work for hitscan and line of sight traces passing through a 'notrace' bmodel, but does not help in the case of point entities we would also expect to pass through them, such as nails, grenades, or gibs. These required a little more work. To enable such entities to pass through creatureclip, their touch functions should call CheckProjectilePassthru() and return without doing anything if it returns true. Note that this code IS used for allowing point entities and projectiles to pass through monsters in death animations, unlike traceline2() and FireBullets().
Much more information on understanding and working with point entity passthrough can be had in the comment blocks of projectiles.qc.
launch_projectile(), projectiles.qc
-----------------------------------
Code duplication in projectile and shooting functions across the codebase was cut down for convenience, and all such functions were gathered together into this file. All nails, rockets, lavaballs, grenades, etc, are spawned by one function or another that either calls launch_projectile() or something else which calls it and modifies the projectile it returns.
CheckValidTouch(), items.qc
---------------------------
Checks at the top of touch functions whether 'other' is a player, is alive, and isn't in NOCLIP were becoming ubiquitous across all triggers and items. Any touch function activated only by players can call this for all-in-one confirmation.
mon_spawner(), monsters.qc
--------------------------
Copper unifies a monster, a triggerable monster spawn, and a repeatedly-triggerable monster spawner into the monster itself. A monster's spawn function is split into two, with initial game frame necessities (such as precaches) separated from actual spawn completion code (such as walkmonster_start()). Initial setup remains in the monster's classname function, and spawn completion is moved to a second function, universally named as monster_classname_spawn().
The unification is accomplished by way of function objects. First, the classname function calls monster_spawnsetup() and passes it the name of a function which will spawn the monster in question when called. This should be a single-line function (universally named as monster_[name]_spawner()) declared uniquely for each monster, which injects some universal monster spawning code into our monster's spawn completion function by calling mon_spawner_use() and passing the spawn completion function as a parameter. This is a little convoluted, but is necessary so that each monster spawner's Use function is both customized to one monster and callable with no parameters (required by the .th_use field prototype). monster_spawnsetup() checks all the possible spawner configuration states and spawnflags by itself, which are universal across all non-boss monsters. It returns True if the classname function should stop before continuing on to spawn the monster directly (ie, call the spawn completion function).
Examine any monster's source file (m_*.qc) and scroll to the bottom for an example. To support triggerable monster spawning on a new monster, you need only ensure spawning code is split in the same way, and uses monster_spawnsetup() and mon_spawner_use() the same way. Note that spawnflags 1-5 and 8 are already reserved for spawner configuration, so new monsters will have to make do with flags 6 and 7. There are plenty of spare keyvalues should you feel you need more flavors than that. (at which point the game designer in me asks, "shouldn't that just be more than one kind of monster?")
PERMISSIONS
===========
You are free to distribute by any electronic means copper.zip, unaltered. Do not distribute new maps made for Copper by repackaging the Copper progs.dat or assets with the map; distribute the map standalone and clearly list Copper as a requirement.
The original QuakeC game source code on which Copper is based is copyright id software, so mods based on Copper cannot be exploited commercially.
ACKNOWLEDGEMENTS
================
Special thanks to:
- Scampie for endless testing, ideas, sounding and discussion
- Spike for FTEQCC, and putting up with my stupid questions
- Preach for providing QuakeC programming sanity checks, ballistic theta code, and for an explanation of how to implement Quoth's drifty fly and swim movement without running into the same bugs they did
- czg for the fog code in honey_fog.qc and the brilliant and terrible stuffcmd_float() (his maps are ok too)
- Bal, ijed, ionous, negke, JCR, mfx, sock, muk, and NewHouse for testing
- VuRkka and zigi for extra coop testing
- iw for diligently identifying, and providing example fixes for, a bunch of bugs in 1.0
- ptoing for pixel art revisions
- the entire Quake community for making so many other great mods over the years, because all the different visions of what Quake can be make this game what it is
Assets not by the author:
- g_shotgn.mdl is from Rubicon2, by John 'metlslime' Fitzgibbons
- Ranger falling-to-his-death sound is from Quake3:Arena, by id software
- Autosave sound by markie music
- Backpack pickup sounds are from Arcane Dimensions, by Simon 'sock' O'Callaghan et al
- deep1.wav and machlp.wav are from Arcane Dimensions, by Simon 'sock' O'Callaghan
- underw1.wav, wdribble.wav, and wpool.wav are from Rubicon2, by John 'metlslime'
Fitzgibbons
- shalrath.mdl modified by 'seven'
================================================================================
June 20th
2019