Merge remote-tracking branch 'origin/master' into samual/weapons
authorSamual Lenks <samual@xonotic.org>
Wed, 14 Aug 2013 16:12:12 +0000 (12:12 -0400)
committerSamual Lenks <samual@xonotic.org>
Wed, 14 Aug 2013 16:12:12 +0000 (12:12 -0400)
Conflicts:
effectinfo.txt
qcsrc/server/w_hlac.qc
qcsrc/server/w_uzi.qc
qcsrc/server/weapons/weaponsystem.qc

20 files changed:
1  2 
effectinfo.txt
qcsrc/client/View.qc
qcsrc/client/particles.qc
qcsrc/client/weapons/projectile.qc
qcsrc/common/constants.qh
qcsrc/server/autocvars.qh
qcsrc/server/bot/havocbot/havocbot.qc
qcsrc/server/cheats.qc
qcsrc/server/cl_client.qc
qcsrc/server/cl_physics.qc
qcsrc/server/cl_player.qc
qcsrc/server/defs.qh
qcsrc/server/g_damage.qc
qcsrc/server/g_world.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/mutators/gamemode_nexball.qc
qcsrc/server/mutators/mutator_minstagib.qc
qcsrc/server/progs.src
qcsrc/server/t_items.qc
qcsrc/server/weapons/selection.qc

diff --cc effectinfo.txt
@@@ -7978,82 -7978,975 +7978,1055 @@@ alpha 190 190 18
  sizeincrease -80
  color 0xFFFFFF 0xFFFFFF
  
+ // nade effects
+ effect nade_blue
+ trailspacing 1
+ type smoke
+ color 0x006cff 0x0600ff
+ tex 65 65
+ size 3 3
+ sizeincrease -1
+ alpha 100 100 250
+ //gravity -0.11
+ // fire
+ effect nade_blue
+ notunderwater
+ trailspacing 8
+ type smoke
+ color 0x0600ff 0x9794ff
+ tex 65 65
+ size 15 25
+ sizeincrease -10
+ alpha 30 30 150
+ // bubbles
+ effect nade_blue
+ underwater
+ trailspacing 16
+ type bubble
+ tex 62 62
+ color 0x006cff 0x0600ff
+ size 1 1
+ alpha 256 256 256
+ gravity -0.125
+ bounce 1.5
+ liquidfriction 4
+ velocityjitter 16 16 16
+ effect nade_red
+ trailspacing 1
+ type smoke
+ color 0xff0000 0xff3c00
+ tex 65 65
+ size 3 3
+ sizeincrease -1
+ alpha 100 100 250
+ //gravity -0.11
+ // fire
+ effect nade_red
+ notunderwater
+ trailspacing 8
+ type smoke
+ color 0xff0000 0xffa2a2
+ tex 65 65
+ size 15 25
+ sizeincrease -10
+ alpha 30 30 150
+ // bubbles
+ effect nade_red
+ underwater
+ trailspacing 16
+ type bubble
+ tex 62 62
+ color 0xff0000 0xff3c00
+ size 1 1
+ alpha 256 256 256
+ gravity -0.125
+ bounce 1.5
+ liquidfriction 4
+ velocityjitter 16 16 16
+ effect nade_yellow
+ trailspacing 1
+ type smoke
+ color 0xFFFF0F 0xFFFF0F
+ tex 65 65
+ size 3 3
+ sizeincrease -1
+ alpha 100 100 250
+ //gravity -0.11
+ // fire
+ effect nade_yellow
+ notunderwater
+ trailspacing 8
+ type smoke
+ color 0xFFFF0F 0xFFFF0F
+ tex 65 65
+ size 15 25
+ sizeincrease -10
+ alpha 30 30 150
+ // bubbles
+ effect nade_yellow
+ underwater
+ trailspacing 16
+ type bubble
+ tex 62 62
+ color 0xFFFF0F 0xFFFF0F
+ size 1 1
+ alpha 256 256 256
+ gravity -0.125
+ bounce 1.5
+ liquidfriction 4
+ velocityjitter 16 16 16
+ effect nade_pink
+ trailspacing 1
+ type smoke
+ color 0xFF0FFF 0xFF0FFF
+ tex 65 65
+ size 3 3
+ sizeincrease -1
+ alpha 100 100 250
+ //gravity -0.11
+ // fire
+ effect nade_pink
+ notunderwater
+ trailspacing 8
+ type smoke
+ color 0xFF0FFF 0xFF0FFF
+ tex 65 65
+ size 15 25
+ sizeincrease -10
+ alpha 30 30 150
+ // bubbles
+ effect nade_pink
+ underwater
+ trailspacing 16
+ type bubble
+ tex 62 62
+ color 0xFF0FFF 0xFF0FFF
+ size 1 1
+ alpha 256 256 256
+ gravity -0.125
+ bounce 1.5
+ liquidfriction 4
+ velocityjitter 16 16 16
+ effect nade
+ trailspacing 1
+ type smoke
+ color 0xFFFFFF 0xFFFFFF
+ tex 65 65
+ size 3 3
+ sizeincrease -1
+ alpha 100 100 250
+ //gravity -0.11
+ // fire
+ effect nade
+ notunderwater
+ trailspacing 8
+ type smoke
+ color 0xFFFFFF 0xFFFFFF
+ tex 65 65
+ size 15 25
+ sizeincrease -10
+ alpha 30 30 150
+ // bubbles
+ effect nade
+ underwater
+ trailspacing 16
+ type bubble
+ tex 62 62
+ color 0xFFFFFF 0xFFFFFF
+ size 1 1
+ alpha 256 256 256
+ gravity -0.125
+ bounce 1.5
+ liquidfriction 4
+ velocityjitter 16 16 16
+ effect nade_red_burn
+ trailspacing 1
+ type smoke
+ color 0xff0000 0xff3c00
+ tex 65 65
+ size 5 5
+ sizeincrease -1
+ alpha 100 100 250
+ //gravity -0.11
+ // fire
+ effect nade_red_burn
+ notunderwater
+ trailspacing 64
+ type smoke
+ color 0xff0000 0xffa2a2
+ tex 65 65
+ size 45 25
+ sizeincrease -30
+ alpha 200 200 1000
+ // bubbles
+ effect nade_red_burn
+ underwater
+ trailspacing 16
+ type bubble
+ tex 62 62
+ color 0xff0000 0xff3c00
+ size 1 1
+ alpha 256 256 256
+ gravity -0.125
+ bounce 1.5
+ liquidfriction 4
+ velocityjitter 16 16 16
+ effect nade_red_burn
+ trailspacing 16
+ type smoke
+ color 0xff0000 0xff3c00
+ tex 71 73
+ size 15 25
+ sizeincrease -40
+ rotate -180 180 20 -20
+ originjitter 2 2 2
+ velocityjitter 10 10 10
+ alpha 300 900 1500
+ effect nade_blue_burn
+ trailspacing 1
+ type smoke
+ color 0x006cff 0x0600ff
+ tex 65 65
+ size 5 5
+ sizeincrease -1
+ alpha 100 100 250
+ //gravity -0.11
+ // fire
+ effect nade_blue_burn
+ notunderwater
+ trailspacing 64
+ type smoke
+ color 0x0600ff 0x9794ff
+ tex 65 65
+ size 45 25
+ sizeincrease -30
+ alpha 200 200 1000
+ // bubbles
+ effect nade_blue_burn
+ underwater
+ trailspacing 16
+ type bubble
+ tex 62 62
+ color 0x006cff 0x0600ff
+ size 1 1
+ alpha 256 256 256
+ gravity -0.125
+ bounce 1.5
+ liquidfriction 4
+ velocityjitter 16 16 16
+ effect nade_blue_burn
+ trailspacing 16
+ type smoke
+ color 0x006cff 0x0600ff
+ tex 33 33
+ size 25 25
+ sizeincrease -30
+ effect nade_yellow_burn
+ trailspacing 1
+ type smoke
+ color 0xFFFF0F 0xFFFF0F
+ tex 65 65
+ size 5 5
+ sizeincrease -1
+ alpha 100 100 250
+ //gravity -0.11
+ // fire
+ effect nade_yellow_burn
+ notunderwater
+ trailspacing 64
+ type smoke
+ color 0xFFFF0F 0xFFFF0F
+ tex 65 65
+ size 45 25
+ sizeincrease -30
+ alpha 200 200 1000
+ // bubbles
+ effect nade_yellow_burn
+ underwater
+ trailspacing 16
+ type bubble
+ tex 62 62
+ color 0xFFFF0F 0xFFFF0F
+ size 1 1
+ alpha 256 256 256
+ gravity -0.125
+ bounce 1.5
+ liquidfriction 4
+ velocityjitter 16 16 16
+ effect nade_yellow_burn
+ trailspacing 16
+ type smoke
+ color 0xFFFF0F 0xFFFF0F
+ tex 33 33
+ size 25 25
+ sizeincrease -30
+ effect nade_pink_burn
+ trailspacing 1
+ type smoke
+ color 0xFF0FFF 0xFF0FFF
+ tex 65 65
+ size 5 5
+ sizeincrease -1
+ alpha 100 100 250
+ //gravity -0.11
+ // fire
+ effect nade_pink_burn
+ notunderwater
+ trailspacing 64
+ type smoke
+ color 0xFF0FFF 0xFF0FFF
+ tex 65 65
+ size 45 25
+ sizeincrease -30
+ alpha 200 200 1000
+ // bubbles
+ effect nade_pink_burn
+ underwater
+ trailspacing 16
+ type bubble
+ tex 62 62
+ color 0xFF0FFF 0xFF0FFF
+ size 1 1
+ alpha 256 256 256
+ gravity -0.125
+ bounce 1.5
+ liquidfriction 4
+ velocityjitter 16 16 16
+ effect nade_pink_burn
+ trailspacing 16
+ type smoke
+ color 0xFF0FFF 0xFF0FFF
+ tex 33 33
+ size 25 25
+ sizeincrease -30
+ effect nade_burn
+ trailspacing 1
+ type smoke
+ color 0xFFFFFF 0xFFFFFF
+ tex 65 65
+ size 5 5
+ sizeincrease -1
+ alpha 100 100 250
+ //gravity -0.11
+ // fire
+ effect nade_burn
+ notunderwater
+ trailspacing 64
+ type smoke
+ color 0xFFFFFF 0xFFFFFF
+ tex 65 65
+ size 45 25
+ sizeincrease -30
+ alpha 200 200 1000
+ // bubbles
+ effect nade_burn
+ underwater
+ trailspacing 16
+ type bubble
+ tex 62 62
+ color 0xFFFFFF 0xFFFFFF
+ size 1 1
+ alpha 256 256 256
+ gravity -0.125
+ bounce 1.5
+ liquidfriction 4
+ velocityjitter 16 16 16
+ effect nade_burn
+ trailspacing 16
+ type smoke
+ color 0xFFFFFF 0xFFFFFF
+ tex 33 33
+ size 25 25
+ sizeincrease -30
+ effect nade_blue_explode
+ countabsolute 1
+ type decal
+ tex 8 16
+ size 88 88
+ alpha 256 256 0
+ originjitter 26 26 26
+ lightradius 300
+ lightradiusfade 1500
+ lightcolor 20 20 100
+ // shockwave
+ effect nade_blue_explode
+ type smoke
+ countabsolute 1
+ tex 33 33
+ size 32 32
+ sizeincrease 1800
+ color 0x80C0FF 0x80C0FF
+ alpha 80 80 650
+ velocitymultiplier 44
+ // fire
+ effect nade_blue_explode
+ notunderwater
+ count 16
+ type smoke
+ color 0x629dff 0x0018ff
+ tex 48 55
+ size 20 24
+ sizeincrease 555
+ alpha 400 656 2000
+ airfriction 30
+ originjitter 50 50 50
+ velocityjitter 320 320 320
+ rotate -180 180 -9 9
+ // fire streched
+ effect nade_blue_explode
+ count 8
+ type spark
+ tex 48 55
+ color 0x629dff 0x0018ff
+ size 60 90
+ alpha 1500 3000 13000
+ stretchfactor 80
+ sizeincrease 40
+ velocityjitter 30 30 30
+ airfriction -9
+ //smoke
+ effect nade_blue_explode
+ type smoke
+ count 32
+ blend alpha
+ tex 0 7
+ size 60 30
+ color 0x222222 0x000000
+ alpha 128 328 390
+ rotate -180 180 2 -2
+ velocityjitter 200 200 200
+ velocityoffset 0 0 180
+ originjitter 50 50 10
+ sizeincrease 50
+ airfriction 0.04
+ gravity 0.4
+ // underwater bubbles
+ effect nade_blue_explode
+ underwater
+ count 32
+ type bubble
+ tex 62 62
+ color 0x404040 0x808080
+ size 3 6
+ alpha 128 256 64
+ gravity -0.125
+ bounce 1.5
+ liquidfriction 0.25
+ originjitter 16 16 16
+ velocityjitter 196 196 196
+ rotate 0 0 0 0
+ // bouncing sparks
+ effect nade_blue_explode
+ notunderwater
+ count 8
+ type spark
+ tex 40 40
+ color 0x006cff 0x0600ff
+ size 1 2
+ alpha 644 956 484
+ gravity 1
+ airfriction 1
+ bounce 1.6
+ liquidfriction 0.8
+ velocityoffset 0 0 80
+ originjitter 16 16 16
+ velocityjitter 424 424 624
+ // notbouncing sparks
+ effect nade_blue_explode
+ count 16
+ type spark
+ tex 40 40
+ color 0x006cff 0x0600ff
+ size 1 2
+ alpha 644 956 684
+ gravity 0.5
+ airfriction 0.7
+ liquidfriction 0.8
+ velocityoffset 0 0 80
+ originjitter 16 16 16
+ velocityjitter 424 424 624
+ // derbis
+ effect nade_blue_explode
+ notunderwater
+ count 12
+ type alphastatic
+ tex 66 68
+ color 0x6a3d25 0xcac5b4
+ size 2 6
+ alpha 644 956 684
+ gravity 1.3
+ airfriction 0.5
+ bounce 1.6
+ velocityjitter 324 324 524
+ rotate -180 180 -1000 1000
+ effect nade_red_explode
+ countabsolute 1
+ type decal
+ tex 8 16
+ size 88 88
+ alpha 256 256 0
+ originjitter 26 26 26
+ lightradius 300
+ lightradiusfade 1500
+ lightcolor 100 20 20
+ // shockwave
+ effect nade_red_explode
+ type smoke
+ countabsolute 1
+ tex 33 33
+ size 32 32
+ sizeincrease 2200
+ color 0xff0000 0xffa2a2
+ alpha 80 80 650
+ velocitymultiplier 44
+ // fire
+ effect nade_red_explode
+ notunderwater
+ count 16
+ type smoke
+ color 0xff0000 0xff4200
+ tex 48 55
+ size 20 24
+ sizeincrease 555
+ alpha 400 656 2000
+ airfriction 30
+ originjitter 50 50 50
+ velocityjitter 320 320 320
+ rotate -180 180 -9 9
+ // fire streched
+ effect nade_red_explode
+ count 8
+ type spark
+ tex 48 55
+ color 0xff0000 0xff4200
+ size 60 90
+ alpha 1500 3000 13000
+ stretchfactor 80
+ sizeincrease 40
+ velocityjitter 30 30 30
+ airfriction -9
+ //smoke
+ effect nade_red_explode
+ type smoke
+ count 32
+ blend alpha
+ tex 0 7
+ size 60 30
+ color 0x222222 0x000000
+ alpha 128 328 390
+ rotate -180 180 2 -2
+ velocityjitter 200 200 200
+ velocityoffset 0 0 180
+ originjitter 50 50 10
+ sizeincrease 50
+ airfriction 0.04
+ gravity 0.4
+ // underwater bubbles
+ effect nade_red_explode
+ underwater
+ count 32
+ type bubble
+ tex 62 62
+ color 0x404040 0x808080
+ size 3 6
+ alpha 128 256 64
+ gravity -0.125
+ bounce 1.5
+ liquidfriction 0.25
+ originjitter 16 16 16
+ velocityjitter 196 196 196
+ rotate 0 0 0 0
+ // bouncing sparks
+ effect nade_red_explode
+ notunderwater
+ count 8
+ type spark
+ tex 40 40
+ color 0xff0000 0xffa2a2
+ size 1 2
+ alpha 644 956 484
+ gravity 1
+ airfriction 1
+ bounce 1.6
+ liquidfriction 0.8
+ velocityoffset 0 0 80
+ originjitter 16 16 16
+ velocityjitter 424 424 624
+ // notbouncing sparks
+ effect nade_red_explode
+ count 16
+ type spark
+ tex 40 40
+ color 0xff0000 0xffa2a2
+ size 1 2
+ alpha 644 956 684
+ gravity 0.5
+ airfriction 0.7
+ liquidfriction 0.8
+ velocityoffset 0 0 80
+ originjitter 16 16 16
+ velocityjitter 424 424 624
+ // derbis
+ effect nade_red_explode
+ notunderwater
+ count 8
+ type smoke
+ tex 71 73
+ color 0xff0000 0xffa2a2
+ size 20 40
+ alpha 644 956 2500
+ originjitter 64 64 64
+ velocityjitter 324 324 324
+ rotate -180 180 -100 100
+ effect nade_yellow_explode
+ countabsolute 1
+ type decal
+ tex 8 16
+ size 88 88
+ alpha 256 256 0
+ originjitter 26 26 26
+ lightradius 300
+ lightradiusfade 1500
+ lightcolor 100 20 20
+ // shockwave
+ effect nade_yellow_explode
+ type smoke
+ countabsolute 1
+ tex 33 33
+ size 32 32
+ sizeincrease 2200
+ color 0xff0000 0xffa2a2
+ alpha 80 80 650
+ velocitymultiplier 44
+ // fire
+ effect nade_yellow_explode
+ notunderwater
+ count 16
+ type smoke
+ color 0xFFFF0F 0xFFFF0F
+ tex 48 55
+ size 20 24
+ sizeincrease 555
+ alpha 400 656 2000
+ airfriction 30
+ originjitter 50 50 50
+ velocityjitter 320 320 320
+ rotate -180 180 -9 9
+ // fire streched
+ effect nade_yellow_explode
+ count 8
+ type spark
+ tex 48 55
+ color 0xFFFF0F 0xFFFF0F
+ size 60 90
+ alpha 1500 3000 13000
+ stretchfactor 80
+ sizeincrease 40
+ velocityjitter 30 30 30
+ airfriction -9
+ //smoke
+ effect nade_yellow_explode
+ type smoke
+ count 32
+ blend alpha
+ tex 0 7
+ size 60 30
+ color 0x222222 0x000000
+ alpha 128 328 390
+ rotate -180 180 2 -2
+ velocityjitter 200 200 200
+ velocityoffset 0 0 180
+ originjitter 50 50 10
+ sizeincrease 50
+ airfriction 0.04
+ gravity 0.4
+ // underwater bubbles
+ effect nade_yellow_explode
+ underwater
+ count 32
+ type bubble
+ tex 62 62
+ color 0x404040 0x808080
+ size 3 6
+ alpha 128 256 64
+ gravity -0.125
+ bounce 1.5
+ liquidfriction 0.25
+ originjitter 16 16 16
+ velocityjitter 196 196 196
+ rotate 0 0 0 0
+ // bouncing sparks
+ effect nade_yellow_explode
+ notunderwater
+ count 8
+ type spark
+ tex 40 40
+ color 0xff0000 0xffa2a2
+ size 1 2
+ alpha 644 956 484
+ gravity 1
+ airfriction 1
+ bounce 1.6
+ liquidfriction 0.8
+ velocityoffset 0 0 80
+ originjitter 16 16 16
+ velocityjitter 424 424 624
+ // notbouncing sparks
+ effect nade_yellow_explode
+ count 16
+ type spark
+ tex 40 40
+ color 0xff0000 0xffa2a2
+ size 1 2
+ alpha 644 956 684
+ gravity 0.5
+ airfriction 0.7
+ liquidfriction 0.8
+ velocityoffset 0 0 80
+ originjitter 16 16 16
+ velocityjitter 424 424 624
+ // derbis
+ effect nade_yellow_explode
+ notunderwater
+ count 8
+ type smoke
+ tex 71 73
+ color 0xff0000 0xffa2a2
+ size 20 40
+ alpha 644 956 2500
+ originjitter 64 64 64
+ velocityjitter 324 324 324
+ rotate -180 180 -100 100
+ effect nade_pink_explode
+ countabsolute 1
+ type decal
+ tex 8 16
+ size 88 88
+ alpha 256 256 0
+ originjitter 26 26 26
+ lightradius 300
+ lightradiusfade 1500
+ lightcolor 100 20 20
+ // shockwave
+ effect nade_pink_explode
+ type smoke
+ countabsolute 1
+ tex 33 33
+ size 32 32
+ sizeincrease 2200
+ color 0xff0000 0xffa2a2
+ alpha 80 80 650
+ velocitymultiplier 44
+ // fire
+ effect nade_pink_explode
+ notunderwater
+ count 16
+ type smoke
+ color 0xFF0FFF 0xFF0FFF
+ tex 48 55
+ size 20 24
+ sizeincrease 555
+ alpha 400 656 2000
+ airfriction 30
+ originjitter 50 50 50
+ velocityjitter 320 320 320
+ rotate -180 180 -9 9
+ // fire streched
+ effect nade_pink_explode
+ count 8
+ type spark
+ tex 48 55
+ color 0xFF0FFF 0xFF0FFF
+ size 60 90
+ alpha 1500 3000 13000
+ stretchfactor 80
+ sizeincrease 40
+ velocityjitter 30 30 30
+ airfriction -9
+ //smoke
+ effect nade_pink_explode
+ type smoke
+ count 32
+ blend alpha
+ tex 0 7
+ size 60 30
+ color 0x222222 0x000000
+ alpha 128 328 390
+ rotate -180 180 2 -2
+ velocityjitter 200 200 200
+ velocityoffset 0 0 180
+ originjitter 50 50 10
+ sizeincrease 50
+ airfriction 0.04
+ gravity 0.4
+ // underwater bubbles
+ effect nade_pink_explode
+ underwater
+ count 32
+ type bubble
+ tex 62 62
+ color 0x404040 0x808080
+ size 3 6
+ alpha 128 256 64
+ gravity -0.125
+ bounce 1.5
+ liquidfriction 0.25
+ originjitter 16 16 16
+ velocityjitter 196 196 196
+ rotate 0 0 0 0
+ // bouncing sparks
+ effect nade_pink_explode
+ notunderwater
+ count 8
+ type spark
+ tex 40 40
+ color 0xff0000 0xffa2a2
+ size 1 2
+ alpha 644 956 484
+ gravity 1
+ airfriction 1
+ bounce 1.6
+ liquidfriction 0.8
+ velocityoffset 0 0 80
+ originjitter 16 16 16
+ velocityjitter 424 424 624
+ // notbouncing sparks
+ effect nade_pink_explode
+ count 16
+ type spark
+ tex 40 40
+ color 0xff0000 0xffa2a2
+ size 1 2
+ alpha 644 956 684
+ gravity 0.5
+ airfriction 0.7
+ liquidfriction 0.8
+ velocityoffset 0 0 80
+ originjitter 16 16 16
+ velocityjitter 424 424 624
+ // derbis
+ effect nade_pink_explode
+ notunderwater
+ count 8
+ type smoke
+ tex 71 73
+ color 0xff0000 0xffa2a2
+ size 20 40
+ alpha 644 956 2500
+ originjitter 64 64 64
+ velocityjitter 324 324 324
+ rotate -180 180 -100 100
+ effect nade_explode
+ countabsolute 1
+ type decal
+ tex 8 16
+ size 88 88
+ alpha 256 256 0
+ originjitter 26 26 26
+ lightradius 300
+ lightradiusfade 1500
+ lightcolor 100 20 20
+ // shockwave
+ effect nade_explode
+ type smoke
+ countabsolute 1
+ tex 33 33
+ size 32 32
+ sizeincrease 2200
+ color 0xff0000 0xffa2a2
+ alpha 80 80 650
+ velocitymultiplier 44
+ // fire
+ effect nade_explode
+ notunderwater
+ count 16
+ type smoke
+ color 0xFFFFFF 0xFFFFFF
+ tex 48 55
+ size 20 24
+ sizeincrease 555
+ alpha 400 656 2000
+ airfriction 30
+ originjitter 50 50 50
+ velocityjitter 320 320 320
+ rotate -180 180 -9 9
+ // fire streched
+ effect nade_explode
+ count 8
+ type spark
+ tex 48 55
+ color 0xFFFFFF 0xFFFFFF
+ size 60 90
+ alpha 1500 3000 13000
+ stretchfactor 80
+ sizeincrease 40
+ velocityjitter 30 30 30
+ airfriction -9
+ //smoke
+ effect nade_explode
+ type smoke
+ count 32
+ blend alpha
+ tex 0 7
+ size 60 30
+ color 0x222222 0x000000
+ alpha 128 328 390
+ rotate -180 180 2 -2
+ velocityjitter 200 200 200
+ velocityoffset 0 0 180
+ originjitter 50 50 10
+ sizeincrease 50
+ airfriction 0.04
+ gravity 0.4
+ // underwater bubbles
+ effect nade_explode
+ underwater
+ count 32
+ type bubble
+ tex 62 62
+ color 0x404040 0x808080
+ size 3 6
+ alpha 128 256 64
+ gravity -0.125
+ bounce 1.5
+ liquidfriction 0.25
+ originjitter 16 16 16
+ velocityjitter 196 196 196
+ rotate 0 0 0 0
+ // bouncing sparks
+ effect nade_explode
+ notunderwater
+ count 8
+ type spark
+ tex 40 40
+ color 0xff0000 0xffa2a2
+ size 1 2
+ alpha 644 956 484
+ gravity 1
+ airfriction 1
+ bounce 1.6
+ liquidfriction 0.8
+ velocityoffset 0 0 80
+ originjitter 16 16 16
+ velocityjitter 424 424 624
+ // notbouncing sparks
+ effect nade_explode
+ count 16
+ type spark
+ tex 40 40
+ color 0xff0000 0xffa2a2
+ size 1 2
+ alpha 644 956 684
+ gravity 0.5
+ airfriction 0.7
+ liquidfriction 0.8
+ velocityoffset 0 0 80
+ originjitter 16 16 16
+ velocityjitter 424 424 624
+ // derbis
+ effect nade_explode
+ notunderwater
+ count 8
+ type smoke
+ tex 71 73
+ color 0xff0000 0xffa2a2
+ size 20 40
+ alpha 644 956 2500
+ originjitter 64 64 64
+ velocityjitter 324 324 324
+ rotate -180 180 -100 100
++
 +// laser_shockwave_attack
 +// used nowhere in code
 +effect laser_shockwave_attack
 +// glow and light
 +//countabsolute 1
 +//type smoke
 +//color 0xcc0000 0xff0000
 +//tex 65 65
 +//size 10 15
 +//alpha 256 512 6280
 +//airfriction 10
 +//sizeincrease 1.5
 +//stretchfactor 2
 +//lightradius 200
 +//lightradiusfade 2000
 +//lightcolor 3 0.1 0.1
 +// electricity
 +effect laser_shockwave_attack
 +count 1
 +type spark
 +color 0xb44215 0xff0000
 +tex 43 43
 +size 5 7
 +bounce 0
 +alpha 4096 4096 20000
 +airfriction 1
 +originjitter 2 2 2
 +velocityjitter 10 10 10
 +velocitymultiplier 10
 +sizeincrease 1.5
 +stretchfactor 2.3
 +rotate -180 180 4000 -4000
 +// fire
 +effect laser_shockwave_attack
 +count 1
 +type spark
 +color 0xff4200 0xff0000
 +tex 8 15
 +size 7 9
 +bounce 0
 +alpha 4096 4096 20000
 +airfriction 1
 +originjitter 2 2 2
 +velocityjitter 10 10 10
 +velocitymultiplier 10
 +sizeincrease 1.5
 +stretchfactor 2
 +
 +// new_laser_impact
 +// used nowhere in code
 +// decal
 +effect new_laser_impact
 +countabsolute 1
 +type decal
 +tex 8 16
 +size 72 72
 +alpha 256 256 0
 +originjitter 2 2 2
 +// flare effect
 +//effect new_laser_impact
 +//countabsolute 1
 +//type static
 +//tex 39 39
 +//color 0xFF2010 0xFF2010
 +//alpha 256 256 1024
 +//size 24 24
 +// sparks that rapidly expand and rapidly slow down to form an interesting spherical effect
 +effect new_laser_impact
 +count 128
 +type spark
 +color 0x800000 0xFF8020
 +alpha 256 256 1024
 +size 4 4
 +bounce 1.5
 +gravity 0.5
 +airfriction 1
 +liquidfriction 1
 +originjitter 20 20 20
 +velocityjitter 256 256 256
Simple merge
@@@ -295,127 -295,10 +295,128 @@@ void Net_ReadNexgunBeamParticle(
        
        //draw either the old v2.3 beam or the new beam
        charge = sqrt(charge); // divide evenly among trail spacing and alpha
-       particles_alphamin = particles_alphamax = charge;
+       particles_alphamin = particles_alphamax = particles_fade = charge;
        if (autocvar_cl_particles_oldnexbeam && (getstati(STAT_ALLOW_OLDNEXBEAM) || isdemo()))
-               WarpZone_TrailParticles_WithMultiplier(world, particleeffectnum("TE_TEI_G3"), shotorg, endpos, charge, 1);
+               WarpZone_TrailParticles_WithMultiplier(world, particleeffectnum("TE_TEI_G3"), shotorg, endpos, 1, PARTICLES_USEALPHA | PARTICLES_USEFADE);
        else
-               WarpZone_TrailParticles_WithMultiplier(world, particleeffectnum("nex_beam"), shotorg, endpos, charge, 1);
+               WarpZone_TrailParticles_WithMultiplier(world, particleeffectnum("nex_beam"), shotorg, endpos, 1, PARTICLES_USEALPHA | PARTICLES_USEFADE);
  }
 +
 +.vector sw_shotorg;
 +.vector sw_endpos;
 +.float sw_spread_max;
 +.float sw_spread_min;
 +.float sw_time;
 +
 +void Draw_Shockwave()
 +{
 +      float a = bound(0, (0.5 - ((time - self.sw_time) / 0.4)), 0.5);
 +
 +      if not(a) { remove(self); }
 +      
 +      vector deviation, angle;
 +
 +      vector sw_color = getcsqcplayercolor(self.sv_entnum); // GetTeamRGB(GetPlayerColor(self.sv_entnum));
 +
 +      vector first_min_end = '0 0 0', prev_min_end = '0 0 0', new_min_end = '0 0 0';
 +      vector first_max_end = '0 0 0', prev_max_end = '0 0 0', new_max_end = '0 0 0';
 +
 +      float new_max_dist, new_min_dist;
 +      
 +      vector shotdir = normalize(self.sw_endpos - self.sw_shotorg);
 +      vectorvectors(shotdir);
 +      vector right = v_right;
 +      vector up = v_up;
 +      
 +      float counter, dist_before_normal = 200, shots = 20;
 +      
 +      vector min_end = ((self.sw_shotorg + (shotdir * dist_before_normal)) + (up * self.sw_spread_min));
 +      vector max_end = (self.sw_endpos + (up * self.sw_spread_max));
 +      
 +      float spread_to_min = vlen(normalize(min_end - self.sw_shotorg) - shotdir);
 +      float spread_to_max = vlen(normalize(max_end - min_end) - shotdir);
 +      
 +      for(counter = 0; counter < shots; ++counter)
 +      {
 +              // perfect circle effect lines
 +              angle = '0 0 0';
 +              makevectors('0 360 0' * (0.75 + (counter - 0.5) / shots));
 +              angle_y = v_forward_x;
 +              angle_z = v_forward_y;
 +
 +              // first do the spread_to_min effect
 +              deviation = angle * spread_to_min;
 +              deviation = ((shotdir + (right * deviation_y) + (up * deviation_z)));
 +              new_min_dist = dist_before_normal;
 +              new_min_end = (self.sw_shotorg + (deviation * new_min_dist));
 +              //te_lightning2(world, new_min_end, self.sw_shotorg);
 +
 +              // then calculate spread_to_max effect
 +              deviation = angle * spread_to_max;
 +              deviation = ((shotdir + (right * deviation_y) + (up * deviation_z)));
 +              new_max_dist = vlen(new_min_end - self.sw_endpos);
 +              new_max_end = (new_min_end + (deviation * new_max_dist));
 +              //te_lightning2(world, new_end, prev_min_end);
 +              
 +
 +              if(counter == 0)
 +              {
 +                      first_min_end = new_min_end;
 +                      first_max_end = new_max_end;
 +              }
 +
 +              if(counter >= 1)
 +              {
 +                      R_BeginPolygon("", DRAWFLAG_NORMAL);
 +                      R_PolygonVertex(prev_min_end, '0 0 0', sw_color, a);
 +                      R_PolygonVertex(new_min_end, '0 0 0', sw_color, a);
 +                      R_PolygonVertex(self.sw_shotorg, '0 0 0', sw_color, a);
 +                      R_EndPolygon();
 +
 +                      R_BeginPolygon("", DRAWFLAG_NORMAL);
 +                      R_PolygonVertex(new_min_end, '0 0 0', sw_color, a);
 +                      R_PolygonVertex(prev_min_end, '0 0 0', sw_color, a);
 +                      R_PolygonVertex(prev_max_end, '0 0 0', sw_color, a);
 +                      R_PolygonVertex(new_max_end, '0 0 0', sw_color, a);
 +                      R_EndPolygon();
 +              }
 +
 +              prev_min_end = new_min_end;
 +              prev_max_end = new_max_end;
 +
 +              if((counter + 1) == shots)
 +              {
 +                      R_BeginPolygon("", DRAWFLAG_NORMAL);
 +                      R_PolygonVertex(prev_min_end, '0 0 0', sw_color, a);
 +                      R_PolygonVertex(first_min_end, '0 0 0', sw_color, a);
 +                      R_PolygonVertex(self.sw_shotorg, '0 0 0', sw_color, a);
 +                      R_EndPolygon();
 +
 +                      R_BeginPolygon("", DRAWFLAG_NORMAL);
 +                      R_PolygonVertex(first_min_end, '0 0 0', sw_color, a);
 +                      R_PolygonVertex(prev_min_end, '0 0 0', sw_color, a);
 +                      R_PolygonVertex(prev_max_end, '0 0 0', sw_color, a);
 +                      R_PolygonVertex(first_max_end, '0 0 0', sw_color, a);
 +                      R_EndPolygon();
 +              }
 +      }
 +}
 +
 +void Net_ReadShockwaveParticle()
 +{
 +      entity shockwave;
 +      shockwave = spawn();
 +      shockwave.draw = Draw_Shockwave;
 +      
 +      shockwave.sw_shotorg_x = ReadCoord(); shockwave.sw_shotorg_y = ReadCoord(); shockwave.sw_shotorg_z = ReadCoord();
 +      shockwave.sw_endpos_x  = ReadCoord(); shockwave.sw_endpos_y  = ReadCoord(); shockwave.sw_endpos_z  = ReadCoord();
 +      
 +      shockwave.sw_spread_max = ReadByte();
 +      shockwave.sw_spread_min = ReadByte();
 +
 +      shockwave.sv_entnum = ReadByte();
 +
 +      shockwave.sw_time = time;
 +}
 +
index fb4fdd5,0000000..de45141
mode 100644,000000..100644
--- /dev/null
@@@ -1,470 -1,0 +1,535 @@@
-               particles_alphamin = particles_alphamax = sqrt(self.alpha);
-               boxparticles(self.traileffect, self, from, to, self.velocity, self.velocity, sqrt(self.alpha), PARTICLES_USEALPHA);
 +.vector iorigin1, iorigin2;
 +.float spawntime;
 +.vector trail_oldorigin;
 +.float trail_oldtime;
 +.float fade_time, fade_rate;
 +
 +void SUB_Stop()
 +{
 +      self.move_velocity = self.move_avelocity = '0 0 0';
 +      self.move_movetype = MOVETYPE_NONE;
 +}
 +
 +.float alphamod;
 +.float count; // set if clientside projectile
 +.float cnt; // sound index
 +.float gravity;
 +.float snd_looping;
 +.float silent;
 +
 +void Projectile_ResetTrail(vector to)
 +{
 +      self.trail_oldorigin = to;
 +      self.trail_oldtime = time;
 +}
 +
 +void Projectile_DrawTrail(vector to)
 +{
 +      vector from;
 +      float t0;
 +
 +      from = self.trail_oldorigin;
 +      t0 = self.trail_oldtime;
 +      self.trail_oldorigin = to;
 +      self.trail_oldtime = time;
 +
 +      // force the effect even for stationary firemine
 +      if(self.cnt == PROJECTILE_FIREMINE)
 +              if(from == to)
 +                      from_z += 1;
 +
 +      if (self.traileffect)
 +      {
++              particles_alphamin = particles_alphamax = particles_fade = sqrt(self.alpha);
++              boxparticles(self.traileffect, self, from, to, self.velocity, self.velocity, 1, PARTICLES_USEALPHA | PARTICLES_USEFADE | PARTICLES_DRAWASTRAIL);
 +      }
 +}
 +
 +void Projectile_Draw()
 +{
 +      vector rot;
 +      vector trailorigin;
 +      float f;
 +      float drawn;
 +      float t;
 +      float a;
 +
 +      f = self.move_flags;
 +
 +      if(self.count & 0x80)
 +      {
 +              //self.move_flags &~= FL_ONGROUND;
 +              if(self.move_movetype == MOVETYPE_NONE || self.move_movetype == MOVETYPE_FLY)
 +                      Movetype_Physics_NoMatchServer();
 +                      // the trivial movetypes do not have to match the
 +                      // server's ticrate as they are ticrate independent
 +                      // NOTE: this assumption is only true if MOVETYPE_FLY
 +                      // projectiles detonate on impact. If they continue
 +                      // moving, we might still be ticrate dependent.
 +              else
 +                      Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
 +              if(!(self.move_flags & FL_ONGROUND))
 +                      if(self.velocity != '0 0 0')
 +                              self.move_angles = self.angles = vectoangles(self.velocity);
 +      }
 +      else
 +      {
 +              InterpolateOrigin_Do();
 +      }
 +
 +      if(self.count & 0x80)
 +      {
 +              drawn = (time >= self.spawntime - 0.02);
 +              t = max(time, self.spawntime);
 +      }
 +      else
 +      {
 +              drawn = (self.iflags & IFLAG_VALID);
 +              t = time;
 +      }
 +
 +      if(!(f & FL_ONGROUND))
 +      {
 +              rot = '0 0 0';
 +              switch(self.cnt)
 +              {
 +                      /*
 +                      case PROJECTILE_GRENADE:
 +                              rot = '-2000 0 0'; // forward
 +                              break;
 +                      */
 +                      case PROJECTILE_GRENADE_BOUNCING:
 +                              rot = '0 -1000 0'; // sideways
 +                              break;
++                      case PROJECTILE_NADE_RED_BURN:
++                      case PROJECTILE_NADE_RED:
++                      case PROJECTILE_NADE_BLUE_BURN:
++                      case PROJECTILE_NADE_BLUE:
++                      case PROJECTILE_NADE_YELLOW_BURN:
++                      case PROJECTILE_NADE_YELLOW:
++                      case PROJECTILE_NADE_PINK_BURN:
++                      case PROJECTILE_NADE_PINK:
++                      case PROJECTILE_NADE_BURN:
++                      case PROJECTILE_NADE:
++                              rot = self.avelocity; 
++                              break;
 +                      case PROJECTILE_HOOKBOMB:
 +                              rot = '1000 0 0'; // forward
 +                              break;
 +                      default:
 +                              break;
 +              }
 +              self.angles = AnglesTransform_ToAngles(AnglesTransform_Multiply(AnglesTransform_FromAngles(self.angles), rot * (t - self.spawntime)));
 +      }
 +
 +      vector ang;
 +      ang = self.angles;
 +      ang_x = -ang_x;
 +      makevectors(ang);
 +
 +      a = 1 - (time - self.fade_time) * self.fade_rate;
 +      self.alpha = bound(0, self.alphamod * a, 1);
 +      if(self.alpha <= 0)
 +              drawn = 0;
 +      self.renderflags = 0;
 +
 +      trailorigin = self.origin;
 +      switch(self.cnt)
 +      {
++          case PROJECTILE_NADE_RED_BURN:
++              case PROJECTILE_NADE_RED:
++              case PROJECTILE_NADE_BLUE_BURN:
++              case PROJECTILE_NADE_BLUE:
++              case PROJECTILE_NADE_YELLOW_BURN:
++              case PROJECTILE_NADE_YELLOW:
++              case PROJECTILE_NADE_PINK_BURN:
++              case PROJECTILE_NADE_PINK:
++              case PROJECTILE_NADE_BURN:
++              case PROJECTILE_NADE:
++                      trailorigin += v_up * 4;
++                      break;
 +              case PROJECTILE_GRENADE:
 +              case PROJECTILE_GRENADE_BOUNCING:
 +                      trailorigin += v_right * 1 + v_forward * -10;
 +                      break;
 +              default:
 +                      break;
 +      }
 +      if(drawn)
 +              Projectile_DrawTrail(trailorigin);
 +      else
 +              Projectile_ResetTrail(trailorigin);
 +
 +      self.drawmask = 0;
 +
 +      if(!drawn)
 +              return;
 +
 +      switch(self.cnt)
 +      {
 +              case PROJECTILE_BULLET_GLOWING:
 +              case PROJECTILE_BULLET_GLOWING_TRACER:
 +                      adddynamiclight(self.origin, 50 * a, '1 1 0');
 +                      break;
 +              default:
 +                      break;
 +      }
 +
 +      self.drawmask = MASK_NORMAL;
 +}
 +
 +void loopsound(entity e, float ch, string samp, float vol, float attn)
 +{
 +      if(self.silent)
 +              return;
 +
 +      sound(e, ch, samp, vol, attn);
 +      e.snd_looping = ch;
 +}
 +
 +void Ent_RemoveProjectile()
 +{
 +      if(self.count & 0x80)
 +      {
 +              tracebox(self.origin, self.mins, self.maxs, self.origin + self.velocity * 0.05, MOVE_NORMAL, self);
 +              Projectile_DrawTrail(trace_endpos);
 +      }
 +}
 +
 +void Ent_Projectile()
 +{
 +      float f;
 +
 +      // projectile properties:
 +      //   kind (interpolated, or clientside)
 +      //
 +      //   modelindex
 +      //   origin
 +      //   scale
 +      //   if clientside:
 +      //     velocity
 +      //     gravity
 +      //   soundindex (hardcoded list)
 +      //   effects
 +      //
 +      // projectiles don't send angles, because they always follow the velocity
 +
 +      f = ReadByte();
 +      self.count = (f & 0x80);
 +      self.iflags = (self.iflags & IFLAG_INTERNALMASK) | IFLAG_AUTOANGLES | IFLAG_ANGLES | IFLAG_ORIGIN;
 +      self.solid = SOLID_TRIGGER;
 +      //self.effects = EF_NOMODELFLAGS;
 +
 +      // this should make collisions with bmodels more exact, but it leads to
 +      // projectiles no longer being able to lie on a bmodel
 +      self.move_nomonsters = MOVE_WORLDONLY;
 +      if(f & 0x40)
 +              self.move_flags |= FL_ONGROUND;
 +      else
 +              self.move_flags &~= FL_ONGROUND;
 +
 +      if(!self.move_time)
 +      {
 +              // for some unknown reason, we don't need to care for
 +              // sv_gameplayfix_delayprojectiles here.
 +              self.move_time = time;
 +              self.spawntime = time;
 +      }
 +      else
 +              self.move_time = max(self.move_time, time);
 +
 +      if(!(self.count & 0x80))
 +              InterpolateOrigin_Undo();
 +
 +      if(f & 1)
 +      {
 +              self.origin_x = ReadCoord();
 +              self.origin_y = ReadCoord();
 +              self.origin_z = ReadCoord();
 +              setorigin(self, self.origin);
 +              if(self.count & 0x80)
 +              {
 +                      self.velocity_x = ReadCoord();
 +                      self.velocity_y = ReadCoord();
 +                      self.velocity_z = ReadCoord();
 +                      if(f & 0x10)
 +                              self.gravity = ReadCoord();
 +                      else
 +                              self.gravity = 0; // none
 +                      self.move_origin = self.origin;
 +                      self.move_velocity = self.velocity;
 +              }
 +
 +              if(time == self.spawntime || (self.count & 0x80) || (f & 0x08))
 +              {
 +                      self.trail_oldorigin = self.origin;
 +                      if(!(self.count & 0x80))
 +                              InterpolateOrigin_Reset();
 +              }
 +
 +              if(f & 0x20)
 +              {
 +                      self.fade_time = time + ReadByte() * ticrate;
 +                      self.fade_rate = 1 / (ReadByte() * ticrate);
 +              }
 +              else
 +              {
 +                      self.fade_time = 0;
 +                      self.fade_rate = 0;
 +              }
 +      }
 +
 +      if(f & 2)
 +      {
 +              self.cnt = ReadByte();
 +
 +              self.silent = (self.cnt & 0x80);
 +              self.cnt = (self.cnt & 0x7F);
 +
 +              self.scale = 1;
 +              self.traileffect = 0;
 +              switch(self.cnt)
 +              {
 +                      case PROJECTILE_ELECTRO: setmodel(self, "models/ebomb.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break;
 +                      case PROJECTILE_ROCKET: setmodel(self, "models/rocket.md3");self.traileffect = particleeffectnum("TR_ROCKET"); self.scale = 2; break;
 +                      case PROJECTILE_BULLET: setmodel(self, "models/tracer.mdl");self.traileffect = particleeffectnum("tr_bullet"); break;
 +                      case PROJECTILE_BULLET_GLOWING: setmodel(self, "models/tracer.mdl");self.traileffect = particleeffectnum("tr_rifle_weak"); break;
 +                      case PROJECTILE_BULLET_GLOWING_TRACER: setmodel(self, "models/tracer.mdl");self.traileffect = particleeffectnum("tr_rifle"); break;
 +                      case PROJECTILE_CRYLINK: setmodel(self, "models/plasmatrail.mdl");self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break;
 +                      case PROJECTILE_CRYLINK_BOUNCING: setmodel(self, "models/plasmatrail.mdl");self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break;
 +                      case PROJECTILE_ELECTRO_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break;
 +                      case PROJECTILE_GRENADE: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break;
 +                      case PROJECTILE_GRENADE_BOUNCING: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break;
 +                      case PROJECTILE_MINE: setmodel(self, "models/mine.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break;
 +                      case PROJECTILE_LASER: setmodel(self, "models/laser.mdl");self.traileffect = particleeffectnum(""); break;
 +                      case PROJECTILE_HLAC: setmodel(self, "models/hlac_bullet.md3");self.traileffect = particleeffectnum(""); break;
 +                      case PROJECTILE_PORTO_RED: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_WIZSPIKE"); self.scale = 4; break;
 +                      case PROJECTILE_PORTO_BLUE: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_WIZSPIKE"); self.scale = 4; break;
 +                      case PROJECTILE_HOOKBOMB: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_KNIGHTSPIKE"); break;
 +                      case PROJECTILE_HAGAR: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum("tr_hagar"); self.scale = 0.75; break;
 +                      case PROJECTILE_HAGAR_BOUNCING: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum("tr_hagar"); self.scale = 0.75; break;
 +                      case PROJECTILE_FIREBALL: self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum("fireball"); break; // particle effect is good enough
 +                      case PROJECTILE_FIREMINE: self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum("firemine"); break; // particle effect is good enough
 +                      case PROJECTILE_TAG: setmodel(self, "models/laser.mdl"); self.traileffect = particleeffectnum("TR_ROCKET"); break;
 +                      case PROJECTILE_FLAC: setmodel(self, "models/hagarmissile.mdl"); self.scale = 0.4; self.traileffect = particleeffectnum("TR_SEEKER"); break;
 +                      case PROJECTILE_SEEKER: setmodel(self, "models/tagrocket.md3"); self.traileffect = particleeffectnum("TR_SEEKER"); break;
 +
 +                      case PROJECTILE_RAPTORBOMB:    setmodel(self, "models/vehicles/clusterbomb.md3"); self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = particleeffectnum(""); break;
 +                      case PROJECTILE_RAPTORBOMBLET: setmodel(self, "models/vehicles/bomblet.md3");     self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = particleeffectnum(""); break;
 +                      case PROJECTILE_RAPTORCANNON:  setmodel(self, "models/plasmatrail.mdl"); self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break;
 +
 +                      case PROJECTILE_SPIDERROCKET: setmodel(self, "models/vehicles/rocket02.md3"); self.traileffect = particleeffectnum("spiderbot_rocket_thrust"); break;
 +                      case PROJECTILE_WAKIROCKET:   setmodel(self, "models/vehicles/rocket01.md3");  self.traileffect = particleeffectnum("wakizashi_rocket_thrust"); break;
 +                      case PROJECTILE_WAKICANNON:   setmodel(self, "models/laser.mdl");  self.traileffect = particleeffectnum(""); break;
 +
 +                      case PROJECTILE_BUMBLE_GUN: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break;
 +                      case PROJECTILE_BUMBLE_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break;
++                      
++                      case PROJECTILE_NADE_RED: setmodel(self, "models/weapons/v_ok_grenade.md3");self.traileffect = particleeffectnum("nade_red"); break;
++                      case PROJECTILE_NADE_RED_BURN: setmodel(self, "models/weapons/v_ok_grenade.md3");self.traileffect = particleeffectnum("nade_red_burn"); break;
++                      case PROJECTILE_NADE_BLUE: setmodel(self, "models/weapons/v_ok_grenade.md3");self.traileffect = particleeffectnum("nade_blue"); break;
++                      case PROJECTILE_NADE_BLUE_BURN: setmodel(self, "models/weapons/v_ok_grenade.md3");self.traileffect = particleeffectnum("nade_blue_burn"); break;
++                      case PROJECTILE_NADE_YELLOW: setmodel(self, "models/weapons/v_ok_grenade.md3");self.traileffect = particleeffectnum("nade_yellow"); break;
++                      case PROJECTILE_NADE_YELLOW_BURN: setmodel(self, "models/weapons/v_ok_grenade.md3");self.traileffect = particleeffectnum("nade_yellow_burn"); break;
++                      case PROJECTILE_NADE_PINK: setmodel(self, "models/weapons/v_ok_grenade.md3");self.traileffect = particleeffectnum("nade_pink"); break;
++                      case PROJECTILE_NADE_PINK_BURN: setmodel(self, "models/weapons/v_ok_grenade.md3");self.traileffect = particleeffectnum("nade_pink_burn"); break;
++                      case PROJECTILE_NADE: setmodel(self, "models/weapons/v_ok_grenade.md3");self.traileffect = particleeffectnum("nade"); break;
++                      case PROJECTILE_NADE_BURN: setmodel(self, "models/weapons/v_ok_grenade.md3");self.traileffect = particleeffectnum("nade_burn"); break;
 +
 +                      default:
 +                              error("Received invalid CSQC projectile, can't work with this!");
 +                              break;
 +              }
 +
 +              self.mins = '0 0 0';
 +              self.maxs = '0 0 0';
 +              self.colormod = '0 0 0';
 +              self.move_touch = SUB_Stop;
 +              self.move_movetype = MOVETYPE_TOSS;
 +              self.alphamod = 1;
 +
 +              switch(self.cnt)
 +              {
 +                      case PROJECTILE_ELECTRO:
 +                              // only new engines support sound moving with object
 +                              loopsound(self, CH_SHOTS_SINGLE, "weapons/electro_fly.wav", VOL_BASE, ATTN_NORM);
 +                              self.mins = '0 0 -4';
 +                              self.maxs = '0 0 -4';
 +                              self.move_movetype = MOVETYPE_BOUNCE;
 +                              self.move_touch = func_null;
 +                              self.move_bounce_factor = g_balance_electro_secondary_bouncefactor;
 +                              self.move_bounce_stopspeed = g_balance_electro_secondary_bouncestop;
 +                              break;
 +                      case PROJECTILE_ROCKET:
 +                              loopsound(self, CH_SHOTS_SINGLE, "weapons/rocket_fly.wav", VOL_BASE, ATTN_NORM);
 +                              self.mins = '-3 -3 -3';
 +                              self.maxs = '3 3 3';
 +                              break;
 +                      case PROJECTILE_GRENADE:
 +                              self.mins = '-3 -3 -3';
 +                              self.maxs = '3 3 3';
 +                              break;
++                      case PROJECTILE_NADE_RED_BURN:
++                      case PROJECTILE_NADE_RED:
++                      case PROJECTILE_NADE_BLUE_BURN:
++                      case PROJECTILE_NADE_BLUE:
++                              self.mins = '-3 -3 -3';
++                              self.maxs = '3 3 3';
++                              self.move_movetype = MOVETYPE_BOUNCE;
++                              self.move_touch = func_null;
++                              self.scale = 1.5;
++                              self.avelocity = randomvec() * 720;
++                              break;
 +                      case PROJECTILE_GRENADE_BOUNCING:
 +                              self.mins = '-3 -3 -3';
 +                              self.maxs = '3 3 3';
 +                              self.move_movetype = MOVETYPE_BOUNCE;
 +                              self.move_touch = func_null;
 +                              self.move_bounce_factor = g_balance_grenadelauncher_bouncefactor;
 +                              self.move_bounce_stopspeed = g_balance_grenadelauncher_bouncestop;
 +                              break;
++                      case PROJECTILE_NADE_RED_BURN:
++                      case PROJECTILE_NADE_RED:
++                      case PROJECTILE_NADE_BLUE_BURN:
++                      case PROJECTILE_NADE_BLUE:
++                      case PROJECTILE_NADE_YELLOW_BURN:
++                      case PROJECTILE_NADE_YELLOW:
++                      case PROJECTILE_NADE_PINK_BURN:
++                      case PROJECTILE_NADE_PINK:
++                      case PROJECTILE_NADE_BURN:
++                      case PROJECTILE_NADE:
++                              self.mins = '-16 -16 -16';
++                              self.maxs = '16 16 16';
++                              self.move_movetype = MOVETYPE_BOUNCE;
++                              self.move_touch = func_null;
++                              self.scale = 1.5;
++                              self.avelocity = randomvec() * 720;
++                              break;
 +                      case PROJECTILE_MINE:
 +                              self.mins = '-4 -4 -4';
 +                              self.maxs = '4 4 4';
 +                              break;
 +                      case PROJECTILE_PORTO_RED:
 +                              self.colormod = '2 1 1';
 +                              self.alphamod = 0.5;
 +                              self.move_movetype = MOVETYPE_BOUNCE;
 +                              self.move_touch = func_null;
 +                              break;
 +                      case PROJECTILE_PORTO_BLUE:
 +                              self.colormod = '1 1 2';
 +                              self.alphamod = 0.5;
 +                              self.move_movetype = MOVETYPE_BOUNCE;
 +                              self.move_touch = func_null;
 +                              break;
 +                      case PROJECTILE_HAGAR_BOUNCING:
 +                              self.move_movetype = MOVETYPE_BOUNCE;
 +                              self.move_touch = func_null;
 +                              break;
 +                      case PROJECTILE_CRYLINK_BOUNCING:
 +                              self.move_movetype = MOVETYPE_BOUNCE;
 +                              self.move_touch = func_null;
 +                              break;
 +                      case PROJECTILE_FIREBALL:
 +                              loopsound(self, CH_SHOTS_SINGLE, "weapons/fireball_fly2.wav", VOL_BASE, ATTN_NORM);
 +                              self.mins = '-16 -16 -16';
 +                              self.maxs = '16 16 16';
 +                              break;
 +                      case PROJECTILE_FIREMINE:
 +                              loopsound(self, CH_SHOTS_SINGLE, "weapons/fireball_fly.wav", VOL_BASE, ATTN_NORM);
 +                              self.move_movetype = MOVETYPE_BOUNCE;
 +                              self.move_touch = func_null;
 +                              self.mins = '-4 -4 -4';
 +                              self.maxs = '4 4 4';
 +                              break;
 +                      case PROJECTILE_TAG:
 +                              self.mins = '-2 -2 -2';
 +                              self.maxs = '2 2 2';
 +                              break;
 +                      case PROJECTILE_FLAC:
 +                              self.mins = '-2 -2 -2';
 +                              self.maxs = '2 2 2';
 +                              break;
 +                      case PROJECTILE_SEEKER:
 +                              loopsound(self, CH_SHOTS_SINGLE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTN_NORM);
 +                              self.mins = '-4 -4 -4';
 +                              self.maxs = '4 4 4';
 +                              break;
 +            case PROJECTILE_RAPTORBOMB:
 +                              self.mins = '-3 -3 -3';
 +                              self.maxs = '3 3 3';
 +                              break;
 +            case PROJECTILE_RAPTORBOMBLET:
 +                              break;
 +            case PROJECTILE_RAPTORCANNON:
 +                              break;
 +            case PROJECTILE_SPIDERROCKET:
 +                loopsound(self, CH_SHOTS_SINGLE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTN_NORM);
 +                              break;
 +            case PROJECTILE_WAKIROCKET:
 +                loopsound(self, CH_SHOTS_SINGLE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTN_NORM);
 +                              break;            
 +            /*
 +            case PROJECTILE_WAKICANNON:
 +                              break;
 +                      case PROJECTILE_BUMBLE_GUN:
 +                              // only new engines support sound moving with object
 +                              loopsound(self, CH_SHOTS_SINGLE, "weapons/electro_fly.wav", VOL_BASE, ATTN_NORM);
 +                              self.mins = '0 0 -4';
 +                              self.maxs = '0 0 -4';
 +                              self.move_movetype = MOVETYPE_BOUNCE;
 +                              self.move_touch = func_null;
 +                              self.move_bounce_factor = g_balance_electro_secondary_bouncefactor;
 +                              self.move_bounce_stopspeed = g_balance_electro_secondary_bouncestop;
 +                              break;
 +                      */
 +                      default:
 +                              break;
 +              }
 +              setsize(self, self.mins, self.maxs);
 +      }
 +
 +      if(self.gravity)
 +      {
 +              if(self.move_movetype == MOVETYPE_FLY)
 +                      self.move_movetype = MOVETYPE_TOSS;
 +              if(self.move_movetype == MOVETYPE_BOUNCEMISSILE)
 +                      self.move_movetype = MOVETYPE_BOUNCE;
 +      }
 +      else
 +      {
 +              if(self.move_movetype == MOVETYPE_TOSS)
 +                      self.move_movetype = MOVETYPE_FLY;
 +              if(self.move_movetype == MOVETYPE_BOUNCE)
 +                      self.move_movetype = MOVETYPE_BOUNCEMISSILE;
 +      }
 +
 +      if(!(self.count & 0x80))
 +              InterpolateOrigin_Note();
 +
 +      self.draw = Projectile_Draw;
 +      self.entremove = Ent_RemoveProjectile;
 +}
 +
 +void Projectile_Precache()
 +{
 +      precache_model("models/ebomb.mdl");
 +      precache_model("models/elaser.mdl");
 +      precache_model("models/grenademodel.md3");
 +      precache_model("models/mine.md3");
 +      precache_model("models/hagarmissile.mdl");
 +      precache_model("models/hlac_bullet.md3");
 +      precache_model("models/laser.mdl");
 +      precache_model("models/plasmatrail.mdl");
 +      precache_model("models/rocket.md3");
 +      precache_model("models/tagrocket.md3");
 +      precache_model("models/tracer.mdl");
++      
++      precache_model("models/weapons/v_ok_grenade.md3");
 +
 +      precache_sound("weapons/electro_fly.wav");
 +      precache_sound("weapons/rocket_fly.wav");
 +      precache_sound("weapons/fireball_fly.wav");
 +      precache_sound("weapons/fireball_fly2.wav");
 +      precache_sound("weapons/tag_rocket_fly.wav");
 +
 +}
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 8373502,0000000..dda999a
mode 100644,000000..100644
--- /dev/null
@@@ -1,269 -1,0 +1,273 @@@
 +// switch between weapons
 +void Send_WeaponComplain(entity e, float wpn, string wpnname, float type)
 +{
 +      msg_entity = e;
 +      WriteByte(MSG_ONE, SVC_TEMPENTITY);
 +      WriteByte(MSG_ONE, TE_CSQC_WEAPONCOMPLAIN);
 +      WriteByte(MSG_ONE, wpn);
 +      WriteString(MSG_ONE, wpnname);
 +      WriteByte(MSG_ONE, type);
 +}
 +
 +float client_hasweapon(entity cl, float wpn, float andammo, float complain)
 +{
 +      float f;
 +      entity oldself;
 +
 +      if(time < self.hasweapon_complain_spam)
 +              complain = 0;
++
++      if(wpn == WEP_HOOK && !g_grappling_hook && autocvar_g_nades && !WEPSET_CONTAINS_EW(cl, wpn) && !WEPSET_CONTAINS_AW(weaponsInMap, wpn))
++              complain = 0;
++              
 +      if(complain)
 +              self.hasweapon_complain_spam = time + 0.2;
 +
 +      if (wpn < WEP_FIRST || wpn > WEP_LAST)
 +      {
 +              if (complain)
 +                      sprint(self, "Invalid weapon\n");
 +              return FALSE;
 +      }
 +      if (WEPSET_CONTAINS_EW(cl, wpn))
 +      {
 +              if (andammo)
 +              {
 +                      if(cl.items & IT_UNLIMITED_WEAPON_AMMO)
 +                      {
 +                              f = 1;
 +                      }
 +                      else
 +                      {
 +                              oldself = self;
 +                              self = cl;
 +                              f = WEP_ACTION(wpn, WR_CHECKAMMO1);
 +                              f = f + WEP_ACTION(wpn, WR_CHECKAMMO2);
 +
 +                              // always allow selecting the Mine Layer if we placed mines, so that we can detonate them
 +                              entity mine;
 +                              if(wpn == WEP_MINE_LAYER)
 +                              for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self)
 +                                      f = 1;
 +
 +                              self = oldself;
 +                      }
 +                      if (!f)
 +                      {
 +                              if (complain)
 +                              if(IS_REAL_CLIENT(cl))
 +                              {
 +                                      play2(cl, "weapons/unavailable.wav");
 +                                      Send_WeaponComplain (cl, wpn, W_Name(wpn), 0);
 +                              }
 +                              return FALSE;
 +                      }
 +              }
 +              return TRUE;
 +      }
 +      if (complain)
 +      {
 +              // DRESK - 3/16/07
 +              // Report Proper Weapon Status / Modified Weapon Ownership Message
 +              if (WEPSET_CONTAINS_AW(weaponsInMap, wpn))
 +              {
 +                      Send_WeaponComplain(cl, wpn, W_Name(wpn), 1);
 +
 +                      if(autocvar_g_showweaponspawns)
 +                      {
 +                              entity e;
 +                              string s;
 +
 +                              e = get_weaponinfo(wpn);
 +                              s = e.model2;
 +
 +                              for(e = world; (e = findfloat(e, weapon, wpn)); )
 +                              {
 +                                      if(e.classname == "droppedweapon")
 +                                              continue;
 +                                      if not(e.flags & FL_ITEM)
 +                                              continue;
 +                                      WaypointSprite_Spawn(
 +                                              s,
 +                                              1, 0,
 +                                              world, e.origin,
 +                                              self, 0,
 +                                              world, enemy,
 +                                              0,
 +                                              RADARICON_NONE, '0 0 0'
 +                                      );
 +                              }
 +                      }
 +              }
 +              else
 +              {
 +                      Send_WeaponComplain (cl, wpn, W_Name(wpn), 2);
 +              }
 +
 +              play2(cl, "weapons/unavailable.wav");
 +      }
 +      return FALSE;
 +}
 +
 +float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, float complain, float skipmissing)
 +{
 +      // We cannot tokenize in this function, as GiveItems calls this
 +      // function. Thus we must use car/cdr.
 +      float weaponwant, first_valid, prev_valid, switchtonext, switchtolast, c;
 +      string rest;
 +      switchtonext = switchtolast = 0;
 +      first_valid = prev_valid = 0;
 +      float weaponcur;
 +
 +      if(skipmissing || pl.selectweapon == 0)
 +              weaponcur = pl.switchweapon;
 +      else
 +              weaponcur = pl.selectweapon;
 +
 +      if(dir == 0)
 +              switchtonext = 1;
 +
 +      c = 0;
 +
 +      rest = weaponorder;
 +      while(rest != "")
 +      {
 +              weaponwant = stof(car(rest)); rest = cdr(rest);
 +              if(imp >= 0)
 +                      if((get_weaponinfo(weaponwant)).impulse != imp)
 +                              continue;
 +
 +              ++c;
 +
 +              if(!skipmissing || client_hasweapon(pl, weaponwant, TRUE, FALSE))
 +              {
 +                      if(switchtonext)
 +                              return weaponwant;
 +                      if(!first_valid)
 +                              first_valid = weaponwant;
 +                      if(weaponwant == weaponcur)
 +                      {
 +                              if(dir >= 0)
 +                                      switchtonext = 1;
 +                              else if(prev_valid)
 +                                      return prev_valid;
 +                              else
 +                                      switchtolast = 1;
 +                      }
 +                      prev_valid = weaponwant;
 +              }
 +      }
 +      if(first_valid)
 +      {
 +              if(switchtolast)
 +                      return prev_valid;
 +              else
 +                      return first_valid;
 +      }
 +      // complain (but only for one weapon on the button that has been pressed)
 +      if(complain)
 +      {
 +              self.weaponcomplainindex += 1;
 +              c = mod(self.weaponcomplainindex, c) + 1;
 +              rest = weaponorder;
 +              while(rest != "")
 +              {
 +                      weaponwant = stof(car(rest)); rest = cdr(rest);
 +                      if(imp >= 0)
 +                              if((get_weaponinfo(weaponwant)).impulse != imp)
 +                                      continue;
 +
 +                      --c;
 +                      if(c == 0)
 +                      {
 +                              client_hasweapon(pl, weaponwant, TRUE, TRUE);
 +                              break;
 +                      }
 +              }
 +      }
 +      return 0;
 +}
 +
 +void W_SwitchWeapon_Force(entity e, float w)
 +{
 +      e.cnt = e.switchweapon;
 +      e.switchweapon = w;
 +      e.selectweapon = w;
 +}
 +
 +// perform weapon to attack (weaponstate and attack_finished check is here)
 +void W_SwitchToOtherWeapon(entity pl)
 +{
 +      // hack to ensure it switches to an OTHER weapon (in case the other fire mode still has ammo, we want that anyway)
 +      float w, ww;
 +      w = pl.weapon;
 +      if(WEPSET_CONTAINS_EW(pl, w))
 +      {
 +              WEPSET_ANDNOT_EW(pl, w);
 +              ww = w_getbestweapon(pl);
 +              WEPSET_OR_EW(pl, w);
 +      }
 +      else
 +              ww = w_getbestweapon(pl);
 +      if(ww)
 +              W_SwitchWeapon_Force(pl, ww);
 +}
 +
 +void W_SwitchWeapon(float imp)
 +{
 +      if (self.switchweapon != imp)
 +      {
 +              if (client_hasweapon(self, imp, TRUE, TRUE))
 +                      W_SwitchWeapon_Force(self, imp);
 +              else
 +                      self.selectweapon = imp; // update selectweapon ANYWAY
 +      }
 +      else { WEP_ACTION(self.weapon, WR_RELOAD); }
 +}
 +
 +void W_CycleWeapon(string weaponorder, float dir)
 +{
 +      float w;
 +      w = W_GetCycleWeapon(self, weaponorder, dir, -1, 1, TRUE);
 +      if(w > 0)
 +              W_SwitchWeapon(w);
 +}
 +
 +void W_NextWeaponOnImpulse(float imp)
 +{
 +      float w;
 +      w = W_GetCycleWeapon(self, self.cvar_cl_weaponpriority, +1, imp, 1, (self.cvar_cl_weaponimpulsemode == 0));
 +      if(w > 0)
 +              W_SwitchWeapon(w);
 +}
 +
 +// next weapon
 +void W_NextWeapon(float list)
 +{
 +      if(list == 0)
 +              W_CycleWeapon(weaponorder_byid, -1);
 +      else if(list == 1)
 +              W_CycleWeapon(self.weaponorder_byimpulse, -1);
 +      else if(list == 2)
 +              W_CycleWeapon(self.cvar_cl_weaponpriority, -1);
 +}
 +
 +// prev weapon
 +void W_PreviousWeapon(float list)
 +{
 +      if(list == 0)
 +              W_CycleWeapon(weaponorder_byid, +1);
 +      else if(list == 1)
 +              W_CycleWeapon(self.weaponorder_byimpulse, +1);
 +      else if(list == 2)
 +              W_CycleWeapon(self.cvar_cl_weaponpriority, +1);
 +}
 +
 +// previously used if exists and has ammo, (second) best otherwise
 +void W_LastWeapon(void)
 +{
 +      if(client_hasweapon(self, self.cnt, TRUE, FALSE))
 +              W_SwitchWeapon(self.cnt);
 +      else
 +              W_SwitchToOtherWeapon(self);
 +}