set sv_jumpspeedcap_min "" "lower bound on the baseline velocity of a jump; final velocity will be >= (jumpheight * min + jumpheight)"
set sv_jumpspeedcap_max "" "upper bound on the baseline velocity of a jump; final velocity will be <= (jumpheight * max + jumpheight)"
set sv_jumpspeedcap_max_disable_on_ramps 0 "disable upper baseline velocity bound on ramps to preserve the old rampjump style"
+set sv_track_canjump 0 "track if the player released the jump key between 2 jumps to decide if they are able to jump or not"
seta sv_precacheplayermodels 1
seta sv_precacheweapons 0
gl_picmip_other 1 // so, picmip -1 is best possible quality
r_mipsprites 1
r_mipskins 1
+gl_max_lightmapsize 4096
r_shadow_realtime_world_lightmaps 1
r_shadow_realtime_world_importlightentitiesfrommap 0 // Whether build process uses keepLights is nontransparent and may change, so better make keepLights not matter.
cl_decals_fadetime 5
alias weapon_group_8 "impulse 8"
alias weapon_group_9 "impulse 9"
alias weapon_group_0 "impulse 14" // cycles the superweapons
+// TODO: remove after 0.8.2. Default impulse commands for 0.8.1 servers
exec weapons.cfg
// score log
-// item respawn effect
-// flare particle and light
-// used in qcsrc/server/bots.qc: //te_wizspike(e.origin)
-// used in qcsrc/server/bots.qc: //te_wizspike(e.nearestwaypoint.wpnearestpoint)
-// used in qcsrc/server/havocbot.qc: // te_wizspike(newgoal.origin)
+// ********************************************** //
+// ** WARNING - DO NOT MANUALLY EDIT THIS FILE ** //
+// ** ** //
+// ** This file is automatically generated by ** //
+// ** code with the command 'dumpeffectinfo'. ** //
+// ** ** //
+// ** If you modify an effect, please ** //
+// ** regenerate this file with that command. ** //
+// ** ** //
+// ********************************************** //
+
effect TE_WIZSPIKE
-countabsolute 1
-type static
-color 0x63F2EA 0x63f2EA
-size 20 20
-alpha 128 128 128
-lightradius 200
-lightradiusfade 200
-lightcolor 0.4 0.9 0.9
-// cloud of particles which expand rapidly and then slow to form a ball
+ type static
+ alpha 128 128 128
+ color 0x63F2EA 0x63f2EA
+ countabsolute 1
+ lightcolor 0.4 0.9 0.9
+ lightradiusfade 200
+ lightradius 200
+ size 20 20
effect TE_WIZSPIKE
-count 50
-type static
-color 0x63F2EA 0x63f2EA
-size 2 2
-alpha 64 64 64
-airfriction 2
-liquidfriction 2
-originjitter 16 16 16
-velocityjitter 32 32 32
-
-// laser impact
-// decal
-// used in qcsrc/server/w_seeker.qc: te_knightspike(org2)
+ type static
+ airfriction 2
+ alpha 64 64 64
+ color 0x63F2EA 0x63f2EA
+ count 50
+ liquidfriction 2
+ originjitter 16 16 16
+ size 2 2
+ velocityjitter 32 32 32
effect TE_KNIGHTSPIKE
-countabsolute 1
-type decal
-tex 47 47
-size 24 24
-alpha 256 256 0
-originjitter 16 16 16
-lightradius 200
-lightradiusfade 1000
-lightcolor 4 0.2 0.2
-// flare effect
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 4 0.2 0.2
+ lightradiusfade 1000
+ lightradius 200
+ originjitter 16 16 16
+ size 24 24
+ tex 47 47
effect TE_KNIGHTSPIKE
-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
+ type static
+ alpha 256 256 1024
+ color 0xFF2010 0xFF2010
+ countabsolute 1
+ size 24 24
+ tex 39 39
effect TE_KNIGHTSPIKE
-count 128
-type spark
-color 0x800000 0xFF8020
-alpha 256 256 1024
-size 4 4
-//bounce 1.5
-airfriction 6
-liquidfriction 6
-//originjitter 32 32 32
-velocityjitter 256 256 256
-
-// machinegun bullet impact
-// bullet impact decal
-// used nowhere in code
+ type spark
+ airfriction 6
+ alpha 256 256 1024
+ color 0x800000 0xFF8020
+ count 128
+ liquidfriction 6
+ size 4 4
+ velocityjitter 256 256 256
effect TE_SPIKE
-countabsolute 1
-type decal
-tex 56 59
-size 5 5
-alpha 256 256 0
-originjitter 6 6 6
-// dust/smoke drifting away from the impact
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ originjitter 6 6 6
+ size 5 5
+ tex 56 59
effect TE_SPIKE
-count 4
-type smoke
-tex 0 8
-color 0x101010 0x101010
-size 3 3
-sizeincrease 3
-alpha 255 255 256
-originjitter 0 0 0
-velocityjitter 8 8 8
-// dust/smoke staying at the impact
+ type smoke
+ alpha 255 255 256
+ color 0x101010 0x101010
+ count 4
+ sizeincrease 3
+ size 3 3
+ tex 0 8
+ velocityjitter 8 8 8
effect TE_SPIKE
-count 0.5
-type smoke
-tex 0 8
-color 0x505050 0x505050
-size 4 4
-sizeincrease 4
-alpha 255 255 128
-originjitter 0 0 0
-velocityjitter 0 0 0
-// bouncing sparks
+ type smoke
+ alpha 255 255 128
+ color 0x505050 0x505050
+ count 0.500000
+ sizeincrease 4
+ size 4 4
+ tex 0 8
effect TE_SPIKE
-count 10
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 0 256 256
-gravity 1
-bounce 1.5
-velocityoffset 0 0 80
-velocityjitter 64 64 64
-
-// electro combo explosion
-// decal
-// used nowhere in code
+ type spark
+ alpha 0 256 256
+ bounce 1.500000
+ color 0x8f4333 0xfff31b
+ count 10
+ gravity 1
+ size 0.400000 0.400000
+ velocityjitter 64 64 64
+ velocityoffset 0 0 80
effect TE_SPIKEQUAD
-countabsolute 1
-type decal
-tex 59 59
-size 64 64
-alpha 256 256 0
-originjitter 34 34 34
-lightradius 400
-lightradiusfade 200
-lightcolor 2 2.5 3
-// flare effect
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 2 2.5 3
+ lightradiusfade 200
+ lightradius 400
+ originjitter 34 34 34
+ size 64 64
+ tex 59 59
effect TE_SPIKEQUAD
-countabsolute 1
-type static
-tex 38 38
-color 0x80C0FF 0x80C0FF
-size 48 48
-alpha 256 256 128
-// large sparks
+ type static
+ alpha 256 256 128
+ color 0x80C0FF 0x80C0FF
+ countabsolute 1
+ size 48 48
+ tex 38 38
effect TE_SPIKEQUAD
-count 10
-type static
-color 0x2030FF 0x80C0FF
-size 32 32
-alpha 256 256 256
-//gravity 1
-bounce 1.5
-airfriction 4
-liquidfriction 16
-//velocityoffset 0 0 120
-velocityjitter 512 512 512
-
-// quake effect
-// decal
-// used nowhere in code
+ type static
+ airfriction 4
+ alpha 256 256 256
+ bounce 1.500000
+ color 0x2030FF 0x80C0FF
+ count 10
+ liquidfriction 16
+ size 32 32
+ velocityjitter 512 512 512
effect TE_SUPERSPIKE
-countabsolute 1
-type decal
-tex 56 59
-size 3 3
-alpha 256 256 0
-originjitter 6 6 6
-// dust/smoke drifting away from the impact
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ originjitter 6 6 6
+ size 3 3
+ tex 56 59
effect TE_SUPERSPIKE
-count 4
-type smoke
-tex 0 8
-color 0x101010 0x101010
-size 3 3
-sizeincrease 3
-alpha 255 255 256
-originjitter 0 0 0
-velocityjitter 8 8 8
-// dust/smoke staying at the impact
+ type smoke
+ alpha 255 255 256
+ color 0x101010 0x101010
+ count 4
+ sizeincrease 3
+ size 3 3
+ tex 0 8
+ velocityjitter 8 8 8
effect TE_SUPERSPIKE
-count 0.5
-type smoke
-tex 0 8
-color 0x505050 0x505050
-size 4 4
-sizeincrease 4
-alpha 255 255 128
-originjitter 0 0 0
-velocityjitter 0 0 0
-// sparks that disappear on impact
+ type smoke
+ alpha 255 255 128
+ color 0x505050 0x505050
+ count 0.500000
+ sizeincrease 4
+ size 4 4
+ tex 0 8
effect TE_SUPERSPIKE
-count 15
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 0 256 768
-gravity 1
-bounce -1
-velocityoffset 0 0 80
-velocityjitter 64 64 64
-
-// quake effect
-// decal
-// used nowhere in code
+ type spark
+ alpha 0 256 768
+ bounce -1
+ color 0x8f4333 0xfff31b
+ count 15
+ gravity 1
+ size 0.400000 0.400000
+ velocityjitter 64 64 64
+ velocityoffset 0 0 80
effect TE_SUPERSPIKEQUAD
-countabsolute 1
-type decal
-tex 56 59
-size 3 3
-alpha 256 256 0
-originjitter 6 6 6
-lightradius 100
-lightradiusfade 500
-lightcolor 0.15 0.15 1.5
-// dust/smoke drifting away from the impact
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 0.2 0.2 1.5
+ lightradiusfade 500
+ lightradius 100
+ originjitter 6 6 6
+ size 3 3
+ tex 56 59
effect TE_SUPERSPIKEQUAD
-count 4
-type smoke
-tex 0 8
-color 0x101010 0x101010
-size 3 3
-sizeincrease 3
-alpha 255 255 256
-originjitter 0 0 0
-velocityjitter 8 8 8
-// dust/smoke staying at the impact
+ type smoke
+ alpha 255 255 256
+ color 0x101010 0x101010
+ count 4
+ sizeincrease 3
+ size 3 3
+ tex 0 8
+ velocityjitter 8 8 8
effect TE_SUPERSPIKEQUAD
-count 0.5
-type smoke
-tex 0 8
-color 0x505050 0x505050
-size 4 4
-sizeincrease 4
-alpha 255 255 128
-originjitter 0 0 0
-velocityjitter 0 0 0
-// sparks that disappear on impact
+ type smoke
+ alpha 255 255 128
+ color 0x505050 0x505050
+ count 0.500000
+ sizeincrease 4
+ size 4 4
+ tex 0 8
effect TE_SUPERSPIKEQUAD
-count 15
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 0 256 768
-gravity 1
-bounce -1
-velocityoffset 0 0 80
-velocityjitter 64 64 64
-
-// shotgun pellet impact
-// decal
-// used nowhere in code
+ type spark
+ alpha 0 256 768
+ bounce -1
+ color 0x8f4333 0xfff31b
+ count 15
+ gravity 1
+ size 0.400000 0.400000
+ velocityjitter 64 64 64
+ velocityoffset 0 0 80
effect TE_GUNSHOT
-countabsolute 1
-type decal
-tex 56 59
-size 3 3
-alpha 256 256 0
-originjitter 6 6 6
-// dust/smoke drifting away from the impact
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ originjitter 6 6 6
+ size 3 3
+ tex 56 59
effect TE_GUNSHOT
-count 0.8
-type smoke
-tex 0 8
-color 0x101010 0x101010
-size 3 3
-sizeincrease 3
-alpha 128 128 64
-originjitter 0 0 0
-velocityjitter 8 8 8
-// dust/smoke staying at the impact
+ type smoke
+ alpha 128 128 64
+ color 0x101010 0x101010
+ count 0.800000
+ sizeincrease 3
+ size 3 3
+ tex 0 8
+ velocityjitter 8 8 8
effect TE_GUNSHOT
-count 0.2
-type smoke
-tex 0 8
-color 0x505050 0x505050
-size 4 4
-sizeincrease 4
-alpha 128 128 64
-originjitter 0 0 0
-velocityjitter 0 0 0
-// bouncing sparks
+ type smoke
+ alpha 128 128 64
+ color 0x505050 0x505050
+ count 0.200000
+ sizeincrease 4
+ size 4 4
+ tex 0 8
effect TE_GUNSHOT
-count 2.5
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 0 64 64
-gravity 1
-bounce 1.5
-velocityoffset 0 0 80
-velocityjitter 64 64 64
-
-// crylink impact effect
-// decal
-// used nowhere in code
+ type spark
+ alpha 0 64 64
+ bounce 1.500000
+ color 0x8f4333 0xfff31b
+ count 2.500000
+ gravity 1
+ size 0.400000 0.400000
+ velocityjitter 64 64 64
+ velocityoffset 0 0 80
effect TE_GUNSHOTQUAD
-countabsolute 1
-type decal
-tex 47 47
-size 8 8
-alpha 256 256 0
-originjitter 12 12 12
-//lightradius 100
-//lightradiusfade 300
-//lightcolor 0.5 0.5 0.5
-// purple flare effect
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ originjitter 12 12 12
+ size 8 8
+ tex 47 47
effect TE_GUNSHOTQUAD
-countabsolute 1
-type static
-tex 39 39
-color 0x504060 0x504060
-size 8 8
-alpha 256 256 512
-// purple sparks
+ type static
+ alpha 256 256 512
+ color 0x504060 0x504060
+ countabsolute 1
+ size 8 8
+ tex 39 39
effect TE_GUNSHOTQUAD
-count 6
-type spark
-color 0xA040C0 0xFFFFFF
-size 1 1
-alpha 128 128 384
-gravity 1
-bounce 1.5
-velocityoffset 0 0 80
-velocityjitter 128 128 128
-
-// mortar/hagar explosion (smaller than rocket)
-// decal
-// used in qcsrc/server/cl_client.qc: te_explosion(org)
+ type spark
+ alpha 128 128 384
+ bounce 1.500000
+ color 0xA040C0 0xFFFFFF
+ count 6
+ gravity 1
+ size 1 1
+ velocityjitter 128 128 128
+ velocityoffset 0 0 80
effect TE_EXPLOSION
-countabsolute 1
-type decal
-tex 8 16
-size 48 48
-alpha 256 256 0
-originjitter 40 40 40
-lightradius 150
-lightradiusfade 300
-lightcolor 4 2 0.5
-// flare effect
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 4 2 0.5
+ lightradiusfade 300
+ lightradius 150
+ originjitter 40 40 40
+ size 48 48
+ tex 8 16
effect TE_EXPLOSION
-countabsolute 1
-type static
-tex 35 37
-color 0x404040 0x404040
-size 48 48
-alpha 192 192 64
-// fire effect which expands then slows
+ type static
+ alpha 192 192 64
+ color 0x404040 0x404040
+ countabsolute 1
+ size 48 48
+ tex 35 37
effect TE_EXPLOSION
-notunderwater
-count 64
-type static
-tex 48 55
-color 0x902010 0xFFD080
-size 16 16
-alpha 128 128 256
-bounce 1.5
-airfriction 4
-liquidfriction 4
-originjitter 8 8 8
-velocityjitter 256 256 256
-// underwater bubbles
+ type static
+ airfriction 4
+ alpha 128 128 256
+ bounce 1.500000
+ color 0x902010 0xFFD080
+ count 64
+ liquidfriction 4
+ notunderwater
+ originjitter 8 8 8
+ size 16 16
+ tex 48 55
+ velocityjitter 256 256 256
effect TE_EXPLOSION
-underwater
-count 16
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 16 16 16
-velocityjitter 96 96 96
-// bouncing sparks
+ type bubble
+ alpha 128 256 64
+ bounce 1.500000
+ color 0x404040 0x808080
+ count 16
+ gravity -0.125000
+ liquidfriction 0.250000
+ originjitter 16 16 16
+ size 3 3
+ tex 62 62
+ underwater
+ velocityjitter 96 96 96
effect TE_EXPLOSION
-notunderwater
-count 16
-type spark
-color 0x903010 0xFFD030
-size 2 2
-alpha 256 256 384
-gravity 1
-airfriction 0.2
-bounce 1.5
-liquidfriction 0.8
-velocityoffset 0 0 80
-velocityjitter 256 256 256
-
-// quake effect
-// decal
-// used nowhere in code
+ type spark
+ airfriction 0.200000
+ alpha 256 256 384
+ bounce 1.500000
+ color 0x903010 0xFFD030
+ count 16
+ gravity 1
+ liquidfriction 0.800000
+ notunderwater
+ size 2 2
+ velocityjitter 256 256 256
+ velocityoffset 0 0 80
effect TE_EXPLOSIONQUAD
-countabsolute 1
-type decal
-tex 8 16
-size 48 48
-alpha 256 256 0
-originjitter 40 40 40
-lightradius 350
-lightradiusfade 700
-lightcolor 4 2 8
-// smoke cloud
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 4 2 8
+ lightradiusfade 700
+ lightradius 350
+ originjitter 40 40 40
+ size 48 48
+ tex 8 16
effect TE_EXPLOSIONQUAD
-notunderwater
-count 16
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 12 12
-alpha 32 32 64
-velocityjitter 48 48 48
-// underwater bubbles
+ type smoke
+ alpha 32 32 64
+ color 0x202020 0x404040
+ count 16
+ notunderwater
+ size 12 12
+ tex 0 8
+ velocityjitter 48 48 48
effect TE_EXPLOSIONQUAD
-underwater
-count 16
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 16 16 16
-velocityjitter 96 96 96
-// sparks which go through walls
+ type bubble
+ alpha 128 256 64
+ bounce 1.500000
+ color 0x404040 0x808080
+ count 16
+ gravity -0.125000
+ liquidfriction 0.250000
+ originjitter 16 16 16
+ size 3 3
+ tex 62 62
+ underwater
+ velocityjitter 96 96 96
effect TE_EXPLOSIONQUAD
-notunderwater
-count 64
-type spark
-color 0x903010 0xFFD030
-size 1 1
-alpha 0 256 512
-gravity 1
-airfriction 0.2
-liquidfriction 0.8
-velocityoffset 0 0 80
-velocityjitter 256 256 256
-
-// quake effect
-// decal
-// used in qcsrc/server/keyhunt.qc: te_tarexplosion(lostkey.origin)
+ type spark
+ airfriction 0.200000
+ alpha 0 256 512
+ color 0x903010 0xFFD030
+ count 64
+ gravity 1
+ liquidfriction 0.800000
+ notunderwater
+ size 1 1
+ velocityjitter 256 256 256
+ velocityoffset 0 0 80
effect TE_TAREXPLOSION
-countabsolute 1
-type decal
-tex 8 16
-size 48 48
-alpha 256 256 0
-originjitter 40 40 40
-lightradius 600
-lightradiusfade 1200
-lightcolor 1.6 0.8 2
-// smoke cloud
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 1.6 0.8 2
+ lightradiusfade 1200
+ lightradius 600
+ originjitter 40 40 40
+ size 48 48
+ tex 8 16
effect TE_TAREXPLOSION
-notunderwater
-count 16
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 12 12
-alpha 32 32 64
-velocityjitter 48 48 48
-// underwater bubbles
+ type smoke
+ alpha 32 32 64
+ color 0x202020 0x404040
+ count 16
+ notunderwater
+ size 12 12
+ tex 0 8
+ velocityjitter 48 48 48
effect TE_TAREXPLOSION
-underwater
-count 16
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 16 16 16
-velocityjitter 96 96 96
-// sparks which go through walls
+ type bubble
+ alpha 128 256 64
+ bounce 1.500000
+ color 0x404040 0x808080
+ count 16
+ gravity -0.125000
+ liquidfriction 0.250000
+ originjitter 16 16 16
+ size 3 3
+ tex 62 62
+ underwater
+ velocityjitter 96 96 96
effect TE_TAREXPLOSION
-notunderwater
-count 64
-type spark
-color 0x903010 0xFFD030
-size 1 1
-alpha 0 256 512
-gravity 1
-airfriction 0.2
-liquidfriction 0.8
-velocityoffset 0 0 80
-velocityjitter 256 256 256
-
-// bloody impact effect indicating damage
-// used nowhere in code
+ type spark
+ airfriction 0.200000
+ alpha 0 256 512
+ color 0x903010 0xFFD030
+ count 64
+ gravity 1
+ liquidfriction 0.800000
+ notunderwater
+ size 1 1
+ velocityjitter 256 256 256
+ velocityoffset 0 0 80
effect TE_BLOOD
-count 0.167
-type blood
-tex 24 32
-size 8 8
-alpha 256 256 64
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 64 64 64
-velocitymultiplier 1
-staincolor 0x808080 0x808080
-staintex 16 24
-
-
-
-// sparks (quake effect)
-// used in qcsrc/server/antilag.qc: te_spark(antilag_takebackorigin(e, time - e.antilag_debug), '0 0 0', 32)
-// used in qcsrc/server/g_triggers.qc: self.mdl = "TE_SPARK"
+ type blood
+ airfriction 1
+ alpha 256 256 64
+ bounce -1
+ count 0.167000
+ liquidfriction 4
+ size 8 8
+ staincolor 0x808080 0x808080
+ staintex 16 24
+ tex 24 32
+ velocityjitter 64 64 64
+ velocitymultiplier 1
effect TE_SPARK
-count 0.5
-type spark
-tex 40 40
-color 0x8f4333 0xfff31b
-size 0.4 0.6
-alpha 64 256 768
-gravity 1
-bounce -1
-velocityoffset 0 0 80
-velocityjitter 64 64 64
-velocitymultiplier 1
-
-// nex impact
-// decal
-// used in qcsrc/server/bots.qc: te_plasmaburn(org)
+ type spark
+ alpha 64 256 768
+ bounce -1
+ color 0x8f4333 0xfff31b
+ count 0.500000
+ gravity 1
+ size 0.400000 0.600000
+ tex 40 40
+ velocityjitter 64 64 64
+ velocitymultiplier 1
+ velocityoffset 0 0 80
effect TE_PLASMABURN
-countabsolute 1
-type decal
-tex 47 47
-size 24 24
-alpha 256 256 0
-originjitter 16 16 16
-lightradius 200
-lightradiusfade 400
-lightcolor 1 1 1
-// flare effect
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 1 1 1
+ lightradiusfade 400
+ lightradius 200
+ originjitter 16 16 16
+ size 24 24
+ tex 47 47
effect TE_PLASMABURN
-countabsolute 1
-type static
-tex 37 37
-color 0x80C0FF 0x80C0FF
-size 8 8
-alpha 256 256 512
-// small sparks which form a sphere as they slow down
+ type static
+ alpha 256 256 512
+ color 0x80C0FF 0x80C0FF
+ countabsolute 1
+ size 8 8
+ tex 37 37
effect TE_PLASMABURN
-count 128
-type spark
-color 0x2030FF 0x80C0FF
-size 1 2
-alpha 256 256 1024
-bounce 2
-airfriction 8
-liquidfriction 8
-velocityjitter 128 128 128
-
-// quake effect
-// used in qcsrc/server/bots.qc: //te_smallflash((e.absmin + e.absmax) * 0.5)
-// used in qcsrc/server/bots.qc: //te_smallflash((e.absmin + e.absmax) * 0.5)
+ type spark
+ airfriction 8
+ alpha 256 256 1024
+ bounce 2
+ color 0x2030FF 0x80C0FF
+ count 128
+ liquidfriction 8
+ size 1 2
+ velocityjitter 128 128 128
effect TE_SMALLFLASH
-lightradius 200
-lightradiusfade 1000
-lightcolor 2 2 2
-
-// quake effect
-// used nowhere in code
+ lightcolor 2 2 2
+ lightradiusfade 1000
+ lightradius 200
effect TE_FLAMEJET
-count 0.5
-type smoke
-color 0x6f0f00 0xe3974f
-size 4 4
-alpha 64 128 384
-gravity -1
-bounce 1.1
-airfriction 1
-liquidfriction 4
-velocityjitter 128 128 128
-velocitymultiplier 1
-
-// quake effect
-// used nowhere in code
+ type smoke
+ airfriction 1
+ alpha 64 128 384
+ bounce 1.100000
+ color 0x6f0f00 0xe3974f
+ count 0.500000
+ gravity -1
+ liquidfriction 4
+ size 4 4
+ velocityjitter 128 128 128
+ velocitymultiplier 1
effect TE_LAVASPLASH
-count 32
-type alphastatic
-color 0x6f0f00 0xe3974f
-size 12 12
-alpha 256 256 256
-gravity 0.05
-originoffset 0 0 32
-originjitter 128 128 32
-velocityoffset 0 0 256
-velocityjitter 128 128 0
-
-// player teleport effect
-// used nowhere in code
+ type alphastatic
+ alpha 256 256 256
+ color 0x6f0f00 0xe3974f
+ count 32
+ gravity 0.050000
+ originjitter 128 128 32
+ originoffset 0 0 32
+ size 12 12
+ velocityjitter 128 128 0
+ velocityoffset 0 0 256
effect TE_TELEPORT
-count 56
-type static
-color 0xA0A0A0 0xFFFFFF
-size 10 10
-alpha 64 128 256
-airfriction 1
-liquidfriction 4
-originoffset 0 0 28
-originjitter 16 16 28
-velocityjitter 0 0 256
-
-// nex beam
-// used in qcsrc/server/w_minstanex.qc: trailparticles(world, particleeffectnum("TE_TEI_G3"), w_shotorg, trace_endpos)
-// used in qcsrc/client/particles.qc: trailparticles(world, particleeffectnum("TE_TEI_G3"), shotorg, endpos)
+ type static
+ airfriction 1
+ alpha 64 128 256
+ color 0xA0A0A0 0xFFFFFF
+ count 56
+ liquidfriction 4
+ originjitter 16 16 28
+ originoffset 0 0 28
+ size 10 10
+ velocityjitter 0 0 256
effect TE_TEI_G3
-countabsolute 1
-type beam
-tex 200 200
-color 0xFFFFFF 0xFFFFFF
-size 4 4
-alpha 128 128 256
-// experimental
+ type beam
+ alpha 128 128 256
+ color 0xFFFFFF 0xFFFFFF
+ countabsolute 1
+ size 4 4
+ tex 200 200
effect TE_TEI_G3
-trailspacing 4
-type static
-color 0x202020 0x404040
-size 1 1
-alpha 256 256 512
-airfriction -4
-//liquidfriction -4
-velocityjitter 8 8 8
-type smoke
-
-// smoke effect
-// used nowhere in code
+ type smoke
+ airfriction -4
+ alpha 256 256 512
+ color 0x202020 0x404040
+ size 1 1
+ trailspacing 4
+ velocityjitter 8 8 8
effect TE_TEI_SMOKE
-count 0.167
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 5 5
-alpha 256 256 512
-originjitter 1.5 1.5 1.5
-velocityjitter 6 6 6
-velocitymultiplier 1
-
-// rocket explosion (bigger than mortar and hagar)
-// decal
-// used nowhere in code
+ type smoke
+ alpha 256 256 512
+ color 0x202020 0x404040
+ count 0.167000
+ originjitter 1.5 1.5 1.5
+ size 5 5
+ tex 0 8
+ velocityjitter 6 6 6
+ velocitymultiplier 1
effect TE_TEI_BIGEXPLOSION
-countabsolute 1
-type decal
-tex 8 16
-size 72 72
-alpha 256 256 0
-originjitter 40 40 40
-lightradius 500
-lightradiusfade 500
-lightcolor 4 2 0.5
-// flare effect
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 4 2 0.5
+ lightradiusfade 500
+ lightradius 500
+ originjitter 40 40 40
+ size 72 72
+ tex 8 16
effect TE_TEI_BIGEXPLOSION
-countabsolute 1
-type static
-tex 35 37
-color 0x404040 0x404040
-size 72 72
-alpha 192 192 64
-// fire effect
+ type static
+ alpha 192 192 64
+ color 0x404040 0x404040
+ countabsolute 1
+ size 72 72
+ tex 35 37
effect TE_TEI_BIGEXPLOSION
-notunderwater
-count 128
-type static
-tex 48 55
-color 0x902010 0xFFD080
-size 16 16
-alpha 128 128 256
-bounce 1.5
-airfriction 4
-liquidfriction 4
-originjitter 8 8 8
-velocityjitter 512 512 512
-// underwater bubbles
+ type static
+ airfriction 4
+ alpha 128 128 256
+ bounce 1.500000
+ color 0x902010 0xFFD080
+ count 128
+ liquidfriction 4
+ notunderwater
+ originjitter 8 8 8
+ size 16 16
+ tex 48 55
+ velocityjitter 512 512 512
effect TE_TEI_BIGEXPLOSION
-underwater
-count 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 16 16 16
-velocityjitter 144 144 144
-// bouncing sparks
+ type bubble
+ alpha 128 256 64
+ bounce 1.500000
+ color 0x404040 0x808080
+ count 32
+ gravity -0.125000
+ liquidfriction 0.250000
+ originjitter 16 16 16
+ size 3 3
+ tex 62 62
+ underwater
+ velocityjitter 144 144 144
effect TE_TEI_BIGEXPLOSION
-notunderwater
-count 64
-type spark
-color 0x903010 0xFFD030
-size 2 2
-alpha 256 256 384
-gravity 1
-airfriction 0.2
-bounce 1.5
-liquidfriction 0.8
-velocityoffset 0 0 80
-velocityjitter 384 384 384
-
-// electro explosion
-// decal
-// used nowhere in code
+ type spark
+ airfriction 0.200000
+ alpha 256 256 384
+ bounce 1.500000
+ color 0x903010 0xFFD030
+ count 64
+ gravity 1
+ liquidfriction 0.800000
+ notunderwater
+ size 2 2
+ velocityjitter 384 384 384
+ velocityoffset 0 0 80
effect TE_TEI_PLASMAHIT
-countabsolute 1
-type decal
-tex 59 59
-size 32 32
-alpha 256 256 0
-originjitter 20 20 20
-lightradius 200
-lightradiusfade 600
-lightcolor 2.4 4.8 8
-// flare effect
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 2.4 4.8 8
+ lightradiusfade 600
+ lightradius 200
+ originjitter 20 20 20
+ size 32 32
+ tex 59 59
effect TE_TEI_PLASMAHIT
-countabsolute 1
-type static
-tex 38 38
-color 0x80C0FF 0x80C0FF
-size 32 32
-alpha 256 256 512
-// cloud of bouncing sparks
+ type static
+ alpha 256 256 512
+ color 0x80C0FF 0x80C0FF
+ countabsolute 1
+ size 32 32
+ tex 38 38
effect TE_TEI_PLASMAHIT
-count 0.5
-type spark
-color 0x2030FF 0x80C0FF
-size 2 4
-alpha 256 256 1024
-//gravity 1
-bounce 1.5
-//velocityoffset 0 0 120
-velocityjitter 512 512 512
-
-
-
-
-
-
-
-
-
-//////////////////////////////////////////////////
-// New effects in 2.4
-//////////////////////////////////////////////////
-
-
-
-// bloody impact effect indicating damage
-// used in qcsrc/client/gibs.qc: pointparticles(particleeffectnum("blood"), self.origin + '0 0 1', '0 0 30', 10)
-// used in qcsrc/client/gibs.qc: pointparticles(particleeffectnum("blood"), org, vel, amount * 16)
+ type spark
+ alpha 256 256 1024
+ bounce 1.500000
+ color 0x2030FF 0x80C0FF
+ count 0.500000
+ size 2 4
+ velocityjitter 512 512 512
effect blood
-count 0.4
-type spark
-blend invmod
-tex 24 32
-size 5 11
-alpha 1560 2560 7000
-color 0xA8FFFF 0xA8FFFFF
-bounce -1
-airfriction 0.4
-velocityjitter 99 99 55
-//velocitymultiplier 2
-staincolor 0x808080 0x808080
-staintex 16 24
-stainsize 1 2
-stretchfactor 20
-sizeincrease 20
-//blood mist
+ type spark
+ airfriction 0.400000
+ alpha 1560 2560 7000
+ blend invmod
+ bounce -1
+ color 0xA8FFFF 0xA8FFFFF
+ count 0.400000
+ sizeincrease 20
+ size 5 11
+ staincolor 0x808080 0x808080
+ stainsize 1 2
+ staintex 16 24
+ stretchfactor 20
+ tex 24 32
+ velocityjitter 99 99 55
effect blood
-countabsolute 1
-type alphastatic
-blend invmod
-tex 24 32
-size 25 30
-sizeincrease 20
-alpha 100 256 400
-color 0x000000 0x420000
-originjitter 11 11 11
-
-
-// player teleport effect
-// used in qcsrc/server/t_teleporters.qc: pointparticles(particleeffectnum("teleport"), player.origin, '0 0 0', 1)
-// used in qcsrc/server/t_teleporters.qc: pointparticles(particleeffectnum("teleport"), to + v_forward * 32, '0 0 0', 1)
+ type alphastatic
+ alpha 100 256 400
+ blend invmod
+ color 0x000000 0x420000
+ countabsolute 1
+ originjitter 11 11 11
+ sizeincrease 20
+ size 25 30
+ tex 24 32
effect teleport
-count 500
-type spark
-tex 64 64
-color 0x807aff 0x4463d5
-size 1 1
-alpha 0 256 100
-stretchfactor 2
-//gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 1000 1000 1500
-velocitymultiplier 0.5
-airfriction 2
-stretchfactor 0.6
+ type spark
+ airfriction 2
+ alpha 0 256 100
+ bounce 1.500000
+ color 0x807aff 0x4463d5
+ count 500
+ originjitter 1 1 1
+ size 1 1
+ stretchfactor 0.600000
+ tex 64 64
+ velocityjitter 1000 1000 1500
+ velocitymultiplier 0.500000
effect teleport
-countabsolute 1
-type smoke
-tex 65 65
-size 150 150
-alpha 190 190 180
-sizeincrease -80
-color 0x807aff 0x4463d5
-
-
-
-// normal super gory blood trail (used by gibs)
-// used in qcsrc/client/gibs.qc: trailparticles(self, particleeffectnum("TR_BLOOD"), oldorg, self.origin)
+ type smoke
+ alpha 190 190 180
+ color 0x807aff 0x4463d5
+ countabsolute 1
+ sizeincrease -80
+ size 150 150
+ tex 65 65
effect TR_BLOOD
-trailspacing 20
-type spark
-blend invmod
-color 0xA8FFFF 0xA8FFFF
-tex 24 32
-size 4 19
-alpha 384 984 1492
-bounce -1
-gravity 0.4
-airfriction -2
-liquidfriction 1
-velocityjitter 64 64 64
-velocitymultiplier -0.1
-staincolor 0x808080 0x808080
-staintex 16 24
-stainsize 1 2
-stretchfactor 7
-sizeincrease -5
-// splash around gib
+ type spark
+ airfriction -2
+ alpha 384 984 1492
+ blend invmod
+ bounce -1
+ color 0xA8FFFF 0xA8FFFF
+ gravity 0.400000
+ liquidfriction 1
+ sizeincrease -5
+ size 4 19
+ staincolor 0x808080 0x808080
+ stainsize 1 2
+ staintex 16 24
+ stretchfactor 7
+ tex 24 32
+ trailspacing 20
+ velocityjitter 64 64 64
+ velocitymultiplier -0.100000
effect TR_BLOOD
-trailspacing 42
-type blood
-color 0xA8FFFF 0xA8FFFF
-tex 24 32
-size 4 6
-alpha 684 684 7492
-sizeincrease 500
-
-// thinner blood trail (used by quake zombies)
-// used in qcsrc/client/gibs.qc: trailparticles(self, particleeffectnum("TR_SLIGHTBLOOD"), oldorg, self.origin)
+ type blood
+ alpha 684 684 7492
+ color 0xA8FFFF 0xA8FFFF
+ sizeincrease 500
+ size 4 6
+ tex 24 32
+ trailspacing 42
+effect TR_BLOOD
+ type blood
+ alpha 684 684 7492
+ color 0xA8FFFF 0xA8FFFF
+ sizeincrease 500
+ size 4 6
+ tex 24 32
+ trailspacing 42
effect TR_SLIGHTBLOOD
-trailspacing 64
-type blood
-color 0xA8FFFF 0xA8FFFF
-tex 24 32
-size 8 8
-alpha 384 384 192
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 64 64 64
-velocitymultiplier 0.5
-staincolor 0x808080 0x808080
-staintex 16 24
-
-
-
-// func_stardust effect, used in some maps to indicate teleporters
-// used in qcsrc/server/g_triggers.qc: self.effects = EF_STARDUST
-// used in qcsrc/server/portals.qc: portal.effects = EF_STARDUST | EF_BLUE
+ type blood
+ airfriction 1
+ alpha 384 384 192
+ bounce -1
+ color 0xA8FFFF 0xA8FFFF
+ liquidfriction 4
+ size 8 8
+ staincolor 0x808080 0x808080
+ staintex 16 24
+ tex 24 32
+ trailspacing 64
+ velocityjitter 64 64 64
+ velocitymultiplier 0.500000
effect EF_STARDUST
-count 37.5
-type static
-color 0xfff368 0xfff368
-size 1.0 2.0
-alpha 64 128 128
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 16 16 64
-velocityjitter 32 32 0
-//lightradius 200
-//lighttime 0
-//lightcolor 0.4 0.9 0.9
-
-// flare particle and light
-// used in qcsrc/server/t_items.qc: //pointparticles(particleeffectnum("item_respawn"), self.origin + self.mins_z * '0 0 1' + '0 0 48', '0 0 0', 1)
-// used in qcsrc/server/t_items.qc: pointparticles(particleeffectnum("item_respawn"), self.origin + 0.5 * (self.mins + self.maxs), '0 0 0', 1)
+ type static
+ airfriction 0.200000
+ alpha 64 128 128
+ color 0xfff368 0xfff368
+ count 37.500000
+ gravity -0.100000
+ liquidfriction 0.800000
+ originjitter 16 16 64
+ size 1 2
+ velocityjitter 32 32 0
effect item_respawn
-countabsolute 1
-type static
-color 0x63F2EA 0x63f2EA
-size 32 32
-alpha 128 128 128
-// cloud of particles which expand rapidly and then slow to form a ball
+ type static
+ alpha 128 128 128
+ color 0x63F2EA 0x63f2EA
+ countabsolute 1
+ size 32 32
effect item_respawn
-count 128
-type spark
-tex 41 41
-color 0x63F2EA 0x63f2EA
-size 2 2
-alpha 256 256 1280
-//originjitter 24 24 24
-velocityjitter 256 256 256
-
-
-
-// used in qcsrc/server/t_jumppads.qc: pointparticles(particleeffectnum("jumppad_activate"), other.origin, other.velocity, 1)
+ type spark
+ alpha 256 256 1280
+ color 0x63F2EA 0x63f2EA
+ count 128
+ size 2 2
+ tex 41 41
+ velocityjitter 256 256 256
effect jumppad_activate
-lightradius 200
-lightradiusfade 2000
-lightcolor 2 2 2
-
-
-
-// used in qcsrc/server/w_hlac.qc: pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
-// used in qcsrc/server/w_hlac.qc: pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
-// used in qcsrc/server/w_laser.qc: pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
+ lightcolor 2 2 2
+ lightradiusfade 2000
+ lightradius 200
effect laser_muzzleflash
-// glow and light
-countabsolute 1
-type smoke
-color 0xcc0000 0xff0000
-tex 65 65
-size 10 15
-alpha 256 512 6280
-airfriction 10
-sizeincrease -100
-stretchfactor 2
-lightradius 200
-lightradiusfade 2000
-lightcolor 3 0.1 0.1
-// electricity
+ type smoke
+ airfriction 10
+ alpha 256 512 6280
+ color 0xcc0000 0xff0000
+ countabsolute 1
+ lightcolor 3 0.1 0.1
+ lightradiusfade 2000
+ lightradius 200
+ sizeincrease -100
+ size 10 15
+ stretchfactor 2
+ tex 65 65
effect laser_muzzleflash
-count 3
-type spark
-color 0xb44215 0xff0000
-tex 43 43
-size 5 7
-alpha 256 512 6280
-airfriction 10
-originjitter 2 2 2
-velocityjitter 150 150 150
-velocitymultiplier 0.2
-sizeincrease -100
-stretchfactor 2.3
-rotate -180 180 4000 -4000
-// fire
+ type spark
+ airfriction 10
+ alpha 256 512 6280
+ color 0xb44215 0xff0000
+ count 3
+ originjitter 2 2 2
+ rotate -180 180 4000 -4000
+ sizeincrease -100
+ size 5 7
+ stretchfactor 2.300000
+ tex 43 43
+ velocityjitter 150 150 150
+ velocitymultiplier 0.200000
effect laser_muzzleflash
-count 6
-type spark
-color 0xff4200 0xff0000
-tex 8 15
-size 7 9
-alpha 256 512 6280
-airfriction 12
-originjitter 2 2 2
-velocityjitter 100 100 100
-velocitymultiplier 0.2
-sizeincrease -100
-stretchfactor 2
-
-
-// decal
-// used in qcsrc/client/damage.qc: pointparticles(particleeffectnum("laser_impact"), org2, backoff * 1000, 1)
-// used in qcsrc/client/damage.qc: pointparticles(particleeffectnum("laser_impact"), org2, backoff * 1000, 1)
+ type spark
+ airfriction 12
+ alpha 256 512 6280
+ color 0xff4200 0xff0000
+ count 6
+ originjitter 2 2 2
+ sizeincrease -100
+ size 7 9
+ stretchfactor 2
+ tex 8 15
+ velocityjitter 100 100 100
+ velocitymultiplier 0.200000
effect laser_impact
-countabsolute 1
-type decal
-tex 47 47
-size 24 24
-alpha 256 256 0
-originjitter 14 14 14
-lightradius 200
-lightradiusfade 500
-lightcolor 8 0.4 0.4
-// flare effect
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 8 0.4 0.4
+ lightradiusfade 500
+ lightradius 200
+ originjitter 14 14 14
+ size 24 24
+ tex 47 47
effect 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
+ type static
+ alpha 256 256 1024
+ color 0xFF2010 0xFF2010
+ countabsolute 1
+ size 24 24
+ tex 39 39
effect laser_impact
-count 128
-type spark
-color 0x800000 0xFF8020
-alpha 256 256 1024
-size 4 4
-//bounce 1.5
-airfriction 6
-liquidfriction 6
-//originjitter 32 32 32
-velocityjitter 256 256 256
+ type spark
+ airfriction 6
+ alpha 256 256 1024
+ color 0x800000 0xFF8020
+ count 128
+ liquidfriction 6
+ size 4 4
+ velocityjitter 256 256 256
effect laser_impact
-count 4
-type smoke
-tex 48 55
-color 0x800000 0xFF8020
-size 12 12
-alpha 128 256 256
-originjitter 1 1 1
-velocitymultiplier 0.01
-velocityjitter 16 16 16
-sizeincrease 6
-
-
-
-// used in qcsrc/server/w_campingrifle.qc: pointparticles(particleeffectnum("shotgun_muzzleflash"), w_shotorg, w_shotdir * 2000, 1)
-// used in qcsrc/server/w_shotgun.qc: pointparticles(particleeffectnum("shotgun_muzzleflash"), w_shotorg, w_shotdir * 1000, cvar("g_balance_shotgun_primary_ammo"))
-// used in qcsrc/server/w_shotgun.qc: pointparticles(particleeffectnum("shotgun_muzzleflash"), w_shotorg, w_shotdir * 1000, cvar("g_balance_shotgun_secondary_ammo"))
-effect shotgun_muzzleflash
-count 1.5
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 5 5
-alpha 256 256 512
-originjitter 1.5 1.5 1.5
-velocityjitter 6 6 6
-velocitymultiplier 0.01
-lightradius 200
-lightradiusfade 2000
-lightcolor 2 1.5 0.2
-sizeincrease 12
-velocitymultiplier 0.05
+ type smoke
+ alpha 128 256 256
+ color 0x800000 0xFF8020
+ count 4
+ originjitter 1 1 1
+ sizeincrease 6
+ size 12 12
+ tex 48 55
+ velocityjitter 16 16 16
+ velocitymultiplier 0.010000
effect shotgun_muzzleflash
-count 16
-type spark
-tex 48 55
-color 0xffdb96 0xff5400
-size 10 20
-alpha 0 128 1024
-originjitter 1 1 1
-velocityjitter 100 100 100
-airfriction 5
-stretchfactor 2.5
-velocitymultiplier 0.5
-
-// shotgun pellet impact
-// decal
-// used in qcsrc/client/damage.qc: pointparticles(particleeffectnum("shotgun_impact"), org2, backoff * 1000, 1)
+ type smoke
+ alpha 256 256 512
+ color 0x202020 0x404040
+ count 1.500000
+ lightcolor 2 1.5 0.2
+ lightradiusfade 2000
+ lightradius 200
+ originjitter 1.5 1.5 1.5
+ sizeincrease 12
+ size 5 5
+ tex 0 8
+ velocityjitter 6 6 6
+ velocitymultiplier 0.050000
+effect shotgun_muzzleflash
+ type spark
+ airfriction 5
+ alpha 0 128 1024
+ color 0xffdb96 0xff5400
+ count 16
+ originjitter 1 1 1
+ size 10 20
+ stretchfactor 2.500000
+ tex 48 55
+ velocityjitter 100 100 100
+ velocitymultiplier 0.500000
effect shotgun_impact
-countabsolute 1
-type decal
-tex 56 59
-size 5 8
-alpha 256 256 0
-originjitter 10 10 10
-//lightradius 30
-//lightradiusfade 90
-//lightcolor 1 1 1
-// dust/smoke drifting away from the impact
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ originjitter 10 10 10
+ size 5 8
+ tex 56 59
effect shotgun_impact
-type alphastatic
-notunderwater
-tex 0 8
-count 1
-size 10 20
-sizeincrease 25
-alpha 300 550 756
-velocityjitter 150 150 150
-velocitymultiplier 0.2
-airfriction 5
-color 0x473a37 0x0b0a07
-rotate 0 360 -50 50
-// dust/smoke staying at the impact
+ type alphastatic
+ airfriction 5
+ alpha 300 550 756
+ color 0x473a37 0x0b0a07
+ count 1
+ notunderwater
+ rotate 0 360 -50 50
+ sizeincrease 25
+ size 10 20
+ tex 0 8
+ velocityjitter 150 150 150
+ velocitymultiplier 0.200000
effect shotgun_impact
-type alphastatic
-notunderwater
-tex 36 36
-count 0.2
-size 10 11
-sizeincrease 74
-alpha 200 350 500
-velocityjitter 11 11 11
-airfriction 5
-color 0x201d1a 0x000000
-bounce 6
-velocitymultiplier 0.03
-rotate 0 360 -50 50
-// sparks
+ type alphastatic
+ airfriction 5
+ alpha 200 350 500
+ bounce 6
+ color 0x201d1a 0x000000
+ count 0.200000
+ notunderwater
+ rotate 0 360 -50 50
+ sizeincrease 74
+ size 10 11
+ tex 36 36
+ velocityjitter 11 11 11
+ velocitymultiplier 0.030000
effect shotgun_impact
-notunderwater
-count 0.5
-type spark
-tex 40 40
-color 0xFDFFD9 0xFDFFD9
-size 0.6 0.6
-alpha 0 356 268
-gravity 1
-bounce 1.5
-airfriction 1.1
-originjitter 1 1 1
-velocityjitter 200 200 200
-velocitymultiplier 0.2
-
-
-// used in qcsrc/server/w_uzi.qc: pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
+ type spark
+ airfriction 1.100000
+ alpha 0 356 268
+ bounce 1.500000
+ color 0xFDFFD9 0xFDFFD9
+ count 0.500000
+ gravity 1
+ notunderwater
+ originjitter 1 1 1
+ size 0.600000 0.600000
+ tex 40 40
+ velocityjitter 200 200 200
+ velocitymultiplier 0.200000
effect uzi_muzzleflash
-count 1
-type static
-color 0x202020 0x404040
-tex 0 8
-size 5 5
-alpha 256 256 512
-originjitter 1.5 1.5 1.5
-velocityjitter 1 1 1
-velocitymultiplier 0.03
-lightradius 200
-lightradiusfade 2000
-lightcolor 2 1.5 0.2
-gravity -0.1
+ type static
+ alpha 256 256 512
+ color 0x202020 0x404040
+ count 1
+ gravity -0.100000
+ lightcolor 2 1.5 0.2
+ lightradiusfade 2000
+ lightradius 200
+ originjitter 1.5 1.5 1.5
+ size 5 5
+ tex 0 8
+ velocityjitter 1 1 1
+ velocitymultiplier 0.030000
effect uzi_muzzleflash
-count 3
-type spark
-tex 40 40
-color 0xff9c00 0xffd200
-size 0.3 0.4
-alpha 0 256 6000
-originjitter 1 1 1
-velocityjitter 555 555 555
-velocitymultiplier 3
-stretchfactor 0.15
-airfriction 12
-
-
-// used in qcsrc/server/cl_client.qc: //pointparticles(particleeffectnum("machinegun_impact"), self.origin + self.view_ofs + '0 0 7', '0 0 0', 1)
-// used in qcsrc/client/damage.qc: pointparticles(particleeffectnum("machinegun_impact"), org2, backoff * 1000, 1)
-// used in qcsrc/client/damage.qc: pointparticles(particleeffectnum("machinegun_impact"), org2, backoff * 1000, 1)
-// decal
+ type spark
+ airfriction 12
+ alpha 0 256 6000
+ color 0xff9c00 0xffd200
+ count 3
+ originjitter 1 1 1
+ size 0.300000 0.400000
+ stretchfactor 0.150000
+ tex 40 40
+ velocityjitter 555 555 555
+ velocitymultiplier 3
effect machinegun_impact
-countabsolute 1
-type decal
-tex 56 59
-size 5 5
-alpha 256 256 0
-originjitter 10 10 10
-lightradius 80
-lightradiusfade 800
-lightcolor 6 3.6 0.6
-// dust/smoke drifting away from the impact
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 6 3.6 0.6
+ lightradiusfade 800
+ lightradius 80
+ originjitter 10 10 10
+ size 5 5
+ tex 56 59
effect machinegun_impact
-type alphastatic
-notunderwater
-tex 0 8
-count 1.5
-size 10 20
-sizeincrease 15
-alpha 300 550 456
-velocityjitter 150 150 150
-velocitymultiplier 0.1
-airfriction 5
-color 0x473a37 0x0b0a07
-rotate 0 360 -50 50
-// dust/smoke staying at the impact
+ type alphastatic
+ airfriction 5
+ alpha 300 550 456
+ color 0x473a37 0x0b0a07
+ count 1.500000
+ notunderwater
+ rotate 0 360 -50 50
+ sizeincrease 15
+ size 10 20
+ tex 0 8
+ velocityjitter 150 150 150
+ velocitymultiplier 0.100000
effect machinegun_impact
-type alphastatic
-notunderwater
-tex 36 36
-count 0.5
-size 10 11
-sizeincrease 74
-alpha 200 350 500
-velocityjitter 11 11 11
-airfriction 5
-color 0x201d1a 0x000000
-bounce 6
-velocitymultiplier 0.03
-rotate 0 360 -50 50
-//debris
+ type alphastatic
+ airfriction 5
+ alpha 200 350 500
+ bounce 6
+ color 0x201d1a 0x000000
+ count 0.500000
+ notunderwater
+ rotate 0 360 -50 50
+ sizeincrease 74
+ size 10 11
+ tex 36 36
+ velocityjitter 11 11 11
+ velocitymultiplier 0.030000
effect machinegun_impact
-type alphastatic
-notunderwater
-tex 66 68
-count 1
-size 1 5
-airfriction 1
-gravity 1.4
-alpha 300 550 256
-velocityjitter 350 350 350
-velocitymultiplier 0.2
-bounce 1.7
-color 0x63493e 0xffffff
-rotate 0 360 -500 500
-// sparks
+ type alphastatic
+ airfriction 1
+ alpha 300 550 256
+ bounce 1.700000
+ color 0x63493e 0xffffff
+ count 1
+ gravity 1.400000
+ notunderwater
+ rotate 0 360 -500 500
+ size 1 5
+ tex 66 68
+ velocityjitter 350 350 350
+ velocitymultiplier 0.200000
effect machinegun_impact
-notunderwater
-count 1
-type spark
-tex 40 40
-color 0xFDFFD9 0xFDFFD9
-size 0.3 0.3
-alpha 256 256 168
-gravity 1
-bounce 1
-airfriction 2
-originjitter 1 1 1
-velocityjitter 300 300 300
-velocitymultiplier 0.2
-
-
-
-
-// used in qcsrc/server/nexball.qc: pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
-// used in qcsrc/server/w_grenadelauncher.qc: pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
-// used in qcsrc/server/w_grenadelauncher.qc: pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
-// used in qcsrc/server/w_porto.qc: //pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
+ type spark
+ airfriction 2
+ alpha 256 256 168
+ bounce 1
+ color 0xFDFFD9 0xFDFFD9
+ count 1
+ gravity 1
+ notunderwater
+ originjitter 1 1 1
+ size 0.300000 0.300000
+ tex 40 40
+ velocityjitter 300 300 300
+ velocitymultiplier 0.200000
effect grenadelauncher_muzzleflash
-count 1.5
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 5 5
-alpha 256 256 512
-originjitter 1.5 1.5 1.5
-airfriction 12
-velocityjitter 20 20 20
-velocitymultiplier 0.03
-lightradius 200
-lightradiusfade 2000
-lightcolor 2 1.5 0.2
+ type smoke
+ airfriction 12
+ alpha 256 256 512
+ color 0x202020 0x404040
+ count 1.500000
+ lightcolor 2 1.5 0.2
+ lightradiusfade 2000
+ lightradius 200
+ originjitter 1.5 1.5 1.5
+ size 5 5
+ tex 0 8
+ velocityjitter 20 20 20
+ velocitymultiplier 0.030000
effect grenadelauncher_muzzleflash
-count 16
-type spark
-tex 48 55
-color 0xffdb96 0xff5400
-size 10 20
-alpha 0 128 1024
-originjitter 1 1 1
-velocityjitter 100 100 100
-velocitymultiplier 0.5
-airfriction 5
-stretchfactor 2.5
-
-
-
-// mortar trail
-// smoke
-// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_GRENADE"), from, to)
-// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_GRENADE"), from, to)
+ type spark
+ airfriction 5
+ alpha 0 128 1024
+ color 0xffdb96 0xff5400
+ count 16
+ originjitter 1 1 1
+ size 10 20
+ stretchfactor 2.500000
+ tex 48 55
+ velocityjitter 100 100 100
+ velocitymultiplier 0.500000
effect TR_GRENADE
-trailspacing 4
-type smoke
-color 0x101010 0x000000
-tex 0 8
-size 3 2
-bounce 1
-sizeincrease 10
-alpha 300 400 780
-originjitter 1 1 1
-velocityjitter 1 1 1
-velocitymultiplier -0.02
-//gravity -0.11
-// fire
+ type smoke
+ alpha 300 400 780
+ bounce 1
+ color 0x101010 0x000000
+ originjitter 1 1 1
+ sizeincrease 10
+ size 3 2
+ tex 0 8
+ trailspacing 4
+ velocityjitter 1 1 1
+ velocitymultiplier -0.020000
effect TR_GRENADE
-notunderwater
-trailspacing 4
-type static
-color 0xffdf72 0x811200
-tex 48 55
-size 5 2
-sizeincrease -15
-alpha 100 144 988
-airfriction 8
-velocityjitter 32 32 32
-velocitymultiplier -1.0
-// bubbles
+ type static
+ airfriction 8
+ alpha 100 144 988
+ color 0xffdf72 0x811200
+ notunderwater
+ sizeincrease -15
+ size 5 2
+ tex 48 55
+ trailspacing 4
+ velocityjitter 32 32 32
+ velocitymultiplier -1
effect TR_GRENADE
-underwater
-trailspacing 16
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 1 1
-alpha 256 256 256
-gravity -0.125
-bounce 1.5
-liquidfriction 4
-velocityjitter 16 16 16
-
-
-
-// hookbomb trail
-// smoke
-// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_KNIGHTSPIKE"), from, to)
-// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_KNIGHTSPIKE"), from, to)
-// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_KNIGHTSPIKE"), from, to)
-effect TR_KNIGHTSPIKE // used for MF_TRACER2
-notunderwater
-trailspacing 6
-type smoke
-color 0x303030 0x000000
-tex 0 8
-size 3 3
-bounce 1
-sizeincrease 11
-alpha 300 400 600
-originjitter 2 2 2
-velocityjitter 3 3 3
-velocitymultiplier -0.02
-gravity -0.11
-//marker
-effect TR_KNIGHTSPIKE // used for MF_TRACER2
-type alphastatic
-color 0x666666 0x000000
-tex 62 62
-size 1 1
-sizeincrease -0.1
-trailspacing 2
-alpha 256 256 720
-// bubbles
-effect TR_KNIGHTSPIKE // used for MF_TRACER2
-underwater
-trailspacing 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 1 1
-alpha 256 256 256
-gravity -0.125
-bounce 1.5
-liquidfriction 4
-velocityjitter 16 16 16
-
-
-
-// decal
-// used in qcsrc/client/damage.qc: pointparticles(particleeffectnum("grenade_explode"), org2, '0 0 0', 1)
+ type bubble
+ alpha 256 256 256
+ bounce 1.500000
+ color 0x404040 0x808080
+ gravity -0.125000
+ liquidfriction 4
+ size 1 1
+ tex 62 62
+ trailspacing 16
+ underwater
+ velocityjitter 16 16 16
+effect TR_KNIGHTSPIKE
+ type smoke
+ alpha 300 400 600
+ bounce 1
+ color 0x303030 0x000000
+ gravity -0.110000
+ notunderwater
+ originjitter 2 2 2
+ sizeincrease 11
+ size 3 3
+ tex 0 8
+ trailspacing 6
+ velocityjitter 3 3 3
+ velocitymultiplier -0.020000
+effect TR_KNIGHTSPIKE
+ type alphastatic
+ alpha 256 256 720
+ color 0x666666 0x000000
+ sizeincrease -0.100000
+ size 1 1
+ tex 62 62
+ trailspacing 2
+effect TR_KNIGHTSPIKE
+ type bubble
+ alpha 256 256 256
+ bounce 1.500000
+ color 0x404040 0x808080
+ gravity -0.125000
+ liquidfriction 4
+ size 1 1
+ tex 62 62
+ trailspacing 32
+ underwater
+ velocityjitter 16 16 16
effect grenade_explode
-countabsolute 1
-type decal
-tex 8 16
-size 48 48
-alpha 256 256 0
-originjitter 26 26 26
-lightradius 250
-lightradiusfade 400
-lightcolor 8 4 1
-// fire effect which expands then slows
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 8 4 1
+ lightradiusfade 400
+ lightradius 250
+ originjitter 26 26 26
+ size 48 48
+ tex 8 16
effect grenade_explode
-notunderwater
-count 40
-type static
-tex 48 55
-color 0xe03f00 0x5e0000
-size 16 26
-sizeincrease 20
-alpha 128 228 356
-bounce 4.5
-airfriction 8
-liquidfriction 8
-originjitter 8 8 8
-velocityjitter 256 256 256
-// fire effect which make brigt dot inside
+ type static
+ airfriction 8
+ alpha 128 228 356
+ bounce 4.500000
+ color 0xe03f00 0x5e0000
+ count 40
+ liquidfriction 8
+ notunderwater
+ originjitter 8 8 8
+ sizeincrease 20
+ size 16 26
+ tex 48 55
+ velocityjitter 256 256 256
effect grenade_explode
-notunderwater
-count 15
-type static
-tex 48 55
-color 0xe03f00 0xffdf92
-size 6 16
-sizeincrease 40
-alpha 228 328 756
-bounce 1
-airfriction 8
-liquidfriction 8
-originjitter 8 8 8
-velocityjitter 256 256 256
-// smoke
+ type static
+ airfriction 8
+ alpha 228 328 756
+ bounce 1
+ color 0xe03f00 0xffdf92
+ count 15
+ liquidfriction 8
+ notunderwater
+ originjitter 8 8 8
+ sizeincrease 40
+ size 6 16
+ tex 48 55
+ velocityjitter 256 256 256
effect grenade_explode
-type alphastatic
-notunderwater
-tex 0 8
-count 10
-size 20 40
-sizeincrease 34
-alpha 300 550 556
-velocityjitter 256 256 256
-airfriction 5
-color 0x000000 0x111111
-bounce 6
-// underwater bubbles
+ type alphastatic
+ airfriction 5
+ alpha 300 550 556
+ bounce 6
+ color 0x000000 0x111111
+ count 10
+ notunderwater
+ sizeincrease 34
+ size 20 40
+ tex 0 8
+ velocityjitter 256 256 256
effect grenade_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
-// underwatershockwave
+ type bubble
+ alpha 128 256 64
+ bounce 1.500000
+ color 0x404040 0x808080
+ count 32
+ gravity -0.125000
+ liquidfriction 0.250000
+ originjitter 16 16 16
+ size 3 6
+ tex 62 62
+ underwater
+ velocityjitter 196 196 196
effect grenade_explode
-underwater
-type smoke
-countabsolute 1
-tex 33 33
-size 5 5
-sizeincrease 1500
-alpha 40 40 300
-velocitymultiplier 0.3
-// bouncing sparks
+ type smoke
+ alpha 40 40 300
+ countabsolute 1
+ sizeincrease 1500
+ size 5 5
+ tex 33 33
+ underwater
+ velocitymultiplier 0.300000
effect grenade_explode
-notunderwater
-count 16
-type spark
-tex 40 40
-color 0xffa35b 0xfff2be
-size 1 0.1
-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
-// debris
+ type spark
+ airfriction 1
+ alpha 644 956 484
+ bounce 1.600000
+ color 0xffa35b 0xfff2be
+ count 16
+ gravity 1
+ liquidfriction 0.800000
+ notunderwater
+ originjitter 16 16 16
+ size 1 0.100000
+ tex 40 40
+ velocityjitter 424 424 624
+ velocityoffset 0 0 80
effect grenade_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
-
-
-
-// used in qcsrc/server/w_electro.qc: pointparticles(particleeffectnum("electro_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
-// used in qcsrc/server/w_electro.qc: pointparticles(particleeffectnum("electro_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
+ type alphastatic
+ airfriction 0.500000
+ alpha 644 956 684
+ bounce 1.600000
+ color 0x6a3d25 0xcac5b4
+ count 12
+ gravity 1.300000
+ notunderwater
+ rotate -180 180 -1000 1000
+ size 2 6
+ tex 66 68
+ velocityjitter 324 324 524
effect electro_muzzleflash
-countabsolute 1
-type smoke
-color 0x283880 0x283880 // 0x202020 0x404040
-tex 65 65
-size 15 15
-alpha 256 256 512
-originjitter 1.5 1.5 1.5
-velocityjitter 6 6 6
-sizeincrease -10
-velocitymultiplier 0.01
-lightradius 200
-lightradiusfade 2000
-lightcolor 1.5 3 6
-
+ type smoke
+ alpha 256 256 512
+ color 0x283880 0x283880
+ countabsolute 1
+ lightcolor 1.5 3 6
+ lightradiusfade 2000
+ lightradius 200
+ originjitter 1.5 1.5 1.5
+ sizeincrease -10
+ size 15 15
+ tex 65 65
+ velocityjitter 6 6 6
+ velocitymultiplier 0.010000
effect electro_muzzleflash
-count 7
-type spark
-tex 8 15
-color 0xD9FDFF 0xD9FDFF
-size 5 15
-alpha 110 228 2024
-originjitter 1 1 1
-velocityjitter 150 150 150
-velocitymultiplier 0.5
-airfriction 2
-stretchfactor 1.5
-
+ type spark
+ airfriction 2
+ alpha 110 228 2024
+ color 0xD9FDFF 0xD9FDFF
+ count 7
+ originjitter 1 1 1
+ size 5 15
+ stretchfactor 1.500000
+ tex 8 15
+ velocityjitter 150 150 150
+ velocitymultiplier 0.500000
effect electro_muzzleflash
-count 5
-type spark
-tex 41 41
-color 0xD9FDFF 0xD9FDFF
-size 7 6
-alpha 110 228 1024
-originjitter 1 1 1
-velocityjitter 350 350 350
-velocitymultiplier 2.5
-airfriction 8
-gravity 1.3
-stretchfactor 0.1
-
-
-// electro trail
-// glowing vapor trail
-// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_NEXUIZPLASMA"), from, to)
+ type spark
+ airfriction 8
+ alpha 110 228 1024
+ color 0xD9FDFF 0xD9FDFF
+ count 5
+ gravity 1.300000
+ originjitter 1 1 1
+ size 7 6
+ stretchfactor 0.100000
+ tex 41 41
+ velocityjitter 350 350 350
+ velocitymultiplier 2.500000
effect TR_NEXUIZPLASMA
-trailspacing 2
-type static
-color 0x283880 0x283880
-size 3 3
-tex 38 38
-alpha 256 256 968
-//velocityjitter 16 16 16
-lightradius 90
-lighttime 0
-lightcolor 1.5 3 6
-velocitymultiplier -0.1
-// bright sparks
+ type static
+ alpha 256 256 968
+ color 0x283880 0x283880
+ lightcolor 1.5 3 6
+ lightradius 90
+ size 3 3
+ tex 38 38
+ trailspacing 2
+ velocitymultiplier -0.100000
effect TR_NEXUIZPLASMA
-trailspacing 12
-count 1.5
-type snow
-tex 42 42
-color 0x629dff 0x0018ff
-size 2 4
-sizeincrease -20
-alpha 444 512 1866
-bounce 1
-velocityoffset 0 0 15
-airfriction 12
-originjitter 1 1 1
-velocityjitter 50 50 50
-
-
-
-// decal
-// used in qcsrc/client/damage.qc: pointparticles(particleeffectnum("electro_impact"), org2, '0 0 0', 1)
+ type snow
+ airfriction 12
+ alpha 444 512 1866
+ bounce 1
+ color 0x629dff 0x0018ff
+ count 1.500000
+ originjitter 1 1 1
+ sizeincrease -20
+ size 2 4
+ tex 42 42
+ trailspacing 12
+ velocityjitter 50 50 50
+ velocityoffset 0 0 15
effect electro_impact
-countabsolute 1
-type decal
-tex 59 59
-size 32 32
-alpha 256 256 0
-originjitter 17 17 17
-lightradius 250
-lightradiusfade 250
-lightcolor 3.125 4.375 10
-// shockwave
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 3.1 4.4 10
+ lightradiusfade 250
+ lightradius 250
+ originjitter 17 17 17
+ size 32 32
+ tex 59 59
effect electro_impact
-type smoke
-countabsolute 1
-tex 33 33
-size 32 32
-sizeincrease 1000
-color 0x80C0FF 0x80C0FF
-alpha 40 40 350
-velocitymultiplier 44
-// flare effect
+ type smoke
+ alpha 40 40 350
+ color 0x80C0FF 0x80C0FF
+ countabsolute 1
+ sizeincrease 1000
+ size 32 32
+ tex 33 33
+ velocitymultiplier 44
effect electro_impact
-countabsolute 1
-type static
-tex 38 38
-color 0x80C0FF 0x80C0FF
-size 12 32
-alpha 256 256 512
-// cloud of bouncing sparks
+ type static
+ alpha 256 256 512
+ color 0x80C0FF 0x80C0FF
+ countabsolute 1
+ size 12 32
+ tex 38 38
effect electro_impact
-count 30
-type smoke
-tex 42 42
-color 0x629dff 0x0018ff
-size 36 36
-sizeincrease -50
-alpha 256 256 1024
-bounce 2
-gravity -0.3
-airfriction 6
-originjitter 1 1 1
-velocityjitter 512 512 512
-rotate -180 180 -9999 9999
-// inner cloud of smoke
+ type smoke
+ airfriction 6
+ alpha 256 256 1024
+ bounce 2
+ color 0x629dff 0x0018ff
+ count 30
+ gravity -0.300000
+ originjitter 1 1 1
+ rotate -180 180 -9999 9999
+ sizeincrease -50
+ size 36 36
+ tex 42 42
+ velocityjitter 512 512 512
effect electro_impact
-count 30
-type smoke
-color 0x629dff 0x0018ff
-tex 0 8
-size 20 24
-sizeincrease 50
-alpha 200 256 512
-airfriction 30
-originjitter 20 20 20
-velocityjitter 320 320 320
-
-// decal
-// used in qcsrc/client/damage.qc: pointparticles(particleeffectnum("electro_ballexplode"), org2, '0 0 0', 1)
+ type smoke
+ airfriction 30
+ alpha 200 256 512
+ color 0x629dff 0x0018ff
+ count 30
+ originjitter 20 20 20
+ sizeincrease 50
+ size 20 24
+ tex 0 8
+ velocityjitter 320 320 320
effect electro_ballexplode
-countabsolute 1
-type decal
-tex 59 59
-size 32 32
-alpha 256 256 0
-originjitter 17 17 17
-lightradius 250
-lightradiusfade 250
-lightcolor 3.125 4.375 10
-// flare effect
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 3.1 4.4 10
+ lightradiusfade 250
+ lightradius 250
+ originjitter 17 17 17
+ size 32 32
+ tex 59 59
effect electro_ballexplode
-countabsolute 1
-type static
-tex 38 38
-color 0x80C0FF 0x80C0FF
-size 32 32
-alpha 256 256 512
-// cloud of bouncing sparks
+ type static
+ alpha 256 256 512
+ color 0x80C0FF 0x80C0FF
+ countabsolute 1
+ size 32 32
+ tex 38 38
effect electro_ballexplode
-count 64
-type spark
-tex 41 41
-color 0xFDFFD9 0xFDFFD9
-size 1 2
-alpha 256 256 1024
-bounce 2
-stretchfactor 0.4
-//airfriction 2
-originjitter 1 1 1
-velocityjitter 512 512 512
-// inner cloud of smoke
+ type spark
+ alpha 256 256 1024
+ bounce 2
+ color 0xFDFFD9 0xFDFFD9
+ count 64
+ originjitter 1 1 1
+ size 1 2
+ stretchfactor 0.400000
+ tex 41 41
+ velocityjitter 512 512 512
effect electro_ballexplode
-count 8
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 24 24
-alpha 256 256 512
-originjitter 20 20 20
-velocityjitter 32 32 32
-
-
-
-// decal
-// used in qcsrc/client/damage.qc: pointparticles(particleeffectnum("electro_combo"), org2, '0 0 0', 1)
+ type smoke
+ alpha 256 256 512
+ color 0x202020 0x404040
+ count 8
+ originjitter 20 20 20
+ size 24 24
+ tex 0 8
+ velocityjitter 32 32 32
effect electro_combo
-countabsolute 1
-type decal
-tex 59 59
-size 64 64
-alpha 256 256 0
-originjitter 17 17 17
-lightradius 400
-lightradiusfade 300
-lightcolor 4 5 6
-// flare effect
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 4 5 6
+ lightradiusfade 300
+ lightradius 400
+ originjitter 17 17 17
+ size 64 64
+ tex 59 59
effect electro_combo
-countabsolute 1
-type static
-tex 38 38
-color 0x80C0FF 0x80C0FF
-size 48 48
-alpha 128 128 64
-// large sparks
+ type static
+ alpha 128 128 64
+ color 0x80C0FF 0x80C0FF
+ countabsolute 1
+ size 48 48
+ tex 38 38
effect electro_combo
-count 5
-type static
-color 0x2030FF 0x80C0FF
-size 32 32
-sizeincrease 50
-tex 0 7
-alpha 156 156 156
-bounce 2
-airfriction 6
-liquidfriction 16
-//velocityoffset 0 0 120
-velocityjitter 512 512 512
+ type static
+ airfriction 6
+ alpha 156 156 156
+ bounce 2
+ color 0x2030FF 0x80C0FF
+ count 5
+ liquidfriction 16
+ sizeincrease 50
+ size 32 32
+ tex 0 7
+ velocityjitter 512 512 512
effect electro_combo
-count 32
-type spark
-tex 41 41
-color 0xa9cacf 0x0054ff
-size 2 4
-stretchfactor 2
-gravity 0.3
-alpha 444 512 700
-velocitymultiplier 3
-bounce 1.6
-//airfriction 2
-originjitter 1 1 1
-velocityjitter 312 312 312
-// inner cloud of smoke
+ type spark
+ alpha 444 512 700
+ bounce 1.600000
+ color 0xa9cacf 0x0054ff
+ count 32
+ gravity 0.300000
+ originjitter 1 1 1
+ size 2 4
+ stretchfactor 2
+ tex 41 41
+ velocityjitter 312 312 312
+ velocitymultiplier 3
effect electro_combo
-count 0.125
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 24 24
-alpha 256 256 256
-originjitter 20 20 20
-velocityjitter 32 32 32
-// shockwave
+ type smoke
+ alpha 256 256 256
+ color 0x202020 0x404040
+ count 0.125000
+ originjitter 20 20 20
+ size 24 24
+ tex 0 8
+ velocityjitter 32 32 32
effect electro_combo
-type smoke
-countabsolute 1
-color 0xa9cacf 0x0054ff
-tex 33 33
-size 30 30
-sizeincrease 600
-alpha 40 40 100
-velocitymultiplier 0.3
-
-
-
-// used in qcsrc/server/w_crylink.qc: pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots)
-// used in qcsrc/server/w_crylink.qc: pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots)
+ type smoke
+ alpha 40 40 100
+ color 0xa9cacf 0x0054ff
+ countabsolute 1
+ sizeincrease 600
+ size 30 30
+ tex 33 33
+ velocitymultiplier 0.300000
effect crylink_muzzleflash
-count 0.5
-type smoke
-color 0xdd9cff 0xff0090
-tex 65 65
-size 15 20
-alpha 128 128 2024
-velocitymultiplier 0.01
-lightradius 200
-lightradiusfade 2000
-lightcolor 1.6 0.2 2
+ type smoke
+ alpha 128 128 2024
+ color 0xdd9cff 0xff0090
+ count 0.500000
+ lightcolor 1.6 0.2 2
+ lightradiusfade 2000
+ lightradius 200
+ size 15 20
+ tex 65 65
+ velocitymultiplier 0.010000
effect crylink_muzzleflash
-count 5
-type spark
-tex 35 36
-color 0xA080C0 0xA080C0
-size 5 10
-alpha 0 128 1024
-originjitter 1 1 1
-velocityjitter 200 200 200
-velocitymultiplier 0.3
-airfriction 12
-stretchfactor 1.5
-
-
-// crylink impact effect
-// decal
-// used in qcsrc/client/damage.qc: pointparticles(particleeffectnum("crylink_impact"), org2, '0 0 0', 1)
+ type spark
+ airfriction 12
+ alpha 0 128 1024
+ color 0xA080C0 0xA080C0
+ count 5
+ originjitter 1 1 1
+ size 5 10
+ stretchfactor 1.500000
+ tex 35 36
+ velocityjitter 200 200 200
+ velocitymultiplier 0.300000
effect crylink_impact
-countabsolute 1
-type decal
-tex 47 47
-size 24 24
-alpha 256 256 0
-originjitter 12 12 12
-//lightradius 200
-//lightradiusfade 800
-//lightcolor 3.2 0.4 4
-// purple flare effect
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ originjitter 12 12 12
+ size 24 24
+ tex 47 47
effect crylink_impact
-countabsolute 1
-type static
-tex 39 39
-color 0x504060 0x504060
-size 24 24
-alpha 256 256 512
-// purple sparks
+ type static
+ alpha 256 256 512
+ color 0x504060 0x504060
+ countabsolute 1
+ size 24 24
+ tex 39 39
effect crylink_impact
-count 40
-type spark
-tex 41 41
-color 0xA040C0 0xA040C0
-bounce 2
-size 6 6
-alpha 256 256 1024
-velocityjitter 512 512 512
-// purple splash
+ type spark
+ alpha 256 256 1024
+ bounce 2
+ color 0xA040C0 0xA040C0
+ count 40
+ size 6 6
+ tex 41 41
+ velocityjitter 512 512 512
effect crylink_impact
-count 1.5
-type static
-color 0xE070FF 0xE070FF
-size 16 16
-alpha 256 256 512
-velocityjitter 32 32 32
-// purple splash
+ type static
+ alpha 256 256 512
+ color 0xE070FF 0xE070FF
+ count 1.500000
+ size 16 16
+ velocityjitter 32 32 32
effect crylink_impact
-count 3
-type static
-color 0xE070FF 0xE070FF
-size 16 16
-alpha 256 256 1024
-velocityjitter 256 256 256
-
-
-
-// used in qcsrc/server/w_minstanex.qc: pointparticles(particleeffectnum("nex_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
-// used in qcsrc/client/particles.qc: pointparticles(particleeffectnum("nex_muzzleflash"), shotorg, normalize(endpos - shotorg) * 1000, 1)
+ type static
+ alpha 256 256 1024
+ color 0xE070FF 0xE070FF
+ count 3
+ size 16 16
+ velocityjitter 256 256 256
effect nex_muzzleflash
-count 12
-type spark
-color 0x202020 0x0072ff
-tex 48 55
-size 16 16
-alpha 328 328 4000
-originjitter 4 4 4
-velocityjitter 180 180 180
-velocitymultiplier 1.4
-stretchfactor 2
-sizeincrease -100
-airfriction 9
-lightradius 200
-lightradiusfade 200
-lightcolor 2 2.5 3
+ type spark
+ airfriction 9
+ alpha 328 328 4000
+ color 0x202020 0x0072ff
+ count 12
+ lightcolor 2 2.5 3
+ lightradiusfade 200
+ lightradius 200
+ originjitter 4 4 4
+ sizeincrease -100
+ size 16 16
+ stretchfactor 2
+ tex 48 55
+ velocityjitter 180 180 180
+ velocitymultiplier 1.400000
effect nex_muzzleflash
-count 50
-type spark
-tex 41 41
-color 0xD9FDFF 0xD9FDFF
-size 1 1
-alpha 0 128 1024
-originjitter 1 1 1
-velocityjitter 600 600 600
-velocitymultiplier 1.5
-airfriction 9
-
-
-
-//// nex beam
-//effect nex_beam
-//countabsolute 1
-//type beam
-//tex 200 200
-//color 0xFFFFFF 0xFFFFFF
-//size 6 6
-//alpha 128 128 192
-// nex beam: ring smoke
-// used in qcsrc/client/particles.qc: trailparticles(world, particleeffectnum("nex_beam"), shotorg, endpos)
+ type spark
+ airfriction 9
+ alpha 0 128 1024
+ color 0xD9FDFF 0xD9FDFF
+ count 50
+ originjitter 1 1 1
+ size 1 1
+ tex 41 41
+ velocityjitter 600 600 600
+ velocitymultiplier 1.500000
effect nex_beam
-trailspacing 64
-color 0x1680A0 0x1680A0
-size 4 4
-tex 32 32
-alpha 64 128 64
-airfriction 5
-sizeincrease 2
-type static
-// nex beam: drifting smoke
+ type static
+ airfriction 5
+ alpha 64 128 64
+ color 0x1680A0 0x1680A0
+ sizeincrease 2
+ size 4 4
+ tex 32 32
+ trailspacing 64
effect nex_beam
-trailspacing 12
-color 0x5080A0 0x5080A0
-size 1 1
-tex 0 8
-alpha 32 64 32
-airfriction 9
-sizeincrease 8
-velocityjitter 64 64 64
-type static
-// nex beam: bright core
+ type static
+ airfriction 9
+ alpha 32 64 32
+ color 0x5080A0 0x5080A0
+ sizeincrease 8
+ size 1 1
+ tex 0 8
+ trailspacing 12
+ velocityjitter 64 64 64
effect nex_beam
-trailspacing 12
-color 0x80CDFF 0x80CDFF
-size 4 4
-//tex 48 55
-alpha 256 256 1280
-type static
-//sparks
+ type static
+ alpha 256 256 1280
+ color 0x80CDFF 0x80CDFF
+ size 4 4
+ trailspacing 12
effect nex_beam
-trailspacing 16
-color 0x1680A0 0x1680A0
-size 1 1
-tex 63 63
-alpha 64 128 80
-airfriction 5
-gravity -0.01
-type snow
-
-// nex impact
-// decal
-// used in qcsrc/client/damage.qc: pointparticles(particleeffectnum("nex_impact"), org2, '0 0 0', 1)
-// used in qcsrc/client/damage.qc: pointparticles(particleeffectnum("nex_impact"), org2, '0 0 0', 1)
+ type snow
+ airfriction 5
+ alpha 64 128 80
+ color 0x1680A0 0x1680A0
+ gravity -0.010000
+ size 1 1
+ tex 63 63
+ trailspacing 16
effect nex_impact
-countabsolute 1
-type decal
-tex 47 47
-size 24 24
-alpha 256 256 0
-originjitter 14 14 14
-lightradius 200
-lightradiusfade 250
-lightcolor 4 6 8
-rotate -180 180 0 0
-// rotating something
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 4 6 8
+ lightradiusfade 250
+ lightradius 200
+ originjitter 14 14 14
+ rotate -180 180 0 0
+ size 24 24
+ tex 47 47
effect nex_impact
-count 5
-type smoke
-tex 46 46
-color 0x1680A0 0x1680A0
-size 25 28
-sizeincrease 20
-alpha 55 55 50
-rotate 180 -180 500 -500
-// shockwave
+ type smoke
+ alpha 55 55 50
+ color 0x1680A0 0x1680A0
+ count 5
+ rotate 180 -180 500 -500
+ sizeincrease 20
+ size 25 28
+ tex 46 46
effect nex_impact
-countabsolute 1
-type static
-tex 33 33
-color 0x1680A0 0x1680A0
-size 16 16
-alpha 50 50 400
-sizeincrease 900
-// shockwave2
+ type static
+ alpha 50 50 400
+ color 0x1680A0 0x1680A0
+ countabsolute 1
+ sizeincrease 900
+ size 16 16
+ tex 33 33
effect nex_impact
-countabsolute 1
-type static
-tex 65 65
-color 0x1680A0 0x1680A0
-size 5 5
-alpha 50 50 100
-sizeincrease 500
-
-// flare effect
+ type static
+ alpha 50 50 100
+ color 0x1680A0 0x1680A0
+ countabsolute 1
+ sizeincrease 500
+ size 5 5
+ tex 65 65
effect nex_impact
-countabsolute 1
-type static
-tex 37 37
-color 0x80C0FF 0x80C0FF
-size 8 8
-alpha 256 256 256
-// small sparks which form a sphere as they slow down
-//effect nex_impact
-//count 256
-//type spark
-//color 0x2030FF 0x80C0FF
-//size 1 2
-//alpha 256 256 512
-//bounce 2
-//airfriction 8
-//liquidfriction 8
-//velocityjitter 384 384 384
-// small sparks which glow brightly but live briefly
+ type static
+ alpha 256 256 256
+ color 0x80C0FF 0x80C0FF
+ countabsolute 1
+ size 8 8
+ tex 37 37
effect nex_impact
-count 64
-type spark
-tex 41 41
-color 0xD9FDFF 0xD9FDFF
-size 4 4
-alpha 0 128 512
-bounce 2
-stretchfactor 3
-velocityjitter 600 600 600
-velocitymultiplier 0.5
-airfriction 9
-// small sparks that live longer
+ type spark
+ airfriction 9
+ alpha 0 128 512
+ bounce 2
+ color 0xD9FDFF 0xD9FDFF
+ count 64
+ size 4 4
+ stretchfactor 3
+ tex 41 41
+ velocityjitter 600 600 600
+ velocitymultiplier 0.500000
effect nex_impact
-count 16
-type spark
-tex 41 41
-color 0xD9FDFF 0xD9FDFF
-size 2 2
-alpha 255 255 112
-bounce 1.6
-stretchfactor 0.7
-velocityjitter 300 300 600
-velocitymultiplier 2.5
-airfriction 2
-gravity 1
-
-// used in qcsrc/server/w_hagar.qc: pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
-// used in qcsrc/server/w_hagar.qc: pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
-// used in qcsrc/server/w_seeker.qc: pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
+ type spark
+ airfriction 2
+ alpha 255 255 112
+ bounce 1.600000
+ color 0xD9FDFF 0xD9FDFF
+ count 16
+ gravity 1
+ size 2 2
+ stretchfactor 0.700000
+ tex 41 41
+ velocityjitter 300 300 600
+ velocitymultiplier 2.500000
effect hagar_muzzleflash
-count 2
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 5 5
-alpha 256 256 512
-originjitter 1.5 1.5 1.5
-velocityjitter 6 6 6
-velocitymultiplier 0.01
-lightradius 200
-lightradiusfade 2000
-lightcolor 2 1.5 0.2
+ type smoke
+ alpha 256 256 512
+ color 0x202020 0x404040
+ count 2
+ lightcolor 2 1.5 0.2
+ lightradiusfade 2000
+ lightradius 200
+ originjitter 1.5 1.5 1.5
+ size 5 5
+ tex 0 8
+ velocityjitter 6 6 6
+ velocitymultiplier 0.010000
effect hagar_muzzleflash
-count 15
-type spark
-tex 48 55
-color 0xff8400 0xff4200
-size 5 10
-alpha 0 128 1024
-originjitter 1 1 1
-velocityjitter 200 200 200
-velocitymultiplier 0.5
-airfriction 12
-stretchfactor 2
-rotate -180 180 -400 400
-
-
-
-// used in qcsrc/server/w_hagar.qc: pointparticles(particleeffectnum("hagar_bounce"), self.origin, self.velocity, 1)
+ type spark
+ airfriction 12
+ alpha 0 128 1024
+ color 0xff8400 0xff4200
+ count 15
+ originjitter 1 1 1
+ rotate -180 180 -400 400
+ size 5 10
+ stretchfactor 2
+ tex 48 55
+ velocityjitter 200 200 200
+ velocitymultiplier 0.500000
effect hagar_bounce
-count 2
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 5 5
-alpha 256 256 256
-originjitter 1.5 1.5 1.5
-velocityjitter 6 6 6
-velocitymultiplier 0.01
-lightradius 60
-lightradiusfade 300
-lightcolor 2 1.5 0.2
+ type smoke
+ alpha 256 256 256
+ color 0x202020 0x404040
+ count 2
+ lightcolor 2 1.5 0.2
+ lightradiusfade 300
+ lightradius 60
+ originjitter 1.5 1.5 1.5
+ size 5 5
+ tex 0 8
+ velocityjitter 6 6 6
+ velocitymultiplier 0.010000
effect hagar_bounce
-count 15
-type spark
-tex 40 40
-color 0xFFFDD9 0xFFFDD9
-size 3 3
-alpha 0 256 256
-gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 600 600 600
-velocitymultiplier 0.5
-airfriction 12
-
-
-
-// decal
-// used in qcsrc/client/damage.qc: pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1)
-// used in qcsrc/client/damage.qc: pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1)
-// used in qcsrc/client/damage.qc: pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1)
+ type spark
+ airfriction 12
+ alpha 0 256 256
+ bounce 1.500000
+ color 0xFFFDD9 0xFFFDD9
+ count 15
+ gravity 1
+ originjitter 1 1 1
+ size 3 3
+ tex 40 40
+ velocityjitter 600 600 600
+ velocitymultiplier 0.500000
effect hagar_explode
-countabsolute 1
-type decal
-tex 8 16
-size 28 38
-alpha 256 256 0
-originjitter 14 14 14
-lightradius 120
-lightradiusfade 400
-lightcolor 8 4 1
-// fire effect which make bright dot inside
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 8 4 1
+ lightradiusfade 400
+ lightradius 120
+ originjitter 14 14 14
+ size 28 38
+ tex 8 16
effect hagar_explode
-notunderwater
-count 3.5
-type smoke
-tex 48 55
-color 0xffe955 0xff5a00
-size 16 26
-sizeincrease 5
-alpha 80 200 356
-bounce 1.5
-airfriction 8
-liquidfriction 8
-originjitter 8 8 8
-velocityjitter 156 156 156
-// fire effect which expands then slows
+ type smoke
+ airfriction 8
+ alpha 80 200 356
+ bounce 1.500000
+ color 0xffe955 0xff5a00
+ count 3.500000
+ liquidfriction 8
+ notunderwater
+ originjitter 8 8 8
+ sizeincrease 5
+ size 16 26
+ tex 48 55
+ velocityjitter 156 156 156
effect hagar_explode
-notunderwater
-count 12
-type static
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 20 26
-sizeincrease 15
-alpha 128 256 456
-bounce 1.5
-airfriction 12
-liquidfriction 8
-originjitter 8 8 8
-velocityjitter 286 286 286
-
-// smoke
+ type static
+ airfriction 12
+ alpha 128 256 456
+ bounce 1.500000
+ color 0x8f0d00 0xff5a00
+ count 12
+ liquidfriction 8
+ notunderwater
+ originjitter 8 8 8
+ sizeincrease 15
+ size 20 26
+ tex 48 55
+ velocityjitter 286 286 286
effect hagar_explode
-type alphastatic
-notunderwater
-tex 0 8
-count 7
-size 20 40
-sizeincrease 20
-alpha 200 500 600
-velocityjitter 244 244 244
-airfriction 5
-color 0x000000 0x111111
-bounce 2
-
-// underwater bubbles
+ type alphastatic
+ airfriction 5
+ alpha 200 500 600
+ bounce 2
+ color 0x000000 0x111111
+ count 7
+ notunderwater
+ sizeincrease 20
+ size 20 40
+ tex 0 8
+ velocityjitter 244 244 244
effect hagar_explode
-underwater
-count 16
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 16 16 16
-velocityjitter 96 96 96
-// bouncing sparks
+ type bubble
+ alpha 128 256 64
+ bounce 1.500000
+ color 0x404040 0x808080
+ count 16
+ gravity -0.125000
+ liquidfriction 0.250000
+ originjitter 16 16 16
+ size 3 3
+ tex 62 62
+ underwater
+ velocityjitter 96 96 96
effect hagar_explode
-notunderwater
-count 4
-type spark
-tex 40 40
-color 0xffa35b 0xfff2be
-size 1 0.1
-alpha 644 956 684
-gravity 1
-airfriction 1
-bounce 1.6
-liquidfriction 0.8
-velocityoffset 0 0 80
-originjitter 16 16 16
-velocityjitter 224 224 224
-
-
-
-// used in qcsrc/server/w_rocketlauncher.qc: pointparticles(particleeffectnum("rocketlauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
+ type spark
+ airfriction 1
+ alpha 644 956 684
+ bounce 1.600000
+ color 0xffa35b 0xfff2be
+ count 4
+ gravity 1
+ liquidfriction 0.800000
+ notunderwater
+ originjitter 16 16 16
+ size 1 0.100000
+ tex 40 40
+ velocityjitter 224 224 224
+ velocityoffset 0 0 80
effect rocketlauncher_muzzleflash
-count 10
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 1 1
-sizeincrease 20
-alpha 256 256 256
-airfriction 2
-originjitter 1.5 1.5 1.5
-velocityjitter 40 40 40
-velocitymultiplier -0.13
-//lightradius 200
-//lightradiusfade 2000
-//lightcolor 2 1.5 0.2
+ type smoke
+ airfriction 2
+ alpha 256 256 256
+ color 0x202020 0x404040
+ count 10
+ originjitter 1.5 1.5 1.5
+ sizeincrease 20
+ size 1 1
+ tex 0 8
+ velocityjitter 40 40 40
+ velocitymultiplier -0.130000
effect rocketlauncher_muzzleflash
-count 6
-type smoke
-tex 35 36
-color 0xFFFDD9 0xFFFDD9
-size 5 10
-sizeincrease 20
-alpha 10 25 20
-originjitter 3 3 3
-velocityjitter 100 100 100
-velocitymultiplier 0.3
-airfriction 9
-rotate -180 180 -30 30
-
-
-
-// rocket trail
-// smoke
-// used in qcsrc/server/cl_client.qc: self.modelflags |= MF_ROCKET
-// used in qcsrc/server/cl_client.qc: self.modelflags &~= MF_ROCKET
-// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_ROCKET"), from, to)
-// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_ROCKET"), from, to)
+ type smoke
+ airfriction 9
+ alpha 10 25 20
+ color 0xFFFDD9 0xFFFDD9
+ count 6
+ originjitter 3 3 3
+ rotate -180 180 -30 30
+ sizeincrease 20
+ size 5 10
+ tex 35 36
+ velocityjitter 100 100 100
+ velocitymultiplier 0.300000
effect TR_ROCKET
-trailspacing 10
-type smoke
-notunderwater
-color 0x000000 0x666666
-tex 0 8
-size 3 4
-bounce 1
-sizeincrease 11
-alpha 200 300 200
-lightradius 150
-lighttime 0
-lightcolor 6 3 1
-originjitter 2 2 2
-velocityjitter 3 3 3
-velocitymultiplier -0.02
-rotate -180 180 -30 30
-//gravity -0.11
-// fire
+ type smoke
+ alpha 200 300 200
+ bounce 1
+ color 0x000000 0x666666
+ lightcolor 6 3 1
+ lightradius 150
+ notunderwater
+ originjitter 2 2 2
+ rotate -180 180 -30 30
+ sizeincrease 11
+ size 3 4
+ tex 0 8
+ trailspacing 10
+ velocityjitter 3 3 3
+ velocitymultiplier -0.020000
effect TR_ROCKET
-trailspacing 4
-type static
-color 0xffdf72 0x811200
-tex 48 55
-size 7 7
-sizeincrease -30
-alpha 100 144 588
-airfriction 8
-velocityjitter 32 32 32
-velocitymultiplier -1.5
-// bubbles
+ type static
+ airfriction 8
+ alpha 100 144 588
+ color 0xffdf72 0x811200
+ sizeincrease -30
+ size 7 7
+ tex 48 55
+ trailspacing 4
+ velocityjitter 32 32 32
+ velocitymultiplier -1.500000
effect TR_ROCKET
-type bubble
-underwater
-trailspacing 16
-tex 62 62
-size 1 2
-alpha 256 256 256
-gravity -0.125
-bounce 1.5
-liquidfriction 4
-velocityjitter 16 16 16
-velocitymultiplier -0.31
-rotate 0 0 0 0
-// sparks
+ type bubble
+ alpha 256 256 256
+ bounce 1.500000
+ gravity -0.125000
+ liquidfriction 4
+ size 1 2
+ tex 62 62
+ trailspacing 16
+ underwater
+ velocityjitter 16 16 16
+ velocitymultiplier -0.310000
effect TR_ROCKET
-notunderwater
-trailspacing 20
-type spark
-tex 40 40
-color 0xFFFDD9 0xFFFDD9
-size 0.5 0.5
-alpha 444 512 1866
-stretchfactor 0.3
-//gravity 1
-bounce 1
-//velocityoffset 0 0 15
-airfriction 5
-originjitter 1 1 1
-velocityjitter 100 100 100
-velocitymultiplier -0.31
-
-// rocket explosion (bigger than mortar and hagar)
+ type spark
+ airfriction 5
+ alpha 444 512 1866
+ bounce 1
+ color 0xFFFDD9 0xFFFDD9
+ notunderwater
+ originjitter 1 1 1
+ size 0.500000 0.500000
+ stretchfactor 0.300000
+ tex 40 40
+ trailspacing 20
+ velocityjitter 100 100 100
+ velocitymultiplier -0.310000
effect rocket_explode
-countabsolute 1
-type decal
-tex 8 16
-size 72 72
-alpha 256 256 0
-originjitter 23 23 23
-lightradius 400
-lightradiusfade 750
-lightcolor 8 4 1
-// fire effect
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 8 4 1
+ lightradiusfade 750
+ lightradius 400
+ originjitter 23 23 23
+ size 72 72
+ tex 8 16
effect rocket_explode
-notunderwater
-count 32
-type static
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 33 44
-sizeincrease 45
-alpha 200 256 512
-bounce 1.5
-airfriction 8
-liquidfriction 8
-originjitter 8 8 8
-velocityjitter 512 512 512
-// fire effect 2
+ type static
+ airfriction 8
+ alpha 200 256 512
+ bounce 1.500000
+ color 0x8f0d00 0xff5a00
+ count 32
+ liquidfriction 8
+ notunderwater
+ originjitter 8 8 8
+ sizeincrease 45
+ size 33 44
+ tex 48 55
+ velocityjitter 512 512 512
effect rocket_explode
-notunderwater
-count 14
-type smoke
-tex 48 55
-color 0xea691b 0xeed05a
-size 33 44
-sizeincrease 55
-alpha 200 256 612
-bounce 2.5
-airfriction 19
-liquidfriction 19
-originjitter 8 8 8
-velocityjitter 912 912 912
-// smoke
+ type smoke
+ airfriction 19
+ alpha 200 256 612
+ bounce 2.500000
+ color 0xea691b 0xeed05a
+ count 14
+ liquidfriction 19
+ notunderwater
+ originjitter 8 8 8
+ sizeincrease 55
+ size 33 44
+ tex 48 55
+ velocityjitter 912 912 912
effect rocket_explode
-type alphastatic
-notunderwater
-tex 0 8
-count 32
-size 20 40
-sizeincrease 44
-alpha 200 450 456
-velocityjitter 444 444 444
-airfriction 5
-color 0x000000 0x111111
-bounce 2
-// underwater bubbles
+ type alphastatic
+ airfriction 5
+ alpha 200 450 456
+ bounce 2
+ color 0x000000 0x111111
+ count 32
+ notunderwater
+ sizeincrease 44
+ size 20 40
+ tex 0 8
+ velocityjitter 444 444 444
effect rocket_explode
-underwater
-count 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 16 16 16
-velocityjitter 144 144 144
-// underwatershockwave
+ type bubble
+ alpha 128 256 64
+ bounce 1.500000
+ color 0x404040 0x808080
+ count 32
+ gravity -0.125000
+ liquidfriction 0.250000
+ originjitter 16 16 16
+ size 3 3
+ tex 62 62
+ underwater
+ velocityjitter 144 144 144
effect rocket_explode
-underwater
-type smoke
-countabsolute 1
-tex 33 33
-size 30 30
-sizeincrease 1900
-alpha 40 40 300
-velocitymultiplier 0.3
-// bouncing sparks
+ type smoke
+ alpha 40 40 300
+ countabsolute 1
+ sizeincrease 1900
+ size 30 30
+ tex 33 33
+ underwater
+ velocitymultiplier 0.300000
effect rocket_explode
-notunderwater
-count 16
-type spark
-tex 40 40
-color 0xffa35b 0xfff2be
-size 1 0.1
-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
-// debris
+ type spark
+ airfriction 1
+ alpha 644 956 484
+ bounce 1.600000
+ color 0xffa35b 0xfff2be
+ count 16
+ gravity 1
+ liquidfriction 0.800000
+ notunderwater
+ originjitter 16 16 16
+ size 1 0.100000
+ tex 40 40
+ velocityjitter 424 424 624
+ velocityoffset 0 0 80
effect rocket_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
-
-// used in qcsrc/server/g_hook.qc: pointparticles(particleeffectnum("grapple_muzzleflash"), org, '0 0 0', 1)
+ type alphastatic
+ airfriction 0.500000
+ alpha 644 956 684
+ bounce 1.600000
+ color 0x6a3d25 0xcac5b4
+ count 12
+ gravity 1.300000
+ notunderwater
+ rotate -180 180 -1000 1000
+ size 2 6
+ tex 66 68
+ velocityjitter 324 324 524
effect grapple_muzzleflash
-lightradius 160
-lightradiusfade 800
-lightcolor 1 0 0
-
-
-
-// used in qcsrc/server/g_hook.qc: pointparticles(particleeffectnum("grapple_impact"), self.origin, '0 0 0', 1)
+ lightcolor 1 0 0
+ lightradiusfade 800
+ lightradius 160
effect grapple_impact
-lightradius 160
-lightradiusfade 800
-lightcolor 1 0 0
-
-
-
-// used nowhere in code
+ lightcolor 1 0 0
+ lightradiusfade 800
+ lightradius 160
effect nex242_misc_laser_beam
-countabsolute 1
-type beam
-tex 200 200
-size 1 1
-alpha 256 256 64
-color 0xff0000 0xff0000
-sizeincrease 1
-
-// used nowhere in code
+ type beam
+ alpha 256 256 64
+ color 0xff0000 0xff0000
+ countabsolute 1
+ sizeincrease 1
+ size 1 1
+ tex 200 200
effect nex242_misc_laser_beam_end
-count 0.5
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 128 256 768
-gravity 1
-bounce -1
-velocityjitter 64 64 64
-velocitymultiplier 100
-
-
-
-// used nowhere in code
+ type spark
+ alpha 128 256 768
+ bounce -1
+ color 0x8f4333 0xfff31b
+ count 0.500000
+ gravity 1
+ size 0.400000 0.400000
+ velocityjitter 64 64 64
+ velocitymultiplier 100
effect nex242_misc_laser_beam_fast
-countabsolute 1
-type beam
-tex 200 200
-size 1 1
-alpha 256 256 640
-color 0xff0000 0xff0000
-sizeincrease 0.1
-
-// used nowhere in code
+ type beam
+ alpha 256 256 640
+ color 0xff0000 0xff0000
+ countabsolute 1
+ sizeincrease 0.100000
+ size 1 1
+ tex 200 200
effect nex242_misc_laser_beam_fast_end
-count 0.5
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 128 256 768
-gravity 1
-bounce -1
-velocityjitter 64 64 64
-velocitymultiplier 100
-
-// additional laser colors (mike)
-// used nowhere in code
+ type spark
+ alpha 128 256 768
+ bounce -1
+ color 0x8f4333 0xfff31b
+ count 0.500000
+ gravity 1
+ size 0.400000 0.400000
+ velocityjitter 64 64 64
+ velocitymultiplier 100
effect nex242_misc_laser_green_beam
-countabsolute 1
-type beam
-tex 200 200
-size 1 1
-alpha 256 256 64
-color 0x00ff00 0x00ff00
-sizeincrease 1
-
-// used nowhere in code
+ type beam
+ alpha 256 256 64
+ color 0x00ff00 0x00ff00
+ countabsolute 1
+ sizeincrease 1
+ size 1 1
+ tex 200 200
effect nex242_misc_laser_green_beam_end
-count 0.5
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 128 256 768
-gravity 1
-bounce -1
-velocityjitter 64 64 64
-velocitymultiplier 100
-
-// used nowhere in code
+ type spark
+ alpha 128 256 768
+ bounce -1
+ color 0x8f4333 0xfff31b
+ count 0.500000
+ gravity 1
+ size 0.400000 0.400000
+ velocityjitter 64 64 64
+ velocitymultiplier 100
effect nex242_misc_laser_blue_beam
-countabsolute 1
-type beam
-tex 200 200
-size 1 1
-alpha 256 256 64
-color 0x0000ff 0x0000ff
-sizeincrease 1
-
-// used nowhere in code
+ type beam
+ alpha 256 256 64
+ color 0x0000ff 0x0000ff
+ countabsolute 1
+ sizeincrease 1
+ size 1 1
+ tex 200 200
effect nex242_misc_laser_blue_beam_end
-count 0.5
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 128 256 768
-gravity 1
-bounce -1
-velocityjitter 64 64 64
-velocitymultiplier 100
-
-// used nowhere in code
+ type spark
+ alpha 128 256 768
+ bounce -1
+ color 0x8f4333 0xfff31b
+ count 0.500000
+ gravity 1
+ size 0.400000 0.400000
+ velocityjitter 64 64 64
+ velocitymultiplier 100
effect nex242_misc_laser_yellow_beam
-countabsolute 1
-type beam
-tex 200 200
-size 1 1
-alpha 256 256 64
-color 0xffff00 0xffff00
-sizeincrease 1
-
-// used nowhere in code
+ type beam
+ alpha 256 256 64
+ color 0xffff00 0xffff00
+ countabsolute 1
+ sizeincrease 1
+ size 1 1
+ tex 200 200
effect nex242_misc_laser_yellow_beam_end
-count 0.5
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 128 256 768
-gravity 1
-bounce -1
-velocityjitter 64 64 64
-velocitymultiplier 100
-
-// used nowhere in code
+ type spark
+ alpha 128 256 768
+ bounce -1
+ color 0x8f4333 0xfff31b
+ count 0.500000
+ gravity 1
+ size 0.400000 0.400000
+ velocityjitter 64 64 64
+ velocitymultiplier 100
effect nex242_misc_laser_cyan_beam
-countabsolute 1
-type beam
-tex 200 200
-size 1 1
-alpha 256 256 64
-color 0x00ffff 0x00ffff
-sizeincrease 1
-
-// used nowhere in code
+ type beam
+ alpha 256 256 64
+ color 0x00ffff 0x00ffff
+ countabsolute 1
+ sizeincrease 1
+ size 1 1
+ tex 200 200
effect nex242_misc_laser_cyan_beam_end
-count 0.5
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 128 256 768
-gravity 1
-bounce -1
-velocityjitter 64 64 64
-velocitymultiplier 100
-
-// used nowhere in code
+ type spark
+ alpha 128 256 768
+ bounce -1
+ color 0x8f4333 0xfff31b
+ count 0.500000
+ gravity 1
+ size 0.400000 0.400000
+ velocityjitter 64 64 64
+ velocitymultiplier 100
effect nex242_misc_laser_magenta_beam
-countabsolute 1
-type beam
-tex 200 200
-size 1 1
-alpha 256 256 64
-color 0xff00ff 0xff00ff
-sizeincrease 1
-
-// used nowhere in code
+ type beam
+ alpha 256 256 64
+ color 0xff00ff 0xff00ff
+ countabsolute 1
+ sizeincrease 1
+ size 1 1
+ tex 200 200
effect nex242_misc_laser_magenta_beam_end
-count 0.5
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 128 256 768
-gravity 1
-bounce -1
-velocityjitter 64 64 64
-velocitymultiplier 100
-
-// used nowhere in code
+ type spark
+ alpha 128 256 768
+ bounce -1
+ color 0x8f4333 0xfff31b
+ count 0.500000
+ gravity 1
+ size 0.400000 0.400000
+ velocityjitter 64 64 64
+ velocitymultiplier 100
effect nex242_misc_laser_white_beam
-countabsolute 1
-type beam
-tex 200 200
-size 1 1
-alpha 256 256 64
-color 0xffffff 0xffffff
-sizeincrease 1
-
-// used nowhere in code
+ type beam
+ alpha 256 256 64
+ color 0xffffff 0xffffff
+ countabsolute 1
+ sizeincrease 1
+ size 1 1
+ tex 200 200
effect nex242_misc_laser_white_beam_end
-count 0.5
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 128 256 768
-gravity 1
-bounce -1
-velocityjitter 64 64 64
-velocitymultiplier 100
-
-// used nowhere in code
+ type spark
+ alpha 128 256 768
+ bounce -1
+ color 0x8f4333 0xfff31b
+ count 0.500000
+ gravity 1
+ size 0.400000 0.400000
+ velocityjitter 64 64 64
+ velocitymultiplier 100
effect nex242_misc_laser_black_beam
-countabsolute 1
-type beam
-tex 200 200
-size 1 1
-alpha 256 256 64
-color 0x000000 0x000000
-sizeincrease 1
-
-// used nowhere in code
+ type beam
+ alpha 256 256 64
+ color 0x000000 0x000000
+ countabsolute 1
+ sizeincrease 1
+ size 1 1
+ tex 200 200
effect nex242_misc_laser_black_beam_end
-count 0.5
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 128 256 768
-gravity 1
-bounce -1
-velocityjitter 64 64 64
-velocitymultiplier 100
-
-// used nowhere in code
+ type spark
+ alpha 128 256 768
+ bounce -1
+ color 0x8f4333 0xfff31b
+ count 0.500000
+ gravity 1
+ size 0.400000 0.400000
+ velocityjitter 64 64 64
+ velocitymultiplier 100
effect nex242_misc_laser_orange_beam
-countabsolute 1
-type beam
-tex 200 200
-size 1 1
-alpha 256 256 64
-color 0xff6600 0xff6600
-sizeincrease 1
-
-// used nowhere in code
+ type beam
+ alpha 256 256 64
+ color 0xff6600 0xff6600
+ countabsolute 1
+ sizeincrease 1
+ size 1 1
+ tex 200 200
effect nex242_misc_laser_orange_beam_end
-count 0.5
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 128 256 768
-gravity 1
-bounce -1
-velocityjitter 64 64 64
-velocitymultiplier 100
-
-
-
-
-// bigger crylink impact effect
-// decal
-// used in qcsrc/client/damage.qc: pointparticles(particleeffectnum("crylink_impactbig"), org2, '0 0 0', 1)
+ type spark
+ alpha 128 256 768
+ bounce -1
+ color 0x8f4333 0xfff31b
+ count 0.500000
+ gravity 1
+ size 0.400000 0.400000
+ velocityjitter 64 64 64
+ velocitymultiplier 100
effect crylink_impactbig
-countabsolute 1
-type decal
-tex 47 47
-size 24 24
-alpha 256 256 0
-originjitter 12 12 12
-//lightradius 200
-//lightradiusfade 800
-//lightcolor 3.2 0.4 4
-// purple flare effect
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ originjitter 12 12 12
+ size 24 24
+ tex 47 47
effect crylink_impactbig
-countabsolute 1
-type static
-tex 39 39
-color 0x504060 0x504060
-size 24 24
-alpha 256 256 512
-// purple sparks
+ type static
+ alpha 256 256 512
+ color 0x504060 0x504060
+ countabsolute 1
+ size 24 24
+ tex 39 39
effect crylink_impactbig
-count 40
-type spark
-tex 41 41
-color 0xA040C0 0xA040C0
-bounce 2
-size 6 6
-alpha 256 256 1024
-velocityjitter 512 512 512
-// purple splash
+ type spark
+ alpha 256 256 1024
+ bounce 2
+ color 0xA040C0 0xA040C0
+ count 40
+ size 6 6
+ tex 41 41
+ velocityjitter 512 512 512
effect crylink_impactbig
-count 1.5
-type static
-color 0xE070FF 0xE070FF
-size 16 16
-alpha 256 256 512
-velocityjitter 32 32 32
-// purple splash
+ type static
+ alpha 256 256 512
+ color 0xE070FF 0xE070FF
+ count 1.500000
+ size 16 16
+ velocityjitter 32 32 32
effect crylink_impactbig
-count 3
-type static
-color 0xE070FF 0xE070FF
-size 16 16
-alpha 256 256 1024
-velocityjitter 256 256 256
-
-// Zero-violence effects
-
-// impact effect indicating damage
-// used in qcsrc/client/gibs.qc: pointparticles(particleeffectnum("damage_hit"), org, vel, amount * 16)
+ type static
+ alpha 256 256 1024
+ color 0xE070FF 0xE070FF
+ count 3
+ size 16 16
+ velocityjitter 256 256 256
effect damage_hit
-tex 48 55
-count 0.5
-type alphastatic
-color 0x00FFFF 0xFF00FF
-size 16 16
-sizeincrease -24
-alpha 128 128 192
-gravity -0.4
-bounce 1.5
-airfriction 5
-liquidfriction 10
-velocityjitter 256 256 256
+ type alphastatic
+ airfriction 5
+ alpha 128 128 192
+ bounce 1.500000
+ color 0x00FFFF 0xFF00FF
+ count 0.500000
+ gravity -0.400000
+ liquidfriction 10
+ sizeincrease -24
+ size 16 16
+ tex 48 55
+ velocityjitter 256 256 256
effect damage_hit
-tex 48 55
-count 0.5
-type alphastatic
-color 0xFF00FF 0xFFFF00
-size 16 16
-sizeincrease -24
-alpha 128 128 192
-gravity -0.4
-bounce 1.5
-airfriction 5
-liquidfriction 10
-velocityjitter 256 256 256
+ type alphastatic
+ airfriction 5
+ alpha 128 128 192
+ bounce 1.500000
+ color 0xFF00FF 0xFFFF00
+ count 0.500000
+ gravity -0.400000
+ liquidfriction 10
+ sizeincrease -24
+ size 16 16
+ tex 48 55
+ velocityjitter 256 256 256
effect damage_hit
-tex 48 55
-count 0.5
-type alphastatic
-color 0xFFFF00 0x00FFFF
-size 16 16
-sizeincrease -24
-alpha 128 128 192
-gravity -0.4
-bounce 1.5
-airfriction 5
-liquidfriction 10
-velocityjitter 256 256 256
-
-// effect for removing player model
-// "teleport"
-// NOTE: maintained by div0, make your own new effect instead of changing this one without asking!
-// large sparks
-// used in qcsrc/client/gibs.qc: pointparticles(particleeffectnum("damage_dissolve"), org, vel, amount)
+ type alphastatic
+ airfriction 5
+ alpha 128 128 192
+ bounce 1.500000
+ color 0xFFFF00 0x00FFFF
+ count 0.500000
+ gravity -0.400000
+ liquidfriction 10
+ sizeincrease -24
+ size 16 16
+ tex 48 55
+ velocityjitter 256 256 256
effect damage_dissolve
-tex 48 55
-count 15
-type alphastatic
-color 0x00FFFF 0xFF00FF
-size 32 32
-sizeincrease -16
-alpha 256 256 128
-gravity -0.4
-bounce 1.5
-airfriction 3
-liquidfriction 6
-velocityjitter 512 512 512
+ type alphastatic
+ airfriction 3
+ alpha 256 256 128
+ bounce 1.500000
+ color 0x00FFFF 0xFF00FF
+ count 15
+ gravity -0.400000
+ liquidfriction 6
+ sizeincrease -16
+ size 32 32
+ tex 48 55
+ velocityjitter 512 512 512
effect damage_dissolve
-tex 48 55
-count 15
-type alphastatic
-color 0xFF00FF 0xFFFF00
-size 32 32
-sizeincrease -16
-alpha 256 256 128
-gravity -0.4
-bounce 1.5
-airfriction 3
-liquidfriction 6
-velocityjitter 512 512 512
+ type alphastatic
+ airfriction 3
+ alpha 256 256 128
+ bounce 1.500000
+ color 0xFF00FF 0xFFFF00
+ count 15
+ gravity -0.400000
+ liquidfriction 6
+ sizeincrease -16
+ size 32 32
+ tex 48 55
+ velocityjitter 512 512 512
effect damage_dissolve
-tex 48 55
-count 15
-type alphastatic
-color 0xFFFF00 0x00FFFF
-size 32 32
-sizeincrease -16
-alpha 256 256 128
-gravity -0.4
-bounce 1.5
-airfriction 3
-liquidfriction 6
-velocityjitter 512 512 512
-
-
-// decal
-// used in qcsrc/server/g_triggers.qc: self.cnt = particleeffectnum("laser_deadly")
-// used in qcsrc/server/g_triggers.qc: self.cnt = particleeffectnum("laser_deadly")
+ type alphastatic
+ airfriction 3
+ alpha 256 256 128
+ bounce 1.500000
+ color 0xFFFF00 0x00FFFF
+ count 15
+ gravity -0.400000
+ liquidfriction 6
+ sizeincrease -16
+ size 32 32
+ tex 48 55
+ velocityjitter 512 512 512
effect laser_deadly
-countabsolute 1
-type decal
-tex 56 59
-size 5 5
-alpha 256 256 0
-originjitter 6 6 6
-// dust/smoke drifting away from the impact
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ originjitter 6 6 6
+ size 5 5
+ tex 56 59
effect laser_deadly
-count 0.025
-type smoke
-tex 48 55
-color 0xFFFFFF 0xFFFFFF
-size 3 3
-alpha 0 64 64
-originjitter 1 1 1
-airfriction 7
-liquidfriction 16
-velocityjitter 15 15 15
-sizeincrease 2
-velocitymultiplier 20
-// sparks
+ type smoke
+ airfriction 7
+ alpha 0 64 64
+ color 0xFFFFFF 0xFFFFFF
+ count 0.025000
+ liquidfriction 16
+ originjitter 1 1 1
+ sizeincrease 2
+ size 3 3
+ tex 48 55
+ velocityjitter 15 15 15
+ velocitymultiplier 20
effect laser_deadly
-notunderwater
-count 0.025
-type spark
-tex 40 40
-color 0xFDFFD9 0xFDFFD9
-size 0.6 0.6
-alpha 256 256 768
-gravity 1
-bounce 1
-airfriction 5
-originjitter 1 1 1
-velocityjitter 100 100 100
-velocitymultiplier 100
-
-
-//torch
-//fire
-// used nowhere in code
+ type spark
+ airfriction 5
+ alpha 256 256 768
+ bounce 1
+ color 0xFDFFD9 0xFDFFD9
+ count 0.025000
+ gravity 1
+ notunderwater
+ originjitter 1 1 1
+ size 0.600000 0.600000
+ tex 40 40
+ velocityjitter 100 100 100
+ velocitymultiplier 100
effect torch_small
-//notunderwater
-count 8
-type smoke
-tex 48 55
-size 1 11
-alpha 200 256 512
-gravity -0.5
-color 0x8f0d00 0xff5a00
-//bounce 1
-sizeincrease -1
-originjitter 5 5 5
-velocityjitter 1 1 50
-// smoke
+ type smoke
+ alpha 200 256 512
+ color 0x8f0d00 0xff5a00
+ count 8
+ gravity -0.500000
+ originjitter 5 5 5
+ sizeincrease -1
+ size 1 11
+ tex 48 55
+ velocityjitter 1 1 50
effect torch_small
-type alphastatic
-count 4
-tex 0 8
-size 5 10
-sizeincrease 5
-alpha 200 256 200
-color 0x000000 0x111111
-gravity -0.3
-originjitter 3 3 3
-velocityjitter 11 11 50
-//bounce 1
-
-//fountain01
-// used nowhere in code
+ type alphastatic
+ alpha 200 256 200
+ color 0x000000 0x111111
+ count 4
+ gravity -0.300000
+ originjitter 3 3 3
+ sizeincrease 5
+ size 5 10
+ tex 0 8
+ velocityjitter 11 11 50
effect fountain01
-count 16
-tex 0 8
-size 10 15
-alpha 0 100 100
-gravity 0.6
-bounce 1
-sizeincrease 20
-type snow
-bounce 1
-originjitter 5 5 5
-velocityjitter 81 81 150
-color 0x7cbaff 0xcfd1ff
-velocitymultiplier 2
-
-// decal
-// used in qcsrc/client/damage.qc: pointparticles(particleeffectnum("hookbomb_explode"), org2, '0 0 0', 1)
+ type snow
+ alpha 0 100 100
+ bounce 1
+ color 0x7cbaff 0xcfd1ff
+ count 16
+ gravity 0.600000
+ originjitter 5 5 5
+ sizeincrease 20
+ size 10 15
+ tex 0 8
+ velocityjitter 81 81 150
+ velocitymultiplier 2
effect hookbomb_explode
-count 25
-type static
-tex 38 38
-color 0x807aff 0x4463d5
-size 150 200
-sizeincrease -160
-alpha 0 256 200
-//gravity 1
-bounce 1.5
-originjitter 10 10 10
-velocityjitter 550 550 550
-//velocitymultiplier -20
-airfriction 10
-// decal in the air
+ type static
+ airfriction 10
+ alpha 0 256 200
+ bounce 1.500000
+ color 0x807aff 0x4463d5
+ count 25
+ originjitter 10 10 10
+ sizeincrease -160
+ size 150 200
+ tex 38 38
+ velocityjitter 550 550 550
effect hookbomb_explode
-countabsolute 3
-type static
-tex 38 38
-color 0x807aff 0x4463d5
-size 160 200
-alpha 256 265 100
-sizeincrease -60
-originoffset 0 0 6
-// decal on the ground
+ type static
+ alpha 256 265 100
+ color 0x807aff 0x4463d5
+ countabsolute 3
+ originoffset 0 0 6
+ sizeincrease -60
+ size 160 200
+ tex 38 38
effect hookbomb_explode
-countabsolute 1
-type decal
-tex 39 39
-size 80 100
-alpha 256 256 0
-originjitter 6 6 6
-// some sparks
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ originjitter 6 6 6
+ size 80 100
+ tex 39 39
effect hookbomb_explode
-count 30
-type spark
-tex 38 38
-color 0x807aff 0x4463d5
-size 20 30
-alpha 256 256 456
-sizeincrease -60
-gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 1900 1900 1300
-velocitymultiplier 0.5
-airfriction 2
-
-
-// smoke
+ type spark
+ airfriction 2
+ alpha 256 256 456
+ bounce 1.500000
+ color 0x807aff 0x4463d5
+ count 30
+ gravity 1
+ originjitter 1 1 1
+ sizeincrease -60
+ size 20 30
+ tex 38 38
+ velocityjitter 1900 1900 1300
+ velocitymultiplier 0.500000
effect EF_MGTURRETTRAIL
-notunderwater
-trailspacing 10
-type smoke
-color 0xd0d0a0 0xffffff
-tex 0 8
-size 5 4
-alpha 128 196 768
-sizeincrease -8
-gravity -0.01
-// bubbles
+ type smoke
+ alpha 128 196 768
+ color 0xd0d0a0 0xffffff
+ gravity -0.010000
+ notunderwater
+ sizeincrease -8
+ size 5 4
+ tex 0 8
+ trailspacing 10
effect EF_MGTURRETTRAIL
-underwater
-trailspacing 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 1 1
-alpha 256 256 256
-gravity -0.125
-bounce 1.5
-liquidfriction 4
-velocityjitter 16 16 16
-
-//fire_big
-//fire
-// used nowhere in code
+ type bubble
+ alpha 256 256 256
+ bounce 1.500000
+ color 0x404040 0x808080
+ gravity -0.125000
+ liquidfriction 4
+ size 1 1
+ tex 62 62
+ trailspacing 32
+ underwater
+ velocityjitter 16 16 16
effect fire_big
-//notunderwater
-count 26
-type smoke
-tex 48 55
-size 11 31
-alpha 200 356 512
-gravity -0.5
-color 0x8f0d00 0xff5a00
-bounce 2
-sizeincrease -3
-originjitter 33 33 33
-velocityjitter 22 22 50
-// smoke
+ type smoke
+ alpha 200 356 512
+ bounce 2
+ color 0x8f0d00 0xff5a00
+ count 26
+ gravity -0.500000
+ originjitter 33 33 33
+ sizeincrease -3
+ size 11 31
+ tex 48 55
+ velocityjitter 22 22 50
effect fire_big
-type alphastatic
-count 11
-tex 0 8
-size 22 33
-sizeincrease 11
-alpha 200 256 200
-color 0x000000 0x111111
-gravity -0.3
-originjitter 44 44 44
-velocityjitter 11 11 50
-bounce 2
-
-//red_flare
-//smoke
-// used nowhere in code
+ type alphastatic
+ alpha 200 256 200
+ bounce 2
+ color 0x000000 0x111111
+ count 11
+ gravity -0.300000
+ originjitter 44 44 44
+ sizeincrease 11
+ size 22 33
+ tex 0 8
+ velocityjitter 11 11 50
effect red_flare
-type alphastatic
-count 10.5
-tex 0 8
-size 1 11
-sizeincrease 11
-alpha 200 256 160
-color 0xff0000 0xdc7171
-gravity -0.24
-originjitter 2 2 0
-velocityjitter 15 15 30
-bounce 1
-
-//blue_flare
-//smoke
-// used nowhere in code
+ type alphastatic
+ alpha 200 256 160
+ bounce 1
+ color 0xff0000 0xdc7171
+ count 10.500000
+ gravity -0.240000
+ originjitter 2 2 0
+ sizeincrease 11
+ size 1 11
+ tex 0 8
+ velocityjitter 15 15 30
effect blue_flare
-type alphastatic
-count 10.5
-tex 0 8
-size 1 11
-sizeincrease 11
-alpha 200 256 160
-color 0x0000ff 0x7194dc
-gravity -0.24
-originjitter 2 2 0
-velocityjitter 15 15 30
-bounce 1
-
-//smoke_ring
-//smoke
-// used in qcsrc/server/ctf.qc: pointparticles(particleeffectnum("smoke_ring"), 0.5 * (self.absmin + self.absmax), '0 0 0', 1);
+ type alphastatic
+ alpha 200 256 160
+ bounce 1
+ color 0x0000ff 0x7194dc
+ count 10.500000
+ gravity -0.240000
+ originjitter 2 2 0
+ sizeincrease 11
+ size 1 11
+ tex 0 8
+ velocityjitter 15 15 30
effect smoke_ring
-type smoke
-count 45
-tex 0 8
-size 1 11
-sizeincrease 21
-gravity 0.1
-airfriction 3
-alpha 100 156 200
-color 0x111111 0x979797
-//originjitter 2 2 0
-velocityjitter 190 190 50
-bounce 1.1
-notunderwater
-
-//smoke_large
-//smoke
-// used nowhere in code
+ type smoke
+ airfriction 3
+ alpha 100 156 200
+ bounce 1.100000
+ color 0x111111 0x979797
+ count 45
+ gravity 0.100000
+ notunderwater
+ sizeincrease 21
+ size 1 11
+ tex 0 8
+ velocityjitter 190 190 50
effect smoke_large
-type alphastatic
-count 25
-tex 0 8
-size 11 21
-sizeincrease 21
-gravity -0.15
-airfriction 7
-alpha 140 256 190
-color 0x9e895f 0xffd39b
-//originjitter 2 2 0
-velocityjitter 390 390 390
-bounce 1.1
-notunderwater
-
-//sparks
-// used nowhere in code
+ type alphastatic
+ airfriction 7
+ alpha 140 256 190
+ bounce 1.100000
+ color 0x9e895f 0xffd39b
+ count 25
+ gravity -0.150000
+ notunderwater
+ sizeincrease 21
+ size 11 21
+ tex 0 8
+ velocityjitter 390 390 390
effect sparks
-count 15
-type spark
-tex 40 40
-color 0xFFFDD9 0xFFFDD9
-size 1 3
-alpha 0 256 256
-gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 300 300 200
-velocitymultiplier 1.5
-airfriction 3
-
-//sparks
-// used nowhere in code
+ type spark
+ airfriction 3
+ alpha 0 256 256
+ bounce 1.500000
+ color 0xFFFDD9 0xFFFDD9
+ count 15
+ gravity 1
+ originjitter 1 1 1
+ size 1 3
+ tex 40 40
+ velocityjitter 300 300 200
+ velocitymultiplier 1.500000
effect electricity_sparks
-count 35
-type spark
-tex 40 40
-color 0x807aff 0x4463d5
-size 1 3
-alpha 0 256 556
-gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 300 300 300
-velocitymultiplier 0.5
-airfriction 3
-
-//steam, it needs direction
-// used nowhere in code
+ type spark
+ airfriction 3
+ alpha 0 256 556
+ bounce 1.500000
+ color 0x807aff 0x4463d5
+ count 35
+ gravity 1
+ originjitter 1 1 1
+ size 1 3
+ tex 40 40
+ velocityjitter 300 300 300
+ velocitymultiplier 0.500000
effect steam
-type smoke
-count 1
-tex 0 8
-size 1 3
-sizeincrease 7
-gravity -0.25
-velocitymultiplier 14
-airfriction 5
-alpha 140 256 190
-color 0xfffbdf 0xffffff
-//originjitter 2 2 0
-velocityjitter 19 19 19
-bounce 1.1
-notunderwater
-
-// smoke emiter
-// used nowhere in code
+ type smoke
+ airfriction 5
+ alpha 140 256 190
+ bounce 1.100000
+ color 0xfffbdf 0xffffff
+ count 1
+ gravity -0.250000
+ notunderwater
+ sizeincrease 7
+ size 1 3
+ tex 0 8
+ velocityjitter 19 19 19
+ velocitymultiplier 14
effect smoking
-count 10
-type alphastatic
-tex 0 8
-color 0x292929 0x000000
-size 10 40
-sizeincrease 5
-alpha 100 256 100
-gravity -0.1
-bounce 1.5
-originjitter 10 10 10
-velocityjitter 5 5 20
-//velocitymultiplier -20
-airfriction -1
-
-//golden dust (create it once per second to cover large area in small yellow particles)
-// used nowhere in code
+ type alphastatic
+ airfriction -1
+ alpha 100 256 100
+ bounce 1.500000
+ color 0x292929 0x000000
+ count 10
+ gravity -0.100000
+ originjitter 10 10 10
+ sizeincrease 5
+ size 10 40
+ tex 0 8
+ velocityjitter 5 5 20
effect goldendust
-count 25
-type snow
-tex 38 38
-color 0xff9600 0xffefb8
-size 2 3
-sizeincrease -0.3
-alpha 256 256 70
-//gravity -0.1
-bounce 1.5
-originjitter 500 500 500
-velocityjitter 0.1 0.1 0.1
-//velocitymultiplier -20
-//airfriction -0.1
-
-// used nowhere in code
+ type snow
+ alpha 256 256 70
+ bounce 1.500000
+ color 0xff9600 0xffefb8
+ count 25
+ originjitter 500 500 500
+ sizeincrease -0.300000
+ size 2 3
+ tex 38 38
+ velocityjitter 0.1 0.1 0.1
effect healing_fx
-count 25
-type spark
-tex 40 40
-color 0xff0000 0xff0000
-size 1 3
-sizeincrease -0.05
-alpha 256 256 170
-gravity -0.1
-bounce 1.5
-originjitter 5 5 100
-velocityjitter 50 50 0
-//velocitymultiplier 20
-airfriction -0.5
-
-// used nowhere in code
+ type spark
+ airfriction -0.500000
+ alpha 256 256 170
+ bounce 1.500000
+ color 0xff0000 0xff0000
+ count 25
+ gravity -0.100000
+ originjitter 5 5 100
+ sizeincrease -0.050000
+ size 1 3
+ tex 40 40
+ velocityjitter 50 50 0
effect armorrepair_fx
-count 25
-type spark
-tex 40 40
-color 0x00ff00 0x00ff00
-size 1 3
-sizeincrease -0.05
-alpha 256 256 170
-gravity -0.1
-bounce 1.5
-originjitter 5 5 50
-velocityjitter 50 50 0
-//velocitymultiplier 20
-airfriction -0.5
-
-// used nowhere in code
+ type spark
+ airfriction -0.500000
+ alpha 256 256 170
+ bounce 1.500000
+ color 0x00ff00 0x00ff00
+ count 25
+ gravity -0.100000
+ originjitter 5 5 50
+ sizeincrease -0.050000
+ size 1 3
+ tex 40 40
+ velocityjitter 50 50 0
effect ammoregen_fx
-count 25
-type spark
-tex 40 40
-color 0x0000ff 0x0000ff
-size 1 3
-sizeincrease -0.05
-alpha 256 256 170
-gravity -0.1
-bounce 1.5
-originjitter 5 5 50
-velocityjitter 50 50 0
-//velocitymultiplier 20
-airfriction -0.5
-
-// red-yellow flame like fx
-// used nowhere in code
+ type spark
+ airfriction -0.500000
+ alpha 256 256 170
+ bounce 1.500000
+ color 0x0000ff 0x0000ff
+ count 25
+ gravity -0.100000
+ originjitter 5 5 50
+ sizeincrease -0.050000
+ size 1 3
+ tex 40 40
+ velocityjitter 50 50 0
effect rage
-count 2.5
-type smoke
-tex 35 36
-color 0xff0000 0xff7800
-size 1 3
-sizeincrease 10
-gravity -0.06
-alpha 256 256 190
-originjitter 5 5 5
-velocityjitter 25 25 25
-airfriction 2
-
-// pieces of glass or ice falling on the floor
-// used nowhere in code
+ type smoke
+ airfriction 2
+ alpha 256 256 190
+ color 0xff0000 0xff7800
+ count 2.500000
+ gravity -0.060000
+ originjitter 5 5 5
+ sizeincrease 10
+ size 1 3
+ tex 35 36
+ velocityjitter 25 25 25
effect iceorglass
-count 15
-type alphastatic
-tex 44 44
-color 0xffffff 0xb2d3e6
-size 3 7
-//sizeincrease 10
-gravity 1.3
-alpha 256 256 0
-time 1 3
-bounce 2
-originjitter 30 30 30
-velocityjitter 100 100 100
-airfriction 3
-
-// cover small area in poison gas, spawn it once per second
-// used nowhere in code
+ type alphastatic
+ airfriction 3
+ alpha 256 256 0
+ bounce 2
+ color 0xffffff 0xb2d3e6
+ count 15
+ gravity 1.300000
+ originjitter 30 30 30
+ size 3 7
+ tex 44 44
+ time 1 3
+ velocityjitter 100 100 100
effect poisonfield
-count 15
-type smoke
-tex 0 8
-color 0x00ff00 0x7db843
-size 1 1
-sizeincrease 30
- gravity -0.01
-alpha 256 256 50
-bounce 1.5
-originjitter 333 333 50
-velocityjitter 5 5 5
-airfriction 1
-
-// cover small area in icy mist, spawn it once per second
-// used nowhere in code
+ type smoke
+ airfriction 1
+ alpha 256 256 50
+ bounce 1.500000
+ color 0x00ff00 0x7db843
+ count 15
+ gravity -0.010000
+ originjitter 333 333 50
+ sizeincrease 30
+ size 1 1
+ tex 0 8
+ velocityjitter 5 5 5
effect icefield
-count 10
-type smoke
-tex 0 8
-color 0x008aff 0x75e7ff
-size 1 1
-sizeincrease 10
- gravity -0.01
-alpha 256 256 50
-bounce 1.5
-originjitter 333 333 0
-velocityjitter 5 5 30
-airfriction 1
+ type smoke
+ airfriction 1
+ alpha 256 256 50
+ bounce 1.500000
+ color 0x008aff 0x75e7ff
+ count 10
+ gravity -0.010000
+ originjitter 333 333 0
+ sizeincrease 10
+ size 1 1
+ tex 0 8
+ velocityjitter 5 5 30
effect icefield
-count 5
-type smoke
-tex 48 55
-size 1 1
-sizeincrease 10
-color 0x008aff 0x75e7ff
-alpha 256 256 50
-gravity -0.001
-originjitter 333 333 0
-
-
-// cover very small area in flames, spawn it 3 times per second (or more often to get better looking fire at cost of fps hit )
-// flames that go up
-// used nowhere in code
+ type smoke
+ alpha 256 256 50
+ color 0x008aff 0x75e7ff
+ count 5
+ gravity -0.001000
+ originjitter 333 333 0
+ sizeincrease 10
+ size 1 1
+ tex 48 55
effect firefield
-count 100
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 1 1
-sizeincrease 20
- gravity -0.06
-alpha 50 256 200
-bounce 1.5
-originjitter 180 180 0
-velocityjitter 5 5 30
-airfriction 1
-//flames that stay on the ground
+ type smoke
+ airfriction 1
+ alpha 50 256 200
+ bounce 1.500000
+ color 0x8f0d00 0xff5a00
+ count 100
+ gravity -0.060000
+ originjitter 180 180 0
+ sizeincrease 20
+ size 1 1
+ tex 48 55
+ velocityjitter 5 5 30
effect firefield
-count 50
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 1 1
-sizeincrease 40
-alpha 50 256 200
-originjitter 180 180 0
-// smoke
+ type smoke
+ alpha 50 256 200
+ color 0x8f0d00 0xff5a00
+ count 50
+ originjitter 180 180 0
+ sizeincrease 40
+ size 1 1
+ tex 48 55
effect firefield
-count 20
-type alphastatic
-tex 0 8
-size 1 1
-sizeincrease 7
-color 0x000000 0x111111
-alpha 256 256 70
-gravity -0.02
-originjitter 180 180 0
-
-//flamethrower, spawn it as fast as you can 20 times per second or more, it needs direction
-//fast fire
-// used nowhere in code
+ type alphastatic
+ alpha 256 256 70
+ color 0x000000 0x111111
+ count 20
+ gravity -0.020000
+ originjitter 180 180 0
+ sizeincrease 7
+ size 1 1
+ tex 0 8
effect flamethrower
-count 3
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 5 5
-sizeincrease 20
- gravity -0.06
-alpha 50 256 250
-bounce 1.5
-velocityjitter 40 40 11
-velocitymultiplier 30
-airfriction 1.2
-//slowfire
+ type smoke
+ airfriction 1.200000
+ alpha 50 256 250
+ bounce 1.500000
+ color 0x8f0d00 0xff5a00
+ count 3
+ gravity -0.060000
+ sizeincrease 20
+ size 5 5
+ tex 48 55
+ velocityjitter 40 40 11
+ velocitymultiplier 30
effect flamethrower
-count 2.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 5 5
-sizeincrease 20
- gravity -0.06
-alpha 50 256 200
-bounce 1.5
-velocityjitter 40 40 40
-velocitymultiplier 20
-airfriction 1.2
-// very slow and small fire
+ type smoke
+ airfriction 1.200000
+ alpha 50 256 200
+ bounce 1.500000
+ color 0x8f0d00 0xff5a00
+ count 2.500000
+ gravity -0.060000
+ sizeincrease 20
+ size 5 5
+ tex 48 55
+ velocityjitter 40 40 40
+ velocitymultiplier 20
effect flamethrower
-count 1.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 5 5
-sizeincrease 10
- gravity -0.06
-alpha 50 256 200
-bounce 1.5
-velocityjitter 30 30 30
-velocitymultiplier 10
-airfriction 0.3
-//decreasing fire
+ type smoke
+ airfriction 0.300000
+ alpha 50 256 200
+ bounce 1.500000
+ color 0x8f0d00 0xff5a00
+ count 1.500000
+ gravity -0.060000
+ sizeincrease 10
+ size 5 5
+ tex 48 55
+ velocityjitter 30 30 30
+ velocitymultiplier 10
effect flamethrower
-count 2
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 20 30
-sizeincrease -10
- gravity -0.06
-alpha 50 256 200
-bounce 1.5
-velocityjitter 10 10 10
-velocitymultiplier 15
-airfriction 0.3
-//smoke
+ type smoke
+ airfriction 0.300000
+ alpha 50 256 200
+ bounce 1.500000
+ color 0x8f0d00 0xff5a00
+ count 2
+ gravity -0.060000
+ sizeincrease -10
+ size 20 30
+ tex 48 55
+ velocityjitter 10 10 10
+ velocitymultiplier 15
effect flamethrower
-count 0.5
-type alphastatic
-tex 0 8
-size 5 15
-sizeincrease 7
-color 0x000000 0x111111
-alpha 256 256 90
-//gravity -0.2
-originjitter 10 10 10
-velocitymultiplier 20
-velocityoffset 0 0 10
-airfriction 1
-
-// port-o-launch trail
-// glowing vapor trail
-// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_WIZSPIKE"), from, to)
-// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_WIZSPIKE"), from, to)
+ type alphastatic
+ airfriction 1
+ alpha 256 256 90
+ color 0x000000 0x111111
+ count 0.500000
+ originjitter 10 10 10
+ sizeincrease 7
+ size 5 15
+ tex 0 8
+ velocitymultiplier 20
+ velocityoffset 0 0 10
effect TR_WIZSPIKE
-trailspacing 4
-type static
-color 0x404040 0x404040
-size 3 3
-tex 62 62
-alpha 256 256 968
-//velocityjitter 16 16 16
-lightradius 90
-lighttime 0
-lightcolor 1.5 3 6
-velocitymultiplier -0.1
-// bright sparks
+ type static
+ alpha 256 256 968
+ color 0x404040 0x404040
+ lightcolor 1.5 3 6
+ lightradius 90
+ size 3 3
+ tex 62 62
+ trailspacing 4
+ velocitymultiplier -0.100000
effect TR_WIZSPIKE
-trailspacing 12
-count 1.5
-type snow
-tex 42 42
-color 0x404040 0x404040
-size 2 4
-sizeincrease -20
-alpha 444 512 1866
-bounce 1
-velocityoffset 0 0 15
-airfriction 12
-originjitter 1 1 1
-velocityjitter 50 50 50
-
-// TAG trail
-// glowing vapor trail
-// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_VORESPIKE"), from, to)
-// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_VORESPIKE"), from, to)
+ type snow
+ airfriction 12
+ alpha 444 512 1866
+ bounce 1
+ color 0x404040 0x404040
+ count 1.500000
+ originjitter 1 1 1
+ sizeincrease -20
+ size 2 4
+ tex 42 42
+ trailspacing 12
+ velocityjitter 50 50 50
+ velocityoffset 0 0 15
effect TR_VORESPIKE
-trailspacing 4
-type static
-color 0x804000 0x804000
-size 3 3
-tex 62 62
-alpha 256 256 968
-//velocityjitter 16 16 16
-lightradius 90
-lighttime 0
-lightcolor 1.5 3 6
-velocitymultiplier -0.1
-// bright sparks
+ type static
+ alpha 256 256 968
+ color 0x804000 0x804000
+ lightcolor 1.5 3 6
+ lightradius 90
+ size 3 3
+ tex 62 62
+ trailspacing 4
+ velocitymultiplier -0.100000
effect TR_VORESPIKE
-trailspacing 12
-count 1.5
-type snow
-tex 42 42
-color 0xff8000 0xff8000
-size 2 4
-sizeincrease -20
-alpha 444 512 1866
-bounce 1
-velocityoffset 0 0 15
-airfriction 12
-originjitter 1 1 1
-velocityjitter 50 50 50
-
-// used in qcsrc/client/damage.qc: pointparticles(particleeffectnum("flac_explode"), org2, '0 0 0', 1)
+ type snow
+ airfriction 12
+ alpha 444 512 1866
+ bounce 1
+ color 0xff8000 0xff8000
+ count 1.500000
+ originjitter 1 1 1
+ sizeincrease -20
+ size 2 4
+ tex 42 42
+ trailspacing 12
+ velocityjitter 50 50 50
+ velocityoffset 0 0 15
effect flac_explode
-countabsolute 1
-type decal
-tex 8 16
-size 18 28
-alpha 256 256 0
-originjitter 40 40 40
-lightradius 150
-lightradiusfade 400
-lightcolor 8 4 1
-// fire effect which make bright dot inside
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 8 4 1
+ lightradiusfade 400
+ lightradius 150
+ originjitter 40 40 40
+ size 18 28
+ tex 8 16
effect flac_explode
-notunderwater
-count 3
-type smoke
-tex 48 55
-color 0xffe955 0xff5a00
-size 6 16
-sizeincrease 5
-alpha 128 256 456
-bounce 1.5
-airfriction 8
-liquidfriction 8
-originjitter 8 8 8
-velocityjitter 156 156 156
-// fire effect which expands then slows
+ type smoke
+ airfriction 8
+ alpha 128 256 456
+ bounce 1.500000
+ color 0xffe955 0xff5a00
+ count 3
+ liquidfriction 8
+ notunderwater
+ originjitter 8 8 8
+ sizeincrease 5
+ size 6 16
+ tex 48 55
+ velocityjitter 156 156 156
effect flac_explode
-notunderwater
-count 6
-type static
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 10 16
-sizeincrease 15
-alpha 128 256 456
-bounce 1.5
-airfriction 12
-liquidfriction 8
-originjitter 8 8 8
-velocityjitter 256 256 256
-
-// smoke
+ type static
+ airfriction 12
+ alpha 128 256 456
+ bounce 1.500000
+ color 0x8f0d00 0xff5a00
+ count 6
+ liquidfriction 8
+ notunderwater
+ originjitter 8 8 8
+ sizeincrease 15
+ size 10 16
+ tex 48 55
+ velocityjitter 256 256 256
effect flac_explode
-type alphastatic
-notunderwater
-tex 0 8
-count 5
-size 10 20
-sizeincrease 20
-alpha 500 600 556
-velocityjitter 244 244 244
-airfriction 5
-color 0x000000 0x111111
-bounce 2
-
-// underwater bubbles
+ type alphastatic
+ airfriction 5
+ alpha 500 600 556
+ bounce 2
+ color 0x000000 0x111111
+ count 5
+ notunderwater
+ sizeincrease 20
+ size 10 20
+ tex 0 8
+ velocityjitter 244 244 244
effect flac_explode
-underwater
-count 8
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 1 2
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 16 16 16
-velocityjitter 96 96 96
-// bouncing sparks
+ type bubble
+ alpha 128 256 64
+ bounce 1.500000
+ color 0x404040 0x808080
+ count 8
+ gravity -0.125000
+ liquidfriction 0.250000
+ originjitter 16 16 16
+ size 1 2
+ tex 62 62
+ underwater
+ velocityjitter 96 96 96
effect flac_explode
-notunderwater
-count 4
-type spark
-color 0x903010 0xFFD030
-size 2 2
-tex 40 40
-alpha 256 256 384
-gravity 1
-airfriction 0.2
-bounce 1.5
-liquidfriction 0.8
-velocityoffset 0 0 80
-velocityjitter 256 256 256
-
-
-// bullet trail (somewhat like a tracer)
-// used in qcsrc/server/w_common.qc: zcurveparticles_from_tracetoss(particleeffectnum("tr_bullet"), self.origin, trace_endpos, self.velocity)
-// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("tr_bullet"), from, to)
+ type spark
+ airfriction 0.200000
+ alpha 256 256 384
+ bounce 1.500000
+ color 0x903010 0xFFD030
+ count 4
+ gravity 1
+ liquidfriction 0.800000
+ notunderwater
+ size 2 2
+ tex 40 40
+ velocityjitter 256 256 256
+ velocityoffset 0 0 80
effect tr_bullet
-trailspacing 750
-type spark
-tex 70 70
-color 0xff8960 0xff8533
-alpha 256 256 2560
-size 4 4
-stretchfactor 0.2
-velocitymultiplier 3
-
-// smoke emitter for small pipes
-// used nowhere in code
+ type spark
+ alpha 256 256 2560
+ color 0xff8960 0xff8533
+ size 4 4
+ stretchfactor 0.200000
+ tex 70 70
+ trailspacing 750
+ velocitymultiplier 3
effect smoking_smallemitter
-count 10
-type alphastatic
-tex 0 8
-color 0x292929 0x000000
-size 6 15
-sizeincrease 20
-alpha 200 256 100
-gravity -0.1
-bounce 0
-originjitter 10 10 10
-velocityjitter 5 5 20
-//velocitymultiplier -20
-airfriction -1
-
-// crylink trail
-// plasma smoke
-// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_CRYLINKPLASMA"), from, to)
-// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_CRYLINKPLASMA"), from, to)
+ type alphastatic
+ airfriction -1
+ alpha 200 256 100
+ color 0x292929 0x000000
+ count 10
+ gravity -0.100000
+ originjitter 10 10 10
+ sizeincrease 20
+ size 6 15
+ tex 0 8
+ velocityjitter 5 5 20
effect TR_CRYLINKPLASMA
-trailspacing 128
-type static
-color 0x5522aa 0x6622ff
-size 2 2
-sizeincrease 8
-tex 32 32
-alpha 256 256 1024
-velocityjitter 8 8 8
-//lightradius 90
-//lighttime 0
-//lightcolor 1 0 1
-velocitymultiplier -0.01
-// crylink main trail
+ type static
+ alpha 256 256 1024
+ color 0x5522aa 0x6622ff
+ sizeincrease 8
+ size 2 2
+ tex 32 32
+ trailspacing 128
+ velocityjitter 8 8 8
+ velocitymultiplier -0.010000
effect TR_CRYLINKPLASMA
-trailspacing 16
-type static
-color 0x5522aa 0x6622ff
-size 3 3
-sizeincrease 15
-tex 3 3
-alpha 256 256 2600
-velocityjitter 2 2 2
-velocitymultiplier 0.01
-
+ type static
+ alpha 256 256 2600
+ color 0x5522aa 0x6622ff
+ sizeincrease 15
+ size 3 3
+ tex 3 3
+ trailspacing 16
+ velocityjitter 2 2 2
+ velocitymultiplier 0.010000
effect cherryblossom
-count 1.5
-type static
-color 0xb123ff 0xb183ff
-size 1.5 2
-alpha 128 256 32
-gravity 0.05
-bounce 1.5
-airfriction 1
-liquidfriction 1
-originjitter 16 16 16
-velocityjitter 32 32 0
-tex 40 40
-//lightradius 200
-//lighttime 0
-
+ type static
+ airfriction 1
+ alpha 128 256 32
+ bounce 1.500000
+ color 0xb123ff 0xb183ff
+ count 1.500000
+ gravity 0.050000
+ liquidfriction 1
+ originjitter 16 16 16
+ size 1.500000 2
+ tex 40 40
+ velocityjitter 32 32 0
effect alien_blood
-count 0.4
-type spark
-blend invmod
-tex 24 32
-size 5 11
-alpha 1560 2560 7000
-color 0xDC9BCD 0xDC9BCD
-bounce -1
-airfriction 0.4
-velocityjitter 99 99 55
-//velocitymultiplier 2
-staincolor 0xDC9BCD 0xDC9BCD
-staintex 16 24
-stainsize 1 2
-stretchfactor 25
-sizeincrease 20
-//blood mist
+ type spark
+ airfriction 0.400000
+ alpha 1560 2560 7000
+ blend invmod
+ bounce -1
+ color 0xDC9BCD 0xDC9BCD
+ count 0.400000
+ sizeincrease 20
+ size 5 11
+ staincolor 0xDC9BCD 0xDC9BCD
+ stainsize 1 2
+ staintex 16 24
+ stretchfactor 25
+ tex 24 32
+ velocityjitter 99 99 55
effect alien_blood
-countabsolute 1
-type smoke
-blend invmod
-tex 24 32
-size 25 30
-sizeincrease 20
-alpha 3000 5560 12000
-color 0xDC9BCD 0xDC9BCD
-originjitter 11 11 11
-
+ type smoke
+ alpha 3000 5560 12000
+ blend invmod
+ color 0xDC9BCD 0xDC9BCD
+ countabsolute 1
+ originjitter 11 11 11
+ sizeincrease 20
+ size 25 30
+ tex 24 32
effect robot_blood
-count 0.167
-type spark
-tex 70 70
-size 1 2
-alpha 256 256 64
-color 0xff3000 0xff7373
-bounce -1
-gravity 1
-airfriction 1
-liquidfriction 4
-velocityjitter 264 264 264
-velocityoffset 0 0 100
-//shockwave
+ type spark
+ airfriction 1
+ alpha 256 256 64
+ bounce -1
+ color 0xff3000 0xff7373
+ count 0.167000
+ gravity 1
+ liquidfriction 4
+ size 1 2
+ tex 70 70
+ velocityjitter 264 264 264
+ velocityoffset 0 0 100
effect robot_blood
-countabsolute 1
-type smoke
-tex 74 74
-size 2 2
-alpha 0 90 1000
-color 0xff8400 0xffbb72
-originjitter 11 11 11
-sizeincrease 800
-// electo sparcks
+ type smoke
+ alpha 0 90 1000
+ color 0xff8400 0xffbb72
+ countabsolute 1
+ originjitter 11 11 11
+ sizeincrease 800
+ size 2 2
+ tex 74 74
effect robot_blood
-count 0.1
-type smoke
-tex 71 73
-size 20 40
-alpha 256 256 5120
-color 0xff3000 0xff8585
-originjitter 41 41 21
-rotate -180 180 4000 -4000
-
-
-
+ type smoke
+ alpha 256 256 5120
+ color 0xff3000 0xff8585
+ count 0.100000
+ originjitter 41 41 21
+ rotate -180 180 4000 -4000
+ size 20 40
+ tex 71 73
effect alien_TR_BLOOD
-trailspacing 20
-type spark
-blend invmod
-color 0xC080B0 0xC080B0
-tex 24 32
-size 4 19
-alpha 384 984 1492
-bounce -1
-gravity 0.4
-airfriction -2
-liquidfriction 1
-velocityjitter 64 64 64
-velocitymultiplier -0.1
-staincolor 0xC080B0 0xC080B0
-staintex 16 24
-stainsize 1 2
-stretchfactor 7
-sizeincrease -5
-// splash around gib
-effect TR_BLOOD
-trailspacing 42
-type blood
-color 0xA8FFFF 0xA8FFFF
-tex 24 32
-size 4 6
-alpha 684 684 7492
-sizeincrease 500
-
+ type spark
+ airfriction -2
+ alpha 384 984 1492
+ blend invmod
+ bounce -1
+ color 0xC080B0 0xC080B0
+ gravity 0.400000
+ liquidfriction 1
+ sizeincrease -5
+ size 4 19
+ staincolor 0xC080B0 0xC080B0
+ stainsize 1 2
+ staintex 16 24
+ stretchfactor 7
+ tex 24 32
+ trailspacing 20
+ velocityjitter 64 64 64
+ velocitymultiplier -0.100000
effect robot_TR_BLOOD
-trailspacing 16
-type spark
-blend invmod
-color 0xC0D890 0xC0D890
-tex 24 32
-size 4 13
-alpha 384 984 1892
-bounce -1
-gravity 0.4
-airfriction -2
-liquidfriction 1
-velocityjitter 64 64 64
-velocitymultiplier -0.3
-staincolor 0x808080 0x808080
-staintex 16 24
-stainsize 1 3
-stretchfactor 6
-sizeincrease -6
-// fire
+ type spark
+ airfriction -2
+ alpha 384 984 1892
+ blend invmod
+ bounce -1
+ color 0xC0D890 0xC0D890
+ gravity 0.400000
+ liquidfriction 1
+ sizeincrease -6
+ size 4 13
+ staincolor 0x808080 0x808080
+ stainsize 1 3
+ staintex 16 24
+ stretchfactor 6
+ tex 24 32
+ trailspacing 16
+ velocityjitter 64 64 64
+ velocitymultiplier -0.300000
effect robot_TR_BLOOD
-notunderwater
-trailspacing 16
-type spark
-tex 48 55
-color 0x902010 0xff3600
-size 5 20
-alpha 128 256 900
-gravity -1
-airfriction 4
-liquidfriction 4
-stretchfactor 5
-sizeincrease 10
-velocityjitter 44 44 44
-// arcs
+ type spark
+ airfriction 4
+ alpha 128 256 900
+ color 0x902010 0xff3600
+ gravity -1
+ liquidfriction 4
+ notunderwater
+ sizeincrease 10
+ size 5 20
+ stretchfactor 5
+ tex 48 55
+ trailspacing 16
+ velocityjitter 44 44 44
effect robot_TR_BLOOD
-trailspacing 128
-type smoke
-tex 71 73
-color 0xff3000 0xff8585
-size 25 30
-alpha 1128 1256 44900
-rotate -180 180 4000 -4000
-velocityjitter 44 44 44
-
-
+ type smoke
+ alpha 1128 1256 44900
+ color 0xff3000 0xff8585
+ rotate -180 180 4000 -4000
+ size 25 30
+ tex 71 73
+ trailspacing 128
+ velocityjitter 44 44 44
effect alien_TR_SLIGHTBLOOD
-trailspacing 64
-type blood
-color 0xC080B0 0xC080B0
-tex 24 32
-size 80 80
-alpha 384 384 192
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 64 64 64
-velocitymultiplier 0.5
-staincolor 0x808080 0x808080
-staintex 16 24
-
+ type blood
+ airfriction 1
+ alpha 384 384 192
+ bounce -1
+ color 0xC080B0 0xC080B0
+ liquidfriction 4
+ size 80 80
+ staincolor 0x808080 0x808080
+ staintex 16 24
+ tex 24 32
+ trailspacing 64
+ velocityjitter 64 64 64
+ velocitymultiplier 0.500000
effect robot_TR_SLIGHTBLOOD
-trailspacing 64
-type blood
-color 0xC0D890 0xC0D890
-tex 24 32
-size 8 8
-alpha 384 384 192
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 64 64 64
-velocitymultiplier 0.5
-staincolor 0x808080 0x808080
-staintex 16 24
-
-// flare particle and light
-// used in qcsrc/server/t_items.qc: pointparticles(particleeffectnum("item_pickup"), self.origin, '0 0 0', 1)
+ type blood
+ airfriction 1
+ alpha 384 384 192
+ bounce -1
+ color 0xC0D890 0xC0D890
+ liquidfriction 4
+ size 8 8
+ staincolor 0x808080 0x808080
+ staintex 16 24
+ tex 24 32
+ trailspacing 64
+ velocityjitter 64 64 64
+ velocitymultiplier 0.500000
effect item_pickup
-countabsolute 1
-type static
-color 0x63F2EA 0xB0C5C4
-size 8 16
-alpha 128 64 64
-// cloud of particles which expand rapidly and then slow to form a ball
+ type static
+ alpha 128 64 64
+ color 0x63F2EA 0xB0C5C4
+ countabsolute 1
+ size 8 16
effect item_pickup
-count 32
-type spark
-tex 41 41
-color 0x63F2EA 0xB0C5C4
-size 1 1
-alpha 256 256 1280
-//originjitter 24 24 24
-velocityjitter 256 256 256
-
+ type spark
+ alpha 256 256 1280
+ color 0x63F2EA 0xB0C5C4
+ count 32
+ size 1 1
+ tex 41 41
+ velocityjitter 256 256 256
effect bloodshower
-count 125
-type spark
-blend invmod
-tex 24 32
-size 8 28
-color 0xA8FFFF 0xA8FFFFF
-alpha 156 656 1664
-bounce -1
-gravity 1
-stretchfactor 3
-liquidfriction 4
-velocityjitter 764 764 764
-// velocitymultiplier 1
-staincolor 0x808080 0x808080
-staintex 16 24
-stainsize 1 2
-// center blood
+ type spark
+ alpha 156 656 1664
+ blend invmod
+ bounce -1
+ color 0xA8FFFF 0xA8FFFFF
+ count 125
+ gravity 1
+ liquidfriction 4
+ size 8 28
+ staincolor 0x808080 0x808080
+ stainsize 1 2
+ staintex 16 24
+ stretchfactor 3
+ tex 24 32
+ velocityjitter 764 764 764
effect bloodshower
-countabsolute 0.1
-type smoke
-blend invmod
-tex 24 32
-size 1 28
-sizeincrease 300
-originjitter 50 50 50
-color 0xA8FFFF 0xA8FFFFF
-alpha 156 656 1664
-
-effect alien_bloodshower
-count 125
-type spark
-blend invmod
-tex 24 32
-size 8 28
-color 0xC080B0 0xC080B0
-alpha 156 656 1664
-bounce -1
-gravity 1
-stretchfactor 3
-liquidfriction 4
-velocityjitter 764 764 764
-// velocitymultiplier 1
-staincolor 0xC080B0 0xC080B0
-staintex 16 24
-stainsize 1 2
-// center blood
+ type smoke
+ alpha 156 656 1664
+ blend invmod
+ color 0xA8FFFF 0xA8FFFFF
+ countabsolute 0.100000
+ originjitter 50 50 50
+ sizeincrease 300
+ size 1 28
+ tex 24 32
effect bloodshower
-countabsolute 0.1
-type smoke
-blend invmod
-tex 24 32
-size 1 28
-sizeincrease 300
-originjitter 50 50 50
-color 0xA8FFFF 0xA8FFFFF
-alpha 156 656 1664
-
-
+ type smoke
+ alpha 156 656 1664
+ blend invmod
+ color 0xA8FFFF 0xA8FFFFF
+ countabsolute 0.100000
+ originjitter 50 50 50
+ sizeincrease 300
+ size 1 28
+ tex 24 32
+effect alien_bloodshower
+ type spark
+ alpha 156 656 1664
+ blend invmod
+ bounce -1
+ color 0xC080B0 0xC080B0
+ count 125
+ gravity 1
+ liquidfriction 4
+ size 8 28
+ staincolor 0xC080B0 0xC080B0
+ stainsize 1 2
+ staintex 16 24
+ stretchfactor 3
+ tex 24 32
+ velocityjitter 764 764 764
effect robot_bloodshower
-count 100
-type spark
-blend invmod
-tex 24 32
-size 8 28
-color 0xC0D890 0xC0D890
-alpha 156 656 1664
-bounce -1
-gravity 1
-stretchfactor 3
-liquidfriction 4
-velocityjitter 764 764 764
-// velocitymultiplier 1
-staincolor 0xC0D890 0xC0D890
-staintex 16 24
-stainsize 1 2
-// arc
+ type spark
+ alpha 156 656 1664
+ blend invmod
+ bounce -1
+ color 0xC0D890 0xC0D890
+ count 100
+ gravity 1
+ liquidfriction 4
+ size 8 28
+ staincolor 0xC0D890 0xC0D890
+ stainsize 1 2
+ staintex 16 24
+ stretchfactor 3
+ tex 24 32
+ velocityjitter 764 764 764
effect robot_bloodshower
-count 2.5
-type smoke
-tex 71 73
-color 0xff3000 0xff8585
-size 25 40
-alpha 1128 1256 4200
-rotate -180 180 99 -99
-velocityjitter 44 44 44
-originjitter 150 150 150
-// shockwave
+ type smoke
+ alpha 1128 1256 4200
+ color 0xff3000 0xff8585
+ count 2.500000
+ originjitter 150 150 150
+ rotate -180 180 99 -99
+ size 25 40
+ tex 71 73
+ velocityjitter 44 44 44
effect robot_bloodshower
-count 2.5
-type smoke
-tex 74 74
-color 0xff3000 0xff8585
-size 5 50
-sizeincrease 3000
-alpha 11 125 990
-
-//red_ground_quake
-//smoke
-// used in qsrc/server/ctf.qc: pointparticles(particleeffectnum("red_ground_quake"), self.origin, '0 0 0', 1);
+ type smoke
+ alpha 11 125 990
+ color 0xff3000 0xff8585
+ count 2.500000
+ sizeincrease 3000
+ size 5 50
+ tex 74 74
effect red_ground_quake
-type smoke
-count 90
-tex 0 8
-size 20 50
-sizeincrease 100
-gravity 0.5
-time 5 10
-airfriction 3
-alpha 100 126 200
-color 0x111111 0xbbbbbb
-//originjitter 2 2 0
-velocityjitter 190 190 50
-bounce 1.1
-notunderwater
+ type smoke
+ airfriction 3
+ alpha 100 126 200
+ bounce 1.100000
+ color 0x111111 0xbbbbbb
+ count 90
+ gravity 0.500000
+ notunderwater
+ sizeincrease 100
+ size 20 50
+ tex 0 8
+ time 5 10
+ velocityjitter 190 190 50
effect red_ground_quake
-type smoke
-count 40
-tex 0 8
-size 10 30
-sizeincrease 60
-gravity 0.2
-time 10 15
-airfriction 4
-alpha 100 126 200
-color 0x111111 0x979797
-//originjitter 2 2 0
-velocityjitter 190 190 50
-bounce 1.2
-notunderwater
+ type smoke
+ airfriction 4
+ alpha 100 126 200
+ bounce 1.200000
+ color 0x111111 0x979797
+ count 40
+ gravity 0.200000
+ notunderwater
+ sizeincrease 60
+ size 10 30
+ tex 0 8
+ time 10 15
+ velocityjitter 190 190 50
effect red_ground_quake
-//notunderwater
-count 16
-type smoke
-tex 48 55
-size 4 20
-time 15 25
-alpha 200 356 512
-gravity -0.5
-color 0x9E6A64 0x91302D
-bounce 6
-sizeincrease 5
-originjitter 33 33 33
-velocityjitter 22 22 50
-// smoke
+ type smoke
+ alpha 200 356 512
+ bounce 6
+ color 0x9E6A64 0x91302D
+ count 16
+ gravity -0.500000
+ originjitter 33 33 33
+ sizeincrease 5
+ size 4 20
+ tex 48 55
+ time 15 25
+ velocityjitter 22 22 50
effect red_ground_quake
-type alphastatic
-count 11
-tex 0 8
-size 22 33
-sizeincrease 11
-time 25 35
-alpha 200 256 200
-color 0x000000 0xffffff
-gravity -0.3
-originjitter 44 44 44
-velocityjitter 11 11 50
-bounce 2
-
-//blue_ground_quake
-//smoke
-// used in qsrc/server/ctf.qc: pointparticles(particleeffectnum("blue_ground_quake"), self.origin, '0 0 0', 1);
+ type alphastatic
+ alpha 200 256 200
+ bounce 2
+ color 0x000000 0xffffff
+ count 11
+ gravity -0.300000
+ originjitter 44 44 44
+ sizeincrease 11
+ size 22 33
+ tex 0 8
+ time 25 35
+ velocityjitter 11 11 50
effect blue_ground_quake
-type smoke
-count 90
-tex 0 8
-size 20 50
-sizeincrease 100
-gravity 0.5
-time 5 10
-airfriction 3
-alpha 100 126 200
-color 0x111111 0xbbbbbb
-//originjitter 2 2 0
-velocityjitter 190 190 50
-bounce 1.1
-notunderwater
+ type smoke
+ airfriction 3
+ alpha 100 126 200
+ bounce 1.100000
+ color 0x111111 0xbbbbbb
+ count 90
+ gravity 0.500000
+ notunderwater
+ sizeincrease 100
+ size 20 50
+ tex 0 8
+ time 5 10
+ velocityjitter 190 190 50
effect blue_ground_quake
-type smoke
-count 40
-tex 0 8
-size 10 30
-sizeincrease 60
-gravity 0.2
-time 10 15
-airfriction 4
-alpha 100 126 200
-color 0x111111 0x979797
-//originjitter 2 2 0
-velocityjitter 190 190 50
-bounce 1.2
-notunderwater
+ type smoke
+ airfriction 4
+ alpha 100 126 200
+ bounce 1.200000
+ color 0x111111 0x979797
+ count 40
+ gravity 0.200000
+ notunderwater
+ sizeincrease 60
+ size 10 30
+ tex 0 8
+ time 10 15
+ velocityjitter 190 190 50
effect blue_ground_quake
-//notunderwater
-count 16
-type smoke
-tex 48 55
-size 4 20
-time 15 25
-alpha 200 356 512
-gravity -0.5
-color 0x64679E 0x2D4C91
-bounce 6
-sizeincrease 5
-originjitter 33 33 33
-velocityjitter 22 22 50
-// smoke
+ type smoke
+ alpha 200 356 512
+ bounce 6
+ color 0x64679E 0x2D4C91
+ count 16
+ gravity -0.500000
+ originjitter 33 33 33
+ sizeincrease 5
+ size 4 20
+ tex 48 55
+ time 15 25
+ velocityjitter 22 22 50
effect blue_ground_quake
-type alphastatic
-count 11
-tex 0 8
-size 22 33
-sizeincrease 11
-time 25 35
-alpha 200 256 200
-color 0x000000 0xffffff
-gravity -0.3
-originjitter 44 44 44
-velocityjitter 11 11 50
-bounce 2
-
-
-
-// cl_gentle impact effect indicating damage
-// maintained by morphed
-// used in qcsrc/client/gibs.qc: pointparticles(particleeffectnum("damage_hit"), org, vel, amount * 16)
+ type alphastatic
+ alpha 200 256 200
+ bounce 2
+ color 0x000000 0xffffff
+ count 11
+ gravity -0.300000
+ originjitter 44 44 44
+ sizeincrease 11
+ size 22 33
+ tex 0 8
+ time 25 35
+ velocityjitter 11 11 50
effect morphed_damage_hit
-tex 43 43
-count 0.5
-type spark
-color 0xffffff 0x9271fb
-size 14 24
-sizeincrease -24
-alpha 128 128 292
-gravity -0.4
-airfriction 5
-liquidfriction 10
-velocityjitter 356 356 456
-
+ type spark
+ airfriction 5
+ alpha 128 128 292
+ color 0xffffff 0x9271fb
+ count 0.500000
+ gravity -0.400000
+ liquidfriction 10
+ sizeincrease -24
+ size 14 24
+ tex 43 43
+ velocityjitter 356 356 456
effect morphed_damage_hit
-tex 0 8
-count 0.5
-type smoke
-color 0xffffff 0x9271fb
-size 24 24
-sizeincrease -24
-alpha 128 128 292
-airfriction 5
-liquidfriction 10
-originjitter 10 10 10
-
-
-// effect for removing player model
-// "teleport"
-
-// cl_gentle deathfx
-// used in qcsrc/client/gibs.qc: pointparticles(particleeffectnum("damage_dissolve"), org, vel, amount)
+ type smoke
+ airfriction 5
+ alpha 128 128 292
+ color 0xffffff 0x9271fb
+ count 0.500000
+ liquidfriction 10
+ originjitter 10 10 10
+ sizeincrease -24
+ size 24 24
+ tex 0 8
effect morphed_damage_dissolve
-tex 43 43
-count 10
-type smoke
-color 0xffffff 0x9271fb
-size 40 40
-sizeincrease -16
-alpha 456 456 1828
-gravity -1.9
-airfriction 8
-liquidfriction 6
-velocityjitter 256 256 512
-rotate -180 180 -399 -99
-
+ type smoke
+ airfriction 8
+ alpha 456 456 1828
+ color 0xffffff 0x9271fb
+ count 10
+ gravity -1.900000
+ liquidfriction 6
+ rotate -180 180 -399 -99
+ sizeincrease -16
+ size 40 40
+ tex 43 43
+ velocityjitter 256 256 512
effect morphed_damage_dissolve
-tex 43 43
-count 2.5
-type smoke
-color 0x7bdbff 0xbed2ff
-size 40 40
-sizeincrease -16
-alpha 256 256 628
-gravity -0.8
-airfriction 9
-liquidfriction 6
-velocityjitter 256 256 512
-rotate -180 180 0 0
-
+ type smoke
+ airfriction 9
+ alpha 256 256 628
+ color 0x7bdbff 0xbed2ff
+ count 2.500000
+ gravity -0.800000
+ liquidfriction 6
+ rotate -180 180 0 0
+ sizeincrease -16
+ size 40 40
+ tex 43 43
+ velocityjitter 256 256 512
effect morphed_damage_dissolve
-tex 65 65
-count 5
-type smoke
-color 0xffffff 0x9271fb
-size 44 44
-sizeincrease -16
-alpha 156 156 128
-airfriction 3
-liquidfriction 6
-originjitter 22 22 76
-
+ type smoke
+ airfriction 3
+ alpha 156 156 128
+ color 0xffffff 0x9271fb
+ count 5
+ liquidfriction 6
+ originjitter 22 22 76
+ sizeincrease -16
+ size 44 44
+ tex 65 65
effect morphed_damage_dissolve
-tex 46 46
-count 15
-type smoke
-color 0xffffff 0x9271fb
-size 32 32
-sizeincrease -16
-alpha 56 56 128
-gravity 1
-bounce 1.5
-airfriction 3
-liquidfriction 6
-velocityjitter 400 400 0
-rotate -180 180 999 -999
-
-// Team / hit minsta effects
+ type smoke
+ airfriction 3
+ alpha 56 56 128
+ bounce 1.500000
+ color 0xffffff 0x9271fb
+ count 15
+ gravity 1
+ liquidfriction 6
+ rotate -180 180 999 -999
+ sizeincrease -16
+ size 32 32
+ tex 46 46
+ velocityjitter 400 400 0
effect TE_TEI_G3RED
-countabsolute 1
-type beam
-tex 200 200
-color 0xFF0000 0xFF0000
-size 4 4
-alpha 128 128 256
-// experimental
+ type beam
+ alpha 128 128 256
+ color 0xFF0000 0xFF0011
+ countabsolute 1
+ size 4 4
+ tex 200 200
effect TE_TEI_G3RED
-trailspacing 8
-type static
-color 0x200000 0x400000
-size 0.3 0.3
-sizeincrease 3
-tex 46 46
-alpha 256 256 512
-airfriction -4
-//liquidfriction -4
-velocityjitter 3 3 3
-type smoke
-
+ type smoke
+ airfriction -4
+ alpha 256 256 512
+ color 0x200000 0x400000
+ sizeincrease 3
+ size 0.300000 0.300000
+ tex 46 46
+ trailspacing 8
+ velocityjitter 3 3 3
effect TE_TEI_G3RED_HIT
-countabsolute 1
-type beam
-tex 200 200
-color 0xFF0000 0xFF0000
-size 8 8
-alpha 128 128 256
-// experimental
+ type beam
+ alpha 128 128 256
+ color 0xFF0000 0xFF0011
+ countabsolute 1
+ size 8 8
+ tex 200 200
effect TE_TEI_G3RED_HIT
-trailspacing 20
-type static
-color 0xFFFFFF 0xFF0011
-size 2 2
-sizeincrease -2
-alpha 256 256 512
-airfriction -4
-//liquidfriction -4
-velocityjitter 2 2 2
-type smoke
-// rings
+ type smoke
+ airfriction -4
+ alpha 256 256 512
+ color 0xFFFFFF 0xFF0011
+ sizeincrease -2
+ size 2 2
+ trailspacing 20
+ velocityjitter 2 2 2
effect TE_TEI_G3RED_HIT
-trailspacing 40
-type static
-color 0xFF0000 0xFF0011
-size 10 10
-sizeincrease -6
-alpha 256 256 512
-airfriction -4
-//liquidfriction -4
-type smoke
-
+ type smoke
+ airfriction -4
+ alpha 256 256 512
+ color 0xFF0000 0xFF0011
+ sizeincrease -6
+ size 10 10
+ trailspacing 40
effect TE_TEI_G3BLUE
-countabsolute 1
-type beam
-tex 200 200
-color 0x0000FF 0x1100FF
-size 4 4
-alpha 128 128 256
-// experimental
+ type beam
+ alpha 128 128 256
+ color 0x0000FF 0x1100FF
+ countabsolute 1
+ size 4 4
+ tex 200 200
effect TE_TEI_G3BLUE
-trailspacing 8
-type static
-color 0x000020 0x000040
-size 0.3 0.3
-sizeincrease 3
-tex 46 46
-alpha 256 256 512
-airfriction -4
-//liquidfriction -4
-velocityjitter 3 3 3
-type smoke
-
+ type smoke
+ airfriction -4
+ alpha 256 256 512
+ color 0x000020 0x000040
+ sizeincrease 3
+ size 0.300000 0.300000
+ tex 46 46
+ trailspacing 8
+ velocityjitter 3 3 3
effect TE_TEI_G3BLUE_HIT
-countabsolute 1
-type beam
-tex 200 200
-color 0x0000FF 0x1100FF
-size 8 8
-alpha 128 128 256
-// experimental
+ type beam
+ alpha 128 128 256
+ color 0x0000FF 0x1100FF
+ countabsolute 1
+ size 8 8
+ tex 200 200
effect TE_TEI_G3BLUE_HIT
-trailspacing 20
-type static
-color 0xFFFFFF 0x100FF
-size 2 2
-sizeincrease -2
-alpha 256 256 512
-airfriction -4
-//liquidfriction -4
-velocityjitter 2 2 2
-type smoke
-// rings
+ type smoke
+ airfriction -4
+ alpha 256 256 512
+ color 0xFFFFFF 0x1100FF
+ sizeincrease -2
+ size 2 2
+ trailspacing 20
+ velocityjitter 2 2 2
effect TE_TEI_G3BLUE_HIT
-trailspacing 40
-type static
-color 0x0000FF 0x1100FF
-size 10 10
-sizeincrease -6
-alpha 256 256 512
-airfriction -4
-//liquidfriction -4
-type smoke
-
-// Yellow
+ type smoke
+ airfriction -4
+ alpha 256 256 512
+ color 0x0000FF 0x1100FF
+ sizeincrease -6
+ size 10 10
+ trailspacing 40
effect TE_TEI_G3YELLOW
-countabsolute 1
-type beam
-tex 200 200
-color 0xffff00 0xffff11
-size 4 4
-alpha 128 128 256
+ type beam
+ alpha 128 128 256
+ color 0xffff00 0xffff11
+ countabsolute 1
+ size 4 4
+ tex 200 200
effect TE_TEI_G3YELLOW
-trailspacing 8
-type static
-color 0x202000 0x404000
-size 0.3 0.3
-sizeincrease 3
-tex 46 46
-alpha 256 256 512
-airfriction -4
-velocityjitter 3 3 3
-type smoke
-
+ type smoke
+ airfriction -4
+ alpha 256 256 512
+ color 0x202000 0x404000
+ sizeincrease 3
+ size 0.300000 0.300000
+ tex 46 46
+ trailspacing 8
+ velocityjitter 3 3 3
effect TE_TEI_G3YELLOW_HIT
-countabsolute 1
-type beam
-tex 200 200
-color 0xffff00 0xffff11
-size 8 8
-alpha 128 128 256
+ type beam
+ alpha 128 128 256
+ color 0xffff00 0xffff11
+ countabsolute 1
+ size 8 8
+ tex 200 200
effect TE_TEI_G3YELLOW_HIT
-trailspacing 20
-type static
-color 0xFFFFFF 0xffff10
-size 2 2
-sizeincrease -2
-alpha 256 256 512
-airfriction -4
-velocityjitter 2 2 2
-type smoke
-// rings
+ type smoke
+ airfriction -4
+ alpha 256 256 512
+ color 0xFFFFFF 0xffff11
+ sizeincrease -2
+ size 2 2
+ trailspacing 20
+ velocityjitter 2 2 2
effect TE_TEI_G3YELLOW_HIT
-trailspacing 40
-type static
-color 0xffff00 0xffff11
-size 10 10
-sizeincrease -6
-alpha 256 256 512
-airfriction -4
-//liquidfriction -4
-type smoke
-
-
-// Pink
+ type smoke
+ airfriction -4
+ alpha 256 256 512
+ color 0xffff00 0xffff11
+ sizeincrease -6
+ size 10 10
+ trailspacing 40
effect TE_TEI_G3PINK
-countabsolute 1
-type beam
-tex 200 200
-color 0xFF00FF 0xFF11FF
-size 4 4
-alpha 128 128 256
-// experimental
+ type beam
+ alpha 128 128 256
+ color 0xFF00FF 0xFF11FF
+ countabsolute 1
+ size 4 4
+ tex 200 200
effect TE_TEI_G3PINK
-trailspacing 8
-type static
-color 0x200020 0x400040
-size 0.3 0.3
-sizeincrease 3
-tex 46 46
-alpha 256 256 512
-airfriction -4
-//liquidfriction -4
-velocityjitter 3 3 3
-type smoke
-
+ type smoke
+ airfriction -4
+ alpha 256 256 512
+ color 0x200020 0x400040
+ sizeincrease 3
+ size 0.300000 0.300000
+ tex 46 46
+ trailspacing 8
+ velocityjitter 3 3 3
effect TE_TEI_G3PINK_HIT
-countabsolute 1
-type beam
-tex 200 200
-color 0xFF00FF 0xFF11FF
-size 8 8
-alpha 128 128 256
-// experimental
+ type beam
+ alpha 128 128 256
+ color 0xFF00FF 0xFF11FF
+ countabsolute 1
+ size 8 8
+ tex 200 200
effect TE_TEI_G3PINK_HIT
-trailspacing 20
-type static
-color 0xFFFFFF 0xFF10FF
-size 2 2
-sizeincrease -2
-alpha 256 256 512
-airfriction -4
-//liquidfriction -4
-velocityjitter 2 2 2
-type smoke
-// rings
+ type smoke
+ airfriction -4
+ alpha 256 256 512
+ color 0xFFFFFF 0xFF11FF
+ sizeincrease -2
+ size 2 2
+ trailspacing 20
+ velocityjitter 2 2 2
effect TE_TEI_G3PINK_HIT
-trailspacing 40
-type static
-color 0xFF00FF 0xFF11FF
-size 10 10
-sizeincrease -6
-alpha 256 256 512
-airfriction -4
-//liquidfriction -4
-type smoke
-
-
-
-
-// cl_gentle impact effect indicating damage
-// maintained by particlegibs
-// used in qcsrc/client/gibs.qc: pointparticles(particleeffectnum("damage_hit"), org, vel, amount * 16)
-// core decal
+ type smoke
+ airfriction -4
+ alpha 256 256 512
+ color 0xFF00FF 0xFF11FF
+ sizeincrease -6
+ size 10 10
+ trailspacing 40
effect particlegibs_damage_hit
-type blood
-count 0.5
-tex 0 8
-size 5 10
-color 0xA8FFFF 0xA8FFFFF
-alpha 256 256 428
-gravity 1
-bounce -1
-airfriction 3
-liquidfriction 6
-velocityjitter 156 156 212
-staincolor 0x808080 0x808080
-staintex 16 24
-// front blood
+ type blood
+ airfriction 3
+ alpha 256 256 428
+ bounce -1
+ color 0xA8FFFF 0xA8FFFFF
+ count 0.500000
+ gravity 1
+ liquidfriction 6
+ size 5 10
+ staincolor 0x808080 0x808080
+ staintex 16 24
+ tex 0 8
+ velocityjitter 156 156 212
effect particlegibs_damage_hit
-type blood
-count 0.1
-tex 24 32
-size 10 20
-color 0xA8FFFF 0xA8FFFFF
-sizeincrease -15
-alpha 256 256 328
-bounce -1
-gravity 0.5
-airfriction 1
-liquidfriction 3
-velocityjitter 6 6 30
-velocitymultiplier -1
-staincolor 0x808080 0x808080
-staintex 16 24
-// back blood
+ type blood
+ airfriction 1
+ alpha 256 256 328
+ bounce -1
+ color 0xA8FFFF 0xA8FFFFF
+ count 0.100000
+ gravity 0.500000
+ liquidfriction 3
+ sizeincrease -15
+ size 10 20
+ staincolor 0x808080 0x808080
+ staintex 16 24
+ tex 24 32
+ velocityjitter 6 6 30
+ velocitymultiplier -1
effect particlegibs_damage_hit
-type blood
-count 0.1
-tex 24 32
-size 5 15
-color 0xA8FFFF 0xA8FFFFF
-sizeincrease 10
-alpha 256 256 328
-bounce -1
-gravity 1
-airfriction 1
-liquidfriction 3
-velocityjitter 26 26 112
-originjitter 3 3 3
-velocitymultiplier 2
-staincolor 0x808080 0x808080
-staintex 16 24
-
-// effect for removing player model
-// "teleport"
-
-// cl_gentle deathfx
-// used in qcsrc/client/gibs.qc: pointparticles(particleeffectnum("damage_dissolve"), org, vel, amount)
-// small core blood no decals
+ type blood
+ airfriction 1
+ alpha 256 256 328
+ bounce -1
+ color 0xA8FFFF 0xA8FFFFF
+ count 0.100000
+ gravity 1
+ liquidfriction 3
+ originjitter 3 3 3
+ sizeincrease 10
+ size 5 15
+ staincolor 0x808080 0x808080
+ staintex 16 24
+ tex 24 32
+ velocityjitter 26 26 112
+ velocitymultiplier 2
effect particlegibs_damage_dissolve
-type blood
-count 32
-tex 0 8
-size 15 20
-color 0x00ffff 0x82ffff
-alpha 256 256 328
-gravity 1
-airfriction 3
-liquidfriction 6
-originjitter 10 10 25
-velocityjitter 256 256 312
-staincolor 0x808080 0x808080
-staintex 16 24
-// core decal
+ type blood
+ airfriction 3
+ alpha 256 256 328
+ color 0x00ffff 0x82ffff
+ count 32
+ gravity 1
+ liquidfriction 6
+ originjitter 10 10 25
+ size 15 20
+ staincolor 0x808080 0x808080
+ staintex 16 24
+ tex 0 8
+ velocityjitter 256 256 312
effect particlegibs_damage_dissolve
-type blood
-count 12
-tex 0 8
-size 20 40
-color 0xA8FFFF 0xA8FFFFF
-alpha 256 256 528
-gravity 2
-bounce -1
-airfriction 2
-liquidfriction 6
-originjitter 10 10 25
-velocityjitter 356 356 412
-staincolor 0x808080 0x808080
-staintex 16 24
-// front blood
+ type blood
+ airfriction 2
+ alpha 256 256 528
+ bounce -1
+ color 0xA8FFFF 0xA8FFFFF
+ count 12
+ gravity 2
+ liquidfriction 6
+ originjitter 10 10 25
+ size 20 40
+ staincolor 0x808080 0x808080
+ staintex 16 24
+ tex 0 8
+ velocityjitter 356 356 412
effect particlegibs_damage_dissolve
-type blood
-count 32
-tex 24 32
-size 10 20
-color 0xA8FFFF 0xA8FFFFF
-sizeincrease -15
-alpha 256 256 328
-bounce -1
-gravity 0.5
-airfriction 1
-liquidfriction 3
-velocityjitter 56 56 212
-originjitter 5 5 10
-velocitymultiplier -0.3
-staincolor 0x808080 0x808080
-staintex 16 24
-// back blood
+ type blood
+ airfriction 1
+ alpha 256 256 328
+ bounce -1
+ color 0xA8FFFF 0xA8FFFFF
+ count 32
+ gravity 0.500000
+ liquidfriction 3
+ originjitter 5 5 10
+ sizeincrease -15
+ size 10 20
+ staincolor 0x808080 0x808080
+ staintex 16 24
+ tex 24 32
+ velocityjitter 56 56 212
+ velocitymultiplier -0.300000
effect particlegibs_damage_dissolve
-type blood
-count 32
-tex 24 32
-size 5 15
-color 0xA8FFFF 0xA8FFFFF
-sizeincrease 10
-alpha 256 256 328
-bounce -1
-gravity 1
-airfriction 1
-liquidfriction 3
-velocityjitter 56 56 212
-originjitter 5 5 10
-velocitymultiplier 0.5
-staincolor 0x808080 0x808080
-staintex 16 24
-// small bits
+ type blood
+ airfriction 1
+ alpha 256 256 328
+ bounce -1
+ color 0xA8FFFF 0xA8FFFFF
+ count 32
+ gravity 1
+ liquidfriction 3
+ originjitter 5 5 10
+ sizeincrease 10
+ size 5 15
+ staincolor 0x808080 0x808080
+ staintex 16 24
+ tex 24 32
+ velocityjitter 56 56 212
+ velocitymultiplier 0.500000
effect particlegibs_damage_dissolve
-type blood
-count 75
-tex 24 32
-size 1 1
-color 0xA8FFFF 0xA8FFFFF
-sizeincrease 10
-alpha 256 256 328
-gravity 1
-airfriction 1.5
-liquidfriction 3
-originjitter 10 10 25
-velocityjitter 656 656 912
-staincolor 0x808080 0x808080
-staintex 16 24
-
-// fire effect which expands then slows
+ type blood
+ airfriction 1.500000
+ alpha 256 256 328
+ color 0xA8FFFF 0xA8FFFFF
+ count 75
+ gravity 1
+ liquidfriction 3
+ originjitter 10 10 25
+ sizeincrease 10
+ size 1 1
+ staincolor 0x808080 0x808080
+ staintex 16 24
+ tex 24 32
+ velocityjitter 656 656 912
effect onslaught_generator_gib_explode
-notunderwater
-count 17
-type static
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 20 26
-sizeincrease 45
-alpha 128 256 356
-bounce 1.5
-airfriction 5
-liquidfriction 8
-originjitter 8 8 8
-velocityjitter 286 286 286
-
-// smoke
+ type static
+ airfriction 5
+ alpha 128 256 356
+ bounce 1.500000
+ color 0x8f0d00 0xff5a00
+ count 17
+ liquidfriction 8
+ notunderwater
+ originjitter 8 8 8
+ sizeincrease 45
+ size 20 26
+ tex 48 55
+ velocityjitter 286 286 286
effect onslaught_generator_gib_explode
-type alphastatic
-notunderwater
-tex 0 8
-count 6
-size 1 10
-sizeincrease 90
-gravity -0.3
-alpha 200 500 600
-velocityjitter 244 244 244
-airfriction 5
-color 0x000000 0x111111
-bounce 2
-
-// underwater bubbles
+ type alphastatic
+ airfriction 5
+ alpha 200 500 600
+ bounce 2
+ color 0x000000 0x111111
+ count 6
+ gravity -0.300000
+ notunderwater
+ sizeincrease 90
+ size 1 10
+ tex 0 8
+ velocityjitter 244 244 244
effect onslaught_generator_gib_explode
-underwater
-count 16
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 16 16 16
-velocityjitter 96 96 96
-
-// fire effect which expands then slows
+ type bubble
+ alpha 128 256 64
+ bounce 1.500000
+ color 0x404040 0x808080
+ count 16
+ gravity -0.125000
+ liquidfriction 0.250000
+ originjitter 16 16 16
+ size 3 3
+ tex 62 62
+ underwater
+ velocityjitter 96 96 96
effect onslaught_generator_gib_flame
-notunderwater
-count 15
-type static
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 5 10
-sizeincrease 25
-alpha 128 256 356
-gravity -0.5
-airfriction 5
-liquidfriction 8
-originjitter 3 3 3
-velocityjitter 86 86 86
-// smoke
+ type static
+ airfriction 5
+ alpha 128 256 356
+ color 0x8f0d00 0xff5a00
+ count 15
+ gravity -0.500000
+ liquidfriction 8
+ notunderwater
+ originjitter 3 3 3
+ sizeincrease 25
+ size 5 10
+ tex 48 55
+ velocityjitter 86 86 86
effect onslaught_generator_gib_flame
-type alphastatic
-notunderwater
-tex 0 8
-count 1
-size 10 20
-sizeincrease 30
-gravity -0.8
-alpha 200 500 600
-velocityjitter 44 44 44
-airfriction 5
-color 0x000000 0x111111
-bounce 2
-
-// underwater bubbles
+ type alphastatic
+ airfriction 5
+ alpha 200 500 600
+ bounce 2
+ color 0x000000 0x111111
+ count 1
+ gravity -0.800000
+ notunderwater
+ sizeincrease 30
+ size 10 20
+ tex 0 8
+ velocityjitter 44 44 44
effect onslaught_generator_gib_flame
-underwater
-count 16
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 16 16 16
-velocityjitter 96 96 96
-
-
-// used nowhere in code
+ type bubble
+ alpha 128 256 64
+ bounce 1.500000
+ color 0x404040 0x808080
+ count 16
+ gravity -0.125000
+ liquidfriction 0.250000
+ originjitter 16 16 16
+ size 3 3
+ tex 62 62
+ underwater
+ velocityjitter 96 96 96
effect firemine
-trailspacing 2
-count 0.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 1 1
-sizeincrease 5
-gravity -0.06
-alpha 50 256 250
-bounce 1.5
-velocityjitter 10 10 2
-airfriction 1.2
-//slowfire
+ type smoke
+ airfriction 1.200000
+ alpha 50 256 250
+ bounce 1.500000
+ color 0x8f0d00 0xff5a00
+ count 0.500000
+ gravity -0.060000
+ sizeincrease 5
+ size 1 1
+ tex 48 55
+ trailspacing 2
+ velocityjitter 10 10 2
effect firemine
-trailspacing 2
-count 0.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 1 1
-sizeincrease 5
-gravity -0.06
-alpha 50 256 200
-bounce 1.5
-velocityjitter 10 10 10
-airfriction 1.2
-// very slow and small fire
+ type smoke
+ airfriction 1.200000
+ alpha 50 256 200
+ bounce 1.500000
+ color 0x8f0d00 0xff5a00
+ count 0.500000
+ gravity -0.060000
+ sizeincrease 5
+ size 1 1
+ tex 48 55
+ trailspacing 2
+ velocityjitter 10 10 10
effect firemine
-trailspacing 4
-count 0.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 1 1
-sizeincrease 2
-gravity -0.06
-alpha 50 256 200
-bounce 1.5
-velocityjitter 8 8 8
-airfriction 0.3
-//decreasing fire
+ type smoke
+ airfriction 0.300000
+ alpha 50 256 200
+ bounce 1.500000
+ color 0x8f0d00 0xff5a00
+ count 0.500000
+ gravity -0.060000
+ sizeincrease 2
+ size 1 1
+ tex 48 55
+ trailspacing 4
+ velocityjitter 8 8 8
effect firemine
-trailspacing 4
-count 0.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 5 7
-sizeincrease -3
-gravity -0.06
-alpha 50 256 200
-bounce 1.5
-velocityjitter 3 3 3
-airfriction 0.3
-//smoke
+ type smoke
+ airfriction 0.300000
+ alpha 50 256 200
+ bounce 1.500000
+ color 0x8f0d00 0xff5a00
+ count 0.500000
+ gravity -0.060000
+ sizeincrease -3
+ size 5 7
+ tex 48 55
+ trailspacing 4
+ velocityjitter 3 3 3
effect firemine
-trailspacing 8
-count 0.5
-type alphastatic
-tex 0 8
-size 1 4
-sizeincrease 1
-color 0x000000 0x111111
-alpha 256 256 90
-//gravity -0.2
-originjitter 2 2 2
-velocityoffset 0 0 3
-airfriction 1
-//fastfire
+ type alphastatic
+ airfriction 1
+ alpha 256 256 90
+ color 0x000000 0x111111
+ count 0.500000
+ originjitter 2 2 2
+ sizeincrease 1
+ size 1 4
+ tex 0 8
+ trailspacing 8
+ velocityoffset 0 0 3
effect firemine
-trailspacing 1
-count 0.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 12 12
-sizeincrease 0
-gravity 0
-alpha 50 256 1600
-bounce 1.5
-velocityjitter 0 0 0
-airfriction 1.2
-// light only
+ type smoke
+ airfriction 1.200000
+ alpha 50 256 1600
+ bounce 1.500000
+ color 0x8f0d00 0xff5a00
+ count 0.500000
+ size 12 12
+ tex 48 55
+ trailspacing 1
effect firemine
-trailspacing 16
-lightradius 50
-lightradiusfade 50000
-lightcolor 2.7 2.7 0.6
-
-// used nowhere in code
+ lightcolor 2.7 2.7 0.6
+ lightradiusfade 50000
+ lightradius 50
+ trailspacing 16
effect fireball
-trailspacing 2
-count 0.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 5 5
-sizeincrease 20
-gravity -0.06
-alpha 50 256 250
-bounce 1.5
-velocityjitter 40 40 11
-airfriction 1.2
-//slowfire
+ type smoke
+ airfriction 1.200000
+ alpha 50 256 250
+ bounce 1.500000
+ color 0x8f0d00 0xff5a00
+ count 0.500000
+ gravity -0.060000
+ sizeincrease 20
+ size 5 5
+ tex 48 55
+ trailspacing 2
+ velocityjitter 40 40 11
effect fireball
-trailspacing 2
-count 0.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 5 5
-sizeincrease 20
-gravity -0.06
-alpha 50 256 200
-bounce 1.5
-velocityjitter 40 40 40
-airfriction 1.2
-// very slow and small fire
+ type smoke
+ airfriction 1.200000
+ alpha 50 256 200
+ bounce 1.500000
+ color 0x8f0d00 0xff5a00
+ count 0.500000
+ gravity -0.060000
+ sizeincrease 20
+ size 5 5
+ tex 48 55
+ trailspacing 2
+ velocityjitter 40 40 40
effect fireball
-trailspacing 4
-count 0.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 5 5
-sizeincrease 10
-gravity -0.06
-alpha 50 256 200
-bounce 1.5
-velocityjitter 30 30 30
-airfriction 0.3
-//decreasing fire
+ type smoke
+ airfriction 0.300000
+ alpha 50 256 200
+ bounce 1.500000
+ color 0x8f0d00 0xff5a00
+ count 0.500000
+ gravity -0.060000
+ sizeincrease 10
+ size 5 5
+ tex 48 55
+ trailspacing 4
+ velocityjitter 30 30 30
effect fireball
-trailspacing 4
-count 0.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 20 30
-sizeincrease -10
-gravity -0.06
-alpha 50 256 200
-bounce 1.5
-velocityjitter 10 10 10
-airfriction 0.3
-//smoke
+ type smoke
+ airfriction 0.300000
+ alpha 50 256 200
+ bounce 1.500000
+ color 0x8f0d00 0xff5a00
+ count 0.500000
+ gravity -0.060000
+ sizeincrease -10
+ size 20 30
+ tex 48 55
+ trailspacing 4
+ velocityjitter 10 10 10
effect fireball
-trailspacing 8
-count 0.5
-type alphastatic
-tex 0 8
-size 5 15
-sizeincrease 7
-color 0x000000 0x111111
-alpha 256 256 90
-//gravity -0.2
-originjitter 10 10 10
-velocityoffset 0 0 10
-airfriction 1
-//fastfire
+ type alphastatic
+ airfriction 1
+ alpha 256 256 90
+ color 0x000000 0x111111
+ count 0.500000
+ originjitter 10 10 10
+ sizeincrease 7
+ size 5 15
+ tex 0 8
+ trailspacing 8
+ velocityoffset 0 0 10
effect fireball
-trailspacing 1
-count 0.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 48 48
-sizeincrease 0
-gravity 0
-alpha 50 256 1600
-bounce 1.5
-velocityjitter 0 0 0
-airfriction 1.2
-// light only
+ type smoke
+ airfriction 1.200000
+ alpha 50 256 1600
+ bounce 1.500000
+ color 0x8f0d00 0xff5a00
+ count 0.500000
+ size 48 48
+ tex 48 55
+ trailspacing 1
effect fireball
-trailspacing 16
-lightradius 300
-lightradiusfade 3000
-lightcolor 2.7 2.7 0.6
-
-// fireball
+ lightcolor 2.7 2.7 0.6
+ lightradiusfade 3000
+ lightradius 300
+ trailspacing 16
effect fireball_laser
-count 10
-type spark
-color 0x800000 0xFF8020
-alpha 192 256 2560
-size 1 1
-velocityjitter 1 1 1
-velocitymultiplier 10
-stretchfactor 0.7
-
-// rocket explosion (bigger than mortar and hagar)
-// decal
-// used nowhere in code
+ type spark
+ alpha 192 256 2560
+ color 0x800000 0xFF8020
+ count 10
+ size 1 1
+ stretchfactor 0.700000
+ velocityjitter 1 1 1
+ velocitymultiplier 10
effect fireball_explode
-countabsolute 1
-type decal
-tex 8 16
-size 72 72
-alpha 256 256 0
-originjitter 56 56 56
-lightradius 500
-lightradiusfade 500
-lightcolor 4 2 0.5
-// flare effect
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 4 2 0.5
+ lightradiusfade 500
+ lightradius 500
+ originjitter 56 56 56
+ size 72 72
+ tex 8 16
effect fireball_explode
-countabsolute 1
-type static
-tex 35 37
-color 0x404040 0x404040
-size 72 72
-alpha 192 192 64
-// fire effect
+ type static
+ alpha 192 192 64
+ color 0x404040 0x404040
+ countabsolute 1
+ size 72 72
+ tex 35 37
effect fireball_explode
-notunderwater
-count 128
-type static
-tex 48 55
-color 0x902010 0xFFD080
-size 16 16
-alpha 128 128 256
-bounce 1.5
-airfriction 4
-liquidfriction 4
-originjitter 8 8 8
-velocityjitter 512 512 512
-// underwater bubbles
+ type static
+ airfriction 4
+ alpha 128 128 256
+ bounce 1.500000
+ color 0x902010 0xFFD080
+ count 128
+ liquidfriction 4
+ notunderwater
+ originjitter 8 8 8
+ size 16 16
+ tex 48 55
+ velocityjitter 512 512 512
effect fireball_explode
-underwater
-count 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 16 16 16
-velocityjitter 144 144 144
-// bouncing sparks
+ type bubble
+ alpha 128 256 64
+ bounce 1.500000
+ color 0x404040 0x808080
+ count 32
+ gravity -0.125000
+ liquidfriction 0.250000
+ originjitter 16 16 16
+ size 3 3
+ tex 62 62
+ underwater
+ velocityjitter 144 144 144
effect fireball_explode
-notunderwater
-count 64
-type spark
-color 0x903010 0xFFD030
-size 2 2
-alpha 256 256 384
-gravity 1
-airfriction 0.2
-bounce 1.5
-liquidfriction 0.8
-velocityoffset 0 0 80
-velocityjitter 384 384 384
-
+ type spark
+ airfriction 0.200000
+ alpha 256 256 384
+ bounce 1.500000
+ color 0x903010 0xFFD030
+ count 64
+ gravity 1
+ liquidfriction 0.800000
+ notunderwater
+ size 2 2
+ velocityjitter 384 384 384
+ velocityoffset 0 0 80
effect fireball_muzzleflash
-count 2
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 5 5
-alpha 256 256 512
-originjitter 1.5 1.5 1.5
-velocityjitter 6 6 6
-velocitymultiplier 0.01
-lightradius 200
-lightradiusfade 2000
-lightcolor 2 1.5 0.2
+ type smoke
+ alpha 256 256 512
+ color 0x202020 0x404040
+ count 2
+ lightcolor 2 1.5 0.2
+ lightradiusfade 2000
+ lightradius 200
+ originjitter 1.5 1.5 1.5
+ size 5 5
+ tex 0 8
+ velocityjitter 6 6 6
+ velocitymultiplier 0.010000
effect fireball_muzzleflash
-count 15
-type spark
-tex 40 40
-color 0xFFFDD9 0xFFFDD9
-size 3 3
-alpha 0 128 1024
-originjitter 1 1 1
-velocityjitter 300 300 300
-velocitymultiplier 0.5
-airfriction 12
-
+ type spark
+ airfriction 12
+ alpha 0 128 1024
+ color 0xFFFDD9 0xFFFDD9
+ count 15
+ originjitter 1 1 1
+ size 3 3
+ tex 40 40
+ velocityjitter 300 300 300
+ velocitymultiplier 0.500000
effect fireball_preattack_muzzleflash
-count 2
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 5 5
-alpha 256 256 512
-originjitter 1.5 1.5 1.5
-velocityjitter 6 6 6
-velocitymultiplier 0.01
-lightradius 200
-lightradiusfade 2000
-lightcolor 2 1.5 0.2
+ type smoke
+ alpha 256 256 512
+ color 0x202020 0x404040
+ count 2
+ lightcolor 2 1.5 0.2
+ lightradiusfade 2000
+ lightradius 200
+ originjitter 1.5 1.5 1.5
+ size 5 5
+ tex 0 8
+ velocityjitter 6 6 6
+ velocitymultiplier 0.010000
effect fireball_preattack_muzzleflash
-count 15
-type spark
-tex 40 40
-color 0xFFFDD9 0xFFFDD9
-size 3 3
-alpha 0 128 1024
-originjitter 1 1 1
-velocityjitter 300 300 300
-velocitymultiplier 0.5
-airfriction 12
-
+ type spark
+ airfriction 12
+ alpha 0 128 1024
+ color 0xFFFDD9 0xFFFDD9
+ count 15
+ originjitter 1 1 1
+ size 3 3
+ tex 40 40
+ velocityjitter 300 300 300
+ velocitymultiplier 0.500000
effect fireball_bfgdamage
-count 2
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 5 5
-alpha 256 256 512
-originjitter 1.5 1.5 1.5
-velocityjitter 6 6 6
-velocitymultiplier 0.01
-lightradius 200
-lightradiusfade 2000
-lightcolor 2 1.5 0.2
+ type smoke
+ alpha 256 256 512
+ color 0x202020 0x404040
+ count 2
+ lightcolor 2 1.5 0.2
+ lightradiusfade 2000
+ lightradius 200
+ originjitter 1.5 1.5 1.5
+ size 5 5
+ tex 0 8
+ velocityjitter 6 6 6
+ velocitymultiplier 0.010000
effect fireball_bfgdamage
-count 15
-type spark
-tex 40 40
-color 0xFFFDD9 0xFFFDD9
-size 3 3
-alpha 0 128 1024
-originjitter 1 1 1
-velocityjitter 300 300 300
-velocitymultiplier 0.5
-airfriction 12
-
-//EF_FLAME
-//fire
-// used nowhere in code
+ type spark
+ airfriction 12
+ alpha 0 128 1024
+ color 0xFFFDD9 0xFFFDD9
+ count 15
+ originjitter 1 1 1
+ size 3 3
+ tex 40 40
+ velocityjitter 300 300 300
+ velocitymultiplier 0.500000
effect EF_FLAME
-//notunderwater
-count 100
-type smoke
-tex 48 55
-size 5 21
-alpha 200 356 512
-gravity -0.5
-color 0x8f0d00 0xff5a00
-bounce 2
-sizeincrease -1
-originoffset 0 0 10
-originjitter 12 12 34
-velocityjitter 22 22 50
-// smoke
+ type smoke
+ alpha 200 356 512
+ bounce 2
+ color 0x8f0d00 0xff5a00
+ count 100
+ gravity -0.500000
+ originjitter 12 12 34
+ originoffset 0 0 10
+ sizeincrease -1
+ size 5 21
+ tex 48 55
+ velocityjitter 22 22 50
effect EF_FLAME
-type alphastatic
-count 50
-tex 0 8
-size 11 15
-sizeincrease 6
-alpha 200 256 200
-color 0x000000 0x111111
-gravity -0.3
-originoffset 0 0 10
-originjitter 12 12 34
-velocityjitter 11 11 50
-bounce 2
+ type alphastatic
+ alpha 200 256 200
+ bounce 2
+ color 0x000000 0x111111
+ count 50
+ gravity -0.300000
+ originjitter 12 12 34
+ originoffset 0 0 10
+ sizeincrease 6
+ size 11 15
+ tex 0 8
+ velocityjitter 11 11 50
effect EF_FLAME
-count 0.5
-lightradius 200
-lightradiusfade 10000
-lightcolor 0.9 0.9 0.2
-
-// rifle bullet trail (somewhat like a tracer)
-// used in qcsrc/server/w_common.qc: zcurveparticles_from_tracetoss(particleeffectnum("tr_bullet"), self.origin, trace_endpos, self.velocity)
-// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("tr_bullet"), from, to)
+ count 0.500000
+ lightcolor 0.9 0.9 0.2
+ lightradiusfade 10000
+ lightradius 200
effect tr_rifle
-trailspacing 128
-type spark
-color 0x800000 0xFF8020
-alpha 256 256 2560
-size 1.5 1.5
-stretchfactor 1
-velocitymultiplier 0.7
+ type spark
+ alpha 256 256 2560
+ color 0x800000 0xFF8020
+ size 1.500000 1.500000
+ stretchfactor 1
+ trailspacing 128
+ velocitymultiplier 0.700000
effect tr_rifle
-notunderwater
-tex 0 8
-trailspacing 8
-type static
-color 0x202020 0x404040
-size 4 4
-sizeincrease 0.4
-alpha 256 256 256
-airfriction -4
-velocityjitter 4 4 4
-type smoke
+ type smoke
+ airfriction -4
+ alpha 256 256 256
+ color 0x202020 0x404040
+ notunderwater
+ sizeincrease 0.400000
+ size 4 4
+ tex 0 8
+ trailspacing 8
+ velocityjitter 4 4 4
effect tr_rifle
-underwater
-trailspacing 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 2 2
-alpha 256 256 128
-gravity -0.125
-bounce 1.5
-liquidfriction 4
-velocityjitter 16 16 16
-
-// rocket guiding start
-// underwater bubbles
+ type bubble
+ alpha 256 256 128
+ bounce 1.500000
+ color 0x404040 0x808080
+ gravity -0.125000
+ liquidfriction 4
+ size 2 2
+ tex 62 62
+ trailspacing 32
+ underwater
+ velocityjitter 16 16 16
effect rocket_guide
-underwater
-count 2
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 1.5 1.5
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 8 8 8
-velocityjitter 48 48 48
-velocitymultiplier -0.1
-// bouncing sparks
+ type bubble
+ alpha 128 256 64
+ bounce 1.500000
+ color 0x404040 0x808080
+ count 2
+ gravity -0.125000
+ liquidfriction 0.250000
+ originjitter 8 8 8
+ size 1.500000 1.500000
+ tex 62 62
+ underwater
+ velocityjitter 48 48 48
+ velocitymultiplier -0.100000
effect rocket_guide
-notunderwater
-count 8
-type spark
-color 0x903010 0xFFD030
-size 0.3 0.7
-tex 40 40
-alpha 256 256 984
-gravity 1
-airfriction 0.2
-bounce 1.5
-liquidfriction 0.8
-velocityoffset 0 0 80
-velocityjitter 156 156 156
-velocitymultiplier -0.3
-stretchfactor 0.4
+ type spark
+ airfriction 0.200000
+ alpha 256 256 984
+ bounce 1.500000
+ color 0x903010 0xFFD030
+ count 8
+ gravity 1
+ liquidfriction 0.800000
+ notunderwater
+ size 0.300000 0.700000
+ stretchfactor 0.400000
+ tex 40 40
+ velocityjitter 156 156 156
+ velocitymultiplier -0.300000
+ velocityoffset 0 0 80
effect rocket_guide
-countabsolute 1
-type smoke
-tex 65 65
-color 0x903010 0xFFD030
-size 10 10
-sizeincrease 300
-alpha 100 100 500
-
-
-// gauntlet laser
-// based off morphed's cl_gentle
-// used in qcsrc/server/w_laser.qc
+ type smoke
+ alpha 100 100 500
+ color 0x903010 0xFFD030
+ countabsolute 1
+ sizeincrease 300
+ size 10 10
+ tex 65 65
effect laser_gauntlet
-count 3
-type spark
-color 0xb44215 0x880000
-tex 43 43
-size 7 10
-alpha 128 512 6280
-airfriction 10
-originjitter 2 2 2
-velocityjitter 150 150 150
-velocitymultiplier 0.2
-sizeincrease -100
-stretchfactor 2.3
-rotate -180 180 4000 -4000
-
+ type spark
+ airfriction 10
+ alpha 128 512 6280
+ color 0xb44215 0x880000
+ count 3
+ originjitter 2 2 2
+ rotate -180 180 4000 -4000
+ sizeincrease -100
+ size 7 10
+ stretchfactor 2.300000
+ tex 43 43
+ velocityjitter 150 150 150
+ velocitymultiplier 0.200000
effect laser_gauntlet
-count 6
-type spark
-color 0xff4200 0xff0000
-tex 8 15
-size 7 9
-alpha 256 512 6280
-airfriction 12
-originjitter 2 2 2
-velocityjitter 100 100 100
-velocitymultiplier 0.2
-sizeincrease -100
-stretchfactor 2
-
-
-// muzzle flash
+ type spark
+ airfriction 12
+ alpha 256 512 6280
+ color 0xff4200 0xff0000
+ count 6
+ originjitter 2 2 2
+ sizeincrease -100
+ size 7 9
+ stretchfactor 2
+ tex 8 15
+ velocityjitter 100 100 100
+ velocitymultiplier 0.200000
effect laser_gauntletmuzzleflash
-// glow and light
-countabsolute 1
-type smoke
-color 0x220000 0x880000
-tex 65 65
-size 10 15
-alpha 256 512 6280
-airfriction 10
-sizeincrease -100
-stretchfactor 2
-lightradius 150
-lightradiusfade 500
-lightcolor 3 0.1 0.1
-// electricity
+ type smoke
+ airfriction 10
+ alpha 256 512 6280
+ color 0x220000 0x880000
+ countabsolute 1
+ lightcolor 3 0.1 0.1
+ lightradiusfade 500
+ lightradius 150
+ sizeincrease -100
+ size 10 15
+ stretchfactor 2
+ tex 65 65
effect laser_gauntletmuzzleflash
-count 3
-type spark
-color 0xb44215 0x880000
-tex 43 43
-size 7 10
-alpha 128 512 6280
-airfriction 10
-originjitter 2 2 2
-velocityjitter 150 150 150
-velocitymultiplier 0.2
-sizeincrease -100
-stretchfactor 2.3
-rotate -180 180 4000 -4000
-
-
-// fire
+ type spark
+ airfriction 10
+ alpha 128 512 6280
+ color 0xb44215 0x880000
+ count 3
+ originjitter 2 2 2
+ rotate -180 180 4000 -4000
+ sizeincrease -100
+ size 7 10
+ stretchfactor 2.300000
+ tex 43 43
+ velocityjitter 150 150 150
+ velocitymultiplier 0.200000
effect laser_gauntletmuzzleflash
-count 6
-type spark
-color 0xff4200 0xff0000
-tex 8 15
-size 7 9
-alpha 256 512 6280
-airfriction 12
-originjitter 2 2 2
-velocityjitter 100 100 100
-velocitymultiplier 0.2
-sizeincrease -100
-stretchfactor 2
-
-//torch flame, spawn it as fast as you can 20 times per second or more, supports direction but not required
-//fast fire
-// used nowhere in code, meant for maps
+ type spark
+ airfriction 12
+ alpha 256 512 6280
+ color 0xff4200 0xff0000
+ count 6
+ originjitter 2 2 2
+ sizeincrease -100
+ size 7 9
+ stretchfactor 2
+ tex 8 15
+ velocityjitter 100 100 100
+ velocitymultiplier 0.200000
effect torchflame
-count 3
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 5 5
-sizeincrease 20
- gravity -0.06
-alpha 50 256 250
-velocityjitter 40 40 11
-velocitymultiplier 30
-airfriction 1.2
-//slowfire
+ type smoke
+ airfriction 1.200000
+ alpha 50 256 250
+ color 0x8f0d00 0xff5a00
+ count 3
+ gravity -0.060000
+ sizeincrease 20
+ size 5 5
+ tex 48 55
+ velocityjitter 40 40 11
+ velocitymultiplier 30
effect torchflame
-count 2.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 5 5
-sizeincrease 20
- gravity -0.06
-alpha 50 256 200
-velocityjitter 40 40 40
-velocitymultiplier 20
-airfriction 1.2
-// very slow and small fire
+ type smoke
+ airfriction 1.200000
+ alpha 50 256 200
+ color 0x8f0d00 0xff5a00
+ count 2.500000
+ gravity -0.060000
+ sizeincrease 20
+ size 5 5
+ tex 48 55
+ velocityjitter 40 40 40
+ velocitymultiplier 20
effect torchflame
-count 1.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 5 5
-sizeincrease 10
- gravity -0.06
-alpha 50 256 200
-velocityjitter 30 30 30
-velocitymultiplier 10
-airfriction 0.3
-//decreasing fire
+ type smoke
+ airfriction 0.300000
+ alpha 50 256 200
+ color 0x8f0d00 0xff5a00
+ count 1.500000
+ gravity -0.060000
+ sizeincrease 10
+ size 5 5
+ tex 48 55
+ velocityjitter 30 30 30
+ velocitymultiplier 10
effect torchflame
-count 2
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 20 30
-sizeincrease -10
- gravity -0.06
-alpha 50 256 200
-velocityjitter 10 10 10
-velocitymultiplier 15
-airfriction 0.3
-//smoke
+ type smoke
+ airfriction 0.300000
+ alpha 50 256 200
+ color 0x8f0d00 0xff5a00
+ count 2
+ gravity -0.060000
+ sizeincrease -10
+ size 20 30
+ tex 48 55
+ velocityjitter 10 10 10
+ velocitymultiplier 15
effect torchflame
-count 0.5
-type alphastatic
-tex 0 8
-size 5 15
-sizeincrease 7
-color 0x000000 0x111111
-alpha 256 256 90
-//gravity -0.2
-originjitter 10 10 10
-velocitymultiplier 20
-velocityoffset 0 0 10
-airfriction 1
-
-//happy death fx for cl_gentle
+ type alphastatic
+ airfriction 1
+ alpha 256 256 90
+ color 0x000000 0x111111
+ count 0.500000
+ originjitter 10 10 10
+ sizeincrease 7
+ size 5 15
+ tex 0 8
+ velocitymultiplier 20
+ velocityoffset 0 0 10
effect happy_damage_dissolve
-tex 69 69
-count 15
-type alphastatic
-color 0x00FFFF 0xFF00FF
-size 32 32
-sizeincrease -10
-alpha 256 256 228
-gravity -0.4
-bounce 1.5
-airfriction 3
-liquidfriction 6
-velocityjitter 312 312 312
+ type alphastatic
+ airfriction 3
+ alpha 256 256 228
+ bounce 1.500000
+ color 0x00FFFF 0xFF00FF
+ count 15
+ gravity -0.400000
+ liquidfriction 6
+ sizeincrease -10
+ size 32 32
+ tex 69 69
+ velocityjitter 312 312 312
effect happy_damage_dissolve
-tex 69 69
-count 15
-type alphastatic
-color 0xFF00FF 0xFFFF00
-size 32 32
-sizeincrease -10
-alpha 256 256 228
-gravity -0.4
-bounce 1.5
-airfriction 3
-liquidfriction 6
-velocityjitter 312 312 312
+ type alphastatic
+ airfriction 3
+ alpha 256 256 228
+ bounce 1.500000
+ color 0xFF00FF 0xFFFF00
+ count 15
+ gravity -0.400000
+ liquidfriction 6
+ sizeincrease -10
+ size 32 32
+ tex 69 69
+ velocityjitter 312 312 312
effect happy_damage_dissolve
-tex 69 69
-count 15
-type alphastatic
-color 0xFFFF00 0x00FFFF
-size 32 32
-sizeincrease -10
-alpha 256 256 228
-gravity -0.4
-bounce 1.5
-airfriction 3
-liquidfriction 6
-velocityjitter 312 312 312
-
-
-//happy damage fx for cl_gentle
+ type alphastatic
+ airfriction 3
+ alpha 256 256 228
+ bounce 1.500000
+ color 0xFFFF00 0x00FFFF
+ count 15
+ gravity -0.400000
+ liquidfriction 6
+ sizeincrease -10
+ size 32 32
+ tex 69 69
+ velocityjitter 312 312 312
effect happy_damage_hit
-tex 69 69
-count 0.1
-type alphastatic
-color 0x00FFFF 0xFF00FF
-size 26 26
-sizeincrease -28
-alpha 128 128 192
-gravity -0.4
-bounce 1.5
-airfriction 5
-liquidfriction 10
-velocityjitter 156 156 156
+ type alphastatic
+ airfriction 5
+ alpha 128 128 192
+ bounce 1.500000
+ color 0x00FFFF 0xFF00FF
+ count 0.100000
+ gravity -0.400000
+ liquidfriction 10
+ sizeincrease -28
+ size 26 26
+ tex 69 69
+ velocityjitter 156 156 156
effect happy_damage_hit
-tex 69 69
-count 0.1
-type alphastatic
-color 0xFF00FF 0xFFFF00
-size 26 26
-sizeincrease -28
-alpha 128 128 192
-gravity -0.4
-bounce 1.5
-airfriction 5
-liquidfriction 10
-velocityjitter 156 156 156
+ type alphastatic
+ airfriction 5
+ alpha 128 128 192
+ bounce 1.500000
+ color 0xFF00FF 0xFFFF00
+ count 0.100000
+ gravity -0.400000
+ liquidfriction 10
+ sizeincrease -28
+ size 26 26
+ tex 69 69
+ velocityjitter 156 156 156
effect happy_damage_hit
-tex 69 69
-count 0.1
-type alphastatic
-color 0xFFFF00 0x00FFFF
-size 26 26
-sizeincrease -28
-alpha 128 128 192
-gravity -0.4
-bounce 1.5
-airfriction 5
-liquidfriction 10
-velocityjitter 156 156 156
-
-
-
-// used in qcsrc/server/w_electro.qc: pointparticles(particleeffectnum("electro_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
-// used in qcsrc/server/w_electro.qc: pointparticles(particleeffectnum("electro_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
+ type alphastatic
+ airfriction 5
+ alpha 128 128 192
+ bounce 1.500000
+ color 0xFFFF00 0x00FFFF
+ count 0.100000
+ gravity -0.400000
+ liquidfriction 10
+ sizeincrease -28
+ size 26 26
+ tex 69 69
+ velocityjitter 156 156 156
effect electro_lightning
-countabsolute 1
-type decal
-tex 59 59
-size 16 16
-alpha 256 256 0
-originjitter 2 2 2
-lightradius 50
-lightradiusfade 500
-lightcolor 3.125 4.375 10
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 3.1 4.4 10
+ lightradiusfade 500
+ lightradius 50
+ originjitter 2 2 2
+ size 16 16
+ tex 59 59
effect electro_lightning
-count 300
-type spark
-// color 0x501860 0x501860 // 0x202020 0x404040
-color 0x2030FF 0x80C0FF
-tex 65 65
-size 6 6
-alpha 100 206 1724
-originjitter 1.5 1.5 1.5
-velocityjitter 6 6 6
-sizeincrease 10
-velocitymultiplier 2000
+ type spark
+ alpha 100 206 1724
+ color 0x2030FF 0x80C0FF
+ count 300
+ originjitter 1.5 1.5 1.5
+ sizeincrease 10
+ size 6 6
+ tex 65 65
+ velocityjitter 6 6 6
+ velocitymultiplier 2000
effect electro_lightning
-count 30
-type spark
-tex 8 15
-color 0xDDFDFF 0xFDFDFF
-size 2 5
-alpha 110 170 1500
-originjitter 1 1 1
-velocityjitter 150 150 150
-velocitymultiplier 0.5
-airfriction 2
-stretchfactor 1.5
+ type spark
+ airfriction 2
+ alpha 110 170 1500
+ color 0xDDFDFF 0xFDFDFF
+ count 30
+ originjitter 1 1 1
+ size 2 5
+ stretchfactor 1.500000
+ tex 8 15
+ velocityjitter 150 150 150
+ velocitymultiplier 0.500000
effect electro_lightning
-count 50
-type spark
-tex 41 41
-color 0xFDFDFF 0xF9FDFF
-size 2 3
-alpha 110 170 1500
-originjitter 1 1 1
-velocityjitter 350 350 350
-velocitymultiplier 2.5
-airfriction 8
-gravity 1.3
-stretchfactor 0.1
-
-// used in qcsrc/server/w_gauntlet.qc: pointparticles(particleeffectnum("electro_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
+ type spark
+ airfriction 8
+ alpha 110 170 1500
+ color 0xFDFDFF 0xF9FDFF
+ count 50
+ gravity 1.300000
+ originjitter 1 1 1
+ size 2 3
+ stretchfactor 0.100000
+ tex 41 41
+ velocityjitter 350 350 350
+ velocitymultiplier 2.500000
effect gauntlet_lightning
-count 300
-type spark
-color 0x280000 0x280000 // 0x202020 0x404040
-tex 65 65
-size 3 3
-alpha 256 256 1024
-originjitter 1.5 1.5 1.5
-velocityjitter 6 6 6
-sizeincrease 15
-velocitymultiplier 2000
+ type spark
+ alpha 256 256 1024
+ color 0x280000 0x280000
+ count 300
+ originjitter 1.5 1.5 1.5
+ sizeincrease 15
+ size 3 3
+ tex 65 65
+ velocityjitter 6 6 6
+ velocitymultiplier 2000
effect gauntlet_lightning
-count 30
-type spark
-tex 8 15
-color 0xDD0000 0xFD0000
-size 2 5
-alpha 110 228 1024
-originjitter 1 1 1
-velocityjitter 150 150 150
-velocitymultiplier 0.5
-airfriction 2
-stretchfactor 1.5
+ type spark
+ airfriction 2
+ alpha 110 228 1024
+ color 0xDD0000 0xFD0000
+ count 30
+ originjitter 1 1 1
+ size 2 5
+ stretchfactor 1.500000
+ tex 8 15
+ velocityjitter 150 150 150
+ velocitymultiplier 0.500000
effect gauntlet_lightning
-count 50
-type spark
-tex 41 41
-color 0xFD0000 0xF90000
-size 2 3
-alpha 110 228 600
-originjitter 1 1 1
-velocityjitter 350 350 350
-velocitymultiplier 2.5
-airfriction 8
-gravity 1.3
-stretchfactor 0.1
-
-
-// crylink joinexplode effect
-// decal
-// used in qcsrc/client/damage.qc: pointparticles(particleeffectnum("crylink_joinexplode"), org2, '0 0 0', 1)
+ type spark
+ airfriction 8
+ alpha 110 228 600
+ color 0xFD0000 0xF90000
+ count 50
+ gravity 1.300000
+ originjitter 1 1 1
+ size 2 3
+ stretchfactor 0.100000
+ tex 41 41
+ velocityjitter 350 350 350
+ velocitymultiplier 2.500000
effect crylink_joinexplode
-countabsolute 1
-type decal
-tex 47 47
-size 24 24
-alpha 256 256 0
-originjitter 12 12 12
-//lightradius 200
-//lightradiusfade 800
-//lightcolor 3.2 0.4 4
-// purple flare effect
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ originjitter 12 12 12
+ size 24 24
+ tex 47 47
effect crylink_joinexplode
-countabsolute 1
-type static
-tex 39 39
-color 0x504060 0x504060
-size 24 24
-alpha 256 256 512
-// purple sparks
+ type static
+ alpha 256 256 512
+ color 0x504060 0x504060
+ countabsolute 1
+ size 24 24
+ tex 39 39
effect crylink_joinexplode
-count 40
-type spark
-tex 41 41
-color 0xA040C0 0xA040C0
-bounce 2
-size 6 6
-alpha 256 256 1024
-velocityjitter 512 512 512
-// purple splash
+ type spark
+ alpha 256 256 1024
+ bounce 2
+ color 0xA040C0 0xA040C0
+ count 40
+ size 6 6
+ tex 41 41
+ velocityjitter 512 512 512
effect crylink_joinexplode
-count 1.5
-type static
-color 0xE070FF 0xE070FF
-size 16 16
-alpha 256 256 512
-velocityjitter 32 32 32
-// purple splash
+ type static
+ alpha 256 256 512
+ color 0xE070FF 0xE070FF
+ count 1.500000
+ size 16 16
+ velocityjitter 32 32 32
effect crylink_joinexplode
-count 3
-type static
-color 0xE070FF 0xE070FF
-size 16 16
-alpha 256 256 1024
-velocityjitter 256 256 256
-
-//sparks for keepaway ball touch
-// used nowhere in code
+ type static
+ alpha 256 256 1024
+ color 0xE070FF 0xE070FF
+ count 3
+ size 16 16
+ velocityjitter 256 256 256
effect kaball_sparks
-count 35
-type spark
-tex 40 40
-color 0xa9cacf 0x0054ff
-size 1 3
-alpha 0 256 556
-gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 300 300 300
-velocitymultiplier 0.5
-airfriction 3
-
-
-// weak rifle bullet trail (somewhat like a tracer)
-// used in qcsrc/server/w_common.qc: zcurveparticles_from_tracetoss(particleeffectnum("tr_bullet"), self.origin, trace_endpos, self.velocity)
-// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("tr_bullet"), from, to)
+ type spark
+ airfriction 3
+ alpha 0 256 556
+ bounce 1.500000
+ color 0xa9cacf 0x0054ff
+ count 35
+ gravity 1
+ originjitter 1 1 1
+ size 1 3
+ tex 40 40
+ velocityjitter 300 300 300
+ velocitymultiplier 0.500000
effect tr_rifle_weak
-trailspacing 128
-type spark
-color 0x800000 0xFF8020
-alpha 256 256 2560
-size 1.5 1.5
-stretchfactor 1
-velocitymultiplier 0.7
+ type spark
+ alpha 256 256 2560
+ color 0x800000 0xFF8020
+ size 1.500000 1.500000
+ stretchfactor 1
+ trailspacing 128
+ velocitymultiplier 0.700000
effect tr_rifle_weak
-notunderwater
-tex 0 8
-trailspacing 48
-type static
-color 0x202020 0x404040
-size 4 4
-sizeincrease 0.4
-alpha 256 256 256
-airfriction -4
-velocityjitter 4 4 4
-type smoke
+ type smoke
+ airfriction -4
+ alpha 256 256 256
+ color 0x202020 0x404040
+ notunderwater
+ sizeincrease 0.400000
+ size 4 4
+ tex 0 8
+ trailspacing 48
+ velocityjitter 4 4 4
effect tr_rifle_weak
-underwater
-trailspacing 192
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 2 2
-alpha 256 256 128
-gravity -0.125
-bounce 1.5
-liquidfriction 4
-velocityjitter 16 16 16
-
-// red smoke emiter
-// used nowhere in code
+ type bubble
+ alpha 256 256 128
+ bounce 1.500000
+ color 0x404040 0x808080
+ gravity -0.125000
+ liquidfriction 4
+ size 2 2
+ tex 62 62
+ trailspacing 192
+ underwater
+ velocityjitter 16 16 16
effect red_smoke
-count 2
-type smoke
-tex 0 8
-color 0xff8866 0x331100
-size 60 120
-sizeincrease 0
-alpha 32 64 32
-gravity -0.007
-originjitter 0 0 0
-velocityjitter 0 0 0
-velocitymultiplier 5
-airfriction -1
-rotate 0 360 -30 30
-
-// pipe smoke emiter
-// used nowhere in code
+ type smoke
+ airfriction -1
+ alpha 32 64 32
+ color 0xff8866 0x331100
+ count 2
+ gravity -0.007000
+ rotate 0 360 -30 30
+ size 60 120
+ tex 0 8
+ velocitymultiplier 5
effect pipe_smoke
-count 2
-type smoke
-tex 0 8
-color 0x999999 0x555555
-size 5 10
-sizeincrease 35
-alpha 32 64 48
-gravity -0.015
-originjitter 0 0 0
-velocityjitter 0 0 5
-velocitymultiplier 15
-airfriction -1
-rotate 0 360 -180 180
-
-// seeker missile trail
+ type smoke
+ airfriction -1
+ alpha 32 64 48
+ color 0x999999 0x555555
+ count 2
+ gravity -0.015000
+ rotate 0 360 -180 180
+ sizeincrease 35
+ size 5 10
+ tex 0 8
+ velocityjitter 0 0 5
+ velocitymultiplier 15
effect TR_SEEKER
-trailspacing 10
-type smoke
-notunderwater
-color 0x000000 0x666666
-tex 0 8
-size 2 2
-bounce 1
-sizeincrease 11
-alpha 200 300 200
-lightradius 100
-lighttime 0
-lightcolor 6 3 1
-originjitter 2 2 2
-velocityjitter 3 3 3
-velocitymultiplier -0.02
-rotate -180 180 -30 30
-//gravity -0.11
-// fire
+ type smoke
+ alpha 200 300 200
+ bounce 1
+ color 0x000000 0x666666
+ lightcolor 6 3 1
+ lightradius 100
+ notunderwater
+ originjitter 2 2 2
+ rotate -180 180 -30 30
+ sizeincrease 11
+ size 2 2
+ tex 0 8
+ trailspacing 10
+ velocityjitter 3 3 3
+ velocitymultiplier -0.020000
effect TR_SEEKER
-trailspacing 4
-type static
-color 0xffdf72 0x811200
-tex 48 55
-size 5 5
-sizeincrease -30
-alpha 100 144 588
-airfriction 8
-velocityjitter 32 32 32
-velocitymultiplier -1.5
-// bubbles
+ type static
+ airfriction 8
+ alpha 100 144 588
+ color 0xffdf72 0x811200
+ sizeincrease -30
+ size 5 5
+ tex 48 55
+ trailspacing 4
+ velocityjitter 32 32 32
+ velocitymultiplier -1.500000
effect TR_SEEKER
-type bubble
-underwater
-trailspacing 16
-tex 62 62
-size 1 2
-alpha 256 256 256
-gravity -0.125
-bounce 1.5
-liquidfriction 4
-velocityjitter 16 16 16
-velocitymultiplier -0.31
-rotate 0 0 0 0
-// sparks
+ type bubble
+ alpha 256 256 256
+ bounce 1.500000
+ gravity -0.125000
+ liquidfriction 4
+ size 1 2
+ tex 62 62
+ trailspacing 16
+ underwater
+ velocityjitter 16 16 16
+ velocitymultiplier -0.310000
effect TR_SEEKER
-notunderwater
-trailspacing 20
-type spark
-tex 40 40
-color 0xFFFDD9 0xFFFDD9
-size 0.5 0.5
-alpha 444 512 1866
-stretchfactor 0.3
-//gravity 1
-bounce 1
-//velocityoffset 0 0 15
-airfriction 5
-originjitter 1 1 1
-velocityjitter 100 100 100
-velocitymultiplier -0.31
-
-// --------------- vehicles
-
+ type spark
+ airfriction 5
+ alpha 444 512 1866
+ bounce 1
+ color 0xFFFDD9 0xFFFDD9
+ notunderwater
+ originjitter 1 1 1
+ size 0.500000 0.500000
+ stretchfactor 0.300000
+ tex 40 40
+ trailspacing 20
+ velocityjitter 100 100 100
+ velocitymultiplier -0.310000
effect spiderbot_minigun_trail
-notunderwater
-trailspacing 10
-type smoke
-color 0xd0d0a0 0xffffff
-tex 0 8
-size 1 2
-alpha 20 50 100
-sizeincrease 2
-velocityjitter 5 5 5
-gravity -0.03
-airfriction 1
-
+ type smoke
+ airfriction 1
+ alpha 20 50 100
+ color 0xd0d0a0 0xffffff
+ gravity -0.030000
+ notunderwater
+ sizeincrease 2
+ size 1 2
+ tex 0 8
+ trailspacing 10
+ velocityjitter 5 5 5
effect spiderbot_minigun_muzzleflash
-count 3
-type spark
-color 0xff9c00 0xff8400
-tex 48 55
-size 10 15
-alpha 256 512 6280
-airfriction 10
-originjitter 2 2 2
-velocityjitter 150 150 150
-velocitymultiplier 0.35
-sizeincrease -100
-stretchfactor 1.3
-rotate -180 180 4000 -4000
-// fire
+ type spark
+ airfriction 10
+ alpha 256 512 6280
+ color 0xff9c00 0xff8400
+ count 3
+ originjitter 2 2 2
+ rotate -180 180 4000 -4000
+ sizeincrease -100
+ size 10 15
+ stretchfactor 1.300000
+ tex 48 55
+ velocityjitter 150 150 150
+ velocitymultiplier 0.350000
effect spiderbot_minigun_muzzleflash
-count 6
-type spark
-color 0xff9c00 0xff8400
-tex 8 15
-size 5 7
-alpha 256 512 6280
-airfriction 12
-originjitter 2 2 2
-velocityjitter 200 200 200
-velocitymultiplier 0.2
-sizeincrease -10
-stretchfactor 0.8
+ type spark
+ airfriction 12
+ alpha 256 512 6280
+ color 0xff9c00 0xff8400
+ count 6
+ originjitter 2 2 2
+ sizeincrease -10
+ size 5 7
+ stretchfactor 0.800000
+ tex 8 15
+ velocityjitter 200 200 200
+ velocitymultiplier 0.200000
effect spiderbot_minigun_muzzleflash
-countabsolute 2
-type static
-tex 48 55
-color 0xff9c00 0xff8400
-size 32 32
-alpha 256 512 6680
-sizeincrease -100
-stretchfactor 0.1
-rotate -180 180 4000 -4000
-lightradius 120
-lightradiusfade 8000
-lightcolor 3 3 0
-
+ type static
+ alpha 256 512 6680
+ color 0xff9c00 0xff8400
+ countabsolute 2
+ lightcolor 3 3 0
+ lightradiusfade 8000
+ lightradius 120
+ rotate -180 180 4000 -4000
+ sizeincrease -100
+ size 32 32
+ stretchfactor 0.100000
+ tex 48 55
effect spiderbot_minigun_impact
-countabsolute 1
-type static
-tex 65 65
-color 0xff9c00 0xf6ff00
-size 52 52
-alpha 50 100 1680
-sizeincrease -100
-stretchfactor 0.1
-rotate -180 180 4000 -4000
-// fire
+ type static
+ alpha 50 100 1680
+ color 0xff9c00 0xf6ff00
+ countabsolute 1
+ rotate -180 180 4000 -4000
+ sizeincrease -100
+ size 52 52
+ stretchfactor 0.100000
+ tex 65 65
effect spiderbot_minigun_impact
-count 7
-type spark
-color 0xff9c00 0xff8400
-tex 48 55
-size 9 15
-alpha 256 512 6280
-airfriction 10
-originjitter 2 2 2
-velocityjitter 250 250 150
-velocitymultiplier 0.2
-sizeincrease 100
-stretchfactor 3
-airfriction 6
-rotate -180 180 4000 -4000
-// smoke
+ type spark
+ airfriction 6
+ alpha 256 512 6280
+ color 0xff9c00 0xff8400
+ count 7
+ originjitter 2 2 2
+ rotate -180 180 4000 -4000
+ sizeincrease 100
+ size 9 15
+ stretchfactor 3
+ tex 48 55
+ velocityjitter 250 250 150
+ velocitymultiplier 0.200000
effect spiderbot_minigun_impact
-count 6
-type smoke
-color 0xd0d0a0 0xffffff
-tex 0 8
-size 10 20
-alpha 50 50 190
-sizeincrease 80
-velocityjitter 100 100 250
-velocitymultiplier 0.49
-gravity 1.3
-airfriction 10
-rotate -180 180 0 0
-// smoke 2
+ type smoke
+ airfriction 10
+ alpha 50 50 190
+ color 0xd0d0a0 0xffffff
+ count 6
+ gravity 1.300000
+ rotate -180 180 0 0
+ sizeincrease 80
+ size 10 20
+ tex 0 8
+ velocityjitter 100 100 250
+ velocitymultiplier 0.490000
effect spiderbot_minigun_impact
-count 7
-type spark
-color 0xd0d0a0 0xffffff
-tex 0 8
-size 15 19
-alpha 25 51 128
-airfriction 6
-originjitter 2 2 2
-velocityjitter 250 250 150
-velocitymultiplier 0.2
-sizeincrease 100
-stretchfactor 7.6
-// debris
+ type spark
+ airfriction 6
+ alpha 25 51 128
+ color 0xd0d0a0 0xffffff
+ count 7
+ originjitter 2 2 2
+ sizeincrease 100
+ size 15 19
+ stretchfactor 7.600000
+ tex 0 8
+ velocityjitter 250 250 150
+ velocitymultiplier 0.200000
effect spiderbot_minigun_impact
-notunderwater
-count 3
-type alphastatic
-tex 66 68
-color 0x99977D 0xFFFFFF
-size 6 8
-alpha 644 756 1484
-gravity 1.1
-airfriction 0.4
-sizeincrease -10
-velocitymultiplier 0.15
-originjitter 16 16 16
-velocityjitter 124 124 224
-rotate -180 180 -1000 1000
-// decal
+ type alphastatic
+ airfriction 0.400000
+ alpha 644 756 1484
+ color 0x99977D 0xFFFFFF
+ count 3
+ gravity 1.100000
+ notunderwater
+ originjitter 16 16 16
+ rotate -180 180 -1000 1000
+ sizeincrease -10
+ size 6 8
+ tex 66 68
+ velocityjitter 124 124 224
+ velocitymultiplier 0.150000
effect spiderbot_minigun_impact
-countabsolute 1
-type decal
-tex 56 59
-size 20 25
-alpha 256 256 0
-originjitter 16 16 16
-rotate -180 180 0 0
-
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ originjitter 16 16 16
+ rotate -180 180 0 0
+ size 20 25
+ tex 56 59
effect spiderbot_rocket_explode
-countabsolute 1
-type decal
-tex 8 16
-size 72 72
-alpha 256 256 0
-originjitter 23 23 23
-lightradius 300
-lightradiusfade 1750
-lightcolor 8 4 0
-// shockwave
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 8 4 0
+ lightradiusfade 1750
+ lightradius 300
+ originjitter 23 23 23
+ size 72 72
+ tex 8 16
effect spiderbot_rocket_explode
-countabsolute 1
-type static
-tex 33 33
-size 22 22
-alpha 56 56 230
-color 0x8f0d00 0xff5a00
-sizeincrease 2400
-// glow
+ type static
+ alpha 56 56 230
+ color 0x8f0d00 0xff5a00
+ countabsolute 1
+ sizeincrease 2400
+ size 22 22
+ tex 33 33
effect spiderbot_rocket_explode
-countabsolute 1
-type static
-tex 64 64
-size 120 120
-alpha 156 156 830
-color 0x8f0d00 0xff5a00
-sizeincrease 240
-// fire effect
+ type static
+ alpha 156 156 830
+ color 0x8f0d00 0xff5a00
+ countabsolute 1
+ sizeincrease 240
+ size 120 120
+ tex 64 64
effect spiderbot_rocket_explode
-notunderwater
-count 32
-type static
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 12 21
-sizeincrease 495
-alpha 200 256 812
-airfriction 8
-liquidfriction 8
-originjitter 100 100 100
-velocityjitter 512 512 512
-rotate -180 180 -50 50
-// fire effect 2
+ type static
+ airfriction 8
+ alpha 200 256 812
+ color 0x8f0d00 0xff5a00
+ count 32
+ liquidfriction 8
+ notunderwater
+ originjitter 100 100 100
+ rotate -180 180 -50 50
+ sizeincrease 495
+ size 12 21
+ tex 48 55
+ velocityjitter 512 512 512
effect spiderbot_rocket_explode
-notunderwater
-count 16
-type spark
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 3 3
-sizeincrease 120
-alpha 200 256 912
-airfriction -2
-liquidfriction 8
-velocityjitter 412 412 412
-rotate -180 180 -150 150
-stretchfactor 10
-// fire rays
+ type spark
+ airfriction -2
+ alpha 200 256 912
+ color 0x8f0d00 0xff5a00
+ count 16
+ liquidfriction 8
+ notunderwater
+ rotate -180 180 -150 150
+ sizeincrease 120
+ size 3 3
+ stretchfactor 10
+ tex 48 55
+ velocityjitter 412 412 412
effect spiderbot_rocket_explode
-notunderwater
-count 10
-type spark
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 13 54
-sizeincrease 120
-alpha 200 256 1600
-airfriction -3
-liquidfriction 8
-originjitter 40 40 40
-velocityjitter 712 712 712
-stretchfactor 10
-// smoke
+ type spark
+ airfriction -3
+ alpha 200 256 1600
+ color 0x8f0d00 0xff5a00
+ count 10
+ liquidfriction 8
+ notunderwater
+ originjitter 40 40 40
+ sizeincrease 120
+ size 13 54
+ stretchfactor 10
+ tex 48 55
+ velocityjitter 712 712 712
effect spiderbot_rocket_explode
-type alphastatic
-notunderwater
-tex 0 8
-count 10
-size 10 15
-sizeincrease 280
-alpha 300 650 756
-originjitter 100 100 100
-velocityjitter 200 200 200
-airfriction 3
-color 0x4F4B46 0x000000
-rotate -180 180 -20 20
-// smoke2
+ type alphastatic
+ airfriction 3
+ alpha 300 650 756
+ color 0x4F4B46 0x000000
+ count 10
+ notunderwater
+ originjitter 100 100 100
+ rotate -180 180 -20 20
+ sizeincrease 280
+ size 10 15
+ tex 0 8
+ velocityjitter 200 200 200
effect spiderbot_rocket_explode
-type alphastatic
-notunderwater
-tex 0 8
-count 3
-size 100 150
-sizeincrease 30
-alpha 300 650 556
-originjitter 10 10 10
-velocityjitter 200 200 200
-airfriction 2
-gravity -0.5
-color 0x4F4B46 0x000000
-rotate -180 180 -20 20
-// underwater bubbles
+ type alphastatic
+ airfriction 2
+ alpha 300 650 556
+ color 0x4F4B46 0x000000
+ count 3
+ gravity -0.500000
+ notunderwater
+ originjitter 10 10 10
+ rotate -180 180 -20 20
+ sizeincrease 30
+ size 100 150
+ tex 0 8
+ velocityjitter 200 200 200
effect spiderbot_rocket_explode
-underwater
-count 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 1 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 160 160 160
-velocityjitter 144 144 144
-// underwatershockwave
+ type bubble
+ alpha 128 256 64
+ bounce 1.500000
+ color 0x404040 0x808080
+ count 32
+ gravity -0.125000
+ liquidfriction 0.250000
+ originjitter 160 160 160
+ size 1 3
+ tex 62 62
+ underwater
+ velocityjitter 144 144 144
effect spiderbot_rocket_explode
-underwater
-type smoke
-countabsolute 1
-tex 33 33
-size 30 30
-sizeincrease 1200
-alpha 40 40 300
-
-
+ type smoke
+ alpha 40 40 300
+ countabsolute 1
+ sizeincrease 1200
+ size 30 30
+ tex 33 33
+ underwater
effect spiderbot_rocket_thrust
-notunderwater
-count 3
-type spark
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 5 10
-sizeincrease -40
-alpha 200 256 1600
-velocityjitter 20 20 20
-velocitymultiplier -1.4
-stretchfactor 0.9
+ type spark
+ alpha 200 256 1600
+ color 0x8f0d00 0xff5a00
+ count 3
+ notunderwater
+ sizeincrease -40
+ size 5 10
+ stretchfactor 0.900000
+ tex 48 55
+ velocityjitter 20 20 20
+ velocitymultiplier -1.400000
effect spiderbot_rocket_thrust
-notunderwater
-count 4
-type static
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 25 25
-sizeincrease -3000
-alpha 200 200 9000
-velocityjitter 60 60 60
-velocitymultiplier -1.4
-stretchfactor 1
-rotate -180 180 -500 500
-
-
-
-// long lasting smoke
+ type static
+ alpha 200 200 9000
+ color 0x8f0d00 0xff5a00
+ count 4
+ notunderwater
+ rotate -180 180 -500 500
+ sizeincrease -3000
+ size 25 25
+ stretchfactor 1
+ tex 48 55
+ velocityjitter 60 60 60
+ velocitymultiplier -1.400000
effect spiderbot_rocket_launch
-notunderwater
-count 8
-type smoke
-tex 0 8
-color 0xFFFFFF 0xD9C4B0
-size 30 30
-sizeincrease 20
-alpha 100 156 60
-velocityjitter 60 60 60
-velocitymultiplier -0.1
-airfriction 0.3
-gravity -0.01
-// fast smoke
+ type smoke
+ airfriction 0.300000
+ alpha 100 156 60
+ color 0xFFFFFF 0xD9C4B0
+ count 8
+ gravity -0.010000
+ notunderwater
+ sizeincrease 20
+ size 30 30
+ tex 0 8
+ velocityjitter 60 60 60
+ velocitymultiplier -0.100000
effect spiderbot_rocket_launch
-notunderwater
-count 14
-type smoke
-tex 0 8
-color 0xFFFFFF 0xD9C4B0
-size 30 30
-sizeincrease 20
-alpha 100 156 260
-gravity -0.3
-velocityjitter 160 160 60
-airfriction 0.3
-// fire
+ type smoke
+ airfriction 0.300000
+ alpha 100 156 260
+ color 0xFFFFFF 0xD9C4B0
+ count 14
+ gravity -0.300000
+ notunderwater
+ sizeincrease 20
+ size 30 30
+ tex 0 8
+ velocityjitter 160 160 60
effect spiderbot_rocket_launch
-notunderwater
-count 14
-type spark
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 30 30
-sizeincrease 40
-velocitymultiplier 0.5
-alpha 200 256 1960
-velocityjitter 60 60 60
-airfriction 0.3
-stretchfactor 3
-airfriction 0.3
-//sparks
+ type spark
+ airfriction 0.300000
+ alpha 200 256 1960
+ color 0x8f0d00 0xff5a00
+ count 14
+ notunderwater
+ sizeincrease 40
+ size 30 30
+ stretchfactor 3
+ tex 48 55
+ velocityjitter 60 60 60
+ velocitymultiplier 0.500000
effect spiderbot_rocket_launch
-notunderwater
-count 10
-type spark
-tex 40 40
-color 0xFFFFFF 0xD9C4B0
-size 1 4
-alpha 200 256 1000
-velocityjitter 160 160 160
-velocitymultiplier -0.5
-
+ type spark
+ alpha 200 256 1000
+ color 0xFFFFFF 0xD9C4B0
+ count 10
+ notunderwater
+ size 1 4
+ tex 40 40
+ velocityjitter 160 160 160
+ velocitymultiplier -0.500000
effect wakizashi_gun_impact
-count 15
-type spark
-color 0xff0000 0xc03535
-tex 41 41
-size 4 7
-alpha 256 512 1180
-airfriction 4
-gravity 3
-originjitter 40 40 10
-velocityjitter 350 350 550
-velocityoffset 0 0 700
-stretchfactor 0.9
+ type spark
+ airfriction 4
+ alpha 256 512 1180
+ color 0xff0000 0xc03535
+ count 15
+ gravity 3
+ originjitter 40 40 10
+ size 4 7
+ stretchfactor 0.900000
+ tex 41 41
+ velocityjitter 350 350 550
+ velocityoffset 0 0 700
effect wakizashi_gun_impact
-type smoke
-count 24
-color 0xd0d0a0 0xc03535
-tex 0 8
-size 10 20
-alpha 50 90 150
-sizeincrease 80
-velocityjitter 250 250 450
-velocityoffset 0 0 600
-originjitter 40 40 10
-airfriction 4
-sizeincrease 80
-rotate -180 180 0 0
+ type smoke
+ airfriction 4
+ alpha 50 90 150
+ color 0xd0d0a0 0xc03535
+ count 24
+ originjitter 40 40 10
+ rotate -180 180 0 0
+ sizeincrease 80
+ size 10 20
+ tex 0 8
+ velocityjitter 250 250 450
+ velocityoffset 0 0 600
effect wakizashi_gun_impact
-countabsolute 1
-type smoke
-tex 65 65
-color 0xff0000 0xc03535
-size 82 82
-alpha 250 300 680
-sizeincrease -180
+ type smoke
+ alpha 250 300 680
+ color 0xff0000 0xc03535
+ countabsolute 1
+ sizeincrease -180
+ size 82 82
+ tex 65 65
effect wakizashi_gun_impact
-countabsolute 1
-type smoke
-tex 33 33
-color 0xff0000 0xc03535
-size 40 40
-alpha 50 100 620
-sizeincrease 900
-rotate -180 180 400 -400
+ type smoke
+ alpha 50 100 620
+ color 0xff0000 0xc03535
+ countabsolute 1
+ rotate -180 180 400 -400
+ sizeincrease 900
+ size 40 40
+ tex 33 33
effect wakizashi_gun_impact
-countabsolute 1
-type decal
-tex 59 59
-size 14 14
-alpha 256 256 0
-originjitter 16 16 16
-rotate -180 180 0 0
-
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ originjitter 16 16 16
+ rotate -180 180 0 0
+ size 14 14
+ tex 59 59
effect wakizashi_gun_muzzleflash
-count 16
-type spark
-color 0xff0000 0xc03535
-tex 8 15
-size 5 7
-alpha 256 512 6280
-airfriction 12
-originjitter 2 2 2
-velocityjitter 200 200 200
-velocitymultiplier 0.2
-sizeincrease -10
-stretchfactor 0.7
-
+ type spark
+ airfriction 12
+ alpha 256 512 6280
+ color 0xff0000 0xc03535
+ count 16
+ originjitter 2 2 2
+ sizeincrease -10
+ size 5 7
+ stretchfactor 0.700000
+ tex 8 15
+ velocityjitter 200 200 200
+ velocitymultiplier 0.200000
effect wakizashi_rocket_explode
-countabsolute 1
-type decal
-tex 8 16
-size 72 72
-alpha 256 256 0
-originjitter 23 23 23
-lightradius 300
-lightradiusfade 1750
-lightcolor 8 4 0
-// shockwave
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 8 4 0
+ lightradiusfade 1750
+ lightradius 300
+ originjitter 23 23 23
+ size 72 72
+ tex 8 16
effect wakizashi_rocket_explode
-countabsolute 1
-type static
-tex 33 33
-size 22 22
-alpha 56 56 230
-color 0x8f0d00 0xff5a00
-sizeincrease 2400
-// glow
+ type static
+ alpha 56 56 230
+ color 0x8f0d00 0xff5a00
+ countabsolute 1
+ sizeincrease 2400
+ size 22 22
+ tex 33 33
effect wakizashi_rocket_explode
-countabsolute 1
-type static
-tex 64 64
-size 120 120
-alpha 156 156 830
-color 0x8f0d00 0xff5a00
-sizeincrease 240
-// fire effect
+ type static
+ alpha 156 156 830
+ color 0x8f0d00 0xff5a00
+ countabsolute 1
+ sizeincrease 240
+ size 120 120
+ tex 64 64
effect wakizashi_rocket_explode
-notunderwater
-count 64
-type static
-tex 48 55
-color 0xFFAE00 0xff5a00
-size 12 21
-sizeincrease 195
-alpha 200 256 512
-airfriction 2
-liquidfriction 8
-originjitter 10 10 10
-velocityjitter 512 512 512
-rotate -180 180 -50 50
-// fire rays
+ type static
+ airfriction 2
+ alpha 200 256 512
+ color 0xFFAE00 0xff5a00
+ count 64
+ liquidfriction 8
+ notunderwater
+ originjitter 10 10 10
+ rotate -180 180 -50 50
+ sizeincrease 195
+ size 12 21
+ tex 48 55
+ velocityjitter 512 512 512
effect wakizashi_rocket_explode
-notunderwater
-count 10
-type spark
-tex 48 55
-color 0xFFEA00 0xff5a00
-size 43 54
-sizeincrease 120
-alpha 200 256 1600
-airfriction -3
-liquidfriction 8
-originjitter 40 40 40
-velocityjitter 512 512 512
-stretchfactor 10
-// smoke
+ type spark
+ airfriction -3
+ alpha 200 256 1600
+ color 0xFFEA00 0xff5a00
+ count 10
+ liquidfriction 8
+ notunderwater
+ originjitter 40 40 40
+ sizeincrease 120
+ size 43 54
+ stretchfactor 10
+ tex 48 55
+ velocityjitter 512 512 512
effect wakizashi_rocket_explode
-type alphastatic
-notunderwater
-tex 0 8
-count 32
-size 10 15
-sizeincrease 230
-alpha 300 450 556
-originjitter 100 100 100
-velocityjitter 200 200 200
-airfriction 3
-color 0x4F4B46 0x000000
-rotate -180 180 -20 20
-// bouncing sparks
+ type alphastatic
+ airfriction 3
+ alpha 300 450 556
+ color 0x4F4B46 0x000000
+ count 32
+ notunderwater
+ originjitter 100 100 100
+ rotate -180 180 -20 20
+ sizeincrease 230
+ size 10 15
+ tex 0 8
+ velocityjitter 200 200 200
effect wakizashi_rocket_explode
-notunderwater
-count 14
-type spark
-tex 40 40
-color 0xffa35b 0xfff2be
-size 1 2
-alpha 644 956 884
-gravity 1
-airfriction 1
-liquidfriction 0.8
-velocityoffset 0 0 170
-originjitter 60 60 60
-velocityjitter 524 524 524
-// underwater bubbles
+ type spark
+ airfriction 1
+ alpha 644 956 884
+ color 0xffa35b 0xfff2be
+ count 14
+ gravity 1
+ liquidfriction 0.800000
+ notunderwater
+ originjitter 60 60 60
+ size 1 2
+ tex 40 40
+ velocityjitter 524 524 524
+ velocityoffset 0 0 170
effect wakizashi_rocket_explode
-underwater
-count 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 1 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 160 160 160
-velocityjitter 144 144 144
-// underwatershockwave
+ type bubble
+ alpha 128 256 64
+ bounce 1.500000
+ color 0x404040 0x808080
+ count 32
+ gravity -0.125000
+ liquidfriction 0.250000
+ originjitter 160 160 160
+ size 1 3
+ tex 62 62
+ underwater
+ velocityjitter 144 144 144
effect wakizashi_rocket_explode
-underwater
-type smoke
-countabsolute 1
-tex 33 33
-size 30 30
-sizeincrease 1200
-alpha 40 40 300
-
+ type smoke
+ alpha 40 40 300
+ countabsolute 1
+ sizeincrease 1200
+ size 30 30
+ tex 33 33
+ underwater
effect wakizashi_rocket_thrust
-notunderwater
-countabsolute 3
-type spark
-tex 48 55
-color 0x00FFDD 0x6200FF
-size 14 19
-sizeincrease -2
-alpha 200 256 1600
-velocityjitter 60 60 60
-velocitymultiplier -1.1
-stretchfactor 1
+ type spark
+ alpha 200 256 1600
+ color 0x00FFDD 0x6200FF
+ countabsolute 3
+ notunderwater
+ sizeincrease -2
+ size 14 19
+ stretchfactor 1
+ tex 48 55
+ velocityjitter 60 60 60
+ velocitymultiplier -1.100000
effect wakizashi_rocket_thrust
-notunderwater
-countabsolute 2
-type spark
-tex 48 55
-color 0xFFFF33 0xFFEE00
-size 5 10
-sizeincrease -2
-alpha 200 256 1900
-velocityjitter 60 60 60
-velocitymultiplier -0.3
-stretchfactor 3
-
-// long lasting smoke
+ type spark
+ alpha 200 256 1900
+ color 0xFFFF33 0xFFEE00
+ countabsolute 2
+ notunderwater
+ sizeincrease -2
+ size 5 10
+ stretchfactor 3
+ tex 48 55
+ velocityjitter 60 60 60
+ velocitymultiplier -0.300000
effect wakizashi_rocket_launch
-notunderwater
-count 8
-type smoke
-tex 0 8
-color 0xFFFFFF 0xD9C4B0
-size 3 30
-sizeincrease 20
-alpha 100 156 60
-velocityjitter 160 160 60
-velocitymultiplier -0.1
-airfriction 0.3
-// fast smoke
+ type smoke
+ airfriction 0.300000
+ alpha 100 156 60
+ color 0xFFFFFF 0xD9C4B0
+ count 8
+ notunderwater
+ sizeincrease 20
+ size 3 30
+ tex 0 8
+ velocityjitter 160 160 60
+ velocitymultiplier -0.100000
effect wakizashi_rocket_launch
-notunderwater
-count 14
-type smoke
-tex 0 8
-color 0xFFFFFF 0xD9C4B0
-size 30 30
-sizeincrease 20
-alpha 100 156 260
-velocityjitter 160 160 60
-velocitymultiplier 0.4
-airfriction 0.3
-//sparks
+ type smoke
+ airfriction 0.300000
+ alpha 100 156 260
+ color 0xFFFFFF 0xD9C4B0
+ count 14
+ notunderwater
+ sizeincrease 20
+ size 30 30
+ tex 0 8
+ velocityjitter 160 160 60
+ velocitymultiplier 0.400000
effect wakizashi_rocket_launch
-notunderwater
-count 10
-type spark
-tex 40 40
-color 0xFFFFFF 0xD9C4B0
-size 1 4
-alpha 200 256 1000
-velocityjitter 60 60 60
-velocitymultiplier -1.5
-
+ type spark
+ alpha 200 256 1000
+ color 0xFFFFFF 0xD9C4B0
+ count 10
+ notunderwater
+ size 1 4
+ tex 40 40
+ velocityjitter 60 60 60
+ velocitymultiplier -1.500000
effect wakizashi_booster_smoke
-type alphastatic
-notunderwater
-tex 0 8
-count 3
-size 60 100
-sizeincrease 10
-gravity -0.1
-alpha 200 750 200
-velocityjitter 40 40 40
-originjitter 60 60 60
-airfriction 2
-color 0xA69A80 0xB3B39F
-rotate -180 180 -20 20
-
-// decal
+ type alphastatic
+ airfriction 2
+ alpha 200 750 200
+ color 0xA69A80 0xB3B39F
+ count 3
+ gravity -0.100000
+ notunderwater
+ originjitter 60 60 60
+ rotate -180 180 -20 20
+ sizeincrease 10
+ size 60 100
+ tex 0 8
+ velocityjitter 40 40 40
effect raptor_cannon_impact
-countabsolute 1
-type decal
-tex 47 47
-size 24 24
-alpha 256 256 0
-originjitter 16 16 16
-rotate -180 180 0 0
-//spark
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ originjitter 16 16 16
+ rotate -180 180 0 0
+ size 24 24
+ tex 47 47
effect raptor_cannon_impact
-notunderwater
-count 6
-type spark
-tex 40 40
-color 0xD400FF 0x571863
-size 1 1
-alpha 644 956 784
-gravity 1
-airfriction 0.2
-velocityoffset 0 0 150
-originjitter 16 16 16
-velocityjitter 124 124 524
-// smoke
+ type spark
+ airfriction 0.200000
+ alpha 644 956 784
+ color 0xD400FF 0x571863
+ count 6
+ gravity 1
+ notunderwater
+ originjitter 16 16 16
+ size 1 1
+ tex 40 40
+ velocityjitter 124 124 524
+ velocityoffset 0 0 150
effect raptor_cannon_impact
-count 4
-type alphastatic
-tex 0 7
-size 50 50
-color 0x646364 0x151515
-alpha 428 428 600
-rotate -180 180 0 0
-velocityjitter 200 200 300
-velocityoffset 0 0 340
-gravity 0.7
-airfriction 2
-// fire
+ type alphastatic
+ airfriction 2
+ alpha 428 428 600
+ color 0x646364 0x151515
+ count 4
+ gravity 0.700000
+ rotate -180 180 0 0
+ size 50 50
+ tex 0 7
+ velocityjitter 200 200 300
+ velocityoffset 0 0 340
effect raptor_cannon_impact
-notunderwater
-count 10
-type static
-tex 48 55
-color 0xD400FF 0x571863
-size 33 44
-sizeincrease 25
-alpha 200 256 812
-bounce 1.5
-airfriction 8
-liquidfriction 8
-originjitter 8 8 8
-velocityjitter 312 312 312
-
-
+ type static
+ airfriction 8
+ alpha 200 256 812
+ bounce 1.500000
+ color 0xD400FF 0x571863
+ count 10
+ liquidfriction 8
+ notunderwater
+ originjitter 8 8 8
+ sizeincrease 25
+ size 33 44
+ tex 48 55
+ velocityjitter 312 312 312
effect raptor_cannon_muzzleflash
-count 16
-type spark
-color 0xD400FF 0x571863
-tex 8 15
-size 10 17
-alpha 1256 1512 56280
-airfriction 12
-originjitter 2 2 2
-velocityjitter 200 200 200
-velocitymultiplier 0.2
-sizeincrease -10
-stretchfactor 0.6
+ type spark
+ airfriction 12
+ alpha 1256 1512 56280
+ color 0xD400FF 0x571863
+ count 16
+ originjitter 2 2 2
+ sizeincrease -10
+ size 10 17
+ stretchfactor 0.600000
+ tex 8 15
+ velocityjitter 200 200 200
+ velocitymultiplier 0.200000
effect raptor_cannon_muzzleflash
-countabsolute 1
-type static
-tex 48 55
-color 0xD400FF 0x571863
-size 32 32
-alpha 6056 20112 406280
-sizeincrease -100
-stretchfactor 0.1
-rotate -180 180 4000 -4000
-lightradius 150
-lightradiusfade 6000
-lightcolor 3 0 6
-
-// decal
+ type static
+ alpha 6056 20112 406280
+ color 0xD400FF 0x571863
+ countabsolute 1
+ lightcolor 3 0 6
+ lightradiusfade 6000
+ lightradius 150
+ rotate -180 180 4000 -4000
+ sizeincrease -100
+ size 32 32
+ stretchfactor 0.100000
+ tex 48 55
effect raptor_bomb_impact
-countabsolute 1
-type decal
-tex 8 16
-size 84 84
-alpha 256 256 0
-originjitter 16 16 16
-rotate -180 180 0 0
-
-//spark vertical
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ originjitter 16 16 16
+ rotate -180 180 0 0
+ size 84 84
+ tex 8 16
effect raptor_bomb_impact
-count 3
-type spark
-color 0xff9c00 0xff3c00
-tex 48 55
-size 20 40
-alpha 300 300 600
-originjitter 10 10 10
-velocityjitter 40 40 120
-stretchfactor 210
-sizeincrease 50
-
-//fire
+ type spark
+ alpha 300 300 600
+ color 0xff9c00 0xff3c00
+ count 3
+ originjitter 10 10 10
+ sizeincrease 50
+ size 20 40
+ stretchfactor 210
+ tex 48 55
+ velocityjitter 40 40 120
effect raptor_bomb_impact
-count 4
-type static
-color 0xff9c00 0xff3c00
-tex 48 55
-size 30 120
-alpha 300 300 500
-originjitter 10 10 10
-velocityjitter 950 950 0
-sizeincrease 230
-airfriction 2
-
-//smoke
+ type static
+ airfriction 2
+ alpha 300 300 500
+ color 0xff9c00 0xff3c00
+ count 4
+ originjitter 10 10 10
+ sizeincrease 230
+ size 30 120
+ tex 48 55
+ velocityjitter 950 950 0
effect raptor_bomb_impact
-count 4
-type spark
-blend alpha
-tex 0 7
-size 120 180
-color 0x646364 0x151515
-alpha 428 428 600
-rotate -180 180 0 0
-velocityjitter 200 200 280
-velocityoffset 0 0 280
-originjitter 30 30 10
-stretchfactor 10
-
-//smoke 2
+ type spark
+ alpha 428 428 600
+ blend alpha
+ color 0x646364 0x151515
+ count 4
+ originjitter 30 30 10
+ rotate -180 180 0 0
+ size 120 180
+ stretchfactor 10
+ tex 0 7
+ velocityjitter 200 200 280
+ velocityoffset 0 0 280
effect raptor_bomb_impact
-count 4
-//type alphastatic
-type spark
-blend alpha
-tex 0 7
-size 40 100
-color 0x646364 0x151515
-alpha 328 328 350
-rotate -180 180 0 0
-velocityjitter 200 200 300
-velocityoffset 0 0 580
-originjitter 30 30 10
-sizeincrease 60
-airfriction 0.6
-gravity 2
-
-// sparks
+ type spark
+ airfriction 0.600000
+ alpha 328 328 350
+ blend alpha
+ color 0x646364 0x151515
+ count 4
+ gravity 2
+ originjitter 30 30 10
+ rotate -180 180 0 0
+ sizeincrease 60
+ size 40 100
+ tex 0 7
+ velocityjitter 200 200 300
+ velocityoffset 0 0 580
effect raptor_bomb_impact
-notunderwater
-count 5
-type spark
-tex 40 40
-color 0xffa35b 0xfff2be
-size 3 5
-alpha 644 956 984
-gravity 1
-airfriction 0.3
-velocityoffset 0 0 350
-originjitter 16 16 16
-velocityjitter 174 174 924
-stretchfactor 2
-
+ type spark
+ airfriction 0.300000
+ alpha 644 956 984
+ color 0xffa35b 0xfff2be
+ count 5
+ gravity 1
+ notunderwater
+ originjitter 16 16 16
+ size 3 5
+ stretchfactor 2
+ tex 40 40
+ velocityjitter 174 174 924
+ velocityoffset 0 0 350
effect raptor_bomb_spread
-notunderwater
-count 34
-type spark
-tex 40 40
-color 0xffa35b 0xfff2be
-size 1 2
-alpha 644 956 1284
-gravity 1
-airfriction 1
-liquidfriction 0.8
-originjitter 110 110 110
-velocityjitter 324 324 324
-
-
-// generic explosion size:big (biggest explosion ever)
+ type spark
+ airfriction 1
+ alpha 644 956 1284
+ color 0xffa35b 0xfff2be
+ count 34
+ gravity 1
+ liquidfriction 0.800000
+ notunderwater
+ originjitter 110 110 110
+ size 1 2
+ tex 40 40
+ velocityjitter 324 324 324
effect explosion_big
-countabsolute 1
-type decal
-tex 8 16
-size 172 172
-alpha 256 256 0
-originjitter 23 23 23
-lightradius 600
-lightradiusfade 1750
-lightcolor 8 4 0
-// shockwave
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 8 4 0
+ lightradiusfade 1750
+ lightradius 600
+ originjitter 23 23 23
+ size 172 172
+ tex 8 16
effect explosion_big
-countabsolute 1
-type static
-tex 33 33
-size 72 72
-alpha 56 56 330
-color 0x8f0d00 0xff5a00
-sizeincrease 4400
-// fire effect
+ type static
+ alpha 56 56 330
+ color 0x8f0d00 0xff5a00
+ countabsolute 1
+ sizeincrease 4400
+ size 72 72
+ tex 33 33
effect explosion_big
-notunderwater
-count 64
-type static
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 133 144
-sizeincrease 45
-alpha 200 256 712
-airfriction 8
-liquidfriction 8
-originjitter 80 80 80
-velocityjitter 2512 2512 2512
-// fire rays
+ type static
+ airfriction 8
+ alpha 200 256 712
+ color 0x8f0d00 0xff5a00
+ count 64
+ liquidfriction 8
+ notunderwater
+ originjitter 80 80 80
+ sizeincrease 45
+ size 133 144
+ tex 48 55
+ velocityjitter 2512 2512 2512
effect explosion_big
-notunderwater
-count 64
-type spark
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 133 144
-sizeincrease 45
-alpha 200 256 800
-airfriction -5
-liquidfriction 8
-originjitter 40 40 40
-velocityjitter 512 512 512
-stretchfactor 10
-// smoke
+ type spark
+ airfriction -5
+ alpha 200 256 800
+ color 0x8f0d00 0xff5a00
+ count 64
+ liquidfriction 8
+ notunderwater
+ originjitter 40 40 40
+ sizeincrease 45
+ size 133 144
+ stretchfactor 10
+ tex 48 55
+ velocityjitter 512 512 512
effect explosion_big
-type alphastatic
-notunderwater
-tex 0 8
-count 32
-size 50 100
-sizeincrease 244
-alpha 300 650 456
-velocityjitter 3444 3444 3444
-airfriction 8
-color 0x4F4B46 0x000000
-// bouncing sparks
+ type alphastatic
+ airfriction 8
+ alpha 300 650 456
+ color 0x4F4B46 0x000000
+ count 32
+ notunderwater
+ sizeincrease 244
+ size 50 100
+ tex 0 8
+ velocityjitter 3444 3444 3444
effect explosion_big
-notunderwater
-count 34
-type spark
-tex 40 40
-color 0xffa35b 0xfff2be
-size 3 4
-alpha 644 956 1284
-gravity 1
-airfriction 1
-liquidfriction 0.8
-velocityoffset 0 0 370
-originjitter 160 160 160
-velocityjitter 924 924 924
-stretchfactor 0.7
-// debris
+ type spark
+ airfriction 1
+ alpha 644 956 1284
+ color 0xffa35b 0xfff2be
+ count 34
+ gravity 1
+ liquidfriction 0.800000
+ notunderwater
+ originjitter 160 160 160
+ size 3 4
+ stretchfactor 0.700000
+ tex 40 40
+ velocityjitter 924 924 924
+ velocityoffset 0 0 370
effect explosion_big
-notunderwater
-count 16
-type alphastatic
-tex 66 68
-color 0xFFFFFF 0xcac5b4
-size 10 16
-alpha 444 1356 1184
-gravity 2.3
-airfriction 0.5
-velocityjitter 1800 1800 1800
-velocityoffset 0 0 970
-sizeincrease -5
-rotate -180 180 -1000 1000
-// underwater bubbles
+ type alphastatic
+ airfriction 0.500000
+ alpha 444 1356 1184
+ color 0xFFFFFF 0xcac5b4
+ count 16
+ gravity 2.300000
+ notunderwater
+ rotate -180 180 -1000 1000
+ sizeincrease -5
+ size 10 16
+ tex 66 68
+ velocityjitter 1800 1800 1800
+ velocityoffset 0 0 970
effect explosion_big
-underwater
-count 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 160 160 160
-velocityjitter 444 444 444
-// underwatershockwave
+ type bubble
+ alpha 128 256 64
+ bounce 1.500000
+ color 0x404040 0x808080
+ count 32
+ gravity -0.125000
+ liquidfriction 0.250000
+ originjitter 160 160 160
+ size 3 3
+ tex 62 62
+ underwater
+ velocityjitter 444 444 444
effect explosion_big
-underwater
-type smoke
-countabsolute 1
-tex 33 33
-size 30 30
-sizeincrease 2900
-alpha 40 40 300
-velocitymultiplier 0.3
-
-
-// generic explosion size:medium (it leaves rising smoke for a longer time)
-// shockwave
+ type smoke
+ alpha 40 40 300
+ countabsolute 1
+ sizeincrease 2900
+ size 30 30
+ tex 33 33
+ underwater
+ velocitymultiplier 0.300000
effect explosion_medium
-countabsolute 1
-type static
-tex 33 33
-size 72 72
-alpha 56 56 330
-color 0x8f0d00 0xff5a00
-sizeincrease 2400
-// fire effect
+ type static
+ alpha 56 56 330
+ color 0x8f0d00 0xff5a00
+ countabsolute 1
+ sizeincrease 2400
+ size 72 72
+ tex 33 33
effect explosion_medium
-notunderwater
-count 32
-type static
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 133 144
-sizeincrease 45
-alpha 200 256 712
-airfriction 8
-liquidfriction 8
-originjitter 30 30 30
-velocityjitter 1512 1512 1512
-rotate -180 180 -500 500
-// fire effect 2
+ type static
+ airfriction 8
+ alpha 200 256 712
+ color 0x8f0d00 0xff5a00
+ count 32
+ liquidfriction 8
+ notunderwater
+ originjitter 30 30 30
+ rotate -180 180 -500 500
+ sizeincrease 45
+ size 133 144
+ tex 48 55
+ velocityjitter 1512 1512 1512
effect explosion_medium
-notunderwater
-count 32
-type static
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 73 94
-sizeincrease 40
-gravity -2
-alpha 200 256 612
-airfriction 8
-liquidfriction 8
-originjitter 30 30 30
-velocityjitter 1512 1512 1512
-rotate -180 180 -150 150
-// fire rays
+ type static
+ airfriction 8
+ alpha 200 256 612
+ color 0x8f0d00 0xff5a00
+ count 32
+ gravity -2
+ liquidfriction 8
+ notunderwater
+ originjitter 30 30 30
+ rotate -180 180 -150 150
+ sizeincrease 40
+ size 73 94
+ tex 48 55
+ velocityjitter 1512 1512 1512
effect explosion_medium
-notunderwater
-count 14
-type spark
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 43 74
-sizeincrease 40
-alpha 200 256 800
-airfriction -3
-liquidfriction 8
-originjitter 40 40 40
-velocityjitter 512 512 512
-stretchfactor 8
-// smoke
+ type spark
+ airfriction -3
+ alpha 200 256 800
+ color 0x8f0d00 0xff5a00
+ count 14
+ liquidfriction 8
+ notunderwater
+ originjitter 40 40 40
+ sizeincrease 40
+ size 43 74
+ stretchfactor 8
+ tex 48 55
+ velocityjitter 512 512 512
effect explosion_medium
-type alphastatic
-notunderwater
-tex 0 8
-count 5
-size 250 300
-sizeincrease -30
-alpha 300 650 756
-originjitter 100 100 100
-velocityjitter 200 200 200
-airfriction 3
-color 0x4F4B46 0x000000
-rotate -180 180 -20 20
-// smoke 2
+ type alphastatic
+ airfriction 3
+ alpha 300 650 756
+ color 0x4F4B46 0x000000
+ count 5
+ notunderwater
+ originjitter 100 100 100
+ rotate -180 180 -20 20
+ sizeincrease -30
+ size 250 300
+ tex 0 8
+ velocityjitter 200 200 200
effect explosion_medium
-type alphastatic
-notunderwater
-tex 0 8
-count 10
-size 50 100
-sizeincrease 50
-gravity -0.3
-alpha 300 650 256
-originjitter 100 100 100
-velocityjitter 500 500 500
-velocityoffset 0 0 200
-airfriction 3
-color 0x4F4B46 0x000000
-rotate -180 180 -20 20
-// smoke rays
+ type alphastatic
+ airfriction 3
+ alpha 300 650 256
+ color 0x4F4B46 0x000000
+ count 10
+ gravity -0.300000
+ notunderwater
+ originjitter 100 100 100
+ rotate -180 180 -20 20
+ sizeincrease 50
+ size 50 100
+ tex 0 8
+ velocityjitter 500 500 500
+ velocityoffset 0 0 200
effect explosion_medium
-type spark
-notunderwater
-tex 0 8
-count 13
-size 150 200
-sizeincrease 100
-alpha 140 255 350
-velocityjitter 250 250 250
-originjitter 40 40 40
-color 0x4F4B46 0x000000
-stretchfactor 50
-// bouncing sparks
+ type spark
+ alpha 140 255 350
+ color 0x4F4B46 0x000000
+ count 13
+ notunderwater
+ originjitter 40 40 40
+ sizeincrease 100
+ size 150 200
+ stretchfactor 50
+ tex 0 8
+ velocityjitter 250 250 250
effect explosion_medium
-notunderwater
-count 14
-type spark
-tex 40 40
-color 0xffa35b 0xfff2be
-size 2 3
-alpha 644 956 984
-gravity 1
-airfriction 1
-liquidfriction 0.8
-velocityoffset 0 0 370
-originjitter 100 100 100
-velocityjitter 624 624 624
-stretchfactor 0.7
-// underwater bubbles
+ type spark
+ airfriction 1
+ alpha 644 956 984
+ color 0xffa35b 0xfff2be
+ count 14
+ gravity 1
+ liquidfriction 0.800000
+ notunderwater
+ originjitter 100 100 100
+ size 2 3
+ stretchfactor 0.700000
+ tex 40 40
+ velocityjitter 624 624 624
+ velocityoffset 0 0 370
effect explosion_medium
-underwater
-count 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 160 160 160
-velocityjitter 444 444 444
-// underwatershockwave
+ type bubble
+ alpha 128 256 64
+ bounce 1.500000
+ color 0x404040 0x808080
+ count 32
+ gravity -0.125000
+ liquidfriction 0.250000
+ originjitter 160 160 160
+ size 3 3
+ tex 62 62
+ underwater
+ velocityjitter 444 444 444
effect explosion_medium
-underwater
-type smoke
-countabsolute 1
-tex 33 33
-size 30 30
-sizeincrease 2900
-alpha 40 40 300
-velocitymultiplier 0.3
-
-// generic explosion size:small (its fire only, made to support other explosions)
-// shockwave
+ type smoke
+ alpha 40 40 300
+ countabsolute 1
+ sizeincrease 2900
+ size 30 30
+ tex 33 33
+ underwater
+ velocitymultiplier 0.300000
effect explosion_small
-countabsolute 1
-type static
-tex 33 33
-size 22 22
-alpha 56 56 330
-color 0x8f0d00 0xff5a00
-sizeincrease 2400
-// fire effect
+ type static
+ alpha 56 56 330
+ color 0x8f0d00 0xff5a00
+ countabsolute 1
+ sizeincrease 2400
+ size 22 22
+ tex 33 33
effect explosion_small
-notunderwater
-count 16
-type static
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 1 44
-sizeincrease 45
-alpha 200 256 1212
-airfriction 5
-liquidfriction 8
-velocityjitter 512 512 512
-rotate -180 180 -500 500
-// fire effect 2
+ type static
+ airfriction 5
+ alpha 200 256 1212
+ color 0x8f0d00 0xff5a00
+ count 16
+ liquidfriction 8
+ notunderwater
+ rotate -180 180 -500 500
+ sizeincrease 45
+ size 1 44
+ tex 48 55
+ velocityjitter 512 512 512
effect explosion_small
-notunderwater
-count 16
-type static
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 73 94
-sizeincrease 40
-alpha 200 256 812
-airfriction 8
-liquidfriction 8
-velocityjitter 912 912 912
-rotate -180 180 -150 150
-// fire rays
+ type static
+ airfriction 8
+ alpha 200 256 812
+ color 0x8f0d00 0xff5a00
+ count 16
+ liquidfriction 8
+ notunderwater
+ rotate -180 180 -150 150
+ sizeincrease 40
+ size 73 94
+ tex 48 55
+ velocityjitter 912 912 912
effect explosion_small
-notunderwater
-count 14
-type spark
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 13 54
-sizeincrease 30
-alpha 200 256 1300
-airfriction -3
-liquidfriction 8
-originjitter 40 40 40
-velocityjitter 512 512 512
-stretchfactor 8
-// underwater bubbles
+ type spark
+ airfriction -3
+ alpha 200 256 1300
+ color 0x8f0d00 0xff5a00
+ count 14
+ liquidfriction 8
+ notunderwater
+ originjitter 40 40 40
+ sizeincrease 30
+ size 13 54
+ stretchfactor 8
+ tex 48 55
+ velocityjitter 512 512 512
effect explosion_small
-underwater
-count 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 1 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 160 160 160
-velocityjitter 144 144 144
-// underwatershockwave
+ type bubble
+ alpha 128 256 64
+ bounce 1.500000
+ color 0x404040 0x808080
+ count 32
+ gravity -0.125000
+ liquidfriction 0.250000
+ originjitter 160 160 160
+ size 1 3
+ tex 62 62
+ underwater
+ velocityjitter 144 144 144
effect explosion_small
-underwater
-type smoke
-countabsolute 1
-tex 33 33
-size 30 30
-sizeincrease 1200
-alpha 40 40 300
-
-// big smoke ( for spamming on damaged stuff )
+ type smoke
+ alpha 40 40 300
+ countabsolute 1
+ sizeincrease 1200
+ size 30 30
+ tex 33 33
+ underwater
effect smoke_big
-type alphastatic
-notunderwater
-tex 0 8
-count 3
-size 30 60
-sizeincrease 15
-gravity -0.5
-alpha 200 750 200
-originjitter 55 55 55
-velocityjitter 140 140 200
-velocityoffset 0 0 200
-airfriction 4
-color 0x4F4B46 0x000000
-rotate -180 180 -20 20
-
-// small smoke ( more precise than big one, for spamming on damaged parts like raptors spinner )
+ type alphastatic
+ airfriction 4
+ alpha 200 750 200
+ color 0x4F4B46 0x000000
+ count 3
+ gravity -0.500000
+ notunderwater
+ originjitter 55 55 55
+ rotate -180 180 -20 20
+ sizeincrease 15
+ size 30 60
+ tex 0 8
+ velocityjitter 140 140 200
+ velocityoffset 0 0 200
effect smoke_small
-type alphastatic
-notunderwater
-tex 0 8
-count 3
-size 60 100
-sizeincrease -10
-gravity -0.5
-alpha 200 750 200
-velocityjitter 40 40 400
-velocityoffset 0 0 200
-airfriction 4
-color 0x4F4B46 0x000000
-rotate -180 180 -20 20
-
-// metal impact effect
-// used in qcsrc/server/mutators/sandbox.qc: pointparticles(particleeffectnum("impact_metal"), self.origin, '0 0 0', 1);
+ type alphastatic
+ airfriction 4
+ alpha 200 750 200
+ color 0x4F4B46 0x000000
+ count 3
+ gravity -0.500000
+ notunderwater
+ rotate -180 180 -20 20
+ sizeincrease -10
+ size 60 100
+ tex 0 8
+ velocityjitter 40 40 400
+ velocityoffset 0 0 200
effect impact_metal
-count 1
-type alphastatic
-tex 0 8
-size 3 6
-sizeincrease 10
-alpha 25 64 50
-gravity -0.01
-color 0x000000 0x886666
-originjitter 20 20 5
-// sparks
+ type alphastatic
+ alpha 25 64 50
+ color 0x000000 0x886666
+ count 1
+ gravity -0.010000
+ originjitter 20 20 5
+ sizeincrease 10
+ size 3 6
+ tex 0 8
effect impact_metal
-count 2
-type spark
-tex 41 41
-color 0xFFCC22 0xFF4422
-size 2 2
-alpha 255 255 112
-bounce 1.8
-stretchfactor 0.5
-velocityjitter 200 200 300
-velocitymultiplier 2
-airfriction 2
-gravity 1
-
-// stone impact effect
-// used in qcsrc/server/mutators/sandbox.qc: pointparticles(particleeffectnum("impact_stone"), self.origin, '0 0 0', 1);
+ type spark
+ airfriction 2
+ alpha 255 255 112
+ bounce 1.800000
+ color 0xFFCC22 0xFF4422
+ count 2
+ gravity 1
+ size 2 2
+ stretchfactor 0.500000
+ tex 41 41
+ velocityjitter 200 200 300
+ velocitymultiplier 2
effect impact_stone
-count 1
-type alphastatic
-tex 0 8
-size 3 6
-sizeincrease 15
-alpha 50 128 75
-gravity -0.01
-color 0x000000 0xcc9966
-originjitter 20 20 5
-// debris
+ type alphastatic
+ alpha 50 128 75
+ color 0x000000 0xcc9966
+ count 1
+ gravity -0.010000
+ originjitter 20 20 5
+ sizeincrease 15
+ size 3 6
+ tex 0 8
effect impact_stone
-notunderwater
-count 1
-type alphastatic
-tex 66 68
-color 0x000000 0x886644
-size 1 2
-alpha 450 750 300
-gravity 1.3
-airfriction 0.5
-bounce 1.2
-velocityjitter 124 124 324
-rotate -180 180 -1000 1000
-
-// wood impact effect
-// used in qcsrc/server/mutators/sandbox.qc: pointparticles(particleeffectnum("impact_wood"), self.origin, '0 0 0', 1);
+ type alphastatic
+ airfriction 0.500000
+ alpha 450 750 300
+ bounce 1.200000
+ color 0x000000 0x886644
+ count 1
+ gravity 1.300000
+ notunderwater
+ rotate -180 180 -1000 1000
+ size 1 2
+ tex 66 68
+ velocityjitter 124 124 324
effect impact_wood
-count 1
-type alphastatic
-tex 0 8
-size 3 6
-sizeincrease 10
-alpha 50 128 75
-gravity -0.01
-color 0x000000 0xcc9966
-originjitter 20 20 5
-// sparks
+ type alphastatic
+ alpha 50 128 75
+ color 0x000000 0xcc9966
+ count 1
+ gravity -0.010000
+ originjitter 20 20 5
+ sizeincrease 10
+ size 3 6
+ tex 0 8
effect impact_wood
-count 2
-type spark
-tex 41 41
-color 0x221100 0x221100
-size 1 8
-alpha 255 255 75
-bounce 1.5
-velocityjitter 180 180 260
-velocitymultiplier 2
-airfriction 2
-gravity 1
-
-// flesh impact effect
-// used in qcsrc/server/mutators/sandbox.qc: pointparticles(particleeffectnum("impact_flesh"), self.origin, '0 0 0', 1);
+ type spark
+ airfriction 2
+ alpha 255 255 75
+ bounce 1.500000
+ color 0x221100 0x221100
+ count 2
+ gravity 1
+ size 1 8
+ tex 41 41
+ velocityjitter 180 180 260
+ velocitymultiplier 2
effect impact_flesh
-count 0.5
-type alphastatic
-tex 0 8
-size 8 12
-alpha 100 256 400
-color 0x000000 0x420000
-originjitter 11 11 11
-// blood splash
+ type alphastatic
+ alpha 100 256 400
+ color 0x000000 0x420000
+ count 0.500000
+ originjitter 11 11 11
+ size 8 12
+ tex 0 8
effect impact_flesh
-count 0.3
-type blood
-tex 24 32
-size 2 6
-alpha 256 256 64
-color 0xA8FFFF 0xA8FFFFF
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 96 96 96
-velocitymultiplier 5
-staincolor 0x808080 0x808080
-staintex 16 24
-
-// hagar trail
-// smoke
+ type blood
+ airfriction 1
+ alpha 256 256 64
+ bounce -1
+ color 0xA8FFFF 0xA8FFFFF
+ count 0.300000
+ liquidfriction 4
+ size 2 6
+ staincolor 0x808080 0x808080
+ staintex 16 24
+ tex 24 32
+ velocityjitter 96 96 96
+ velocitymultiplier 5
effect tr_hagar
-trailspacing 4
-type smoke
-color 0x101010 0x000000
-tex 0 8
-size 3 2
-bounce 1
-sizeincrease 10
-alpha 300 400 780
-originjitter 1 1 1
-velocityjitter 1 1 1
-velocitymultiplier -0.02
-//gravity -0.11
-// fire
+ type smoke
+ alpha 300 400 780
+ bounce 1
+ color 0x101010 0x000000
+ originjitter 1 1 1
+ sizeincrease 10
+ size 3 2
+ tex 0 8
+ trailspacing 4
+ velocityjitter 1 1 1
+ velocitymultiplier -0.020000
effect tr_hagar
-notunderwater
-trailspacing 4
-type static
-color 0xffdf72 0x811200
-tex 48 55
-size 5 2
-sizeincrease -15
-alpha 100 144 988
-airfriction 8
-velocityjitter 32 32 32
-velocitymultiplier -1.0
-// bubbles
+ type static
+ airfriction 8
+ alpha 100 144 988
+ color 0xffdf72 0x811200
+ notunderwater
+ sizeincrease -15
+ size 5 2
+ tex 48 55
+ trailspacing 4
+ velocityjitter 32 32 32
+ velocitymultiplier -1
effect tr_hagar
-underwater
-trailspacing 16
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 1 1
-alpha 256 256 256
-gravity -0.125
-bounce 1.5
-liquidfriction 4
-velocityjitter 16 16 16
-
-// laser damage effect
-// used in qcsrc/client/damage.qc: pointparticles(self.team, org, '0 0 0', 1);
+ type bubble
+ alpha 256 256 256
+ bounce 1.500000
+ color 0x404040 0x808080
+ gravity -0.125000
+ liquidfriction 4
+ size 1 1
+ tex 62 62
+ trailspacing 16
+ underwater
+ velocityjitter 16 16 16
effect damage_laser
-notunderwater
-count 3
-type smoke
-tex 0 8
-color 0x880000 0xff4400
-size 2 4
-sizeincrease 8
-alpha 128 16 128
-gravity 0
-originjitter 2 2 2
-velocityjitter 0.4 0.4 0.6
-velocitymultiplier 0
-airfriction -0.35
-rotate 0 180 -30 30
-
-// shotgun damage effect, normal blood
-// used in qcsrc/client/damage.qc: pointparticles(self.team, org, '0 0 0', 1);
+ type smoke
+ airfriction -0.350000
+ alpha 128 16 128
+ color 0x880000 0xff4400
+ count 3
+ notunderwater
+ originjitter 2 2 2
+ rotate 0 180 -30 30
+ sizeincrease 8
+ size 2 4
+ tex 0 8
+ velocityjitter 0.4 0.4 0.6
effect damage_shotgun
-count 0.6
-type blood
-tex 24 32
-size 2 4
-alpha 256 256 64
-color 0xA8FFFF 0xA8FFFFF
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 64 64 64
-velocitymultiplier 5
-staincolor 0x808080 0x808080
-staintex 16 24
-//blood mist
+ type blood
+ airfriction 1
+ alpha 256 256 64
+ bounce -1
+ color 0xA8FFFF 0xA8FFFFF
+ count 0.600000
+ liquidfriction 4
+ size 2 4
+ staincolor 0x808080 0x808080
+ staintex 16 24
+ tex 24 32
+ velocityjitter 64 64 64
+ velocitymultiplier 5
effect damage_shotgun
-count 1
-type alphastatic
-tex 0 8
-size 8 16
-alpha 100 256 400
-color 0x000000 0x420000
-originjitter 1 1 1
-
-// shotgun damage effect, alien blood
-// used in qcsrc/client/damage.qc: pointparticles(self.team, org, '0 0 0', 1);
+ type alphastatic
+ alpha 100 256 400
+ color 0x000000 0x420000
+ count 1
+ originjitter 1 1 1
+ size 8 16
+ tex 0 8
effect damage_shotgun_alien
-count 0.6
-type blood
-tex 24 32
-size 2 4
-alpha 256 256 64
-color 0xDC9BCD 0xDC9BCD
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 64 64 64
-velocitymultiplier 5
-staincolor 0x808080 0x808080
-staintex 16 24
-//blood mist
+ type blood
+ airfriction 1
+ alpha 256 256 64
+ bounce -1
+ color 0xDC9BCD 0xDC9BCD
+ count 0.600000
+ liquidfriction 4
+ size 2 4
+ staincolor 0x808080 0x808080
+ staintex 16 24
+ tex 24 32
+ velocityjitter 64 64 64
+ velocitymultiplier 5
effect damage_shotgun_alien
-count 1
-type alphastatic
-tex 0 8
-size 8 16
-alpha 100 256 400
-color 0x000000 0x204010
-originjitter 1 1 1
-
-// shotgun damage effect, robot blood
-// used in qcsrc/client/damage.qc: pointparticles(self.team, org, '0 0 0', 1);
+ type alphastatic
+ alpha 100 256 400
+ color 0x000000 0x204010
+ count 1
+ originjitter 1 1 1
+ size 8 16
+ tex 0 8
effect damage_shotgun_robot
-count 0.6
-type blood
-tex 24 32
-size 2 4
-alpha 256 256 64
-color 0xC0D890 0xC0D890
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 64 64 64
-velocitymultiplier 5
-staincolor 0x808080 0x808080
-staintex 16 24
-//blood mist
+ type blood
+ airfriction 1
+ alpha 256 256 64
+ bounce -1
+ color 0xC0D890 0xC0D890
+ count 0.600000
+ liquidfriction 4
+ size 2 4
+ staincolor 0x808080 0x808080
+ staintex 16 24
+ tex 24 32
+ velocityjitter 64 64 64
+ velocitymultiplier 5
effect damage_shotgun_robot
-count 1
-type alphastatic
-tex 0 8
-size 8 16
-alpha 100 256 400
-color 0x000000 0x301860
-originjitter 1 1 1
-
-// uzi damage effect, normal blood
-// used in qcsrc/client/damage.qc: pointparticles(self.team, org, '0 0 0', 1);
+ type alphastatic
+ alpha 100 256 400
+ color 0x000000 0x301860
+ count 1
+ originjitter 1 1 1
+ size 8 16
+ tex 0 8
effect damage_uzi
-count 0.3
-type blood
-tex 24 32
-size 2 4
-alpha 256 256 64
-color 0xA8FFFF 0xA8FFFFF
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 32 32 32
-velocitymultiplier 5
-staincolor 0x808080 0x808080
-staintex 16 24
-//blood mist
+ type blood
+ airfriction 1
+ alpha 256 256 64
+ bounce -1
+ color 0xA8FFFF 0xA8FFFFF
+ count 0.300000
+ liquidfriction 4
+ size 2 4
+ staincolor 0x808080 0x808080
+ staintex 16 24
+ tex 24 32
+ velocityjitter 32 32 32
+ velocitymultiplier 5
effect damage_uzi
-count 1
-type alphastatic
-tex 0 8
-size 6 12
-alpha 100 256 400
-color 0x000000 0x420000
-originjitter 0 0 0
-
-// uzi damage effect, alien blood
-// used in qcsrc/client/damage.qc: pointparticles(self.team, org, '0 0 0', 1);
+ type alphastatic
+ alpha 100 256 400
+ color 0x000000 0x420000
+ count 1
+ size 6 12
+ tex 0 8
effect damage_uzi_alien
-count 0.3
-type blood
-tex 24 32
-size 2 4
-alpha 256 256 64
-color 0xDC9BCD 0xDC9BCD
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 32 32 32
-velocitymultiplier 5
-staincolor 0x808080 0x808080
-staintex 16 24
-//blood mist
+ type blood
+ airfriction 1
+ alpha 256 256 64
+ bounce -1
+ color 0xDC9BCD 0xDC9BCD
+ count 0.300000
+ liquidfriction 4
+ size 2 4
+ staincolor 0x808080 0x808080
+ staintex 16 24
+ tex 24 32
+ velocityjitter 32 32 32
+ velocitymultiplier 5
effect damage_uzi_alien
-count 1
-type alphastatic
-tex 0 8
-size 6 12
-alpha 100 256 400
-color 0x000000 0x204010
-originjitter 0 0 0
-
-// uzi damage effect, robot blood
-// used in qcsrc/client/damage.qc: pointparticles(self.team, org, '0 0 0', 1);
+ type alphastatic
+ alpha 100 256 400
+ color 0x000000 0x204010
+ count 1
+ size 6 12
+ tex 0 8
effect damage_uzi_robot
-count 0.3
-type blood
-tex 24 32
-size 2 4
-alpha 256 256 64
-color 0xC0D890 0xC0D890
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 32 32 32
-velocitymultiplier 5
-staincolor 0x808080 0x808080
-staintex 16 24
-//blood mist
+ type blood
+ airfriction 1
+ alpha 256 256 64
+ bounce -1
+ color 0xC0D890 0xC0D890
+ count 0.300000
+ liquidfriction 4
+ size 2 4
+ staincolor 0x808080 0x808080
+ staintex 16 24
+ tex 24 32
+ velocityjitter 32 32 32
+ velocitymultiplier 5
effect damage_uzi_robot
-count 1
-type alphastatic
-tex 0 8
-size 6 12
-alpha 100 256 400
-color 0x000000 0x301860
-originjitter 0 0 0
-
-// minelayer damage effect
-// used in qcsrc/client/damage.qc: pointparticles(self.team, org, '0 0 0', 1);
+ type alphastatic
+ alpha 100 256 400
+ color 0x000000 0x301860
+ count 1
+ size 6 12
+ tex 0 8
effect damage_minelayer
-notunderwater
-count 3
-type smoke
-tex 48 55
-size 4 8
-alpha 512 64 1024
-gravity -0.5
-color 0x8f0d00 0xff5a00
-sizeincrease -15
-originjitter 2 2 2
-velocityjitter 22 22 50
-// smoke
+ type smoke
+ alpha 512 64 1024
+ color 0x8f0d00 0xff5a00
+ count 3
+ gravity -0.500000
+ notunderwater
+ originjitter 2 2 2
+ sizeincrease -15
+ size 4 8
+ tex 48 55
+ velocityjitter 22 22 50
effect damage_minelayer
-notunderwater
-type alphastatic
-count 2
-tex 0 8
-size 4 8
-sizeincrease 5
-alpha 128 32 128
-color 0x000000 0x111111
-gravity -0.3
-originjitter 4 4 4
-velocityjitter 11 11 50
-// light
-/*effect damage_minelayer
-notunderwater
-trailspacing 8
-lightradius 60
-lightradiusfade 280
-lightcolor 0.7 0.4 0.2*/
-
-// grenadelauncher damage effect
-// used in qcsrc/client/damage.qc: pointparticles(self.team, org, '0 0 0', 1);
+ type alphastatic
+ alpha 128 32 128
+ color 0x000000 0x111111
+ count 2
+ gravity -0.300000
+ notunderwater
+ originjitter 4 4 4
+ sizeincrease 5
+ size 4 8
+ tex 0 8
+ velocityjitter 11 11 50
effect damage_grenadelauncher
-notunderwater
-count 3
-type smoke
-tex 48 55
-size 4 8
-alpha 512 64 1024
-gravity -0.5
-color 0x8f0d00 0xff5a00
-sizeincrease -15
-originjitter 2 2 2
-velocityjitter 22 22 50
-// smoke
+ type smoke
+ alpha 512 64 1024
+ color 0x8f0d00 0xff5a00
+ count 3
+ gravity -0.500000
+ notunderwater
+ originjitter 2 2 2
+ sizeincrease -15
+ size 4 8
+ tex 48 55
+ velocityjitter 22 22 50
effect damage_grenadelauncher
-notunderwater
-type alphastatic
-count 2
-tex 0 8
-size 4 8
-sizeincrease 5
-alpha 128 32 128
-color 0x000000 0x111111
-gravity -0.3
-originjitter 4 4 4
-velocityjitter 11 11 50
-// light
-/*effect damage_grenadelauncher
-notunderwater
-trailspacing 8
-lightradius 60
-lightradiusfade 280
-lightcolor 0.7 0.4 0.2*/
-
-// electro damage effect
-// used in qcsrc/client/damage.qc: pointparticles(self.team, org, '0 0 0', 1);
+ type alphastatic
+ alpha 128 32 128
+ color 0x000000 0x111111
+ count 2
+ gravity -0.300000
+ notunderwater
+ originjitter 4 4 4
+ sizeincrease 5
+ size 4 8
+ tex 0 8
+ velocityjitter 11 11 50
effect damage_electro
-notunderwater
-count 2
-type static
-tex 47 47
-color 0x66ffff 0x2288ff
-size 6 10
-sizeincrease -14
-alpha 48 8 48
-gravity -0.0001
-airfriction 0.2
-liquidfriction 0.8
-originjitter 3 3 3
-velocityjitter 8 8 16
-velocitymultiplier 0
-airfriction -0.5
-rotate 180 360 -30 30
-// plasma smoke
+ type static
+ airfriction -0.500000
+ alpha 48 8 48
+ color 0x66ffff 0x2288ff
+ count 2
+ gravity -0.000100
+ liquidfriction 0.800000
+ notunderwater
+ originjitter 3 3 3
+ rotate 180 360 -30 30
+ sizeincrease -14
+ size 6 10
+ tex 47 47
+ velocityjitter 8 8 16
effect damage_electro
-notunderwater
-count 4
-type smoke
-tex 0 8
-color 0x2244ff 0x002266
-size 4 8
-sizeincrease 10
-alpha 64 16 64
-gravity 0
-originjitter 4 4 4
-velocityjitter 0.4 0.4 0.6
-velocitymultiplier 0
-airfriction -0.35
-rotate 0 180 -30 30
-// bouncing sparks
+ type smoke
+ airfriction -0.350000
+ alpha 64 16 64
+ color 0x2244ff 0x002266
+ count 4
+ notunderwater
+ originjitter 4 4 4
+ rotate 0 180 -30 30
+ sizeincrease 10
+ size 4 8
+ tex 0 8
+ velocityjitter 0.4 0.4 0.6
effect damage_electro
-count 0.5
-type spark
-tex 66 68
-color 0x003090 0x00CCFF
-size 1 1
-alpha 768 64 256
-gravity 0.2
-airfriction 1
-bounce 1.5
-liquidfriction 0.8
-velocityoffset 0 0 0
-velocityjitter 32 32 32
-// light
-/*effect damage_electro
-notunderwater
-trailspacing 8
-lightradius 50
-lightradiusfade 220
-lightcolor 0.2 0.6 0.8*/
-
-// crylink damage effect
-// used in qcsrc/client/damage.qc: pointparticles(self.team, org, '0 0 0', 1);
+ type spark
+ airfriction 1
+ alpha 768 64 256
+ bounce 1.500000
+ color 0x003090 0x00CCFF
+ count 0.500000
+ gravity 0.200000
+ liquidfriction 0.800000
+ size 1 1
+ tex 66 68
+ velocityjitter 32 32 32
effect damage_crylink
-notunderwater
-count 2
-type static
-tex 38 38
-color 0xff44ff 0x9966ff
-size 0.5 1
-sizeincrease -8
-alpha 48 16 48
-gravity -0.0001
-airfriction 0.6
-liquidfriction 0.8
-originjitter 3 3 3
-velocityjitter 10 10 20
-velocitymultiplier 0
-airfriction -0.5
-rotate 180 360 -30 30
-// plasma smoke
+ type static
+ airfriction -0.500000
+ alpha 48 16 48
+ color 0xff44ff 0x9966ff
+ count 2
+ gravity -0.000100
+ liquidfriction 0.800000
+ notunderwater
+ originjitter 3 3 3
+ rotate 180 360 -30 30
+ sizeincrease -8
+ size 0.500000 1
+ tex 38 38
+ velocityjitter 10 10 20
effect damage_crylink
-notunderwater
-count 4
-type smoke
-tex 0 8
-color 0x8844ff 0x662244
-size 5 10
-sizeincrease 6
-alpha 64 16 64
-gravity 0.001
-originjitter 4 4 4
-velocityjitter 0.4 0.4 0.6
-velocitymultiplier 0
-airfriction -0.35
-rotate 0 180 -30 30
-// floating sparks
+ type smoke
+ airfriction -0.350000
+ alpha 64 16 64
+ color 0x8844ff 0x662244
+ count 4
+ gravity 0.001000
+ notunderwater
+ originjitter 4 4 4
+ rotate 0 180 -30 30
+ sizeincrease 6
+ size 5 10
+ tex 0 8
+ velocityjitter 0.4 0.4 0.6
effect damage_crylink
-count 0.3
-type spark
-color 0x903090 0xFFD0FF
-size 0.5 0.5
-sizeincrease -5
-alpha 192 192 128
-gravity 0
-airfriction 0.2
-liquidfriction 0.8
-velocityoffset 0 0 0
-velocityjitter 12 12 12
-// light
-/*effect damage_crylink
-notunderwater
-trailspacing 8
-lightradius 50
-lightradiusfade 240
-lightcolor 0.6 0.2 0.8*/
-
-// hlac damage effect
-// used in qcsrc/client/damage.qc: pointparticles(self.team, org, '0 0 0', 1);
+ type spark
+ airfriction 0.200000
+ alpha 192 192 128
+ color 0x903090 0xFFD0FF
+ count 0.300000
+ liquidfriction 0.800000
+ sizeincrease -5
+ size 0.500000 0.500000
+ velocityjitter 12 12 12
effect damage_hlac
-notunderwater
-count 3
-type smoke
-tex 0 8
-color 0x880000 0xff4400
-size 2 4
-sizeincrease 10
-alpha 128 16 128
-gravity 0
-originjitter 4 4 4
-velocityjitter 0.4 0.4 0.6
-velocitymultiplier 0
-airfriction -0.35
-rotate 0 180 -30 30
-
-// nex damage effect
-// used in qcsrc/client/damage.qc: pointparticles(self.team, org, '0 0 0', 1);
+ type smoke
+ airfriction -0.350000
+ alpha 128 16 128
+ color 0x880000 0xff4400
+ count 3
+ notunderwater
+ originjitter 4 4 4
+ rotate 0 180 -30 30
+ sizeincrease 10
+ size 2 4
+ tex 0 8
+ velocityjitter 0.4 0.4 0.6
effect damage_nex
-count 1
-type static
-tex 47 47
-color 0xffffff 0x88ffff
-size 5 10
-sizeincrease -14
-alpha 64 8 64
-gravity -0.0001
-airfriction 0.1
-liquidfriction 0.6
-originjitter 4 4 4
-velocityjitter 8 8 16
-velocitymultiplier 0
-airfriction -0.5
-rotate 180 360 -30 30
-// plasma smoke
+ type static
+ airfriction -0.500000
+ alpha 64 8 64
+ color 0xffffff 0x88ffff
+ count 1
+ gravity -0.000100
+ liquidfriction 0.600000
+ originjitter 4 4 4
+ rotate 180 360 -30 30
+ sizeincrease -14
+ size 5 10
+ tex 47 47
+ velocityjitter 8 8 16
effect damage_nex
-count 2
-type smoke
-tex 0 8
-color 0x6688ff 0x226688
-size 4 8
-sizeincrease 8
-alpha 64 16 64
-gravity 0
-originjitter 2 2 2
-velocityjitter 0.5 0.5 0.8
-velocitymultiplier 0
-airfriction -0.35
-rotate 0 180 -30 30
-// bouncing sparks
+ type smoke
+ airfriction -0.350000
+ alpha 64 16 64
+ color 0x6688ff 0x226688
+ count 2
+ originjitter 2 2 2
+ rotate 0 180 -30 30
+ sizeincrease 8
+ size 4 8
+ tex 0 8
+ velocityjitter 0.5 0.5 0.8
effect damage_nex
-count 0.2
-type spark
-tex 41 41
-color 0xD9FDFF 0xD9FDFF
-size 1 1
-alpha 255 255 112
-bounce 1.6
-stretchfactor 0.7
-velocityjitter 100 100 300
-velocitymultiplier 3
-airfriction 2
-gravity 1
-// light
-/*effect damage_nex
-trailspacing 8
-lightradius 60
-lightradiusfade 280
-lightcolor 0.6 0.8 0.8*/
-
-// minstanex damage effect
-// used in qcsrc/client/damage.qc: pointparticles(self.team, org, '0 0 0', 1);
+ type spark
+ airfriction 2
+ alpha 255 255 112
+ bounce 1.600000
+ color 0xD9FDFF 0xD9FDFF
+ count 0.200000
+ gravity 1
+ size 1 1
+ stretchfactor 0.700000
+ tex 41 41
+ velocityjitter 100 100 300
+ velocitymultiplier 3
effect damage_minstanex
-count 2
-type static
-tex 47 47
-color 0xffffff 0x88ffff
-size 5 10
-sizeincrease -14
-alpha 64 8 64
-gravity -0.0001
-airfriction 0.1
-liquidfriction 0.6
-originjitter 4 4 4
-velocityjitter 8 8 16
-velocitymultiplier 0
-airfriction -0.5
-rotate 180 360 -30 30
-// plasma smoke
+ type static
+ airfriction -0.500000
+ alpha 64 8 64
+ color 0xffffff 0x88ffff
+ count 2
+ gravity -0.000100
+ liquidfriction 0.600000
+ originjitter 4 4 4
+ rotate 180 360 -30 30
+ sizeincrease -14
+ size 5 10
+ tex 47 47
+ velocityjitter 8 8 16
effect damage_minstanex
-count 4
-type smoke
-tex 0 8
-color 0x6688ff 0x226688
-size 4 8
-sizeincrease 8
-alpha 64 16 64
-gravity 0
-originjitter 2 2 2
-velocityjitter 0.5 0.5 0.8
-velocitymultiplier 0
-airfriction -0.35
-rotate 0 180 -30 30
-// bouncing sparks
+ type smoke
+ airfriction -0.350000
+ alpha 64 16 64
+ color 0x6688ff 0x226688
+ count 4
+ originjitter 2 2 2
+ rotate 0 180 -30 30
+ sizeincrease 8
+ size 4 8
+ tex 0 8
+ velocityjitter 0.5 0.5 0.8
effect damage_minstanex
-count 0.2
-type spark
-tex 41 41
-color 0xD9FDFF 0xD9FDFF
-size 1 1
-alpha 255 255 112
-bounce 1.6
-stretchfactor 0.7
-velocityjitter 100 100 300
-velocitymultiplier 3
-airfriction 2
-gravity 1
-// light
-/*effect damage_minstanex
-trailspacing 8
-lightradius 60
-lightradiusfade 240
-lightcolor 0.6 0.8 0.8*/
-
-// sniperrifle damage effect, normal blood
-// used in qcsrc/client/damage.qc: pointparticles(self.team, org, '0 0 0', 1);
+ type spark
+ airfriction 2
+ alpha 255 255 112
+ bounce 1.600000
+ color 0xD9FDFF 0xD9FDFF
+ count 0.200000
+ gravity 1
+ size 1 1
+ stretchfactor 0.700000
+ tex 41 41
+ velocityjitter 100 100 300
+ velocitymultiplier 3
effect damage_rifle
-count 0.3
-type blood
-tex 24 32
-size 2 4
-alpha 256 256 64
-color 0xA8FFFF 0xA8FFFFF
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 32 32 32
-velocitymultiplier 5
-staincolor 0x808080 0x808080
-staintex 16 24
-//blood mist
+ type blood
+ airfriction 1
+ alpha 256 256 64
+ bounce -1
+ color 0xA8FFFF 0xA8FFFFF
+ count 0.300000
+ liquidfriction 4
+ size 2 4
+ staincolor 0x808080 0x808080
+ staintex 16 24
+ tex 24 32
+ velocityjitter 32 32 32
+ velocitymultiplier 5
effect damage_rifle
-count 1
-type alphastatic
-tex 0 8
-size 6 12
-alpha 100 256 400
-color 0x000000 0x420000
-originjitter 0 0 0
-
-// sniperrifle damage effect, alien blood
-// used in qcsrc/client/damage.qc: pointparticles(self.team, org, '0 0 0', 1);
+ type alphastatic
+ alpha 100 256 400
+ color 0x000000 0x420000
+ count 1
+ size 6 12
+ tex 0 8
effect damage_rifle_alien
-count 0.3
-type blood
-tex 24 32
-size 2 4
-alpha 256 256 64
-color 0xDC9BCD 0xDC9BCD
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 32 32 32
-velocitymultiplier 5
-staincolor 0x808080 0x808080
-staintex 16 24
-//blood mist
+ type blood
+ airfriction 1
+ alpha 256 256 64
+ bounce -1
+ color 0xDC9BCD 0xDC9BCD
+ count 0.300000
+ liquidfriction 4
+ size 2 4
+ staincolor 0x808080 0x808080
+ staintex 16 24
+ tex 24 32
+ velocityjitter 32 32 32
+ velocitymultiplier 5
effect damage_rifle_alien
-count 1
-type alphastatic
-tex 0 8
-size 6 12
-alpha 100 256 400
-color 0x000000 0x204010
-originjitter 0 0 0
-
-// sniperrifle damage effect, robot blood
-// used in qcsrc/client/damage.qc: pointparticles(self.team, org, '0 0 0', 1);
+ type alphastatic
+ alpha 100 256 400
+ color 0x000000 0x204010
+ count 1
+ size 6 12
+ tex 0 8
effect damage_rifle_robot
-count 0.3
-type blood
-tex 24 32
-size 2 4
-alpha 256 256 64
-color 0xC0D890 0xC0D890
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 32 32 32
-velocitymultiplier 5
-staincolor 0x808080 0x808080
-staintex 16 24
-//blood mist
+ type blood
+ airfriction 1
+ alpha 256 256 64
+ bounce -1
+ color 0xC0D890 0xC0D890
+ count 0.300000
+ liquidfriction 4
+ size 2 4
+ staincolor 0x808080 0x808080
+ staintex 16 24
+ tex 24 32
+ velocityjitter 32 32 32
+ velocitymultiplier 5
effect damage_rifle_robot
-count 1
-type alphastatic
-tex 0 8
-size 6 12
-alpha 100 256 400
-color 0x000000 0x301860
-originjitter 0 0 0
-
-// seeker damage effect
-// used in qcsrc/client/damage.qc: pointparticles(self.team, org, '0 0 0', 1);
+ type alphastatic
+ alpha 100 256 400
+ color 0x000000 0x301860
+ count 1
+ size 6 12
+ tex 0 8
effect damage_seeker
-notunderwater
-count 3
-type smoke
-tex 48 55
-size 4 8
-alpha 512 32 1024
-gravity -0.3
-color 0x8f0c00 0xff2200
-sizeincrease -10
-originjitter 2 2 2
-velocityjitter 22 22 50
-// smoke
+ type smoke
+ alpha 512 32 1024
+ color 0x8f0c00 0xff2200
+ count 3
+ gravity -0.300000
+ notunderwater
+ originjitter 2 2 2
+ sizeincrease -10
+ size 4 8
+ tex 48 55
+ velocityjitter 22 22 50
effect damage_seeker
-notunderwater
-type alphastatic
-count 2
-tex 0 8
-size 2 4
-sizeincrease 10
-alpha 128 32 128
-color 0x000000 0x111111
-gravity -0.3
-originjitter 4 4 4
-velocityjitter 11 11 50
-// light
-/*effect damage_seeker
-notunderwater
-trailspacing 8
-lightradius 65
-lightradiusfade 280
-lightcolor 0.7 0.5 0.1*/
-
-// hagar damage effect
-// used in qcsrc/client/damage.qc: pointparticles(self.team, org, '0 0 0', 1);
+ type alphastatic
+ alpha 128 32 128
+ color 0x000000 0x111111
+ count 2
+ gravity -0.300000
+ notunderwater
+ originjitter 4 4 4
+ sizeincrease 10
+ size 2 4
+ tex 0 8
+ velocityjitter 11 11 50
effect damage_hagar
-notunderwater
-count 3
-type smoke
-tex 48 55
-size 4 8
-alpha 512 32 1024
-gravity -0.3
-color 0x8f0c00 0xff3a00
-sizeincrease -10
-originjitter 2 2 2
-velocityjitter 22 22 50
-// smoke
+ type smoke
+ alpha 512 32 1024
+ color 0x8f0c00 0xff3a00
+ count 3
+ gravity -0.300000
+ notunderwater
+ originjitter 2 2 2
+ sizeincrease -10
+ size 4 8
+ tex 48 55
+ velocityjitter 22 22 50
effect damage_hagar
-notunderwater
-type alphastatic
-count 2
-tex 0 8
-size 2 4
-sizeincrease 10
-alpha 128 32 128
-color 0x000000 0x111111
-gravity -0.3
-originjitter 4 4 4
-velocityjitter 11 11 50
-// light
-/*effect damage_hagar
-notunderwater
-trailspacing 8
-lightradius 65
-lightradiusfade 280
-lightcolor 0.7 0.5 0.1*/
-
-// fireball damage effect
-// used in qcsrc/client/damage.qc: pointparticles(self.team, org, '0 0 0', 1);
+ type alphastatic
+ alpha 128 32 128
+ color 0x000000 0x111111
+ count 2
+ gravity -0.300000
+ notunderwater
+ originjitter 4 4 4
+ sizeincrease 10
+ size 2 4
+ tex 0 8
+ velocityjitter 11 11 50
effect damage_fireball
-notunderwater
-count 4
-type smoke
-tex 48 55
-size 5 10
-alpha 256 16 512
-gravity -0.5
-color 0x8f0d00 0xff5a00
-sizeincrease -10
-originjitter 8 8 8
-velocityjitter 22 22 50
-// smoke
+ type smoke
+ alpha 256 16 512
+ color 0x8f0d00 0xff5a00
+ count 4
+ gravity -0.500000
+ notunderwater
+ originjitter 8 8 8
+ sizeincrease -10
+ size 5 10
+ tex 48 55
+ velocityjitter 22 22 50
effect damage_fireball
-notunderwater
-type alphastatic
-count 4
-tex 0 8
-size 4 8
-sizeincrease 10
-alpha 128 32 128
-color 0x000000 0x111111
-gravity -0.3
-originjitter 6 6 6
-velocityjitter 11 11 50
-// light
-/*effect damage_fireball
-notunderwater
-trailspacing 8
-lightradius 65
-lightradiusfade 280
-lightcolor 1.0 0.8 0.4*/
-
-// rocketlauncher damage effect
-// used in qcsrc/client/damage.qc: pointparticles(self.team, org, '0 0 0', 1);
+ type alphastatic
+ alpha 128 32 128
+ color 0x000000 0x111111
+ count 4
+ gravity -0.300000
+ notunderwater
+ originjitter 6 6 6
+ sizeincrease 10
+ size 4 8
+ tex 0 8
+ velocityjitter 11 11 50
effect damage_rocketlauncher
-notunderwater
-count 3
-type smoke
-tex 48 55
-size 5 10
-alpha 512 64 1024
-gravity -0.7
-color 0x8f0c00 0xff2a00
-sizeincrease -10
-originjitter 4 4 4
-velocityjitter 22 22 30
-// smoke
+ type smoke
+ alpha 512 64 1024
+ color 0x8f0c00 0xff2a00
+ count 3
+ gravity -0.700000
+ notunderwater
+ originjitter 4 4 4
+ sizeincrease -10
+ size 5 10
+ tex 48 55
+ velocityjitter 22 22 30
effect damage_rocketlauncher
-notunderwater
-type alphastatic
-count 3
-tex 0 8
-size 4 8
-sizeincrease 10
-alpha 128 32 128
-color 0x000000 0x111111
-gravity -0.3
-originjitter 4 4 4
-velocityjitter 11 11 50
-// light
-/*effect damage_rocketlauncher
-notunderwater
-trailspacing 8
-lightradius 60
-lightradiusfade 280
-lightcolor 0.8 0.6 0.2*/
-
-// fireflies
-// used nowhere in code
+ type alphastatic
+ alpha 128 32 128
+ color 0x000000 0x111111
+ count 3
+ gravity -0.300000
+ notunderwater
+ originjitter 4 4 4
+ sizeincrease 10
+ size 4 8
+ tex 0 8
+ velocityjitter 11 11 50
effect fireflies
-count 1
-bounce -1
-airfriction 5
-time 1 2
-type static
-tex 38 38
-color 0xff9600 0xffefb8
-size 2 3
-sizeincrease -0.3
-alpha 256 256 70
-gravity 0
-originoffset 8 8 8
-originjitter 32 32 32
-velocityoffset 2 2 2
-velocityjitter 64 64 64
-//lightradius 50
-//lightradiusfade 50
-//lightcolor 1 0.9 0.7
-//lightshadow 1
-
-// heal ray muzzleflash
+ type static
+ airfriction 5
+ alpha 256 256 70
+ bounce -1
+ color 0xff9600 0xffefb8
+ count 1
+ originjitter 32 32 32
+ originoffset 8 8 8
+ sizeincrease -0.300000
+ size 2 3
+ tex 38 38
+ time 1 2
+ velocityjitter 64 64 64
+ velocityoffset 2 2 2
effect healray_muzzleflash
-countabsolute 1
-type smoke
-color 0x283880 0x283880 // 0x202020 0x404040
-tex 65 65
-size 20 20
-alpha 256 256 512
-originjitter 1.5 1.5 1.5
-velocityjitter 6 6 6
-sizeincrease -10
-velocitymultiplier 0.01
-lightradius 200
-lightradiusfade 2000
-lightcolor 1.5 3 6
-
+ type smoke
+ alpha 256 256 512
+ color 0x283880 0x283880
+ countabsolute 1
+ lightcolor 1.5 3 6
+ lightradiusfade 2000
+ lightradius 200
+ originjitter 1.5 1.5 1.5
+ sizeincrease -10
+ size 20 20
+ tex 65 65
+ velocityjitter 6 6 6
+ velocitymultiplier 0.010000
effect healray_muzzleflash
-count 22
-type spark
-tex 71 73
-color 0xD9FDFF 0x00f0ff
-size 1 15
-sizeincrease 3
-alpha 50 150 1924
-originjitter 1 1 1
-velocityjitter 150 150 150
-velocitymultiplier 0.4
-airfriction 5
-stretchfactor 3.9
-
+ type spark
+ airfriction 5
+ alpha 50 150 1924
+ color 0xD9FDFF 0x00f0ff
+ count 22
+ originjitter 1 1 1
+ sizeincrease 3
+ size 1 15
+ stretchfactor 3.900000
+ tex 71 73
+ velocityjitter 150 150 150
+ velocitymultiplier 0.400000
effect healray_muzzleflash
-count 4
-type spark
-tex 70 70
-color 0xD9FDFF 0x00f0ff
-size 1 1
-alpha 110 228 4024
-originjitter 1 1 1
-velocityjitter 650 650 650
-velocitymultiplier 1.1
-stretchfactor 0.2
-
-
-
-//healray impact
-
+ type spark
+ alpha 110 228 4024
+ color 0xD9FDFF 0x00f0ff
+ count 4
+ originjitter 1 1 1
+ size 1 1
+ stretchfactor 0.200000
+ tex 70 70
+ velocityjitter 650 650 650
+ velocitymultiplier 1.100000
effect healray_impact
-countabsolute 1
-type decal
-tex 59 59
-size 32 32
-alpha 256 256 0
-color 0xd800ff 0xd800ff
-originjitter 17 17 17
-lightradius 125
-lightradiusfade 450
-lightcolor 0 4.375 0
-// shockwave
+ type decal
+ alpha 256 256 0
+ color 0xd800ff 0xd800ff
+ countabsolute 1
+ lightcolor 0 4.4 0
+ lightradiusfade 450
+ lightradius 125
+ originjitter 17 17 17
+ size 32 32
+ tex 59 59
effect healray_impact
-type smoke
-countabsolute 1
-tex 33 33
-size 32 32
-sizeincrease 1400
-color 0x00ff00 0x84c52f
-alpha 40 40 350
-velocitymultiplier 44
-// cloud of bouncing sparks
+ type smoke
+ alpha 40 40 350
+ color 0x00ff00 0x84c52f
+ countabsolute 1
+ sizeincrease 1400
+ size 32 32
+ tex 33 33
+ velocitymultiplier 44
effect healray_impact
-count 30
-type spark
-tex 70 70
-color 0x00ff00 0x84c52f
-size 1 2
-alpha 156 300 1024
-gravity 2
-airfriction 6
-originjitter 1 1 1
-velocityjitter 1112 1112 1112
-// inner cloud of smoke
+ type spark
+ airfriction 6
+ alpha 156 300 1024
+ color 0x00ff00 0x84c52f
+ count 30
+ gravity 2
+ originjitter 1 1 1
+ size 1 2
+ tex 70 70
+ velocityjitter 1112 1112 1112
effect healray_impact
-count 15
-type smoke
-color 0x00ff00 0x84c52f
-tex 40 40
-size 2 3
-alpha 200 456 512
-airfriction 3
-gravity -2
-velocityjitter 120 120 420
-rotate -180 180 -90 90
-
-
-
-
-// big plasma muzzle flash
-
+ type smoke
+ airfriction 3
+ alpha 200 456 512
+ color 0x00ff00 0x84c52f
+ count 15
+ gravity -2
+ rotate -180 180 -90 90
+ size 2 3
+ tex 40 40
+ velocityjitter 120 120 420
effect bigplasma_muzzleflash
-countabsolute 1
-type smoke
-color 0x283880 0x283880 // 0x202020 0x404040
-tex 65 65
-size 50 50
-alpha 256 256 812
-originjitter 1.5 1.5 1.5
-velocityjitter 6 6 6
-sizeincrease -10
-velocitymultiplier 0.01
-lightradius 200
-lightradiusfade 2000
-lightcolor 1.5 3 6
-
+ type smoke
+ alpha 256 256 812
+ color 0x283880 0x283880
+ countabsolute 1
+ lightcolor 1.5 3 6
+ lightradiusfade 2000
+ lightradius 200
+ originjitter 1.5 1.5 1.5
+ sizeincrease -10
+ size 50 50
+ tex 65 65
+ velocityjitter 6 6 6
+ velocitymultiplier 0.010000
effect bigplasma_muzzleflash
-countabsolute 1
-type smoke
-color 0x00f0ff 0x00f0ff
-tex 74 74
-size 20 20
-alpha 56 56 1112
-sizeincrease 300
-
+ type smoke
+ alpha 56 56 1112
+ color 0x00f0ff 0x00f0ff
+ countabsolute 1
+ sizeincrease 300
+ size 20 20
+ tex 74 74
effect bigplasma_muzzleflash
-count 14
-type spark
-tex 51 55
-color 0xD9FDFF 0x00f0ff
-size 5 10
-sizeincrease 135
-alpha 50 150 1924
-originjitter 1 1 1
-velocityjitter 350 350 350
-velocitymultiplier 0.4
-airfriction 5
-stretchfactor 1.9
-
+ type spark
+ airfriction 5
+ alpha 50 150 1924
+ color 0xD9FDFF 0x00f0ff
+ count 14
+ originjitter 1 1 1
+ sizeincrease 135
+ size 5 10
+ stretchfactor 1.900000
+ tex 51 55
+ velocityjitter 350 350 350
+ velocitymultiplier 0.400000
effect bigplasma_muzzleflash
-count 4
-type spark
-tex 70 70
-color 0xD9FDFF 0x00f0ff
-size 20 20
-alpha 110 228 4024
-originjitter 1 1 1
-velocityjitter 650 650 650
-velocitymultiplier 1.1
-stretchfactor 0.2
-
-
-// big plasma impact
-
+ type spark
+ alpha 110 228 4024
+ color 0xD9FDFF 0x00f0ff
+ count 4
+ originjitter 1 1 1
+ size 20 20
+ stretchfactor 0.200000
+ tex 70 70
+ velocityjitter 650 650 650
+ velocitymultiplier 1.100000
effect bigplasma_impact
-countabsolute 1
-type decal
-tex 59 59
-size 32 32
-alpha 256 256 0
-originjitter 17 17 17
-lightradius 125
-lightradiusfade 450
-lightcolor 3.125 4.375 10
-// shockwave
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 3.1 4.4 10
+ lightradiusfade 450
+ lightradius 125
+ originjitter 17 17 17
+ size 32 32
+ tex 59 59
effect bigplasma_impact
-type smoke
-countabsolute 1
-tex 33 33
-size 32 32
-sizeincrease 1400
-color 0x80C0FF 0x80C0FF
-alpha 40 40 350
-velocitymultiplier 44
-// cloud of bouncing sparks
+ type smoke
+ alpha 40 40 350
+ color 0x80C0FF 0x80C0FF
+ countabsolute 1
+ sizeincrease 1400
+ size 32 32
+ tex 33 33
+ velocitymultiplier 44
effect bigplasma_impact
-count 30
-type spark
-tex 70 70
-color 0x629dff 0x0018ff
-size 1 2
-alpha 156 300 1024
-gravity 2
-airfriction 6
-originjitter 1 1 1
-velocityjitter 1512 1512 1512
-// inner cloud of smoke
+ type spark
+ airfriction 6
+ alpha 156 300 1024
+ color 0x629dff 0x0018ff
+ count 30
+ gravity 2
+ originjitter 1 1 1
+ size 1 2
+ tex 70 70
+ velocityjitter 1512 1512 1512
effect bigplasma_impact
-count 15
-type smoke
-color 0x629dff 0x0018ff
-tex 48 55
-size 20 24
-sizeincrease 555
-alpha 200 456 1512
-airfriction 30
-originjitter 20 20 20
-velocityjitter 320 320 320
-rotate -180 180 -9 9
-// smoke
+ type smoke
+ airfriction 30
+ alpha 200 456 1512
+ color 0x629dff 0x0018ff
+ count 15
+ originjitter 20 20 20
+ rotate -180 180 -9 9
+ sizeincrease 555
+ size 20 24
+ tex 48 55
+ velocityjitter 320 320 320
effect bigplasma_impact
-type smoke
-count 16
-blend alpha
-tex 0 7
-size 60 30
-color 0x222222 0x000000
-alpha 128 328 390
-rotate -180 180 2 -2
-velocityjitter 100 100 200
-velocityoffset 0 0 180
-originjitter 80 80 10
-sizeincrease 30
-airfriction 0.04
-gravity 0.4
-// smoke in the middle
+ type smoke
+ airfriction 0.040000
+ alpha 128 328 390
+ blend alpha
+ color 0x222222 0x000000
+ count 16
+ gravity 0.400000
+ originjitter 80 80 10
+ rotate -180 180 2 -2
+ sizeincrease 30
+ size 60 30
+ tex 0 7
+ velocityjitter 100 100 200
+ velocityoffset 0 0 180
effect bigplasma_impact
-type alphastatic
-count 10
-tex 0 7
-size 60 70
-color 0x222222 0x000000
-alpha 128 328 310
-rotate -180 180 20 -20
-velocityjitter 10 10 10
-originjitter 80 80 80
-sizeincrease -10
-airfriction 0.04
-gravity -0.2
-
-// redflag_touch -- effects for touching the red flag
-// used nowhere in code
+ type alphastatic
+ airfriction 0.040000
+ alpha 128 328 310
+ color 0x222222 0x000000
+ count 10
+ gravity -0.200000
+ originjitter 80 80 80
+ rotate -180 180 20 -20
+ sizeincrease -10
+ size 60 70
+ tex 0 7
+ velocityjitter 10 10 10
effect redflag_touch
-count 35
-type spark
-tex 40 40
-color 0xFF0000 0x970000
-size 1 3
-alpha 0 256 556
-gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 300 300 300
-velocitymultiplier 0.5
-airfriction 3
-
-// blueflag_touch -- effects for touching the blue flag
-// used nowhere in code
+ type spark
+ airfriction 3
+ alpha 0 256 556
+ bounce 1.500000
+ color 0xFF0000 0x970000
+ count 35
+ gravity 1
+ originjitter 1 1 1
+ size 1 3
+ tex 40 40
+ velocityjitter 300 300 300
+ velocitymultiplier 0.500000
effect blueflag_touch
-count 35
-type spark
-tex 40 40
-color 0x0000FF 0x000097
-size 1 3
-alpha 0 256 556
-gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 300 300 300
-velocitymultiplier 0.5
-airfriction 3
-
-// red_pass
-// used nowhere in code
+ type spark
+ airfriction 3
+ alpha 0 256 556
+ bounce 1.500000
+ color 0x0000FF 0x000097
+ count 35
+ gravity 1
+ originjitter 1 1 1
+ size 1 3
+ tex 40 40
+ velocityjitter 300 300 300
+ velocitymultiplier 0.500000
effect red_pass
-trailspacing 64
-color 0xFF0000 0x970000
-size 2 2
-tex 32 32
-alpha 64 128 64
-airfriction 5
-sizeincrease 2
-type static
+ type static
+ airfriction 5
+ alpha 64 128 64
+ color 0xFF0000 0x970000
+ sizeincrease 2
+ size 2 2
+ tex 32 32
+ trailspacing 64
effect red_pass
-trailspacing 12
-color 0xFF0000 0x970000
-size 1 1
-tex 0 8
-alpha 32 64 32
-airfriction 9
-sizeincrease 8
-velocityjitter 64 64 64
-type static
+ type static
+ airfriction 9
+ alpha 32 64 32
+ color 0xFF0000 0x970000
+ sizeincrease 8
+ size 1 1
+ tex 0 8
+ trailspacing 12
+ velocityjitter 64 64 64
effect red_pass
-trailspacing 12
-color 0xFF0000 0x970000
-size 4 4
-//tex 48 55
-alpha 256 256 1280
-type static
-
-// blue_pass
-// used nowhere in code
+ type static
+ alpha 256 256 1280
+ color 0xFF0000 0x970000
+ size 4 4
+ trailspacing 12
effect blue_pass
-trailspacing 64
-color 0x0000FF 0x000097
-size 2 2
-tex 32 32
-alpha 64 128 64
-airfriction 5
-sizeincrease 2
-type static
+ type static
+ airfriction 5
+ alpha 64 128 64
+ color 0x0000FF 0x000097
+ sizeincrease 2
+ size 2 2
+ tex 32 32
+ trailspacing 64
effect blue_pass
-trailspacing 12
-color 0x0000FF 0x000097
-size 1 1
-tex 0 8
-alpha 32 64 32
-airfriction 9
-sizeincrease 8
-velocityjitter 64 64 64
-type static
+ type static
+ airfriction 9
+ alpha 32 64 32
+ color 0x0000FF 0x000097
+ sizeincrease 8
+ size 1 1
+ tex 0 8
+ trailspacing 12
+ velocityjitter 64 64 64
effect blue_pass
-trailspacing 12
-color 0x0000FF 0x000097
-size 4 4
-//tex 48 55
-alpha 256 256 1280
-type static
-
-// red_cap -- red team capture effect
+ type static
+ alpha 256 256 1280
+ color 0x0000FF 0x000097
+ size 4 4
+ trailspacing 12
effect red_cap
-count 500
-type spark
-tex 64 64
-color 0xFF0000 0x970000
-size 1 1
-alpha 0 256 100
-stretchfactor 2
-//gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 1000 1000 1500
-velocitymultiplier 0.5
-airfriction 2
-stretchfactor 0.6
+ type spark
+ airfriction 2
+ alpha 0 256 100
+ bounce 1.500000
+ color 0xFF0000 0x970000
+ count 500
+ originjitter 1 1 1
+ size 1 1
+ stretchfactor 0.600000
+ tex 64 64
+ velocityjitter 1000 1000 1500
+ velocitymultiplier 0.500000
effect red_cap
-countabsolute 1
-type smoke
-tex 65 65
-size 150 150
-alpha 190 190 180
-sizeincrease -80
-color 0xFF0000 0x970000
-
-// blue_cap -- blue team capture effect
+ type smoke
+ alpha 190 190 180
+ color 0xFF0000 0x970000
+ countabsolute 1
+ sizeincrease -80
+ size 150 150
+ tex 65 65
effect blue_cap
-count 500
-type spark
-tex 64 64
-color 0x0000FF 0x000097
-size 1 1
-alpha 0 256 100
-stretchfactor 2
-//gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 1000 1000 1500
-velocitymultiplier 0.5
-airfriction 2
-stretchfactor 0.6
+ type spark
+ airfriction 2
+ alpha 0 256 100
+ bounce 1.500000
+ color 0x0000FF 0x000097
+ count 500
+ originjitter 1 1 1
+ size 1 1
+ stretchfactor 0.600000
+ tex 64 64
+ velocityjitter 1000 1000 1500
+ velocitymultiplier 0.500000
effect blue_cap
-countabsolute 1
-type smoke
-tex 65 65
-size 150 150
-alpha 190 190 180
-sizeincrease -80
-color 0x0000FF 0x000097
-
-// spawn_point_red -- red team idle spawn point effect
+ type smoke
+ alpha 190 190 180
+ color 0x0000FF 0x000097
+ countabsolute 1
+ sizeincrease -80
+ size 150 150
+ tex 65 65
effect spawn_point_red
-count 37.5
-type static
-color 0xFF0F0F 0xFF0F0F
-size 1.0 2.0
-alpha 64 128 128
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 16 16 64
-velocityjitter 32 32 0
-//lightradius 200
-//lighttime 0
-//lightcolor 0.4 0.9 0.9
-
-// spawn_point_blue -- blue team idle spawn point effect
+ type static
+ airfriction 0.200000
+ alpha 64 128 128
+ color 0xFF0F0F 0xFF0F0F
+ count 37.500000
+ gravity -0.100000
+ liquidfriction 0.800000
+ originjitter 16 16 64
+ size 1 2
+ velocityjitter 32 32 0
effect spawn_point_blue
-count 37.5
-type static
-color 0x0F0FFF 0x0F0FFF
-size 1.0 2.0
-alpha 64 128 128
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 16 16 64
-velocityjitter 32 32 0
-//lightradius 200
-//lighttime 0
-//lightcolor 0.4 0.9 0.9
-
-// spawn_point_yellow -- yellow team idle spawn point effect
+ type static
+ airfriction 0.200000
+ alpha 64 128 128
+ color 0x0F0FFF 0x0F0FFF
+ count 37.500000
+ gravity -0.100000
+ liquidfriction 0.800000
+ originjitter 16 16 64
+ size 1 2
+ velocityjitter 32 32 0
effect spawn_point_yellow
-count 37.5
-type static
-color 0xFFFF0F 0xFFFF0F
-size 1.0 2.0
-alpha 64 128 128
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 16 16 64
-velocityjitter 32 32 0
-//lightradius 200
-//lighttime 0
-//lightcolor 0.4 0.9 0.9
-
-// spawn_point_pink -- pink team idle spawn point effect
+ type static
+ airfriction 0.200000
+ alpha 64 128 128
+ color 0xFFFF0F 0xFFFF0F
+ count 37.500000
+ gravity -0.100000
+ liquidfriction 0.800000
+ originjitter 16 16 64
+ size 1 2
+ velocityjitter 32 32 0
effect spawn_point_pink
-count 37.5
-type static
-color 0xFF0FFF 0xFF0FFF
-size 1.0 2.0
-alpha 64 128 128
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 16 16 64
-velocityjitter 32 32 0
-//lightradius 200
-//lighttime 0
-//lightcolor 0.4 0.9 0.9
-
-// spawn_point_neutral -- neutral idle spawn point effect
+ type static
+ airfriction 0.200000
+ alpha 64 128 128
+ color 0xFF0FFF 0xFF0FFF
+ count 37.500000
+ gravity -0.100000
+ liquidfriction 0.800000
+ originjitter 16 16 64
+ size 1 2
+ velocityjitter 32 32 0
effect spawn_point_neutral
-count 37.5
-type static
-color 0xFFFFFF 0xFFFFFF
-size 1.0 2.0
-alpha 64 128 128
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 16 16 64
-velocityjitter 32 32 0
-//lightradius 200
-//lighttime 0
-//lightcolor 0.4 0.9 0.9
-
-// spawn_event_red -- red team spawning effect
+ type static
+ airfriction 0.200000
+ alpha 64 128 128
+ color 0xFFFFFF 0xFFFFFF
+ count 37.500000
+ gravity -0.100000
+ liquidfriction 0.800000
+ originjitter 16 16 64
+ size 1 2
+ velocityjitter 32 32 0
effect spawn_event_red
-count 100
-type spark
-tex 64 64
-color 0xFF0F0F 0xFF0F0F
-size 1 1
-alpha 0 256 256
-stretchfactor 0.6
-//gravity 1
-bounce 1
-originjitter 1 1 1
-velocityjitter 500 500 500
-velocitymultiplier 0.1
-airfriction 2
+ type spark
+ airfriction 2
+ alpha 0 256 256
+ bounce 1
+ color 0xFF0F0F 0xFF0F0F
+ count 100
+ originjitter 1 1 1
+ size 1 1
+ stretchfactor 0.600000
+ tex 64 64
+ velocityjitter 500 500 500
+ velocitymultiplier 0.100000
effect spawn_event_red
-countabsolute 1
-type smoke
-tex 65 65
-size 100 100
-alpha 190 190 180
-sizeincrease -80
-color 0xFF0F0F 0xFF0F0F
-
-// spawn_event_blue -- blue team spawning effect
+ type smoke
+ alpha 190 190 180
+ color 0xFF0F0F 0xFF0F0F
+ countabsolute 1
+ sizeincrease -80
+ size 100 100
+ tex 65 65
effect spawn_event_blue
-count 100
-type spark
-tex 64 64
-color 0x0F0FFF 0x0F0FFF
-size 1 1
-alpha 0 256 256
-stretchfactor 0.6
-//gravity 1
-bounce 1
-originjitter 1 1 1
-velocityjitter 500 500 500
-velocitymultiplier 0.1
-airfriction 2
+ type spark
+ airfriction 2
+ alpha 0 256 256
+ bounce 1
+ color 0x0F0FFF 0x0F0FFF
+ count 100
+ originjitter 1 1 1
+ size 1 1
+ stretchfactor 0.600000
+ tex 64 64
+ velocityjitter 500 500 500
+ velocitymultiplier 0.100000
effect spawn_event_blue
-countabsolute 1
-type smoke
-tex 65 65
-size 100 100
-alpha 190 190 180
-sizeincrease -80
-color 0x0F0FFF 0x0F0FFF
-
-// spawn_event_yellow -- yellow team spawning effect
+ type smoke
+ alpha 190 190 180
+ color 0x0F0FFF 0x0F0FFF
+ countabsolute 1
+ sizeincrease -80
+ size 100 100
+ tex 65 65
effect spawn_event_yellow
-count 100
-type spark
-tex 64 64
-color 0xFFFF0F 0xFFFF0F
-size 1 1
-alpha 0 256 256
-stretchfactor 0.6
-//gravity 1
-bounce 1
-originjitter 1 1 1
-velocityjitter 500 500 500
-velocitymultiplier 0.1
-airfriction 2
+ type spark
+ airfriction 2
+ alpha 0 256 256
+ bounce 1
+ color 0xFFFF0F 0xFFFF0F
+ count 100
+ originjitter 1 1 1
+ size 1 1
+ stretchfactor 0.600000
+ tex 64 64
+ velocityjitter 500 500 500
+ velocitymultiplier 0.100000
effect spawn_event_yellow
-countabsolute 1
-type smoke
-tex 65 65
-size 100 100
-alpha 190 190 180
-sizeincrease -80
-color 0xFFFF0F 0xFFFF0F
-
-// spawn_event_pink -- pink team spawning effect
+ type smoke
+ alpha 190 190 180
+ color 0xFFFF0F 0xFFFF0F
+ countabsolute 1
+ sizeincrease -80
+ size 100 100
+ tex 65 65
effect spawn_event_pink
-count 100
-type spark
-tex 64 64
-color 0xFF0FFF 0xFF0FFF
-size 1 1
-alpha 0 256 256
-stretchfactor 0.6
-//gravity 1
-bounce 1
-originjitter 1 1 1
-velocityjitter 500 500 500
-velocitymultiplier 0.1
-airfriction 2
+ type spark
+ airfriction 2
+ alpha 0 256 256
+ bounce 1
+ color 0xFF0FFF 0xFF0FFF
+ count 100
+ originjitter 1 1 1
+ size 1 1
+ stretchfactor 0.600000
+ tex 64 64
+ velocityjitter 500 500 500
+ velocitymultiplier 0.100000
effect spawn_event_pink
-countabsolute 1
-type smoke
-tex 65 65
-size 100 100
-alpha 190 190 180
-sizeincrease -80
-color 0xFF0FFF 0xFF0FFF
-
-// spawn_event_neutral -- neutral spawning effect
+ type smoke
+ alpha 190 190 180
+ color 0xFF0FFF 0xFF0FFF
+ countabsolute 1
+ sizeincrease -80
+ size 100 100
+ tex 65 65
effect spawn_event_neutral
-count 100
-type spark
-tex 64 64
-color 0xFFFFFF 0xFFFFFF
-size 1 1
-alpha 0 256 256
-stretchfactor 0.6
-//gravity 1
-bounce 1
-originjitter 1 1 1
-velocityjitter 500 500 500
-velocitymultiplier 0.1
-airfriction 2
+ type spark
+ airfriction 2
+ alpha 0 256 256
+ bounce 1
+ color 0xFFFFFF 0xFFFFFF
+ count 100
+ originjitter 1 1 1
+ size 1 1
+ stretchfactor 0.600000
+ tex 64 64
+ velocityjitter 500 500 500
+ velocitymultiplier 0.100000
effect spawn_event_neutral
-countabsolute 1
-type smoke
-tex 65 65
-size 100 100
-alpha 190 190 180
-sizeincrease -80
-color 0xFFFFFF 0xFFFFFF
-
-// nade effects
+ type smoke
+ alpha 190 190 180
+ color 0xFFFFFF 0xFFFFFF
+ countabsolute 1
+ sizeincrease -80
+ size 100 100
+ tex 65 65
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
+ type smoke
+ alpha 100 100 250
+ color 0x006cff 0x0600ff
+ sizeincrease -1
+ size 3 3
+ tex 65 65
+ trailspacing 1
effect nade_blue
-notunderwater
-trailspacing 8
-type smoke
-color 0x0600ff 0x9794ff
-tex 65 65
-size 15 25
-sizeincrease -10
-alpha 30 30 150
-// bubbles
+ type smoke
+ alpha 30 30 150
+ color 0x0600ff 0x9794ff
+ notunderwater
+ sizeincrease -10
+ size 15 25
+ tex 65 65
+ trailspacing 8
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
-
+ type bubble
+ alpha 256 256 256
+ bounce 1.500000
+ color 0x006cff 0x0600ff
+ gravity -0.125000
+ liquidfriction 4
+ size 1 1
+ tex 62 62
+ trailspacing 16
+ underwater
+ 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
+ type smoke
+ alpha 100 100 250
+ color 0xff0000 0xff3c00
+ sizeincrease -1
+ size 3 3
+ tex 65 65
+ trailspacing 1
effect nade_red
-notunderwater
-trailspacing 8
-type smoke
-color 0xff0000 0xffa2a2
-tex 65 65
-size 15 25
-sizeincrease -10
-alpha 30 30 150
-// bubbles
+ type smoke
+ alpha 30 30 150
+ color 0xff0000 0xffa2a2
+ notunderwater
+ sizeincrease -10
+ size 15 25
+ tex 65 65
+ trailspacing 8
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
-
+ type bubble
+ alpha 256 256 256
+ bounce 1.500000
+ color 0xff0000 0xff3c00
+ gravity -0.125000
+ liquidfriction 4
+ size 1 1
+ tex 62 62
+ trailspacing 16
+ underwater
+ 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
+ type smoke
+ alpha 100 100 250
+ color 0xFFFF0F 0xFFFF0F
+ sizeincrease -1
+ size 3 3
+ tex 65 65
+ trailspacing 1
effect nade_yellow
-notunderwater
-trailspacing 8
-type smoke
-color 0xFFFF0F 0xFFFF0F
-tex 65 65
-size 15 25
-sizeincrease -10
-alpha 30 30 150
-// bubbles
+ type smoke
+ alpha 30 30 150
+ color 0xFFFF0F 0xFFFF0F
+ notunderwater
+ sizeincrease -10
+ size 15 25
+ tex 65 65
+ trailspacing 8
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
-
+ type bubble
+ alpha 256 256 256
+ bounce 1.500000
+ color 0xFFFF0F 0xFFFF0F
+ gravity -0.125000
+ liquidfriction 4
+ size 1 1
+ tex 62 62
+ trailspacing 16
+ underwater
+ 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
+ type smoke
+ alpha 100 100 250
+ color 0xFF0FFF 0xFF0FFF
+ sizeincrease -1
+ size 3 3
+ tex 65 65
+ trailspacing 1
effect nade_pink
-notunderwater
-trailspacing 8
-type smoke
-color 0xFF0FFF 0xFF0FFF
-tex 65 65
-size 15 25
-sizeincrease -10
-alpha 30 30 150
-// bubbles
+ type smoke
+ alpha 30 30 150
+ color 0xFF0FFF 0xFF0FFF
+ notunderwater
+ sizeincrease -10
+ size 15 25
+ tex 65 65
+ trailspacing 8
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
-
+ type bubble
+ alpha 256 256 256
+ bounce 1.500000
+ color 0xFF0FFF 0xFF0FFF
+ gravity -0.125000
+ liquidfriction 4
+ size 1 1
+ tex 62 62
+ trailspacing 16
+ underwater
+ velocityjitter 16 16 16
effect nade_neutral
-trailspacing 1
-type smoke
-color 0xFFFFFF 0xFFFFFF
-tex 65 65
-size 3 3
-sizeincrease -1
-alpha 100 100 250
-//gravity -0.11
-// fire
+ type smoke
+ alpha 100 100 250
+ color 0xFFFFFF 0xFFFFFF
+ sizeincrease -1
+ size 3 3
+ tex 65 65
+ trailspacing 1
effect nade_neutral
-notunderwater
-trailspacing 8
-type smoke
-color 0xFFFFFF 0xFFFFFF
-tex 65 65
-size 15 25
-sizeincrease -10
-alpha 30 30 150
-// bubbles
+ type smoke
+ alpha 30 30 150
+ color 0xFFFFFF 0xFFFFFF
+ notunderwater
+ sizeincrease -10
+ size 15 25
+ tex 65 65
+ trailspacing 8
effect nade_neutral
-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
-
+ type bubble
+ alpha 256 256 256
+ bounce 1.500000
+ color 0xFFFFFF 0xFFFFFF
+ gravity -0.125000
+ liquidfriction 4
+ size 1 1
+ tex 62 62
+ trailspacing 16
+ underwater
+ 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
+ type smoke
+ alpha 100 100 250
+ color 0xff0000 0xff3c00
+ sizeincrease -1
+ size 5 5
+ tex 65 65
+ trailspacing 1
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
+ type smoke
+ alpha 200 200 1000
+ color 0xff0000 0xffa2a2
+ notunderwater
+ sizeincrease -30
+ size 45 25
+ tex 65 65
+ trailspacing 64
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
+ type bubble
+ alpha 256 256 256
+ bounce 1.500000
+ color 0xff0000 0xff3c00
+ gravity -0.125000
+ liquidfriction 4
+ size 1 1
+ tex 62 62
+ trailspacing 16
+ underwater
+ 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
-
+ type smoke
+ alpha 300 900 1500
+ color 0xff0000 0xff3c00
+ originjitter 2 2 2
+ rotate -180 180 20 -20
+ sizeincrease -40
+ size 15 25
+ tex 71 73
+ trailspacing 16
+ velocityjitter 10 10 10
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
+ type smoke
+ alpha 100 100 250
+ color 0x006cff 0x0600ff
+ sizeincrease -1
+ size 5 5
+ tex 65 65
+ trailspacing 1
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
+ type smoke
+ alpha 200 200 1000
+ color 0x0600ff 0x9794ff
+ notunderwater
+ sizeincrease -30
+ size 45 25
+ tex 65 65
+ trailspacing 64
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
+ type bubble
+ alpha 256 256 256
+ bounce 1.500000
+ color 0x006cff 0x0600ff
+ gravity -0.125000
+ liquidfriction 4
+ size 1 1
+ tex 62 62
+ trailspacing 16
+ underwater
+ velocityjitter 16 16 16
effect nade_blue_burn
-trailspacing 16
-type smoke
-color 0x006cff 0x0600ff
-tex 33 33
-size 25 25
-sizeincrease -30
-
+ type smoke
+ alpha 300 900 1500
+ color 0x006cff 0x0600ff
+ originjitter 2 2 2
+ rotate -180 180 20 -20
+ sizeincrease -40
+ size 15 25
+ tex 71 73
+ trailspacing 16
+ velocityjitter 10 10 10
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
+ type smoke
+ alpha 100 100 250
+ color 0xFFFF0F 0xFFFF0F
+ sizeincrease -1
+ size 5 5
+ tex 65 65
+ trailspacing 1
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
+ type smoke
+ alpha 200 200 1000
+ color 0xFFFF0F 0xFFFF0F
+ notunderwater
+ sizeincrease -30
+ size 45 25
+ tex 65 65
+ trailspacing 64
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
+ type bubble
+ alpha 256 256 256
+ bounce 1.500000
+ color 0xFFFF0F 0xFFFF0F
+ gravity -0.125000
+ liquidfriction 4
+ size 1 1
+ tex 62 62
+ trailspacing 16
+ underwater
+ velocityjitter 16 16 16
effect nade_yellow_burn
-trailspacing 16
-type smoke
-color 0xFFFF0F 0xFFFF0F
-tex 33 33
-size 25 25
-sizeincrease -30
-
+ type smoke
+ alpha 300 900 1500
+ color 0xFFFF0F 0xFFFF0F
+ originjitter 2 2 2
+ rotate -180 180 20 -20
+ sizeincrease -40
+ size 15 25
+ tex 71 73
+ trailspacing 16
+ velocityjitter 10 10 10
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
+ type smoke
+ alpha 100 100 250
+ color 0xFF0FFF 0xFF0FFF
+ sizeincrease -1
+ size 5 5
+ tex 65 65
+ trailspacing 1
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
+ type smoke
+ alpha 200 200 1000
+ color 0xFF0FFF 0xFF0FFF
+ notunderwater
+ sizeincrease -30
+ size 45 25
+ tex 65 65
+ trailspacing 64
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
+ type bubble
+ alpha 256 256 256
+ bounce 1.500000
+ color 0xFF0FFF 0xFF0FFF
+ gravity -0.125000
+ liquidfriction 4
+ size 1 1
+ tex 62 62
+ trailspacing 16
+ underwater
+ velocityjitter 16 16 16
effect nade_pink_burn
-trailspacing 16
-type smoke
-color 0xFF0FFF 0xFF0FFF
-tex 33 33
-size 25 25
-sizeincrease -30
-
+ type smoke
+ alpha 300 900 1500
+ color 0xFF0FFF 0xFF0FFF
+ originjitter 2 2 2
+ rotate -180 180 20 -20
+ sizeincrease -40
+ size 15 25
+ tex 71 73
+ trailspacing 16
+ velocityjitter 10 10 10
effect nade_neutral_burn
-trailspacing 1
-type smoke
-color 0xFFFFFF 0xFFFFFF
-tex 65 65
-size 5 5
-sizeincrease -1
-alpha 100 100 250
-//gravity -0.11
-// fire
+ type smoke
+ alpha 100 100 250
+ color 0xFFFFFF 0xFFFFFF
+ sizeincrease -1
+ size 5 5
+ tex 65 65
+ trailspacing 1
effect nade_neutral_burn
-notunderwater
-trailspacing 64
-type smoke
-color 0xFFFFFF 0xFFFFFF
-tex 65 65
-size 45 25
-sizeincrease -30
-alpha 200 200 1000
-// bubbles
+ type smoke
+ alpha 200 200 1000
+ color 0xFFFFFF 0xFFFFFF
+ notunderwater
+ sizeincrease -30
+ size 45 25
+ tex 65 65
+ trailspacing 64
effect nade_neutral_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
+ type bubble
+ alpha 256 256 256
+ bounce 1.500000
+ color 0xFFFFFF 0xFFFFFF
+ gravity -0.125000
+ liquidfriction 4
+ size 1 1
+ tex 62 62
+ trailspacing 16
+ underwater
+ velocityjitter 16 16 16
effect nade_neutral_burn
-trailspacing 16
-type smoke
-color 0xFFFFFF 0xFFFFFF
-tex 33 33
-size 25 25
-sizeincrease -30
-
+ type smoke
+ alpha 300 900 1500
+ color 0xFFFFFF 0xFFFFFF
+ originjitter 2 2 2
+ rotate -180 180 20 -20
+ sizeincrease -40
+ size 15 25
+ tex 71 73
+ trailspacing 16
+ velocityjitter 10 10 10
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
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 20 20 100
+ lightradiusfade 1500
+ lightradius 300
+ originjitter 26 26 26
+ size 88 88
+ tex 8 16
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
+ type smoke
+ alpha 80 80 650
+ color 0x80C0FF 0x80C0FF
+ countabsolute 1
+ sizeincrease 1800
+ size 32 32
+ tex 33 33
+ velocitymultiplier 44
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 stretched
+ type smoke
+ airfriction 30
+ alpha 400 656 2000
+ color 0x629dff 0x0018ff
+ count 16
+ notunderwater
+ originjitter 50 50 50
+ rotate -180 180 -9 9
+ sizeincrease 555
+ size 20 24
+ tex 48 55
+ velocityjitter 320 320 320
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
+ type spark
+ airfriction -9
+ alpha 1500 3000 13000
+ color 0x629dff 0x0018ff
+ count 8
+ sizeincrease 40
+ size 60 90
+ stretchfactor 80
+ tex 48 55
+ velocityjitter 30 30 30
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
+ type smoke
+ airfriction 0.040000
+ alpha 128 328 390
+ blend alpha
+ color 0x222222 0x000000
+ count 32
+ gravity 0.400000
+ originjitter 50 50 10
+ rotate -180 180 2 -2
+ sizeincrease 50
+ size 60 30
+ tex 0 7
+ velocityjitter 200 200 200
+ velocityoffset 0 0 180
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
+ type bubble
+ alpha 128 256 64
+ bounce 1.500000
+ color 0x404040 0x808080
+ count 32
+ gravity -0.125000
+ liquidfriction 0.250000
+ originjitter 16 16 16
+ size 3 6
+ tex 62 62
+ underwater
+ velocityjitter 196 196 196
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
+ type spark
+ airfriction 1
+ alpha 644 956 484
+ bounce 1.600000
+ color 0x006cff 0x0600ff
+ count 8
+ gravity 1
+ liquidfriction 0.800000
+ notunderwater
+ originjitter 16 16 16
+ size 1 2
+ tex 40 40
+ velocityjitter 424 424 624
+ velocityoffset 0 0 80
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
-// debris
+ type spark
+ airfriction 0.700000
+ alpha 644 956 684
+ color 0x006cff 0x0600ff
+ count 16
+ gravity 0.500000
+ liquidfriction 0.800000
+ originjitter 16 16 16
+ size 1 2
+ tex 40 40
+ velocityjitter 424 424 624
+ velocityoffset 0 0 80
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
-
+ type smoke
+ alpha 644 956 2500
+ color 0x006cff 0x0600ff
+ count 8
+ notunderwater
+ originjitter 64 64 64
+ rotate -180 180 -100 100
+ size 20 40
+ tex 71 73
+ velocityjitter 324 324 324
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
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 100 20 20
+ lightradiusfade 1500
+ lightradius 300
+ originjitter 26 26 26
+ size 88 88
+ tex 8 16
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
+ type smoke
+ alpha 80 80 650
+ color 0xff0000 0xffa2a2
+ countabsolute 1
+ sizeincrease 1800
+ size 32 32
+ tex 33 33
+ velocitymultiplier 44
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 stretched
+ type smoke
+ airfriction 30
+ alpha 400 656 2000
+ color 0xff0000 0xff4200
+ count 16
+ notunderwater
+ originjitter 50 50 50
+ rotate -180 180 -9 9
+ sizeincrease 555
+ size 20 24
+ tex 48 55
+ velocityjitter 320 320 320
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
+ type spark
+ airfriction -9
+ alpha 1500 3000 13000
+ color 0xff0000 0xff4200
+ count 8
+ sizeincrease 40
+ size 60 90
+ stretchfactor 80
+ tex 48 55
+ velocityjitter 30 30 30
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
+ type smoke
+ airfriction 0.040000
+ alpha 128 328 390
+ blend alpha
+ color 0x222222 0x000000
+ count 32
+ gravity 0.400000
+ originjitter 50 50 10
+ rotate -180 180 2 -2
+ sizeincrease 50
+ size 60 30
+ tex 0 7
+ velocityjitter 200 200 200
+ velocityoffset 0 0 180
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
+ type bubble
+ alpha 128 256 64
+ bounce 1.500000
+ color 0x404040 0x808080
+ count 32
+ gravity -0.125000
+ liquidfriction 0.250000
+ originjitter 16 16 16
+ size 3 6
+ tex 62 62
+ underwater
+ velocityjitter 196 196 196
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
+ type spark
+ airfriction 1
+ alpha 644 956 484
+ bounce 1.600000
+ color 0xff0000 0xffa2a2
+ count 8
+ gravity 1
+ liquidfriction 0.800000
+ notunderwater
+ originjitter 16 16 16
+ size 1 2
+ tex 40 40
+ velocityjitter 424 424 624
+ velocityoffset 0 0 80
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
-// debris
+ type spark
+ airfriction 0.700000
+ alpha 644 956 684
+ color 0xff0000 0xffa2a2
+ count 16
+ gravity 0.500000
+ liquidfriction 0.800000
+ originjitter 16 16 16
+ size 1 2
+ tex 40 40
+ velocityjitter 424 424 624
+ velocityoffset 0 0 80
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
-
+ type smoke
+ alpha 644 956 2500
+ color 0xff0000 0xffa2a2
+ count 8
+ notunderwater
+ originjitter 64 64 64
+ rotate -180 180 -100 100
+ size 20 40
+ tex 71 73
+ velocityjitter 324 324 324
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
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 100 20 20
+ lightradiusfade 1500
+ lightradius 300
+ originjitter 26 26 26
+ size 88 88
+ tex 8 16
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
+ type smoke
+ alpha 80 80 650
+ color 0xff0000 0xffa2a2
+ countabsolute 1
+ sizeincrease 1800
+ size 32 32
+ tex 33 33
+ velocitymultiplier 44
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 stretched
+ type smoke
+ airfriction 30
+ alpha 400 656 2000
+ color 0xFFFF0F 0xFFFF0F
+ count 16
+ notunderwater
+ originjitter 50 50 50
+ rotate -180 180 -9 9
+ sizeincrease 555
+ size 20 24
+ tex 48 55
+ velocityjitter 320 320 320
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
+ type spark
+ airfriction -9
+ alpha 1500 3000 13000
+ color 0xFFFF0F 0xFFFF0F
+ count 8
+ sizeincrease 40
+ size 60 90
+ stretchfactor 80
+ tex 48 55
+ velocityjitter 30 30 30
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
+ type smoke
+ airfriction 0.040000
+ alpha 128 328 390
+ blend alpha
+ color 0x222222 0x000000
+ count 32
+ gravity 0.400000
+ originjitter 50 50 10
+ rotate -180 180 2 -2
+ sizeincrease 50
+ size 60 30
+ tex 0 7
+ velocityjitter 200 200 200
+ velocityoffset 0 0 180
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
+ type bubble
+ alpha 128 256 64
+ bounce 1.500000
+ color 0x404040 0x808080
+ count 32
+ gravity -0.125000
+ liquidfriction 0.250000
+ originjitter 16 16 16
+ size 3 6
+ tex 62 62
+ underwater
+ velocityjitter 196 196 196
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
+ type spark
+ airfriction 1
+ alpha 644 956 484
+ bounce 1.600000
+ color 0xff0000 0xffa2a2
+ count 8
+ gravity 1
+ liquidfriction 0.800000
+ notunderwater
+ originjitter 16 16 16
+ size 1 2
+ tex 40 40
+ velocityjitter 424 424 624
+ velocityoffset 0 0 80
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
-// debris
+ type spark
+ airfriction 0.700000
+ alpha 644 956 684
+ color 0xff0000 0xffa2a2
+ count 16
+ gravity 0.500000
+ liquidfriction 0.800000
+ originjitter 16 16 16
+ size 1 2
+ tex 40 40
+ velocityjitter 424 424 624
+ velocityoffset 0 0 80
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
-
+ type smoke
+ alpha 644 956 2500
+ color 0xff0000 0xffa2a2
+ count 8
+ notunderwater
+ originjitter 64 64 64
+ rotate -180 180 -100 100
+ size 20 40
+ tex 71 73
+ velocityjitter 324 324 324
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
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 100 20 20
+ lightradiusfade 1500
+ lightradius 300
+ originjitter 26 26 26
+ size 88 88
+ tex 8 16
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
+ type smoke
+ alpha 80 80 650
+ color 0xff0000 0xffa2a2
+ countabsolute 1
+ sizeincrease 1800
+ size 32 32
+ tex 33 33
+ velocitymultiplier 44
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 stretched
+ type smoke
+ airfriction 30
+ alpha 400 656 2000
+ color 0xFF0FFF 0xFF0FFF
+ count 16
+ notunderwater
+ originjitter 50 50 50
+ rotate -180 180 -9 9
+ sizeincrease 555
+ size 20 24
+ tex 48 55
+ velocityjitter 320 320 320
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
+ type spark
+ airfriction -9
+ alpha 1500 3000 13000
+ color 0xFF0FFF 0xFF0FFF
+ count 8
+ sizeincrease 40
+ size 60 90
+ stretchfactor 80
+ tex 48 55
+ velocityjitter 30 30 30
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
+ type smoke
+ airfriction 0.040000
+ alpha 128 328 390
+ blend alpha
+ color 0x222222 0x000000
+ count 32
+ gravity 0.400000
+ originjitter 50 50 10
+ rotate -180 180 2 -2
+ sizeincrease 50
+ size 60 30
+ tex 0 7
+ velocityjitter 200 200 200
+ velocityoffset 0 0 180
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
+ type bubble
+ alpha 128 256 64
+ bounce 1.500000
+ color 0x404040 0x808080
+ count 32
+ gravity -0.125000
+ liquidfriction 0.250000
+ originjitter 16 16 16
+ size 3 6
+ tex 62 62
+ underwater
+ velocityjitter 196 196 196
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
+ type spark
+ airfriction 1
+ alpha 644 956 484
+ bounce 1.600000
+ color 0xff0000 0xffa2a2
+ count 8
+ gravity 1
+ liquidfriction 0.800000
+ notunderwater
+ originjitter 16 16 16
+ size 1 2
+ tex 40 40
+ velocityjitter 424 424 624
+ velocityoffset 0 0 80
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
-// debris
+ type spark
+ airfriction 0.700000
+ alpha 644 956 684
+ color 0xff0000 0xffa2a2
+ count 16
+ gravity 0.500000
+ liquidfriction 0.800000
+ originjitter 16 16 16
+ size 1 2
+ tex 40 40
+ velocityjitter 424 424 624
+ velocityoffset 0 0 80
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
-
+ type smoke
+ alpha 644 956 2500
+ color 0xff0000 0xffa2a2
+ count 8
+ notunderwater
+ originjitter 64 64 64
+ rotate -180 180 -100 100
+ size 20 40
+ tex 71 73
+ velocityjitter 324 324 324
effect nade_neutral_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
+ type decal
+ alpha 256 256 0
+ countabsolute 1
+ lightcolor 100 20 20
+ lightradiusfade 1500
+ lightradius 300
+ originjitter 26 26 26
+ size 88 88
+ tex 8 16
effect nade_neutral_explode
-type smoke
-countabsolute 1
-tex 33 33
-size 32 32
-sizeincrease 2200
-color 0xff0000 0xffa2a2
-alpha 80 80 650
-velocitymultiplier 44
-// fire
+ type smoke
+ alpha 80 80 650
+ color 0xff0000 0xffa2a2
+ countabsolute 1
+ sizeincrease 1800
+ size 32 32
+ tex 33 33
+ velocitymultiplier 44
effect nade_neutral_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 stretched
+ type smoke
+ airfriction 30
+ alpha 400 656 2000
+ color 0xFFFFFF 0xFFFFFF
+ count 16
+ notunderwater
+ originjitter 50 50 50
+ rotate -180 180 -9 9
+ sizeincrease 555
+ size 20 24
+ tex 48 55
+ velocityjitter 320 320 320
effect nade_neutral_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
+ type spark
+ airfriction -9
+ alpha 1500 3000 13000
+ color 0xFFFFFF 0xFFFFFF
+ count 8
+ sizeincrease 40
+ size 60 90
+ stretchfactor 80
+ tex 48 55
+ velocityjitter 30 30 30
effect nade_neutral_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
+ type smoke
+ airfriction 0.040000
+ alpha 128 328 390
+ blend alpha
+ color 0x222222 0x000000
+ count 32
+ gravity 0.400000
+ originjitter 50 50 10
+ rotate -180 180 2 -2
+ sizeincrease 50
+ size 60 30
+ tex 0 7
+ velocityjitter 200 200 200
+ velocityoffset 0 0 180
effect nade_neutral_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
+ type bubble
+ alpha 128 256 64
+ bounce 1.500000
+ color 0x404040 0x808080
+ count 32
+ gravity -0.125000
+ liquidfriction 0.250000
+ originjitter 16 16 16
+ size 3 6
+ tex 62 62
+ underwater
+ velocityjitter 196 196 196
effect nade_neutral_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
+ type spark
+ airfriction 1
+ alpha 644 956 484
+ bounce 1.600000
+ color 0xff0000 0xffa2a2
+ count 8
+ gravity 1
+ liquidfriction 0.800000
+ notunderwater
+ originjitter 16 16 16
+ size 1 2
+ tex 40 40
+ velocityjitter 424 424 624
+ velocityoffset 0 0 80
effect nade_neutral_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
-// debris
+ type spark
+ airfriction 0.700000
+ alpha 644 956 684
+ color 0xff0000 0xffa2a2
+ count 16
+ gravity 0.500000
+ liquidfriction 0.800000
+ originjitter 16 16 16
+ size 1 2
+ tex 40 40
+ velocityjitter 424 424 624
+ velocityoffset 0 0 80
effect nade_neutral_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
-
-// shockwave_attack
-// used nowhere in code
-effect 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
-effect shockwave_attack // electricity
- count 1
+ type smoke
+ alpha 644 956 2500
+ color 0xff0000 0xffa2a2
+ count 8
+ notunderwater
+ originjitter 64 64 64
+ rotate -180 180 -100 100
+ size 20 40
+ tex 71 73
+ velocityjitter 324 324 324
+effect shockwave_attack
type spark
- color 0xb44215 0xff0000
- tex 43 43
- size 5 7
- bounce 0
- alpha 4096 4096 20000
airfriction 1
+ alpha 4096 4096 20000
+ color 0xb44215 0xff0000
+ count 1
originjitter 2 2 2
+ rotate -180 180 4000 -4000
+ sizeincrease 1.500000
+ size 5 7
+ stretchfactor 2.300000
+ tex 43 43
velocityjitter 10 10 10
velocitymultiplier 10
- sizeincrease 1.5
- stretchfactor 2.3
- rotate -180 180 4000 -4000
-effect shockwave_attack // fire
- count 1
+effect shockwave_attack
type spark
- color 0xff4200 0xff0000
- tex 8 15
- size 7 9
- bounce 0
- alpha 4096 4096 20000
airfriction 1
+ alpha 4096 4096 20000
+ color 0xff4200 0xff0000
+ count 1
originjitter 2 2 2
+ sizeincrease 1.500000
+ size 7 9
+ stretchfactor 2
+ tex 8 15
velocityjitter 10 10 10
velocitymultiplier 10
- sizeincrease 1.5
- stretchfactor 2
-
-// ARC
-// used in qcsrc/server/w_arc.qc
-effect arc_lightning // impact decal
- countabsolute 1
+effect arc_lightning
type decal
- tex 16 32 // fps killer, spamming decals like that
- size 16 16
alpha 32 32 0
- originjitter 2 2 2
- lightradius 50
+ countabsolute 1
+ lightcolor 3.1 4.4 10
lightradiusfade 200
- lightcolor 3.125 4.375 10
-
-effect arc_lightning // impact sparks
+ lightradius 50
+ originjitter 2 2 2
+ size 16 16
+ tex 16 32
+effect arc_lightning
type static
+ airfriction 110
+ alpha 256 256 512
+ color 0xDDFDFF 0xFDFDFF
count 100
- tex 71 74
+ originjitter 20 20 20
rotate 0 360 -36000 36000
- stretchfactor 1
- size 0 5
sizeincrease -5
- color 0xDDFDFF 0xFDFDFF
- alpha 256 256 512
- originjitter 20 20 20
+ size 0 5
+ stretchfactor 1
+ tex 71 74
velocityjitter 250 250 250
velocitymultiplier 100
- airfriction 110
-
-effect arc_lightning // impact sparks (underwater)
+effect arc_lightning
type static
- underwater
+ airfriction 5
+ alpha 256 256 512
+ color 0xDDFDFF 0xFDFDFF
count 100
- tex 71 74
+ liquidfriction 5
+ orientation spark
+ originjitter 20 20 20
rotate 0 360 -36000 36000
- stretchfactor 1
- size 0 5
sizeincrease -5
- color 0xDDFDFF 0xFDFDFF
- alpha 256 256 512
- originjitter 20 20 20
+ size 0 5
+ stretchfactor 1
+ tex 71 74
+ underwater
velocityjitter 250 250 250
- // underwater
- orientation spark
velocitymultiplier 20
- airfriction 5
- liquidfriction 5
-
-effect arc_beam // sparks on beam
+effect arc_beam
type spark
- stretchfactor 1
- rotate 0 360 360 1000
- time 0.05 0.05
- color 0xfafad2 0xffffff
- alpha 256 256 16384
airfriction -10
- originoffset 0 0 0
- relativeoriginoffset 10 0 0
+ alpha 256 256 16384
+ color 0xfafad2 0xffffff
originjitter 3 3 3
- velocityoffset 0 0 0
+ relativeoriginoffset 10 0 0
+ rotate 0 360 360 1000
+ stretchfactor 1
+ tex 71 74
+ time 0.050000 0.050000
+ trailspacing 10
velocityjitter 100 100 100
velocitymultiplier 200
- //lightcolor 0 0 0
- trailspacing 10
- tex 71 74
-
-effect arc_beam // sparks on beam (underwater)
+effect arc_beam
type spark
- underwater
- stretchfactor 1
- rotate 0 360 360 1000
- time 0.001 0.001
- color 0xfafad2 0xffffff
alpha 256 256 16384
+ color 0xfafad2 0xffffff
liquidfriction -10
- originoffset 0 0 0
- relativeoriginoffset 10 0 0
originjitter 30 30 30
- velocityoffset 0 0 0
+ relativeoriginoffset 10 0 0
+ rotate 0 360 360 1000
+ stretchfactor 1
+ tex 71 74
+ time 0.001000 0.001000
+ trailspacing 10
+ underwater
velocityjitter 100 100 100
velocitymultiplier 200
- //lightcolor 0 0 0
- trailspacing 10
- tex 71 74
-
-// ARC healing effect
-effect arc_beam_heal // bubble this...
- type static
- trailspacing 1500
- tex 74 74
- color 0x20FF20 0x40FF40
- size 0.1 0.1
- sizeincrease 20
- alpha 2048 2048 256
- //time 0.8 0.8
- airfriction -20
+effect arc_beam_heal
type smoke
+ airfriction -20
+ alpha 2048 2048 256
+ color 0x20FF20 0x40FF40
relativeoriginoffset 5 0 0
relativevelocityoffset 100 0 0
+ sizeincrease 20
+ size 0.100000 0.100000
+ tex 74 74
+ trailspacing 1500
velocityjitter 3 3 3
velocitymultiplier 200
-
-effect arc_beam_healimpact // healing "aura"
+effect arc_beam_healimpact
type smoke
+ alpha 40 40 350
+ color 0x00ff00 0x84c52f
countabsolute 1
- tex 33 33
- size 32 32
+ lightcolor 0 4.4 0
+ lightradiusfade 150
+ lightradius 20
sizeincrease -1000
- color 0x00ff00 0x84c52f
- alpha 40 40 350
+ size 32 32
+ tex 33 33
velocitymultiplier 44
- lightradius 20
- lightradiusfade 150
- lightcolor 0 4.375 0
-
-effect arc_beam_healimpact // rising "smoke"
+effect arc_beam_healimpact
type smoke
- count 15
- color 0x00ff00 0x84c52f
- tex 40 40
- size 0.5 1
- alpha 200 456 512
airfriction 3
+ alpha 200 456 512
+ color 0x00ff00 0x84c52f
+ count 15
gravity -2
- velocityjitter 120 120 420
rotate -180 180 -90 90
-
-effect arc_smoke // arc heat smoke (notunderwater)
- notunderwater
- count 2
+ size 0.500000 1
+ tex 40 40
+ velocityjitter 120 120 420
+effect arc_smoke
type smoke
- tex 0 8
+ airfriction 1
+ alpha 32 64 48
color 0x4c453f 0x2a241f
- size 5 10
+ count 2
+ gravity -0.125000
+ notunderwater
+ rotate 0 360 -180 180
sizeincrease 10
- alpha 32 64 48
- gravity -0.125
- originjitter 0 0 0
+ size 5 10
+ tex 0 8
velocityjitter 0 0 16
- airfriction 1
- rotate 0 360 -180 180
-
-effect arc_smoke // arc heat bubbles (underwater)
- underwater
- count 2
+effect arc_smoke
type bubble
- tex 62 62
- color 0x404040 0x808080
- size 0.1 1
alpha 170 256 64
- gravity -0.125
- bounce 1.5
- liquidfriction 0.25
+ bounce 1.500000
+ color 0x404040 0x808080
+ count 2
+ gravity -0.125000
+ liquidfriction 0.250000
originjitter 6 6 6
+ size 0.100000 1
+ tex 62 62
+ underwater
velocityjitter 16 16 16
-
-effect arc_overheat // arc overheat electric bolts
- tex 43 43
- count 24
+effect arc_overheat
type spark
- color 0xffffff 0x9271fb
- size 6 12
- sizeincrease -24
- alpha 128 128 292
- gravity -0.4
airfriction 5
+ alpha 128 128 292
+ color 0xffffff 0x9271fb
+ count 24
+ gravity -0.400000
liquidfriction 10
- velocityjitter 256 256 256
originjitter 10 10 10
-
-effect arc_overheat_fire // arc overheat bouncing sparks
- count 1
+ sizeincrease -24
+ size 6 12
+ tex 43 43
+ velocityjitter 256 256 256
+effect arc_overheat_fire
type spark
- color 0x4444ff 0xeeeeff
- size 0.4 1
alpha 0 256 640
+ bounce 1.500000
+ color 0x4444ff 0xeeeeff
+ count 1
gravity 1
- bounce 1.5
- velocityoffset 0 0 80
- velocityjitter 92 92 92
- originjitter 6 6 6
liquidfriction 5
+ originjitter 6 6 6
+ size 0.400000 1
+ velocityjitter 92 92 92
velocitymultiplier 80
-
-// yellowflag_touch -- effects for touching the yellow flag
-// used nowhere in code
+ velocityoffset 0 0 80
effect yellowflag_touch
-count 35
-type spark
-tex 40 40
-color 0xFFFF0F 0xFFFF0F
-size 1 3
-alpha 0 256 556
-gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 300 300 300
-velocitymultiplier 0.5
-airfriction 3
-
-// pinkflag_touch -- effects for touching the pink flag
-// used nowhere in code
+ type spark
+ airfriction 3
+ alpha 0 256 556
+ bounce 1.500000
+ color 0xFFFF0F 0xFFFF0F
+ count 35
+ gravity 1
+ originjitter 1 1 1
+ size 1 3
+ tex 40 40
+ velocityjitter 300 300 300
+ velocitymultiplier 0.500000
effect pinkflag_touch
-count 35
-type spark
-tex 40 40
-color 0xFF0FFF 0xFF0FFF
-size 1 3
-alpha 0 256 556
-gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 300 300 300
-velocitymultiplier 0.5
-airfriction 3
-
-// neutralflag_touch -- effects for touching the neutral flag
-// used nowhere in code
+ type spark
+ airfriction 3
+ alpha 0 256 556
+ bounce 1.500000
+ color 0xFF0FFF 0xFF0FFF
+ count 35
+ gravity 1
+ originjitter 1 1 1
+ size 1 3
+ tex 40 40
+ velocityjitter 300 300 300
+ velocitymultiplier 0.500000
effect neutralflag_touch
-count 35
-type spark
-tex 40 40
-color 0xFFFFFF 0xFFFFFF
-size 1 3
-alpha 0 256 556
-gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 300 300 300
-velocitymultiplier 0.5
-airfriction 3
-
-// yellow_pass
-// used nowhere in code
+ type spark
+ airfriction 3
+ alpha 0 256 556
+ bounce 1.500000
+ color 0xFFFFFF 0xFFFFFF
+ count 35
+ gravity 1
+ originjitter 1 1 1
+ size 1 3
+ tex 40 40
+ velocityjitter 300 300 300
+ velocitymultiplier 0.500000
effect yellow_pass
-trailspacing 64
-color 0xFFFF0F 0xFFFF0F
-size 2 2
-tex 32 32
-alpha 64 128 64
-airfriction 5
-sizeincrease 2
-type static
+ type static
+ airfriction 5
+ alpha 64 128 64
+ color 0xFFFF0F 0xFFFF0F
+ sizeincrease 2
+ size 2 2
+ tex 32 32
+ trailspacing 64
effect yellow_pass
-trailspacing 12
-color 0xFFFF0F 0xFFFF0F
-size 1 1
-tex 0 8
-alpha 32 64 32
-airfriction 9
-sizeincrease 8
-velocityjitter 64 64 64
-type static
+ type static
+ airfriction 9
+ alpha 32 64 32
+ color 0xFFFF0F 0xFFFF0F
+ sizeincrease 8
+ size 1 1
+ tex 0 8
+ trailspacing 12
+ velocityjitter 64 64 64
effect yellow_pass
-trailspacing 12
-color 0xFFFF0F 0xFFFF0F
-size 4 4
-//tex 48 55
-alpha 256 256 1280
-type static
-
-// pink_pass
-// used nowhere in code
+ type static
+ alpha 256 256 1280
+ color 0xFFFF0F 0xFFFF0F
+ size 4 4
+ trailspacing 12
effect pink_pass
-trailspacing 64
-color 0xFFFFFF 0xFFFFFF
-size 2 2
-tex 32 32
-alpha 64 128 64
-airfriction 5
-sizeincrease 2
-type static
+ type static
+ airfriction 5
+ alpha 64 128 64
+ color 0xFFFFFF 0xFFFFFF
+ sizeincrease 2
+ size 2 2
+ tex 32 32
+ trailspacing 64
effect pink_pass
-trailspacing 12
-color 0xFFFFFF 0xFFFFFF
-size 1 1
-tex 0 8
-alpha 32 64 32
-airfriction 9
-sizeincrease 8
-velocityjitter 64 64 64
-type static
+ type static
+ airfriction 9
+ alpha 32 64 32
+ color 0xFFFFFF 0xFFFFFF
+ sizeincrease 8
+ size 1 1
+ tex 0 8
+ trailspacing 12
+ velocityjitter 64 64 64
effect pink_pass
-trailspacing 12
-color 0xFFFFFF 0xFFFFFF
-size 4 4
-//tex 48 55
-alpha 256 256 1280
-type static
-
-// neutral_pass
-// used nowhere in code
+ type static
+ alpha 256 256 1280
+ color 0xFFFFFF 0xFFFFFF
+ size 4 4
+ trailspacing 12
effect neutral_pass
-trailspacing 64
-color 0xFFFFFF 0xFFFFFF
-size 2 2
-tex 32 32
-alpha 64 128 64
-airfriction 5
-sizeincrease 2
-type static
+ type static
+ airfriction 5
+ alpha 64 128 64
+ color 0xFFFFFF 0xFFFFFF
+ sizeincrease 2
+ size 2 2
+ tex 32 32
+ trailspacing 64
effect neutral_pass
-trailspacing 12
-color 0xFFFFFF 0xFFFFFF
-size 1 1
-tex 0 8
-alpha 32 64 32
-airfriction 9
-sizeincrease 8
-velocityjitter 64 64 64
-type static
+ type static
+ airfriction 9
+ alpha 32 64 32
+ color 0xFFFFFF 0xFFFFFF
+ sizeincrease 8
+ size 1 1
+ tex 0 8
+ trailspacing 12
+ velocityjitter 64 64 64
effect neutral_pass
-trailspacing 12
-color 0xFFFFFF 0xFFFFFF
-size 4 4
-//tex 48 55
-alpha 256 256 1280
-type static
-
-// yellow_cap -- yellow team capture effect
+ type static
+ alpha 256 256 1280
+ color 0xFFFFFF 0xFFFFFF
+ size 4 4
+ trailspacing 12
effect yellow_cap
-count 500
-type spark
-tex 64 64
-color 0xFFFF0F 0xFFFF0F
-size 1 1
-alpha 0 256 100
-stretchfactor 2
-//gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 1000 1000 1500
-velocitymultiplier 0.5
-airfriction 2
-stretchfactor 0.6
+ type spark
+ airfriction 2
+ alpha 0 256 100
+ bounce 1.500000
+ color 0xFFFF0F 0xFFFF0F
+ count 500
+ originjitter 1 1 1
+ size 1 1
+ stretchfactor 0.600000
+ tex 64 64
+ velocityjitter 1000 1000 1500
+ velocitymultiplier 0.500000
effect yellow_cap
-countabsolute 1
-type smoke
-tex 65 65
-size 150 150
-alpha 190 190 180
-sizeincrease -80
-color 0xFFFF0F 0xFFFF0F
-
-// pink_cap -- pink team capture effect
+ type smoke
+ alpha 190 190 180
+ color 0xFFFF0F 0xFFFF0F
+ countabsolute 1
+ sizeincrease -80
+ size 150 150
+ tex 65 65
effect pink_cap
-count 500
-type spark
-tex 64 64
-color 0xFF0FFF 0xFF0FFF
-size 1 1
-alpha 0 256 100
-stretchfactor 2
-//gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 1000 1000 1500
-velocitymultiplier 0.5
-airfriction 2
-stretchfactor 0.6
+ type spark
+ airfriction 2
+ alpha 0 256 100
+ bounce 1.500000
+ color 0xFF0FFF 0xFF0FFF
+ count 500
+ originjitter 1 1 1
+ size 1 1
+ stretchfactor 0.600000
+ tex 64 64
+ velocityjitter 1000 1000 1500
+ velocitymultiplier 0.500000
effect pink_cap
-countabsolute 1
-type smoke
-tex 65 65
-size 150 150
-alpha 190 190 180
-sizeincrease -80
-color 0xFF0FFF 0xFF0FFF
-
-// relic_resistance effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+ type smoke
+ alpha 190 190 180
+ color 0xFF0FFF 0xFF0FFF
+ countabsolute 1
+ sizeincrease -80
+ size 150 150
+ tex 65 65
effect relic_resistance
-count 20
-type static
-color 0x00ff80 0x00ff80
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_regeneration effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+ type static
+ airfriction 0.200000
+ alpha 128 256 256
+ color 0x00ff80 0x00ff80
+ count 20
+ gravity -0.100000
+ liquidfriction 0.800000
+ originjitter 8 8 32
+ size 1.500000 1.500000
+ velocityjitter 64 64 32
effect relic_regeneration
-count 1
-type static
-color 0x00ffff 0x00ffff
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_vempire effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+ type static
+ airfriction 0.200000
+ alpha 128 256 256
+ color 0x00ffff 0x00ffff
+ count 1
+ gravity -0.100000
+ liquidfriction 0.800000
+ originjitter 8 8 32
+ size 1.500000 1.500000
+ velocityjitter 64 64 32
effect relic_vampire
-count 20
-type static
-color 0xff00ff 0xff00ff
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_ammo effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+ type static
+ airfriction 0.200000
+ alpha 128 256 256
+ color 0xff00ff 0xff00ff
+ count 20
+ gravity -0.100000
+ liquidfriction 0.800000
+ originjitter 8 8 32
+ size 1.500000 1.500000
+ velocityjitter 64 64 32
effect relic_ammo
-count 1
-type static
-color 0x80ff00 0x80ff00
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_damage effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+ type static
+ airfriction 0.200000
+ alpha 128 256 256
+ color 0x80ff00 0x80ff00
+ count 1
+ gravity -0.100000
+ liquidfriction 0.800000
+ originjitter 8 8 32
+ size 1.500000 1.500000
+ velocityjitter 64 64 32
effect relic_damage
-count 20
-type static
-color 0xff0000 0xff0000
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_splashdamage effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+ type static
+ airfriction 0.200000
+ alpha 128 256 256
+ color 0xff0000 0xff0000
+ count 20
+ gravity -0.100000
+ liquidfriction 0.800000
+ originjitter 8 8 32
+ size 1.500000 1.500000
+ velocityjitter 64 64 32
effect relic_ssplashdamage
-count 20
-type static
-color 0xff8000 0xff8000
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_firingspeed effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+ type static
+ airfriction 0.200000
+ alpha 128 256 256
+ color 0xff8000 0xff8000
+ count 20
+ gravity -0.100000
+ liquidfriction 0.800000
+ originjitter 8 8 32
+ size 1.500000 1.500000
+ velocityjitter 64 64 32
effect relic_firingspeed
-count 20
-type static
-color 0xffff00 0xffff00
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_disability effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+ type static
+ airfriction 0.200000
+ alpha 128 256 256
+ color 0xffff00 0xffff00
+ count 20
+ gravity -0.100000
+ liquidfriction 0.800000
+ originjitter 8 8 32
+ size 1.500000 1.500000
+ velocityjitter 64 64 32
effect relic_disability
-count 20
-type static
-color 0x0000ff 0x0000ff
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_disability_curse effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+ type static
+ airfriction 0.200000
+ alpha 128 256 256
+ color 0x0000ff 0x0000ff
+ count 20
+ gravity -0.100000
+ liquidfriction 0.800000
+ originjitter 8 8 32
+ size 1.500000 1.500000
+ velocityjitter 64 64 32
effect relic_disability_curse
-count 1
-type static
-color 0x000080 0x000080
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_teamboost effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+ type static
+ airfriction 0.200000
+ alpha 128 256 256
+ color 0x000080 0x000080
+ count 1
+ gravity -0.100000
+ liquidfriction 0.800000
+ originjitter 8 8 32
+ size 1.500000 1.500000
+ velocityjitter 64 64 32
effect relic_teamboost
-count 20
-type static
-color 0xffffff 0xffffff
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_teamboost_boost effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+ type static
+ airfriction 0.200000
+ alpha 128 256 256
+ color 0xffffff 0xffffff
+ count 20
+ gravity -0.100000
+ liquidfriction 0.800000
+ originjitter 8 8 32
+ size 1.500000 1.500000
+ velocityjitter 64 64 32
effect relic_teamboost_boost
-count 1
-type static
-color 0x808080 0x808080
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_speed effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+ type static
+ airfriction 0.200000
+ alpha 128 256 256
+ color 0x808080 0x808080
+ count 1
+ gravity -0.100000
+ liquidfriction 0.800000
+ originjitter 8 8 32
+ size 1.500000 1.500000
+ velocityjitter 64 64 32
effect relic_speed
-count 1
-type static
-color 0x80ffff 0x80ffff
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_jump effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+ type static
+ airfriction 0.200000
+ alpha 128 256 256
+ color 0x80ffff 0x80ffff
+ count 1
+ gravity -0.100000
+ liquidfriction 0.800000
+ originjitter 8 8 32
+ size 1.500000 1.500000
+ velocityjitter 64 64 32
effect relic_jump
-count 20
-type static
-color 0xffff80 0xffff80
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_flight effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+ type static
+ airfriction 0.200000
+ alpha 128 256 256
+ color 0xffff80 0xffff80
+ count 20
+ gravity -0.100000
+ liquidfriction 0.800000
+ originjitter 8 8 32
+ size 1.500000 1.500000
+ velocityjitter 64 64 32
effect relic_flight
-count 1
-type static
-color 0x8080ff 0x8080ff
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_radioactive effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+ type static
+ airfriction 0.200000
+ alpha 128 256 256
+ color 0x8080ff 0x8080ff
+ count 1
+ gravity -0.100000
+ liquidfriction 0.800000
+ originjitter 8 8 32
+ size 1.500000 1.500000
+ velocityjitter 64 64 32
effect relic_radioactive
-count 20
-type static
-color 0x00ff00 0x00ff00
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_resurrection effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+ type static
+ airfriction 0.200000
+ alpha 128 256 256
+ color 0x00ff00 0x00ff00
+ count 20
+ gravity -0.100000
+ liquidfriction 0.800000
+ originjitter 8 8 32
+ size 1.500000 1.500000
+ velocityjitter 64 64 32
effect relic_resurrection
-count 20
-type static
-color 0xff0080 0xff0080
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_vengeance effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+ type static
+ airfriction 0.200000
+ alpha 128 256 256
+ color 0xff0080 0xff0080
+ count 20
+ gravity -0.100000
+ liquidfriction 0.800000
+ originjitter 8 8 32
+ size 1.500000 1.500000
+ velocityjitter 64 64 32
effect relic_vengeance
-count 20
-type static
-color 0xff8080 0xff8080
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// rocketminsta laser trail - red
+ type static
+ airfriction 0.200000
+ alpha 128 256 256
+ color 0xff8080 0xff8080
+ count 20
+ gravity -0.100000
+ liquidfriction 0.800000
+ originjitter 8 8 32
+ size 1.500000 1.500000
+ velocityjitter 64 64 32
effect rocketminsta_laser_red
-trailspacing 2
-type static
-color 0xFF0F0F 0xFF0F0F
-size 3 3
-tex 38 38
-alpha 256 256 968
-//velocityjitter 16 16 16
-lightradius 90
-lighttime 0
-lightcolor 1.5 3 6
-velocitymultiplier -0.1
-// bright sparks
+ type static
+ alpha 256 256 968
+ color 0xFF0F0F 0xFF0F0F
+ lightcolor 1.5 3 6
+ lightradius 90
+ size 3 3
+ tex 38 38
+ trailspacing 2
+ velocitymultiplier -0.100000
effect rocketminsta_laser_red
-trailspacing 12
-count 1.5
-type snow
-tex 42 42
-color 0xFF0F0F 0xFF0F0F
-size 2 4
-sizeincrease -20
-alpha 444 512 1866
-bounce 1
-velocityoffset 0 0 15
-airfriction 12
-originjitter 1 1 1
-velocityjitter 50 50 50
-
-// rocketminsta laser trail - blue
+ type snow
+ airfriction 12
+ alpha 444 512 1866
+ bounce 1
+ color 0xFF0F0F 0xFF0F0F
+ count 1.500000
+ originjitter 1 1 1
+ sizeincrease -20
+ size 2 4
+ tex 42 42
+ trailspacing 12
+ velocityjitter 50 50 50
+ velocityoffset 0 0 15
effect rocketminsta_laser_blue
-trailspacing 2
-type static
-color 0x0F0FFF 0x0F0FFF
-size 3 3
-tex 38 38
-alpha 256 256 968
-//velocityjitter 16 16 16
-lightradius 90
-lighttime 0
-lightcolor 1.5 3 6
-velocitymultiplier -0.1
-// bright sparks
+ type static
+ alpha 256 256 968
+ color 0x0F0FFF 0x0F0FFF
+ lightcolor 1.5 3 6
+ lightradius 90
+ size 3 3
+ tex 38 38
+ trailspacing 2
+ velocitymultiplier -0.100000
effect rocketminsta_laser_blue
-trailspacing 12
-count 1.5
-type snow
-tex 42 42
-color 0x0F0FFF 0x0F0FFF
-size 2 4
-sizeincrease -20
-alpha 444 512 1866
-bounce 1
-velocityoffset 0 0 15
-airfriction 12
-originjitter 1 1 1
-velocityjitter 50 50 50
-
-// rocketminsta laser trail - yellow
+ type snow
+ airfriction 12
+ alpha 444 512 1866
+ bounce 1
+ color 0x0F0FFF 0x0F0FFF
+ count 1.500000
+ originjitter 1 1 1
+ sizeincrease -20
+ size 2 4
+ tex 42 42
+ trailspacing 12
+ velocityjitter 50 50 50
+ velocityoffset 0 0 15
effect rocketminsta_laser_yellow
-trailspacing 2
-type static
-color 0xFFFF0F 0xFFFF0F
-size 3 3
-tex 38 38
-alpha 256 256 968
-//velocityjitter 16 16 16
-lightradius 90
-lighttime 0
-lightcolor 1.5 3 6
-velocitymultiplier -0.1
-// bright sparks
+ type static
+ alpha 256 256 968
+ color 0xFFFF0F 0xFFFF0F
+ lightcolor 1.5 3 6
+ lightradius 90
+ size 3 3
+ tex 38 38
+ trailspacing 2
+ velocitymultiplier -0.100000
effect rocketminsta_laser_yellow
-trailspacing 12
-count 1.5
-type snow
-tex 42 42
-color 0xFFFF0F 0xFFFF0F
-size 2 4
-sizeincrease -20
-alpha 444 512 1866
-bounce 1
-velocityoffset 0 0 15
-airfriction 12
-originjitter 1 1 1
-velocityjitter 50 50 50
-
-// rocketminsta laser trail - pink
+ type snow
+ airfriction 12
+ alpha 444 512 1866
+ bounce 1
+ color 0xFFFF0F 0xFFFF0F
+ count 1.500000
+ originjitter 1 1 1
+ sizeincrease -20
+ size 2 4
+ tex 42 42
+ trailspacing 12
+ velocityjitter 50 50 50
+ velocityoffset 0 0 15
effect rocketminsta_laser_pink
-trailspacing 2
-type static
-color 0xFF0FFF 0xFF0FFF
-size 3 3
-tex 38 38
-alpha 256 256 968
-//velocityjitter 16 16 16
-lightradius 90
-lighttime 0
-lightcolor 1.5 3 6
-velocitymultiplier -0.1
-// bright sparks
+ type static
+ alpha 256 256 968
+ color 0xFF0FFF 0xFF0FFF
+ lightcolor 1.5 3 6
+ lightradius 90
+ size 3 3
+ tex 38 38
+ trailspacing 2
+ velocitymultiplier -0.100000
effect rocketminsta_laser_pink
-trailspacing 12
-count 1.5
-type snow
-tex 42 42
-color 0xFF0FFF 0xFF0FFF
-size 2 4
-sizeincrease -20
-alpha 444 512 1866
-bounce 1
-velocityoffset 0 0 15
-airfriction 12
-originjitter 1 1 1
-velocityjitter 50 50 50
-
-// rocketminsta laser trail - neutral
+ type snow
+ airfriction 12
+ alpha 444 512 1866
+ bounce 1
+ color 0xFF0FFF 0xFF0FFF
+ count 1.500000
+ originjitter 1 1 1
+ sizeincrease -20
+ size 2 4
+ tex 42 42
+ trailspacing 12
+ velocityjitter 50 50 50
+ velocityoffset 0 0 15
effect rocketminsta_laser_neutral
-trailspacing 2
-type static
-color 0xFFFFFF 0xFFFFFF
-size 3 3
-tex 38 38
-alpha 256 256 968
-//velocityjitter 16 16 16
-lightradius 90
-lighttime 0
-lightcolor 1.5 3 6
-velocitymultiplier -0.1
-// bright sparks
+ type static
+ alpha 256 256 968
+ color 0xFFFFFF 0xFFFFFF
+ lightcolor 1.5 3 6
+ lightradius 90
+ size 3 3
+ tex 38 38
+ trailspacing 2
+ velocitymultiplier -0.100000
effect rocketminsta_laser_neutral
-trailspacing 12
-count 1.5
-type snow
-tex 42 42
-color 0xFFFFFF 0xFFFFFF
-size 2 4
-sizeincrease -20
-alpha 444 512 1866
-bounce 1
-velocityoffset 0 0 15
-airfriction 12
-originjitter 1 1 1
-velocityjitter 50 50 50
+ type snow
+ airfriction 12
+ alpha 444 512 1866
+ bounce 1
+ color 0xFFFFFF 0xFFFFFF
+ count 1.500000
+ originjitter 1 1 1
+ sizeincrease -20
+ size 2 4
+ tex 42 42
+ trailspacing 12
+ velocityjitter 50 50 50
+ velocityoffset 0 0 15
set sv_minigames_pong_ball_number 1 "Number of balls to be played at once"
set sv_minigames_pong_ai_thinkspeed 0.1 "Seconds between AI actions"
-set sv_minigames_pong_ai_tolerance 0.33 "Distance of the ball relative to the paddle size"
\ No newline at end of file
+set sv_minigames_pong_ai_tolerance 0.33 "Distance of the ball relative to the paddle size"
+
+
+// Snake? Snake! SNAAAAKE!!
+set sv_minigames_snake_wrap 0 "Wrap around the edges of the screen instead of dying on touch"
+set sv_minigames_snake_delay_initial 0.7 "Initial delay between snake movement"
+set sv_minigames_snake_delay_multiplier 50 "Multiplier of incremental of movement speed (player_score / cvar)"
+set sv_minigames_snake_delay_min 0.1 "Minimum delay between snake movement (at fastest rate)"
+++ /dev/null
-REGISTER_MUTATOR(mutator_mod, cvar("g_mod"));
-
-MUTATOR_HOOKFUNCTION(mutator_mod, BuildMutatorsString) {
- ret_string = strcat(ret_string, ":mod");
-}
-
-MUTATOR_HOOKFUNCTION(mutator_mod, BuildMutatorsPrettyString) {
- ret_string = strcat(ret_string, ", Mod");
-}
+++ /dev/null
-#if BUILD_MOD
-#include "main.qc"
-#endif
+++ /dev/null
-REGISTER_MUTATOR(mutator_mod, cvar("g_mod"));
-
-MUTATOR_HOOKFUNCTION(mutator_mod, BuildMutatorsString) {
- ret_string = strcat(ret_string, ":mod");
-}
-
-MUTATOR_HOOKFUNCTION(mutator_mod, BuildMutatorsPrettyString) {
- ret_string = strcat(ret_string, ", Mod");
-}
+++ /dev/null
-#if BUILD_MOD
-#include "main.qc"
-#endif
+++ /dev/null
-REGISTER_MUTATOR(mutator_mod, cvar("g_mod"));
-
-MUTATOR_HOOKFUNCTION(mutator_mod, BuildMutatorsString) {
- ret_string = strcat(ret_string, ":mod");
-}
-
-MUTATOR_HOOKFUNCTION(mutator_mod, BuildMutatorsPrettyString) {
- ret_string = strcat(ret_string, ", Mod");
-}
+++ /dev/null
-#if BUILD_MOD
-#include "main.qc"
-#endif
set g_monsters_typefrag 1
set g_monsters_target_range 2000
set g_monsters_target_infront 0
+set g_monsters_target_infront_range 0.3
set g_monsters_attack_range 120
set g_monsters_respawn 1
set g_monsters_respawn_delay 20
// ===========
// multijump
// ===========
-seta cl_multijump 1 "allow multijump mutator"
+seta cl_multijump 0 "allow multijump mutator"
set g_multijump 0 "Number of multiple jumps to allow (jumping again in the air), -1 allows for infinite jumps"
set g_multijump_add 0 "0 = make the current z velocity equal to jumpvelocity, 1 = add jumpvelocity to the current z velocity"
set g_multijump_speed -999999 "Minimum vertical speed a player must have in order to jump again"
set g_physics_xonotic_stopspeed 100
set g_physics_xonotic_airaccelerate 2
set g_physics_xonotic_airstopaccelerate 3
+set g_physics_xonotic_track_canjump 0
// ========
// Nexuiz
set g_physics_nexuiz_stopspeed 100
set g_physics_nexuiz_airaccelerate 5.5
set g_physics_nexuiz_airstopaccelerate 0
+set g_physics_nexuiz_track_canjump 0
// =======
// Quake
set g_physics_quake_stopspeed 100
set g_physics_quake_airaccelerate 106.66666666666666666666
set g_physics_quake_airstopaccelerate 0
+set g_physics_quake_track_canjump 1
// ========
// Warsow
set g_physics_warsow_stopspeed 100
set g_physics_warsow_airaccelerate 1
set g_physics_warsow_airstopaccelerate 2.5
+set g_physics_warsow_track_canjump 0
// ========
// DeFrag
set g_physics_defrag_stopspeed 100
set g_physics_defrag_airaccelerate 1
set g_physics_defrag_airstopaccelerate 2.5
+set g_physics_defrag_track_canjump 0
// =========
// Quake 3
set g_physics_quake3_stopspeed 100
set g_physics_quake3_airaccelerate 1
set g_physics_quake3_airstopaccelerate 0
+set g_physics_quake3_track_canjump 1
// ========
// Vecxis
set g_physics_vecxis_stopspeed 100
set g_physics_vecxis_airaccelerate 5.5
set g_physics_vecxis_airstopaccelerate 0
+set g_physics_vecxis_track_canjump 0
// =========
// Quake 2
set g_physics_quake2_stopspeed 100
set g_physics_quake2_airaccelerate 1
set g_physics_quake2_airstopaccelerate 0
+set g_physics_quake2_track_canjump 1
// =======
// Bones
set g_physics_bones_stopspeed 100
set g_physics_bones_airaccelerate 1
set g_physics_bones_airstopaccelerate 2.5
+set g_physics_bones_track_canjump 0
sv_jumpspeedcap_max ""
sv_jumpspeedcap_max_disable_on_ramps 0
g_teleport_maxspeed 400
+sv_track_canjump 0
sv_jumpspeedcap_max 0.35
sv_jumpspeedcap_max_disable_on_ramps 1
g_teleport_maxspeed 0
+sv_track_canjump 0
sv_jumpspeedcap_max ""
sv_jumpspeedcap_max_disable_on_ramps 0
g_teleport_maxspeed 0
+sv_track_canjump 0
sv_jumpspeedcap_max ""
sv_jumpspeedcap_max_disable_on_ramps 1
g_teleport_maxspeed 0
+sv_track_canjump 0
sv_jumpspeedcap_max ""
sv_jumpspeedcap_max_disable_on_ramps 1
g_teleport_maxspeed 0
+sv_track_canjump 0
sv_jumpspeedcap_max 0.38
sv_jumpspeedcap_max_disable_on_ramps 0
g_teleport_maxspeed 0
+sv_track_canjump 0
sv_jumpspeedcap_max ""
sv_jumpspeedcap_max_disable_on_ramps 0
g_teleport_maxspeed 0
+sv_track_canjump 0
sv_jumpspeedcap_max ""
sv_jumpspeedcap_max_disable_on_ramps 0
g_teleport_maxspeed 0
+sv_track_canjump 0
sv_jumpspeedcap_max ""
sv_jumpspeedcap_max_disable_on_ramps 0
g_teleport_maxspeed 0
+sv_track_canjump 0
sv_jumpspeedcap_max ""
sv_jumpspeedcap_max_disable_on_ramps 0
g_teleport_maxspeed 0
+sv_track_canjump 0
sv_jumpspeedcap_max ""
sv_jumpspeedcap_max_disable_on_ramps 0
g_teleport_maxspeed 0
+sv_track_canjump 0
sv_jumpspeedcap_max ""
sv_jumpspeedcap_max_disable_on_ramps 0
g_teleport_maxspeed 0
+sv_track_canjump 0
sv_jumpspeedcap_max ""
sv_jumpspeedcap_max_disable_on_ramps 0
g_teleport_maxspeed 0
+sv_track_canjump 0
sv_jumpspeedcap_max ""
sv_jumpspeedcap_max_disable_on_ramps 0
g_teleport_maxspeed 0
+sv_track_canjump 0
sv_jumpspeedcap_max ""
sv_jumpspeedcap_max_disable_on_ramps 0
g_teleport_maxspeed 0
+sv_track_canjump 0
sv_jumpspeedcap_max ""
sv_jumpspeedcap_max_disable_on_ramps 1
g_teleport_maxspeed 0
+sv_track_canjump 0
sv_jumpspeedcap_max ""
sv_jumpspeedcap_max_disable_on_ramps 0
g_teleport_maxspeed 0
+sv_track_canjump 0
sv_jumpspeedcap_max ""
sv_jumpspeedcap_max_disable_on_ramps 0
g_teleport_maxspeed 0
+sv_track_canjump 0
sv_jumpspeedcap_max ""
sv_jumpspeedcap_max_disable_on_ramps 0
g_teleport_maxspeed 0
+sv_track_canjump 0
sv_jumpspeedcap_max ""
sv_jumpspeedcap_max_disable_on_ramps 0
g_teleport_maxspeed 320
+sv_track_canjump 0
sv_jumpspeedcap_max ""
sv_jumpspeedcap_max_disable_on_ramps 0
g_teleport_maxspeed 0
+sv_track_canjump 0
sv_jumpspeedcap_max ""
sv_jumpspeedcap_max_disable_on_ramps 0
g_teleport_maxspeed 0
+sv_track_canjump 0
sv_jumpspeedcap_max ""
sv_jumpspeedcap_max_disable_on_ramps 0
g_teleport_maxspeed 0
+sv_track_canjump 0
sv_jumpspeedcap_max ""
sv_jumpspeedcap_max_disable_on_ramps 0
g_teleport_maxspeed 0
+sv_track_canjump 0
sv_jumpspeedcap_max ""
sv_jumpspeedcap_max_disable_on_ramps 0
g_teleport_maxspeed 0
+sv_track_canjump 0
sv_jumpspeedcap_max ""
sv_jumpspeedcap_max_disable_on_ramps 0
g_teleport_maxspeed 0
+sv_track_canjump 0
--- /dev/null
+# Doxyfile 1.8.10
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = "Xonotic"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY =
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = YES
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = YES
+
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING = qc=C qh=C inc=C
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = YES
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = YES
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = YES
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = YES
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO, these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = YES
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES, upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong or incomplete
+# parameter documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
+# Note: If this tag is empty the current directory is searched.
+
+INPUT =
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
+# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd,
+# *.vhdl, *.ucf, *.qsf, *.as and *.js.
+
+FILE_PATTERNS = *.qc *.qh *.inc
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS = _
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = YES
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = YES
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the master .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = YES
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 250
+
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
+# string, for the replacement values of the other commands the user is referred
+# to HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES, to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
+# with syntax highlighting in the RTF output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_SOURCE_CODE = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sf.net) file that captures the
+# structure of the code including all documentation. Note that this feature is
+# still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = NO
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT = YES
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 2
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = YES
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = YES
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = svg
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = YES
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+
+PLANTUML_JAR_PATH =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 500
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT = YES
+
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = YES
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP = YES
PERL ?= perl
QCCFLAGS_WATERMARK ?= -DWATERMARK='"$(shell git describe)"'
QCC ?= gmqcc
-
+
QCCVERSIONFILE := qccversion.$(shell (cd server && $(QCC) --version) > qccversion.txt && git hash-object qccversion.txt)
# We eventually need to get rid of these.
QCCFLAGS_WTFS ?= \
-Wno-field-redeclared
-QCCFLAGS ?= \
- -std=gmqcc \
- -O3 -flno \
- -Werror -fno-bail-on-werror -Wall \
- -fftepp -fftepp-predefs -Wcpp -futf8 -frelaxed-switch -freturn-assignments \
- $(QCCFLAGS_WTFS) \
- $(QCCFLAGS_FEATURES) \
- $(QCCFLAGS_EXTRA) $(QCCFLAGS_WATERMARK)
-
QCCFLAGS_FEATURES ?= \
-DVEHICLES_ENABLED=1 \
-DVEHICLES_USE_ODE=0 \
-DBUILD_MOD=$(BUILD_MOD)
+QCCFLAGS ?= \
+ -std=gmqcc \
+ -O3 \
+ -Werror -Wall -Wcpp \
+ $(QCCFLAGS_WTFS) \
+ -fftepp -flno -futf8 -fno-bail-on-werror -fftepp-predefs \
+ -frelaxed-switch -freturn-assignments \
+ $(QCCFLAGS_WATERMARK) \
+ $(QCCFLAGS_FEATURES) \
+ $(QCCFLAGS_EXTRA)
+
# xonotic build system overrides this by command line argument to turn off the update-cvarcount step
XON_BUILDSYSTEM =
-all: qc
.PHONY: all
+all: qc
.PHONY: qc
qc: ../menu.dat ../progs.dat ../csprogs.dat
.PHONY: clean
clean:
- rm -f ../progs.dat ../menu.dat ../csprogs.dat server/precache-for-csqc.inc
+ rm -f ../progs.dat ../menu.dat ../csprogs.dat
$(QCCVERSIONFILE):
$(RM) qccversion.*
echo This file intentionally left blank. > $@
-FILES_CSPROGS = $(shell find client common warpzonelib csqcmodellib -type f -not -name fteqcc.log -not -name qc.asm)
+FILES_CSPROGS = $(shell find client lib common warpzonelib csqcmodellib -type f -not -name fteqcc.log -not -name qc.asm)
../csprogs.dat: $(FILES_CSPROGS) $(QCCVERSIONFILE)
@echo make[1]: Entering directory \`$(PWD)/client\'
cd client && $(QCC) $(QCCFLAGS) -DCSQC
-server/precache-for-csqc.inc: $(FILES_CSPROGS)
- sh collect-precache.sh
-
-FILES_PROGS = $(shell find server common warpzonelib csqcmodellib -type f -not -name fteqcc.log -not -name qc.asm)
-../progs.dat: $(FILES_PROGS) $(QCCVERSIONFILE) server/precache-for-csqc.inc
+FILES_PROGS = $(shell find server lib common warpzonelib csqcmodellib -type f -not -name fteqcc.log -not -name qc.asm)
+../progs.dat: $(FILES_PROGS) $(QCCVERSIONFILE)
@echo make[1]: Entering directory \`$(PWD)/server\'
cd server && $(QCC) $(QCCFLAGS) -DSVQC
-FILES_MENU = $(shell find menu common warpzonelib -type f -not -name fteqcc.log -not -name qc.asm)
+FILES_MENU = $(shell find menu lib common warpzonelib -type f -not -name fteqcc.log -not -name qc.asm)
../menu.dat: $(FILES_MENU) $(QCCVERSIONFILE)
@echo make[1]: Entering directory \`$(PWD)/menu\'
cd menu && $(QCC) $(QCCFLAGS) -DMENUQC
#include "../dpdefs/csprogsdefs.qh"
+#include "../common/models/all.qh"
+#include "../common/sounds/all.qh"
+
#endif
bool announcer_5min;
void Announcer_Countdown()
{
+ SELFPARAM();
float starttime = getstatf(STAT_GAMESTARTTIME);
float roundstarttime = getstatf(STAT_ROUNDSTARTTIME);
if(roundstarttime == -1)
{
Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_ROUNDSTOP);
- remove(self);
+ remove(this);
return;
}
if(roundstarttime >= starttime)
{
Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_BEGIN);
Local_Notification(MSG_MULTI, MULTI_COUNTDOWN_BEGIN);
- remove(self);
+ remove(this);
return;
}
else // countdown is still going
Local_Notification(MSG_ANNCE, Announcer_PickNumber(CNT_GAMESTART, countdown_rounded));
}
- self.nextthink = (starttime - (countdown - 1));
+ this.nextthink = (starttime - (countdown - 1));
}
}
#include "../../common/command/generic.qh"
-void DrawDebugModel()
+void DrawDebugModel(entity this)
{
if(time - floor(time) > 0.5)
{
debugmodel_entity = spawn();
precache_model(modelname);
- setmodel(debugmodel_entity, modelname);
+ _setmodel(debugmodel_entity, modelname);
setorigin(debugmodel_entity, view_origin);
debugmodel_entity.angles = view_angles;
debugmodel_entity.draw = DrawDebugModel;
#include "../common/movetypes/movetypes.qh"
.float alpha;
-bool cpicon_precached;
.int count;
.float pain_finished;
.entity icon_realmodel;
-void cpicon_precache()
+void cpicon_draw(entity this)
{
- if(cpicon_precached)
- return; // already precached
+ if(time < this.move_time) { return; }
- precache_model("models/onslaught/controlpoint_icon_dmg3.md3");
- precache_model("models/onslaught/controlpoint_icon_dmg2.md3");
- precache_model("models/onslaught/controlpoint_icon_dmg1.md3");
- precache_model("models/onslaught/controlpoint_icon.md3");
-
- cpicon_precached = true;
-}
-
-void cpicon_draw()
-{
- if(time < self.move_time) { return; }
-
- if(self.cp_bob_dmg_z > 0)
- self.cp_bob_dmg_z = self.cp_bob_dmg_z - 3 * frametime;
+ if(this.cp_bob_dmg_z > 0)
+ this.cp_bob_dmg_z = this.cp_bob_dmg_z - 3 * frametime;
else
- self.cp_bob_dmg_z = 0;
- self.cp_bob_origin_z = 4 * PI * (1 - cos(self.cp_bob_spd));
- self.cp_bob_spd = self.cp_bob_spd + 1.875 * frametime;
- self.colormod = '1 1 1' * (2 - bound(0, (self.pain_finished - time) / 10, 1));
+ this.cp_bob_dmg_z = 0;
+ this.cp_bob_origin_z = 4 * PI * (1 - cos(this.cp_bob_spd));
+ this.cp_bob_spd = this.cp_bob_spd + 1.875 * frametime;
+ this.colormod = '1 1 1' * (2 - bound(0, (this.pain_finished - time) / 10, 1));
- if(!self.iscaptured) self.alpha = self.health / self.max_health;
+ if(!this.iscaptured) this.alpha = this.health / this.max_health;
- if(self.iscaptured)
+ if(this.iscaptured)
{
- if (self.punchangle_x > 0)
+ if (this.punchangle_x > 0)
{
- self.punchangle_x = self.punchangle_x - 60 * frametime;
- if (self.punchangle_x < 0)
- self.punchangle_x = 0;
+ this.punchangle_x = this.punchangle_x - 60 * frametime;
+ if (this.punchangle_x < 0)
+ this.punchangle_x = 0;
}
- else if (self.punchangle_x < 0)
+ else if (this.punchangle_x < 0)
{
- self.punchangle_x = self.punchangle_x + 60 * frametime;
- if (self.punchangle_x > 0)
- self.punchangle_x = 0;
+ this.punchangle_x = this.punchangle_x + 60 * frametime;
+ if (this.punchangle_x > 0)
+ this.punchangle_x = 0;
}
- if (self.punchangle_y > 0)
+ if (this.punchangle_y > 0)
{
- self.punchangle_y = self.punchangle_y - 60 * frametime;
- if (self.punchangle_y < 0)
- self.punchangle_y = 0;
+ this.punchangle_y = this.punchangle_y - 60 * frametime;
+ if (this.punchangle_y < 0)
+ this.punchangle_y = 0;
}
- else if (self.punchangle_y < 0)
+ else if (this.punchangle_y < 0)
{
- self.punchangle_y = self.punchangle_y + 60 * frametime;
- if (self.punchangle_y > 0)
- self.punchangle_y = 0;
+ this.punchangle_y = this.punchangle_y + 60 * frametime;
+ if (this.punchangle_y > 0)
+ this.punchangle_y = 0;
}
- if (self.punchangle_z > 0)
+ if (this.punchangle_z > 0)
{
- self.punchangle_z = self.punchangle_z - 60 * frametime;
- if (self.punchangle_z < 0)
- self.punchangle_z = 0;
+ this.punchangle_z = this.punchangle_z - 60 * frametime;
+ if (this.punchangle_z < 0)
+ this.punchangle_z = 0;
}
- else if (self.punchangle_z < 0)
+ else if (this.punchangle_z < 0)
{
- self.punchangle_z = self.punchangle_z + 60 * frametime;
- if (self.punchangle_z > 0)
- self.punchangle_z = 0;
+ this.punchangle_z = this.punchangle_z + 60 * frametime;
+ if (this.punchangle_z > 0)
+ this.punchangle_z = 0;
}
- self.angles_x = self.punchangle_x;
- self.angles_y = self.punchangle_y + self.move_angles_y;
- self.angles_z = self.punchangle_z;
- self.move_angles_y = self.move_angles_y + 45 * frametime;
+ this.angles_x = this.punchangle_x;
+ this.angles_y = this.punchangle_y + this.move_angles_y;
+ this.angles_z = this.punchangle_z;
+ this.move_angles_y = this.move_angles_y + 45 * frametime;
}
- setorigin(self, self.cp_origin + self.cp_bob_origin + self.cp_bob_dmg);
+ setorigin(this, this.cp_origin + this.cp_bob_origin + this.cp_bob_dmg);
}
-void cpicon_damage(float hp)
+void cpicon_damage(entity this, float hp)
{
- if(!self.iscaptured) { return; }
+ if(!this.iscaptured) { return; }
- if(hp < self.max_health * 0.25)
- setmodel(self, "models/onslaught/controlpoint_icon_dmg3.md3");
- else if(hp < self.max_health * 0.50)
- setmodel(self, "models/onslaught/controlpoint_icon_dmg2.md3");
- else if(hp < self.max_health * 0.75)
- setmodel(self, "models/onslaught/controlpoint_icon_dmg1.md3");
- else if(hp <= self.max_health || hp >= self.max_health)
- setmodel(self, "models/onslaught/controlpoint_icon.md3");
+ if(hp < this.max_health * 0.25)
+ setmodel(this, MDL_ONS_CP3);
+ else if(hp < this.max_health * 0.50)
+ setmodel(this, MDL_ONS_CP2);
+ else if(hp < this.max_health * 0.75)
+ setmodel(this, MDL_ONS_CP1);
+ else if(hp <= this.max_health || hp >= this.max_health)
+ setmodel(this, MDL_ONS_CP);
- self.punchangle = (2 * randomvec() - '1 1 1') * 45;
+ this.punchangle = (2 * randomvec() - '1 1 1') * 45;
- self.cp_bob_dmg_z = (2 * random() - 1) * 15;
- self.pain_finished = time + 1;
- self.colormod = '2 2 2';
+ this.cp_bob_dmg_z = (2 * random() - 1) * 15;
+ this.pain_finished = time + 1;
+ this.colormod = '2 2 2';
- setsize(self, CPICON_MIN, CPICON_MAX);
+ setsize(this, CPICON_MIN, CPICON_MAX);
}
-void cpicon_construct()
+void cpicon_construct(entity this)
{
- self.netname = "Control Point Icon";
+ this.netname = "Control Point Icon";
- setmodel(self, "models/onslaught/controlpoint_icon.md3");
- setsize(self, CPICON_MIN, CPICON_MAX);
+ setmodel(this, MDL_ONS_CP);
+ setsize(this, CPICON_MIN, CPICON_MAX);
- if(self.icon_realmodel == world)
+ if(this.icon_realmodel == world)
{
- self.icon_realmodel = spawn();
- setmodel(self.icon_realmodel, "null");
- setorigin(self.icon_realmodel, self.origin);
- setsize(self.icon_realmodel, CPICON_MIN, CPICON_MAX);
- self.icon_realmodel.movetype = MOVETYPE_NOCLIP;
- self.icon_realmodel.solid = SOLID_NOT;
- self.icon_realmodel.move_origin = self.icon_realmodel.origin;
+ this.icon_realmodel = spawn();
+ setmodel(this.icon_realmodel, MDL_Null);
+ setorigin(this.icon_realmodel, this.origin);
+ setsize(this.icon_realmodel, CPICON_MIN, CPICON_MAX);
+ this.icon_realmodel.movetype = MOVETYPE_NOCLIP;
+ this.icon_realmodel.solid = SOLID_NOT;
+ this.icon_realmodel.move_origin = this.icon_realmodel.origin;
}
- if(self.iscaptured) { self.icon_realmodel.solid = SOLID_BBOX; }
-
- self.move_movetype = MOVETYPE_NOCLIP;
- self.solid = SOLID_NOT;
- self.movetype = MOVETYPE_NOCLIP;
- self.move_origin = self.origin;
- self.move_time = time;
- self.drawmask = MASK_NORMAL;
- self.alpha = 1;
- self.draw = cpicon_draw;
- self.cp_origin = self.origin;
- self.cp_bob_origin = '0 0 0.1';
- self.cp_bob_spd = 0;
+ if(this.iscaptured) { this.icon_realmodel.solid = SOLID_BBOX; }
+
+ this.move_movetype = MOVETYPE_NOCLIP;
+ this.solid = SOLID_NOT;
+ this.movetype = MOVETYPE_NOCLIP;
+ this.move_origin = this.origin;
+ this.move_time = time;
+ this.drawmask = MASK_NORMAL;
+ this.alpha = 1;
+ this.draw = cpicon_draw;
+ this.cp_origin = this.origin;
+ this.cp_bob_origin = '0 0 0.1';
+ this.cp_bob_spd = 0;
}
.vector glowmod;
-void cpicon_changeteam()
+void cpicon_changeteam(entity this)
{
- if(self.team)
+ if(this.team)
{
- self.glowmod = Team_ColorRGB(self.team - 1);
- self.teamradar_color = Team_ColorRGB(self.team - 1);
- self.colormap = 1024 + (self.team - 1) * 17;
+ this.glowmod = Team_ColorRGB(this.team - 1);
+ this.teamradar_color = Team_ColorRGB(this.team - 1);
+ this.colormap = 1024 + (this.team - 1) * 17;
}
else
{
- self.colormap = 1024;
- self.glowmod = '1 1 0';
- self.teamradar_color = '1 1 0';
+ this.colormap = 1024;
+ this.glowmod = '1 1 0';
+ this.teamradar_color = '1 1 0';
}
}
-void ent_cpicon()
+void ent_cpicon(entity this)
{
int sf = ReadByte();
if(sf & CPSF_SETUP)
{
- self.origin_x = ReadCoord();
- self.origin_y = ReadCoord();
- self.origin_z = ReadCoord();
- setorigin(self, self.origin);
-
- self.health = ReadByte();
- self.max_health = ReadByte();
- self.count = ReadByte();
- self.team = ReadByte();
- self.iscaptured = ReadByte();
-
- if(!self.count)
- self.count = (self.health - self.max_health) * frametime;
-
- cpicon_changeteam();
- cpicon_precache();
- cpicon_construct();
+ this.origin_x = ReadCoord();
+ this.origin_y = ReadCoord();
+ this.origin_z = ReadCoord();
+ setorigin(this, this.origin);
+
+ this.health = ReadByte();
+ this.max_health = ReadByte();
+ this.count = ReadByte();
+ this.team = ReadByte();
+ this.iscaptured = ReadByte();
+
+ if(!this.count)
+ this.count = (this.health - this.max_health) * frametime;
+
+ cpicon_changeteam(this);
+ cpicon_construct(this);
}
if(sf & CPSF_STATUS)
{
int _tmp = ReadByte();
- if(_tmp != self.team)
+ if(_tmp != this.team)
{
- self.team = _tmp;
- cpicon_changeteam();
+ this.team = _tmp;
+ cpicon_changeteam(this);
}
_tmp = ReadByte();
- if(_tmp != self.health)
- cpicon_damage(_tmp);
+ if(_tmp != this.health)
+ cpicon_damage(this, _tmp);
- self.health = _tmp;
+ this.health = _tmp;
}
}
const int CPSF_STATUS = 4;
const int CPSF_SETUP = 8;
-void ent_cpicon();
-void cpicon_precache();
+void ent_cpicon(entity this);
#endif
-#include "csqcmodel_hooks.qh"
#include "_all.qh"
#include "gibs.qh"
#include "../common/animdecide.qh"
#include "../common/csqcmodel_settings.qh"
-#include "../common/effects.qh"
+#include "../common/effects/effects.qh"
#include "../common/teams.qh"
#include "../common/triggers/trigger/viewloc.qh"
+#include "../common/viewloc.qh"
#include "mutators/events.qh"
.int lodmodelindex1;
.int lodmodelindex2;
void CSQCPlayer_LOD_Apply(void)
-{
+{SELFPARAM();
// LOD model loading
if(self.lodmodelindex0 != self.modelindex)
{
if(fexists(s))
{
precache_model(s);
- setmodel(self, s);
+ _setmodel(self, s);
if(self.modelindex)
self.lodmodelindex1 = self.modelindex;
}
if(fexists(s))
{
precache_model(s);
- setmodel(self, s);
+ _setmodel(self, s);
if(self.modelindex)
self.lodmodelindex2 = self.modelindex;
}
- setmodel(self, modelname); // make everything normal again
+ _setmodel(self, modelname); // make everything normal again
setsize(self, mi, ma);
}
.vector old_glowmod;
void CSQCPlayer_ModelAppearance_PreUpdate(void)
-{
+{SELFPARAM();
self.model = self.forceplayermodels_savemodel;
self.modelindex = self.forceplayermodels_savemodelindex;
self.skin = self.forceplayermodels_saveskin;
self.colormap = self.forceplayermodels_savecolormap;
}
void CSQCPlayer_ModelAppearance_PostUpdate(void)
-{
+{SELFPARAM();
self.forceplayermodels_savemodel = self.model;
self.forceplayermodels_savemodelindex = self.modelindex;
self.forceplayermodels_saveskin = self.skin;
}
}
void CSQCPlayer_ModelAppearance_Apply(bool islocalplayer)
-{
+{SELFPARAM();
// FORCEMODEL
// which one is ALWAYS good?
if (!forceplayermodels_goodmodel)
entity e;
e = spawn();
precache_model(cvar_defstring("_cl_playermodel"));
- setmodel(e, cvar_defstring("_cl_playermodel"));
+ _setmodel(e, cvar_defstring("_cl_playermodel"));
forceplayermodels_goodmodel = e.model;
forceplayermodels_goodmodelindex = e.modelindex;
remove(e);
// only if this failed, find it out on our own
entity e;
e = spawn();
- setmodel(e, autocvar__cl_playermodel); // this is harmless, see below
+ _setmodel(e, autocvar__cl_playermodel); // this is harmless, see below
forceplayermodels_modelisgoodmodel = fexists(e.model);
forceplayermodels_model = e.model;
forceplayermodels_modelindex = e.modelindex;
{
entity e;
e = spawn();
- setmodel(e, autocvar_cl_forcemyplayermodel); // this is harmless, see below
+ _setmodel(e, autocvar_cl_forcemyplayermodel); // this is harmless, see below
forceplayermodels_myisgoodmodel = fexists(e.model);
forceplayermodels_mymodel = e.model;
forceplayermodels_mymodelindex = e.modelindex;
#define IS_DEAD_FRAME(f) ((f) == 0 || (f) == 1)
void CSQCPlayer_FallbackFrame_PreUpdate(void)
-{
+{SELFPARAM();
self.frame = self.csqcmodel_saveframe;
self.frame2 = self.csqcmodel_saveframe2;
#ifdef CSQCMODEL_HAVE_TWO_FRAMES
#endif
}
void CSQCPlayer_FallbackFrame_PostUpdate(bool isnew)
-{
+{SELFPARAM();
self.csqcmodel_saveframe = self.frame;
self.csqcmodel_saveframe2 = self.frame2;
#ifdef CSQCMODEL_HAVE_TWO_FRAMES
self.csqcmodel_isdead = IS_DEAD_FRAME(self.frame);
}
void CSQCPlayer_AnimDecide_PostUpdate(bool isnew)
-{
+{SELFPARAM();
self.csqcmodel_isdead = !!(self.anim_state & (ANIMSTATE_DEAD1 | ANIMSTATE_DEAD2));
}
int CSQCPlayer_FallbackFrame(int f)
-{
+{SELFPARAM();
if(frameduration(self.modelindex, f) > 0)
return f; // goooooood
if(frameduration(self.modelindex, 1) <= 0)
return f;
}
void CSQCPlayer_FallbackFrame_Apply(void)
-{
+{SELFPARAM();
self.frame = CSQCPlayer_FallbackFrame(self.frame);
self.frame2 = CSQCPlayer_FallbackFrame(self.frame2);
#ifdef CSQCMODEL_HAVE_TWO_FRAMES
.int tag_entity_lastmodelindex;
.int tag_index;
void CSQCModel_AutoTagIndex_Apply(void)
-{
+{SELFPARAM();
if(self.tag_entity && wasfreed(self.tag_entity))
self.tag_entity = world;
- if(self.viewloc && wasfreed(self.viewloc))
- self.viewloc = world;
-
- if(self.viewloc.entnum != self.tag_networkviewloc)
- self.viewloc = findfloat(world, entnum, self.tag_networkviewloc);
+ viewloc_SetTags();
MUTATOR_CALLHOOK(TagIndex_Update, self);
// recursive predraw call to fix issues with forcemodels and LOD if bone indexes mismatch
if(self.tag_entity.classname == "csqcmodel")
{
- entity oldself = self;
- self = self.tag_entity;
- CSQCModel_Hook_PreDraw((self.entnum >= 1 && self.entnum <= maxclients));
- self = oldself;
+ WITH(entity, self, self.tag_entity, CSQCModel_Hook_PreDraw((self.entnum >= 1 && self.entnum <= maxclients)));
}
if(self.tag_entity.modelindex != self.tag_entity_lastmodelindex)
const int MF_TRACER3 = 128; // purple trail
.int csqcmodel_effects;
.int csqcmodel_modelflags;
+.int csqcmodel_traileffect;
void CSQCModel_Effects_PreUpdate(void)
-{
+{SELFPARAM();
self.effects = self.csqcmodel_effects;
self.modelflags = self.csqcmodel_modelflags;
+ self.traileffect = self.csqcmodel_traileffect;
}
void Reset_ArcBeam(void);
void CSQCModel_Effects_PostUpdate(void)
-{
+{SELFPARAM();
if (self == csqcplayer) {
if (self.csqcmodel_teleported) {
Reset_ArcBeam();
}
self.csqcmodel_effects = self.effects;
self.csqcmodel_modelflags = self.modelflags;
+ self.csqcmodel_traileffect = self.traileffect;
self.effects = 0;
self.modelflags = 0;
if(self.csqcmodel_teleported)
- Projectile_ResetTrail(self.origin);
+ Projectile_ResetTrail(self, self.origin);
}
.int snd_looping;
void CSQCModel_Effects_Apply(void)
-{
+{SELFPARAM();
int eff = self.csqcmodel_effects & ~CSQCMODEL_EF_RESPAWNGHOST;
+ int tref = self.csqcmodel_traileffect;
self.renderflags &= ~(RF_DEPTHHACK | RF_ADDITIVE | RF_FULLBRIGHT | EF_NOSHADOW | RF_USEAXIS);
self.effects = 0;
self.traileffect = 0;
if(eff & EF_BRIGHTFIELD)
- self.traileffect = particleeffectnum(EFFECT_TR_NEXUIZPLASMA);
+ tref = EFFECT_TR_NEXUIZPLASMA.m_id;
// ignoring EF_MUZZLEFLASH
if(eff & EF_BRIGHTLIGHT)
adddynamiclight(self.origin, 400, '3 3 3');
self.renderflags |= RF_DYNAMICMODELLIGHT;
// ignoring EF_UNUSED18, EF_UNUSED19, EF_RESTARTANIM_BIT, EF_TELEPORT_BIT, EF_LOWPRECISION
if(self.csqcmodel_modelflags & MF_ROCKET)
- self.traileffect = particleeffectnum(EFFECT_TR_ROCKET);
+ tref = EFFECT_TR_ROCKET.m_id;
if(self.csqcmodel_modelflags & MF_GRENADE)
- self.traileffect = particleeffectnum(EFFECT_TR_GRENADE);
+ tref = EFFECT_TR_GRENADE.m_id;
if(self.csqcmodel_modelflags & MF_GIB)
- self.traileffect = particleeffectnum(EFFECT_TR_BLOOD);
+ tref = EFFECT_TR_BLOOD.m_id;
if(self.csqcmodel_modelflags & MF_ROTATE)
{
self.renderflags |= RF_USEAXIS;
makevectors(self.angles + '0 100 0' * fmod(time, 3.6));
}
if(self.csqcmodel_modelflags & MF_TRACER)
- self.traileffect = particleeffectnum(EFFECT_TR_WIZSPIKE);
+ tref = EFFECT_TR_WIZSPIKE.m_id;
if(self.csqcmodel_modelflags & MF_ZOMGIB)
- self.traileffect = particleeffectnum(EFFECT_TR_SLIGHTBLOOD);
+ tref = EFFECT_TR_SLIGHTBLOOD.m_id;
if(self.csqcmodel_modelflags & MF_TRACER2)
- self.traileffect = particleeffectnum(EFFECT_TR_KNIGHTSPIKE);
+ tref = EFFECT_TR_KNIGHTSPIKE.m_id;
if(self.csqcmodel_modelflags & MF_TRACER3)
- self.traileffect = particleeffectnum(EFFECT_TR_VORESPIKE);
+ tref = EFFECT_TR_VORESPIKE.m_id;
+
+ self.traileffect = tref;
if(self.drawmask)
- Projectile_DrawTrail(self.origin);
+ Projectile_DrawTrail(self, self.origin);
else
- Projectile_ResetTrail(self.origin);
+ Projectile_ResetTrail(self, self.origin);
if(self.csqcmodel_effects & CSQCMODEL_EF_RESPAWNGHOST)
self.renderflags |= RF_ADDITIVE;
{
if(!self.snd_looping)
{
- sound(self, CH_TRIGGER_SINGLE, "misc/jetpack_fly.wav", VOL_BASE, autocvar_g_jetpack_attenuation);
+ sound(self, CH_TRIGGER_SINGLE, SND_JETPACK_FLY, VOL_BASE, autocvar_g_jetpack_attenuation);
self.snd_looping = CH_TRIGGER_SINGLE;
}
}
{
if(self.snd_looping)
{
- sound(self, self.snd_looping, "misc/null.wav", VOL_BASE, autocvar_g_jetpack_attenuation);
+ sound(self, self.snd_looping, SND_Null, VOL_BASE, autocvar_g_jetpack_attenuation);
self.snd_looping = 0;
}
}
}
-void CSQCPlayer_Precache()
-{
- precache_sound("misc/jetpack_fly.wav");
-}
-
// general functions
.int csqcmodel_predraw_run;
.int anim_frame;
.int anim_saveframe2time;
.int anim_prev_pmove_flags;
void CSQCModel_Hook_PreDraw(bool isplayer)
-{
+{SELFPARAM();
if(self.csqcmodel_predraw_run == framecount)
return;
self.csqcmodel_predraw_run = framecount;
}
void CSQCModel_Hook_PreUpdate(bool isnew, bool isplayer, bool islocalplayer)
-{
+{SELFPARAM();
// interpolate v_angle
self.iflags |= IFLAG_V_ANGLE_X;
// revert to values from server
}
void CSQCModel_Hook_PostUpdate(bool isnew, bool isplayer, bool islocalplayer)
-{
+{SELFPARAM();
// is it a player model? (shared state)
self.isplayermodel = (substring(self.model, 0, 14) == "models/player/" || substring(self.model, 0, 17) == "models/ok_player/" || (substring(self.model, 0, 16) == "models/monsters/" && (self.entnum >= 1 && self.entnum <= maxclients)));
+++ /dev/null
-#ifndef CSQCMODEL_HOOKS
-#define CSQCMODEL_HOOKS
-
-void CSQCPlayer_Precache();
-
-#endif
#include "../common/constants.qh"
#include "../common/deathtypes.qh"
-#include "../common/effects.qh"
+#include "../common/effects/effects.qh"
#include "../common/movetypes/movetypes.qh"
#include "../common/util.qh"
.bool isplayermodel;
void DamageEffect_Think()
-{
+{SELFPARAM();
// if particle distribution is enabled, slow ticrate by total number of damages
if(autocvar_cl_damageeffect_distribute)
self.nextthink = time + autocvar_cl_damageeffect_ticrate * self.owner.total_damages;
}
void DamageEffect(vector hitorg, float thedamage, int type, int specnum)
-{
+{SELFPARAM();
// particle effects for players and objects damaged by weapons (eg: flames coming out of victims shot with rockets)
int nearestbone = 0;
}
e = spawn();
- setmodel(e, "null"); // necessary to attach and read origin
+ setmodel(e, MDL_Null); // necessary to attach and read origin
setattachment(e, self, gettaginfo_name); // attach to the given bone
e.classname = "damage";
e.owner = self;
}
void Ent_DamageInfo(float isNew)
-{
+{SELFPARAM();
float thedamage, rad, edge, thisdmg;
bool hitplayer = false;
int species, forcemul;
vector force, thisforce;
- entity oldself;
-
- oldself = self;
w_deathtype = ReadShort();
w_issilent = (w_deathtype & 0x8000);
else
forcemul = 1;
- for(self = findradius(w_org, rad + MAX_DAMAGEEXTRARADIUS); self; self = self.chain)
+ for(entity e = findradius(w_org, rad + MAX_DAMAGEEXTRARADIUS); e; e = e.chain)
{
+ setself(e);
// attached ents suck
if(self.tag_entity)
continue;
if(self.isplayermodel)
hitplayer = true; // this impact damaged a player
}
-
- self = oldself;
+ setself(this);
if(DEATH_ISVEHICLE(w_deathtype))
{
// spiderbot
case DEATH_VH_SPID_MINIGUN:
- string _snd;
- _snd = W_Sound(strcat("ric", ftos(1 + rint(random() * 2))));
- sound(self, CH_SHOTS, _snd, VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_RIC_RANDOM(), VOL_BASE, ATTEN_NORM);
pointparticles(particleeffectnum(EFFECT_SPIDERBOT_MINIGUN_IMPACT), self.origin, w_backoff * 1000, 1);
break;
case DEATH_VH_SPID_ROCKET:
- sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
pointparticles(particleeffectnum(EFFECT_SPIDERBOT_ROCKET_EXPLODE), self.origin, w_backoff * 1000, 1);
break;
case DEATH_VH_SPID_DEATH:
- sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_MIN);
+ sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_MIN);
pointparticles(particleeffectnum(EFFECT_EXPLOSION_BIG), self.origin, w_backoff * 1000, 1);
break;
case DEATH_VH_WAKI_GUN:
- sound(self, CH_SHOTS, W_Sound("laserimpact"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTEN_NORM);
pointparticles(particleeffectnum(EFFECT_RACER_IMPACT), self.origin, w_backoff * 1000, 1);
break;
case DEATH_VH_WAKI_ROCKET:
- sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
pointparticles(particleeffectnum(EFFECT_RACER_ROCKET_EXPLODE), self.origin, w_backoff * 1000, 1);
break;
case DEATH_VH_WAKI_DEATH:
- sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_MIN);
+ sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_MIN);
pointparticles(particleeffectnum(EFFECT_EXPLOSION_BIG), self.origin, w_backoff * 1000, 1);
break;
case DEATH_VH_RAPT_CANNON:
- sound(self, CH_SHOTS, W_Sound("laserimpact"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTEN_NORM);
pointparticles(particleeffectnum(EFFECT_RAPTOR_CANNON_IMPACT), self.origin, w_backoff * 1000, 1);
break;
case DEATH_VH_RAPT_FRAGMENT:
ang = vectoangles(vel);
RaptorCBShellfragToss(w_org, vel, ang + '0 0 1' * (120 * i));
}
- sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
pointparticles(particleeffectnum(EFFECT_RAPTOR_BOMB_SPREAD), self.origin, w_backoff * 1000, 1);
break;
case DEATH_VH_RAPT_BOMB:
- sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
pointparticles(particleeffectnum(EFFECT_RAPTOR_BOMB_IMPACT), self.origin, w_backoff * 1000, 1);
break;
case DEATH_VH_RAPT_DEATH:
- sound(self, CH_SHOTS, W_Sound("laserimpact"), VOL_BASE, ATTEN_MIN);
+ sound(self, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTEN_MIN);
pointparticles(particleeffectnum(EFFECT_EXPLOSION_BIG), self.origin, w_backoff * 1000, 1);
break;
case DEATH_VH_BUMB_GUN:
- sound(self, CH_SHOTS, W_Sound("fireball_impact2"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_FIREBALL_IMPACT2, VOL_BASE, ATTEN_NORM);
pointparticles(particleeffectnum(EFFECT_BIGPLASMA_IMPACT), self.origin, w_backoff * 1000, 1);
break;
}
if(DEATH_ISTURRET(w_deathtype))
{
- string _snd;
traceline(w_org - normalize(force) * 16, w_org + normalize(force) * 16, MOVE_NOMONSTERS, world);
if(trace_plane_normal != '0 0 0')
w_backoff = trace_plane_normal;
switch(w_deathtype)
{
case DEATH_TURRET_EWHEEL:
- sound(self, CH_SHOTS, W_Sound("laserimpact"), VOL_BASE, ATTEN_MIN);
+ sound(self, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTEN_MIN);
pointparticles(particleeffectnum(EFFECT_BLASTER_IMPACT), self.origin, w_backoff * 1000, 1);
break;
case DEATH_TURRET_FLAC:
pointparticles(particleeffectnum(EFFECT_HAGAR_EXPLODE), w_org, '0 0 0', 1);
- _snd = W_Sound(strcat("hagexp", ftos(1 + rint(random() * 2))));
- sound(self, CH_SHOTS, _snd, VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_HAGEXP_RANDOM(), VOL_BASE, ATTEN_NORM);
break;
case DEATH_TURRET_MLRS:
case DEATH_TURRET_HK:
case DEATH_TURRET_WALK_ROCKET:
case DEATH_TURRET_HELLION:
- sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_MIN);
+ sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_MIN);
pointparticles(particleeffectnum(EFFECT_ROCKET_EXPLODE), self.origin, w_backoff * 1000, 1);
break;
case DEATH_TURRET_MACHINEGUN:
case DEATH_TURRET_WALK_GUN:
- _snd = W_Sound(strcat("ric", ftos(1 + rint(random() * 2))));
- sound(self, CH_SHOTS, _snd, VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_RIC_RANDOM(), VOL_BASE, ATTEN_NORM);
pointparticles(particleeffectnum(EFFECT_MACHINEGUN_IMPACT), self.origin, w_backoff * 1000, 1);
break;
case DEATH_TURRET_PLASMA:
- sound(self, CH_SHOTS, W_Sound("electro_impact"), VOL_BASE, ATTEN_MIN);
+ sound(self, CH_SHOTS, SND_ELECTRO_IMPACT, VOL_BASE, ATTEN_MIN);
pointparticles(particleeffectnum(EFFECT_ELECTRO_IMPACT), self.origin, w_backoff * 1000, 1);
break;
case DEATH_TURRET_WALK_MELEE:
- sound(self, CH_SHOTS, W_Sound("ric1"), VOL_BASE, ATTEN_MIN);
+ sound(self, CH_SHOTS, SND_RIC1, VOL_BASE, ATTEN_MIN);
pointparticles(particleeffectnum(EFFECT_TE_SPARK), self.origin, w_backoff * 1000, 1);
break;
w_backoff = -1 * normalize(force);
setorigin(self, w_org + w_backoff * 2); // for sound() calls
- if(!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)) { WEP_ACTION(hitwep, WR_IMPACTEFFECT); }
+ if(!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)) {
+ Weapon w = get_weaponinfo(hitwep); w.wr_impacteffect(w);
+ }
}
}
#include "generator.qh"
-bool generator_precached;
.int count;
.float max_health;
-void generator_precache()
-{
- if(generator_precached)
- return; // already precached
-
- precache_model("models/onslaught/generator.md3");
- precache_model("models/onslaught/generator_dead.md3");
- precache_model("models/onslaught/generator_dmg1.md3");
- precache_model("models/onslaught/generator_dmg2.md3");
- precache_model("models/onslaught/generator_dmg3.md3");
- precache_model("models/onslaught/generator_dmg4.md3");
- precache_model("models/onslaught/generator_dmg5.md3");
- precache_model("models/onslaught/generator_dmg6.md3");
- precache_model("models/onslaught/generator_dmg7.md3");
- precache_model("models/onslaught/generator_dmg8.md3");
- precache_model("models/onslaught/generator_dmg9.md3");
- precache_model("models/onslaught/generator_dead.md3");
-
- precache_model("models/onslaught/ons_ray.md3");
- precache_sound("onslaught/shockwave.wav");
- precache_sound(W_Sound("grenade_impact"));
- precache_sound(W_Sound("rocket_impact"));
- precache_sound("onslaught/electricity_explode.wav");
-
- generator_precached = true;
-}
-
-void ons_generator_ray_draw()
+void ons_generator_ray_draw(entity this)
{
if(time < self.move_time)
return;
entity e;
e = spawn();
e.classname = "ons_ray";
- setmodel(e, "models/onslaught/ons_ray.md3");
+ setmodel(e, MDL_ONS_RAY);
setorigin(e, org);
e.angles = randomvec() * 360;
e.move_origin = org;
e.draw = ons_generator_ray_draw;
}
-void generator_draw()
+void generator_draw(entity this)
{
if(time < self.move_time)
return;
if(random() < 0.01)
{
pointparticles(particleeffectnum(EFFECT_ELECTRO_BALLEXPLODE), self.origin + randompos('-50 -50 -20', '50 50 50'), '0 0 0', 1);
- sound(self, CH_TRIGGER, "onslaught/electricity_explode.wav", VOL_BASE, ATTEN_NORM);
+ sound(self, CH_TRIGGER, SND_ONS_ELECTRICITY_EXPLODE, VOL_BASE, ATTEN_NORM);
}
else
pointparticles(particleeffectnum(EFFECT_ONS_GENERATOR_DAMAGED), self.origin + randompos('-60 -60 -20', '60 60 60'), '0 0 0', 1);
// White shockwave
if(self.count==40||self.count==20)
{
- sound(self, CH_TRIGGER, "onslaught/shockwave.wav", VOL_BASE, ATTEN_NORM);
+ sound(self, CH_TRIGGER, SND_ONS_SHOCKWAVE, VOL_BASE, ATTEN_NORM);
pointparticles(particleeffectnum(EFFECT_ELECTRO_COMBO), self.origin, '0 0 0', 6);
}
if(random() < 0.25)
{
te_explosion(self.origin);
- sound(self, CH_TRIGGER, W_Sound("grenade_impact"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_TRIGGER, SND_GRENADE_IMPACT, VOL_BASE, ATTEN_NORM);
}
// Particles
org = self.origin;
te_explosion(org);
pointparticles(particleeffectnum(EFFECT_ONS_GENERATOR_EXPLODE2), org, '0 0 0', 1);
- sound(self, CH_TRIGGER, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_TRIGGER, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
}
self.move_time = time + 0.05;
}
void generator_damage(float hp)
-{
+{SELFPARAM();
if(hp <= 0)
- setmodel(self, "models/onslaught/generator_dead.md3");
+ setmodel(self, MDL_ONS_GEN_DEAD);
else if(hp < self.max_health * 0.10)
- setmodel(self, "models/onslaught/generator_dmg9.md3");
+ setmodel(self, MDL_ONS_GEN9);
else if(hp < self.max_health * 0.20)
- setmodel(self, "models/onslaught/generator_dmg8.md3");
+ setmodel(self, MDL_ONS_GEN8);
else if(hp < self.max_health * 0.30)
- setmodel(self, "models/onslaught/generator_dmg7.md3");
+ setmodel(self, MDL_ONS_GEN7);
else if(hp < self.max_health * 0.40)
- setmodel(self, "models/onslaught/generator_dmg6.md3");
+ setmodel(self, MDL_ONS_GEN6);
else if(hp < self.max_health * 0.50)
- setmodel(self, "models/onslaught/generator_dmg5.md3");
+ setmodel(self, MDL_ONS_GEN5);
else if(hp < self.max_health * 0.60)
- setmodel(self, "models/onslaught/generator_dmg4.md3");
+ setmodel(self, MDL_ONS_GEN4);
else if(hp < self.max_health * 0.70)
- setmodel(self, "models/onslaught/generator_dmg3.md3");
+ setmodel(self, MDL_ONS_GEN3);
else if(hp < self.max_health * 0.80)
- setmodel(self, "models/onslaught/generator_dmg2.md3");
+ setmodel(self, MDL_ONS_GEN2);
else if(hp < self.max_health * 0.90)
- setmodel(self, "models/onslaught/generator_dmg1.md3");
+ setmodel(self, MDL_ONS_GEN1);
else if(hp <= self.max_health || hp >= self.max_health)
- setmodel(self, "models/onslaught/generator.md3");
+ setmodel(self, MDL_ONS_GEN);
setsize(self, GENERATOR_MIN, GENERATOR_MAX);
}
void generator_construct()
-{
+{SELFPARAM();
self.netname = "Generator";
self.classname = "onslaught_generator";
setorigin(self, self.origin);
- setmodel(self, "models/onslaught/generator.md3");
+ setmodel(self, MDL_ONS_GEN);
setsize(self, GENERATOR_MIN, GENERATOR_MAX);
self.move_movetype = MOVETYPE_NOCLIP;
.vector glowmod;
void generator_changeteam()
-{
+{SELFPARAM();
if(self.team)
{
self.glowmod = Team_ColorRGB(self.team - 1);
}
void ent_generator()
-{
+{SELFPARAM();
int sf = ReadByte();
if(sf & GSF_SETUP)
self.count = 40;
generator_changeteam();
- generator_precache();
generator_construct();
}
const int GSF_SETUP = 8;
void ent_generator();
-void generator_precache();
#endif
.float gravity;
void Gib_Delete()
-{
+{SELFPARAM();
remove(self);
}
if(specnum != SPECIES_ROBOT_SOLID || mdlname == "models/gibs/chunk.mdl")
{
if(mdlname == "models/gibs/bloodyskull.md3")
- setmodel(gib, "models/gibs/robo.md3");
+ setmodel(gib, MDL_GIB_ROBO);
else
- setmodel(gib, strcat("models/gibs/robo", ftos(floor(random() * 8) + 1), ".md3"));
+ setmodel(gib, MDL_GIB_ROBO_RANDOM());
if(specnum == SPECIES_ROBOT_SHINY)
{
gib.skin = 1;
break;
}
default:
- setmodel(gib, mdlname);
+ _setmodel(gib, mdlname);
gib.skin = specnum;
break;
}
}
void Gib_Touch()
-{
+{SELFPARAM();
// TODO maybe bounce of walls, make more gibs, etc.
if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
}
if(!self.silent)
- sound(self, CH_PAIN, strcat("misc/gib_splat0", ftos(floor(prandom() * 4 + 1)), ".wav"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_PAIN, SND_GIB_SPLAT_RANDOM(), VOL_BASE, ATTEN_NORM);
pointparticles(_particleeffectnum(strcat(species_prefix(self.cnt), "blood")), self.origin + '0 0 1', '0 0 30', 10);
Gib_Delete();
}
-void Gib_Draw()
+void Gib_Draw(entity this)
{
vector oldorg;
oldorg = self.origin;
}
void Ent_GibSplash(bool isNew)
-{
+{SELFPARAM();
int amount, type, specnum;
vector org, vel;
string specstr;
{
case 0x01:
if(!issilent)
- sound (self, CH_PAIN, "misc/gib.wav", VOL_BASE, ATTEN_NORM);
+ sound (self, CH_PAIN, SND_GIB, VOL_BASE, ATTEN_NORM);
if(prandom() < amount)
TossGib ("models/gibs/eye.md3", org, org, vel, prandomvec() * 150, specnum, 0, issilent);
break;
}
}
-
-void GibSplash_Precache()
-{
- precache_model("models/gibs/chunk.mdl");
- precache_model("models/gibs/leg1.md3");
- precache_model("models/gibs/leg2.md3");
- precache_model("models/gibs/chest.md3");
- precache_model("models/gibs/smallchest.md3");
- precache_model("models/gibs/arm.md3");
- precache_model("models/gibs/bloodyskull.md3");
- precache_model("models/gibs/eye.md3");
-
- precache_model("models/gibs/robo.md3");
- precache_model("models/gibs/robo1.md3");
- precache_model("models/gibs/robo2.md3");
- precache_model("models/gibs/robo3.md3");
- precache_model("models/gibs/robo4.md3");
- precache_model("models/gibs/robo5.md3");
- precache_model("models/gibs/robo6.md3");
- precache_model("models/gibs/robo7.md3");
- precache_model("models/gibs/robo8.md3");
-
- precache_sound ("misc/gib.wav");
- precache_sound ("misc/gib_splat01.wav");
- precache_sound ("misc/gib_splat02.wav");
- precache_sound ("misc/gib_splat03.wav");
- precache_sound ("misc/gib_splat04.wav");
-}
void Gib_Touch();
-void Gib_Draw();
+void Gib_Draw(entity this);
void TossGib (string mdlname, vector safeorg, vector org, vector vconst, vector vrand, int specnum, bool destroyontouch, bool issilent);
void Ent_GibSplash(bool isNew);
-void GibSplash_Precache();
#endif
}
class(Hook) .float teleport_time;
-void Draw_GrapplingHook()
+void Draw_GrapplingHook(entity this)
{
vector a, b, atrans;
string tex;
if(self.teleport_time)
if(time > self.teleport_time)
{
- sound (self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTEN_NORM); // safeguard
+ sound (self, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM); // safeguard
self.teleport_time = 0;
}
}
void Remove_GrapplingHook()
-{
- sound (self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTEN_NORM);
+{SELFPARAM();
+ sound (self, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
}
void Ent_ReadHook(float bIsNew, float type)
-{
+{SELFPARAM();
self.HookType = type;
int sf = ReadByte();
default:
case ENT_CLIENT_HOOK:
// for the model
- setmodel(self, "models/hook.md3");
+ setmodel(self, MDL_HOOK);
self.drawmask = MASK_NORMAL;
break;
case ENT_CLIENT_ARC_BEAM:
- sound (self, CH_SHOTS_SINGLE, W_Sound("lgbeam_fly"), VOL_BASE, ATTEN_NORM);
+ sound (self, CH_SHOTS_SINGLE, SND_LGBEAM_FLY, VOL_BASE, ATTEN_NORM);
break;
}
}
self.teleport_time = time + 10;
}
-void Hook_Precache()
-{
- precache_sound(W_Sound("lgbeam_fly"));
- precache_model("models/hook.md3");
-}
-
// TODO: hook: temporarily transform self.origin for drawing the model along warpzones!
#define HOOK_H
void Draw_CylindricLine(vector from, vector to, float thickness, string texture, float aspect, float shift, vector rgb, float theAlpha, float drawflag, vector vieworg);
-void Hook_Precache();
void Ent_ReadHook(float bIsNew, float type);
#include "../dpdefs/keycodes.qh"
-#include "../common/buffs.qh"
+#include "../common/buffs/all.qh"
#include "../common/constants.qh"
#include "../common/deathtypes.qh"
#include "../common/items/all.qc"
#include "../common/mapinfo.qh"
-#include "../common/nades.qh"
+#include "../common/nades/all.qh"
+#include "../common/mutators/mutator/waypoints/all.qh"
#include "../server/mutators/gamemode_ctf.qh"
#include "../common/stats.qh"
// Weapon icons (#0)
//
-entity weaponorder[WEP_MAXCOUNT];
+entity weaponorder[Weapons_MAX];
void weaponorder_swap(int i, int j, entity pass)
{
entity h = weaponorder[i];
}
void HUD_Weapons(void)
-{
+{SELFPARAM();
// declarations
WepSet weapons_stat = WepSet_GetFromStat();
int i;
weapon_cnt = 0;
for(i = WEP_FIRST; i <= WEP_LAST; ++i)
{
- self = get_weaponinfo(i);
+ setself(get_weaponinfo(i));
if(self.impulse >= 0)
{
weaponorder[weapon_cnt] = self;
++weapon_cnt;
}
}
- for(i = weapon_cnt; i < WEP_MAXCOUNT; ++i)
+ for(i = weapon_cnt; i < Weapons_MAX; ++i)
weaponorder[i] = world;
heapsort(weapon_cnt, weaponorder_swap, weaponorder_cmp, world);
if(cvar("wep_add"))
{
weapons_stat = '0 0 0';
- float countw = 1 + floor((floor(time * cvar("wep_add"))) % WEP_COUNT);
+ float countw = 1 + floor((floor(time * cvar("wep_add"))) % (Weapons_COUNT - 1));
for(i = WEP_FIRST; i <= countw; ++i)
weapons_stat |= WepSet_FromWeapon(i);
}
vector padded_panel_size = panel_size - '2 2 0' * panel_bg_padding;
// get the all-weapons layout
- vector table_size = HUD_GetTableSize_BestItemAR(WEP_COUNT, padded_panel_size, aspect);
+ int nHidden = 0;
+ WepSet weapons_stat = WepSet_GetFromStat();
+ for (int i = WEP_FIRST; i <= WEP_LAST; ++i) {
+ WepSet weapons_wep = WepSet_FromWeapon(i);
+ if (weapons_stat & weapons_wep) continue;
+ Weapon w = get_weaponinfo(i);
+ if (w.spawnflags & WEP_FLAG_MUTATORBLOCKED) nHidden += 1;
+ }
+ vector table_size = HUD_GetTableSize_BestItemAR((Weapons_COUNT - 1) - nHidden, padded_panel_size, aspect);
columns = table_size.x;
rows = table_size.y;
weapon_size.x = padded_panel_size.x / columns;
panel_pos.y += (old_panel_size.y - panel_size.y) / 2;
}
else
- weapon_count = WEP_COUNT;
+ weapon_count = (Weapons_COUNT - 1);
// animation for fading in/out the panel respectively when not in use
if(!autocvar__hud_configure)
if(!rows) // if rows is > 0 onlyowned code has already updated these vars
{
- vector table_size = HUD_GetTableSize_BestItemAR(WEP_COUNT, panel_size, aspect);
+ vector table_size = HUD_GetTableSize_BestItemAR((Weapons_COUNT - 1), panel_size, aspect);
columns = table_size.x;
rows = table_size.y;
weapon_size.x = panel_size.x / columns;
for(i = 0; i <= WEP_LAST-WEP_FIRST; ++i)
{
// retrieve information about the current weapon to be drawn
- self = weaponorder[i];
+ setself(weaponorder[i]);
weapon_id = self.impulse;
isCurrent = (self.weapon == switchweapon);
float bonusNades = getstatf(STAT_NADE_BONUS);
float bonusProgress = getstatf(STAT_NADE_BONUS_SCORE);
float bonusType = getstati(STAT_NADE_BONUS_TYPE);
- vector nadeColor = NADES[bonusType].m_color;
- string nadeIcon = NADES[bonusType].m_icon;
+ vector nadeColor = Nades[bonusType].m_color;
+ string nadeIcon = Nades[bonusType].m_icon;
vector iconPos, textPos;
if(superTime)
addPowerupItem("Superweapons", "superweapons", autocvar_hud_progressbar_superweapons_color, superTime, 30);
- FOREACH(BUFFS, it.m_itemid & allBuffs, LAMBDA(
+ FOREACH(Buffs, it.m_itemid & allBuffs, LAMBDA(
addPowerupItem(it.m_prettyName, strcat("buff_", it.m_name), it.m_color, bound(0, getstatf(STAT_BUFF_TIME) - time, 99), 60);
));
drawpic(coord - '8 8 0', "gfx/teamradar_icon_glow", '16 16 0', brightcolor, panel_fg_alpha, 0);
}
}
-
- draw_teamradar_icon(tm.origin, tm.teamradar_icon, tm, tm.teamradar_color, panel_fg_alpha);
+ entity icon = RadarIcons[tm.teamradar_icon];
+ draw_teamradar_icon(tm.origin, icon, tm, spritelookupcolor(tm, icon.netname, tm.teamradar_color), panel_fg_alpha);
}
for(tm = world; (tm = find(tm, classname, "entcs_receiver")); )
{
reset_centerprint_messages();
if (time > hud_configure_cp_generation_time)
{
- if(HUD_PANEL(CENTERPRINT) == highlightedPanel)
+ if(highlightedPanel == HUD_PANEL(CENTERPRINT))
{
float r;
r = random();
// cache the panel order into the panel_order array
if(autocvar__hud_panelorder != hud_panelorder_prev) {
- for(i = 0; i < HUD_PANEL_NUM; ++i)
+ for(i = 0; i < hud_panels_COUNT; ++i)
panel_order[i] = -1;
string s = "";
int p_num;
bool warning = false;
int argc = tokenize_console(autocvar__hud_panelorder);
- if (argc > HUD_PANEL_NUM)
+ if (argc > hud_panels_COUNT)
warning = true;
//first detect wrong/missing panel numbers
- for(i = 0; i < HUD_PANEL_NUM; ++i) {
+ for(i = 0; i < hud_panels_COUNT; ++i) {
p_num = stoi(argv(i));
- if (p_num >= 0 && p_num < HUD_PANEL_NUM) { //correct panel number?
+ if (p_num >= 0 && p_num < hud_panels_COUNT) { //correct panel number?
if (panel_order[p_num] == -1) //found for the first time?
s = strcat(s, ftos(p_num), " ");
panel_order[p_num] = 1; //mark as found
else
warning = true;
}
- for(i = 0; i < HUD_PANEL_NUM; ++i) {
+ for(i = 0; i < hud_panels_COUNT; ++i) {
if (panel_order[i] == -1) {
warning = true;
s = strcat(s, ftos(i), " "); //add missing panel number
//now properly set panel_order
tokenize_console(s);
- for(i = 0; i < HUD_PANEL_NUM; ++i) {
+ for(i = 0; i < hud_panels_COUNT; ++i) {
panel_order[i] = stof(argv(i));
}
}
hud_draw_maximized = 0;
// draw panels in the order specified by panel_order array
- for(i = HUD_PANEL_NUM - 1; i >= 0; --i)
- HUD_Panel_Draw(hud_panel[panel_order[i]]);
+ for(i = hud_panels_COUNT - 1; i >= 0; --i)
+ HUD_Panel_Draw(hud_panels[panel_order[i]]);
hud_draw_maximized = 1; // panels that may be maximized must check this var
// draw maximized panels on top
#include "../common/weapons/all.qh"
-const int HUD_PANEL_MAX = 24;
-entity hud_panel[HUD_PANEL_MAX];
-const int HUD_PANEL_FIRST = 0;
-int HUD_PANEL_NUM;
-int HUD_PANEL_LAST;
+REGISTRY(hud_panels, 24)
+REGISTER_REGISTRY(Registerhud_panels)
-int panel_order[HUD_PANEL_MAX];
+#define REGISTER_HUD_PANEL(id, draw_func, name, showflags) \
+ void draw_func(); \
+ REGISTER(Registerhud_panels, HUD_PANEL, hud_panels, id, m_id, new(hud_panel)) { \
+ this.panel_id = this.m_id; \
+ this.panel_draw = draw_func; \
+ this.panel_name = #name; \
+ this.panel_showflags = showflags; \
+ }
+
+#define HUD_PANEL(NAME) HUD_PANEL_##NAME
+
+int panel_order[hud_panels_MAX];
string hud_panelorder_prev;
bool hud_draw_maximized;
const float BORDER_MULTIPLIER = 0.25;
float scoreboard_bottom;
-int weapon_accuracy[WEP_MAXCOUNT];
+int weapon_accuracy[Weapons_MAX];
int complain_weapon;
string complain_weapon_name;
void HUD_ItemsTime();
-#define HUD_PANELS(HUD_PANEL) \
- HUD_PANEL(WEAPONS , HUD_Weapons , weapons, PANEL_SHOW_MAINGAME ) \
- HUD_PANEL(AMMO , HUD_Ammo , ammo, PANEL_SHOW_MAINGAME ) \
- HUD_PANEL(POWERUPS , HUD_Powerups , powerups, PANEL_SHOW_MAINGAME ) \
- HUD_PANEL(HEALTHARMOR , HUD_HealthArmor , healtharmor, PANEL_SHOW_MAINGAME ) \
- HUD_PANEL(NOTIFY , HUD_Notify , notify, PANEL_SHOW_ALWAYS ) \
- HUD_PANEL(TIMER , HUD_Timer , timer, PANEL_SHOW_ALWAYS ) \
- HUD_PANEL(RADAR , HUD_Radar , radar, PANEL_SHOW_MAINGAME ) \
- HUD_PANEL(SCORE , HUD_Score , score, PANEL_SHOW_ALWAYS ) \
- HUD_PANEL(RACETIMER , HUD_RaceTimer , racetimer, PANEL_SHOW_MAINGAME ) \
- HUD_PANEL(VOTE , HUD_Vote , vote, PANEL_SHOW_ALWAYS ) \
- HUD_PANEL(MODICONS , HUD_ModIcons , modicons, PANEL_SHOW_MAINGAME ) \
- HUD_PANEL(PRESSEDKEYS , HUD_PressedKeys , pressedkeys, PANEL_SHOW_MAINGAME ) \
- HUD_PANEL(CHAT , HUD_Chat , chat, PANEL_SHOW_ALWAYS ) \
- HUD_PANEL(ENGINEINFO , HUD_EngineInfo , engineinfo, PANEL_SHOW_ALWAYS ) \
- HUD_PANEL(INFOMESSAGES , HUD_InfoMessages , infomessages, PANEL_SHOW_MAINGAME ) \
- HUD_PANEL(PHYSICS , HUD_Physics , physics, PANEL_SHOW_MAINGAME ) \
- HUD_PANEL(CENTERPRINT , HUD_CenterPrint , centerprint, PANEL_SHOW_MAINGAME ) \
- HUD_PANEL(MINIGAME_BOARD, HUD_MinigameBoard ,minigameboard, PANEL_SHOW_MINIGAME ) \
- HUD_PANEL(MINIGAME_STATUS,HUD_MinigameStatus,minigamestatus,PANEL_SHOW_MINIGAME ) \
- HUD_PANEL(MINIGAME_HELP, HUD_MinigameHelp ,minigamehelp, PANEL_SHOW_MINIGAME ) \
- HUD_PANEL(MINIGAME_MENU, HUD_MinigameMenu ,minigamemenu, PANEL_SHOW_ALWAYS ) \
- HUD_PANEL(MAPVOTE , MapVote_Draw ,mapvote, PANEL_SHOW_ALWAYS ) \
- HUD_PANEL(ITEMSTIME , HUD_ItemsTime ,itemstime, PANEL_SHOW_MAINGAME ) \
- HUD_PANEL(QUICKMENU , HUD_QuickMenu , quickmenu, PANEL_SHOW_MAINGAME ) \
- // always add new panels to the end of list
-
-
-#define HUD_PANEL(NAME, draw_func, name, showflags) \
- int HUD_PANEL_##NAME; \
- void draw_func(void); \
- void RegisterHUD_Panel_##NAME() { \
- HUD_PANEL_LAST = HUD_PANEL_##NAME = HUD_PANEL_NUM; \
- entity hud_panelent = spawn(); \
- hud_panel[HUD_PANEL_##NAME] = hud_panelent; \
- hud_panelent.classname = "hud_panel"; \
- hud_panelent.panel_name = #name; \
- hud_panelent.panel_id = HUD_PANEL_##NAME; \
- hud_panelent.panel_draw = draw_func; \
- hud_panelent.panel_showflags = showflags; \
- HUD_PANEL_NUM++; \
- } \
- ACCUMULATE_FUNCTION(RegisterHUD_Panels, RegisterHUD_Panel_##NAME);
-
-HUD_PANELS(HUD_PANEL)
-#undef HUD_PANEL
-
-#define HUD_PANEL(NAME) hud_panel[HUD_PANEL_##NAME]
-
+REGISTER_HUD_PANEL(WEAPONS, HUD_Weapons, weapons, PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(AMMO, HUD_Ammo, ammo, PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(POWERUPS, HUD_Powerups, powerups, PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(HEALTHARMOR, HUD_HealthArmor, healtharmor, PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(NOTIFY, HUD_Notify, notify, PANEL_SHOW_ALWAYS )
+REGISTER_HUD_PANEL(TIMER, HUD_Timer, timer, PANEL_SHOW_ALWAYS )
+REGISTER_HUD_PANEL(RADAR, HUD_Radar, radar, PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(SCORE, HUD_Score, score, PANEL_SHOW_ALWAYS )
+REGISTER_HUD_PANEL(RACETIMER, HUD_RaceTimer, racetimer, PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(VOTE, HUD_Vote, vote, PANEL_SHOW_ALWAYS )
+REGISTER_HUD_PANEL(MODICONS, HUD_ModIcons, modicons, PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(PRESSEDKEYS, HUD_PressedKeys, pressedkeys, PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(CHAT, HUD_Chat, chat, PANEL_SHOW_ALWAYS )
+REGISTER_HUD_PANEL(ENGINEINFO, HUD_EngineInfo, engineinfo, PANEL_SHOW_ALWAYS )
+REGISTER_HUD_PANEL(INFOMESSAGES, HUD_InfoMessages, infomessages, PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(PHYSICS, HUD_Physics, physics, PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(CENTERPRINT, HUD_CenterPrint, centerprint, PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(MINIGAME_BOARD, HUD_MinigameBoard, minigameboard, PANEL_SHOW_MINIGAME)
+REGISTER_HUD_PANEL(MINIGAME_STATUS, HUD_MinigameStatus, minigamestatus, PANEL_SHOW_MINIGAME)
+REGISTER_HUD_PANEL(MINIGAME_HELP, HUD_MinigameHelp, minigamehelp, PANEL_SHOW_MINIGAME)
+REGISTER_HUD_PANEL(MINIGAME_MENU, HUD_MinigameMenu, minigamemenu, PANEL_SHOW_ALWAYS )
+REGISTER_HUD_PANEL(MAPVOTE, MapVote_Draw, mapvote, PANEL_SHOW_ALWAYS )
+REGISTER_HUD_PANEL(ITEMSTIME, HUD_ItemsTime, itemstime, PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(QUICKMENU, HUD_QuickMenu, quickmenu, PANEL_SHOW_MAINGAME)
+// always add new panels to the end of list
// Because calling lots of functions in QC apparently cuts fps in half on many machines:
// ----------------------
HUD_Write("\n");
// common cvars for all panels
- int i;
- for (i = 0; i < HUD_PANEL_NUM; ++i)
+ for (int i = 0; i < hud_panels_COUNT; ++i)
{
- panel = hud_panel[i];
+ panel = hud_panels[i];
HUD_Write_PanelCvar_n("");
HUD_Write_PanelCvar_q("_pos");
HUD_Write_PanelCvar_q("_bg_alpha");
HUD_Write_PanelCvar_q("_bg_border");
HUD_Write_PanelCvar_q("_bg_padding");
- switch(i) {
+ switch(panel) {
case HUD_PANEL_WEAPONS:
HUD_Write_PanelCvar_q("_accuracy");
HUD_Write_PanelCvar_q("_label");
vector myCenter, targCenter;
vector myTarget = myPos;
int i;
- for (i = 0; i < HUD_PANEL_NUM; ++i) {
- panel = hud_panel[i];
+ for (i = 0; i < hud_panels_COUNT; ++i) {
+ panel = hud_panels[i];
if(panel == HUD_PANEL(MAPVOTE)) continue;
if(panel == highlightedPanel) continue;
HUD_Panel_UpdatePosSize();
vector dist;
float ratio = mySize.x/mySize.y;
int i;
- for (i = 0; i < HUD_PANEL_NUM; ++i) {
- panel = hud_panel[i];
+ for (i = 0; i < hud_panels_COUNT; ++i) {
+ panel = hud_panels[i];
if(panel == HUD_PANEL(MAPVOTE)) continue;
if(panel == highlightedPanel) continue;
HUD_Panel_UpdatePosSize();
}
void HUD_Panel_EnableMenu();
-entity tab_panels[HUD_PANEL_MAX];
+entity tab_panels[hud_panels_MAX];
entity tab_panel;
vector tab_panel_pos;
float tab_backward;
void reset_tab_panels()
{
int i;
- for(i = 0; i < HUD_PANEL_NUM; ++i)
+ for(i = 0; i < hud_panels_COUNT; ++i)
tab_panels[i] = world;
}
float HUD_Panel_InputEvent(float bInputType, float nPrimary, float nSecondary)
k=0;
while(++k)
{
- for(i = 0; i < HUD_PANEL_NUM; ++i)
+ for(i = 0; i < hud_panels_COUNT; ++i)
{
- panel = hud_panel[i];
+ panel = hud_panels[i];
if(panel == HUD_PANEL(MAPVOTE))
continue;
if (panel == tab_panels[i] || panel == starting_panel)
float HUD_Panel_Check_Mouse_Pos(float allow_move)
{
int i, j = 0;
- while(j < HUD_PANEL_NUM)
+ while(j < hud_panels_COUNT)
{
i = panel_order[j];
j += 1;
- panel = hud_panel[i];
+ panel = hud_panels[i];
if(panel == HUD_PANEL(MAPVOTE)) continue;
HUD_Panel_UpdatePosSize();
int i;
int place = -1;
// find out where in the array our current id is, save into place
- for(i = 0; i < HUD_PANEL_NUM; ++i)
+ for(i = 0; i < hud_panels_COUNT; ++i)
{
if(panel_order[i] == id)
{
}
// place last if we didn't find a place for it yet (probably new panel, or screwed up cvar)
if(place == -1)
- place = HUD_PANEL_NUM - 1;
+ place = hud_panels_COUNT - 1;
// move all ids up by one step in the array until "place"
for(i = place; i > 0; --i)
// let's save them into the cvar by some strcat trickery
string s = "";
- for(i = 0; i < HUD_PANEL_NUM; ++i)
+ for(i = 0; i < hud_panels_COUNT; ++i)
{
s = strcat(s, ftos(panel_order[i]), " ");
}
{
int i, j = 0;
- while(j < HUD_PANEL_NUM)
+ while(j < hud_panels_COUNT)
{
i = panel_order[j];
j += 1;
- panel = hud_panel[i];
+ panel = hud_panels[i];
if(panel == HUD_PANEL(MAPVOTE))
continue;
HUD_Panel_UpdatePosSize();
// move
if(allow_move && mousepos.x > panel_pos.x && mousepos.y > panel_pos.y && mousepos.x < panel_pos.x + panel_size.x && mousepos.y < panel_pos.y + panel_size.y)
{
- highlightedPanel = hud_panel[i];
+ highlightedPanel = hud_panels[i];
HUD_Panel_FirstInDrawQ(i);
highlightedAction = 1;
panel_click_distance = mousepos - panel_pos;
// resize from topleft border
else if(mousepos.x >= panel_pos.x - border && mousepos.y >= panel_pos.y - border && mousepos.x <= panel_pos.x + 0.5 * panel_size.x && mousepos.y <= panel_pos.y + 0.5 * panel_size.y)
{
- highlightedPanel = hud_panel[i];
+ highlightedPanel = hud_panels[i];
HUD_Panel_FirstInDrawQ(i);
highlightedAction = 2;
resizeCorner = 1;
// resize from topright border
else if(mousepos.x >= panel_pos.x + 0.5 * panel_size.x && mousepos.y >= panel_pos.y - border && mousepos.x <= panel_pos.x + panel_size.x + border && mousepos.y <= panel_pos.y + 0.5 * panel_size.y)
{
- highlightedPanel = hud_panel[i];
+ highlightedPanel = hud_panels[i];
HUD_Panel_FirstInDrawQ(i);
highlightedAction = 2;
resizeCorner = 2;
// resize from bottomleft border
else if(mousepos.x >= panel_pos.x - border && mousepos.y >= panel_pos.y + 0.5 * panel_size.y && mousepos.x <= panel_pos.x + 0.5 * panel_size.x && mousepos.y <= panel_pos.y + panel_size.y + border)
{
- highlightedPanel = hud_panel[i];
+ highlightedPanel = hud_panels[i];
HUD_Panel_FirstInDrawQ(i);
highlightedAction = 2;
resizeCorner = 3;
// resize from bottomright border
else if(mousepos.x >= panel_pos.x + 0.5 * panel_size.x && mousepos.y >= panel_pos.y + 0.5 * panel_size.y && mousepos.x <= panel_pos.x + panel_size.x + border && mousepos.y <= panel_pos.y + panel_size.y + border)
{
- highlightedPanel = hud_panel[i];
+ highlightedPanel = hud_panels[i];
HUD_Panel_FirstInDrawQ(i);
highlightedAction = 2;
resizeCorner = 4;
if(autocvar_hud_cursormode)
setcursormode(1);
hudShiftState = 0;
- for(i = HUD_PANEL_NUM - 1; i >= 0; --i)
- hud_panel[panel_order[i]].update_time = time;
+ for(i = hud_panels_COUNT - 1; i >= 0; --i)
+ hud_panels[panel_order[i]].update_time = time;
}
// NOTE this check is necessary because _menu_alpha isn't updated the frame the menu gets enabled
#include "hook.qh"
-#include "../common/buffs.qh"
+#include "../common/buffs/all.qh"
#include "../csqcmodellib/cl_model.qh"
#include "../csqcmodellib/interpolate.qh"
class(Laser) .float scale; // scaling factor of the thickness
class(Laser) .float modelscale; // scaling factor of the dlight
-void Draw_Laser()
+void Draw_Laser(entity this)
{
if(!self.state)
return;
#include "_all.qh"
#include "controlpoint.qh"
-#include "csqcmodel_hooks.qh"
#include "damage.qh"
#include "effects.qh"
#include "generator.qh"
#include "weapons/projectile.qh"
-#include "../common/buffs.qh"
+#include "../common/buffs/all.qh"
#include "../common/deathtypes.qh"
-#include "../common/effects.qh"
+#include "../common/effects/effects.qh"
#include "../common/mapinfo.qh"
#include "../common/monsters/all.qh"
-#include "../common/nades.qh"
+#include "../common/nades/all.qh"
#include "../common/net_notice.qh"
#include "../common/notifications.qh"
#include "../common/stats.qh"
#include "../common/triggers/include.qh"
#include "../common/turrets/cl_turrets.qh"
-#include "../common/turrets/turrets.qh"
#include "../warpzonelib/client.qh"
{
}
+void draw_null(entity this) { }
+
string forcefog;
void ConsoleCommand_macro_init();
void CSQC_Init(void)
registercvar("cl_jumpspeedcap_min", "");
registercvar("cl_jumpspeedcap_max", "");
- registercvar("cl_multijump", "1");
+ registercvar("cl_multijump", "0");
registercvar("cl_spawn_near_teammate", "1");
// needs to be done so early because of the constants they create
static_init();
- CALL_ACCUMULATED_FUNCTION(RegisterTurrets);
CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
- CALL_ACCUMULATED_FUNCTION(RegisterHUD_Panels);
-
- initialize_minigames();
// precaches
- precache_model("null");
- precache_sound("misc/hit.wav");
- precache_sound("misc/typehit.wav");
- generator_precache();
Projectile_Precache();
- Hook_Precache();
- GibSplash_Precache();
Tuba_Precache();
- CSQCPlayer_Precache();
if(autocvar_cl_reticle)
{
}
void Playerchecker_Think()
-{
+{SELFPARAM();
int i;
entity e;
for(i = 0; i < maxclients; ++i)
// BEGIN OPTIONAL CSQC FUNCTIONS
void Ent_RemoveEntCS()
-{
- entcs_receiver[self.sv_entnum] = world;
+{SELFPARAM();
+ entcs_receiver[self.sv_entnum] = NULL;
}
void Ent_ReadEntCS()
-{
- int sf;
+{SELFPARAM();
InterpolateOrigin_Undo();
-
self.classname = "entcs_receiver";
- sf = ReadByte();
+ int sf = ReadByte();
- if(sf & 1)
+ if(sf & BIT(0))
self.sv_entnum = ReadByte();
- if(sf & 2)
+ if (sf & BIT(1))
{
self.origin_x = ReadShort();
self.origin_y = ReadShort();
self.origin_z = ReadShort();
setorigin(self, self.origin);
}
- if(sf & 4)
+ if (sf & BIT(2))
{
self.angles_y = ReadByte() * 360.0 / 256;
self.angles_x = self.angles_z = 0;
}
- if(sf & 8)
+ if (sf & BIT(3))
self.healthvalue = ReadByte() * 10;
- if(sf & 16)
+ if (sf & BIT(4))
self.armorvalue = ReadByte() * 10;
entcs_receiver[self.sv_entnum] = self;
void Ent_Remove();
void Ent_RemovePlayerScore()
-{
+{SELFPARAM();
if(self.owner) {
SetTeam(self.owner, -1);
self.owner.gotscores = 0;
}
void Ent_ReadPlayerScore()
-{
+{SELFPARAM();
int i, n;
bool isNew;
entity o;
}
void Ent_ReadTeamScore()
-{
+{SELFPARAM();
int i;
entity o;
}
}
-void Spawn_Draw(void)
+void Spawn_Draw(entity this)
{
- pointparticles(self.cnt, self.origin + '0 0 28', '0 0 2', bound(0, frametime, 0.1));
+ pointparticles(this.cnt, this.origin + '0 0 28', '0 0 2', bound(0, frametime, 0.1));
}
void Ent_ReadSpawnPoint(float is_new) // entity for spawnpoint
-{
+{SELFPARAM();
float teamnum = (ReadByte() - 1);
vector spn_origin;
spn_origin.x = ReadShort();
}
void Ent_ReadSpawnEvent(float is_new)
-{
+{SELFPARAM();
// If entnum is 0, ONLY do the local spawn actions
// this way the server can disable the sending of
// spawn origin or such to clients if wanted.
}
if(autocvar_cl_spawn_event_sound)
{
- sound(self, CH_TRIGGER, "misc/spawn.wav", VOL_BASE, ATTEN_NORM);
+ sound(self, CH_TRIGGER, SND_SPAWN, VOL_BASE, ATTEN_NORM);
}
}
}
void Ent_Init();
void Ent_ScoresInfo();
void CSQC_Ent_Update(float bIsNewEntity)
-{
- float t;
- float savetime;
- t = ReadByte();
+{SELFPARAM();
+ int t = ReadByte();
if(autocvar_developer_csqcentities)
LOG_INFOF("CSQC_Ent_Update(%d) with self=%i self.entnum=%d self.enttype=%d t=%d\n", bIsNewEntity, self, self.entnum, self.enttype, t);
// set up the "time" global for received entities to be correct for interpolation purposes
- savetime = time;
+ float savetime = time;
if(servertime)
{
time = servertime;
{
if(t != self.enttype || bIsNewEntity)
{
- //print("A CSQC entity changed its type!\n");
LOG_INFOF("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)\n", num_for_edict(self), self.entnum, self.enttype, t);
Ent_Remove();
clearentity(self);
}
#endif
self.enttype = t;
+ bool done = false;
+ FOREACH(LinkedEntities, it.m_id == t, LAMBDA(
+ it.m_read(self, bIsNewEntity);
+ done = true;
+ break;
+ ));
+ if (!done)
switch(t)
{
case ENT_CLIENT_MUTATOR: {
case ENT_CLIENT_AUXILIARYXHAIR: Net_AuXair2(bIsNewEntity); break;
case ENT_CLIENT_TURRET: ent_turret(); break;
case ENT_CLIENT_GENERATOR: ent_generator(); break;
- case ENT_CLIENT_CONTROLPOINT_ICON: ent_cpicon(); break;
+ case ENT_CLIENT_CONTROLPOINT_ICON: ent_cpicon(this); break;
case ENT_CLIENT_MODEL: CSQCModel_Read(bIsNewEntity); break;
case ENT_CLIENT_ITEM: ItemRead(bIsNewEntity); break;
case ENT_CLIENT_BUMBLE_RAYGUN: bumble_raygun_read(bIsNewEntity); break;
case ENT_CLIENT_SPAWNPOINT: Ent_ReadSpawnPoint(bIsNewEntity); break;
case ENT_CLIENT_SPAWNEVENT: Ent_ReadSpawnEvent(bIsNewEntity); break;
case ENT_CLIENT_NOTIFICATION: Read_Notification(bIsNewEntity); break;
- case ENT_CLIENT_HEALING_ORB: ent_healer(); break;
case ENT_CLIENT_MINIGAME: ent_read_minigame(); break;
case ENT_CLIENT_VIEWLOC: ent_viewloc(); break;
case ENT_CLIENT_VIEWLOC_TRIGGER: ent_viewloc_trigger(); break;
// used when an entity changes its type. For an entity that someone interacts
// with others, make sure it can no longer do so.
void Ent_Remove()
-{
+{SELFPARAM();
if(self.entremove)
self.entremove();
if(self.snd_looping > 0)
{
- sound(self, self.snd_looping, "misc/null.wav", VOL_BASE, autocvar_g_jetpack_attenuation);
+ sound(self, self.snd_looping, SND_Null, VOL_BASE, autocvar_g_jetpack_attenuation);
self.snd_looping = 0;
}
self.enttype = 0;
self.classname = "";
- self.draw = menu_sub_null;
+ self.draw = draw_null;
self.entremove = menu_sub_null;
// TODO possibly set more stuff to defaults
}
// CSQC_Ent_Remove : Called when the server requests a SSQC / CSQC entity to be removed. Essentially call remove(self) as well.
void CSQC_Ent_Remove()
-{
+{SELFPARAM();
if(autocvar_developer_csqcentities)
LOG_INFOF("CSQC_Ent_Remove() with self=%i self.entnum=%d self.enttype=%d\n", self, self.entnum, self.enttype);
if(autocvar_developer_csqcentities)
LOG_INFOF("CSQC_Parse_Print(\"%s\")\n", strMessage);
- LOG_INFO(ColorTranslateRGB(strMessage));
+ print(ColorTranslateRGB(strMessage));
}
// CSQC_Parse_CenterPrint : Provides the centerprint_hud string in the first parameter that the server provided.
void Gamemode_Init();
void Ent_ScoresInfo()
-{
+{SELFPARAM();
int i;
self.classname = "ent_client_scores_info";
gametype = ReadInt24_t();
}
void Ent_Init()
-{
+{SELFPARAM();
self.classname = "ent_client_init";
nb_pb_period = ReadByte() / 32; //Accuracy of 1/32th
// CSQC_Parse_TempEntity : Handles all temporary entity network data in the CSQC layer.
// You must ALWAYS first acquire the temporary ID, which is sent as a byte.
// Return value should be 1 if CSQC handled the temporary entity, otherwise return 0 to have the engine process the event.
-float CSQC_Parse_TempEntity()
+bool CSQC_Parse_TempEntity()
{
// Acquire TE ID
int nTEID = ReadByte();
if (autocvar_developer_csqcentities)
LOG_INFOF("CSQC_Parse_TempEntity() with nTEID=%d\n", nTEID);
+ FOREACH(TempEntities, it.m_id == nTEID, LAMBDA(
+ it.m_read(NULL, true);
+ return true;
+ ));
switch (nTEID)
{
case TE_CSQC_MUTATOR:
.float ready;
.float eliminated;
-.void(void) draw;
-.void(void) draw2d;
+.void(entity) draw;
+.void(entity) draw2d;
.void(void) entremove;
float drawframetime;
vector view_origin, view_forward, view_right, view_up;
void MapVote_Init()
{
- precache_sound ("misc/invshot.wav");
-
mv_active = 1;
if(autocvar_hud_cursormode) { setcursormode(1); }
else { mv_mousepos = '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight; }
.float scale;
.float alpha;
-void ModelEffect_Draw()
+void ModelEffect_Draw(entity this)
{
self.angles = self.angles + frametime * self.avelocity;
setorigin(self, self.origin + frametime * self.velocity);
}
void Ent_ModelEffect(bool isNew)
-{
+{SELFPARAM();
self.classname = "modeleffect_spawner";
int f = ReadByte();
class(ModelEffect) .float teleport_time;
class(ModelEffect) .float scale1, scale2;
-void ModelEffect_Draw();
+void ModelEffect_Draw(entity this);
void Ent_ModelEffect(bool isNew);
#endif
/** Called when a projectile is linked with CSQC */
#define EV_Ent_Projectile(i, o) \
- /** entity id */ i(entity, self) \
+ /** entity id */ i(entity, __self) \
/**/
MUTATOR_HOOKABLE(Ent_Projectile, EV_Ent_Projectile);
/** Called when a projectile's properties are being modified */
#define EV_EditProjectile(i, o) \
- /** entity id */ i(entity, self) \
+ /** entity id */ i(entity, __self) \
/**/
MUTATOR_HOOKABLE(EditProjectile, EV_EditProjectile);
/** Called when updating the attached tags index */
#define EV_TagIndex_Update(i, o) \
- /** entity id */ i(entity, self) \
+ /** entity id */ i(entity, __self) \
/**/
MUTATOR_HOOKABLE(TagIndex_Update, EV_TagIndex_Update);
/** Called when setting the attached tags */
#define EV_TagIndex_Apply(i, o) \
- /** entity id */ i(entity, self) \
+ /** entity id */ i(entity, __self) \
/**/
MUTATOR_HOOKABLE(TagIndex_Apply, EV_TagIndex_Apply);
/** Called when setting up skeleton bones */
#define EV_Skeleton_CheckBones(i, o) \
- /** entity id */ i(entity, self) \
+ /** entity id */ i(entity, __self) \
/**/
MUTATOR_HOOKABLE(Skeleton_CheckBones, EV_Skeleton_CheckBones);
/** Called when setting up bones from the loaded model */
#define EV_Skeleton_CheckModel(i, o) \
- /** entity id */ i(entity, self) \
+ /** entity id */ i(entity, __self) \
/**/
MUTATOR_HOOKABLE(Skeleton_CheckModel, EV_Skeleton_CheckModel);
/** Called checking if 3rd person mode should be forced on */
#define EV_WantEventchase(i, o) \
- /** entity id */ i(entity, self) \
+ /** entity id */ i(entity, __self) \
/**/
MUTATOR_HOOKABLE(WantEventchase, EV_WantEventchase);
class(PointParticles) .float absolute; // 1 = count per second is absolute, 2 = only spawn at toggle
class(PointParticles) .vector movedir; // trace direction
-void Draw_PointParticles();
+void Draw_PointParticles(entity this);
void Ent_PointParticles_Remove();
}
void skeleton_from_frames(entity e, float is_dead)
-{
+{SELFPARAM();
float m = e.modelindex;
if(!e.skeletonindex)
{
--- /dev/null
+#include "../common/util-pre.qh"
+#include "../dpdefs/csprogsdefs.qh"
+#include "../common/util-post.qh"
+
+#include "../lib/_all.inc"
+
+#include "announcer.qc"
+#include "bgmscript.qc"
+#include "controlpoint.qc"
+#include "csqcmodel_hooks.qc"
+#include "damage.qc"
+#include "effects.qc"
+#include "generator.qc"
+#include "gibs.qc"
+#include "hook.qc"
+#include "hud.qc"
+#include "hud_config.qc"
+#include "main.qc"
+#include "mapvoting.qc"
+#include "miscfunctions.qc"
+#include "modeleffects.qc"
+#include "movelib.qc"
+#include "particles.qc"
+#include "player_skeleton.qc"
+#include "rubble.qc"
+#include "scoreboard.qc"
+#include "shownames.qc"
+#include "teamradar.qc"
+#include "tuba.qc"
+#include "t_items.qc"
+#include "view.qc"
+#include "wall.qc"
+
+#include "command/all.qc"
+
+#include "weapons/projectile.qc" // TODO
+
+#include "../common/animdecide.qc"
+#include "../common/effects/effects.qc"
+#include "../common/effects/effectinfo.qc"
+#include "../common/mapinfo.qc"
+#include "../common/movetypes/include.qc"
+#include "../common/net_notice.qc"
+#include "../common/notifications.qc"
+#include "../common/physics.qc"
+#include "../common/playerstats.qc"
+#include "../common/util.qc"
+
+#include "../common/viewloc.qc"
+
+#include "../common/minigames/minigames.qc"
+#include "../common/minigames/cl_minigames.qc"
+
+#include "../common/buffs/all.qc"
+#include "../common/items/all.qc"
+#include "../common/monsters/all.qc"
+#include "../common/mutators/all.qc"
+#include "../common/nades/all.qc"
+#include "../common/turrets/all.qc"
+#include "../common/vehicles/all.qc"
+#include "../common/weapons/all.qc"
+
+#include "../common/turrets/cl_turrets.qc"
+
+#include "../common/triggers/include.qc"
+
+#include "../csqcmodellib/cl_model.qc"
+#include "../csqcmodellib/cl_player.qc"
+#include "../csqcmodellib/interpolate.qc"
+
+#include "../server/mutators/mutator_multijump.qc"
+
+#include "../warpzonelib/anglestransform.qc"
+#include "../warpzonelib/client.qc"
+#include "../warpzonelib/common.qc"
+#include "../warpzonelib/util_server.qc"
+
+#if BUILD_MOD
+#include "../../mod/client/progs.inc"
+#endif
../../csprogs.dat
-
-../common/util-pre.qh
-../dpdefs/csprogsdefs.qh
-../common/util-post.qh
-
-../lib/_all.inc
-
-announcer.qc
-bgmscript.qc
-controlpoint.qc
-csqcmodel_hooks.qc
-damage.qc
-effects.qc
-generator.qc
-gibs.qc
-hook.qc
-hud.qc
-hud_config.qc
-main.qc
-mapvoting.qc
-miscfunctions.qc
-modeleffects.qc
-movelib.qc
-particles.qc
-player_skeleton.qc
-rubble.qc
-scoreboard.qc
-shownames.qc
-teamradar.qc
-tuba.qc
-t_items.qc
-view.qc
-wall.qc
-
-command/all.qc
-
-weapons/projectile.qc // TODO
-
-../common/animdecide.qc
-../common/buffs.qc
-../common/effects.qc
-../common/mapinfo.qc
-../common/movetypes/include.qc
-../common/nades.qc
-../common/net_notice.qc
-../common/notifications.qc
-../common/physics.qc
-../common/playerstats.qc
-../common/util.qc
-
-../common/viewloc.qc
-
-../common/minigames/minigames.qc
-../common/minigames/cl_minigames.qc
-
-../common/items/all.qc
-../common/monsters/all.qc
-../common/mutators/all.qc
-../common/vehicles/all.qc
-../common/weapons/all.qc
-
-../common/turrets/cl_turrets.qc
-../common/turrets/turrets.qc
-
-../common/triggers/include.qc
-
-../csqcmodellib/cl_model.qc
-../csqcmodellib/cl_player.qc
-../csqcmodellib/interpolate.qc
-
-../server/mutators/mutator_multijump.qc
-
-../warpzonelib/anglestransform.qc
-../warpzonelib/client.qc
-../warpzonelib/common.qc
-../warpzonelib/util_server.qc
-
-../../mod/client/progs.inc
+progs.inc
{
if(argv(1) == "")
continue;
- QuickMenu_Buffer_Set(QM_TAG_TITLE, argv(0));
+ QuickMenu_Buffer_Set(QM_TAG_TITLE, argv(0));
++QuickMenu_Buffer_Size;
QuickMenu_Buffer_Set(QM_TAG_COMMAND, argv(1));
}
setcursormode(1);
hudShiftState = 0;
- QuickMenu_TimeOut = time + autocvar_hud_panel_quickmenu_time;
+ QuickMenu_TimeOut = ((autocvar_hud_panel_quickmenu_time > 0) ? time + autocvar_hud_panel_quickmenu_time : 0);
return true;
}
QuickMenu_Close();
return false;
}
- QuickMenu_TimeOut = time + autocvar_hud_panel_quickmenu_time;
+ QuickMenu_TimeOut = ((autocvar_hud_panel_quickmenu_time > 0) ? time + autocvar_hud_panel_quickmenu_time : 0);
return true;
}
if (QuickMenu_Page_Command[num] != "")
{
localcmd(strcat("\n", QuickMenu_Page_Command[num], "\n"));
- QuickMenu_TimeOut = time + autocvar_hud_panel_quickmenu_time;
+ QuickMenu_TimeOut = ((autocvar_hud_panel_quickmenu_time > 0) ? time + autocvar_hud_panel_quickmenu_time : 0);
return true;
}
if (QuickMenu_Page_Description[num] != "")
//if(!autocvar_hud_panel_quickmenu) return;
if(!hud_panel_quickmenu) return;
+ if(QuickMenu_TimeOut)
if(time > QuickMenu_TimeOut)
{
QuickMenu_Close();
QUICKMENU_ENTRY_TC(CTX(_("QMCMD^killed flag, icon")), "say_team %s; g_waypointsprite_team_here_p", "killed flagcarrier (l:%y^7)", CTX(_("QMCMD^killed flagcarrier (l:%y^7)")))
QUICKMENU_ENTRY_TC(CTX(_("QMCMD^dropped flag, icon")), "say_team %s; g_waypointsprite_team_here_d", "dropped flag (l:%d^7)", CTX(_("QMCMD^dropped flag (l:%d^7)")))
QUICKMENU_ENTRY_TC(CTX(_("QMCMD^drop gun, icon")), "say_team %s; g_waypointsprite_team_here; wait; dropweapon", "dropped gun %w^7 (l:%l^7)", CTX(_("QMCMD^dropped gun %w^7 (l:%l^7)")))
- QUICKMENU_ENTRY_TC(CTX(_("QMCMD^drop flag/key, icon")), "say_team %s; g_waypointsprite_team_here; wait; +use", "dropped flag/key %w^7 (l:%l^7)", CTX(_("QMCMD^dropped flag/key %w^7 (l:%l^7)")))
+ QUICKMENU_ENTRY_TC(CTX(_("QMCMD^drop flag/key, icon")), "say_team %s; g_waypointsprite_team_here; wait; use", "dropped flag/key %w^7 (l:%l^7)", CTX(_("QMCMD^dropped flag/key %w^7 (l:%l^7)")))
QUICKMENU_SMENU(CTX(_("QMCMD^Team chat")), "Team chat")
}
// LordHavoc: rewrote this file, it was really bad code
void RubbleLimit(string cname, float limit, void() deleteproc)
-{
+{SELFPARAM();
entity e;
entity oldest;
- entity oldself;
float c;
float oldesttime;
- oldself = self;
-
// remove rubble of the same type if it's at the limit
// remove multiple rubble if the limit has been decreased
while(1)
break;
// delete this oldest one and search again
- self = oldest;
- deleteproc();
- self = oldself;
+ WITH(entity, self, oldest, deleteproc());
}
}
float average_accuracy;
vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
-{
+{SELFPARAM();
WepSet weapons_stat = WepSet_GetFromStat();
WepSet weapons_inmap = WepSet_GetFromStat_InMap();
float initial_posx = pos.x;
int disownedcnt = 0;
for(i = WEP_FIRST; i <= WEP_LAST; ++i)
{
- self = get_weaponinfo(i);
+ setself(get_weaponinfo(i));
if(!self.weapon)
continue;
++disownedcnt;
}
- int weapon_cnt = WEP_COUNT - disownedcnt;
+ int weapon_cnt = (Weapons_COUNT - 1) - disownedcnt;
if(weapon_cnt <= 0)
return pos;
int rows;
- if(autocvar_scoreboard_accuracy_doublerows && weapon_cnt >= floor(WEP_COUNT * 0.5))
+ if(autocvar_scoreboard_accuracy_doublerows && weapon_cnt >= floor((Weapons_COUNT - 1) * 0.5))
rows = 2;
else
rows = 1;
int column;
for(i = WEP_FIRST, column = 0; i <= WEP_LAST; ++i)
{
- self = get_weaponinfo(i);
+ setself(get_weaponinfo(i));
if (!self.weapon)
continue;
weapon_stats = weapon_accuracy[i-WEP_FIRST];
#include "_all.qh"
-#include "../common/buffs.qh"
+#include "../common/buffs/all.qh"
#include "../common/movetypes/movetypes.qh"
#include "../common/util.qh"
#include "../common/weapons/all.qh"
R_EndPolygon();
}
-void draw_teamradar_icon(vector coord, float icon, entity pingdata, vector rgb, float a)
+void draw_teamradar_icon(vector coord, entity icon, entity pingdata, vector rgb, float a)
{
coord = teamradar_texcoord_to_2dcoord(teamradar_3dcoord_to_texcoord(coord));
- drawpic(coord - '4 4 0', strcat("gfx/teamradar_icon_", ftos(icon)), '8 8 0', rgb, a, 0);
+ drawpic(coord - '4 4 0', strcat("gfx/teamradar_icon_", ftos(icon.m_radaricon)), '8 8 0', rgb, a, 0);
if(pingdata)
{
// radar links
void Ent_RadarLink()
-{
+{SELFPARAM();
int sendflags = ReadByte();
InterpolateOrigin_Undo();
void draw_teamradar_player(vector coord3d, vector pangles, vector rgb);
-void draw_teamradar_icon(vector coord, float icon, entity pingdata, vector rgb, float a);
+void draw_teamradar_icon(vector coord, entity icon, entity pingdata, vector rgb, float a);
void draw_teamradar_link(vector start, vector end, int colors);
if (restart) {
snd1 = TUBA_STARTNOTE(e.tuba_instrument, e.note);
}
- sound(e, CH_TUBA_SINGLE, snd1, e.tuba_volume, e.tuba_attenuate * autocvar_g_balance_tuba_attenuation);
+ _sound(e, CH_TUBA_SINGLE, snd1, e.tuba_volume, e.tuba_attenuate * autocvar_g_balance_tuba_attenuation);
}
}
void Ent_TubaNote_Think()
-{
+{SELFPARAM();
float f = autocvar_g_balance_tuba_fadetime;
if (f > 0) {
self.tuba_volume -= frametime * self.tuba_volume_initial / f;
}
self.nextthink = time;
if (self.tuba_volume <= 0) {
- sound(self, CH_TUBA_SINGLE, "misc/null.wav", 0, 0);
+ sound(self, CH_TUBA_SINGLE, SND_Null, 0, 0);
if (self.enemy) {
- sound(self.enemy, CH_TUBA_SINGLE, "misc/null.wav", 0, 0);
+ sound(self.enemy, CH_TUBA_SINGLE, SND_Null, 0, 0);
remove(self.enemy);
}
remove(self);
}
void Ent_TubaNote_UpdateSound()
-{
+{SELFPARAM();
self.enemy.tuba_volume = bound(0, VOL_BASE * autocvar_g_balance_tuba_volume, 1);
self.enemy.tuba_volume_initial = self.enemy.tuba_volume;
self.enemy.note = self.note;
}
void Ent_TubaNote_StopSound()
-{
+{SELFPARAM();
self.enemy.nextthink = time;
self.enemy = world;
}
void Ent_TubaNote(bool isNew)
-{
+{SELFPARAM();
bool upd = false;
int f = ReadByte();
if (f & 1) {
#include "../common/constants.qh"
#include "../common/mapinfo.qh"
-#include "../common/nades.qh"
+#include "../common/nades/all.qh"
#include "../common/stats.qh"
#include "../common/triggers/target/music.qh"
#include "../common/teams.qh"
entity porto;
vector polyline[16];
-void Porto_Draw()
+void Porto_Draw(entity this)
{
vector p, dir, ang, q, nextdir;
float portal_number, portal1_idx;
{
case WEP_TUBA.m_id: // no aim
case WEP_PORTO.m_id: // shoots from eye
+ case WEP_NEXBALL.m_id: // shoots from eye
case WEP_HOOK.m_id: // no trueaim
case WEP_MORTAR.m_id: // toss curve
return SHOTTYPE_HITWORLD;
float eventchase_current_distance;
float eventchase_running;
bool WantEventchase()
-{
+{SELFPARAM();
if(autocvar_cl_orthoview)
return false;
if(intermission)
return true;
if(MUTATOR_CALLHOOK(WantEventchase, self))
return true;
- if(autocvar_cl_eventchase_nexball && gametype == MAPINFO_TYPE_NEXBALL && !(WepSet_GetFromStat() & WepSet_FromWeapon(WEP_PORTO.m_id)))
+ if(autocvar_cl_eventchase_nexball && gametype == MAPINFO_TYPE_NEXBALL && !(WepSet_GetFromStat() & WepSet_FromWeapon(WEP_NEXBALL.m_id)))
return true;
if(autocvar_cl_eventchase_death && (getstati(STAT_HEALTH) <= 0))
{
// todo: avoid very long and very short sounds from wave stretching using different sound files? seems unnecessary
// todo: normalize sound pressure levels? seems unnecessary
- sound7(world, CH_INFO, "misc/hit.wav", VOL_BASE, ATTN_NONE, pitch_shift * 100, 0);
+ sound7(world, CH_INFO, SND(HIT), VOL_BASE, ATTN_NONE, pitch_shift * 100, 0);
}
unaccounted_damage = 0;
hitsound_time_prev = time;
float typehit_time = getstatf(STAT_TYPEHIT_TIME);
if (COMPARE_INCREASING(typehit_time, typehit_time_prev) > autocvar_cl_hitsound_antispam_time)
{
- sound(world, CH_INFO, "misc/typehit.wav", VOL_BASE, ATTN_NONE);
+ sound(world, CH_INFO, SND_TYPEHIT, VOL_BASE, ATTN_NONE);
typehit_time_prev = typehit_time;
}
}
void UpdateCrosshair()
-{
+{SELFPARAM();
static float rainbow_last_flicker;
static vector rainbow_prev_color;
entity e = self;
CSQC_common_hud();
// crosshair goes VERY LAST
- if(!scoreboard_active && !camera_active && intermission != 2 &&
+ if(!scoreboard_active && !camera_active && intermission != 2 &&
spectatee_status != -1 && hud == HUD_NORMAL && !csqcplayer.viewloc &&
!HUD_MinigameMenu_IsOpened() )
{
float vh_notice_time;
void WaypointSprite_Load();
void CSQC_UpdateView(float w, float h)
-{
+{SELFPARAM();
entity e;
float fov;
float f;
- int i;
vector vf_size, vf_min;
float a;
if(myteam != prev_myteam)
{
myteamcolors = colormapPaletteColor(myteam, 1);
- for(i = 0; i < HUD_PANEL_NUM; ++i)
- hud_panel[i].update_time = time;
+ FOREACH(hud_panels, true, LAMBDA(it.update_time = time));
prev_myteam = myteam;
}
mousepos = mousepos*0.5 + getmousepos();
*/
- e = self;
- for(self = world; (self = nextent(self)); )
- if(self.draw)
- self.draw();
- self = e;
+ for(entity e = NULL; (e = nextent(e)); ) if (e.draw) {
+ WITH(entity, self, e, e.draw(e));
+ }
addentities(MASK_NORMAL | MASK_ENGINE | MASK_ENGINEVIEWMODELS);
renderscene();
if(autocvar_cl_reticle)
{
+ Weapon wep = get_weaponinfo(activeweapon);
// Draw the aiming reticle for weapons that use it
// reticle_type is changed to the item we are zooming / aiming with, to decide which reticle to use
// It must be a persisted float for fading out to work properly (you let go of the zoom button for
// no zoom reticle while dead
reticle_type = 0;
}
- else if(WEP_ACTION(activeweapon, WR_ZOOMRETICLE) && autocvar_cl_reticle_weapon)
+ else if(wep.wr_zoomreticle(wep) && autocvar_cl_reticle_weapon)
{
if(reticle_image != "") { reticle_type = 2; }
else { reticle_type = 0; }
} else */
// draw 2D entities
- e = self;
- for(self = world; (self = nextent(self)); )
- if(self.draw2d)
- self.draw2d();
- self = e;
+ for (entity e = NULL; (e = nextent(e)); ) if (e.draw2d) {
+ WITH(entity, self, e, e.draw2d(e));
+ }
Draw_ShowNames_All();
scoreboard_active = HUD_WouldDrawScoreboard();
if(hud && !intermission)
if(hud == HUD_BUMBLEBEE_GUN)
CSQC_BUMBLE_GUN_HUD();
- else
- VEH_ACTION(hud, VR_HUD);
+ else {
+ Vehicle info = get_vehicleinfo(hud);
+ info.vr_hud(info);
+ }
cl_notice_run();
.vector movedir;
void Ent_Wall_PreDraw()
-{
+{SELFPARAM();
if (self.inactive)
{
self.alpha = 0;
self.drawmask = MASK_NORMAL;
}
-void Ent_Wall_Draw()
+void Ent_Wall_Draw(entity this)
{
float f;
var .vector fld;
}
void Ent_Wall_Remove()
-{
+{SELFPARAM();
if(self.bgmscript)
strunzone(self.bgmscript);
self.bgmscript = string_null;
}
void Ent_Wall()
-{
+{SELFPARAM();
int f;
var .vector fld;
.float fade_start, fade_end, fade_vertical_offset;
.float default_solid;
-void Ent_Wall_Draw();
+void Ent_Wall_Draw(entity this);
void Ent_Wall_Remove();
#include "../main.qh"
#include "../../common/constants.qh"
-#include "../../common/nades.qh"
+#include "../../common/nades/all.qh"
#include "../../common/movetypes/movetypes.qh"
#include "../../common/util.qh"
.vector colormod;
void SUB_Stop()
-{
+{SELFPARAM();
self.move_velocity = self.move_avelocity = '0 0 0';
self.move_movetype = MOVETYPE_NONE;
}
-void Projectile_ResetTrail(vector to)
+void Projectile_ResetTrail(entity this, vector to)
{
- self.trail_oldorigin = to;
- self.trail_oldtime = time;
+ this.trail_oldorigin = to;
+ this.trail_oldtime = time;
}
-void Projectile_DrawTrail(vector to)
+void Projectile_DrawTrail(entity this, vector to)
{
- vector from;
- float t0;
-
- from = self.trail_oldorigin;
- t0 = self.trail_oldtime;
- self.trail_oldorigin = to;
- self.trail_oldtime = time;
+ vector from = this.trail_oldorigin;
+ // float t0 = this.trail_oldtime;
+ this.trail_oldorigin = to;
+ this.trail_oldtime = time;
// force the effect even for stationary firemine
- if(self.cnt == PROJECTILE_FIREMINE)
+ if(this.cnt == PROJECTILE_FIREMINE)
if(from == to)
from.z += 1;
- if (self.traileffect)
+ if (this.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);
+ particles_alphamin = particles_alphamax = particles_fade = sqrt(this.alpha);
+ boxparticles(particleeffectnum(Effects[this.traileffect]), this, from, to, this.velocity, this.velocity, 1, PARTICLES_USEALPHA | PARTICLES_USEFADE | PARTICLES_DRAWASTRAIL);
}
}
-void Projectile_Draw()
+void Projectile_Draw(entity this)
{
vector rot;
vector trailorigin;
break;
}
- if(Nade_FromProjectile(self.cnt) != NADE_TYPE_NULL)
+ if(Nade_FromProjectile(self.cnt) != NADE_TYPE_Null)
rot = self.avelocity;
self.angles = AnglesTransform_ToAngles(AnglesTransform_Multiply(AnglesTransform_FromAngles(self.angles), rot * (t - self.spawntime)));
break;
}
- if(Nade_FromProjectile(self.cnt) != NADE_TYPE_NULL)
+ if(Nade_FromProjectile(self.cnt) != NADE_TYPE_Null)
trailorigin += v_up * 4;
if(drawn)
- Projectile_DrawTrail(trailorigin);
+ Projectile_DrawTrail(self, trailorigin);
else
- Projectile_ResetTrail(trailorigin);
+ Projectile_ResetTrail(self, trailorigin);
self.drawmask = 0;
}
void loopsound(entity e, int ch, string samp, float vol, float attn)
-{
+{SELFPARAM();
if(self.silent)
return;
- sound(e, ch, samp, vol, attn);
+ _sound(e, ch, samp, vol, attn);
e.snd_looping = ch;
}
void Ent_RemoveProjectile()
-{
+{SELFPARAM();
if(self.count & 0x80)
{
tracebox(self.origin, self.mins, self.maxs, self.origin + self.velocity * 0.05, MOVE_NORMAL, self);
- Projectile_DrawTrail(trace_endpos);
+ Projectile_DrawTrail(self, trace_endpos);
}
}
void Ent_Projectile()
-{
+{SELFPARAM();
int f;
// projectile properties:
if(f & 2)
{
- string rm_suffix = strcat("rocketminsta_laser_", Static_Team_ColorName_Lower(self.team));
- if(_particleeffectnum(rm_suffix) < 0 || Team_TeamToNumber(self.team) == -1) { rm_suffix = "TR_NEXUIZPLASMA"; }
-
self.cnt = ReadByte();
self.silent = (self.cnt & 0x80);
self.scale = 1;
self.traileffect = 0;
- switch(self.cnt)
- {
- case PROJECTILE_ELECTRO: setmodel(self, "models/ebomb.mdl");self.traileffect = particleeffectnum(EFFECT_TR_NEXUIZPLASMA); break;
- case PROJECTILE_ROCKET: setmodel(self, "models/rocket.md3");self.traileffect = particleeffectnum(EFFECT_TR_ROCKET); self.scale = 2; break;
- case PROJECTILE_CRYLINK: setmodel(self, "models/plasmatrail.mdl");self.traileffect = particleeffectnum(EFFECT_TR_CRYLINKPLASMA); break;
- case PROJECTILE_CRYLINK_BOUNCING: setmodel(self, "models/plasmatrail.mdl");self.traileffect = particleeffectnum(EFFECT_TR_CRYLINKPLASMA); break;
- case PROJECTILE_ELECTRO_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum(EFFECT_TR_NEXUIZPLASMA); break;
- case PROJECTILE_GRENADE: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum(EFFECT_TR_GRENADE); break;
- case PROJECTILE_GRENADE_BOUNCING: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum(EFFECT_TR_GRENADE); break;
- case PROJECTILE_MINE: setmodel(self, "models/mine.md3");self.traileffect = particleeffectnum(EFFECT_TR_GRENADE); break;
- case PROJECTILE_BLASTER: setmodel(self, "models/laser.mdl");self.traileffect = particleeffectnum(EFFECT_NULL); break;
- case PROJECTILE_HLAC: setmodel(self, "models/hlac_bullet.md3");self.traileffect = particleeffectnum(EFFECT_NULL); break;
- case PROJECTILE_PORTO_RED: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum(EFFECT_TR_WIZSPIKE); self.scale = 4; break;
- case PROJECTILE_PORTO_BLUE: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum(EFFECT_TR_WIZSPIKE); self.scale = 4; break;
- case PROJECTILE_HOOKBOMB: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum(EFFECT_TR_KNIGHTSPIKE); break;
- case PROJECTILE_HAGAR: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum(EFFECT_HAGAR_ROCKET); self.scale = 0.75; break;
- case PROJECTILE_HAGAR_BOUNCING: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum(EFFECT_HAGAR_ROCKET); self.scale = 0.75; break;
- case PROJECTILE_NAPALM_FOUNTAIN: //self.model = ""; self.modelindex = 0; self.traileffect = _particleeffectnum("torch_small"); break;
- case PROJECTILE_FIREBALL: self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum(EFFECT_FIREBALL); break; // particle effect is good enough
- case PROJECTILE_FIREMINE: self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum(EFFECT_FIREMINE); break; // particle effect is good enough
- case PROJECTILE_TAG: setmodel(self, "models/laser.mdl"); self.traileffect = particleeffectnum(EFFECT_TR_ROCKET); break;
- case PROJECTILE_FLAC: setmodel(self, "models/hagarmissile.mdl"); self.scale = 0.4; self.traileffect = particleeffectnum(EFFECT_FLAC_TRAIL); break;
- case PROJECTILE_SEEKER: setmodel(self, "models/tagrocket.md3"); self.traileffect = particleeffectnum(EFFECT_SEEKER_TRAIL); break;
-
- case PROJECTILE_MAGE_SPIKE: setmodel(self, "models/ebomb.mdl"); self.traileffect = particleeffectnum(EFFECT_TR_VORESPIKE); break;
- case PROJECTILE_SHAMBLER_LIGHTNING: setmodel(self, "models/ebomb.mdl"); self.traileffect = particleeffectnum(EFFECT_TR_NEXUIZPLASMA); break;
-
- case PROJECTILE_RAPTORBOMB: setmodel(self, "models/vehicles/clusterbomb.md3"); self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = particleeffectnum(EFFECT_NULL); break;
- case PROJECTILE_RAPTORBOMBLET: setmodel(self, "models/vehicles/bomblet.md3"); self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = particleeffectnum(EFFECT_NULL); break;
- case PROJECTILE_RAPTORCANNON: setmodel(self, "models/plasmatrail.mdl"); self.traileffect = particleeffectnum(EFFECT_TR_CRYLINKPLASMA); break;
-
- case PROJECTILE_SPIDERROCKET: setmodel(self, "models/vehicles/rocket02.md3"); self.traileffect = particleeffectnum(EFFECT_SPIDERBOT_ROCKET_TRAIL); break;
- case PROJECTILE_WAKIROCKET: setmodel(self, "models/vehicles/rocket01.md3"); self.traileffect = particleeffectnum(EFFECT_RACER_ROCKET_TRAIL); break;
- case PROJECTILE_WAKICANNON: setmodel(self, "models/laser.mdl"); self.traileffect = particleeffectnum(EFFECT_NULL); break;
-
- case PROJECTILE_BUMBLE_GUN: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum(EFFECT_TR_NEXUIZPLASMA); break;
- case PROJECTILE_BUMBLE_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum(EFFECT_TR_NEXUIZPLASMA); break;
-
- case PROJECTILE_RPC: setmodel(self, W_Model("ok_rocket"));self.traileffect = particleeffectnum(EFFECT_TR_ROCKET); break;
-
- case PROJECTILE_ROCKETMINSTA_LASER: setmodel(self, "models/elaser.mdl");self.traileffect = _particleeffectnum(rm_suffix); break;
-
+ switch (self.cnt) {
+#define CASE(id) case PROJECTILE_##id: setmodel(self, MDL_PROJECTILE_##id);
+ CASE(ELECTRO) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
+ CASE(ROCKET) self.traileffect = EFFECT_TR_ROCKET.m_id; self.scale = 2; break;
+ CASE(CRYLINK) self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
+ CASE(CRYLINK_BOUNCING) self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
+ CASE(ELECTRO_BEAM) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
+ CASE(GRENADE) self.traileffect = EFFECT_TR_GRENADE.m_id; break;
+ CASE(GRENADE_BOUNCING) self.traileffect = EFFECT_TR_GRENADE.m_id; break;
+ CASE(MINE) self.traileffect = EFFECT_TR_GRENADE.m_id; break;
+ CASE(BLASTER) self.traileffect = EFFECT_Null.m_id; break;
+ CASE(HLAC) self.traileffect = EFFECT_Null.m_id; break;
+ CASE(PORTO_RED) self.traileffect = EFFECT_TR_WIZSPIKE.m_id; self.scale = 4; break;
+ CASE(PORTO_BLUE) self.traileffect = EFFECT_TR_WIZSPIKE.m_id; self.scale = 4; break;
+ CASE(HOOKBOMB) self.traileffect = EFFECT_TR_KNIGHTSPIKE.m_id; break;
+ CASE(HAGAR) self.traileffect = EFFECT_HAGAR_ROCKET.m_id; self.scale = 0.75; break;
+ CASE(HAGAR_BOUNCING) self.traileffect = EFFECT_HAGAR_ROCKET.m_id; self.scale = 0.75; break;
+ CASE(NAPALM_FOUNTAIN) // fallthrough // sself.modelindex = 0; self.traileffect = _particleeffectnum("torch_small"); break;
+ CASE(FIREBALL) self.modelindex = 0; self.traileffect = EFFECT_FIREBALL.m_id; break; // particle effect is good enough
+ CASE(FIREMINE) self.modelindex = 0; self.traileffect = EFFECT_FIREMINE.m_id; break; // particle effect is good enough
+ CASE(TAG) self.traileffect = EFFECT_TR_ROCKET.m_id; break;
+ CASE(FLAC) self.scale = 0.4; self.traileffect = EFFECT_FLAC_TRAIL.m_id; break;
+ CASE(SEEKER) self.traileffect = EFFECT_SEEKER_TRAIL.m_id; break;
+
+ CASE(MAGE_SPIKE) self.traileffect = EFFECT_TR_VORESPIKE.m_id; break;
+ CASE(SHAMBLER_LIGHTNING) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
+
+ CASE(RAPTORBOMB) self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = EFFECT_Null.m_id; break;
+ CASE(RAPTORBOMBLET) self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = EFFECT_Null.m_id; break;
+ CASE(RAPTORCANNON) self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
+
+ CASE(SPIDERROCKET) self.traileffect = EFFECT_SPIDERBOT_ROCKET_TRAIL.m_id; break;
+ CASE(WAKIROCKET) self.traileffect = EFFECT_RACER_ROCKET_TRAIL.m_id; break;
+ CASE(WAKICANNON) self.traileffect = EFFECT_Null.m_id; break;
+
+ CASE(BUMBLE_GUN) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
+ CASE(BUMBLE_BEAM) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
+
+ CASE(RPC) self.traileffect = EFFECT_TR_ROCKET.m_id; break;
+
+ CASE(ROCKETMINSTA_LASER) self.traileffect = EFFECT_ROCKETMINSTA_LASER(self.team).m_id; break;
+#undef CASE
default:
if(MUTATOR_CALLHOOK(Ent_Projectile, self))
break;
- if (Nade_FromProjectile(self.cnt) != NADE_TYPE_NULL)
+ if (Nade_FromProjectile(self.cnt) != NADE_TYPE_Null)
{
- setmodel(self, W_Model("v_ok_grenade.md3"));
- self.traileffect = _particleeffectnum(Nade_TrailEffect(self.cnt, self.team));
+ setmodel(self, MDL_PROJECTILE_NADE);
+ entity trail = Nade_TrailEffect(self.cnt, self.team);
+ if (trail.eent_eff_name) self.traileffect = trail.m_id;
break;
}
error("Received invalid CSQC projectile, can't work with this!");
{
case PROJECTILE_ELECTRO:
// only new engines support sound moving with object
- loopsound(self, CH_SHOTS_SINGLE, W_Sound("electro_fly"), VOL_BASE, ATTEN_NORM);
+ loopsound(self, CH_SHOTS_SINGLE, SND(ELECTRO_FLY), VOL_BASE, ATTEN_NORM);
self.mins = '0 0 -4';
self.maxs = '0 0 -4';
self.move_movetype = MOVETYPE_BOUNCE;
break;
case PROJECTILE_RPC:
case PROJECTILE_ROCKET:
- loopsound(self, CH_SHOTS_SINGLE, W_Sound("rocket_fly"), VOL_BASE, ATTEN_NORM);
+ loopsound(self, CH_SHOTS_SINGLE, SND(ROCKET_FLY), VOL_BASE, ATTEN_NORM);
self.mins = '-3 -3 -3';
self.maxs = '3 3 3';
break;
break;
case PROJECTILE_NAPALM_FOUNTAIN:
case PROJECTILE_FIREBALL:
- loopsound(self, CH_SHOTS_SINGLE, W_Sound("fireball_fly2"), VOL_BASE, ATTEN_NORM);
+ loopsound(self, CH_SHOTS_SINGLE, SND(FIREBALL_FLY2), VOL_BASE, ATTEN_NORM);
self.mins = '-16 -16 -16';
self.maxs = '16 16 16';
break;
case PROJECTILE_FIREMINE:
- loopsound(self, CH_SHOTS_SINGLE, W_Sound("fireball_fly"), VOL_BASE, ATTEN_NORM);
+ loopsound(self, CH_SHOTS_SINGLE, SND(FIREBALL_FLY), VOL_BASE, ATTEN_NORM);
self.move_movetype = MOVETYPE_BOUNCE;
self.move_touch = func_null;
self.mins = '-4 -4 -4';
self.maxs = '2 2 2';
break;
case PROJECTILE_SEEKER:
- loopsound(self, CH_SHOTS_SINGLE, W_Sound("tag_rocket_fly"), VOL_BASE, ATTEN_NORM);
+ loopsound(self, CH_SHOTS_SINGLE, SND(TAG_ROCKET_FLY), VOL_BASE, ATTEN_NORM);
self.mins = '-4 -4 -4';
self.maxs = '4 4 4';
break;
case PROJECTILE_RAPTORCANNON:
break;
case PROJECTILE_SPIDERROCKET:
- loopsound(self, CH_SHOTS_SINGLE, W_Sound("tag_rocket_fly"), VOL_BASE, ATTEN_NORM);
+ loopsound(self, CH_SHOTS_SINGLE, SND(TAG_ROCKET_FLY), VOL_BASE, ATTEN_NORM);
break;
case PROJECTILE_WAKIROCKET:
- loopsound(self, CH_SHOTS_SINGLE, W_Sound("tag_rocket_fly"), VOL_BASE, ATTEN_NORM);
+ loopsound(self, CH_SHOTS_SINGLE, SND(TAG_ROCKET_FLY), VOL_BASE, ATTEN_NORM);
break;
/*
case PROJECTILE_WAKICANNON:
break;
case PROJECTILE_BUMBLE_GUN:
// only new engines support sound moving with object
- loopsound(self, CH_SHOTS_SINGLE, W_Sound("electro_fly"), VOL_BASE, ATTEN_NORM);
+ loopsound(self, CH_SHOTS_SINGLE, SND(ELECTRO_FLY), VOL_BASE, ATTEN_NORM);
self.mins = '0 0 -4';
self.maxs = '0 0 -4';
self.move_movetype = MOVETYPE_BOUNCE;
break;
}
- if(Nade_FromProjectile(self.cnt) != NADE_TYPE_NULL)
+ if(Nade_FromProjectile(self.cnt) != NADE_TYPE_Null)
{
entity nade_type = Nade_FromProjectile(self.cnt);
self.mins = '-16 -16 -16';
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/sphere/sphere.md3");
-
- precache_model(W_Model("v_ok_grenade.md3"));
- precache_model(W_Model("ok_rocket.md3"));
-
- precache_sound(W_Sound("electro_fly"));
- precache_sound(W_Sound("rocket_fly"));
- precache_sound(W_Sound("fireball_fly"));
- precache_sound(W_Sound("fireball_fly2"));
- precache_sound(W_Sound("tag_rocket_fly"));
-
MUTATOR_CALLHOOK(PrecacheProjectiles);
}
void SUB_Stop();
-void Projectile_ResetTrail(vector to);
+void Projectile_ResetTrail(entity this, vector to);
-void Projectile_DrawTrail(vector to);
+void Projectile_DrawTrail(entity this, vector to);
-void Projectile_Draw();
+void Projectile_Draw(entity this);
void loopsound(entity e, int ch, string samp, float vol, float attn);
+++ /dev/null
-#!/bin/sh
-
-{
- grep -h '\<precache_model *( *"' client/* | grep -v "//NO_SV_PRECACHE"
- grep -h '\<precache_sound *( *"' client/* | grep -v "//NO_SV_PRECACHE"
-} > server/precache-for-csqc.inc
-
bool monsters_animoverride(entity e)
{
- int monster_id = 0;
+ Monster monster_id = NULL;
for(int i = MON_FIRST; i <= MON_LAST; ++i)
{
entity mon = get_monsterinfo(i);
//if(substring(e.model, 0, strlen(mon.model) - 4) == substring(mon.model, 0, strlen(mon.model) - 4))
if(e.model == mon.model)
{
- monster_id = i;
+ monster_id = mon;
break;
}
}
if(!monster_id) { return false; }
- MON_ACTION(monster_id, MR_ANIM);
+ monster_id.mr_anim(monster_id);
vector none = '0 0 0';
e.anim_duckwalk = e.anim_walk;
+++ /dev/null
-#if defined(CSQC)
- #include "../dpdefs/csprogsdefs.qh"
- #include "../client/defs.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
- #include "../dpdefs/progsdefs.qh"
- #include "../dpdefs/dpextensions.qh"
-#endif
-#include "buffs.qh"
-
+++ /dev/null
-#ifndef BUFFS_H
-#define BUFFS_H
-// Welcome to the stuff behind the scenes
-// Below, you will find the list of buffs
-// Add new buffs here!
-// Note: Buffs also need spawnfuncs, which are set below
-
-#include "teams.qh"
-#include "util.qh"
-
-void RegisterBuffs();
-const int BUFFS_MAX = 16;
-entity BUFFS[BUFFS_MAX], BUFFS_first, BUFFS_last;
-int BUFFS_COUNT;
-#define REGISTER_BUFF(id) \
- REGISTER(RegisterBuffs, BUFF, BUFFS, BUFFS_COUNT, id, m_id, NEW(Buff)); \
- REGISTER_INIT_POST(BUFF, id) { \
- this.netname = this.m_name; \
- this.m_itemid = BIT(this.m_id - 1); \
- this.m_sprite = strzone(strcat("buff-", this.m_name)); \
- } \
- REGISTER_INIT(BUFF, id)
-REGISTER_REGISTRY(RegisterBuffs)
-
-#include "items/item/pickup.qh"
-CLASS(Buff, Pickup)
- /** bit index */
- ATTRIB(Buff, m_itemid, int, 0)
- ATTRIB(Buff, m_name, string, "buff")
- ATTRIB(Buff, m_color, vector, '1 1 1')
- ATTRIB(Buff, m_prettyName, string, "Buff")
- ATTRIB(Buff, m_skin, int, 0)
- ATTRIB(Buff, m_sprite, string, "")
- METHOD(Buff, display, void(entity this, void(string name, string icon) returns)) {
- returns(this.m_prettyName, sprintf("/gfx/hud/%s/buff_%s", cvar_string("menu_skin"), this.m_name));
- }
-#ifdef SVQC
- METHOD(Buff, m_time, float(entity));
- float Buff_m_time(entity this) { return cvar(strcat("g_buffs_", this.netname, "_time")); }
-#endif
-ENDCLASS(Buff)
-
-REGISTER_BUFF(NULL);
-
-REGISTER_BUFF(AMMO) {
- this.m_prettyName = _("Ammo");
- this.m_name = "ammo";
- this.m_skin = 3;
- this.m_color = '0.76 1 0.1';
-}
-
-REGISTER_BUFF(RESISTANCE) {
- this.m_prettyName = _("Resistance");
- this.m_name = "resistance";
- this.m_skin = 0;
- this.m_color = '0.36 1 0.07';
-}
-
-REGISTER_BUFF(SPEED) {
- this.m_prettyName = _("Speed");
- this.m_name = "speed";
- this.m_skin = 9;
- this.m_color = '0.1 1 0.84';
-}
-
-REGISTER_BUFF(MEDIC) {
- this.m_prettyName = _("Medic");
- this.m_name = "medic";
- this.m_skin = 1;
- this.m_color = '1 0.12 0';
-}
-
-REGISTER_BUFF(BASH) {
- this.m_prettyName = _("Bash");
- this.m_name = "bash";
- this.m_skin = 5;
- this.m_color = '1 0.39 0';
-}
-
-REGISTER_BUFF(VAMPIRE) {
- this.m_prettyName = _("Vampire");
- this.m_name = "vampire";
- this.m_skin = 2;
- this.m_color = '1 0 0.24';
-}
-
-REGISTER_BUFF(DISABILITY) {
- this.m_prettyName = _("Disability");
- this.m_name = "disability";
- this.m_skin = 7;
- this.m_color = '0.94 0.3 1';
-}
-
-REGISTER_BUFF(VENGEANCE) {
- this.m_prettyName = _("Vengeance");
- this.m_name = "vengeance";
- this.m_skin = 15;
- this.m_color = '1 0.23 0.61';
-}
-
-REGISTER_BUFF(JUMP) {
- this.m_prettyName = _("Jump");
- this.m_name = "jump";
- this.m_skin = 10;
- this.m_color = '0.24 0.78 1';
-}
-
-REGISTER_BUFF(FLIGHT) {
- this.m_prettyName = _("Flight");
- this.m_name = "flight";
- this.m_skin = 11;
- this.m_color = '0.33 0.56 1';
-}
-
-REGISTER_BUFF(INVISIBLE) {
- this.m_prettyName = _("Invisible");
- this.m_name = "invisible";
- this.m_skin = 12;
- this.m_color = '0.5 0.5 1';
-}
-
-REGISTER_BUFF(INFERNO) {
- this.m_prettyName = _("Inferno");
- this.m_name = "inferno";
- this.m_skin = 16;
- this.m_color = '1 0.62 0';
-}
-
-REGISTER_BUFF(SWAPPER) {
- this.m_prettyName = _("Swapper");
- this.m_name = "swapper";
- this.m_skin = 17;
- this.m_color = '0.63 0.36 1';
-}
-
-REGISTER_BUFF(MAGNET) {
- this.m_prettyName = _("Magnet");
- this.m_name = "magnet";
- this.m_skin = 18;
- this.m_color = '1 0.95 0.18';
-}
-
-#ifdef SVQC
-.int buffs;
-void buff_Init(entity ent);
-void buff_Init_Compat(entity ent, entity replacement);
-
-#define BUFF_SPAWNFUNC(e, b, t) void spawnfunc_item_buff_##e() { \
- self.buffs = b.m_itemid; \
- self.team = t; \
- buff_Init(self); \
-}
-#define BUFF_SPAWNFUNCS(e, b) \
- BUFF_SPAWNFUNC(e, b, 0) \
- BUFF_SPAWNFUNC(e##_team1, b, NUM_TEAM_1) \
- BUFF_SPAWNFUNC(e##_team2, b, NUM_TEAM_2) \
- BUFF_SPAWNFUNC(e##_team3, b, NUM_TEAM_3) \
- BUFF_SPAWNFUNC(e##_team4, b, NUM_TEAM_4)
-#define BUFF_SPAWNFUNC_Q3TA_COMPAT(o, r) void spawnfunc_item_##o() { buff_Init_Compat(self, r); }
-
-BUFF_SPAWNFUNCS(resistance, BUFF_RESISTANCE)
-BUFF_SPAWNFUNCS(ammo, BUFF_AMMO)
-BUFF_SPAWNFUNCS(speed, BUFF_SPEED)
-BUFF_SPAWNFUNCS(medic, BUFF_MEDIC)
-BUFF_SPAWNFUNCS(bash, BUFF_BASH)
-BUFF_SPAWNFUNCS(vampire, BUFF_VAMPIRE)
-BUFF_SPAWNFUNCS(disability, BUFF_DISABILITY)
-BUFF_SPAWNFUNCS(vengeance, BUFF_VENGEANCE)
-BUFF_SPAWNFUNCS(jump, BUFF_JUMP)
-BUFF_SPAWNFUNCS(flight, BUFF_FLIGHT)
-BUFF_SPAWNFUNCS(invisible, BUFF_INVISIBLE)
-BUFF_SPAWNFUNCS(inferno, BUFF_INFERNO)
-BUFF_SPAWNFUNCS(swapper, BUFF_SWAPPER)
-BUFF_SPAWNFUNCS(magnet, BUFF_MAGNET)
-BUFF_SPAWNFUNCS(random, BUFF_NULL)
-
-BUFF_SPAWNFUNC_Q3TA_COMPAT(doubler, BUFF_MEDIC)
-BUFF_SPAWNFUNC_Q3TA_COMPAT(resistance, BUFF_RESISTANCE)
-BUFF_SPAWNFUNC_Q3TA_COMPAT(scout, BUFF_SPEED)
-BUFF_SPAWNFUNC_Q3TA_COMPAT(ammoregen, BUFF_AMMO)
-
-// actually Q3
-BUFF_SPAWNFUNC_Q3TA_COMPAT(haste, BUFF_SPEED)
-BUFF_SPAWNFUNC_Q3TA_COMPAT(invis, BUFF_INVISIBLE)
-BUFF_SPAWNFUNC_Q3TA_COMPAT(medic, BUFF_MEDIC)
-
-#undef BUFF_SPAWNFUNC
-#undef BUFF_SPAWNFUNC_Q3TA_COMPAT
-#undef BUFF_SPAWNFUNCS
-#endif
-
-#endif
--- /dev/null
+REGISTER_BUFF(AMMO) {
+ this.m_prettyName = _("Ammo");
+ this.m_name = "ammo";
+ this.m_skin = 3;
+ this.m_color = '0.76 1 0.1';
+}
+BUFF_SPAWNFUNCS(ammo, BUFF_AMMO)
+BUFF_SPAWNFUNC_Q3TA_COMPAT(ammoregen, BUFF_AMMO)
+
+REGISTER_BUFF(RESISTANCE) {
+ this.m_prettyName = _("Resistance");
+ this.m_name = "resistance";
+ this.m_skin = 0;
+ this.m_color = '0.36 1 0.07';
+}
+BUFF_SPAWNFUNCS(resistance, BUFF_RESISTANCE)
+BUFF_SPAWNFUNC_Q3TA_COMPAT(resistance, BUFF_RESISTANCE)
+
+REGISTER_BUFF(SPEED) {
+ this.m_prettyName = _("Speed");
+ this.m_name = "speed";
+ this.m_skin = 9;
+ this.m_color = '0.1 1 0.84';
+}
+BUFF_SPAWNFUNCS(speed, BUFF_SPEED)
+BUFF_SPAWNFUNC_Q3TA_COMPAT(haste, BUFF_SPEED)
+BUFF_SPAWNFUNC_Q3TA_COMPAT(scout, BUFF_SPEED)
+
+REGISTER_BUFF(MEDIC) {
+ this.m_prettyName = _("Medic");
+ this.m_name = "medic";
+ this.m_skin = 1;
+ this.m_color = '1 0.12 0';
+}
+BUFF_SPAWNFUNCS(medic, BUFF_MEDIC)
+BUFF_SPAWNFUNC_Q3TA_COMPAT(doubler, BUFF_MEDIC)
+BUFF_SPAWNFUNC_Q3TA_COMPAT(medic, BUFF_MEDIC)
+
+REGISTER_BUFF(BASH) {
+ this.m_prettyName = _("Bash");
+ this.m_name = "bash";
+ this.m_skin = 5;
+ this.m_color = '1 0.39 0';
+}
+BUFF_SPAWNFUNCS(bash, BUFF_BASH)
+
+REGISTER_BUFF(VAMPIRE) {
+ this.m_prettyName = _("Vampire");
+ this.m_name = "vampire";
+ this.m_skin = 2;
+ this.m_color = '1 0 0.24';
+}
+BUFF_SPAWNFUNCS(vampire, BUFF_VAMPIRE)
+
+REGISTER_BUFF(DISABILITY) {
+ this.m_prettyName = _("Disability");
+ this.m_name = "disability";
+ this.m_skin = 7;
+ this.m_color = '0.94 0.3 1';
+}
+BUFF_SPAWNFUNCS(disability, BUFF_DISABILITY)
+
+REGISTER_BUFF(VENGEANCE) {
+ this.m_prettyName = _("Vengeance");
+ this.m_name = "vengeance";
+ this.m_skin = 15;
+ this.m_color = '1 0.23 0.61';
+}
+BUFF_SPAWNFUNCS(vengeance, BUFF_VENGEANCE)
+
+REGISTER_BUFF(JUMP) {
+ this.m_prettyName = _("Jump");
+ this.m_name = "jump";
+ this.m_skin = 10;
+ this.m_color = '0.24 0.78 1';
+}
+BUFF_SPAWNFUNCS(jump, BUFF_JUMP)
+
+REGISTER_BUFF(FLIGHT) {
+ this.m_prettyName = _("Flight");
+ this.m_name = "flight";
+ this.m_skin = 11;
+ this.m_color = '0.33 0.56 1';
+}
+BUFF_SPAWNFUNCS(flight, BUFF_FLIGHT)
+
+REGISTER_BUFF(INVISIBLE) {
+ this.m_prettyName = _("Invisible");
+ this.m_name = "invisible";
+ this.m_skin = 12;
+ this.m_color = '0.5 0.5 1';
+}
+BUFF_SPAWNFUNCS(invisible, BUFF_INVISIBLE)
+BUFF_SPAWNFUNC_Q3TA_COMPAT(invis, BUFF_INVISIBLE)
+
+REGISTER_BUFF(INFERNO) {
+ this.m_prettyName = _("Inferno");
+ this.m_name = "inferno";
+ this.m_skin = 16;
+ this.m_color = '1 0.62 0';
+}
+BUFF_SPAWNFUNCS(inferno, BUFF_INFERNO)
+
+REGISTER_BUFF(SWAPPER) {
+ this.m_prettyName = _("Swapper");
+ this.m_name = "swapper";
+ this.m_skin = 17;
+ this.m_color = '0.63 0.36 1';
+}
+BUFF_SPAWNFUNCS(swapper, BUFF_SWAPPER)
+
+REGISTER_BUFF(MAGNET) {
+ this.m_prettyName = _("Magnet");
+ this.m_name = "magnet";
+ this.m_skin = 18;
+ this.m_color = '1 0.95 0.18';
+}
+BUFF_SPAWNFUNCS(magnet, BUFF_MAGNET)
--- /dev/null
+#if defined(CSQC)
+ #include "../../dpdefs/csprogsdefs.qh"
+ #include "../../client/defs.qh"
+#elif defined(MENUQC)
+#elif defined(SVQC)
+ #include "../../dpdefs/progsdefs.qh"
+ #include "../../dpdefs/dpextensions.qh"
+#endif
+#include "all.qh"
+
--- /dev/null
+#ifndef BUFFS_ALL_H
+#define BUFFS_ALL_H
+// Welcome to the stuff behind the scenes
+// Below, you will find the list of buffs
+// Add new buffs here!
+// Note: Buffs also need spawnfuncs, which are set below
+
+#include "../teams.qh"
+#include "../util.qh"
+
+REGISTRY(Buffs, BIT(4))
+REGISTER_REGISTRY(RegisterBuffs)
+
+#define REGISTER_BUFF(id) \
+ REGISTER(RegisterBuffs, BUFF, Buffs, id, m_id, NEW(Buff)); \
+ REGISTER_INIT_POST(BUFF, id) { \
+ this.netname = this.m_name; \
+ this.m_itemid = BIT(this.m_id - 1); \
+ this.m_sprite = strzone(strcat("buff-", this.m_name)); \
+ } \
+ REGISTER_INIT(BUFF, id)
+
+#include "../items/item/pickup.qh"
+CLASS(Buff, Pickup)
+ /** bit index */
+ ATTRIB(Buff, m_itemid, int, 0)
+ ATTRIB(Buff, m_name, string, "buff")
+ ATTRIB(Buff, m_color, vector, '1 1 1')
+ ATTRIB(Buff, m_prettyName, string, "Buff")
+ ATTRIB(Buff, m_skin, int, 0)
+ ATTRIB(Buff, m_sprite, string, "")
+ METHOD(Buff, display, void(entity this, void(string name, string icon) returns)) {
+ returns(this.m_prettyName, sprintf("/gfx/hud/%s/buff_%s", cvar_string("menu_skin"), this.m_name));
+ }
+#ifdef SVQC
+ METHOD(Buff, m_time, float(entity));
+ float Buff_m_time(entity this) { return cvar(strcat("g_buffs_", this.netname, "_time")); }
+#endif
+ENDCLASS(Buff)
+
+#ifdef SVQC
+ .int buffs;
+ void buff_Init(entity ent);
+ void buff_Init_Compat(entity ent, entity replacement);
+ #define BUFF_SPAWNFUNC(e, b, t) spawnfunc(item_buff_##e) { \
+ self.buffs = b.m_itemid; \
+ self.team = t; \
+ buff_Init(self); \
+ }
+ #define BUFF_SPAWNFUNCS(e, b) \
+ BUFF_SPAWNFUNC(e, b, 0) \
+ BUFF_SPAWNFUNC(e##_team1, b, NUM_TEAM_1) \
+ BUFF_SPAWNFUNC(e##_team2, b, NUM_TEAM_2) \
+ BUFF_SPAWNFUNC(e##_team3, b, NUM_TEAM_3) \
+ BUFF_SPAWNFUNC(e##_team4, b, NUM_TEAM_4)
+ #define BUFF_SPAWNFUNC_Q3TA_COMPAT(o, r) spawnfunc(item_##o) { buff_Init_Compat(self, r); }
+#else
+ #define BUFF_SPAWNFUNC(e, b, t)
+ #define BUFF_SPAWNFUNCS(e, b)
+ #define BUFF_SPAWNFUNC_Q3TA_COMPAT(o, r)
+#endif
+
+REGISTER_BUFF(Null);
+BUFF_SPAWNFUNCS(random, BUFF_Null)
+
+#include "all.inc"
+
+#endif
}
}
+#ifndef MENUQC
+void effectinfo_dump(int fh, bool alsoprint);
+#endif
+void GenericCommand_dumpeffectinfo(float request)
+{
+ switch (request) {
+ case CMD_REQUEST_COMMAND: {
+ #ifndef MENUQC
+ string filename = argv(1);
+ bool alsoprint = false;
+ if (filename == "") {
+ filename = "effectinfo_dump.txt";
+ alsoprint = false;
+ } else if (filename == "-") {
+ filename = "effectinfo_dump.txt";
+ alsoprint = true;
+ }
+ int fh = fopen(filename, FILE_WRITE);
+ if (fh >= 0) {
+ effectinfo_dump(fh, alsoprint);
+ LOG_INFOF("Dumping effectinfo... File located at ^2data/data/%s^7.\n", filename);
+ LOG_INFOF("Reload with ^2cl_particles_reloadeffects data/%s^7.\n", filename);
+ fclose(fh);
+ } else {
+ LOG_WARNINGF("Could not open file '%s'!\n", filename);
+ }
+ #else
+ LOG_INFO(_("Effectinfo dump command only works with cl_cmd and sv_cmd.\n"));
+ #endif
+ return;
+ }
+ default:
+ case CMD_REQUEST_USAGE: {
+ LOG_INFO(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " dumpeffectinfo [filename]"));
+ LOG_INFO(" Where 'filename' is the file to write (default is effectinfo_dump.txt),\n");
+ LOG_INFO(" if supplied with '-' output to console as well as default,\n");
+ LOG_INFO(" if left blank, it will only write to default.\n");
+ return;
+ }
+ }
+}
+STATIC_INIT(dumpeffectinfo) { localcmd("alias dumpeffectinfo \"qc_cmd_svcl dumpeffectinfo ${* ?}\"\n"); }
+
void GenericCommand_dumpitems(float request)
{
switch(request)
#define GENERIC_COMMANDS(request,arguments,command) \
GENERIC_COMMAND("addtolist", GenericCommand_addtolist(request, arguments), "Add a string to a cvar") \
GENERIC_COMMAND("dumpcommands", GenericCommand_dumpcommands(request), "Dump all commands on the program to *_cmd_dump.txt") \
+ GENERIC_COMMAND("dumpeffectinfo", GenericCommand_dumpeffectinfo(request), "Dump all effectinfo to effectinfo_dump.txt") \
GENERIC_COMMAND("dumpitems", GenericCommand_dumpitems(request), "Dump all items to the console") \
GENERIC_COMMAND("dumpnotifs", GenericCommand_dumpnotifs(request), "Dump all notifications into notifications_dump.txt") \
GENERIC_COMMAND("dumpturrets", GenericCommand_dumpturrets(request), "Dump all turrets into turrets_dump.txt") \
const int ENT_CLIENT_MINIGAME = 75;
const int ENT_CLIENT_VIEWLOC = 78;
const int ENT_CLIENT_VIEWLOC_TRIGGER = 79;
-const int ENT_CLIENT_HEALING_ORB = 80;
const int ENT_CLIENT_MUTATOR = TE_CSQC_MUTATOR; // 99
const int SPRITERULE_TEAMPLAY = 1;
const int SPRITERULE_SPECTATOR = 2;
-const int RADARICON_NONE = 0;
-const int RADARICON_FLAG = 1;
-const int RADARICON_FLAGCARRIER = 1;
-const int RADARICON_HERE = 1; // TODO make these 3 and 4, and make images for them
-const int RADARICON_DANGER = 1;
-const int RADARICON_WAYPOINT = 1;
-const int RADARICON_HELPME = 1;
-const int RADARICON_CONTROLPOINT = 1;
-const int RADARICON_GENERATOR = 1;
-const int RADARICON_OBJECTIVE = 1;
-const int RADARICON_DOMPOINT = 1;
-const int RADARICON_POWERUP = 1;
-const int RADARICON_TAGGED = 1;
-
///////////////////////////
// keys pressed
const int KEY_FORWARD = 1;
CSQCMODEL_PROPERTY(512, float, ReadApproxPastTime, WriteApproxPastTime, anim_upper_time) \
CSQCMODEL_ENDIF \
CSQCMODEL_PROPERTY(1024, float, ReadAngle, WriteAngle, v_angle_x) \
+ CSQCMODEL_PROPERTY(2048, int, ReadByte, WriteByte, traileffect) \
CSQCMODEL_PROPERTY_SCALED(4096, float, ReadByte, WriteByte, scale, 16, 0, 255) \
CSQCMODEL_PROPERTY(8192, int, ReadInt24_t, WriteInt24_t, dphitcontentsmask) \
CSQCMODEL_PROPERTY(16384, TAG_VIEWLOC_TYPE, ReadShort, WriteEntity, TAG_VIEWLOC_NAME)
//vector PL_CROUCH_VIEW_OFS = ...;
#ifdef SVQC
-# define CSQCMODEL_AUTOINIT() CSQCModel_LinkEntity()
-# define CSQCMODEL_AUTOUPDATE() CSQCModel_CheckUpdate()
+# define CSQCMODEL_AUTOINIT(e) CSQCModel_LinkEntity(e)
+# define CSQCMODEL_AUTOUPDATE(e) CSQCModel_CheckUpdate(e)
#endif
#define CSQCMODEL_EF_RESPAWNGHOST EF_SELECTABLE
if (msg_death_by != NO_MSG) \
deathent.death_msgmurder = msg_multi_notifs[msg_death_by - 1]; \
} \
- ACCUMULATE_FUNCTION(RegisterDeathtypes, RegisterDeathtype_##name);
+ ACCUMULATE_FUNCTION(RegisterDeathtypes, RegisterDeathtype_##name)
DEATHTYPES
#undef DEATHTYPE
+++ /dev/null
-// Global list of effects, networked to CSQC by ID to save bandwidth and to use client particle numbers (allows mismatching effectinfos to some degree)
-// Not too concerned about the order of this list, just keep the weapon effects together!
-
-// EFFECT(istrail, EFFECT_NAME, "effectinfo_string")
-EFFECT(0, EXPLOSION_SMALL, "explosion_small")
-EFFECT(0, EXPLOSION_MEDIUM, "explosion_medium")
-EFFECT(0, EXPLOSION_BIG, "explosion_big")
-
-EFFECT(0, SMOKE_SMALL, "smoke_small")
-EFFECT(0, SMOKE_LARGE, "smoke_large")
-
-
-
-EFFECT(0, BLASTER_IMPACT, "laser_impact")
-EFFECT(0, BLASTER_MUZZLEFLASH, "laser_muzzleflash")
-
-EFFECT(0, SHOTGUN_IMPACT, "shotgun_impact")
-EFFECT(0, SHOTGUN_MUZZLEFLASH, "shotgun_muzzleflash")
-
-EFFECT(0, ARC_BEAM, "arc_beam")
-EFFECT(0, ARC_BEAM_HEAL, "arc_beam_heal")
-EFFECT(0, ARC_BEAM_HEAL_IMPACT, "arc_beam_healimpact")
-EFFECT(0, ARC_BEAM_HEAL_IMPACT2, "healray_impact")
-EFFECT(0, ARC_LIGHTNING, "arc_lightning")
-EFFECT(0, ARC_LIGHTNING2, "electro_lightning")
-
-EFFECT(0, MACHINEGUN_IMPACT, "machinegun_impact")
-EFFECT(0, MACHINEGUN_MUZZLEFLASH, "uzi_muzzleflash")
-
-EFFECT(0, GRENADE_EXPLODE, "grenade_explode")
-EFFECT(0, GRENADE_MUZZLEFLASH, "grenadelauncher_muzzleflash")
-
-EFFECT(0, ELECTRO_BALLEXPLODE, "electro_ballexplode")
-EFFECT(0, ELECTRO_COMBO, "electro_combo")
-EFFECT(0, ELECTRO_IMPACT, "electro_impact")
-EFFECT(0, ELECTRO_MUZZLEFLASH, "electro_muzzleflash")
-
-EFFECT(0, CRYLINK_IMPACT, "crylink_impactbig")
-EFFECT(0, CRYLINK_IMPACT2, "crylink_impact")
-EFFECT(0, CRYLINK_JOINEXPLODE, "crylink_joinexplode")
-EFFECT(0, CRYLINK_MUZZLEFLASH, "crylink_muzzleflash")
-
-EFFECT(0, VORTEX_BEAM, "nex_beam")
-EFFECT(0, VORTEX_BEAM_OLD, "TE_TEI_G3")
-EFFECT(0, VORTEX_IMPACT, "nex_impact")
-EFFECT(0, VORTEX_MUZZLEFLASH, "nex_muzzleflash")
-
-EFFECT(1, VAPORIZER_RED, "TE_TEI_G3RED")
-EFFECT(1, VAPORIZER_RED_HIT, "TE_TEI_G3RED_HIT")
-EFFECT(1, VAPORIZER_BLUE, "TE_TEI_G3BLUE")
-EFFECT(1, VAPORIZER_BLUE_HIT, "TE_TEI_G3BLUE_HIT")
-EFFECT(1, VAPORIZER_YELLOW, "TE_TEI_G3YELLOW")
-EFFECT(1, VAPORIZER_YELLOW_HIT, "TE_TEI_G3YELLOW_HIT")
-EFFECT(1, VAPORIZER_PINK, "TE_TEI_G3PINK")
-EFFECT(1, VAPORIZER_PINK_HIT, "TE_TEI_G3PINK_HIT")
-EFFECT(1, VAPORIZER_NEUTRAL, "TE_TEI_G3")
-EFFECT(1, VAPORIZER_NEUTRAL_HIT, "TE_TEI_G3_HIT")
-
-EFFECT(0, RIFLE_IMPACT, "machinegun_impact")
-EFFECT(0, RIFLE_MUZZLEFLASH, "rifle_muzzleflash")
-EFFECT(1, RIFLE, "tr_rifle")
-EFFECT(1, RIFLE_WEAK, "tr_rifle_weak")
-
-EFFECT(0, HAGAR_BOUNCE, "hagar_bounce")
-EFFECT(0, HAGAR_EXPLODE, "hagar_explode")
-EFFECT(0, HAGAR_MUZZLEFLASH, "hagar_muzzleflash")
-EFFECT(1, HAGAR_ROCKET, "tr_hagar")
-
-EFFECT(0, ROCKET_EXPLODE, "rocket_explode")
-EFFECT(0, ROCKET_GUIDE, "rocket_guide")
-EFFECT(0, ROCKET_MUZZLEFLASH, "rocketlauncher_muzzleflash")
-
-EFFECT(0, HOOK_EXPLODE, "hookbomb_explode")
-EFFECT(0, HOOK_IMPACT, "grapple_impact")
-EFFECT(0, HOOK_MUZZLEFLASH, "grapple_muzzleflash")
-
-EFFECT(0, SEEKER_MUZZLEFLASH, "seeker_muzzleflash")
-
-EFFECT(0, FLAK_BOUNCE, "flak_bounce")
-
-EFFECT(1, FIREBALL, "fireball")
-EFFECT(0, FIREBALL_BFGDAMAGE, "fireball_bfgdamage")
-EFFECT(0, FIREBALL_EXPLODE, "fireball_explode")
-EFFECT(0, FIREBALL_LASER, "fireball_laser")
-EFFECT(0, FIREBALL_MUZZLEFLASH, "fireball_muzzleflash")
-EFFECT(0, FIREBALL_PRE_MUZZLEFLASH, "fireball_preattack_muzzleflash")
-
-
-
-EFFECT(0, RAPTOR_CANNON_IMPACT, "raptor_cannon_impact")
-EFFECT(0, RAPTOR_BOMB_IMPACT, "raptor_bomb_impact")
-EFFECT(0, RAPTOR_BOMB_SPREAD, "raptor_bomb_spread")
-EFFECT(0, RAPTOR_MUZZLEFLASH, "raptor_cannon_muzzleflash")
-
-EFFECT(0, RACER_BOOSTER, "wakizashi_booster_smoke")
-EFFECT(0, RACER_IMPACT, "wakizashi_gun_impact")
-EFFECT(0, RACER_MUZZLEFLASH, "wakizashi_gun_muzzleflash")
-EFFECT(0, RACER_ROCKETLAUNCH, "wakizashi_rocket_launch")
-EFFECT(0, RACER_ROCKET_EXPLODE, "wakizashi_rocket_launch")
-EFFECT(1, RACER_ROCKET_TRAIL, "wakizashi_rocket_thrust")
-
-EFFECT(0, SPIDERBOT_ROCKETLAUNCH, "spiderbot_rocket_launch")
-EFFECT(1, SPIDERBOT_ROCKET_TRAIL, "spiderbot_rocket_thrust")
-EFFECT(0, SPIDERBOT_ROCKET_EXPLODE, "spiderbot_rocket_explode")
-EFFECT(0, SPIDERBOT_MINIGUN_IMPACT, "spiderbot_minigun_impact")
-EFFECT(0, SPIDERBOT_MINIGUN_MUZZLEFLASH, "spiderbot_minigun_muzzleflash")
-
-EFFECT(0, BUMBLEBEE_HEAL_MUZZLEFLASH, "healray_muzzleflash")
-EFFECT(0, BUMBLEBEE_HEAL_IMPACT, "healray_impact")
-
-EFFECT(0, BIGPLASMA_IMPACT, "bigplasma_impact")
-EFFECT(0, BIGPLASMA_MUZZLEFLASH, "bigplasma_muzzleflash")
-
-EFFECT(0, TELEPORT, "teleport")
-
-EFFECT(0, SPAWNPOINT_RED, "spawn_point_red")
-EFFECT(0, SPAWN_RED, "spawn_event_red")
-EFFECT(0, SPAWNPOINT_BLUE, "spawn_point_blue")
-EFFECT(0, SPAWN_BLUE, "spawn_event_blue")
-EFFECT(0, SPAWNPOINT_YELLOW, "spawn_point_yellow")
-EFFECT(0, SPAWN_YELLOW, "spawn_event_yellow")
-EFFECT(0, SPAWNPOINT_PINK, "spawn_point_pink")
-EFFECT(0, SPAWN_PINK, "spawn_event_pink")
-EFFECT(0, SPAWNPOINT_NEUTRAL, "spawn_point_neutral")
-EFFECT(0, SPAWN_NEUTRAL, "spawn_event_neutral")
-
-EFFECT(0, NADE_RED_EXPLODE, "nade_red_explode")
-EFFECT(0, NADE_BLUE_EXPLODE, "nade_blue_explode")
-EFFECT(0, NADE_YELLOW_EXPLODE, "nade_yellow_explode")
-EFFECT(0, NADE_PINK_EXPLODE, "nade_pink_explode")
-EFFECT(0, NADE_NEUTRAL_EXPLODE, "nade_neutral_explode")
-
-EFFECT(0, ICEORGLASS, "iceorglass")
-EFFECT(0, ICEFIELD, "icefield")
-EFFECT(0, FIREFIELD, "firefield")
-EFFECT(0, HEALING, "healing_fx")
-EFFECT(1, LASER_BEAM_FAST, "nex242_misc_laser_beam_fast")
-EFFECT(0, RESPAWN_GHOST, "respawn_ghost")
-
-EFFECT(0, FLAG_RED_TOUCH, "redflag_touch")
-EFFECT(0, FLAG_BLUE_TOUCH, "blueflag_touch")
-EFFECT(0, FLAG_YELLOW_TOUCH, "yellowflag_touch")
-EFFECT(0, FLAG_PINK_TOUCH, "pinkflag_touch")
-EFFECT(0, FLAG_NEUTRAL_TOUCH, "neutralflag_touch")
-EFFECT(1, RED_PASS, "red_pass")
-EFFECT(1, BLUE_PASS, "blue_pass")
-EFFECT(1, YELLOW_PASS, "yellow_pass")
-EFFECT(1, PINK_PASS, "pink_pass")
-EFFECT(1, NEUTRAL_PASS, "neutral_pass")
-EFFECT(0, RED_CAP, "red_cap")
-EFFECT(0, BLUE_CAP, "blue_cap")
-EFFECT(0, YELLOW_CAP, "yellow_cap")
-EFFECT(0, PINK_CAP, "pink_cap")
-
-EFFECT(0, ITEM_PICKUP, "item_pickup")
-EFFECT(0, ITEM_RESPAWN, "item_respawn")
-
-EFFECT(0, ONS_GENERATOR_DAMAGED, "torch_small")
-EFFECT(0, ONS_GENERATOR_GIB, "onslaught_generator_gib_explode")
-EFFECT(0, ONS_GENERATOR_EXPLODE, "onslaught_generator_smallexplosion")
-EFFECT(0, ONS_GENERATOR_EXPLODE2, "onslaught_generator_finalexplosion")
-
-
-
-EFFECT(0, LASER_DEADLY, "laser_deadly")
-EFFECT(1, FLAC_TRAIL, "TR_SEEKER")
-EFFECT(1, SEEKER_TRAIL, "TR_SEEKER")
-EFFECT(1, FIREMINE, "firemine")
-EFFECT(0, BALL_SPARKS, "kaball_sparks")
-EFFECT(0, ELECTRIC_SPARKS, "electricity_sparks")
-EFFECT(0, SPARKS, "sparks")
-EFFECT(0, RAGE, "rage")
-EFFECT(0, SMOKING, "smoking")
-EFFECT(0, SMOKE_RING, "smoke_ring")
-EFFECT(0, JUMPPAD, "jumppad_activate")
-EFFECT(1, BULLET, "tr_bullet")
-EFFECT(0, EF_FLAME, "EF_FLAME")
-EFFECT(0, EF_STARDUST, "EF_STARDUST")
-EFFECT(0, TE_EXPLOSION, "TE_EXPLOSION")
-EFFECT(1, TR_NEXUIZPLASMA, "TR_NEXUIZPLASMA")
-EFFECT(1, TR_CRYLINKPLASMA, "TR_CRYLINKPLASMA")
-EFFECT(1, TR_ROCKET, "TR_ROCKET")
-EFFECT(1, TR_GRENADE, "TR_GRENADE")
-EFFECT(1, TR_BLOOD, "TR_BLOOD")
-EFFECT(1, TR_WIZSPIKE, "TR_WIZSPIKE")
-EFFECT(1, TR_SLIGHTBLOOD, "TR_SLIGHTBLOOD")
-EFFECT(1, TR_KNIGHTSPIKE, "TR_KNIGHTSPIKE")
-EFFECT(1, TR_VORESPIKE, "TR_VORESPIKE")
-EFFECT(0, TE_SPARK, "TE_SPARK")
+++ /dev/null
-#ifdef CSQC
-void Read_Effect(bool is_new)
-{
-#if EFFECTS_COUNT >= 255
- int net_name = ReadShort();
-#else
- int net_name = ReadByte();
-#endif
-
- entity eff = effects_ent[net_name];
-
- vector v, vel = '0 0 0';
- int eff_cnt = 1;
- bool eff_trail = eff.eent_eff_trail;
- v_x = ReadCoord();
- v_y = ReadCoord();
- v_z = ReadCoord();
-
- bool use_vel = ReadByte();
- if(use_vel)
- {
- vel_x = ReadCoord();
- vel_y = ReadCoord();
- vel_z = ReadCoord();
- }
-
- if(!eff_trail)
- eff_cnt = ReadByte();
-
- if(is_new)
- {
- if(eff_trail)
- WarpZone_TrailParticles(world, particleeffectnum(eff), v, vel);
- else
- pointparticles(particleeffectnum(eff), v, vel, eff_cnt);
- }
-}
-#endif
-
-#ifdef SVQC
-bool Net_Write_Effect(entity client, int sf)
-{
- WriteByte(MSG_ENTITY, ENT_CLIENT_EFFECT);
-#if EFFECTS_COUNT >= 255
- WriteShort(MSG_ENTITY, self.m_id);
-#else
- WriteByte(MSG_ENTITY, self.m_id);
-#endif
- WriteCoord(MSG_ENTITY, self.eent_net_location_x);
- WriteCoord(MSG_ENTITY, self.eent_net_location_y);
- WriteCoord(MSG_ENTITY, self.eent_net_location_z);
-
- // attempt to save a tiny bit more bandwidth by not sending velocity if it isn't set
- if(self.eent_net_velocity)
- {
- WriteByte(MSG_ENTITY, true);
- WriteCoord(MSG_ENTITY, self.eent_net_velocity_x);
- WriteCoord(MSG_ENTITY, self.eent_net_velocity_y);
- WriteCoord(MSG_ENTITY, self.eent_net_velocity_z);
- }
- else { WriteByte(MSG_ENTITY, false); }
-
- if(!self.eent_eff_trail) { WriteByte(MSG_ENTITY, self.eent_net_count); }
- return true;
-}
-
-void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt)
-{
- if(!eff) { return; }
- if(!eff.eent_eff_trail && !eff_cnt) { return; } // effect has no count!
- entity net_eff = spawn();
- net_eff.owner = eff;
- net_eff.classname = "net_effect";
- //net_eff.eent_broadcast = broadcast;
- net_eff.m_id = eff.m_id;
- net_eff.eent_net_velocity = eff_vel;
- net_eff.eent_net_location = eff_loc;
- net_eff.eent_net_count = eff_cnt;
- net_eff.eent_eff_trail = eff.eent_eff_trail;
-
- net_eff.think = SUB_Remove;
- net_eff.nextthink = time + 0.2; // don't need to keep this long
-
- Net_LinkEntity(net_eff, false, 0, Net_Write_Effect);
-}
-
-void Send_Effect_(string eff_name, vector eff_loc, vector eff_vel, int eff_cnt)
-{
- // problem with this is, we might not have all the available effects for it
- FOREACH(effects_ent, it.eent_eff_name == eff_name, LAMBDA(
- Send_Effect(it, eff_loc, eff_vel, eff_cnt);
- return;
- ));
- // revert to engine handling
- pointparticles(_particleeffectnum(eff_name), eff_loc, eff_vel, eff_cnt);
-}
-#endif
+++ /dev/null
-#ifndef P_EFFECTS_H
-#define P_EFFECTS_H
-
-#ifdef CSQC
-void Read_Effect(bool is_new);
-#elif defined(SVQC)
-void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt);
-void Send_Effect_(string eff_name, vector eff_loc, vector eff_vel, int eff_cnt);
-#endif
-
-#define particleeffectnum(e) _particleeffectnum(e.eent_eff_name)
-
-void RegisterEffects();
-const int MAX_EFFECTS = 512;
-entity effects_ent[MAX_EFFECTS], effects_ent_first, effects_ent_last;
-int EFFECT_COUNT;
-
-#define EFFECT(istrail, name, realname) \
- REGISTER(RegisterEffects, EFFECT, effects_ent, EFFECT_COUNT, name, m_id, Create_Effect_Entity(realname, istrail));
-REGISTER_REGISTRY(RegisterEffects)
-
-.int m_id;
-.string eent_eff_name;
-.int eent_eff_trail;
-
-.vector eent_net_location;
-.vector eent_net_velocity;
-.int eent_net_count;
-
-entity Create_Effect_Entity(string eff_name, bool eff_trail)
-{
- entity this = new(effect_entity);
- this.eent_eff_name = eff_name;
- this.eent_eff_trail = eff_trail;
- return this;
-}
-
-void RegisterEffects_First()
-{
- #ifdef SVQC
- #define dedi (server_is_dedicated ? "a dedicated " : "")
- #else
- #define dedi ""
- #endif
-
- LOG_TRACEF("Beginning effect initialization on %s%s program...\n", dedi, PROGNAME);
- #undef dedi
-}
-
-void RegisterEffects_Done()
-{
- LOG_TRACE("Effects initialization successful!\n");
-}
-
-// NOW we actually activate the declarations
-ACCUMULATE_FUNCTION(RegisterEffects, RegisterEffects_First);
-EFFECT(0, NULL, string_null)
-#include "effects.inc"
-ACCUMULATE_FUNCTION(RegisterEffects, RegisterEffects_Done);
-
-#endif
--- /dev/null
+// item respawn effect
+DEF(TE_WIZSPIKE);
+// flare particle and light
+SUB(TE_WIZSPIKE) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 128;
+ MY(color_min) = "0x63F2EA";
+ MY(color_max) = "0x63f2EA";
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '0.4 0.9 0.9';
+ MY(lightradiusfade) = 200;
+ MY(lightradius) = 200;
+ MY(size_min) = 20;
+ MY(size_max) = 20;
+ MY(type) = "static";
+}
+// cloud of particles which expand rapidly and then slow to form a ball
+SUB(TE_WIZSPIKE) {
+ MY(airfriction) = 2;
+ MY(alpha_min) = 64;
+ MY(alpha_max) = 64;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0x63F2EA";
+ MY(color_max) = "0x63f2EA";
+ MY(count) = 50;
+ MY(liquidfriction) = 2;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(size_min) = 2;
+ MY(size_max) = 2;
+ MY(type) = "static";
+ MY(velocityjitter) = '32.0 32.0 32.0';
+}
+
+// laser impact
+DEF(TE_KNIGHTSPIKE);
+// decal
+SUB(TE_KNIGHTSPIKE) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '4.0 0.2 0.2';
+ MY(lightradiusfade) = 1000;
+ MY(lightradius) = 200;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(size_min) = 24;
+ MY(size_max) = 24;
+ MY(tex_min) = 47;
+ MY(tex_max) = 47;
+ MY(type) = "decal";
+}
+// flare effect
+SUB(TE_KNIGHTSPIKE) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0xFF2010";
+ MY(color_max) = "0xFF2010";
+ MY(countabsolute) = 1;
+ MY(size_min) = 24;
+ MY(size_max) = 24;
+ MY(tex_min) = 39;
+ MY(tex_max) = 39;
+ MY(type) = "static";
+}
+// sparks that rapidly expand and rapidly slow down to form an interesting spherical effect
+SUB(TE_KNIGHTSPIKE) {
+ MY(airfriction) = 6;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0x800000";
+ MY(color_max) = "0xFF8020";
+ MY(count) = 128;
+ MY(liquidfriction) = 6;
+ MY(size_min) = 4;
+ MY(size_max) = 4;
+ MY(type) = "spark";
+ MY(velocityjitter) = '256.0 256.0 256.0';
+}
+
+// machinegun bullet impact
+DEF(TE_SPIKE);
+// bullet impact decal
+SUB(TE_SPIKE) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(originjitter) = '6.0 6.0 6.0';
+ MY(size_min) = 5;
+ MY(size_max) = 5;
+ MY(tex_min) = 56;
+ MY(tex_max) = 59;
+ MY(type) = "decal";
+}
+// dust/smoke drifting away from the impact
+SUB(TE_SPIKE) {
+ MY(alpha_min) = 255;
+ MY(alpha_max) = 255;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0x101010";
+ MY(color_max) = "0x101010";
+ MY(count) = 4;
+ MY(sizeincrease) = 3;
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '8.0 8.0 8.0';
+}
+// dust/smoke staying at the impact
+SUB(TE_SPIKE) {
+ MY(alpha_min) = 255;
+ MY(alpha_max) = 255;
+ MY(alpha_fade) = 128;
+ MY(color_min) = "0x505050";
+ MY(color_max) = "0x505050";
+ MY(count) = 0.500000;
+ MY(sizeincrease) = 4;
+ MY(size_min) = 4;
+ MY(size_max) = 4;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+}
+// bouncing sparks
+SUB(TE_SPIKE) {
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x8f4333";
+ MY(color_max) = "0xfff31b";
+ MY(count) = 10;
+ MY(gravity) = 1;
+ MY(size_min) = 0.400000;
+ MY(size_max) = 0.400000;
+ MY(type) = "spark";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+ MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+// electro combo explosion
+DEF(TE_SPIKEQUAD);
+// decal
+SUB(TE_SPIKEQUAD) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '2.0 2.5 3.0';
+ MY(lightradiusfade) = 200;
+ MY(lightradius) = 400;
+ MY(originjitter) = '34.0 34.0 34.0';
+ MY(size_min) = 64;
+ MY(size_max) = 64;
+ MY(tex_min) = 59;
+ MY(tex_max) = 59;
+ MY(type) = "decal";
+}
+// flare effect
+SUB(TE_SPIKEQUAD) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 128;
+ MY(color_min) = "0x80C0FF";
+ MY(color_max) = "0x80C0FF";
+ MY(countabsolute) = 1;
+ MY(size_min) = 48;
+ MY(size_max) = 48;
+ MY(tex_min) = 38;
+ MY(tex_max) = 38;
+ MY(type) = "static";
+}
+// large sparks
+SUB(TE_SPIKEQUAD) {
+ MY(airfriction) = 4;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x2030FF";
+ MY(color_max) = "0x80C0FF";
+ MY(count) = 10;
+ MY(liquidfriction) = 16;
+ MY(size_min) = 32;
+ MY(size_max) = 32;
+ MY(type) = "static";
+ MY(velocityjitter) = '512.0 512.0 512.0';
+}
+
+// quake effect
+DEF(TE_SUPERSPIKE);
+// decal
+SUB(TE_SUPERSPIKE) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(originjitter) = '6.0 6.0 6.0';
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_min) = 56;
+ MY(tex_max) = 59;
+ MY(type) = "decal";
+}
+// dust/smoke drifting away from the impact
+SUB(TE_SUPERSPIKE) {
+ MY(alpha_min) = 255;
+ MY(alpha_max) = 255;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0x101010";
+ MY(color_max) = "0x101010";
+ MY(count) = 4;
+ MY(sizeincrease) = 3;
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '8.0 8.0 8.0';
+}
+// dust/smoke staying at the impact
+SUB(TE_SUPERSPIKE) {
+ MY(alpha_min) = 255;
+ MY(alpha_max) = 255;
+ MY(alpha_fade) = 128;
+ MY(color_min) = "0x505050";
+ MY(color_max) = "0x505050";
+ MY(count) = 0.500000;
+ MY(sizeincrease) = 4;
+ MY(size_min) = 4;
+ MY(size_max) = 4;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+}
+// sparks that disappear on impact
+SUB(TE_SUPERSPIKE) {
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 768;
+ MY(bounce) = -1;
+ MY(color_min) = "0x8f4333";
+ MY(color_max) = "0xfff31b";
+ MY(count) = 15;
+ MY(gravity) = 1;
+ MY(size_min) = 0.400000;
+ MY(size_max) = 0.400000;
+ MY(type) = "spark";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+ MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+// quake effect
+DEF(TE_SUPERSPIKEQUAD);
+// decal
+SUB(TE_SUPERSPIKEQUAD) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '0.2 0.2 1.5';
+ MY(lightradiusfade) = 500;
+ MY(lightradius) = 100;
+ MY(originjitter) = '6.0 6.0 6.0';
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_min) = 56;
+ MY(tex_max) = 59;
+ MY(type) = "decal";
+}
+// dust/smoke drifting away from the impact
+SUB(TE_SUPERSPIKEQUAD) {
+ MY(alpha_min) = 255;
+ MY(alpha_max) = 255;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0x101010";
+ MY(color_max) = "0x101010";
+ MY(count) = 4;
+ MY(sizeincrease) = 3;
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '8.0 8.0 8.0';
+}
+// dust/smoke staying at the impact
+SUB(TE_SUPERSPIKEQUAD) {
+ MY(alpha_min) = 255;
+ MY(alpha_max) = 255;
+ MY(alpha_fade) = 128;
+ MY(color_min) = "0x505050";
+ MY(color_max) = "0x505050";
+ MY(count) = 0.500000;
+ MY(sizeincrease) = 4;
+ MY(size_min) = 4;
+ MY(size_max) = 4;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+}
+// sparks that disappear on impact
+SUB(TE_SUPERSPIKEQUAD) {
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 768;
+ MY(bounce) = -1;
+ MY(color_min) = "0x8f4333";
+ MY(color_max) = "0xfff31b";
+ MY(count) = 15;
+ MY(gravity) = 1;
+ MY(size_min) = 0.400000;
+ MY(size_max) = 0.400000;
+ MY(type) = "spark";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+ MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+// shotgun pellet impact
+DEF(TE_GUNSHOT);
+// decal
+SUB(TE_GUNSHOT) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(originjitter) = '6.0 6.0 6.0';
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_min) = 56;
+ MY(tex_max) = 59;
+ MY(type) = "decal";
+}
+// dust/smoke drifting away from the impact
+SUB(TE_GUNSHOT) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0x101010";
+ MY(color_max) = "0x101010";
+ MY(count) = 0.800000;
+ MY(sizeincrease) = 3;
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '8.0 8.0 8.0';
+}
+// dust/smoke staying at the impact
+SUB(TE_GUNSHOT) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0x505050";
+ MY(color_max) = "0x505050";
+ MY(count) = 0.200000;
+ MY(sizeincrease) = 4;
+ MY(size_min) = 4;
+ MY(size_max) = 4;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+}
+// bouncing sparks
+SUB(TE_GUNSHOT) {
+ MY(alpha_max) = 64;
+ MY(alpha_fade) = 64;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x8f4333";
+ MY(color_max) = "0xfff31b";
+ MY(count) = 2.500000;
+ MY(gravity) = 1;
+ MY(size_min) = 0.400000;
+ MY(size_max) = 0.400000;
+ MY(type) = "spark";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+ MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+// crylink impact effect
+DEF(TE_GUNSHOTQUAD);
+// decal
+SUB(TE_GUNSHOTQUAD) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(originjitter) = '12.0 12.0 12.0';
+ MY(size_min) = 8;
+ MY(size_max) = 8;
+ MY(tex_min) = 47;
+ MY(tex_max) = 47;
+ MY(type) = "decal";
+}
+// purple flare effect
+SUB(TE_GUNSHOTQUAD) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x504060";
+ MY(color_max) = "0x504060";
+ MY(countabsolute) = 1;
+ MY(size_min) = 8;
+ MY(size_max) = 8;
+ MY(tex_min) = 39;
+ MY(tex_max) = 39;
+ MY(type) = "static";
+}
+// purple sparks
+SUB(TE_GUNSHOTQUAD) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 384;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0xA040C0";
+ MY(color_max) = "0xFFFFFF";
+ MY(count) = 6;
+ MY(gravity) = 1;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(type) = "spark";
+ MY(velocityjitter) = '128.0 128.0 128.0';
+ MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+// mortar/hagar explosion (smaller than rocket)
+DEF(TE_EXPLOSION);
+// decal
+SUB(TE_EXPLOSION) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '4.0 2.0 0.5';
+ MY(lightradiusfade) = 300;
+ MY(lightradius) = 150;
+ MY(originjitter) = '40.0 40.0 40.0';
+ MY(size_min) = 48;
+ MY(size_max) = 48;
+ MY(tex_min) = 8;
+ MY(tex_max) = 16;
+ MY(type) = "decal";
+}
+// flare effect
+SUB(TE_EXPLOSION) {
+ MY(alpha_min) = 192;
+ MY(alpha_max) = 192;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x404040";
+ MY(countabsolute) = 1;
+ MY(size_min) = 48;
+ MY(size_max) = 48;
+ MY(tex_min) = 35;
+ MY(tex_max) = 37;
+ MY(type) = "static";
+}
+// fire effect which expands then slows
+SUB(TE_EXPLOSION) {
+ MY(airfriction) = 4;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 256;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x902010";
+ MY(color_max) = "0xFFD080";
+ MY(count) = 64;
+ MY(liquidfriction) = 4;
+ MY(notunderwater) = true;
+ MY(originjitter) = '8.0 8.0 8.0';
+ MY(size_min) = 16;
+ MY(size_max) = 16;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "static";
+ MY(velocityjitter) = '256.0 256.0 256.0';
+}
+// underwater bubbles
+SUB(TE_EXPLOSION) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x808080";
+ MY(count) = 16;
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 0.250000;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '96.0 96.0 96.0';
+}
+// bouncing sparks
+SUB(TE_EXPLOSION) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 384;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x903010";
+ MY(color_max) = "0xFFD030";
+ MY(count) = 16;
+ MY(gravity) = 1;
+ MY(liquidfriction) = 0.800000;
+ MY(notunderwater) = true;
+ MY(size_min) = 2;
+ MY(size_max) = 2;
+ MY(type) = "spark";
+ MY(velocityjitter) = '256.0 256.0 256.0';
+ MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+// quake effect
+DEF(TE_EXPLOSIONQUAD);
+// decal
+SUB(TE_EXPLOSIONQUAD) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '4.0 2.0 8.0';
+ MY(lightradiusfade) = 700;
+ MY(lightradius) = 350;
+ MY(originjitter) = '40.0 40.0 40.0';
+ MY(size_min) = 48;
+ MY(size_max) = 48;
+ MY(tex_min) = 8;
+ MY(tex_max) = 16;
+ MY(type) = "decal";
+}
+// smoke cloud
+SUB(TE_EXPLOSIONQUAD) {
+ MY(alpha_min) = 32;
+ MY(alpha_max) = 32;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0x202020";
+ MY(color_max) = "0x404040";
+ MY(count) = 16;
+ MY(notunderwater) = true;
+ MY(size_min) = 12;
+ MY(size_max) = 12;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '48.0 48.0 48.0';
+}
+// underwater bubbles
+SUB(TE_EXPLOSIONQUAD) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x808080";
+ MY(count) = 16;
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 0.250000;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '96.0 96.0 96.0';
+}
+// sparks which go through walls
+SUB(TE_EXPLOSIONQUAD) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x903010";
+ MY(color_max) = "0xFFD030";
+ MY(count) = 64;
+ MY(gravity) = 1;
+ MY(liquidfriction) = 0.800000;
+ MY(notunderwater) = true;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(type) = "spark";
+ MY(velocityjitter) = '256.0 256.0 256.0';
+ MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+// quake effect
+DEF(TE_TAREXPLOSION);
+// decal
+SUB(TE_TAREXPLOSION) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '1.6 0.8 2.0';
+ MY(lightradiusfade) = 1200;
+ MY(lightradius) = 600;
+ MY(originjitter) = '40.0 40.0 40.0';
+ MY(size_min) = 48;
+ MY(size_max) = 48;
+ MY(tex_min) = 8;
+ MY(tex_max) = 16;
+ MY(type) = "decal";
+}
+// smoke cloud
+SUB(TE_TAREXPLOSION) {
+ MY(alpha_min) = 32;
+ MY(alpha_max) = 32;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0x202020";
+ MY(color_max) = "0x404040";
+ MY(count) = 16;
+ MY(notunderwater) = true;
+ MY(size_min) = 12;
+ MY(size_max) = 12;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '48.0 48.0 48.0';
+}
+// underwater bubbles
+SUB(TE_TAREXPLOSION) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x808080";
+ MY(count) = 16;
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 0.250000;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '96.0 96.0 96.0';
+}
+// sparks which go through walls
+SUB(TE_TAREXPLOSION) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x903010";
+ MY(color_max) = "0xFFD030";
+ MY(count) = 64;
+ MY(gravity) = 1;
+ MY(liquidfriction) = 0.800000;
+ MY(notunderwater) = true;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(type) = "spark";
+ MY(velocityjitter) = '256.0 256.0 256.0';
+ MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+// bloody impact effect indicating damage
+DEF(TE_BLOOD);
+SUB(TE_BLOOD) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = -1;
+ MY(count) = 0.167000;
+ MY(liquidfriction) = 4;
+ MY(size_min) = 8;
+ MY(size_max) = 8;
+ MY(staincolor_min) = "0x808080";
+ MY(staincolor_max) = "0x808080";
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(type) = "blood";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+ MY(velocitymultiplier) = 1;
+}
+
+// sparks (quake effect)
+DEF(TE_SPARK);
+SUB(TE_SPARK) {
+ MY(alpha_min) = 64;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 768;
+ MY(bounce) = -1;
+ MY(color_min) = "0x8f4333";
+ MY(color_max) = "0xfff31b";
+ MY(count) = 0.500000;
+ MY(gravity) = 1;
+ MY(size_min) = 0.400000;
+ MY(size_max) = 0.600000;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+ MY(velocitymultiplier) = 1;
+ MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+// vortex impact
+DEF(TE_PLASMABURN);
+// decal
+SUB(TE_PLASMABURN) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '1.0 1.0 1.0';
+ MY(lightradiusfade) = 400;
+ MY(lightradius) = 200;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(size_min) = 24;
+ MY(size_max) = 24;
+ MY(tex_min) = 47;
+ MY(tex_max) = 47;
+ MY(type) = "decal";
+}
+// flare effect
+SUB(TE_PLASMABURN) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x80C0FF";
+ MY(color_max) = "0x80C0FF";
+ MY(countabsolute) = 1;
+ MY(size_min) = 8;
+ MY(size_max) = 8;
+ MY(tex_min) = 37;
+ MY(tex_max) = 37;
+ MY(type) = "static";
+}
+// small sparks which form a sphere as they slow down
+SUB(TE_PLASMABURN) {
+ MY(airfriction) = 8;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1024;
+ MY(bounce) = 2;
+ MY(color_min) = "0x2030FF";
+ MY(color_max) = "0x80C0FF";
+ MY(count) = 128;
+ MY(liquidfriction) = 8;
+ MY(size_min) = 1;
+ MY(size_max) = 2;
+ MY(type) = "spark";
+ MY(velocityjitter) = '128.0 128.0 128.0';
+}
+
+// quake effect
+DEF(TE_SMALLFLASH);
+SUB(TE_SMALLFLASH) {
+ MY(lightcolor) = '2.0 2.0 2.0';
+ MY(lightradiusfade) = 1000;
+ MY(lightradius) = 200;
+}
+
+// quake effect
+DEF(TE_FLAMEJET);
+SUB(TE_FLAMEJET) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 64;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 384;
+ MY(bounce) = 1.100000;
+ MY(color_min) = "0x6f0f00";
+ MY(color_max) = "0xe3974f";
+ MY(count) = 0.500000;
+ MY(gravity) = -1;
+ MY(liquidfriction) = 4;
+ MY(size_min) = 4;
+ MY(size_max) = 4;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '128.0 128.0 128.0';
+ MY(velocitymultiplier) = 1;
+}
+
+// quake effect
+DEF(TE_LAVASPLASH);
+SUB(TE_LAVASPLASH) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0x6f0f00";
+ MY(color_max) = "0xe3974f";
+ MY(count) = 32;
+ MY(gravity) = 0.050000;
+ MY(originjitter) = '128.0 128.0 32.0';
+ MY(originoffset) = '0.0 0.0 32.0';
+ MY(size_min) = 12;
+ MY(size_max) = 12;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '128.0 128.0 0.0';
+ MY(velocityoffset) = '0.0 0.0 256.0';
+}
+
+// player teleport effect
+DEF(TE_TELEPORT);
+SUB(TE_TELEPORT) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 64;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0xA0A0A0";
+ MY(color_max) = "0xFFFFFF";
+ MY(count) = 56;
+ MY(liquidfriction) = 4;
+ MY(originjitter) = '16.0 16.0 28.0';
+ MY(originoffset) = '0.0 0.0 28.0';
+ MY(size_min) = 10;
+ MY(size_max) = 10;
+ MY(type) = "static";
+ MY(velocityjitter) = '0.0 0.0 256.0';
+}
+
+// vortex beam
+DEF(TE_TEI_G3);
+SUB(TE_TEI_G3) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0xFFFFFF";
+ MY(color_max) = "0xFFFFFF";
+ MY(countabsolute) = 1;
+ MY(size_min) = 4;
+ MY(size_max) = 4;
+ MY(tex_min) = 200;
+ MY(tex_max) = 200;
+ MY(type) = "beam";
+}
+SUB(TE_TEI_G3) {
+ MY(airfriction) = -4;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x202020";
+ MY(color_max) = "0x404040";
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(trailspacing) = 4;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '8.0 8.0 8.0';
+}
+
+// smoke effect
+DEF(TE_TEI_SMOKE);
+SUB(TE_TEI_SMOKE) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x202020";
+ MY(color_max) = "0x404040";
+ MY(count) = 0.167000;
+ MY(originjitter) = '1.5 1.5 1.5';
+ MY(size_min) = 5;
+ MY(size_max) = 5;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '6.0 6.0 6.0';
+ MY(velocitymultiplier) = 1;
+}
+
+// rocket explosion (bigger than mortar and hagar)
+DEF(TE_TEI_BIGEXPLOSION);
+// decal
+SUB(TE_TEI_BIGEXPLOSION) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '4.0 2.0 0.5';
+ MY(lightradiusfade) = 500;
+ MY(lightradius) = 500;
+ MY(originjitter) = '40.0 40.0 40.0';
+ MY(size_min) = 72;
+ MY(size_max) = 72;
+ MY(tex_min) = 8;
+ MY(tex_max) = 16;
+ MY(type) = "decal";
+}
+// flare effect
+SUB(TE_TEI_BIGEXPLOSION) {
+ MY(alpha_min) = 192;
+ MY(alpha_max) = 192;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x404040";
+ MY(countabsolute) = 1;
+ MY(size_min) = 72;
+ MY(size_max) = 72;
+ MY(tex_min) = 35;
+ MY(tex_max) = 37;
+ MY(type) = "static";
+}
+// fire effect
+SUB(TE_TEI_BIGEXPLOSION) {
+ MY(airfriction) = 4;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 256;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x902010";
+ MY(color_max) = "0xFFD080";
+ MY(count) = 128;
+ MY(liquidfriction) = 4;
+ MY(notunderwater) = true;
+ MY(originjitter) = '8.0 8.0 8.0';
+ MY(size_min) = 16;
+ MY(size_max) = 16;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "static";
+ MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// underwater bubbles
+SUB(TE_TEI_BIGEXPLOSION) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x808080";
+ MY(count) = 32;
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 0.250000;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '144.0 144.0 144.0';
+}
+// bouncing sparks
+SUB(TE_TEI_BIGEXPLOSION) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 384;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x903010";
+ MY(color_max) = "0xFFD030";
+ MY(count) = 64;
+ MY(gravity) = 1;
+ MY(liquidfriction) = 0.800000;
+ MY(notunderwater) = true;
+ MY(size_min) = 2;
+ MY(size_max) = 2;
+ MY(type) = "spark";
+ MY(velocityjitter) = '384.0 384.0 384.0';
+ MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+// electro explosion
+DEF(TE_TEI_PLASMAHIT);
+// decal
+SUB(TE_TEI_PLASMAHIT) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '2.4 4.8 8.0';
+ MY(lightradiusfade) = 600;
+ MY(lightradius) = 200;
+ MY(originjitter) = '20.0 20.0 20.0';
+ MY(size_min) = 32;
+ MY(size_max) = 32;
+ MY(tex_min) = 59;
+ MY(tex_max) = 59;
+ MY(type) = "decal";
+}
+// flare effect
+SUB(TE_TEI_PLASMAHIT) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x80C0FF";
+ MY(color_max) = "0x80C0FF";
+ MY(countabsolute) = 1;
+ MY(size_min) = 32;
+ MY(size_max) = 32;
+ MY(tex_min) = 38;
+ MY(tex_max) = 38;
+ MY(type) = "static";
+}
+// cloud of bouncing sparks
+SUB(TE_TEI_PLASMAHIT) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1024;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x2030FF";
+ MY(color_max) = "0x80C0FF";
+ MY(count) = 0.500000;
+ MY(size_min) = 2;
+ MY(size_max) = 4;
+ MY(type) = "spark";
+ MY(velocityjitter) = '512.0 512.0 512.0';
+}
+
+// bloody impact effect indicating damage
+DEF(blood);
+SUB(blood) {
+ MY(airfriction) = 0.400000;
+ MY(alpha_min) = 1560;
+ MY(alpha_max) = 2560;
+ MY(alpha_fade) = 7000;
+ MY(blend) = "invmod";
+ MY(bounce) = -1;
+ MY(color_min) = "0xA8FFFF";
+ MY(color_max) = "0xA8FFFFF";
+ MY(count) = 0.400000;
+ MY(sizeincrease) = 20;
+ MY(size_min) = 5;
+ MY(size_max) = 11;
+ MY(staincolor_min) = "0x808080";
+ MY(staincolor_max) = "0x808080";
+ MY(stainsize_min) = 1;
+ MY(stainsize_max) = 2;
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(stretchfactor) = 20;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(type) = "spark";
+ MY(velocityjitter) = '99.0 99.0 55.0';
+}
+//blood mist
+SUB(blood) {
+ MY(alpha_min) = 100;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 400;
+ MY(blend) = "invmod";
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x420000";
+ MY(countabsolute) = 1;
+ MY(originjitter) = '11.0 11.0 11.0';
+ MY(sizeincrease) = 20;
+ MY(size_min) = 25;
+ MY(size_max) = 30;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(type) = "alphastatic";
+}
+
+// player teleport effect
+DEF(teleport);
+SUB(teleport) {
+ MY(airfriction) = 2;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 100;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x807aff";
+ MY(color_max) = "0x4463d5";
+ MY(count) = 500;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(stretchfactor) = 0.600000;
+ MY(tex_min) = 64;
+ MY(tex_max) = 64;
+ MY(type) = "spark";
+ MY(velocityjitter) = '1000.0 1000.0 1500.0';
+ MY(velocitymultiplier) = 0.500000;
+}
+SUB(teleport) {
+ MY(alpha_min) = 190;
+ MY(alpha_max) = 190;
+ MY(alpha_fade) = 180;
+ MY(color_min) = "0x807aff";
+ MY(color_max) = "0x4463d5";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = -80;
+ MY(size_min) = 150;
+ MY(size_max) = 150;
+ MY(tex_min) = 65;
+ MY(tex_max) = 65;
+ MY(type) = "smoke";
+}
+
+// normal super gory blood trail (used by gibs)
+DEF(TR_BLOOD);
+SUB(TR_BLOOD) {
+ MY(airfriction) = -2;
+ MY(alpha_min) = 384;
+ MY(alpha_max) = 984;
+ MY(alpha_fade) = 1492;
+ MY(blend) = "invmod";
+ MY(bounce) = -1;
+ MY(color_min) = "0xA8FFFF";
+ MY(color_max) = "0xA8FFFF";
+ MY(gravity) = 0.400000;
+ MY(liquidfriction) = 1;
+ MY(sizeincrease) = -5;
+ MY(size_min) = 4;
+ MY(size_max) = 19;
+ MY(staincolor_min) = "0x808080";
+ MY(staincolor_max) = "0x808080";
+ MY(stainsize_min) = 1;
+ MY(stainsize_max) = 2;
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(stretchfactor) = 7;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(trailspacing) = 20;
+ MY(type) = "spark";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+ MY(velocitymultiplier) = -0.100000;
+}
+// splash around gib
+SUB(TR_BLOOD) {
+ MY(alpha_min) = 684;
+ MY(alpha_max) = 684;
+ MY(alpha_fade) = 7492;
+ MY(color_min) = "0xA8FFFF";
+ MY(color_max) = "0xA8FFFF";
+ MY(sizeincrease) = 500;
+ MY(size_min) = 4;
+ MY(size_max) = 6;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(trailspacing) = 42;
+ MY(type) = "blood";
+}
+
+// thinner blood trail (used by quake zombies)
+DEF(TR_SLIGHTBLOOD);
+SUB(TR_SLIGHTBLOOD) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 384;
+ MY(alpha_max) = 384;
+ MY(alpha_fade) = 192;
+ MY(bounce) = -1;
+ MY(color_min) = "0xA8FFFF";
+ MY(color_max) = "0xA8FFFF";
+ MY(liquidfriction) = 4;
+ MY(size_min) = 8;
+ MY(size_max) = 8;
+ MY(staincolor_min) = "0x808080";
+ MY(staincolor_max) = "0x808080";
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(trailspacing) = 64;
+ MY(type) = "blood";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+ MY(velocitymultiplier) = 0.500000;
+}
+
+// func_stardust effect, used in some maps to indicate teleporters
+DEF(EF_STARDUST);
+SUB(EF_STARDUST) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_min) = 64;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 128;
+ MY(color_min) = "0xfff368";
+ MY(color_max) = "0xfff368";
+ MY(count) = 37.500000;
+ MY(gravity) = -0.100000;
+ MY(liquidfriction) = 0.800000;
+ MY(originjitter) = '16.0 16.0 64.0';
+ MY(size_min) = 1;
+ MY(size_max) = 2;
+ MY(type) = "static";
+ MY(velocityjitter) = '32.0 32.0 0.0';
+}
+
+// flare particle and light
+DEF(item_respawn);
+SUB(item_respawn) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 128;
+ MY(color_min) = "0x63F2EA";
+ MY(color_max) = "0x63f2EA";
+ MY(countabsolute) = 1;
+ MY(size_min) = 32;
+ MY(size_max) = 32;
+ MY(type) = "static";
+}
+// cloud of particles which expand rapidly and then slow to form a ball
+SUB(item_respawn) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1280;
+ MY(color_min) = "0x63F2EA";
+ MY(color_max) = "0x63f2EA";
+ MY(count) = 128;
+ MY(size_min) = 2;
+ MY(size_max) = 2;
+ MY(tex_min) = 41;
+ MY(tex_max) = 41;
+ MY(type) = "spark";
+ MY(velocityjitter) = '256.0 256.0 256.0';
+}
+
+DEF(jumppad_activate);
+SUB(jumppad_activate) {
+ MY(lightcolor) = '2.0 2.0 2.0';
+ MY(lightradiusfade) = 2000;
+ MY(lightradius) = 200;
+}
+
+DEF(laser_muzzleflash);
+// glow and light
+SUB(laser_muzzleflash) {
+ MY(airfriction) = 10;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 512;
+ MY(alpha_fade) = 6280;
+ MY(color_min) = "0xcc0000";
+ MY(color_max) = "0xff0000";
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '3.0 0.1 0.1';
+ MY(lightradiusfade) = 2000;
+ MY(lightradius) = 200;
+ MY(sizeincrease) = -100;
+ MY(size_min) = 10;
+ MY(size_max) = 15;
+ MY(stretchfactor) = 2;
+ MY(tex_min) = 65;
+ MY(tex_max) = 65;
+ MY(type) = "smoke";
+}
+// electricity
+SUB(laser_muzzleflash) {
+ MY(airfriction) = 10;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 512;
+ MY(alpha_fade) = 6280;
+ MY(color_min) = "0xb44215";
+ MY(color_max) = "0xff0000";
+ MY(count) = 3;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = 4000;
+ MY(spin_max) = -4000;
+ MY(sizeincrease) = -100;
+ MY(size_min) = 5;
+ MY(size_max) = 7;
+ MY(stretchfactor) = 2.300000;
+ MY(tex_min) = 43;
+ MY(tex_max) = 43;
+ MY(type) = "spark";
+ MY(velocityjitter) = '150.0 150.0 150.0';
+ MY(velocitymultiplier) = 0.200000;
+}
+// fire
+SUB(laser_muzzleflash) {
+ MY(airfriction) = 12;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 512;
+ MY(alpha_fade) = 6280;
+ MY(color_min) = "0xff4200";
+ MY(color_max) = "0xff0000";
+ MY(count) = 6;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(sizeincrease) = -100;
+ MY(size_min) = 7;
+ MY(size_max) = 9;
+ MY(stretchfactor) = 2;
+ MY(tex_min) = 8;
+ MY(tex_max) = 15;
+ MY(type) = "spark";
+ MY(velocityjitter) = '100.0 100.0 100.0';
+ MY(velocitymultiplier) = 0.200000;
+}
+
+DEF(laser_impact);
+// decal
+SUB(laser_impact) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '8.0 0.4 0.4';
+ MY(lightradiusfade) = 500;
+ MY(lightradius) = 200;
+ MY(originjitter) = '14.0 14.0 14.0';
+ MY(size_min) = 24;
+ MY(size_max) = 24;
+ MY(tex_min) = 47;
+ MY(tex_max) = 47;
+ MY(type) = "decal";
+}
+// flare effect
+SUB(laser_impact) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0xFF2010";
+ MY(color_max) = "0xFF2010";
+ MY(countabsolute) = 1;
+ MY(size_min) = 24;
+ MY(size_max) = 24;
+ MY(tex_min) = 39;
+ MY(tex_max) = 39;
+ MY(type) = "static";
+}
+// sparks that rapidly expand and rapidly slow down to form an interesting spherical effect
+SUB(laser_impact) {
+ MY(airfriction) = 6;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0x800000";
+ MY(color_max) = "0xFF8020";
+ MY(count) = 128;
+ MY(liquidfriction) = 6;
+ MY(size_min) = 4;
+ MY(size_max) = 4;
+ MY(type) = "spark";
+ MY(velocityjitter) = '256.0 256.0 256.0';
+}
+SUB(laser_impact) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0x800000";
+ MY(color_max) = "0xFF8020";
+ MY(count) = 4;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(sizeincrease) = 6;
+ MY(size_min) = 12;
+ MY(size_max) = 12;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '16.0 16.0 16.0';
+ MY(velocitymultiplier) = 0.010000;
+}
+
+DEF(shotgun_muzzleflash);
+SUB(shotgun_muzzleflash) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x202020";
+ MY(color_max) = "0x404040";
+ MY(count) = 1.500000;
+ MY(lightcolor) = '2.0 1.5 0.2';
+ MY(lightradiusfade) = 2000;
+ MY(lightradius) = 200;
+ MY(originjitter) = '1.5 1.5 1.5';
+ MY(sizeincrease) = 12;
+ MY(size_min) = 5;
+ MY(size_max) = 5;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '6.0 6.0 6.0';
+ MY(velocitymultiplier) = 0.050000;
+}
+SUB(shotgun_muzzleflash) {
+ MY(airfriction) = 5;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0xffdb96";
+ MY(color_max) = "0xff5400";
+ MY(count) = 16;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 10;
+ MY(size_max) = 20;
+ MY(stretchfactor) = 2.500000;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "spark";
+ MY(velocityjitter) = '100.0 100.0 100.0';
+ MY(velocitymultiplier) = 0.500000;
+}
+
+// shotgun pellet impact
+DEF(shotgun_impact);
+// decal
+SUB(shotgun_impact) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(originjitter) = '10.0 10.0 10.0';
+ MY(size_min) = 5;
+ MY(size_max) = 8;
+ MY(tex_min) = 56;
+ MY(tex_max) = 59;
+ MY(type) = "decal";
+}
+// dust/smoke drifting away from the impact
+SUB(shotgun_impact) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 300;
+ MY(alpha_max) = 550;
+ MY(alpha_fade) = 756;
+ MY(color_min) = "0x473a37";
+ MY(color_max) = "0x0b0a07";
+ MY(count) = 1;
+ MY(notunderwater) = true;
+ MY(startangle_max) = 360;
+ MY(spin_min) = -50;
+ MY(spin_max) = 50;
+ MY(sizeincrease) = 25;
+ MY(size_min) = 10;
+ MY(size_max) = 20;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '150.0 150.0 150.0';
+ MY(velocitymultiplier) = 0.200000;
+}
+// dust/smoke staying at the impact
+SUB(shotgun_impact) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 350;
+ MY(alpha_fade) = 500;
+ MY(bounce) = 6;
+ MY(color_min) = "0x201d1a";
+ MY(color_max) = "0x000000";
+ MY(count) = 0.200000;
+ MY(notunderwater) = true;
+ MY(startangle_max) = 360;
+ MY(spin_min) = -50;
+ MY(spin_max) = 50;
+ MY(sizeincrease) = 74;
+ MY(size_min) = 10;
+ MY(size_max) = 11;
+ MY(tex_min) = 36;
+ MY(tex_max) = 36;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '11.0 11.0 11.0';
+ MY(velocitymultiplier) = 0.030000;
+}
+// sparks
+SUB(shotgun_impact) {
+ MY(airfriction) = 1.100000;
+ MY(alpha_max) = 356;
+ MY(alpha_fade) = 268;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0xFDFFD9";
+ MY(color_max) = "0xFDFFD9";
+ MY(count) = 0.500000;
+ MY(gravity) = 1;
+ MY(notunderwater) = true;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 0.600000;
+ MY(size_max) = 0.600000;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '200.0 200.0 200.0';
+ MY(velocitymultiplier) = 0.200000;
+}
+
+DEF(uzi_muzzleflash);
+SUB(uzi_muzzleflash) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x202020";
+ MY(color_max) = "0x404040";
+ MY(count) = 1;
+ MY(gravity) = -0.100000;
+ MY(lightcolor) = '2.0 1.5 0.2';
+ MY(lightradiusfade) = 2000;
+ MY(lightradius) = 200;
+ MY(originjitter) = '1.5 1.5 1.5';
+ MY(size_min) = 5;
+ MY(size_max) = 5;
+ MY(tex_max) = 8;
+ MY(type) = "static";
+ MY(velocityjitter) = '1.0 1.0 1.0';
+ MY(velocitymultiplier) = 0.030000;
+}
+SUB(uzi_muzzleflash) {
+ MY(airfriction) = 12;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 6000;
+ MY(color_min) = "0xff9c00";
+ MY(color_max) = "0xffd200";
+ MY(count) = 3;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 0.300000;
+ MY(size_max) = 0.400000;
+ MY(stretchfactor) = 0.150000;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '555.0 555.0 555.0';
+ MY(velocitymultiplier) = 3;
+}
+
+DEF(machinegun_impact);
+// decal
+SUB(machinegun_impact) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '6.0 3.6 0.6';
+ MY(lightradiusfade) = 800;
+ MY(lightradius) = 80;
+ MY(originjitter) = '10.0 10.0 10.0';
+ MY(size_min) = 5;
+ MY(size_max) = 5;
+ MY(tex_min) = 56;
+ MY(tex_max) = 59;
+ MY(type) = "decal";
+}
+// dust/smoke drifting away from the impact
+SUB(machinegun_impact) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 300;
+ MY(alpha_max) = 550;
+ MY(alpha_fade) = 456;
+ MY(color_min) = "0x473a37";
+ MY(color_max) = "0x0b0a07";
+ MY(count) = 1.500000;
+ MY(notunderwater) = true;
+ MY(startangle_max) = 360;
+ MY(spin_min) = -50;
+ MY(spin_max) = 50;
+ MY(sizeincrease) = 15;
+ MY(size_min) = 10;
+ MY(size_max) = 20;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '150.0 150.0 150.0';
+ MY(velocitymultiplier) = 0.100000;
+}
+// dust/smoke staying at the impact
+SUB(machinegun_impact) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 350;
+ MY(alpha_fade) = 500;
+ MY(bounce) = 6;
+ MY(color_min) = "0x201d1a";
+ MY(color_max) = "0x000000";
+ MY(count) = 0.500000;
+ MY(notunderwater) = true;
+ MY(startangle_max) = 360;
+ MY(spin_min) = -50;
+ MY(spin_max) = 50;
+ MY(sizeincrease) = 74;
+ MY(size_min) = 10;
+ MY(size_max) = 11;
+ MY(tex_min) = 36;
+ MY(tex_max) = 36;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '11.0 11.0 11.0';
+ MY(velocitymultiplier) = 0.030000;
+}
+// debris
+SUB(machinegun_impact) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 300;
+ MY(alpha_max) = 550;
+ MY(alpha_fade) = 256;
+ MY(bounce) = 1.700000;
+ MY(color_min) = "0x63493e";
+ MY(color_max) = "0xffffff";
+ MY(count) = 1;
+ MY(gravity) = 1.400000;
+ MY(notunderwater) = true;
+ MY(startangle_max) = 360;
+ MY(spin_min) = -500;
+ MY(spin_max) = 500;
+ MY(size_min) = 1;
+ MY(size_max) = 5;
+ MY(tex_min) = 66;
+ MY(tex_max) = 68;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '350.0 350.0 350.0';
+ MY(velocitymultiplier) = 0.200000;
+}
+// sparks
+SUB(machinegun_impact) {
+ MY(airfriction) = 2;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 168;
+ MY(bounce) = 1;
+ MY(color_min) = "0xFDFFD9";
+ MY(color_max) = "0xFDFFD9";
+ MY(count) = 1;
+ MY(gravity) = 1;
+ MY(notunderwater) = true;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 0.300000;
+ MY(size_max) = 0.300000;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '300.0 300.0 300.0';
+ MY(velocitymultiplier) = 0.200000;
+}
+
+DEF(grenadelauncher_muzzleflash);
+SUB(grenadelauncher_muzzleflash) {
+ MY(airfriction) = 12;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x202020";
+ MY(color_max) = "0x404040";
+ MY(count) = 1.500000;
+ MY(lightcolor) = '2.0 1.5 0.2';
+ MY(lightradiusfade) = 2000;
+ MY(lightradius) = 200;
+ MY(originjitter) = '1.5 1.5 1.5';
+ MY(size_min) = 5;
+ MY(size_max) = 5;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '20.0 20.0 20.0';
+ MY(velocitymultiplier) = 0.030000;
+}
+SUB(grenadelauncher_muzzleflash) {
+ MY(airfriction) = 5;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0xffdb96";
+ MY(color_max) = "0xff5400";
+ MY(count) = 16;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 10;
+ MY(size_max) = 20;
+ MY(stretchfactor) = 2.500000;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "spark";
+ MY(velocityjitter) = '100.0 100.0 100.0';
+ MY(velocitymultiplier) = 0.500000;
+}
+
+// mortar trail
+DEF(TR_GRENADE);
+// smoke
+SUB(TR_GRENADE) {
+ MY(alpha_min) = 300;
+ MY(alpha_max) = 400;
+ MY(alpha_fade) = 780;
+ MY(bounce) = 1;
+ MY(color_min) = "0x101010";
+ MY(color_max) = "0x000000";
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(sizeincrease) = 10;
+ MY(size_min) = 3;
+ MY(size_max) = 2;
+ MY(tex_max) = 8;
+ MY(trailspacing) = 4;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '1.0 1.0 1.0';
+ MY(velocitymultiplier) = -0.020000;
+}
+// fire
+SUB(TR_GRENADE) {
+ MY(airfriction) = 8;
+ MY(alpha_min) = 100;
+ MY(alpha_max) = 144;
+ MY(alpha_fade) = 988;
+ MY(color_min) = "0xffdf72";
+ MY(color_max) = "0x811200";
+ MY(notunderwater) = true;
+ MY(sizeincrease) = -15;
+ MY(size_min) = 5;
+ MY(size_max) = 2;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(trailspacing) = 4;
+ MY(type) = "static";
+ MY(velocityjitter) = '32.0 32.0 32.0';
+ MY(velocitymultiplier) = -1;
+}
+// bubbles
+SUB(TR_GRENADE) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x808080";
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 4;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(trailspacing) = 16;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '16.0 16.0 16.0';
+}
+
+// hookbomb trail
+DEF(TR_KNIGHTSPIKE);
+// smoke
+SUB(TR_KNIGHTSPIKE) {
+ MY(alpha_min) = 300;
+ MY(alpha_max) = 400;
+ MY(alpha_fade) = 600;
+ MY(bounce) = 1;
+ MY(color_min) = "0x303030";
+ MY(color_max) = "0x000000";
+ MY(gravity) = -0.110000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(sizeincrease) = 11;
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_max) = 8;
+ MY(trailspacing) = 6;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '3.0 3.0 3.0';
+ MY(velocitymultiplier) = -0.020000;
+}
+// marker
+SUB(TR_KNIGHTSPIKE) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 720;
+ MY(color_min) = "0x666666";
+ MY(color_max) = "0x000000";
+ MY(sizeincrease) = -0.100000;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(trailspacing) = 2;
+ MY(type) = "alphastatic";
+}
+// bubbles
+SUB(TR_KNIGHTSPIKE) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x808080";
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 4;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(trailspacing) = 32;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '16.0 16.0 16.0';
+}
+
+DEF(grenade_explode);
+// decal
+SUB(grenade_explode) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '8.0 4.0 1.0';
+ MY(lightradiusfade) = 400;
+ MY(lightradius) = 250;
+ MY(originjitter) = '26.0 26.0 26.0';
+ MY(size_min) = 48;
+ MY(size_max) = 48;
+ MY(tex_min) = 8;
+ MY(tex_max) = 16;
+ MY(type) = "decal";
+}
+// fire effect which expands then slows
+SUB(grenade_explode) {
+ MY(airfriction) = 8;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 228;
+ MY(alpha_fade) = 356;
+ MY(bounce) = 4.500000;
+ MY(color_min) = "0xe03f00";
+ MY(color_max) = "0x5e0000";
+ MY(count) = 40;
+ MY(liquidfriction) = 8;
+ MY(notunderwater) = true;
+ MY(originjitter) = '8.0 8.0 8.0';
+ MY(sizeincrease) = 20;
+ MY(size_min) = 16;
+ MY(size_max) = 26;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "static";
+ MY(velocityjitter) = '256.0 256.0 256.0';
+}
+// fire effect which make bright dot inside
+SUB(grenade_explode) {
+ MY(airfriction) = 8;
+ MY(alpha_min) = 228;
+ MY(alpha_max) = 328;
+ MY(alpha_fade) = 756;
+ MY(bounce) = 1;
+ MY(color_min) = "0xe03f00";
+ MY(color_max) = "0xffdf92";
+ MY(count) = 15;
+ MY(liquidfriction) = 8;
+ MY(notunderwater) = true;
+ MY(originjitter) = '8.0 8.0 8.0';
+ MY(sizeincrease) = 40;
+ MY(size_min) = 6;
+ MY(size_max) = 16;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "static";
+ MY(velocityjitter) = '256.0 256.0 256.0';
+}
+// smoke
+SUB(grenade_explode) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 300;
+ MY(alpha_max) = 550;
+ MY(alpha_fade) = 556;
+ MY(bounce) = 6;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x111111";
+ MY(count) = 10;
+ MY(notunderwater) = true;
+ MY(sizeincrease) = 34;
+ MY(size_min) = 20;
+ MY(size_max) = 40;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '256.0 256.0 256.0';
+}
+// underwater bubbles
+SUB(grenade_explode) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x808080";
+ MY(count) = 32;
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 0.250000;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(size_min) = 3;
+ MY(size_max) = 6;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '196.0 196.0 196.0';
+}
+// underwatershockwave
+SUB(grenade_explode) {
+ MY(alpha_min) = 40;
+ MY(alpha_max) = 40;
+ MY(alpha_fade) = 300;
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 1500;
+ MY(size_min) = 5;
+ MY(size_max) = 5;
+ MY(tex_min) = 33;
+ MY(tex_max) = 33;
+ MY(type) = "smoke";
+ MY(underwater) = true;
+ MY(velocitymultiplier) = 0.300000;
+}
+// bouncing sparks
+SUB(grenade_explode) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 644;
+ MY(alpha_max) = 956;
+ MY(alpha_fade) = 484;
+ MY(bounce) = 1.600000;
+ MY(color_min) = "0xffa35b";
+ MY(color_max) = "0xfff2be";
+ MY(count) = 16;
+ MY(gravity) = 1;
+ MY(liquidfriction) = 0.800000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(size_min) = 1;
+ MY(size_max) = 0.100000;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '424.0 424.0 624.0';
+ MY(velocityoffset) = '0.0 0.0 80.0';
+}
+// debris
+SUB(grenade_explode) {
+ MY(airfriction) = 0.500000;
+ MY(alpha_min) = 644;
+ MY(alpha_max) = 956;
+ MY(alpha_fade) = 684;
+ MY(bounce) = 1.600000;
+ MY(color_min) = "0x6a3d25";
+ MY(color_max) = "0xcac5b4";
+ MY(count) = 12;
+ MY(gravity) = 1.300000;
+ MY(notunderwater) = true;
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -1000;
+ MY(spin_max) = 1000;
+ MY(size_min) = 2;
+ MY(size_max) = 6;
+ MY(tex_min) = 66;
+ MY(tex_max) = 68;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '324.0 324.0 524.0';
+}
+
+DEF(electro_muzzleflash);
+SUB(electro_muzzleflash) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x283880";
+ MY(color_max) = "0x283880";
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '1.5 3.0 6.0';
+ MY(lightradiusfade) = 2000;
+ MY(lightradius) = 200;
+ MY(originjitter) = '1.5 1.5 1.5';
+ MY(sizeincrease) = -10;
+ MY(size_min) = 15;
+ MY(size_max) = 15;
+ MY(tex_min) = 65;
+ MY(tex_max) = 65;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '6.0 6.0 6.0';
+ MY(velocitymultiplier) = 0.010000;
+}
+SUB(electro_muzzleflash) {
+ MY(airfriction) = 2;
+ MY(alpha_min) = 110;
+ MY(alpha_max) = 228;
+ MY(alpha_fade) = 2024;
+ MY(color_min) = "0xD9FDFF";
+ MY(color_max) = "0xD9FDFF";
+ MY(count) = 7;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 5;
+ MY(size_max) = 15;
+ MY(stretchfactor) = 1.500000;
+ MY(tex_min) = 8;
+ MY(tex_max) = 15;
+ MY(type) = "spark";
+ MY(velocityjitter) = '150.0 150.0 150.0';
+ MY(velocitymultiplier) = 0.500000;
+}
+SUB(electro_muzzleflash) {
+ MY(airfriction) = 8;
+ MY(alpha_min) = 110;
+ MY(alpha_max) = 228;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0xD9FDFF";
+ MY(color_max) = "0xD9FDFF";
+ MY(count) = 5;
+ MY(gravity) = 1.300000;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 7;
+ MY(size_max) = 6;
+ MY(stretchfactor) = 0.100000;
+ MY(tex_min) = 41;
+ MY(tex_max) = 41;
+ MY(type) = "spark";
+ MY(velocityjitter) = '350.0 350.0 350.0';
+ MY(velocitymultiplier) = 2.500000;
+}
+
+// electro trail
+DEF(TR_NEXUIZPLASMA);
+// glowing vapor trail
+SUB(TR_NEXUIZPLASMA) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 968;
+ MY(color_min) = "0x283880";
+ MY(color_max) = "0x283880";
+ MY(lightcolor) = '1.5 3.0 6.0';
+ MY(lightradius) = 90;
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_min) = 38;
+ MY(tex_max) = 38;
+ MY(trailspacing) = 2;
+ MY(type) = "static";
+ MY(velocitymultiplier) = -0.100000;
+}
+// bright sparks
+SUB(TR_NEXUIZPLASMA) {
+ MY(airfriction) = 12;
+ MY(alpha_min) = 444;
+ MY(alpha_max) = 512;
+ MY(alpha_fade) = 1866;
+ MY(bounce) = 1;
+ MY(color_min) = "0x629dff";
+ MY(color_max) = "0x0018ff";
+ MY(count) = 1.500000;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(sizeincrease) = -20;
+ MY(size_min) = 2;
+ MY(size_max) = 4;
+ MY(tex_min) = 42;
+ MY(tex_max) = 42;
+ MY(trailspacing) = 12;
+ MY(type) = "snow";
+ MY(velocityjitter) = '50.0 50.0 50.0';
+ MY(velocityoffset) = '0.0 0.0 15.0';
+}
+
+DEF(electro_impact);
+// decal
+SUB(electro_impact) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '3.1 4.4 10.0';
+ MY(lightradiusfade) = 250;
+ MY(lightradius) = 250;
+ MY(originjitter) = '17.0 17.0 17.0';
+ MY(size_min) = 32;
+ MY(size_max) = 32;
+ MY(tex_min) = 59;
+ MY(tex_max) = 59;
+ MY(type) = "decal";
+}
+// shockwave
+SUB(electro_impact) {
+ MY(alpha_min) = 40;
+ MY(alpha_max) = 40;
+ MY(alpha_fade) = 350;
+ MY(color_min) = "0x80C0FF";
+ MY(color_max) = "0x80C0FF";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 1000;
+ MY(size_min) = 32;
+ MY(size_max) = 32;
+ MY(tex_min) = 33;
+ MY(tex_max) = 33;
+ MY(type) = "smoke";
+ MY(velocitymultiplier) = 44;
+}
+// flare effect
+SUB(electro_impact) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x80C0FF";
+ MY(color_max) = "0x80C0FF";
+ MY(countabsolute) = 1;
+ MY(size_min) = 12;
+ MY(size_max) = 32;
+ MY(tex_min) = 38;
+ MY(tex_max) = 38;
+ MY(type) = "static";
+}
+// cloud of bouncing sparks
+SUB(electro_impact) {
+ MY(airfriction) = 6;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1024;
+ MY(bounce) = 2;
+ MY(color_min) = "0x629dff";
+ MY(color_max) = "0x0018ff";
+ MY(count) = 30;
+ MY(gravity) = -0.300000;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -9999;
+ MY(spin_max) = 9999;
+ MY(sizeincrease) = -50;
+ MY(size_min) = 36;
+ MY(size_max) = 36;
+ MY(tex_min) = 42;
+ MY(tex_max) = 42;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// inner cloud of smoke
+SUB(electro_impact) {
+ MY(airfriction) = 30;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x629dff";
+ MY(color_max) = "0x0018ff";
+ MY(count) = 30;
+ MY(originjitter) = '20.0 20.0 20.0';
+ MY(sizeincrease) = 50;
+ MY(size_min) = 20;
+ MY(size_max) = 24;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '320.0 320.0 320.0';
+}
+
+DEF(electro_ballexplode);
+// decal
+SUB(electro_ballexplode) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '3.1 4.4 10.0';
+ MY(lightradiusfade) = 250;
+ MY(lightradius) = 250;
+ MY(originjitter) = '17.0 17.0 17.0';
+ MY(size_min) = 32;
+ MY(size_max) = 32;
+ MY(tex_min) = 59;
+ MY(tex_max) = 59;
+ MY(type) = "decal";
+}
+// flare effect
+SUB(electro_ballexplode) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x80C0FF";
+ MY(color_max) = "0x80C0FF";
+ MY(countabsolute) = 1;
+ MY(size_min) = 32;
+ MY(size_max) = 32;
+ MY(tex_min) = 38;
+ MY(tex_max) = 38;
+ MY(type) = "static";
+}
+// cloud of bouncing sparks
+SUB(electro_ballexplode) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1024;
+ MY(bounce) = 2;
+ MY(color_min) = "0xFDFFD9";
+ MY(color_max) = "0xFDFFD9";
+ MY(count) = 64;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 1;
+ MY(size_max) = 2;
+ MY(stretchfactor) = 0.400000;
+ MY(tex_min) = 41;
+ MY(tex_max) = 41;
+ MY(type) = "spark";
+ MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// inner cloud of smoke
+SUB(electro_ballexplode) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x202020";
+ MY(color_max) = "0x404040";
+ MY(count) = 8;
+ MY(originjitter) = '20.0 20.0 20.0';
+ MY(size_min) = 24;
+ MY(size_max) = 24;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '32.0 32.0 32.0';
+}
+
+DEF(electro_combo);
+// decal
+SUB(electro_combo) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '4.0 5.0 6.0';
+ MY(lightradiusfade) = 300;
+ MY(lightradius) = 400;
+ MY(originjitter) = '17.0 17.0 17.0';
+ MY(size_min) = 64;
+ MY(size_max) = 64;
+ MY(tex_min) = 59;
+ MY(tex_max) = 59;
+ MY(type) = "decal";
+}
+// flare effect
+SUB(electro_combo) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0x80C0FF";
+ MY(color_max) = "0x80C0FF";
+ MY(countabsolute) = 1;
+ MY(size_min) = 48;
+ MY(size_max) = 48;
+ MY(tex_min) = 38;
+ MY(tex_max) = 38;
+ MY(type) = "static";
+}
+// large sparks
+SUB(electro_combo) {
+ MY(airfriction) = 6;
+ MY(alpha_min) = 156;
+ MY(alpha_max) = 156;
+ MY(alpha_fade) = 156;
+ MY(bounce) = 2;
+ MY(color_min) = "0x2030FF";
+ MY(color_max) = "0x80C0FF";
+ MY(count) = 5;
+ MY(liquidfriction) = 16;
+ MY(sizeincrease) = 50;
+ MY(size_min) = 32;
+ MY(size_max) = 32;
+ MY(tex_max) = 7;
+ MY(type) = "static";
+ MY(velocityjitter) = '512.0 512.0 512.0';
+}
+SUB(electro_combo) {
+ MY(alpha_min) = 444;
+ MY(alpha_max) = 512;
+ MY(alpha_fade) = 700;
+ MY(bounce) = 1.600000;
+ MY(color_min) = "0xa9cacf";
+ MY(color_max) = "0x0054ff";
+ MY(count) = 32;
+ MY(gravity) = 0.300000;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 2;
+ MY(size_max) = 4;
+ MY(stretchfactor) = 2;
+ MY(tex_min) = 41;
+ MY(tex_max) = 41;
+ MY(type) = "spark";
+ MY(velocityjitter) = '312.0 312.0 312.0';
+ MY(velocitymultiplier) = 3;
+}
+// inner cloud of smoke
+SUB(electro_combo) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0x202020";
+ MY(color_max) = "0x404040";
+ MY(count) = 0.125000;
+ MY(originjitter) = '20.0 20.0 20.0';
+ MY(size_min) = 24;
+ MY(size_max) = 24;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '32.0 32.0 32.0';
+}
+// shockwave
+SUB(electro_combo) {
+ MY(alpha_min) = 40;
+ MY(alpha_max) = 40;
+ MY(alpha_fade) = 100;
+ MY(color_min) = "0xa9cacf";
+ MY(color_max) = "0x0054ff";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 600;
+ MY(size_min) = 30;
+ MY(size_max) = 30;
+ MY(tex_min) = 33;
+ MY(tex_max) = 33;
+ MY(type) = "smoke";
+ MY(velocitymultiplier) = 0.300000;
+}
+
+DEF(crylink_muzzleflash);
+SUB(crylink_muzzleflash) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 2024;
+ MY(color_min) = "0xdd9cff";
+ MY(color_max) = "0xff0090";
+ MY(count) = 0.500000;
+ MY(lightcolor) = '1.6 0.2 2.0';
+ MY(lightradiusfade) = 2000;
+ MY(lightradius) = 200;
+ MY(size_min) = 15;
+ MY(size_max) = 20;
+ MY(tex_min) = 65;
+ MY(tex_max) = 65;
+ MY(type) = "smoke";
+ MY(velocitymultiplier) = 0.010000;
+}
+SUB(crylink_muzzleflash) {
+ MY(airfriction) = 12;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0xA080C0";
+ MY(color_max) = "0xA080C0";
+ MY(count) = 5;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 5;
+ MY(size_max) = 10;
+ MY(stretchfactor) = 1.500000;
+ MY(tex_min) = 35;
+ MY(tex_max) = 36;
+ MY(type) = "spark";
+ MY(velocityjitter) = '200.0 200.0 200.0';
+ MY(velocitymultiplier) = 0.300000;
+}
+
+DEF(crylink_impact);
+// decal
+SUB(crylink_impact) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(originjitter) = '12.0 12.0 12.0';
+ MY(size_min) = 24;
+ MY(size_max) = 24;
+ MY(tex_min) = 47;
+ MY(tex_max) = 47;
+ MY(type) = "decal";
+}
+// purple flare effect
+SUB(crylink_impact) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x504060";
+ MY(color_max) = "0x504060";
+ MY(countabsolute) = 1;
+ MY(size_min) = 24;
+ MY(size_max) = 24;
+ MY(tex_min) = 39;
+ MY(tex_max) = 39;
+ MY(type) = "static";
+}
+// purple sparks
+SUB(crylink_impact) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1024;
+ MY(bounce) = 2;
+ MY(color_min) = "0xA040C0";
+ MY(color_max) = "0xA040C0";
+ MY(count) = 40;
+ MY(size_min) = 6;
+ MY(size_max) = 6;
+ MY(tex_min) = 41;
+ MY(tex_max) = 41;
+ MY(type) = "spark";
+ MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// purple splash
+SUB(crylink_impact) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0xE070FF";
+ MY(color_max) = "0xE070FF";
+ MY(count) = 1.500000;
+ MY(size_min) = 16;
+ MY(size_max) = 16;
+ MY(type) = "static";
+ MY(velocityjitter) = '32.0 32.0 32.0';
+}
+// purple splash
+SUB(crylink_impact) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0xE070FF";
+ MY(color_max) = "0xE070FF";
+ MY(count) = 3;
+ MY(size_min) = 16;
+ MY(size_max) = 16;
+ MY(type) = "static";
+ MY(velocityjitter) = '256.0 256.0 256.0';
+}
+
+DEF(nex_muzzleflash);
+SUB(nex_muzzleflash) {
+ MY(airfriction) = 9;
+ MY(alpha_min) = 328;
+ MY(alpha_max) = 328;
+ MY(alpha_fade) = 4000;
+ MY(color_min) = "0x202020";
+ MY(color_max) = "0x0072ff";
+ MY(count) = 12;
+ MY(lightcolor) = '2.0 2.5 3.0';
+ MY(lightradiusfade) = 200;
+ MY(lightradius) = 200;
+ MY(originjitter) = '4.0 4.0 4.0';
+ MY(sizeincrease) = -100;
+ MY(size_min) = 16;
+ MY(size_max) = 16;
+ MY(stretchfactor) = 2;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "spark";
+ MY(velocityjitter) = '180.0 180.0 180.0';
+ MY(velocitymultiplier) = 1.400000;
+}
+SUB(nex_muzzleflash) {
+ MY(airfriction) = 9;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0xD9FDFF";
+ MY(color_max) = "0xD9FDFF";
+ MY(count) = 50;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_min) = 41;
+ MY(tex_max) = 41;
+ MY(type) = "spark";
+ MY(velocityjitter) = '600.0 600.0 600.0';
+ MY(velocitymultiplier) = 1.500000;
+}
+
+// vortex beam
+DEF(nex_beam);
+SUB(nex_beam) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 64;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0x1680A0";
+ MY(color_max) = "0x1680A0";
+ MY(sizeincrease) = 2;
+ MY(size_min) = 4;
+ MY(size_max) = 4;
+ MY(tex_min) = 32;
+ MY(tex_max) = 32;
+ MY(trailspacing) = 64;
+ MY(type) = "static";
+}
+// drifting smoke
+SUB(nex_beam) {
+ MY(airfriction) = 9;
+ MY(alpha_min) = 32;
+ MY(alpha_max) = 64;
+ MY(alpha_fade) = 32;
+ MY(color_min) = "0x5080A0";
+ MY(color_max) = "0x5080A0";
+ MY(sizeincrease) = 8;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_max) = 8;
+ MY(trailspacing) = 12;
+ MY(type) = "static";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+}
+// bright core
+SUB(nex_beam) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1280;
+ MY(color_min) = "0x80CDFF";
+ MY(color_max) = "0x80CDFF";
+ MY(size_min) = 4;
+ MY(size_max) = 4;
+ MY(trailspacing) = 12;
+ MY(type) = "static";
+}
+// sparks
+SUB(nex_beam) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 64;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 80;
+ MY(color_min) = "0x1680A0";
+ MY(color_max) = "0x1680A0";
+ MY(gravity) = -0.010000;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_min) = 63;
+ MY(tex_max) = 63;
+ MY(trailspacing) = 16;
+ MY(type) = "snow";
+}
+
+DEF(nex_impact);
+// decal
+SUB(nex_impact) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '4.0 6.0 8.0';
+ MY(lightradiusfade) = 250;
+ MY(lightradius) = 200;
+ MY(originjitter) = '14.0 14.0 14.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(size_min) = 24;
+ MY(size_max) = 24;
+ MY(tex_min) = 47;
+ MY(tex_max) = 47;
+ MY(type) = "decal";
+}
+// rotating something
+SUB(nex_impact) {
+ MY(alpha_min) = 55;
+ MY(alpha_max) = 55;
+ MY(alpha_fade) = 50;
+ MY(color_min) = "0x1680A0";
+ MY(color_max) = "0x1680A0";
+ MY(count) = 5;
+ MY(startangle_min) = 180;
+ MY(startangle_max) = -180;
+ MY(spin_min) = 500;
+ MY(spin_max) = -500;
+ MY(sizeincrease) = 20;
+ MY(size_min) = 25;
+ MY(size_max) = 28;
+ MY(tex_min) = 46;
+ MY(tex_max) = 46;
+ MY(type) = "smoke";
+}
+// shockwave
+SUB(nex_impact) {
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 50;
+ MY(alpha_fade) = 400;
+ MY(color_min) = "0x1680A0";
+ MY(color_max) = "0x1680A0";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 900;
+ MY(size_min) = 16;
+ MY(size_max) = 16;
+ MY(tex_min) = 33;
+ MY(tex_max) = 33;
+ MY(type) = "static";
+}
+// shockwave2
+SUB(nex_impact) {
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 50;
+ MY(alpha_fade) = 100;
+ MY(color_min) = "0x1680A0";
+ MY(color_max) = "0x1680A0";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 500;
+ MY(size_min) = 5;
+ MY(size_max) = 5;
+ MY(tex_min) = 65;
+ MY(tex_max) = 65;
+ MY(type) = "static";
+}
+// flare effect
+SUB(nex_impact) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0x80C0FF";
+ MY(color_max) = "0x80C0FF";
+ MY(countabsolute) = 1;
+ MY(size_min) = 8;
+ MY(size_max) = 8;
+ MY(tex_min) = 37;
+ MY(tex_max) = 37;
+ MY(type) = "static";
+}
+// small sparks which glow brightly but live briefly
+SUB(nex_impact) {
+ MY(airfriction) = 9;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 512;
+ MY(bounce) = 2;
+ MY(color_min) = "0xD9FDFF";
+ MY(color_max) = "0xD9FDFF";
+ MY(count) = 64;
+ MY(size_min) = 4;
+ MY(size_max) = 4;
+ MY(stretchfactor) = 3;
+ MY(tex_min) = 41;
+ MY(tex_max) = 41;
+ MY(type) = "spark";
+ MY(velocityjitter) = '600.0 600.0 600.0';
+ MY(velocitymultiplier) = 0.500000;
+}
+// small sparks that live longer
+SUB(nex_impact) {
+ MY(airfriction) = 2;
+ MY(alpha_min) = 255;
+ MY(alpha_max) = 255;
+ MY(alpha_fade) = 112;
+ MY(bounce) = 1.600000;
+ MY(color_min) = "0xD9FDFF";
+ MY(color_max) = "0xD9FDFF";
+ MY(count) = 16;
+ MY(gravity) = 1;
+ MY(size_min) = 2;
+ MY(size_max) = 2;
+ MY(stretchfactor) = 0.700000;
+ MY(tex_min) = 41;
+ MY(tex_max) = 41;
+ MY(type) = "spark";
+ MY(velocityjitter) = '300.0 300.0 600.0';
+ MY(velocitymultiplier) = 2.500000;
+}
+
+DEF(hagar_muzzleflash);
+SUB(hagar_muzzleflash) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x202020";
+ MY(color_max) = "0x404040";
+ MY(count) = 2;
+ MY(lightcolor) = '2.0 1.5 0.2';
+ MY(lightradiusfade) = 2000;
+ MY(lightradius) = 200;
+ MY(originjitter) = '1.5 1.5 1.5';
+ MY(size_min) = 5;
+ MY(size_max) = 5;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '6.0 6.0 6.0';
+ MY(velocitymultiplier) = 0.010000;
+}
+SUB(hagar_muzzleflash) {
+ MY(airfriction) = 12;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0xff8400";
+ MY(color_max) = "0xff4200";
+ MY(count) = 15;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -400;
+ MY(spin_max) = 400;
+ MY(size_min) = 5;
+ MY(size_max) = 10;
+ MY(stretchfactor) = 2;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "spark";
+ MY(velocityjitter) = '200.0 200.0 200.0';
+ MY(velocitymultiplier) = 0.500000;
+}
+
+DEF(hagar_bounce);
+SUB(hagar_bounce) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0x202020";
+ MY(color_max) = "0x404040";
+ MY(count) = 2;
+ MY(lightcolor) = '2.0 1.5 0.2';
+ MY(lightradiusfade) = 300;
+ MY(lightradius) = 60;
+ MY(originjitter) = '1.5 1.5 1.5';
+ MY(size_min) = 5;
+ MY(size_max) = 5;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '6.0 6.0 6.0';
+ MY(velocitymultiplier) = 0.010000;
+}
+SUB(hagar_bounce) {
+ MY(airfriction) = 12;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0xFFFDD9";
+ MY(color_max) = "0xFFFDD9";
+ MY(count) = 15;
+ MY(gravity) = 1;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '600.0 600.0 600.0';
+ MY(velocitymultiplier) = 0.500000;
+}
+
+DEF(hagar_explode);
+// decal
+SUB(hagar_explode) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '8.0 4.0 1.0';
+ MY(lightradiusfade) = 400;
+ MY(lightradius) = 120;
+ MY(originjitter) = '14.0 14.0 14.0';
+ MY(size_min) = 28;
+ MY(size_max) = 38;
+ MY(tex_min) = 8;
+ MY(tex_max) = 16;
+ MY(type) = "decal";
+}
+// fire effect which make bright dot inside
+SUB(hagar_explode) {
+ MY(airfriction) = 8;
+ MY(alpha_min) = 80;
+ MY(alpha_max) = 200;
+ MY(alpha_fade) = 356;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0xffe955";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 3.500000;
+ MY(liquidfriction) = 8;
+ MY(notunderwater) = true;
+ MY(originjitter) = '8.0 8.0 8.0';
+ MY(sizeincrease) = 5;
+ MY(size_min) = 16;
+ MY(size_max) = 26;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '156.0 156.0 156.0';
+}
+// fire effect which expands then slows
+SUB(hagar_explode) {
+ MY(airfriction) = 12;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 456;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 12;
+ MY(liquidfriction) = 8;
+ MY(notunderwater) = true;
+ MY(originjitter) = '8.0 8.0 8.0';
+ MY(sizeincrease) = 15;
+ MY(size_min) = 20;
+ MY(size_max) = 26;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "static";
+ MY(velocityjitter) = '286.0 286.0 286.0';
+}
+// smoke
+SUB(hagar_explode) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 500;
+ MY(alpha_fade) = 600;
+ MY(bounce) = 2;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x111111";
+ MY(count) = 7;
+ MY(notunderwater) = true;
+ MY(sizeincrease) = 20;
+ MY(size_min) = 20;
+ MY(size_max) = 40;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '244.0 244.0 244.0';
+}
+// underwater bubbles
+SUB(hagar_explode) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x808080";
+ MY(count) = 16;
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 0.250000;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '96.0 96.0 96.0';
+}
+// bouncing sparks
+SUB(hagar_explode) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 644;
+ MY(alpha_max) = 956;
+ MY(alpha_fade) = 684;
+ MY(bounce) = 1.600000;
+ MY(color_min) = "0xffa35b";
+ MY(color_max) = "0xfff2be";
+ MY(count) = 4;
+ MY(gravity) = 1;
+ MY(liquidfriction) = 0.800000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(size_min) = 1;
+ MY(size_max) = 0.100000;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '224.0 224.0 224.0';
+ MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+DEF(rocketlauncher_muzzleflash);
+SUB(rocketlauncher_muzzleflash) {
+ MY(airfriction) = 2;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0x202020";
+ MY(color_max) = "0x404040";
+ MY(count) = 10;
+ MY(originjitter) = '1.5 1.5 1.5';
+ MY(sizeincrease) = 20;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '40.0 40.0 40.0';
+ MY(velocitymultiplier) = -0.130000;
+}
+SUB(rocketlauncher_muzzleflash) {
+ MY(airfriction) = 9;
+ MY(alpha_min) = 10;
+ MY(alpha_max) = 25;
+ MY(alpha_fade) = 20;
+ MY(color_min) = "0xFFFDD9";
+ MY(color_max) = "0xFFFDD9";
+ MY(count) = 6;
+ MY(originjitter) = '3.0 3.0 3.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -30;
+ MY(spin_max) = 30;
+ MY(sizeincrease) = 20;
+ MY(size_min) = 5;
+ MY(size_max) = 10;
+ MY(tex_min) = 35;
+ MY(tex_max) = 36;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '100.0 100.0 100.0';
+ MY(velocitymultiplier) = 0.300000;
+}
+
+// rocket trail
+DEF(TR_ROCKET);
+// smoke
+SUB(TR_ROCKET) {
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 300;
+ MY(alpha_fade) = 200;
+ MY(bounce) = 1;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x666666";
+ MY(lightcolor) = '6.0 3.0 1.0';
+ MY(lightradius) = 150;
+ MY(notunderwater) = true;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -30;
+ MY(spin_max) = 30;
+ MY(sizeincrease) = 11;
+ MY(size_min) = 3;
+ MY(size_max) = 4;
+ MY(tex_max) = 8;
+ MY(trailspacing) = 10;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '3.0 3.0 3.0';
+ MY(velocitymultiplier) = -0.020000;
+}
+// fire
+SUB(TR_ROCKET) {
+ MY(airfriction) = 8;
+ MY(alpha_min) = 100;
+ MY(alpha_max) = 144;
+ MY(alpha_fade) = 588;
+ MY(color_min) = "0xffdf72";
+ MY(color_max) = "0x811200";
+ MY(sizeincrease) = -30;
+ MY(size_min) = 7;
+ MY(size_max) = 7;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(trailspacing) = 4;
+ MY(type) = "static";
+ MY(velocityjitter) = '32.0 32.0 32.0';
+ MY(velocitymultiplier) = -1.500000;
+}
+// bubbles
+SUB(TR_ROCKET) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(bounce) = 1.500000;
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 4;
+ MY(size_min) = 1;
+ MY(size_max) = 2;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(trailspacing) = 16;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '16.0 16.0 16.0';
+ MY(velocitymultiplier) = -0.310000;
+}
+// sparks
+SUB(TR_ROCKET) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 444;
+ MY(alpha_max) = 512;
+ MY(alpha_fade) = 1866;
+ MY(bounce) = 1;
+ MY(color_min) = "0xFFFDD9";
+ MY(color_max) = "0xFFFDD9";
+ MY(notunderwater) = true;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 0.500000;
+ MY(size_max) = 0.500000;
+ MY(stretchfactor) = 0.300000;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(trailspacing) = 20;
+ MY(type) = "spark";
+ MY(velocityjitter) = '100.0 100.0 100.0';
+ MY(velocitymultiplier) = -0.310000;
+}
+
+// rocket explosion (bigger than mortar and hagar)
+DEF(rocket_explode);
+SUB(rocket_explode) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '8.0 4.0 1.0';
+ MY(lightradiusfade) = 750;
+ MY(lightradius) = 400;
+ MY(originjitter) = '23.0 23.0 23.0';
+ MY(size_min) = 72;
+ MY(size_max) = 72;
+ MY(tex_min) = 8;
+ MY(tex_max) = 16;
+ MY(type) = "decal";
+}
+// fire effect
+SUB(rocket_explode) {
+ MY(airfriction) = 8;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 32;
+ MY(liquidfriction) = 8;
+ MY(notunderwater) = true;
+ MY(originjitter) = '8.0 8.0 8.0';
+ MY(sizeincrease) = 45;
+ MY(size_min) = 33;
+ MY(size_max) = 44;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "static";
+ MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// fire effect 2
+SUB(rocket_explode) {
+ MY(airfriction) = 19;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 612;
+ MY(bounce) = 2.500000;
+ MY(color_min) = "0xea691b";
+ MY(color_max) = "0xeed05a";
+ MY(count) = 14;
+ MY(liquidfriction) = 19;
+ MY(notunderwater) = true;
+ MY(originjitter) = '8.0 8.0 8.0';
+ MY(sizeincrease) = 55;
+ MY(size_min) = 33;
+ MY(size_max) = 44;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '912.0 912.0 912.0';
+}
+// smoke
+SUB(rocket_explode) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 450;
+ MY(alpha_fade) = 456;
+ MY(bounce) = 2;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x111111";
+ MY(count) = 32;
+ MY(notunderwater) = true;
+ MY(sizeincrease) = 44;
+ MY(size_min) = 20;
+ MY(size_max) = 40;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '444.0 444.0 444.0';
+}
+// underwater bubbles
+SUB(rocket_explode) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x808080";
+ MY(count) = 32;
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 0.250000;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '144.0 144.0 144.0';
+}
+// underwatershockwave
+SUB(rocket_explode) {
+ MY(alpha_min) = 40;
+ MY(alpha_max) = 40;
+ MY(alpha_fade) = 300;
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 1900;
+ MY(size_min) = 30;
+ MY(size_max) = 30;
+ MY(tex_min) = 33;
+ MY(tex_max) = 33;
+ MY(type) = "smoke";
+ MY(underwater) = true;
+ MY(velocitymultiplier) = 0.300000;
+}
+// bouncing sparks
+SUB(rocket_explode) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 644;
+ MY(alpha_max) = 956;
+ MY(alpha_fade) = 484;
+ MY(bounce) = 1.600000;
+ MY(color_min) = "0xffa35b";
+ MY(color_max) = "0xfff2be";
+ MY(count) = 16;
+ MY(gravity) = 1;
+ MY(liquidfriction) = 0.800000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(size_min) = 1;
+ MY(size_max) = 0.100000;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '424.0 424.0 624.0';
+ MY(velocityoffset) = '0.0 0.0 80.0';
+}
+// debris
+SUB(rocket_explode) {
+ MY(airfriction) = 0.500000;
+ MY(alpha_min) = 644;
+ MY(alpha_max) = 956;
+ MY(alpha_fade) = 684;
+ MY(bounce) = 1.600000;
+ MY(color_min) = "0x6a3d25";
+ MY(color_max) = "0xcac5b4";
+ MY(count) = 12;
+ MY(gravity) = 1.300000;
+ MY(notunderwater) = true;
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -1000;
+ MY(spin_max) = 1000;
+ MY(size_min) = 2;
+ MY(size_max) = 6;
+ MY(tex_min) = 66;
+ MY(tex_max) = 68;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '324.0 324.0 524.0';
+}
+
+DEF(grapple_muzzleflash);
+SUB(grapple_muzzleflash) {
+ MY(lightcolor) = '1.0 0.0 0.0';
+ MY(lightradiusfade) = 800;
+ MY(lightradius) = 160;
+}
+
+DEF(grapple_impact);
+SUB(grapple_impact) {
+ MY(lightcolor) = '1.0 0.0 0.0';
+ MY(lightradiusfade) = 800;
+ MY(lightradius) = 160;
+}
+
+DEF(nex242_misc_laser_beam);
+SUB(nex242_misc_laser_beam) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0xff0000";
+ MY(color_max) = "0xff0000";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 1;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_min) = 200;
+ MY(tex_max) = 200;
+ MY(type) = "beam";
+}
+
+DEF(nex242_misc_laser_beam_end);
+SUB(nex242_misc_laser_beam_end) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 768;
+ MY(bounce) = -1;
+ MY(color_min) = "0x8f4333";
+ MY(color_max) = "0xfff31b";
+ MY(count) = 0.500000;
+ MY(gravity) = 1;
+ MY(size_min) = 0.400000;
+ MY(size_max) = 0.400000;
+ MY(type) = "spark";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+ MY(velocitymultiplier) = 100;
+}
+
+DEF(nex242_misc_laser_beam_fast);
+SUB(nex242_misc_laser_beam_fast) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 640;
+ MY(color_min) = "0xff0000";
+ MY(color_max) = "0xff0000";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 0.100000;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_min) = 200;
+ MY(tex_max) = 200;
+ MY(type) = "beam";
+}
+
+DEF(nex242_misc_laser_beam_fast_end);
+SUB(nex242_misc_laser_beam_fast_end) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 768;
+ MY(bounce) = -1;
+ MY(color_min) = "0x8f4333";
+ MY(color_max) = "0xfff31b";
+ MY(count) = 0.500000;
+ MY(gravity) = 1;
+ MY(size_min) = 0.400000;
+ MY(size_max) = 0.400000;
+ MY(type) = "spark";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+ MY(velocitymultiplier) = 100;
+}
+
+DEF(nex242_misc_laser_green_beam);
+SUB(nex242_misc_laser_green_beam) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0x00ff00";
+ MY(color_max) = "0x00ff00";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 1;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_min) = 200;
+ MY(tex_max) = 200;
+ MY(type) = "beam";
+}
+
+DEF(nex242_misc_laser_green_beam_end);
+SUB(nex242_misc_laser_green_beam_end) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 768;
+ MY(bounce) = -1;
+ MY(color_min) = "0x8f4333";
+ MY(color_max) = "0xfff31b";
+ MY(count) = 0.500000;
+ MY(gravity) = 1;
+ MY(size_min) = 0.400000;
+ MY(size_max) = 0.400000;
+ MY(type) = "spark";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+ MY(velocitymultiplier) = 100;
+}
+
+DEF(nex242_misc_laser_blue_beam);
+SUB(nex242_misc_laser_blue_beam) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0x0000ff";
+ MY(color_max) = "0x0000ff";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 1;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_min) = 200;
+ MY(tex_max) = 200;
+ MY(type) = "beam";
+}
+
+DEF(nex242_misc_laser_blue_beam_end);
+SUB(nex242_misc_laser_blue_beam_end) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 768;
+ MY(bounce) = -1;
+ MY(color_min) = "0x8f4333";
+ MY(color_max) = "0xfff31b";
+ MY(count) = 0.500000;
+ MY(gravity) = 1;
+ MY(size_min) = 0.400000;
+ MY(size_max) = 0.400000;
+ MY(type) = "spark";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+ MY(velocitymultiplier) = 100;
+}
+
+DEF(nex242_misc_laser_yellow_beam);
+SUB(nex242_misc_laser_yellow_beam) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0xffff00";
+ MY(color_max) = "0xffff00";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 1;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_min) = 200;
+ MY(tex_max) = 200;
+ MY(type) = "beam";
+}
+
+DEF(nex242_misc_laser_yellow_beam_end);
+SUB(nex242_misc_laser_yellow_beam_end) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 768;
+ MY(bounce) = -1;
+ MY(color_min) = "0x8f4333";
+ MY(color_max) = "0xfff31b";
+ MY(count) = 0.500000;
+ MY(gravity) = 1;
+ MY(size_min) = 0.400000;
+ MY(size_max) = 0.400000;
+ MY(type) = "spark";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+ MY(velocitymultiplier) = 100;
+}
+
+DEF(nex242_misc_laser_cyan_beam);
+SUB(nex242_misc_laser_cyan_beam) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0x00ffff";
+ MY(color_max) = "0x00ffff";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 1;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_min) = 200;
+ MY(tex_max) = 200;
+ MY(type) = "beam";
+}
+
+DEF(nex242_misc_laser_cyan_beam_end);
+SUB(nex242_misc_laser_cyan_beam_end) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 768;
+ MY(bounce) = -1;
+ MY(color_min) = "0x8f4333";
+ MY(color_max) = "0xfff31b";
+ MY(count) = 0.500000;
+ MY(gravity) = 1;
+ MY(size_min) = 0.400000;
+ MY(size_max) = 0.400000;
+ MY(type) = "spark";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+ MY(velocitymultiplier) = 100;
+}
+
+DEF(nex242_misc_laser_magenta_beam);
+SUB(nex242_misc_laser_magenta_beam) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0xff00ff";
+ MY(color_max) = "0xff00ff";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 1;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_min) = 200;
+ MY(tex_max) = 200;
+ MY(type) = "beam";
+}
+
+DEF(nex242_misc_laser_magenta_beam_end);
+SUB(nex242_misc_laser_magenta_beam_end) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 768;
+ MY(bounce) = -1;
+ MY(color_min) = "0x8f4333";
+ MY(color_max) = "0xfff31b";
+ MY(count) = 0.500000;
+ MY(gravity) = 1;
+ MY(size_min) = 0.400000;
+ MY(size_max) = 0.400000;
+ MY(type) = "spark";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+ MY(velocitymultiplier) = 100;
+}
+
+DEF(nex242_misc_laser_white_beam);
+SUB(nex242_misc_laser_white_beam) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0xffffff";
+ MY(color_max) = "0xffffff";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 1;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_min) = 200;
+ MY(tex_max) = 200;
+ MY(type) = "beam";
+}
+
+DEF(nex242_misc_laser_white_beam_end);
+SUB(nex242_misc_laser_white_beam_end) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 768;
+ MY(bounce) = -1;
+ MY(color_min) = "0x8f4333";
+ MY(color_max) = "0xfff31b";
+ MY(count) = 0.500000;
+ MY(gravity) = 1;
+ MY(size_min) = 0.400000;
+ MY(size_max) = 0.400000;
+ MY(type) = "spark";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+ MY(velocitymultiplier) = 100;
+}
+
+DEF(nex242_misc_laser_black_beam);
+SUB(nex242_misc_laser_black_beam) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x000000";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 1;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_min) = 200;
+ MY(tex_max) = 200;
+ MY(type) = "beam";
+}
+
+DEF(nex242_misc_laser_black_beam_end);
+SUB(nex242_misc_laser_black_beam_end) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 768;
+ MY(bounce) = -1;
+ MY(color_min) = "0x8f4333";
+ MY(color_max) = "0xfff31b";
+ MY(count) = 0.500000;
+ MY(gravity) = 1;
+ MY(size_min) = 0.400000;
+ MY(size_max) = 0.400000;
+ MY(type) = "spark";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+ MY(velocitymultiplier) = 100;
+}
+
+DEF(nex242_misc_laser_orange_beam);
+SUB(nex242_misc_laser_orange_beam) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0xff6600";
+ MY(color_max) = "0xff6600";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 1;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_min) = 200;
+ MY(tex_max) = 200;
+ MY(type) = "beam";
+}
+
+DEF(nex242_misc_laser_orange_beam_end);
+SUB(nex242_misc_laser_orange_beam_end) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 768;
+ MY(bounce) = -1;
+ MY(color_min) = "0x8f4333";
+ MY(color_max) = "0xfff31b";
+ MY(count) = 0.500000;
+ MY(gravity) = 1;
+ MY(size_min) = 0.400000;
+ MY(size_max) = 0.400000;
+ MY(type) = "spark";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+ MY(velocitymultiplier) = 100;
+}
+
+// bigger crylink impact effect
+DEF(crylink_impactbig);
+// decal
+SUB(crylink_impactbig) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(originjitter) = '12.0 12.0 12.0';
+ MY(size_min) = 24;
+ MY(size_max) = 24;
+ MY(tex_min) = 47;
+ MY(tex_max) = 47;
+ MY(type) = "decal";
+}
+// purple flare effect
+SUB(crylink_impactbig) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x504060";
+ MY(color_max) = "0x504060";
+ MY(countabsolute) = 1;
+ MY(size_min) = 24;
+ MY(size_max) = 24;
+ MY(tex_min) = 39;
+ MY(tex_max) = 39;
+ MY(type) = "static";
+}
+// purple sparks
+SUB(crylink_impactbig) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1024;
+ MY(bounce) = 2;
+ MY(color_min) = "0xA040C0";
+ MY(color_max) = "0xA040C0";
+ MY(count) = 40;
+ MY(size_min) = 6;
+ MY(size_max) = 6;
+ MY(tex_min) = 41;
+ MY(tex_max) = 41;
+ MY(type) = "spark";
+ MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// purple splash
+SUB(crylink_impactbig) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0xE070FF";
+ MY(color_max) = "0xE070FF";
+ MY(count) = 1.500000;
+ MY(size_min) = 16;
+ MY(size_max) = 16;
+ MY(type) = "static";
+ MY(velocityjitter) = '32.0 32.0 32.0';
+}
+// purple splash
+SUB(crylink_impactbig) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0xE070FF";
+ MY(color_max) = "0xE070FF";
+ MY(count) = 3;
+ MY(size_min) = 16;
+ MY(size_max) = 16;
+ MY(type) = "static";
+ MY(velocityjitter) = '256.0 256.0 256.0';
+}
+
+#include "effectinfo_gentle.inc"
+
+DEF(laser_deadly);
+// decal
+SUB(laser_deadly) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(originjitter) = '6.0 6.0 6.0';
+ MY(size_min) = 5;
+ MY(size_max) = 5;
+ MY(tex_min) = 56;
+ MY(tex_max) = 59;
+ MY(type) = "decal";
+}
+// dust/smoke drifting away from the impact
+SUB(laser_deadly) {
+ MY(airfriction) = 7;
+ MY(alpha_max) = 64;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0xFFFFFF";
+ MY(color_max) = "0xFFFFFF";
+ MY(count) = 0.025000;
+ MY(liquidfriction) = 16;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(sizeincrease) = 2;
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '15.0 15.0 15.0';
+ MY(velocitymultiplier) = 20;
+}
+// sparks
+SUB(laser_deadly) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 768;
+ MY(bounce) = 1;
+ MY(color_min) = "0xFDFFD9";
+ MY(color_max) = "0xFDFFD9";
+ MY(count) = 0.025000;
+ MY(gravity) = 1;
+ MY(notunderwater) = true;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 0.600000;
+ MY(size_max) = 0.600000;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '100.0 100.0 100.0';
+ MY(velocitymultiplier) = 100;
+}
+
+DEF(torch_small);
+// fire
+SUB(torch_small) {
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 8;
+ MY(gravity) = -0.500000;
+ MY(originjitter) = '5.0 5.0 5.0';
+ MY(sizeincrease) = -1;
+ MY(size_min) = 1;
+ MY(size_max) = 11;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '1.0 1.0 50.0';
+}
+// smoke
+SUB(torch_small) {
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 200;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x111111";
+ MY(count) = 4;
+ MY(gravity) = -0.300000;
+ MY(originjitter) = '3.0 3.0 3.0';
+ MY(sizeincrease) = 5;
+ MY(size_min) = 5;
+ MY(size_max) = 10;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '11.0 11.0 50.0';
+}
+
+DEF(fountain01);
+SUB(fountain01) {
+ MY(alpha_max) = 100;
+ MY(alpha_fade) = 100;
+ MY(bounce) = 1;
+ MY(color_min) = "0x7cbaff";
+ MY(color_max) = "0xcfd1ff";
+ MY(count) = 16;
+ MY(gravity) = 0.600000;
+ MY(originjitter) = '5.0 5.0 5.0';
+ MY(sizeincrease) = 20;
+ MY(size_min) = 10;
+ MY(size_max) = 15;
+ MY(tex_max) = 8;
+ MY(type) = "snow";
+ MY(velocityjitter) = '81.0 81.0 150.0';
+ MY(velocitymultiplier) = 2;
+}
+
+DEF(hookbomb_explode);
+// decal
+SUB(hookbomb_explode) {
+ MY(airfriction) = 10;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 200;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x807aff";
+ MY(color_max) = "0x4463d5";
+ MY(count) = 25;
+ MY(originjitter) = '10.0 10.0 10.0';
+ MY(sizeincrease) = -160;
+ MY(size_min) = 150;
+ MY(size_max) = 200;
+ MY(tex_min) = 38;
+ MY(tex_max) = 38;
+ MY(type) = "static";
+ MY(velocityjitter) = '550.0 550.0 550.0';
+}
+// decal in the air
+SUB(hookbomb_explode) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 265;
+ MY(alpha_fade) = 100;
+ MY(color_min) = "0x807aff";
+ MY(color_max) = "0x4463d5";
+ MY(countabsolute) = 3;
+ MY(originoffset) = '0.0 0.0 6.0';
+ MY(sizeincrease) = -60;
+ MY(size_min) = 160;
+ MY(size_max) = 200;
+ MY(tex_min) = 38;
+ MY(tex_max) = 38;
+ MY(type) = "static";
+}
+// decal on the ground
+SUB(hookbomb_explode) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(originjitter) = '6.0 6.0 6.0';
+ MY(size_min) = 80;
+ MY(size_max) = 100;
+ MY(tex_min) = 39;
+ MY(tex_max) = 39;
+ MY(type) = "decal";
+}
+// some sparks
+SUB(hookbomb_explode) {
+ MY(airfriction) = 2;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 456;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x807aff";
+ MY(color_max) = "0x4463d5";
+ MY(count) = 30;
+ MY(gravity) = 1;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(sizeincrease) = -60;
+ MY(size_min) = 20;
+ MY(size_max) = 30;
+ MY(tex_min) = 38;
+ MY(tex_max) = 38;
+ MY(type) = "spark";
+ MY(velocityjitter) = '1900.0 1900.0 1300.0';
+ MY(velocitymultiplier) = 0.500000;
+}
+
+DEF(EF_MGTURRETTRAIL);
+// smoke
+SUB(EF_MGTURRETTRAIL) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 196;
+ MY(alpha_fade) = 768;
+ MY(color_min) = "0xd0d0a0";
+ MY(color_max) = "0xffffff";
+ MY(gravity) = -0.010000;
+ MY(notunderwater) = true;
+ MY(sizeincrease) = -8;
+ MY(size_min) = 5;
+ MY(size_max) = 4;
+ MY(tex_max) = 8;
+ MY(trailspacing) = 10;
+ MY(type) = "smoke";
+}
+// bubbles
+SUB(EF_MGTURRETTRAIL) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x808080";
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 4;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(trailspacing) = 32;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '16.0 16.0 16.0';
+}
+
+DEF(fire_big);
+// fire
+SUB(fire_big) {
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 356;
+ MY(alpha_fade) = 512;
+ MY(bounce) = 2;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 26;
+ MY(gravity) = -0.500000;
+ MY(originjitter) = '33.0 33.0 33.0';
+ MY(sizeincrease) = -3;
+ MY(size_min) = 11;
+ MY(size_max) = 31;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '22.0 22.0 50.0';
+}
+// smoke
+SUB(fire_big) {
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 200;
+ MY(bounce) = 2;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x111111";
+ MY(count) = 11;
+ MY(gravity) = -0.300000;
+ MY(originjitter) = '44.0 44.0 44.0';
+ MY(sizeincrease) = 11;
+ MY(size_min) = 22;
+ MY(size_max) = 33;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '11.0 11.0 50.0';
+}
+
+#define flare(name, colormin, colormax) \
+ DEF(name##_flare); \
+ SUB(name##_flare) /* smoke */ { \
+ MY(alpha_min) = 200; \
+ MY(alpha_max) = 256; \
+ MY(alpha_fade) = 160; \
+ MY(bounce) = 1; \
+ MY(color_min) = colormin; \
+ MY(color_max) = colormax; \
+ MY(count) = 10.500000; \
+ MY(gravity) = -0.240000; \
+ MY(originjitter) = '2.0 2.0 0.0'; \
+ MY(sizeincrease) = 11; \
+ MY(size_min) = 1; \
+ MY(size_max) = 11; \
+ MY(tex_max) = 8; \
+ MY(type) = "alphastatic"; \
+ MY(velocityjitter) = '15.0 15.0 30.0'; \
+ }
+
+flare(red, "0xff0000", "0xdc7171")
+flare(blue, "0x0000ff", "0x7194dc")
+#undef flare
+
+DEF(smoke_ring);
+// smoke
+SUB(smoke_ring) {
+ MY(airfriction) = 3;
+ MY(alpha_min) = 100;
+ MY(alpha_max) = 156;
+ MY(alpha_fade) = 200;
+ MY(bounce) = 1.100000;
+ MY(color_min) = "0x111111";
+ MY(color_max) = "0x979797";
+ MY(count) = 45;
+ MY(gravity) = 0.100000;
+ MY(notunderwater) = true;
+ MY(sizeincrease) = 21;
+ MY(size_min) = 1;
+ MY(size_max) = 11;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '190.0 190.0 50.0';
+}
+
+DEF(smoke_large);
+// smoke
+SUB(smoke_large) {
+ MY(airfriction) = 7;
+ MY(alpha_min) = 140;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 190;
+ MY(bounce) = 1.100000;
+ MY(color_min) = "0x9e895f";
+ MY(color_max) = "0xffd39b";
+ MY(count) = 25;
+ MY(gravity) = -0.150000;
+ MY(notunderwater) = true;
+ MY(sizeincrease) = 21;
+ MY(size_min) = 11;
+ MY(size_max) = 21;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '390.0 390.0 390.0';
+}
+
+DEF(sparks);
+SUB(sparks) {
+ MY(airfriction) = 3;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0xFFFDD9";
+ MY(color_max) = "0xFFFDD9";
+ MY(count) = 15;
+ MY(gravity) = 1;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 1;
+ MY(size_max) = 3;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '300.0 300.0 200.0';
+ MY(velocitymultiplier) = 1.500000;
+}
+
+DEF(electricity_sparks);
+SUB(electricity_sparks) {
+ MY(airfriction) = 3;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 556;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x807aff";
+ MY(color_max) = "0x4463d5";
+ MY(count) = 35;
+ MY(gravity) = 1;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 1;
+ MY(size_max) = 3;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '300.0 300.0 300.0';
+ MY(velocitymultiplier) = 0.500000;
+}
+
+DEF(steam);
+SUB(steam) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 140;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 190;
+ MY(bounce) = 1.100000;
+ MY(color_min) = "0xfffbdf";
+ MY(color_max) = "0xffffff";
+ MY(count) = 1;
+ MY(gravity) = -0.250000;
+ MY(notunderwater) = true;
+ MY(sizeincrease) = 7;
+ MY(size_min) = 1;
+ MY(size_max) = 3;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '19.0 19.0 19.0';
+ MY(velocitymultiplier) = 14;
+}
+
+DEF(smoking);
+SUB(smoking) {
+ MY(airfriction) = -1;
+ MY(alpha_min) = 100;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 100;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x292929";
+ MY(color_max) = "0x000000";
+ MY(count) = 10;
+ MY(gravity) = -0.100000;
+ MY(originjitter) = '10.0 10.0 10.0';
+ MY(sizeincrease) = 5;
+ MY(size_min) = 10;
+ MY(size_max) = 40;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '5.0 5.0 20.0';
+}
+
+// golden dust (create it once per second to cover large area in small yellow particles)
+DEF(goldendust);
+SUB(goldendust) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 70;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0xff9600";
+ MY(color_max) = "0xffefb8";
+ MY(count) = 25;
+ MY(originjitter) = '500.0 500.0 500.0';
+ MY(sizeincrease) = -0.300000;
+ MY(size_min) = 2;
+ MY(size_max) = 3;
+ MY(tex_min) = 38;
+ MY(tex_max) = 38;
+ MY(type) = "snow";
+ MY(velocityjitter) = '0.1 0.1 0.1';
+}
+
+DEF(healing_fx);
+SUB(healing_fx) {
+ MY(airfriction) = -0.500000;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 170;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0xff0000";
+ MY(color_max) = "0xff0000";
+ MY(count) = 25;
+ MY(gravity) = -0.100000;
+ MY(originjitter) = '5.0 5.0 100.0';
+ MY(sizeincrease) = -0.050000;
+ MY(size_min) = 1;
+ MY(size_max) = 3;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '50.0 50.0 0.0';
+}
+
+DEF(armorrepair_fx);
+SUB(armorrepair_fx) {
+ MY(airfriction) = -0.500000;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 170;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x00ff00";
+ MY(color_max) = "0x00ff00";
+ MY(count) = 25;
+ MY(gravity) = -0.100000;
+ MY(originjitter) = '5.0 5.0 50.0';
+ MY(sizeincrease) = -0.050000;
+ MY(size_min) = 1;
+ MY(size_max) = 3;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '50.0 50.0 0.0';
+}
+
+DEF(ammoregen_fx);
+SUB(ammoregen_fx) {
+ MY(airfriction) = -0.500000;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 170;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x0000ff";
+ MY(color_max) = "0x0000ff";
+ MY(count) = 25;
+ MY(gravity) = -0.100000;
+ MY(originjitter) = '5.0 5.0 50.0';
+ MY(sizeincrease) = -0.050000;
+ MY(size_min) = 1;
+ MY(size_max) = 3;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '50.0 50.0 0.0';
+}
+
+// red-yellow flame like fx
+DEF(rage);
+SUB(rage) {
+ MY(airfriction) = 2;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 190;
+ MY(color_min) = "0xff0000";
+ MY(color_max) = "0xff7800";
+ MY(count) = 2.500000;
+ MY(gravity) = -0.060000;
+ MY(originjitter) = '5.0 5.0 5.0';
+ MY(sizeincrease) = 10;
+ MY(size_min) = 1;
+ MY(size_max) = 3;
+ MY(tex_min) = 35;
+ MY(tex_max) = 36;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '25.0 25.0 25.0';
+}
+
+// pieces of glass or ice falling on the floor
+DEF(iceorglass);
+SUB(iceorglass) {
+ MY(airfriction) = 3;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(bounce) = 2;
+ MY(color_min) = "0xffffff";
+ MY(color_max) = "0xb2d3e6";
+ MY(count) = 15;
+ MY(gravity) = 1.300000;
+ MY(originjitter) = '30.0 30.0 30.0';
+ MY(size_min) = 3;
+ MY(size_max) = 7;
+ MY(tex_min) = 44;
+ MY(tex_max) = 44;
+ MY(time_min) = 1;
+ MY(time_max) = 3;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '100.0 100.0 100.0';
+}
+
+// cover small area in poison gas, spawn it once per second
+DEF(poisonfield);
+SUB(poisonfield) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 50;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x00ff00";
+ MY(color_max) = "0x7db843";
+ MY(count) = 15;
+ MY(gravity) = -0.010000;
+ MY(originjitter) = '333.0 333.0 50.0';
+ MY(sizeincrease) = 30;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '5.0 5.0 5.0';
+}
+
+// cover small area in icy mist, spawn it once per second
+DEF(icefield);
+SUB(icefield) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 50;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x008aff";
+ MY(color_max) = "0x75e7ff";
+ MY(count) = 10;
+ MY(gravity) = -0.010000;
+ MY(originjitter) = '333.0 333.0 0.0';
+ MY(sizeincrease) = 10;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '5.0 5.0 30.0';
+}
+SUB(icefield) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 50;
+ MY(color_min) = "0x008aff";
+ MY(color_max) = "0x75e7ff";
+ MY(count) = 5;
+ MY(gravity) = -0.001000;
+ MY(originjitter) = '333.0 333.0 0.0';
+ MY(sizeincrease) = 10;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+}
+
+// cover very small area in flames, spawn it 3 times per second (or more often to get better looking fire at cost of fps hit )
+DEF(firefield);
+// flames that go up
+SUB(firefield) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 200;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 100;
+ MY(gravity) = -0.060000;
+ MY(originjitter) = '180.0 180.0 0.0';
+ MY(sizeincrease) = 20;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '5.0 5.0 30.0';
+}
+// flames that stay on the ground
+SUB(firefield) {
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 200;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 50;
+ MY(originjitter) = '180.0 180.0 0.0';
+ MY(sizeincrease) = 40;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+}
+// smoke
+SUB(firefield) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 70;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x111111";
+ MY(count) = 20;
+ MY(gravity) = -0.020000;
+ MY(originjitter) = '180.0 180.0 0.0';
+ MY(sizeincrease) = 7;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+}
+
+// flamethrower, spawn it as fast as you can 20 times per second or more, it needs direction
+DEF(flamethrower);
+// fast fire
+SUB(flamethrower) {
+ MY(airfriction) = 1.200000;
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 250;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 3;
+ MY(gravity) = -0.060000;
+ MY(sizeincrease) = 20;
+ MY(size_min) = 5;
+ MY(size_max) = 5;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '40.0 40.0 11.0';
+ MY(velocitymultiplier) = 30;
+}
+// slow fire
+SUB(flamethrower) {
+ MY(airfriction) = 1.200000;
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 200;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 2.500000;
+ MY(gravity) = -0.060000;
+ MY(sizeincrease) = 20;
+ MY(size_min) = 5;
+ MY(size_max) = 5;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '40.0 40.0 40.0';
+ MY(velocitymultiplier) = 20;
+}
+// very slow and small fire
+SUB(flamethrower) {
+ MY(airfriction) = 0.300000;
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 200;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 1.500000;
+ MY(gravity) = -0.060000;
+ MY(sizeincrease) = 10;
+ MY(size_min) = 5;
+ MY(size_max) = 5;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '30.0 30.0 30.0';
+ MY(velocitymultiplier) = 10;
+}
+// decreasing fire
+SUB(flamethrower) {
+ MY(airfriction) = 0.300000;
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 200;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 2;
+ MY(gravity) = -0.060000;
+ MY(sizeincrease) = -10;
+ MY(size_min) = 20;
+ MY(size_max) = 30;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '10.0 10.0 10.0';
+ MY(velocitymultiplier) = 15;
+}
+// smoke
+SUB(flamethrower) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 90;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x111111";
+ MY(count) = 0.500000;
+ MY(originjitter) = '10.0 10.0 10.0';
+ MY(sizeincrease) = 7;
+ MY(size_min) = 5;
+ MY(size_max) = 15;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocitymultiplier) = 20;
+ MY(velocityoffset) = '0.0 0.0 10.0';
+}
+
+// port-o-launch trail
+DEF(TR_WIZSPIKE);
+// glowing vapor trail
+SUB(TR_WIZSPIKE) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 968;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x404040";
+ MY(lightcolor) = '1.5 3.0 6.0';
+ MY(lightradius) = 90;
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(trailspacing) = 4;
+ MY(type) = "static";
+ MY(velocitymultiplier) = -0.100000;
+}
+// bright sparks
+SUB(TR_WIZSPIKE) {
+ MY(airfriction) = 12;
+ MY(alpha_min) = 444;
+ MY(alpha_max) = 512;
+ MY(alpha_fade) = 1866;
+ MY(bounce) = 1;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x404040";
+ MY(count) = 1.500000;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(sizeincrease) = -20;
+ MY(size_min) = 2;
+ MY(size_max) = 4;
+ MY(tex_min) = 42;
+ MY(tex_max) = 42;
+ MY(trailspacing) = 12;
+ MY(type) = "snow";
+ MY(velocityjitter) = '50.0 50.0 50.0';
+ MY(velocityoffset) = '0.0 0.0 15.0';
+}
+
+// TAG trail
+DEF(TR_VORESPIKE);
+// glowing vapor trail
+SUB(TR_VORESPIKE) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 968;
+ MY(color_min) = "0x804000";
+ MY(color_max) = "0x804000";
+ MY(lightcolor) = '1.5 3.0 6.0';
+ MY(lightradius) = 90;
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(trailspacing) = 4;
+ MY(type) = "static";
+ MY(velocitymultiplier) = -0.100000;
+}
+// bright sparks
+SUB(TR_VORESPIKE) {
+ MY(airfriction) = 12;
+ MY(alpha_min) = 444;
+ MY(alpha_max) = 512;
+ MY(alpha_fade) = 1866;
+ MY(bounce) = 1;
+ MY(color_min) = "0xff8000";
+ MY(color_max) = "0xff8000";
+ MY(count) = 1.500000;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(sizeincrease) = -20;
+ MY(size_min) = 2;
+ MY(size_max) = 4;
+ MY(tex_min) = 42;
+ MY(tex_max) = 42;
+ MY(trailspacing) = 12;
+ MY(type) = "snow";
+ MY(velocityjitter) = '50.0 50.0 50.0';
+ MY(velocityoffset) = '0.0 0.0 15.0';
+}
+
+DEF(flac_explode);
+SUB(flac_explode) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '8.0 4.0 1.0';
+ MY(lightradiusfade) = 400;
+ MY(lightradius) = 150;
+ MY(originjitter) = '40.0 40.0 40.0';
+ MY(size_min) = 18;
+ MY(size_max) = 28;
+ MY(tex_min) = 8;
+ MY(tex_max) = 16;
+ MY(type) = "decal";
+}
+// fire effect which make bright dot inside
+SUB(flac_explode) {
+ MY(airfriction) = 8;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 456;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0xffe955";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 3;
+ MY(liquidfriction) = 8;
+ MY(notunderwater) = true;
+ MY(originjitter) = '8.0 8.0 8.0';
+ MY(sizeincrease) = 5;
+ MY(size_min) = 6;
+ MY(size_max) = 16;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '156.0 156.0 156.0';
+}
+// fire effect which expands then slows
+SUB(flac_explode) {
+ MY(airfriction) = 12;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 456;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 6;
+ MY(liquidfriction) = 8;
+ MY(notunderwater) = true;
+ MY(originjitter) = '8.0 8.0 8.0';
+ MY(sizeincrease) = 15;
+ MY(size_min) = 10;
+ MY(size_max) = 16;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "static";
+ MY(velocityjitter) = '256.0 256.0 256.0';
+}
+// smoke
+SUB(flac_explode) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 500;
+ MY(alpha_max) = 600;
+ MY(alpha_fade) = 556;
+ MY(bounce) = 2;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x111111";
+ MY(count) = 5;
+ MY(notunderwater) = true;
+ MY(sizeincrease) = 20;
+ MY(size_min) = 10;
+ MY(size_max) = 20;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '244.0 244.0 244.0';
+}
+// underwater bubbles
+SUB(flac_explode) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x808080";
+ MY(count) = 8;
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 0.250000;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(size_min) = 1;
+ MY(size_max) = 2;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '96.0 96.0 96.0';
+}
+// bouncing sparks
+SUB(flac_explode) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 384;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x903010";
+ MY(color_max) = "0xFFD030";
+ MY(count) = 4;
+ MY(gravity) = 1;
+ MY(liquidfriction) = 0.800000;
+ MY(notunderwater) = true;
+ MY(size_min) = 2;
+ MY(size_max) = 2;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '256.0 256.0 256.0';
+ MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+// bullet trail (somewhat like a tracer)
+DEF(tr_bullet);
+SUB(tr_bullet) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 2560;
+ MY(color_min) = "0xff8960";
+ MY(color_max) = "0xff8533";
+ MY(size_min) = 4;
+ MY(size_max) = 4;
+ MY(stretchfactor) = 0.200000;
+ MY(tex_min) = 70;
+ MY(tex_max) = 70;
+ MY(trailspacing) = 750;
+ MY(type) = "spark";
+ MY(velocitymultiplier) = 3;
+}
+
+// smoke emitter for small pipes
+DEF(smoking_smallemitter);
+SUB(smoking_smallemitter) {
+ MY(airfriction) = -1;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 100;
+ MY(color_min) = "0x292929";
+ MY(color_max) = "0x000000";
+ MY(count) = 10;
+ MY(gravity) = -0.100000;
+ MY(originjitter) = '10.0 10.0 10.0';
+ MY(sizeincrease) = 20;
+ MY(size_min) = 6;
+ MY(size_max) = 15;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '5.0 5.0 20.0';
+}
+
+// crylink trail
+DEF(TR_CRYLINKPLASMA);
+// plasma smoke
+SUB(TR_CRYLINKPLASMA) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0x5522aa";
+ MY(color_max) = "0x6622ff";
+ MY(sizeincrease) = 8;
+ MY(size_min) = 2;
+ MY(size_max) = 2;
+ MY(tex_min) = 32;
+ MY(tex_max) = 32;
+ MY(trailspacing) = 128;
+ MY(type) = "static";
+ MY(velocityjitter) = '8.0 8.0 8.0';
+ MY(velocitymultiplier) = -0.010000;
+}
+// crylink main trail
+SUB(TR_CRYLINKPLASMA) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 2600;
+ MY(color_min) = "0x5522aa";
+ MY(color_max) = "0x6622ff";
+ MY(sizeincrease) = 15;
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_min) = 3;
+ MY(tex_max) = 3;
+ MY(trailspacing) = 16;
+ MY(type) = "static";
+ MY(velocityjitter) = '2.0 2.0 2.0';
+ MY(velocitymultiplier) = 0.010000;
+}
+
+DEF(cherryblossom);
+SUB(cherryblossom) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 32;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0xb123ff";
+ MY(color_max) = "0xb183ff";
+ MY(count) = 1.500000;
+ MY(gravity) = 0.050000;
+ MY(liquidfriction) = 1;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(size_min) = 1.500000;
+ MY(size_max) = 2;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "static";
+ MY(velocityjitter) = '32.0 32.0 0.0';
+}
+
+DEF(alien_blood);
+SUB(alien_blood) {
+ MY(airfriction) = 0.400000;
+ MY(alpha_min) = 1560;
+ MY(alpha_max) = 2560;
+ MY(alpha_fade) = 7000;
+ MY(blend) = "invmod";
+ MY(bounce) = -1;
+ MY(color_min) = "0xDC9BCD";
+ MY(color_max) = "0xDC9BCD";
+ MY(count) = 0.400000;
+ MY(sizeincrease) = 20;
+ MY(size_min) = 5;
+ MY(size_max) = 11;
+ MY(staincolor_min) = "0xDC9BCD";
+ MY(staincolor_max) = "0xDC9BCD";
+ MY(stainsize_min) = 1;
+ MY(stainsize_max) = 2;
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(stretchfactor) = 25;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(type) = "spark";
+ MY(velocityjitter) = '99.0 99.0 55.0';
+}
+// blood mist
+SUB(alien_blood) {
+ MY(alpha_min) = 3000;
+ MY(alpha_max) = 5560;
+ MY(alpha_fade) = 12000;
+ MY(blend) = "invmod";
+ MY(color_min) = "0xDC9BCD";
+ MY(color_max) = "0xDC9BCD";
+ MY(countabsolute) = 1;
+ MY(originjitter) = '11.0 11.0 11.0';
+ MY(sizeincrease) = 20;
+ MY(size_min) = 25;
+ MY(size_max) = 30;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(type) = "smoke";
+}
+
+DEF(robot_blood);
+SUB(robot_blood) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = -1;
+ MY(color_min) = "0xff3000";
+ MY(color_max) = "0xff7373";
+ MY(count) = 0.167000;
+ MY(gravity) = 1;
+ MY(liquidfriction) = 4;
+ MY(size_min) = 1;
+ MY(size_max) = 2;
+ MY(tex_min) = 70;
+ MY(tex_max) = 70;
+ MY(type) = "spark";
+ MY(velocityjitter) = '264.0 264.0 264.0';
+ MY(velocityoffset) = '0.0 0.0 100.0';
+}
+// shockwave
+SUB(robot_blood) {
+ MY(alpha_max) = 90;
+ MY(alpha_fade) = 1000;
+ MY(color_min) = "0xff8400";
+ MY(color_max) = "0xffbb72";
+ MY(countabsolute) = 1;
+ MY(originjitter) = '11.0 11.0 11.0';
+ MY(sizeincrease) = 800;
+ MY(size_min) = 2;
+ MY(size_max) = 2;
+ MY(tex_min) = 74;
+ MY(tex_max) = 74;
+ MY(type) = "smoke";
+}
+// electo sparks
+SUB(robot_blood) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 5120;
+ MY(color_min) = "0xff3000";
+ MY(color_max) = "0xff8585";
+ MY(count) = 0.100000;
+ MY(originjitter) = '41.0 41.0 21.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = 4000;
+ MY(spin_max) = -4000;
+ MY(size_min) = 20;
+ MY(size_max) = 40;
+ MY(tex_min) = 71;
+ MY(tex_max) = 73;
+ MY(type) = "smoke";
+}
+
+DEF(alien_TR_BLOOD);
+SUB(alien_TR_BLOOD) {
+ MY(airfriction) = -2;
+ MY(alpha_min) = 384;
+ MY(alpha_max) = 984;
+ MY(alpha_fade) = 1492;
+ MY(blend) = "invmod";
+ MY(bounce) = -1;
+ MY(color_min) = "0xC080B0";
+ MY(color_max) = "0xC080B0";
+ MY(gravity) = 0.400000;
+ MY(liquidfriction) = 1;
+ MY(sizeincrease) = -5;
+ MY(size_min) = 4;
+ MY(size_max) = 19;
+ MY(staincolor_min) = "0xC080B0";
+ MY(staincolor_max) = "0xC080B0";
+ MY(stainsize_min) = 1;
+ MY(stainsize_max) = 2;
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(stretchfactor) = 7;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(trailspacing) = 20;
+ MY(type) = "spark";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+ MY(velocitymultiplier) = -0.100000;
+}
+
+// splash around gib
+SUB(TR_BLOOD) {
+ MY(alpha_min) = 684;
+ MY(alpha_max) = 684;
+ MY(alpha_fade) = 7492;
+ MY(color_min) = "0xA8FFFF";
+ MY(color_max) = "0xA8FFFF";
+ MY(sizeincrease) = 500;
+ MY(size_min) = 4;
+ MY(size_max) = 6;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(trailspacing) = 42;
+ MY(type) = "blood";
+}
+
+DEF(robot_TR_BLOOD);
+SUB(robot_TR_BLOOD) {
+ MY(airfriction) = -2;
+ MY(alpha_min) = 384;
+ MY(alpha_max) = 984;
+ MY(alpha_fade) = 1892;
+ MY(blend) = "invmod";
+ MY(bounce) = -1;
+ MY(color_min) = "0xC0D890";
+ MY(color_max) = "0xC0D890";
+ MY(gravity) = 0.400000;
+ MY(liquidfriction) = 1;
+ MY(sizeincrease) = -6;
+ MY(size_min) = 4;
+ MY(size_max) = 13;
+ MY(staincolor_min) = "0x808080";
+ MY(staincolor_max) = "0x808080";
+ MY(stainsize_min) = 1;
+ MY(stainsize_max) = 3;
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(stretchfactor) = 6;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(trailspacing) = 16;
+ MY(type) = "spark";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+ MY(velocitymultiplier) = -0.300000;
+}
+// fire
+SUB(robot_TR_BLOOD) {
+ MY(airfriction) = 4;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 900;
+ MY(color_min) = "0x902010";
+ MY(color_max) = "0xff3600";
+ MY(gravity) = -1;
+ MY(liquidfriction) = 4;
+ MY(notunderwater) = true;
+ MY(sizeincrease) = 10;
+ MY(size_min) = 5;
+ MY(size_max) = 20;
+ MY(stretchfactor) = 5;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(trailspacing) = 16;
+ MY(type) = "spark";
+ MY(velocityjitter) = '44.0 44.0 44.0';
+}
+// arcs
+SUB(robot_TR_BLOOD) {
+ MY(alpha_min) = 1128;
+ MY(alpha_max) = 1256;
+ MY(alpha_fade) = 44900;
+ MY(color_min) = "0xff3000";
+ MY(color_max) = "0xff8585";
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = 4000;
+ MY(spin_max) = -4000;
+ MY(size_min) = 25;
+ MY(size_max) = 30;
+ MY(tex_min) = 71;
+ MY(tex_max) = 73;
+ MY(trailspacing) = 128;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '44.0 44.0 44.0';
+}
+
+DEF(alien_TR_SLIGHTBLOOD);
+SUB(alien_TR_SLIGHTBLOOD) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 384;
+ MY(alpha_max) = 384;
+ MY(alpha_fade) = 192;
+ MY(bounce) = -1;
+ MY(color_min) = "0xC080B0";
+ MY(color_max) = "0xC080B0";
+ MY(liquidfriction) = 4;
+ MY(size_min) = 80;
+ MY(size_max) = 80;
+ MY(staincolor_min) = "0x808080";
+ MY(staincolor_max) = "0x808080";
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(trailspacing) = 64;
+ MY(type) = "blood";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+ MY(velocitymultiplier) = 0.500000;
+}
+
+DEF(robot_TR_SLIGHTBLOOD);
+SUB(robot_TR_SLIGHTBLOOD) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 384;
+ MY(alpha_max) = 384;
+ MY(alpha_fade) = 192;
+ MY(bounce) = -1;
+ MY(color_min) = "0xC0D890";
+ MY(color_max) = "0xC0D890";
+ MY(liquidfriction) = 4;
+ MY(size_min) = 8;
+ MY(size_max) = 8;
+ MY(staincolor_min) = "0x808080";
+ MY(staincolor_max) = "0x808080";
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(trailspacing) = 64;
+ MY(type) = "blood";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+ MY(velocitymultiplier) = 0.500000;
+}
+
+DEF(item_pickup);
+// flare particle and light
+SUB(item_pickup) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 64;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0x63F2EA";
+ MY(color_max) = "0xB0C5C4";
+ MY(countabsolute) = 1;
+ MY(size_min) = 8;
+ MY(size_max) = 16;
+ MY(type) = "static";
+}
+// cloud of particles which expand rapidly and then slow to form a ball
+SUB(item_pickup) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1280;
+ MY(color_min) = "0x63F2EA";
+ MY(color_max) = "0xB0C5C4";
+ MY(count) = 32;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_min) = 41;
+ MY(tex_max) = 41;
+ MY(type) = "spark";
+ MY(velocityjitter) = '256.0 256.0 256.0';
+}
+
+DEF(bloodshower);
+SUB(bloodshower) {
+ MY(alpha_min) = 156;
+ MY(alpha_max) = 656;
+ MY(alpha_fade) = 1664;
+ MY(blend) = "invmod";
+ MY(bounce) = -1;
+ MY(color_min) = "0xA8FFFF";
+ MY(color_max) = "0xA8FFFFF";
+ MY(count) = 125;
+ MY(gravity) = 1;
+ MY(liquidfriction) = 4;
+ MY(size_min) = 8;
+ MY(size_max) = 28;
+ MY(staincolor_min) = "0x808080";
+ MY(staincolor_max) = "0x808080";
+ MY(stainsize_min) = 1;
+ MY(stainsize_max) = 2;
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(stretchfactor) = 3;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(type) = "spark";
+ MY(velocityjitter) = '764.0 764.0 764.0';
+}
+// center blood
+SUB(bloodshower) {
+ MY(alpha_min) = 156;
+ MY(alpha_max) = 656;
+ MY(alpha_fade) = 1664;
+ MY(blend) = "invmod";
+ MY(color_min) = "0xA8FFFF";
+ MY(color_max) = "0xA8FFFFF";
+ MY(countabsolute) = 0.100000;
+ MY(originjitter) = '50.0 50.0 50.0';
+ MY(sizeincrease) = 300;
+ MY(size_min) = 1;
+ MY(size_max) = 28;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(type) = "smoke";
+}
+
+DEF(alien_bloodshower);
+SUB(alien_bloodshower) {
+ MY(alpha_min) = 156;
+ MY(alpha_max) = 656;
+ MY(alpha_fade) = 1664;
+ MY(blend) = "invmod";
+ MY(bounce) = -1;
+ MY(color_min) = "0xC080B0";
+ MY(color_max) = "0xC080B0";
+ MY(count) = 125;
+ MY(gravity) = 1;
+ MY(liquidfriction) = 4;
+ MY(size_min) = 8;
+ MY(size_max) = 28;
+ MY(staincolor_min) = "0xC080B0";
+ MY(staincolor_max) = "0xC080B0";
+ MY(stainsize_min) = 1;
+ MY(stainsize_max) = 2;
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(stretchfactor) = 3;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(type) = "spark";
+ MY(velocityjitter) = '764.0 764.0 764.0';
+}
+// center blood
+SUB(bloodshower) {
+ MY(alpha_min) = 156;
+ MY(alpha_max) = 656;
+ MY(alpha_fade) = 1664;
+ MY(blend) = "invmod";
+ MY(color_min) = "0xA8FFFF";
+ MY(color_max) = "0xA8FFFFF";
+ MY(countabsolute) = 0.100000;
+ MY(originjitter) = '50.0 50.0 50.0';
+ MY(sizeincrease) = 300;
+ MY(size_min) = 1;
+ MY(size_max) = 28;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(type) = "smoke";
+}
+
+DEF(robot_bloodshower);
+SUB(robot_bloodshower) {
+ MY(alpha_min) = 156;
+ MY(alpha_max) = 656;
+ MY(alpha_fade) = 1664;
+ MY(blend) = "invmod";
+ MY(bounce) = -1;
+ MY(color_min) = "0xC0D890";
+ MY(color_max) = "0xC0D890";
+ MY(count) = 100;
+ MY(gravity) = 1;
+ MY(liquidfriction) = 4;
+ MY(size_min) = 8;
+ MY(size_max) = 28;
+ MY(staincolor_min) = "0xC0D890";
+ MY(staincolor_max) = "0xC0D890";
+ MY(stainsize_min) = 1;
+ MY(stainsize_max) = 2;
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(stretchfactor) = 3;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(type) = "spark";
+ MY(velocityjitter) = '764.0 764.0 764.0';
+}
+// arc
+SUB(robot_bloodshower) {
+ MY(alpha_min) = 1128;
+ MY(alpha_max) = 1256;
+ MY(alpha_fade) = 4200;
+ MY(color_min) = "0xff3000";
+ MY(color_max) = "0xff8585";
+ MY(count) = 2.500000;
+ MY(originjitter) = '150.0 150.0 150.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = 99;
+ MY(spin_max) = -99;
+ MY(size_min) = 25;
+ MY(size_max) = 40;
+ MY(tex_min) = 71;
+ MY(tex_max) = 73;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '44.0 44.0 44.0';
+}
+// shockwave
+SUB(robot_bloodshower) {
+ MY(alpha_min) = 11;
+ MY(alpha_max) = 125;
+ MY(alpha_fade) = 990;
+ MY(color_min) = "0xff3000";
+ MY(color_max) = "0xff8585";
+ MY(count) = 2.500000;
+ MY(sizeincrease) = 3000;
+ MY(size_min) = 5;
+ MY(size_max) = 50;
+ MY(tex_min) = 74;
+ MY(tex_max) = 74;
+ MY(type) = "smoke";
+}
+
+#define ground_quake(name, colormin, colormax) \
+ DEF(name##_ground_quake); \
+ SUB(name##_ground_quake) /* smoke */ { \
+ MY(airfriction) = 3; \
+ MY(alpha_min) = 100; \
+ MY(alpha_max) = 126; \
+ MY(alpha_fade) = 200; \
+ MY(bounce) = 1.100000; \
+ MY(color_min) = "0x111111"; \
+ MY(color_max) = "0xbbbbbb"; \
+ MY(count) = 90; \
+ MY(gravity) = 0.500000; \
+ MY(notunderwater) = true; \
+ MY(sizeincrease) = 100; \
+ MY(size_min) = 20; \
+ MY(size_max) = 50; \
+ MY(tex_max) = 8; \
+ MY(time_min) = 5; \
+ MY(time_max) = 10; \
+ MY(type) = "smoke"; \
+ MY(velocityjitter) = '190.0 190.0 50.0'; \
+ } \
+ SUB(name##_ground_quake) { \
+ MY(airfriction) = 4; \
+ MY(alpha_min) = 100; \
+ MY(alpha_max) = 126; \
+ MY(alpha_fade) = 200; \
+ MY(bounce) = 1.200000; \
+ MY(color_min) = "0x111111"; \
+ MY(color_max) = "0x979797"; \
+ MY(count) = 40; \
+ MY(gravity) = 0.200000; \
+ MY(notunderwater) = true; \
+ MY(sizeincrease) = 60; \
+ MY(size_min) = 10; \
+ MY(size_max) = 30; \
+ MY(tex_max) = 8; \
+ MY(time_min) = 10; \
+ MY(time_max) = 15; \
+ MY(type) = "smoke"; \
+ MY(velocityjitter) = '190.0 190.0 50.0'; \
+ } \
+ SUB(name##_ground_quake) { \
+ MY(alpha_min) = 200; \
+ MY(alpha_max) = 356; \
+ MY(alpha_fade) = 512; \
+ MY(bounce) = 6; \
+ MY(color_min) = colormin; \
+ MY(color_max) = colormax; \
+ MY(count) = 16; \
+ MY(gravity) = -0.500000; \
+ MY(originjitter) = '33.0 33.0 33.0'; \
+ MY(sizeincrease) = 5; \
+ MY(size_min) = 4; \
+ MY(size_max) = 20; \
+ MY(tex_min) = 48; \
+ MY(tex_max) = 55; \
+ MY(time_min) = 15; \
+ MY(time_max) = 25; \
+ MY(type) = "smoke"; \
+ MY(velocityjitter) = '22.0 22.0 50.0'; \
+ } \
+ SUB(name##_ground_quake) /* smoke */ { \
+ MY(alpha_min) = 200; \
+ MY(alpha_max) = 256; \
+ MY(alpha_fade) = 200; \
+ MY(bounce) = 2; \
+ MY(color_min) = "0x000000"; \
+ MY(color_max) = "0xffffff"; \
+ MY(count) = 11; \
+ MY(gravity) = -0.300000; \
+ MY(originjitter) = '44.0 44.0 44.0'; \
+ MY(sizeincrease) = 11; \
+ MY(size_min) = 22; \
+ MY(size_max) = 33; \
+ MY(tex_max) = 8; \
+ MY(time_min) = 25; \
+ MY(time_max) = 35; \
+ MY(type) = "alphastatic"; \
+ MY(velocityjitter) = '11.0 11.0 50.0'; \
+ } \
+ /**/
+
+ground_quake(red, "0x9E6A64", "0x91302D")
+ground_quake(blue, "0x64679E", "0x2D4C91")
+#undef ground_quake
+
+#include "effectinfo_gentle_morphed.inc"
+
+// Team / hit vaporizer effects
+#define TE_TEI_G3(name, colormin1, colormax1, colormin2, colormax2) \
+ DEF(TE_TEI_G3##name); \
+ SUB(TE_TEI_G3##name) { \
+ MY(alpha_min) = 128; \
+ MY(alpha_max) = 128; \
+ MY(alpha_fade) = 256; \
+ MY(color_min) = colormin1; \
+ MY(color_max) = colormax1; \
+ MY(countabsolute) = 1; \
+ MY(size_min) = 4; \
+ MY(size_max) = 4; \
+ MY(tex_min) = 200; \
+ MY(tex_max) = 200; \
+ MY(type) = "beam"; \
+ } \
+ SUB(TE_TEI_G3##name) { \
+ MY(airfriction) = -4; \
+ MY(alpha_min) = 256; \
+ MY(alpha_max) = 256; \
+ MY(alpha_fade) = 512; \
+ MY(color_min) = colormin2; \
+ MY(color_max) = colormax2; \
+ MY(sizeincrease) = 3; \
+ MY(size_min) = 0.300000; \
+ MY(size_max) = 0.300000; \
+ MY(tex_min) = 46; \
+ MY(tex_max) = 46; \
+ MY(trailspacing) = 8; \
+ MY(type) = "smoke"; \
+ MY(velocityjitter) = '3.0 3.0 3.0'; \
+ } \
+ DEF(TE_TEI_G3##name##_HIT); \
+ SUB(TE_TEI_G3##name##_HIT) { \
+ MY(alpha_min) = 128; \
+ MY(alpha_max) = 128; \
+ MY(alpha_fade) = 256; \
+ MY(color_min) = colormin1; \
+ MY(color_max) = colormax1; \
+ MY(countabsolute) = 1; \
+ MY(size_min) = 8; \
+ MY(size_max) = 8; \
+ MY(tex_min) = 200; \
+ MY(tex_max) = 200; \
+ MY(type) = "beam"; \
+ } \
+ SUB(TE_TEI_G3##name##_HIT) /* rings */ { \
+ MY(airfriction) = -4; \
+ MY(alpha_min) = 256; \
+ MY(alpha_max) = 256; \
+ MY(alpha_fade) = 512; \
+ MY(color_min) = "0xFFFFFF"; \
+ MY(color_max) = colormax1; \
+ MY(sizeincrease) = -2; \
+ MY(size_min) = 2; \
+ MY(size_max) = 2; \
+ MY(trailspacing) = 20; \
+ MY(type) = "smoke"; \
+ MY(velocityjitter) = '2.0 2.0 2.0'; \
+ } \
+ SUB(TE_TEI_G3##name##_HIT) { \
+ MY(airfriction) = -4; \
+ MY(alpha_min) = 256; \
+ MY(alpha_max) = 256; \
+ MY(alpha_fade) = 512; \
+ MY(color_min) = colormin1; \
+ MY(color_max) = colormax1; \
+ MY(sizeincrease) = -6; \
+ MY(size_min) = 10; \
+ MY(size_max) = 10; \
+ MY(trailspacing) = 40; \
+ MY(type) = "smoke"; \
+ } \
+ /**/
+TE_TEI_G3(RED, "0xFF0000", "0xFF0011", "0x200000", "0x400000")
+TE_TEI_G3(BLUE, "0x0000FF", "0x1100FF", "0x000020", "0x000040")
+TE_TEI_G3(YELLOW, "0xffff00", "0xffff11", "0x202000", "0x404000")
+TE_TEI_G3(PINK, "0xFF00FF", "0xFF11FF", "0x200020", "0x400040")
+#undef TE_TEI_G3
+
+#include "effectinfo_gentle_particlegibs.inc"
+
+#include "effectinfo_onslaught.inc"
+
+DEF(firemine);
+SUB(firemine) {
+ MY(airfriction) = 1.200000;
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 250;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 0.500000;
+ MY(gravity) = -0.060000;
+ MY(sizeincrease) = 5;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(trailspacing) = 2;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '10.0 10.0 2.0';
+}
+// slowfire
+SUB(firemine) {
+ MY(airfriction) = 1.200000;
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 200;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 0.500000;
+ MY(gravity) = -0.060000;
+ MY(sizeincrease) = 5;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(trailspacing) = 2;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '10.0 10.0 10.0';
+}
+// very slow and small fire
+SUB(firemine) {
+ MY(airfriction) = 0.300000;
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 200;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 0.500000;
+ MY(gravity) = -0.060000;
+ MY(sizeincrease) = 2;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(trailspacing) = 4;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '8.0 8.0 8.0';
+}
+// decreasing fire
+SUB(firemine) {
+ MY(airfriction) = 0.300000;
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 200;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 0.500000;
+ MY(gravity) = -0.060000;
+ MY(sizeincrease) = -3;
+ MY(size_min) = 5;
+ MY(size_max) = 7;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(trailspacing) = 4;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '3.0 3.0 3.0';
+}
+// smoke
+SUB(firemine) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 90;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x111111";
+ MY(count) = 0.500000;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(sizeincrease) = 1;
+ MY(size_min) = 1;
+ MY(size_max) = 4;
+ MY(tex_max) = 8;
+ MY(trailspacing) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityoffset) = '0.0 0.0 3.0';
+}
+// fastfire
+SUB(firemine) {
+ MY(airfriction) = 1.200000;
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1600;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 0.500000;
+ MY(size_min) = 12;
+ MY(size_max) = 12;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(trailspacing) = 1;
+ MY(type) = "smoke";
+}
+// light only
+SUB(firemine) {
+ MY(lightcolor) = '2.7 2.7 0.6';
+ MY(lightradiusfade) = 50000;
+ MY(lightradius) = 50;
+ MY(trailspacing) = 16;
+}
+
+DEF(fireball);
+SUB(fireball) {
+ MY(airfriction) = 1.200000;
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 250;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 0.500000;
+ MY(gravity) = -0.060000;
+ MY(sizeincrease) = 20;
+ MY(size_min) = 5;
+ MY(size_max) = 5;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(trailspacing) = 2;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '40.0 40.0 11.0';
+}
+// slow fire
+SUB(fireball) {
+ MY(airfriction) = 1.200000;
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 200;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 0.500000;
+ MY(gravity) = -0.060000;
+ MY(sizeincrease) = 20;
+ MY(size_min) = 5;
+ MY(size_max) = 5;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(trailspacing) = 2;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '40.0 40.0 40.0';
+}
+// very slow and small fire
+SUB(fireball) {
+ MY(airfriction) = 0.300000;
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 200;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 0.500000;
+ MY(gravity) = -0.060000;
+ MY(sizeincrease) = 10;
+ MY(size_min) = 5;
+ MY(size_max) = 5;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(trailspacing) = 4;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '30.0 30.0 30.0';
+}
+// decreasing fire
+SUB(fireball) {
+ MY(airfriction) = 0.300000;
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 200;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 0.500000;
+ MY(gravity) = -0.060000;
+ MY(sizeincrease) = -10;
+ MY(size_min) = 20;
+ MY(size_max) = 30;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(trailspacing) = 4;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '10.0 10.0 10.0';
+}
+// smoke
+SUB(fireball) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 90;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x111111";
+ MY(count) = 0.500000;
+ MY(originjitter) = '10.0 10.0 10.0';
+ MY(sizeincrease) = 7;
+ MY(size_min) = 5;
+ MY(size_max) = 15;
+ MY(tex_max) = 8;
+ MY(trailspacing) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityoffset) = '0.0 0.0 10.0';
+}
+// fast fire
+SUB(fireball) {
+ MY(airfriction) = 1.200000;
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1600;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 0.500000;
+ MY(size_min) = 48;
+ MY(size_max) = 48;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(trailspacing) = 1;
+ MY(type) = "smoke";
+}
+// light only
+SUB(fireball) {
+ MY(lightcolor) = '2.7 2.7 0.6';
+ MY(lightradiusfade) = 3000;
+ MY(lightradius) = 300;
+ MY(trailspacing) = 16;
+}
+
+DEF(fireball_laser);
+SUB(fireball_laser) {
+ MY(alpha_min) = 192;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 2560;
+ MY(color_min) = "0x800000";
+ MY(color_max) = "0xFF8020";
+ MY(count) = 10;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(stretchfactor) = 0.700000;
+ MY(type) = "spark";
+ MY(velocityjitter) = '1.0 1.0 1.0';
+ MY(velocitymultiplier) = 10;
+}
+
+// rocket explosion (bigger than mortar and hagar)
+DEF(fireball_explode);
+// decal
+SUB(fireball_explode) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '4.0 2.0 0.5';
+ MY(lightradiusfade) = 500;
+ MY(lightradius) = 500;
+ MY(originjitter) = '56.0 56.0 56.0';
+ MY(size_min) = 72;
+ MY(size_max) = 72;
+ MY(tex_min) = 8;
+ MY(tex_max) = 16;
+ MY(type) = "decal";
+}
+// flare effect
+SUB(fireball_explode) {
+ MY(alpha_min) = 192;
+ MY(alpha_max) = 192;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x404040";
+ MY(countabsolute) = 1;
+ MY(size_min) = 72;
+ MY(size_max) = 72;
+ MY(tex_min) = 35;
+ MY(tex_max) = 37;
+ MY(type) = "static";
+}
+// fire effect
+SUB(fireball_explode) {
+ MY(airfriction) = 4;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 256;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x902010";
+ MY(color_max) = "0xFFD080";
+ MY(count) = 128;
+ MY(liquidfriction) = 4;
+ MY(notunderwater) = true;
+ MY(originjitter) = '8.0 8.0 8.0';
+ MY(size_min) = 16;
+ MY(size_max) = 16;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "static";
+ MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// underwater bubbles
+SUB(fireball_explode) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x808080";
+ MY(count) = 32;
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 0.250000;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '144.0 144.0 144.0';
+}
+// bouncing sparks
+SUB(fireball_explode) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 384;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x903010";
+ MY(color_max) = "0xFFD030";
+ MY(count) = 64;
+ MY(gravity) = 1;
+ MY(liquidfriction) = 0.800000;
+ MY(notunderwater) = true;
+ MY(size_min) = 2;
+ MY(size_max) = 2;
+ MY(type) = "spark";
+ MY(velocityjitter) = '384.0 384.0 384.0';
+ MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+DEF(fireball_muzzleflash);
+SUB(fireball_muzzleflash) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x202020";
+ MY(color_max) = "0x404040";
+ MY(count) = 2;
+ MY(lightcolor) = '2.0 1.5 0.2';
+ MY(lightradiusfade) = 2000;
+ MY(lightradius) = 200;
+ MY(originjitter) = '1.5 1.5 1.5';
+ MY(size_min) = 5;
+ MY(size_max) = 5;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '6.0 6.0 6.0';
+ MY(velocitymultiplier) = 0.010000;
+}
+SUB(fireball_muzzleflash) {
+ MY(airfriction) = 12;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0xFFFDD9";
+ MY(color_max) = "0xFFFDD9";
+ MY(count) = 15;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '300.0 300.0 300.0';
+ MY(velocitymultiplier) = 0.500000;
+}
+
+DEF(fireball_preattack_muzzleflash);
+SUB(fireball_preattack_muzzleflash) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x202020";
+ MY(color_max) = "0x404040";
+ MY(count) = 2;
+ MY(lightcolor) = '2.0 1.5 0.2';
+ MY(lightradiusfade) = 2000;
+ MY(lightradius) = 200;
+ MY(originjitter) = '1.5 1.5 1.5';
+ MY(size_min) = 5;
+ MY(size_max) = 5;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '6.0 6.0 6.0';
+ MY(velocitymultiplier) = 0.010000;
+}
+SUB(fireball_preattack_muzzleflash) {
+ MY(airfriction) = 12;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0xFFFDD9";
+ MY(color_max) = "0xFFFDD9";
+ MY(count) = 15;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '300.0 300.0 300.0';
+ MY(velocitymultiplier) = 0.500000;
+}
+
+DEF(fireball_bfgdamage);
+SUB(fireball_bfgdamage) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x202020";
+ MY(color_max) = "0x404040";
+ MY(count) = 2;
+ MY(lightcolor) = '2.0 1.5 0.2';
+ MY(lightradiusfade) = 2000;
+ MY(lightradius) = 200;
+ MY(originjitter) = '1.5 1.5 1.5';
+ MY(size_min) = 5;
+ MY(size_max) = 5;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '6.0 6.0 6.0';
+ MY(velocitymultiplier) = 0.010000;
+}
+SUB(fireball_bfgdamage) {
+ MY(airfriction) = 12;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0xFFFDD9";
+ MY(color_max) = "0xFFFDD9";
+ MY(count) = 15;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '300.0 300.0 300.0';
+ MY(velocitymultiplier) = 0.500000;
+}
+
+DEF(EF_FLAME);
+// fire
+SUB(EF_FLAME) {
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 356;
+ MY(alpha_fade) = 512;
+ MY(bounce) = 2;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 100;
+ MY(gravity) = -0.500000;
+ MY(originjitter) = '12.0 12.0 34.0';
+ MY(originoffset) = '0.0 0.0 10.0';
+ MY(sizeincrease) = -1;
+ MY(size_min) = 5;
+ MY(size_max) = 21;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '22.0 22.0 50.0';
+}
+// smoke
+SUB(EF_FLAME) {
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 200;
+ MY(bounce) = 2;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x111111";
+ MY(count) = 50;
+ MY(gravity) = -0.300000;
+ MY(originjitter) = '12.0 12.0 34.0';
+ MY(originoffset) = '0.0 0.0 10.0';
+ MY(sizeincrease) = 6;
+ MY(size_min) = 11;
+ MY(size_max) = 15;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '11.0 11.0 50.0';
+}
+SUB(EF_FLAME) {
+ MY(count) = 0.500000;
+ MY(lightcolor) = '0.9 0.9 0.2';
+ MY(lightradiusfade) = 10000;
+ MY(lightradius) = 200;
+}
+
+// rifle bullet trail (somewhat like a tracer)
+DEF(tr_rifle);
+SUB(tr_rifle) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 2560;
+ MY(color_min) = "0x800000";
+ MY(color_max) = "0xFF8020";
+ MY(size_min) = 1.500000;
+ MY(size_max) = 1.500000;
+ MY(stretchfactor) = 1;
+ MY(trailspacing) = 128;
+ MY(type) = "spark";
+ MY(velocitymultiplier) = 0.700000;
+}
+SUB(tr_rifle) {
+ MY(airfriction) = -4;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0x202020";
+ MY(color_max) = "0x404040";
+ MY(notunderwater) = true;
+ MY(sizeincrease) = 0.400000;
+ MY(size_min) = 4;
+ MY(size_max) = 4;
+ MY(tex_max) = 8;
+ MY(trailspacing) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '4.0 4.0 4.0';
+}
+SUB(tr_rifle) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 128;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x808080";
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 4;
+ MY(size_min) = 2;
+ MY(size_max) = 2;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(trailspacing) = 32;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '16.0 16.0 16.0';
+}
+
+// rocket guiding start
+DEF(rocket_guide);
+// underwater bubbles
+SUB(rocket_guide) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x808080";
+ MY(count) = 2;
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 0.250000;
+ MY(originjitter) = '8.0 8.0 8.0';
+ MY(size_min) = 1.500000;
+ MY(size_max) = 1.500000;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '48.0 48.0 48.0';
+ MY(velocitymultiplier) = -0.100000;
+}
+// bouncing sparks
+SUB(rocket_guide) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 984;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x903010";
+ MY(color_max) = "0xFFD030";
+ MY(count) = 8;
+ MY(gravity) = 1;
+ MY(liquidfriction) = 0.800000;
+ MY(notunderwater) = true;
+ MY(size_min) = 0.300000;
+ MY(size_max) = 0.700000;
+ MY(stretchfactor) = 0.400000;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '156.0 156.0 156.0';
+ MY(velocitymultiplier) = -0.300000;
+ MY(velocityoffset) = '0.0 0.0 80.0';
+}
+SUB(rocket_guide) {
+ MY(alpha_min) = 100;
+ MY(alpha_max) = 100;
+ MY(alpha_fade) = 500;
+ MY(color_min) = "0x903010";
+ MY(color_max) = "0xFFD030";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 300;
+ MY(size_min) = 10;
+ MY(size_max) = 10;
+ MY(tex_min) = 65;
+ MY(tex_max) = 65;
+ MY(type) = "smoke";
+}
+
+// gauntlet laser
+DEF(laser_gauntlet);
+SUB(laser_gauntlet) {
+ MY(airfriction) = 10;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 512;
+ MY(alpha_fade) = 6280;
+ MY(color_min) = "0xb44215";
+ MY(color_max) = "0x880000";
+ MY(count) = 3;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = 4000;
+ MY(spin_max) = -4000;
+ MY(sizeincrease) = -100;
+ MY(size_min) = 7;
+ MY(size_max) = 10;
+ MY(stretchfactor) = 2.300000;
+ MY(tex_min) = 43;
+ MY(tex_max) = 43;
+ MY(type) = "spark";
+ MY(velocityjitter) = '150.0 150.0 150.0';
+ MY(velocitymultiplier) = 0.200000;
+}
+SUB(laser_gauntlet) {
+ MY(airfriction) = 12;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 512;
+ MY(alpha_fade) = 6280;
+ MY(color_min) = "0xff4200";
+ MY(color_max) = "0xff0000";
+ MY(count) = 6;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(sizeincrease) = -100;
+ MY(size_min) = 7;
+ MY(size_max) = 9;
+ MY(stretchfactor) = 2;
+ MY(tex_min) = 8;
+ MY(tex_max) = 15;
+ MY(type) = "spark";
+ MY(velocityjitter) = '100.0 100.0 100.0';
+ MY(velocitymultiplier) = 0.200000;
+}
+
+DEF(laser_gauntletmuzzleflash);
+// glow and light
+SUB(laser_gauntletmuzzleflash) {
+ MY(airfriction) = 10;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 512;
+ MY(alpha_fade) = 6280;
+ MY(color_min) = "0x220000";
+ MY(color_max) = "0x880000";
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '3.0 0.1 0.1';
+ MY(lightradiusfade) = 500;
+ MY(lightradius) = 150;
+ MY(sizeincrease) = -100;
+ MY(size_min) = 10;
+ MY(size_max) = 15;
+ MY(stretchfactor) = 2;
+ MY(tex_min) = 65;
+ MY(tex_max) = 65;
+ MY(type) = "smoke";
+}
+// electricity
+SUB(laser_gauntletmuzzleflash) {
+ MY(airfriction) = 10;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 512;
+ MY(alpha_fade) = 6280;
+ MY(color_min) = "0xb44215";
+ MY(color_max) = "0x880000";
+ MY(count) = 3;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = 4000;
+ MY(spin_max) = -4000;
+ MY(sizeincrease) = -100;
+ MY(size_min) = 7;
+ MY(size_max) = 10;
+ MY(stretchfactor) = 2.300000;
+ MY(tex_min) = 43;
+ MY(tex_max) = 43;
+ MY(type) = "spark";
+ MY(velocityjitter) = '150.0 150.0 150.0';
+ MY(velocitymultiplier) = 0.200000;
+}
+// fire
+SUB(laser_gauntletmuzzleflash) {
+ MY(airfriction) = 12;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 512;
+ MY(alpha_fade) = 6280;
+ MY(color_min) = "0xff4200";
+ MY(color_max) = "0xff0000";
+ MY(count) = 6;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(sizeincrease) = -100;
+ MY(size_min) = 7;
+ MY(size_max) = 9;
+ MY(stretchfactor) = 2;
+ MY(tex_min) = 8;
+ MY(tex_max) = 15;
+ MY(type) = "spark";
+ MY(velocityjitter) = '100.0 100.0 100.0';
+ MY(velocitymultiplier) = 0.200000;
+}
+
+// torch flame, spawn it as fast as you can 20 times per second or more, supports direction but not required
+DEF(torchflame);
+// fast fire
+SUB(torchflame) {
+ MY(airfriction) = 1.200000;
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 250;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 3;
+ MY(gravity) = -0.060000;
+ MY(sizeincrease) = 20;
+ MY(size_min) = 5;
+ MY(size_max) = 5;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '40.0 40.0 11.0';
+ MY(velocitymultiplier) = 30;
+}
+// slow fire
+SUB(torchflame) {
+ MY(airfriction) = 1.200000;
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 200;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 2.500000;
+ MY(gravity) = -0.060000;
+ MY(sizeincrease) = 20;
+ MY(size_min) = 5;
+ MY(size_max) = 5;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '40.0 40.0 40.0';
+ MY(velocitymultiplier) = 20;
+}
+// very slow and small fire
+SUB(torchflame) {
+ MY(airfriction) = 0.300000;
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 200;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 1.500000;
+ MY(gravity) = -0.060000;
+ MY(sizeincrease) = 10;
+ MY(size_min) = 5;
+ MY(size_max) = 5;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '30.0 30.0 30.0';
+ MY(velocitymultiplier) = 10;
+}
+// decreasing fire
+SUB(torchflame) {
+ MY(airfriction) = 0.300000;
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 200;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 2;
+ MY(gravity) = -0.060000;
+ MY(sizeincrease) = -10;
+ MY(size_min) = 20;
+ MY(size_max) = 30;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '10.0 10.0 10.0';
+ MY(velocitymultiplier) = 15;
+}
+// smoke
+SUB(torchflame) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 90;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x111111";
+ MY(count) = 0.500000;
+ MY(originjitter) = '10.0 10.0 10.0';
+ MY(sizeincrease) = 7;
+ MY(size_min) = 5;
+ MY(size_max) = 15;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocitymultiplier) = 20;
+ MY(velocityoffset) = '0.0 0.0 10.0';
+}
+
+#include "effectinfo_gentle_happy.inc"
+
+DEF(electro_lightning);
+SUB(electro_lightning) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '3.1 4.4 10.0';
+ MY(lightradiusfade) = 500;
+ MY(lightradius) = 50;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(size_min) = 16;
+ MY(size_max) = 16;
+ MY(tex_min) = 59;
+ MY(tex_max) = 59;
+ MY(type) = "decal";
+}
+SUB(electro_lightning) {
+ MY(alpha_min) = 100;
+ MY(alpha_max) = 206;
+ MY(alpha_fade) = 1724;
+ MY(color_min) = "0x2030FF";
+ MY(color_max) = "0x80C0FF";
+ MY(count) = 300;
+ MY(originjitter) = '1.5 1.5 1.5';
+ MY(sizeincrease) = 10;
+ MY(size_min) = 6;
+ MY(size_max) = 6;
+ MY(tex_min) = 65;
+ MY(tex_max) = 65;
+ MY(type) = "spark";
+ MY(velocityjitter) = '6.0 6.0 6.0';
+ MY(velocitymultiplier) = 2000;
+}
+SUB(electro_lightning) {
+ MY(airfriction) = 2;
+ MY(alpha_min) = 110;
+ MY(alpha_max) = 170;
+ MY(alpha_fade) = 1500;
+ MY(color_min) = "0xDDFDFF";
+ MY(color_max) = "0xFDFDFF";
+ MY(count) = 30;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 2;
+ MY(size_max) = 5;
+ MY(stretchfactor) = 1.500000;
+ MY(tex_min) = 8;
+ MY(tex_max) = 15;
+ MY(type) = "spark";
+ MY(velocityjitter) = '150.0 150.0 150.0';
+ MY(velocitymultiplier) = 0.500000;
+}
+SUB(electro_lightning) {
+ MY(airfriction) = 8;
+ MY(alpha_min) = 110;
+ MY(alpha_max) = 170;
+ MY(alpha_fade) = 1500;
+ MY(color_min) = "0xFDFDFF";
+ MY(color_max) = "0xF9FDFF";
+ MY(count) = 50;
+ MY(gravity) = 1.300000;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 2;
+ MY(size_max) = 3;
+ MY(stretchfactor) = 0.100000;
+ MY(tex_min) = 41;
+ MY(tex_max) = 41;
+ MY(type) = "spark";
+ MY(velocityjitter) = '350.0 350.0 350.0';
+ MY(velocitymultiplier) = 2.500000;
+}
+
+DEF(gauntlet_lightning);
+SUB(gauntlet_lightning) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0x280000";
+ MY(color_max) = "0x280000";
+ MY(count) = 300;
+ MY(originjitter) = '1.5 1.5 1.5';
+ MY(sizeincrease) = 15;
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_min) = 65;
+ MY(tex_max) = 65;
+ MY(type) = "spark";
+ MY(velocityjitter) = '6.0 6.0 6.0';
+ MY(velocitymultiplier) = 2000;
+}
+SUB(gauntlet_lightning) {
+ MY(airfriction) = 2;
+ MY(alpha_min) = 110;
+ MY(alpha_max) = 228;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0xDD0000";
+ MY(color_max) = "0xFD0000";
+ MY(count) = 30;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 2;
+ MY(size_max) = 5;
+ MY(stretchfactor) = 1.500000;
+ MY(tex_min) = 8;
+ MY(tex_max) = 15;
+ MY(type) = "spark";
+ MY(velocityjitter) = '150.0 150.0 150.0';
+ MY(velocitymultiplier) = 0.500000;
+}
+SUB(gauntlet_lightning) {
+ MY(airfriction) = 8;
+ MY(alpha_min) = 110;
+ MY(alpha_max) = 228;
+ MY(alpha_fade) = 600;
+ MY(color_min) = "0xFD0000";
+ MY(color_max) = "0xF90000";
+ MY(count) = 50;
+ MY(gravity) = 1.300000;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 2;
+ MY(size_max) = 3;
+ MY(stretchfactor) = 0.100000;
+ MY(tex_min) = 41;
+ MY(tex_max) = 41;
+ MY(type) = "spark";
+ MY(velocityjitter) = '350.0 350.0 350.0';
+ MY(velocitymultiplier) = 2.500000;
+}
+
+DEF(crylink_joinexplode);
+// decal
+SUB(crylink_joinexplode) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(originjitter) = '12.0 12.0 12.0';
+ MY(size_min) = 24;
+ MY(size_max) = 24;
+ MY(tex_min) = 47;
+ MY(tex_max) = 47;
+ MY(type) = "decal";
+}
+// purple flare effect
+SUB(crylink_joinexplode) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x504060";
+ MY(color_max) = "0x504060";
+ MY(countabsolute) = 1;
+ MY(size_min) = 24;
+ MY(size_max) = 24;
+ MY(tex_min) = 39;
+ MY(tex_max) = 39;
+ MY(type) = "static";
+}
+// purple sparks
+SUB(crylink_joinexplode) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1024;
+ MY(bounce) = 2;
+ MY(color_min) = "0xA040C0";
+ MY(color_max) = "0xA040C0";
+ MY(count) = 40;
+ MY(size_min) = 6;
+ MY(size_max) = 6;
+ MY(tex_min) = 41;
+ MY(tex_max) = 41;
+ MY(type) = "spark";
+ MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// purple splash
+SUB(crylink_joinexplode) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0xE070FF";
+ MY(color_max) = "0xE070FF";
+ MY(count) = 1.500000;
+ MY(size_min) = 16;
+ MY(size_max) = 16;
+ MY(type) = "static";
+ MY(velocityjitter) = '32.0 32.0 32.0';
+}
+// purple splash
+SUB(crylink_joinexplode) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0xE070FF";
+ MY(color_max) = "0xE070FF";
+ MY(count) = 3;
+ MY(size_min) = 16;
+ MY(size_max) = 16;
+ MY(type) = "static";
+ MY(velocityjitter) = '256.0 256.0 256.0';
+}
+
+// sparks for keepaway ball touch
+DEF(kaball_sparks);
+SUB(kaball_sparks) {
+ MY(airfriction) = 3;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 556;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0xa9cacf";
+ MY(color_max) = "0x0054ff";
+ MY(count) = 35;
+ MY(gravity) = 1;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 1;
+ MY(size_max) = 3;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '300.0 300.0 300.0';
+ MY(velocitymultiplier) = 0.500000;
+}
+
+// weak rifle bullet trail (somewhat like a tracer)
+DEF(tr_rifle_weak);
+SUB(tr_rifle_weak) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 2560;
+ MY(color_min) = "0x800000";
+ MY(color_max) = "0xFF8020";
+ MY(size_min) = 1.500000;
+ MY(size_max) = 1.500000;
+ MY(stretchfactor) = 1;
+ MY(trailspacing) = 128;
+ MY(type) = "spark";
+ MY(velocitymultiplier) = 0.700000;
+}
+SUB(tr_rifle_weak) {
+ MY(airfriction) = -4;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0x202020";
+ MY(color_max) = "0x404040";
+ MY(notunderwater) = true;
+ MY(sizeincrease) = 0.400000;
+ MY(size_min) = 4;
+ MY(size_max) = 4;
+ MY(tex_max) = 8;
+ MY(trailspacing) = 48;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '4.0 4.0 4.0';
+}
+SUB(tr_rifle_weak) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 128;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x808080";
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 4;
+ MY(size_min) = 2;
+ MY(size_max) = 2;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(trailspacing) = 192;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '16.0 16.0 16.0';
+}
+
+// red smoke emiter
+DEF(red_smoke);
+SUB(red_smoke) {
+ MY(airfriction) = -1;
+ MY(alpha_min) = 32;
+ MY(alpha_max) = 64;
+ MY(alpha_fade) = 32;
+ MY(color_min) = "0xff8866";
+ MY(color_max) = "0x331100";
+ MY(count) = 2;
+ MY(gravity) = -0.007000;
+ MY(startangle_max) = 360;
+ MY(spin_min) = -30;
+ MY(spin_max) = 30;
+ MY(size_min) = 60;
+ MY(size_max) = 120;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocitymultiplier) = 5;
+}
+
+// pipe smoke emiter
+DEF(pipe_smoke);
+SUB(pipe_smoke) {
+ MY(airfriction) = -1;
+ MY(alpha_min) = 32;
+ MY(alpha_max) = 64;
+ MY(alpha_fade) = 48;
+ MY(color_min) = "0x999999";
+ MY(color_max) = "0x555555";
+ MY(count) = 2;
+ MY(gravity) = -0.015000;
+ MY(startangle_max) = 360;
+ MY(spin_min) = -180;
+ MY(spin_max) = 180;
+ MY(sizeincrease) = 35;
+ MY(size_min) = 5;
+ MY(size_max) = 10;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '0.0 0.0 5.0';
+ MY(velocitymultiplier) = 15;
+}
+
+// seeker missile trail
+DEF(TR_SEEKER);
+SUB(TR_SEEKER) {
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 300;
+ MY(alpha_fade) = 200;
+ MY(bounce) = 1;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x666666";
+ MY(lightcolor) = '6.0 3.0 1.0';
+ MY(lightradius) = 100;
+ MY(notunderwater) = true;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -30;
+ MY(spin_max) = 30;
+ MY(sizeincrease) = 11;
+ MY(size_min) = 2;
+ MY(size_max) = 2;
+ MY(tex_max) = 8;
+ MY(trailspacing) = 10;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '3.0 3.0 3.0';
+ MY(velocitymultiplier) = -0.020000;
+}
+// fire
+SUB(TR_SEEKER) {
+ MY(airfriction) = 8;
+ MY(alpha_min) = 100;
+ MY(alpha_max) = 144;
+ MY(alpha_fade) = 588;
+ MY(color_min) = "0xffdf72";
+ MY(color_max) = "0x811200";
+ MY(sizeincrease) = -30;
+ MY(size_min) = 5;
+ MY(size_max) = 5;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(trailspacing) = 4;
+ MY(type) = "static";
+ MY(velocityjitter) = '32.0 32.0 32.0';
+ MY(velocitymultiplier) = -1.500000;
+}
+// bubbles
+SUB(TR_SEEKER) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(bounce) = 1.500000;
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 4;
+ MY(size_min) = 1;
+ MY(size_max) = 2;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(trailspacing) = 16;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '16.0 16.0 16.0';
+ MY(velocitymultiplier) = -0.310000;
+}
+// sparks
+SUB(TR_SEEKER) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 444;
+ MY(alpha_max) = 512;
+ MY(alpha_fade) = 1866;
+ MY(bounce) = 1;
+ MY(color_min) = "0xFFFDD9";
+ MY(color_max) = "0xFFFDD9";
+ MY(notunderwater) = true;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 0.500000;
+ MY(size_max) = 0.500000;
+ MY(stretchfactor) = 0.300000;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(trailspacing) = 20;
+ MY(type) = "spark";
+ MY(velocityjitter) = '100.0 100.0 100.0';
+ MY(velocitymultiplier) = -0.310000;
+}
+
+#include "effectinfo_vehicles.inc"
+
+// generic explosion size:big (biggest explosion ever)
+DEF(explosion_big);
+// decal
+SUB(explosion_big) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '8.0 4.0 0.0';
+ MY(lightradiusfade) = 1750;
+ MY(lightradius) = 600;
+ MY(originjitter) = '23.0 23.0 23.0';
+ MY(size_min) = 172;
+ MY(size_max) = 172;
+ MY(tex_min) = 8;
+ MY(tex_max) = 16;
+ MY(type) = "decal";
+}
+// shockwave
+SUB(explosion_big) {
+ MY(alpha_min) = 56;
+ MY(alpha_max) = 56;
+ MY(alpha_fade) = 330;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 4400;
+ MY(size_min) = 72;
+ MY(size_max) = 72;
+ MY(tex_min) = 33;
+ MY(tex_max) = 33;
+ MY(type) = "static";
+}
+// fire effect
+SUB(explosion_big) {
+ MY(airfriction) = 8;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 712;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 64;
+ MY(liquidfriction) = 8;
+ MY(notunderwater) = true;
+ MY(originjitter) = '80.0 80.0 80.0';
+ MY(sizeincrease) = 45;
+ MY(size_min) = 133;
+ MY(size_max) = 144;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "static";
+ MY(velocityjitter) = '2512.0 2512.0 2512.0';
+}
+// fire rays
+SUB(explosion_big) {
+ MY(airfriction) = -5;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 800;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 64;
+ MY(liquidfriction) = 8;
+ MY(notunderwater) = true;
+ MY(originjitter) = '40.0 40.0 40.0';
+ MY(sizeincrease) = 45;
+ MY(size_min) = 133;
+ MY(size_max) = 144;
+ MY(stretchfactor) = 10;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "spark";
+ MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// smoke
+SUB(explosion_big) {
+ MY(airfriction) = 8;
+ MY(alpha_min) = 300;
+ MY(alpha_max) = 650;
+ MY(alpha_fade) = 456;
+ MY(color_min) = "0x4F4B46";
+ MY(color_max) = "0x000000";
+ MY(count) = 32;
+ MY(notunderwater) = true;
+ MY(sizeincrease) = 244;
+ MY(size_min) = 50;
+ MY(size_max) = 100;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '3444.0 3444.0 3444.0';
+}
+// bouncing sparks
+SUB(explosion_big) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 644;
+ MY(alpha_max) = 956;
+ MY(alpha_fade) = 1284;
+ MY(color_min) = "0xffa35b";
+ MY(color_max) = "0xfff2be";
+ MY(count) = 34;
+ MY(gravity) = 1;
+ MY(liquidfriction) = 0.800000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '160.0 160.0 160.0';
+ MY(size_min) = 3;
+ MY(size_max) = 4;
+ MY(stretchfactor) = 0.700000;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '924.0 924.0 924.0';
+ MY(velocityoffset) = '0.0 0.0 370.0';
+}
+// debris
+SUB(explosion_big) {
+ MY(airfriction) = 0.500000;
+ MY(alpha_min) = 444;
+ MY(alpha_max) = 1356;
+ MY(alpha_fade) = 1184;
+ MY(color_min) = "0xFFFFFF";
+ MY(color_max) = "0xcac5b4";
+ MY(count) = 16;
+ MY(gravity) = 2.300000;
+ MY(notunderwater) = true;
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -1000;
+ MY(spin_max) = 1000;
+ MY(sizeincrease) = -5;
+ MY(size_min) = 10;
+ MY(size_max) = 16;
+ MY(tex_min) = 66;
+ MY(tex_max) = 68;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '1800.0 1800.0 1800.0';
+ MY(velocityoffset) = '0.0 0.0 970.0';
+}
+// underwater bubbles
+SUB(explosion_big) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x808080";
+ MY(count) = 32;
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 0.250000;
+ MY(originjitter) = '160.0 160.0 160.0';
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '444.0 444.0 444.0';
+}
+// underwatershockwave
+SUB(explosion_big) {
+ MY(alpha_min) = 40;
+ MY(alpha_max) = 40;
+ MY(alpha_fade) = 300;
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 2900;
+ MY(size_min) = 30;
+ MY(size_max) = 30;
+ MY(tex_min) = 33;
+ MY(tex_max) = 33;
+ MY(type) = "smoke";
+ MY(underwater) = true;
+ MY(velocitymultiplier) = 0.300000;
+}
+
+// generic explosion size:medium (it leaves rising smoke for a longer time)
+DEF(explosion_medium);
+// shockwave
+SUB(explosion_medium) {
+ MY(alpha_min) = 56;
+ MY(alpha_max) = 56;
+ MY(alpha_fade) = 330;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 2400;
+ MY(size_min) = 72;
+ MY(size_max) = 72;
+ MY(tex_min) = 33;
+ MY(tex_max) = 33;
+ MY(type) = "static";
+}
+// fire effect
+SUB(explosion_medium) {
+ MY(airfriction) = 8;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 712;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 32;
+ MY(liquidfriction) = 8;
+ MY(notunderwater) = true;
+ MY(originjitter) = '30.0 30.0 30.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -500;
+ MY(spin_max) = 500;
+ MY(sizeincrease) = 45;
+ MY(size_min) = 133;
+ MY(size_max) = 144;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "static";
+ MY(velocityjitter) = '1512.0 1512.0 1512.0';
+}
+// fire effect 2
+SUB(explosion_medium) {
+ MY(airfriction) = 8;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 612;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 32;
+ MY(gravity) = -2;
+ MY(liquidfriction) = 8;
+ MY(notunderwater) = true;
+ MY(originjitter) = '30.0 30.0 30.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -150;
+ MY(spin_max) = 150;
+ MY(sizeincrease) = 40;
+ MY(size_min) = 73;
+ MY(size_max) = 94;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "static";
+ MY(velocityjitter) = '1512.0 1512.0 1512.0';
+}
+// fire rays
+SUB(explosion_medium) {
+ MY(airfriction) = -3;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 800;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 14;
+ MY(liquidfriction) = 8;
+ MY(notunderwater) = true;
+ MY(originjitter) = '40.0 40.0 40.0';
+ MY(sizeincrease) = 40;
+ MY(size_min) = 43;
+ MY(size_max) = 74;
+ MY(stretchfactor) = 8;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "spark";
+ MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// smoke
+SUB(explosion_medium) {
+ MY(airfriction) = 3;
+ MY(alpha_min) = 300;
+ MY(alpha_max) = 650;
+ MY(alpha_fade) = 756;
+ MY(color_min) = "0x4F4B46";
+ MY(color_max) = "0x000000";
+ MY(count) = 5;
+ MY(notunderwater) = true;
+ MY(originjitter) = '100.0 100.0 100.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -20;
+ MY(spin_max) = 20;
+ MY(sizeincrease) = -30;
+ MY(size_min) = 250;
+ MY(size_max) = 300;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '200.0 200.0 200.0';
+}
+// smoke 2
+SUB(explosion_medium) {
+ MY(airfriction) = 3;
+ MY(alpha_min) = 300;
+ MY(alpha_max) = 650;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0x4F4B46";
+ MY(color_max) = "0x000000";
+ MY(count) = 10;
+ MY(gravity) = -0.300000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '100.0 100.0 100.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -20;
+ MY(spin_max) = 20;
+ MY(sizeincrease) = 50;
+ MY(size_min) = 50;
+ MY(size_max) = 100;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '500.0 500.0 500.0';
+ MY(velocityoffset) = '0.0 0.0 200.0';
+}
+// smoke rays
+SUB(explosion_medium) {
+ MY(alpha_min) = 140;
+ MY(alpha_max) = 255;
+ MY(alpha_fade) = 350;
+ MY(color_min) = "0x4F4B46";
+ MY(color_max) = "0x000000";
+ MY(count) = 13;
+ MY(notunderwater) = true;
+ MY(originjitter) = '40.0 40.0 40.0';
+ MY(sizeincrease) = 100;
+ MY(size_min) = 150;
+ MY(size_max) = 200;
+ MY(stretchfactor) = 50;
+ MY(tex_max) = 8;
+ MY(type) = "spark";
+ MY(velocityjitter) = '250.0 250.0 250.0';
+}
+// bouncing sparks
+SUB(explosion_medium) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 644;
+ MY(alpha_max) = 956;
+ MY(alpha_fade) = 984;
+ MY(color_min) = "0xffa35b";
+ MY(color_max) = "0xfff2be";
+ MY(count) = 14;
+ MY(gravity) = 1;
+ MY(liquidfriction) = 0.800000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '100.0 100.0 100.0';
+ MY(size_min) = 2;
+ MY(size_max) = 3;
+ MY(stretchfactor) = 0.700000;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '624.0 624.0 624.0';
+ MY(velocityoffset) = '0.0 0.0 370.0';
+}
+// underwater bubbles
+SUB(explosion_medium) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x808080";
+ MY(count) = 32;
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 0.250000;
+ MY(originjitter) = '160.0 160.0 160.0';
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '444.0 444.0 444.0';
+}
+// underwatershockwave
+SUB(explosion_medium) {
+ MY(alpha_min) = 40;
+ MY(alpha_max) = 40;
+ MY(alpha_fade) = 300;
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 2900;
+ MY(size_min) = 30;
+ MY(size_max) = 30;
+ MY(tex_min) = 33;
+ MY(tex_max) = 33;
+ MY(type) = "smoke";
+ MY(underwater) = true;
+ MY(velocitymultiplier) = 0.300000;
+}
+
+// generic explosion size:small (its fire only, made to support other explosions)
+DEF(explosion_small);
+// shockwave
+SUB(explosion_small) {
+ MY(alpha_min) = 56;
+ MY(alpha_max) = 56;
+ MY(alpha_fade) = 330;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 2400;
+ MY(size_min) = 22;
+ MY(size_max) = 22;
+ MY(tex_min) = 33;
+ MY(tex_max) = 33;
+ MY(type) = "static";
+}
+// fire effect
+SUB(explosion_small) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1212;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 16;
+ MY(liquidfriction) = 8;
+ MY(notunderwater) = true;
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -500;
+ MY(spin_max) = 500;
+ MY(sizeincrease) = 45;
+ MY(size_min) = 1;
+ MY(size_max) = 44;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "static";
+ MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// fire effect 2
+SUB(explosion_small) {
+ MY(airfriction) = 8;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 812;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 16;
+ MY(liquidfriction) = 8;
+ MY(notunderwater) = true;
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -150;
+ MY(spin_max) = 150;
+ MY(sizeincrease) = 40;
+ MY(size_min) = 73;
+ MY(size_max) = 94;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "static";
+ MY(velocityjitter) = '912.0 912.0 912.0';
+}
+// fire rays
+SUB(explosion_small) {
+ MY(airfriction) = -3;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1300;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 14;
+ MY(liquidfriction) = 8;
+ MY(notunderwater) = true;
+ MY(originjitter) = '40.0 40.0 40.0';
+ MY(sizeincrease) = 30;
+ MY(size_min) = 13;
+ MY(size_max) = 54;
+ MY(stretchfactor) = 8;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "spark";
+ MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// underwater bubbles
+SUB(explosion_small) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x808080";
+ MY(count) = 32;
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 0.250000;
+ MY(originjitter) = '160.0 160.0 160.0';
+ MY(size_min) = 1;
+ MY(size_max) = 3;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '144.0 144.0 144.0';
+}
+// underwatershockwave
+SUB(explosion_small) {
+ MY(alpha_min) = 40;
+ MY(alpha_max) = 40;
+ MY(alpha_fade) = 300;
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 1200;
+ MY(size_min) = 30;
+ MY(size_max) = 30;
+ MY(tex_min) = 33;
+ MY(tex_max) = 33;
+ MY(type) = "smoke";
+ MY(underwater) = true;
+}
+
+// big smoke ( for spamming on damaged stuff )
+DEF(smoke_big);
+SUB(smoke_big) {
+ MY(airfriction) = 4;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 750;
+ MY(alpha_fade) = 200;
+ MY(color_min) = "0x4F4B46";
+ MY(color_max) = "0x000000";
+ MY(count) = 3;
+ MY(gravity) = -0.500000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '55.0 55.0 55.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -20;
+ MY(spin_max) = 20;
+ MY(sizeincrease) = 15;
+ MY(size_min) = 30;
+ MY(size_max) = 60;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '140.0 140.0 200.0';
+ MY(velocityoffset) = '0.0 0.0 200.0';
+}
+
+// small smoke ( more precise than big one, for spamming on damaged parts like raptors spinner )
+DEF(smoke_small);
+SUB(smoke_small) {
+ MY(airfriction) = 4;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 750;
+ MY(alpha_fade) = 200;
+ MY(color_min) = "0x4F4B46";
+ MY(color_max) = "0x000000";
+ MY(count) = 3;
+ MY(gravity) = -0.500000;
+ MY(notunderwater) = true;
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -20;
+ MY(spin_max) = 20;
+ MY(sizeincrease) = -10;
+ MY(size_min) = 60;
+ MY(size_max) = 100;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '40.0 40.0 400.0';
+ MY(velocityoffset) = '0.0 0.0 200.0';
+}
+
+// metal impact effect
+DEF(impact_metal);
+SUB(impact_metal) {
+ MY(alpha_min) = 25;
+ MY(alpha_max) = 64;
+ MY(alpha_fade) = 50;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x886666";
+ MY(count) = 1;
+ MY(gravity) = -0.010000;
+ MY(originjitter) = '20.0 20.0 5.0';
+ MY(sizeincrease) = 10;
+ MY(size_min) = 3;
+ MY(size_max) = 6;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+}
+// sparks
+SUB(impact_metal) {
+ MY(airfriction) = 2;
+ MY(alpha_min) = 255;
+ MY(alpha_max) = 255;
+ MY(alpha_fade) = 112;
+ MY(bounce) = 1.800000;
+ MY(color_min) = "0xFFCC22";
+ MY(color_max) = "0xFF4422";
+ MY(count) = 2;
+ MY(gravity) = 1;
+ MY(size_min) = 2;
+ MY(size_max) = 2;
+ MY(stretchfactor) = 0.500000;
+ MY(tex_min) = 41;
+ MY(tex_max) = 41;
+ MY(type) = "spark";
+ MY(velocityjitter) = '200.0 200.0 300.0';
+ MY(velocitymultiplier) = 2;
+}
+
+// stone impact effect
+DEF(impact_stone);
+SUB(impact_stone) {
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 75;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0xcc9966";
+ MY(count) = 1;
+ MY(gravity) = -0.010000;
+ MY(originjitter) = '20.0 20.0 5.0';
+ MY(sizeincrease) = 15;
+ MY(size_min) = 3;
+ MY(size_max) = 6;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+}
+// debris
+SUB(impact_stone) {
+ MY(airfriction) = 0.500000;
+ MY(alpha_min) = 450;
+ MY(alpha_max) = 750;
+ MY(alpha_fade) = 300;
+ MY(bounce) = 1.200000;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x886644";
+ MY(count) = 1;
+ MY(gravity) = 1.300000;
+ MY(notunderwater) = true;
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -1000;
+ MY(spin_max) = 1000;
+ MY(size_min) = 1;
+ MY(size_max) = 2;
+ MY(tex_min) = 66;
+ MY(tex_max) = 68;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '124.0 124.0 324.0';
+}
+
+// wood impact effect
+DEF(impact_wood);
+SUB(impact_wood) {
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 75;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0xcc9966";
+ MY(count) = 1;
+ MY(gravity) = -0.010000;
+ MY(originjitter) = '20.0 20.0 5.0';
+ MY(sizeincrease) = 10;
+ MY(size_min) = 3;
+ MY(size_max) = 6;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+}
+// sparks
+SUB(impact_wood) {
+ MY(airfriction) = 2;
+ MY(alpha_min) = 255;
+ MY(alpha_max) = 255;
+ MY(alpha_fade) = 75;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x221100";
+ MY(color_max) = "0x221100";
+ MY(count) = 2;
+ MY(gravity) = 1;
+ MY(size_min) = 1;
+ MY(size_max) = 8;
+ MY(tex_min) = 41;
+ MY(tex_max) = 41;
+ MY(type) = "spark";
+ MY(velocityjitter) = '180.0 180.0 260.0';
+ MY(velocitymultiplier) = 2;
+}
+
+// flesh impact effect
+DEF(impact_flesh);
+SUB(impact_flesh) {
+ MY(alpha_min) = 100;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 400;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x420000";
+ MY(count) = 0.500000;
+ MY(originjitter) = '11.0 11.0 11.0';
+ MY(size_min) = 8;
+ MY(size_max) = 12;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+}
+// blood splash
+SUB(impact_flesh) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = -1;
+ MY(color_min) = "0xA8FFFF";
+ MY(color_max) = "0xA8FFFFF";
+ MY(count) = 0.300000;
+ MY(liquidfriction) = 4;
+ MY(size_min) = 2;
+ MY(size_max) = 6;
+ MY(staincolor_min) = "0x808080";
+ MY(staincolor_max) = "0x808080";
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(type) = "blood";
+ MY(velocityjitter) = '96.0 96.0 96.0';
+ MY(velocitymultiplier) = 5;
+}
+
+// hagar trail
+DEF(tr_hagar);
+// smoke
+SUB(tr_hagar) {
+ MY(alpha_min) = 300;
+ MY(alpha_max) = 400;
+ MY(alpha_fade) = 780;
+ MY(bounce) = 1;
+ MY(color_min) = "0x101010";
+ MY(color_max) = "0x000000";
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(sizeincrease) = 10;
+ MY(size_min) = 3;
+ MY(size_max) = 2;
+ MY(tex_max) = 8;
+ MY(trailspacing) = 4;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '1.0 1.0 1.0';
+ MY(velocitymultiplier) = -0.020000;
+}
+// fire
+SUB(tr_hagar) {
+ MY(airfriction) = 8;
+ MY(alpha_min) = 100;
+ MY(alpha_max) = 144;
+ MY(alpha_fade) = 988;
+ MY(color_min) = "0xffdf72";
+ MY(color_max) = "0x811200";
+ MY(notunderwater) = true;
+ MY(sizeincrease) = -15;
+ MY(size_min) = 5;
+ MY(size_max) = 2;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(trailspacing) = 4;
+ MY(type) = "static";
+ MY(velocityjitter) = '32.0 32.0 32.0';
+ MY(velocitymultiplier) = -1;
+}
+// bubbles
+SUB(tr_hagar) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x808080";
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 4;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(trailspacing) = 16;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '16.0 16.0 16.0';
+}
+
+// laser damage effect
+DEF(damage_laser);
+SUB(damage_laser) {
+ MY(airfriction) = -0.350000;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 16;
+ MY(alpha_fade) = 128;
+ MY(color_min) = "0x880000";
+ MY(color_max) = "0xff4400";
+ MY(count) = 3;
+ MY(notunderwater) = true;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(startangle_max) = 180;
+ MY(spin_min) = -30;
+ MY(spin_max) = 30;
+ MY(sizeincrease) = 8;
+ MY(size_min) = 2;
+ MY(size_max) = 4;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '0.4 0.4 0.6';
+}
+
+// shotgun damage effect, normal blood
+DEF(damage_shotgun);
+SUB(damage_shotgun) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = -1;
+ MY(color_min) = "0xA8FFFF";
+ MY(color_max) = "0xA8FFFFF";
+ MY(count) = 0.600000;
+ MY(liquidfriction) = 4;
+ MY(size_min) = 2;
+ MY(size_max) = 4;
+ MY(staincolor_min) = "0x808080";
+ MY(staincolor_max) = "0x808080";
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(type) = "blood";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+ MY(velocitymultiplier) = 5;
+}
+// blood mist
+SUB(damage_shotgun) {
+ MY(alpha_min) = 100;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 400;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x420000";
+ MY(count) = 1;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 8;
+ MY(size_max) = 16;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+}
+
+// shotgun damage effect, alien blood
+DEF(damage_shotgun_alien);
+SUB(damage_shotgun_alien) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = -1;
+ MY(color_min) = "0xDC9BCD";
+ MY(color_max) = "0xDC9BCD";
+ MY(count) = 0.600000;
+ MY(liquidfriction) = 4;
+ MY(size_min) = 2;
+ MY(size_max) = 4;
+ MY(staincolor_min) = "0x808080";
+ MY(staincolor_max) = "0x808080";
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(type) = "blood";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+ MY(velocitymultiplier) = 5;
+}
+// blood mist
+SUB(damage_shotgun_alien) {
+ MY(alpha_min) = 100;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 400;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x204010";
+ MY(count) = 1;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 8;
+ MY(size_max) = 16;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+}
+
+// shotgun damage effect, robot blood
+DEF(damage_shotgun_robot);
+SUB(damage_shotgun_robot) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = -1;
+ MY(color_min) = "0xC0D890";
+ MY(color_max) = "0xC0D890";
+ MY(count) = 0.600000;
+ MY(liquidfriction) = 4;
+ MY(size_min) = 2;
+ MY(size_max) = 4;
+ MY(staincolor_min) = "0x808080";
+ MY(staincolor_max) = "0x808080";
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(type) = "blood";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+ MY(velocitymultiplier) = 5;
+}
+// blood mist
+SUB(damage_shotgun_robot) {
+ MY(alpha_min) = 100;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 400;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x301860";
+ MY(count) = 1;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 8;
+ MY(size_max) = 16;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+}
+
+// machinegun damage effect, normal blood
+DEF(damage_uzi);
+SUB(damage_uzi) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = -1;
+ MY(color_min) = "0xA8FFFF";
+ MY(color_max) = "0xA8FFFFF";
+ MY(count) = 0.300000;
+ MY(liquidfriction) = 4;
+ MY(size_min) = 2;
+ MY(size_max) = 4;
+ MY(staincolor_min) = "0x808080";
+ MY(staincolor_max) = "0x808080";
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(type) = "blood";
+ MY(velocityjitter) = '32.0 32.0 32.0';
+ MY(velocitymultiplier) = 5;
+}
+// blood mist
+SUB(damage_uzi) {
+ MY(alpha_min) = 100;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 400;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x420000";
+ MY(count) = 1;
+ MY(size_min) = 6;
+ MY(size_max) = 12;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+}
+
+// machinegun damage effect, alien blood
+DEF(damage_uzi_alien);
+SUB(damage_uzi_alien) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = -1;
+ MY(color_min) = "0xDC9BCD";
+ MY(color_max) = "0xDC9BCD";
+ MY(count) = 0.300000;
+ MY(liquidfriction) = 4;
+ MY(size_min) = 2;
+ MY(size_max) = 4;
+ MY(staincolor_min) = "0x808080";
+ MY(staincolor_max) = "0x808080";
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(type) = "blood";
+ MY(velocityjitter) = '32.0 32.0 32.0';
+ MY(velocitymultiplier) = 5;
+}
+// blood mist
+SUB(damage_uzi_alien) {
+ MY(alpha_min) = 100;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 400;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x204010";
+ MY(count) = 1;
+ MY(size_min) = 6;
+ MY(size_max) = 12;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+}
+
+// machinegun damage effect, robot blood
+DEF(damage_uzi_robot);
+SUB(damage_uzi_robot) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = -1;
+ MY(color_min) = "0xC0D890";
+ MY(color_max) = "0xC0D890";
+ MY(count) = 0.300000;
+ MY(liquidfriction) = 4;
+ MY(size_min) = 2;
+ MY(size_max) = 4;
+ MY(staincolor_min) = "0x808080";
+ MY(staincolor_max) = "0x808080";
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(type) = "blood";
+ MY(velocityjitter) = '32.0 32.0 32.0';
+ MY(velocitymultiplier) = 5;
+}
+// blood mist
+SUB(damage_uzi_robot) {
+ MY(alpha_min) = 100;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 400;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x301860";
+ MY(count) = 1;
+ MY(size_min) = 6;
+ MY(size_max) = 12;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+}
+
+// minelayer damage effect
+DEF(damage_minelayer);
+SUB(damage_minelayer) {
+ MY(alpha_min) = 512;
+ MY(alpha_max) = 64;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 3;
+ MY(gravity) = -0.500000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(sizeincrease) = -15;
+ MY(size_min) = 4;
+ MY(size_max) = 8;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '22.0 22.0 50.0';
+}
+// smoke
+SUB(damage_minelayer) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 32;
+ MY(alpha_fade) = 128;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x111111";
+ MY(count) = 2;
+ MY(gravity) = -0.300000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '4.0 4.0 4.0';
+ MY(sizeincrease) = 5;
+ MY(size_min) = 4;
+ MY(size_max) = 8;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '11.0 11.0 50.0';
+}
+
+// mortar damage effect
+DEF(damage_grenadelauncher);
+SUB(damage_grenadelauncher) {
+ MY(alpha_min) = 512;
+ MY(alpha_max) = 64;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 3;
+ MY(gravity) = -0.500000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(sizeincrease) = -15;
+ MY(size_min) = 4;
+ MY(size_max) = 8;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '22.0 22.0 50.0';
+}
+// smoke
+SUB(damage_grenadelauncher) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 32;
+ MY(alpha_fade) = 128;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x111111";
+ MY(count) = 2;
+ MY(gravity) = -0.300000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '4.0 4.0 4.0';
+ MY(sizeincrease) = 5;
+ MY(size_min) = 4;
+ MY(size_max) = 8;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '11.0 11.0 50.0';
+}
+
+// electro damage effect
+DEF(damage_electro);
+SUB(damage_electro) {
+ MY(airfriction) = -0.500000;
+ MY(alpha_min) = 48;
+ MY(alpha_max) = 8;
+ MY(alpha_fade) = 48;
+ MY(color_min) = "0x66ffff";
+ MY(color_max) = "0x2288ff";
+ MY(count) = 2;
+ MY(gravity) = -0.000100;
+ MY(liquidfriction) = 0.800000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '3.0 3.0 3.0';
+ MY(startangle_min) = 180;
+ MY(startangle_max) = 360;
+ MY(spin_min) = -30;
+ MY(spin_max) = 30;
+ MY(sizeincrease) = -14;
+ MY(size_min) = 6;
+ MY(size_max) = 10;
+ MY(tex_min) = 47;
+ MY(tex_max) = 47;
+ MY(type) = "static";
+ MY(velocityjitter) = '8.0 8.0 16.0';
+}
+// plasma smoke
+SUB(damage_electro) {
+ MY(airfriction) = -0.350000;
+ MY(alpha_min) = 64;
+ MY(alpha_max) = 16;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0x2244ff";
+ MY(color_max) = "0x002266";
+ MY(count) = 4;
+ MY(notunderwater) = true;
+ MY(originjitter) = '4.0 4.0 4.0';
+ MY(startangle_max) = 180;
+ MY(spin_min) = -30;
+ MY(spin_max) = 30;
+ MY(sizeincrease) = 10;
+ MY(size_min) = 4;
+ MY(size_max) = 8;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '0.4 0.4 0.6';
+}
+// bouncing sparks
+SUB(damage_electro) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 768;
+ MY(alpha_max) = 64;
+ MY(alpha_fade) = 256;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x003090";
+ MY(color_max) = "0x00CCFF";
+ MY(count) = 0.500000;
+ MY(gravity) = 0.200000;
+ MY(liquidfriction) = 0.800000;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_min) = 66;
+ MY(tex_max) = 68;
+ MY(type) = "spark";
+ MY(velocityjitter) = '32.0 32.0 32.0';
+}
+
+// crylink damage effect
+DEF(damage_crylink);
+SUB(damage_crylink) {
+ MY(airfriction) = -0.500000;
+ MY(alpha_min) = 48;
+ MY(alpha_max) = 16;
+ MY(alpha_fade) = 48;
+ MY(color_min) = "0xff44ff";
+ MY(color_max) = "0x9966ff";
+ MY(count) = 2;
+ MY(gravity) = -0.000100;
+ MY(liquidfriction) = 0.800000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '3.0 3.0 3.0';
+ MY(startangle_min) = 180;
+ MY(startangle_max) = 360;
+ MY(spin_min) = -30;
+ MY(spin_max) = 30;
+ MY(sizeincrease) = -8;
+ MY(size_min) = 0.500000;
+ MY(size_max) = 1;
+ MY(tex_min) = 38;
+ MY(tex_max) = 38;
+ MY(type) = "static";
+ MY(velocityjitter) = '10.0 10.0 20.0';
+}
+// plasma smoke
+SUB(damage_crylink) {
+ MY(airfriction) = -0.350000;
+ MY(alpha_min) = 64;
+ MY(alpha_max) = 16;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0x8844ff";
+ MY(color_max) = "0x662244";
+ MY(count) = 4;
+ MY(gravity) = 0.001000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '4.0 4.0 4.0';
+ MY(startangle_max) = 180;
+ MY(spin_min) = -30;
+ MY(spin_max) = 30;
+ MY(sizeincrease) = 6;
+ MY(size_min) = 5;
+ MY(size_max) = 10;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '0.4 0.4 0.6';
+}
+// floating sparks
+SUB(damage_crylink) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_min) = 192;
+ MY(alpha_max) = 192;
+ MY(alpha_fade) = 128;
+ MY(color_min) = "0x903090";
+ MY(color_max) = "0xFFD0FF";
+ MY(count) = 0.300000;
+ MY(liquidfriction) = 0.800000;
+ MY(sizeincrease) = -5;
+ MY(size_min) = 0.500000;
+ MY(size_max) = 0.500000;
+ MY(type) = "spark";
+ MY(velocityjitter) = '12.0 12.0 12.0';
+}
+
+// hlac damage effect
+DEF(damage_hlac);
+SUB(damage_hlac) {
+ MY(airfriction) = -0.350000;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 16;
+ MY(alpha_fade) = 128;
+ MY(color_min) = "0x880000";
+ MY(color_max) = "0xff4400";
+ MY(count) = 3;
+ MY(notunderwater) = true;
+ MY(originjitter) = '4.0 4.0 4.0';
+ MY(startangle_max) = 180;
+ MY(spin_min) = -30;
+ MY(spin_max) = 30;
+ MY(sizeincrease) = 10;
+ MY(size_min) = 2;
+ MY(size_max) = 4;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '0.4 0.4 0.6';
+}
+
+// vortex damage effect
+DEF(damage_nex);
+SUB(damage_nex) {
+ MY(airfriction) = -0.500000;
+ MY(alpha_min) = 64;
+ MY(alpha_max) = 8;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0xffffff";
+ MY(color_max) = "0x88ffff";
+ MY(count) = 1;
+ MY(gravity) = -0.000100;
+ MY(liquidfriction) = 0.600000;
+ MY(originjitter) = '4.0 4.0 4.0';
+ MY(startangle_min) = 180;
+ MY(startangle_max) = 360;
+ MY(spin_min) = -30;
+ MY(spin_max) = 30;
+ MY(sizeincrease) = -14;
+ MY(size_min) = 5;
+ MY(size_max) = 10;
+ MY(tex_min) = 47;
+ MY(tex_max) = 47;
+ MY(type) = "static";
+ MY(velocityjitter) = '8.0 8.0 16.0';
+}
+// plasma smoke
+SUB(damage_nex) {
+ MY(airfriction) = -0.350000;
+ MY(alpha_min) = 64;
+ MY(alpha_max) = 16;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0x6688ff";
+ MY(color_max) = "0x226688";
+ MY(count) = 2;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(startangle_max) = 180;
+ MY(spin_min) = -30;
+ MY(spin_max) = 30;
+ MY(sizeincrease) = 8;
+ MY(size_min) = 4;
+ MY(size_max) = 8;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '0.5 0.5 0.8';
+}
+// bouncing sparks
+SUB(damage_nex) {
+ MY(airfriction) = 2;
+ MY(alpha_min) = 255;
+ MY(alpha_max) = 255;
+ MY(alpha_fade) = 112;
+ MY(bounce) = 1.600000;
+ MY(color_min) = "0xD9FDFF";
+ MY(color_max) = "0xD9FDFF";
+ MY(count) = 0.200000;
+ MY(gravity) = 1;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(stretchfactor) = 0.700000;
+ MY(tex_min) = 41;
+ MY(tex_max) = 41;
+ MY(type) = "spark";
+ MY(velocityjitter) = '100.0 100.0 300.0';
+ MY(velocitymultiplier) = 3;
+}
+
+// vaporizer damage effect
+DEF(damage_minstanex);
+SUB(damage_minstanex) {
+ MY(airfriction) = -0.500000;
+ MY(alpha_min) = 64;
+ MY(alpha_max) = 8;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0xffffff";
+ MY(color_max) = "0x88ffff";
+ MY(count) = 2;
+ MY(gravity) = -0.000100;
+ MY(liquidfriction) = 0.600000;
+ MY(originjitter) = '4.0 4.0 4.0';
+ MY(startangle_min) = 180;
+ MY(startangle_max) = 360;
+ MY(spin_min) = -30;
+ MY(spin_max) = 30;
+ MY(sizeincrease) = -14;
+ MY(size_min) = 5;
+ MY(size_max) = 10;
+ MY(tex_min) = 47;
+ MY(tex_max) = 47;
+ MY(type) = "static";
+ MY(velocityjitter) = '8.0 8.0 16.0';
+}
+// plasma smoke
+SUB(damage_minstanex) {
+ MY(airfriction) = -0.350000;
+ MY(alpha_min) = 64;
+ MY(alpha_max) = 16;
+ MY(alpha_fade) = 64;
+ MY(color_min) = "0x6688ff";
+ MY(color_max) = "0x226688";
+ MY(count) = 4;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(startangle_max) = 180;
+ MY(spin_min) = -30;
+ MY(spin_max) = 30;
+ MY(sizeincrease) = 8;
+ MY(size_min) = 4;
+ MY(size_max) = 8;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '0.5 0.5 0.8';
+}
+// bouncing sparks
+SUB(damage_minstanex) {
+ MY(airfriction) = 2;
+ MY(alpha_min) = 255;
+ MY(alpha_max) = 255;
+ MY(alpha_fade) = 112;
+ MY(bounce) = 1.600000;
+ MY(color_min) = "0xD9FDFF";
+ MY(color_max) = "0xD9FDFF";
+ MY(count) = 0.200000;
+ MY(gravity) = 1;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(stretchfactor) = 0.700000;
+ MY(tex_min) = 41;
+ MY(tex_max) = 41;
+ MY(type) = "spark";
+ MY(velocityjitter) = '100.0 100.0 300.0';
+ MY(velocitymultiplier) = 3;
+}
+
+// rifle damage effect, normal blood
+DEF(damage_rifle);
+SUB(damage_rifle) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = -1;
+ MY(color_min) = "0xA8FFFF";
+ MY(color_max) = "0xA8FFFFF";
+ MY(count) = 0.300000;
+ MY(liquidfriction) = 4;
+ MY(size_min) = 2;
+ MY(size_max) = 4;
+ MY(staincolor_min) = "0x808080";
+ MY(staincolor_max) = "0x808080";
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(type) = "blood";
+ MY(velocityjitter) = '32.0 32.0 32.0';
+ MY(velocitymultiplier) = 5;
+}
+// blood mist
+SUB(damage_rifle) {
+ MY(alpha_min) = 100;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 400;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x420000";
+ MY(count) = 1;
+ MY(size_min) = 6;
+ MY(size_max) = 12;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+}
+
+// rifle damage effect, alien blood
+DEF(damage_rifle_alien);
+SUB(damage_rifle_alien) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = -1;
+ MY(color_min) = "0xDC9BCD";
+ MY(color_max) = "0xDC9BCD";
+ MY(count) = 0.300000;
+ MY(liquidfriction) = 4;
+ MY(size_min) = 2;
+ MY(size_max) = 4;
+ MY(staincolor_min) = "0x808080";
+ MY(staincolor_max) = "0x808080";
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(type) = "blood";
+ MY(velocityjitter) = '32.0 32.0 32.0';
+ MY(velocitymultiplier) = 5;
+}
+// blood mist
+SUB(damage_rifle_alien) {
+ MY(alpha_min) = 100;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 400;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x204010";
+ MY(count) = 1;
+ MY(size_min) = 6;
+ MY(size_max) = 12;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+}
+
+// rifle damage effect, robot blood
+DEF(damage_rifle_robot);
+SUB(damage_rifle_robot) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = -1;
+ MY(color_min) = "0xC0D890";
+ MY(color_max) = "0xC0D890";
+ MY(count) = 0.300000;
+ MY(liquidfriction) = 4;
+ MY(size_min) = 2;
+ MY(size_max) = 4;
+ MY(staincolor_min) = "0x808080";
+ MY(staincolor_max) = "0x808080";
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(type) = "blood";
+ MY(velocityjitter) = '32.0 32.0 32.0';
+ MY(velocitymultiplier) = 5;
+}
+// blood mist
+SUB(damage_rifle_robot) {
+ MY(alpha_min) = 100;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 400;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x301860";
+ MY(count) = 1;
+ MY(size_min) = 6;
+ MY(size_max) = 12;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+}
+
+// seeker damage effect
+DEF(damage_seeker);
+SUB(damage_seeker) {
+ MY(alpha_min) = 512;
+ MY(alpha_max) = 32;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0x8f0c00";
+ MY(color_max) = "0xff2200";
+ MY(count) = 3;
+ MY(gravity) = -0.300000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(sizeincrease) = -10;
+ MY(size_min) = 4;
+ MY(size_max) = 8;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '22.0 22.0 50.0';
+}
+// smoke
+SUB(damage_seeker) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 32;
+ MY(alpha_fade) = 128;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x111111";
+ MY(count) = 2;
+ MY(gravity) = -0.300000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '4.0 4.0 4.0';
+ MY(sizeincrease) = 10;
+ MY(size_min) = 2;
+ MY(size_max) = 4;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '11.0 11.0 50.0';
+}
+
+// hagar damage effect
+DEF(damage_hagar);
+SUB(damage_hagar) {
+ MY(alpha_min) = 512;
+ MY(alpha_max) = 32;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0x8f0c00";
+ MY(color_max) = "0xff3a00";
+ MY(count) = 3;
+ MY(gravity) = -0.300000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(sizeincrease) = -10;
+ MY(size_min) = 4;
+ MY(size_max) = 8;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '22.0 22.0 50.0';
+}
+// smoke
+SUB(damage_hagar) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 32;
+ MY(alpha_fade) = 128;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x111111";
+ MY(count) = 2;
+ MY(gravity) = -0.300000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '4.0 4.0 4.0';
+ MY(sizeincrease) = 10;
+ MY(size_min) = 2;
+ MY(size_max) = 4;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '11.0 11.0 50.0';
+}
+
+// fireball damage effect
+DEF(damage_fireball);
+SUB(damage_fireball) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 16;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 4;
+ MY(gravity) = -0.500000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '8.0 8.0 8.0';
+ MY(sizeincrease) = -10;
+ MY(size_min) = 5;
+ MY(size_max) = 10;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '22.0 22.0 50.0';
+}
+// smoke
+SUB(damage_fireball) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 32;
+ MY(alpha_fade) = 128;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x111111";
+ MY(count) = 4;
+ MY(gravity) = -0.300000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '6.0 6.0 6.0';
+ MY(sizeincrease) = 10;
+ MY(size_min) = 4;
+ MY(size_max) = 8;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '11.0 11.0 50.0';
+}
+
+// rocketlauncher damage effect
+DEF(damage_rocketlauncher);
+SUB(damage_rocketlauncher) {
+ MY(alpha_min) = 512;
+ MY(alpha_max) = 64;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0x8f0c00";
+ MY(color_max) = "0xff2a00";
+ MY(count) = 3;
+ MY(gravity) = -0.700000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '4.0 4.0 4.0';
+ MY(sizeincrease) = -10;
+ MY(size_min) = 5;
+ MY(size_max) = 10;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '22.0 22.0 30.0';
+}
+// smoke
+SUB(damage_rocketlauncher) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 32;
+ MY(alpha_fade) = 128;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x111111";
+ MY(count) = 3;
+ MY(gravity) = -0.300000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '4.0 4.0 4.0';
+ MY(sizeincrease) = 10;
+ MY(size_min) = 4;
+ MY(size_max) = 8;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '11.0 11.0 50.0';
+}
+
+// fireflies
+DEF(fireflies);
+SUB(fireflies) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 70;
+ MY(bounce) = -1;
+ MY(color_min) = "0xff9600";
+ MY(color_max) = "0xffefb8";
+ MY(count) = 1;
+ MY(originjitter) = '32.0 32.0 32.0';
+ MY(originoffset) = '8.0 8.0 8.0';
+ MY(sizeincrease) = -0.300000;
+ MY(size_min) = 2;
+ MY(size_max) = 3;
+ MY(tex_min) = 38;
+ MY(tex_max) = 38;
+ MY(time_min) = 1;
+ MY(time_max) = 2;
+ MY(type) = "static";
+ MY(velocityjitter) = '64.0 64.0 64.0';
+ MY(velocityoffset) = '2.0 2.0 2.0';
+}
+
+DEF(healray_muzzleflash);
+SUB(healray_muzzleflash) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x283880";
+ MY(color_max) = "0x283880";
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '1.5 3.0 6.0';
+ MY(lightradiusfade) = 2000;
+ MY(lightradius) = 200;
+ MY(originjitter) = '1.5 1.5 1.5';
+ MY(sizeincrease) = -10;
+ MY(size_min) = 20;
+ MY(size_max) = 20;
+ MY(tex_min) = 65;
+ MY(tex_max) = 65;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '6.0 6.0 6.0';
+ MY(velocitymultiplier) = 0.010000;
+}
+SUB(healray_muzzleflash) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 150;
+ MY(alpha_fade) = 1924;
+ MY(color_min) = "0xD9FDFF";
+ MY(color_max) = "0x00f0ff";
+ MY(count) = 22;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(sizeincrease) = 3;
+ MY(size_min) = 1;
+ MY(size_max) = 15;
+ MY(stretchfactor) = 3.900000;
+ MY(tex_min) = 71;
+ MY(tex_max) = 73;
+ MY(type) = "spark";
+ MY(velocityjitter) = '150.0 150.0 150.0';
+ MY(velocitymultiplier) = 0.400000;
+}
+SUB(healray_muzzleflash) {
+ MY(alpha_min) = 110;
+ MY(alpha_max) = 228;
+ MY(alpha_fade) = 4024;
+ MY(color_min) = "0xD9FDFF";
+ MY(color_max) = "0x00f0ff";
+ MY(count) = 4;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(stretchfactor) = 0.200000;
+ MY(tex_min) = 70;
+ MY(tex_max) = 70;
+ MY(type) = "spark";
+ MY(velocityjitter) = '650.0 650.0 650.0';
+ MY(velocitymultiplier) = 1.100000;
+}
+
+DEF(healray_impact);
+SUB(healray_impact) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(color_min) = "0xd800ff";
+ MY(color_max) = "0xd800ff";
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '0.0 4.4 0.0';
+ MY(lightradiusfade) = 450;
+ MY(lightradius) = 125;
+ MY(originjitter) = '17.0 17.0 17.0';
+ MY(size_min) = 32;
+ MY(size_max) = 32;
+ MY(tex_min) = 59;
+ MY(tex_max) = 59;
+ MY(type) = "decal";
+}
+// shockwave
+SUB(healray_impact) {
+ MY(alpha_min) = 40;
+ MY(alpha_max) = 40;
+ MY(alpha_fade) = 350;
+ MY(color_min) = "0x00ff00";
+ MY(color_max) = "0x84c52f";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 1400;
+ MY(size_min) = 32;
+ MY(size_max) = 32;
+ MY(tex_min) = 33;
+ MY(tex_max) = 33;
+ MY(type) = "smoke";
+ MY(velocitymultiplier) = 44;
+}
+// cloud of bouncing sparks
+SUB(healray_impact) {
+ MY(airfriction) = 6;
+ MY(alpha_min) = 156;
+ MY(alpha_max) = 300;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0x00ff00";
+ MY(color_max) = "0x84c52f";
+ MY(count) = 30;
+ MY(gravity) = 2;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 1;
+ MY(size_max) = 2;
+ MY(tex_min) = 70;
+ MY(tex_max) = 70;
+ MY(type) = "spark";
+ MY(velocityjitter) = '1112.0 1112.0 1112.0';
+}
+// inner cloud of smoke
+SUB(healray_impact) {
+ MY(airfriction) = 3;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 456;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x00ff00";
+ MY(color_max) = "0x84c52f";
+ MY(count) = 15;
+ MY(gravity) = -2;
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -90;
+ MY(spin_max) = 90;
+ MY(size_min) = 2;
+ MY(size_max) = 3;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '120.0 120.0 420.0';
+}
+
+DEF(bigplasma_muzzleflash);
+SUB(bigplasma_muzzleflash) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 812;
+ MY(color_min) = "0x283880";
+ MY(color_max) = "0x283880";
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '1.5 3.0 6.0';
+ MY(lightradiusfade) = 2000;
+ MY(lightradius) = 200;
+ MY(originjitter) = '1.5 1.5 1.5';
+ MY(sizeincrease) = -10;
+ MY(size_min) = 50;
+ MY(size_max) = 50;
+ MY(tex_min) = 65;
+ MY(tex_max) = 65;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '6.0 6.0 6.0';
+ MY(velocitymultiplier) = 0.010000;
+}
+SUB(bigplasma_muzzleflash) {
+ MY(alpha_min) = 56;
+ MY(alpha_max) = 56;
+ MY(alpha_fade) = 1112;
+ MY(color_min) = "0x00f0ff";
+ MY(color_max) = "0x00f0ff";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 300;
+ MY(size_min) = 20;
+ MY(size_max) = 20;
+ MY(tex_min) = 74;
+ MY(tex_max) = 74;
+ MY(type) = "smoke";
+}
+SUB(bigplasma_muzzleflash) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 150;
+ MY(alpha_fade) = 1924;
+ MY(color_min) = "0xD9FDFF";
+ MY(color_max) = "0x00f0ff";
+ MY(count) = 14;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(sizeincrease) = 135;
+ MY(size_min) = 5;
+ MY(size_max) = 10;
+ MY(stretchfactor) = 1.900000;
+ MY(tex_min) = 51;
+ MY(tex_max) = 55;
+ MY(type) = "spark";
+ MY(velocityjitter) = '350.0 350.0 350.0';
+ MY(velocitymultiplier) = 0.400000;
+}
+SUB(bigplasma_muzzleflash) {
+ MY(alpha_min) = 110;
+ MY(alpha_max) = 228;
+ MY(alpha_fade) = 4024;
+ MY(color_min) = "0xD9FDFF";
+ MY(color_max) = "0x00f0ff";
+ MY(count) = 4;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 20;
+ MY(size_max) = 20;
+ MY(stretchfactor) = 0.200000;
+ MY(tex_min) = 70;
+ MY(tex_max) = 70;
+ MY(type) = "spark";
+ MY(velocityjitter) = '650.0 650.0 650.0';
+ MY(velocitymultiplier) = 1.100000;
+}
+
+DEF(bigplasma_impact);
+SUB(bigplasma_impact) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '3.1 4.4 10.0';
+ MY(lightradiusfade) = 450;
+ MY(lightradius) = 125;
+ MY(originjitter) = '17.0 17.0 17.0';
+ MY(size_min) = 32;
+ MY(size_max) = 32;
+ MY(tex_min) = 59;
+ MY(tex_max) = 59;
+ MY(type) = "decal";
+}
+// shockwave
+SUB(bigplasma_impact) {
+ MY(alpha_min) = 40;
+ MY(alpha_max) = 40;
+ MY(alpha_fade) = 350;
+ MY(color_min) = "0x80C0FF";
+ MY(color_max) = "0x80C0FF";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 1400;
+ MY(size_min) = 32;
+ MY(size_max) = 32;
+ MY(tex_min) = 33;
+ MY(tex_max) = 33;
+ MY(type) = "smoke";
+ MY(velocitymultiplier) = 44;
+}
+// cloud of bouncing sparks
+SUB(bigplasma_impact) {
+ MY(airfriction) = 6;
+ MY(alpha_min) = 156;
+ MY(alpha_max) = 300;
+ MY(alpha_fade) = 1024;
+ MY(color_min) = "0x629dff";
+ MY(color_max) = "0x0018ff";
+ MY(count) = 30;
+ MY(gravity) = 2;
+ MY(originjitter) = '1.0 1.0 1.0';
+ MY(size_min) = 1;
+ MY(size_max) = 2;
+ MY(tex_min) = 70;
+ MY(tex_max) = 70;
+ MY(type) = "spark";
+ MY(velocityjitter) = '1512.0 1512.0 1512.0';
+}
+// inner cloud of smoke
+SUB(bigplasma_impact) {
+ MY(airfriction) = 30;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 456;
+ MY(alpha_fade) = 1512;
+ MY(color_min) = "0x629dff";
+ MY(color_max) = "0x0018ff";
+ MY(count) = 15;
+ MY(originjitter) = '20.0 20.0 20.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -9;
+ MY(spin_max) = 9;
+ MY(sizeincrease) = 555;
+ MY(size_min) = 20;
+ MY(size_max) = 24;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '320.0 320.0 320.0';
+}
+// smoke
+SUB(bigplasma_impact) {
+ MY(airfriction) = 0.040000;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 328;
+ MY(alpha_fade) = 390;
+ MY(blend) = "alpha";
+ MY(color_min) = "0x222222";
+ MY(color_max) = "0x000000";
+ MY(count) = 16;
+ MY(gravity) = 0.400000;
+ MY(originjitter) = '80.0 80.0 10.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = 2;
+ MY(spin_max) = -2;
+ MY(sizeincrease) = 30;
+ MY(size_min) = 60;
+ MY(size_max) = 30;
+ MY(tex_max) = 7;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '100.0 100.0 200.0';
+ MY(velocityoffset) = '0.0 0.0 180.0';
+}
+// smoke in the middle
+SUB(bigplasma_impact) {
+ MY(airfriction) = 0.040000;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 328;
+ MY(alpha_fade) = 310;
+ MY(color_min) = "0x222222";
+ MY(color_max) = "0x000000";
+ MY(count) = 10;
+ MY(gravity) = -0.200000;
+ MY(originjitter) = '80.0 80.0 80.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = 20;
+ MY(spin_max) = -20;
+ MY(sizeincrease) = -10;
+ MY(size_min) = 60;
+ MY(size_max) = 70;
+ MY(tex_max) = 7;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '10.0 10.0 10.0';
+}
+
+#include "effectinfo_ctf.inc"
+
+// spawn_point -- team idle spawn point effect
+#define spawn_point(name, color) \
+ DEF(spawn_point_##name); \
+ SUB(spawn_point_##name) { \
+ MY(airfriction) = 0.200000; \
+ MY(alpha_min) = 64; \
+ MY(alpha_max) = 128; \
+ MY(alpha_fade) = 128; \
+ MY(color_min) = color; \
+ MY(color_max) = color; \
+ MY(count) = 37.500000; \
+ MY(gravity) = -0.100000; \
+ MY(liquidfriction) = 0.800000; \
+ MY(originjitter) = '16.0 16.0 64.0'; \
+ MY(size_min) = 1; \
+ MY(size_max) = 2; \
+ MY(type) = "static"; \
+ MY(velocityjitter) = '32.0 32.0 0.0'; \
+ }
+
+spawn_point(red, "0xFF0F0F")
+spawn_point(blue, "0x0F0FFF")
+spawn_point(yellow, "0xFFFF0F")
+spawn_point(pink, "0xFF0FFF")
+spawn_point(neutral, "0xFFFFFF")
+#undef spawn_point
+
+// spawn_event -- team spawning effect
+#define spawn_event(name, color) \
+ DEF(spawn_event_##name); \
+ SUB(spawn_event_##name) { \
+ MY(airfriction) = 2; \
+ MY(alpha_max) = 256; \
+ MY(alpha_fade) = 256; \
+ MY(bounce) = 1; \
+ MY(color_min) = color; \
+ MY(color_max) = color; \
+ MY(count) = 100; \
+ MY(originjitter) = '1.0 1.0 1.0'; \
+ MY(size_min) = 1; \
+ MY(size_max) = 1; \
+ MY(stretchfactor) = 0.600000; \
+ MY(tex_min) = 64; \
+ MY(tex_max) = 64; \
+ MY(type) = "spark"; \
+ MY(velocityjitter) = '500.0 500.0 500.0'; \
+ MY(velocitymultiplier) = 0.100000; \
+ } \
+ SUB(spawn_event_##name) { \
+ MY(alpha_min) = 190; \
+ MY(alpha_max) = 190; \
+ MY(alpha_fade) = 180; \
+ MY(color_min) = color; \
+ MY(color_max) = color; \
+ MY(countabsolute) = 1; \
+ MY(sizeincrease) = -80; \
+ MY(size_min) = 100; \
+ MY(size_max) = 100; \
+ MY(tex_min) = 65; \
+ MY(tex_max) = 65; \
+ MY(type) = "smoke"; \
+ } \
+ /**/
+
+spawn_event(red, "0xFF0F0F")
+spawn_event(blue, "0x0F0FFF")
+spawn_event(yellow, "0xFFFF0F")
+spawn_event(pink, "0xFF0FFF")
+spawn_event(neutral, "0xFFFFFF")
+#undef spawn_event
+
+#include "effectinfo_nades.inc"
+
+DEF(shockwave_attack);
+// electricity
+SUB(shockwave_attack) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 4096;
+ MY(alpha_max) = 4096;
+ MY(alpha_fade) = 20000;
+ MY(color_min) = "0xb44215";
+ MY(color_max) = "0xff0000";
+ MY(count) = 1;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = 4000;
+ MY(spin_max) = -4000;
+ MY(sizeincrease) = 1.500000;
+ MY(size_min) = 5;
+ MY(size_max) = 7;
+ MY(stretchfactor) = 2.300000;
+ MY(tex_min) = 43;
+ MY(tex_max) = 43;
+ MY(type) = "spark";
+ MY(velocityjitter) = '10.0 10.0 10.0';
+ MY(velocitymultiplier) = 10;
+}
+// fire
+SUB(shockwave_attack) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 4096;
+ MY(alpha_max) = 4096;
+ MY(alpha_fade) = 20000;
+ MY(color_min) = "0xff4200";
+ MY(color_max) = "0xff0000";
+ MY(count) = 1;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(sizeincrease) = 1.500000;
+ MY(size_min) = 7;
+ MY(size_max) = 9;
+ MY(stretchfactor) = 2;
+ MY(tex_min) = 8;
+ MY(tex_max) = 15;
+ MY(type) = "spark";
+ MY(velocityjitter) = '10.0 10.0 10.0';
+ MY(velocitymultiplier) = 10;
+}
+
+DEF(arc_lightning);
+// impact decal
+SUB(arc_lightning) {
+ MY(alpha_min) = 32;
+ MY(alpha_max) = 32;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '3.1 4.4 10.0';
+ MY(lightradiusfade) = 200;
+ MY(lightradius) = 50;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(size_min) = 16;
+ MY(size_max) = 16;
+ MY(tex_min) = 16;
+ MY(tex_max) = 32;
+ MY(type) = "decal";
+}
+// impact sparks
+SUB(arc_lightning) {
+ MY(airfriction) = 110;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0xDDFDFF";
+ MY(color_max) = "0xFDFDFF";
+ MY(count) = 100;
+ MY(originjitter) = '20.0 20.0 20.0';
+ MY(startangle_max) = 360;
+ MY(spin_min) = -36000;
+ MY(spin_max) = 36000;
+ MY(sizeincrease) = -5;
+ MY(size_max) = 5;
+ MY(stretchfactor) = 1;
+ MY(tex_min) = 71;
+ MY(tex_max) = 74;
+ MY(type) = "static";
+ MY(velocityjitter) = '250.0 250.0 250.0';
+ MY(velocitymultiplier) = 100;
+}
+// impact sparks (underwater)
+SUB(arc_lightning) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0xDDFDFF";
+ MY(color_max) = "0xFDFDFF";
+ MY(count) = 100;
+ MY(liquidfriction) = 5;
+ MY(orientation) = "spark";
+ MY(originjitter) = '20.0 20.0 20.0';
+ MY(startangle_max) = 360;
+ MY(spin_min) = -36000;
+ MY(spin_max) = 36000;
+ MY(sizeincrease) = -5;
+ MY(size_max) = 5;
+ MY(stretchfactor) = 1;
+ MY(tex_min) = 71;
+ MY(tex_max) = 74;
+ MY(type) = "static";
+ MY(underwater) = true;
+ MY(velocityjitter) = '250.0 250.0 250.0';
+ MY(velocitymultiplier) = 20;
+}
+
+DEF(arc_beam);
+// sparks on beam
+SUB(arc_beam) {
+ MY(airfriction) = -10;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 16384;
+ MY(color_min) = "0xfafad2";
+ MY(color_max) = "0xffffff";
+ MY(originjitter) = '3.0 3.0 3.0';
+ MY(relativeoriginoffset) = '10.0 0.0 0.0';
+ MY(startangle_max) = 360;
+ MY(spin_min) = 360;
+ MY(spin_max) = 1000;
+ MY(stretchfactor) = 1;
+ MY(tex_min) = 71;
+ MY(tex_max) = 74;
+ MY(time_min) = 0.050000;
+ MY(time_max) = 0.050000;
+ MY(trailspacing) = 10;
+ MY(type) = "spark";
+ MY(velocityjitter) = '100.0 100.0 100.0';
+ MY(velocitymultiplier) = 200;
+}
+// sparks on beam (underwater)
+SUB(arc_beam) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 16384;
+ MY(color_min) = "0xfafad2";
+ MY(color_max) = "0xffffff";
+ MY(liquidfriction) = -10;
+ MY(originjitter) = '30.0 30.0 30.0';
+ MY(relativeoriginoffset) = '10.0 0.0 0.0';
+ MY(startangle_max) = 360;
+ MY(spin_min) = 360;
+ MY(spin_max) = 1000;
+ MY(stretchfactor) = 1;
+ MY(tex_min) = 71;
+ MY(tex_max) = 74;
+ MY(time_min) = 0.001000;
+ MY(time_max) = 0.001000;
+ MY(trailspacing) = 10;
+ MY(type) = "spark";
+ MY(underwater) = true;
+ MY(velocityjitter) = '100.0 100.0 100.0';
+ MY(velocitymultiplier) = 200;
+}
+
+DEF(arc_beam_heal);
+// bubble this...
+SUB(arc_beam_heal) {
+ MY(airfriction) = -20;
+ MY(alpha_min) = 2048;
+ MY(alpha_max) = 2048;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0x20FF20";
+ MY(color_max) = "0x40FF40";
+ MY(relativeoriginoffset) = '5.0 0.0 0.0';
+ MY(relativevelocityoffset) = '100.0 0.0 0.0';
+ MY(sizeincrease) = 20;
+ MY(size_min) = 0.100000;
+ MY(size_max) = 0.100000;
+ MY(tex_min) = 74;
+ MY(tex_max) = 74;
+ MY(trailspacing) = 1500;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '3.0 3.0 3.0';
+ MY(velocitymultiplier) = 200;
+}
+
+DEF(arc_beam_healimpact);
+// healing "aura"
+SUB(arc_beam_healimpact) {
+ MY(alpha_min) = 40;
+ MY(alpha_max) = 40;
+ MY(alpha_fade) = 350;
+ MY(color_min) = "0x00ff00";
+ MY(color_max) = "0x84c52f";
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '0.0 4.4 0.0';
+ MY(lightradiusfade) = 150;
+ MY(lightradius) = 20;
+ MY(sizeincrease) = -1000;
+ MY(size_min) = 32;
+ MY(size_max) = 32;
+ MY(tex_min) = 33;
+ MY(tex_max) = 33;
+ MY(type) = "smoke";
+ MY(velocitymultiplier) = 44;
+}
+// rising "smoke"
+SUB(arc_beam_healimpact) {
+ MY(airfriction) = 3;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 456;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0x00ff00";
+ MY(color_max) = "0x84c52f";
+ MY(count) = 15;
+ MY(gravity) = -2;
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -90;
+ MY(spin_max) = 90;
+ MY(size_min) = 0.500000;
+ MY(size_max) = 1;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '120.0 120.0 420.0';
+}
+
+DEF(arc_smoke);
+// arc heat smoke (notunderwater)
+SUB(arc_smoke) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 32;
+ MY(alpha_max) = 64;
+ MY(alpha_fade) = 48;
+ MY(color_min) = "0x4c453f";
+ MY(color_max) = "0x2a241f";
+ MY(count) = 2;
+ MY(gravity) = -0.125000;
+ MY(notunderwater) = true;
+ MY(startangle_max) = 360;
+ MY(spin_min) = -180;
+ MY(spin_max) = 180;
+ MY(sizeincrease) = 10;
+ MY(size_min) = 5;
+ MY(size_max) = 10;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '0.0 0.0 16.0';
+}
+// arc heat bubbles (underwater)
+SUB(arc_smoke) {
+ MY(alpha_min) = 170;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x808080";
+ MY(count) = 2;
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 0.250000;
+ MY(originjitter) = '6.0 6.0 6.0';
+ MY(size_min) = 0.100000;
+ MY(size_max) = 1;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '16.0 16.0 16.0';
+}
+
+DEF(arc_overheat);
+// arc overheat electric bolts
+SUB(arc_overheat) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 292;
+ MY(color_min) = "0xffffff";
+ MY(color_max) = "0x9271fb";
+ MY(count) = 24;
+ MY(gravity) = -0.400000;
+ MY(liquidfriction) = 10;
+ MY(originjitter) = '10.0 10.0 10.0';
+ MY(sizeincrease) = -24;
+ MY(size_min) = 6;
+ MY(size_max) = 12;
+ MY(tex_min) = 43;
+ MY(tex_max) = 43;
+ MY(type) = "spark";
+ MY(velocityjitter) = '256.0 256.0 256.0';
+}
+
+DEF(arc_overheat_fire);
+// arc overheat bouncing sparks
+SUB(arc_overheat_fire) {
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 640;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x4444ff";
+ MY(color_max) = "0xeeeeff";
+ MY(count) = 1;
+ MY(gravity) = 1;
+ MY(liquidfriction) = 5;
+ MY(originjitter) = '6.0 6.0 6.0';
+ MY(size_min) = 0.400000;
+ MY(size_max) = 1;
+ MY(type) = "spark";
+ MY(velocityjitter) = '92.0 92.0 92.0';
+ MY(velocitymultiplier) = 80;
+ MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+#include "effectinfo_buffs.inc"
+
+#include "effectinfo_instagib.inc"
--- /dev/null
+#define EFFECTINFO_PARSER(on) \
+ on(type, MY(type) \
+ ,{ ASSERT(n == 1 && "type"); MY(type) = strzone(argv(1)); \
+ }, sprintf(" %s", (MY(type)) \
+ )) \
+ on(airfriction, MY(airfriction) \
+ ,{ ASSERT(n == 1 && "airfriction"); MY(airfriction) = stof(argv(1)); \
+ }, sprintf(" %s", ftos(MY(airfriction)) \
+ )) \
+ on(alpha, MY(alpha_min) || MY(alpha_max) || MY(alpha_fade) \
+ ,{ ASSERT(n == 3 && "alpha"); MY(alpha_min) = stof(argv(1)); MY(alpha_max) = stof(argv(2)); MY(alpha_fade) = stof(argv(3)); \
+ }, sprintf(" %s %s %s", ftos(MY(alpha_min)), ftos(MY(alpha_max)), ftos(MY(alpha_fade)) \
+ )) \
+ on(blend, MY(blend) \
+ ,{ ASSERT(n == 1 && "blend"); MY(blend) = strzone(argv(1)); \
+ }, sprintf(" %s", (MY(blend)) \
+ )) \
+ on(bounce, MY(bounce) \
+ ,{ ASSERT(n == 1 && "bounce"); MY(bounce) = stof(argv(1)); \
+ }, sprintf(" %s", ftos(MY(bounce)) \
+ )) \
+ on(color, MY(color_min) || MY(color_max) \
+ ,{ ASSERT(n == 2 && "color"); MY(color_min) = strzone(argv(1)); MY(color_max) = strzone(argv(2)); \
+ }, sprintf(" %s %s", (MY(color_min)), (MY(color_max)) \
+ )) \
+ on(countabsolute, MY(countabsolute) \
+ ,{ ASSERT(n == 1 && "countabsolute"); MY(countabsolute) = stof(argv(1)); \
+ }, sprintf(" %s", ftos(MY(countabsolute)) \
+ )) \
+ on(count, MY(count) \
+ ,{ ASSERT(n == 1 && "count"); MY(count) = stof(argv(1)); \
+ }, sprintf(" %s", ftos(MY(count)) \
+ )) \
+ on(gravity, MY(gravity) \
+ ,{ ASSERT(n == 1 && "gravity"); MY(gravity) = stof(argv(1)); \
+ }, sprintf(" %s", ftos(MY(gravity)) \
+ )) \
+ on(lightcolor, MY(lightcolor) \
+ ,{ ASSERT(n == 3 && "lightcolor"); MY(lightcolor) = vec3(stof(argv(1)), stof(argv(2)), stof(argv(3))); \
+ }, sprintf(" %v", (MY(lightcolor)) \
+ )) \
+ on(lightradiusfade, MY(lightradiusfade) \
+ ,{ ASSERT(n == 1 && "lightradiusfade"); MY(lightradiusfade) = stof(argv(1)); \
+ }, sprintf(" %s", ftos(MY(lightradiusfade)) \
+ )) \
+ on(lightradius, MY(lightradius) \
+ ,{ ASSERT(n == 1 && "lightradius"); MY(lightradius) = stof(argv(1)); \
+ }, sprintf(" %s", ftos(MY(lightradius)) \
+ )) \
+ on(lighttime, MY(lighttime) \
+ ,{ ASSERT(n == 1 && "lighttime"); MY(lighttime) = stof(argv(1)); \
+ }, sprintf(" %s", ftos(MY(lighttime)) \
+ )) \
+ on(liquidfriction, MY(liquidfriction) \
+ ,{ ASSERT(n == 1 && "liquidfriction"); MY(liquidfriction) = stof(argv(1)); \
+ }, sprintf(" %s", ftos(MY(liquidfriction)) \
+ )) \
+ on(notunderwater, MY(notunderwater) \
+ ,{ ASSERT(n == 0 && "notunderwater"); MY(notunderwater) = true; \
+ }, "" \
+ ) \
+ on(orientation, MY(orientation) \
+ ,{ ASSERT(n == 1 && "orientation"); MY(orientation) = strzone(argv(1)); \
+ }, sprintf(" %s", (MY(orientation)) \
+ )) \
+ on(originjitter, MY(originjitter) \
+ ,{ ASSERT(n == 3 && "originjitter"); MY(originjitter) = vec3(stof(argv(1)), stof(argv(2)), stof(argv(3))); \
+ }, sprintf(" %v", (MY(originjitter)) \
+ )) \
+ on(originoffset, MY(originoffset) \
+ ,{ ASSERT(n == 3 && "originoffset"); MY(originoffset) = vec3(stof(argv(1)), stof(argv(2)), stof(argv(3))); \
+ }, sprintf(" %v", (MY(originoffset)) \
+ )) \
+ on(relativeoriginoffset, MY(relativeoriginoffset) \
+ ,{ ASSERT(n == 3 && "relativeoriginoffset"); MY(relativeoriginoffset) = vec3(stof(argv(1)), stof(argv(2)), stof(argv(3))); \
+ }, sprintf(" %v", (MY(relativeoriginoffset)) \
+ )) \
+ on(relativevelocityoffset, MY(relativevelocityoffset) \
+ ,{ ASSERT(n == 3 && "relativevelocityoffset"); MY(relativevelocityoffset) = vec3(stof(argv(1)), stof(argv(2)), stof(argv(3))); \
+ }, sprintf(" %v", (MY(relativevelocityoffset)) \
+ )) \
+ on(rotate, MY(startangle_min) || MY(startangle_max) || MY(spin_min) || MY(spin_max) \
+ ,{ ASSERT(n == 4 && "rotate"); MY(startangle_min) = stof(argv(1)); MY(startangle_max) = stof(argv(2)); MY(spin_min) = stof(argv(3)); MY(spin_max) = stof(argv(4)); \
+ }, sprintf(" %s %s %s %s", ftos(MY(startangle_min)), ftos(MY(startangle_max)), ftos(MY(spin_min)), ftos(MY(spin_max)) \
+ )) \
+ on(sizeincrease, MY(sizeincrease) \
+ ,{ ASSERT(n == 1 && "sizeincrease"); MY(sizeincrease) = stof(argv(1)); \
+ }, sprintf(" %s", ftos(MY(sizeincrease)) \
+ )) \
+ on(size, MY(size_min) || MY(size_max) \
+ ,{ ASSERT(n == 2 && "size"); MY(size_min) = stof(argv(1)); MY(size_max) = stof(argv(2)); \
+ }, sprintf(" %s %s", ftos(MY(size_min)), ftos(MY(size_max)) \
+ )) \
+ on(staincolor, MY(staincolor_min) || MY(staincolor_max) \
+ ,{ ASSERT(n == 2 && "staincolor"); MY(staincolor_min) = strzone(argv(1)); MY(staincolor_max) = strzone(argv(2)); \
+ }, sprintf(" %s %s", (MY(staincolor_min)), (MY(staincolor_max)) \
+ )) \
+ on(stainsize, MY(stainsize_min) || MY(stainsize_max) \
+ ,{ ASSERT(n == 2 && "stainsize"); MY(stainsize_min) = stof(argv(1)); MY(stainsize_max) = stof(argv(2)); \
+ }, sprintf(" %s %s", ftos(MY(stainsize_min)), ftos(MY(stainsize_max)) \
+ )) \
+ on(staintex, MY(staintex_min) || MY(staintex_max) \
+ ,{ ASSERT(n == 2 && "staintex"); MY(staintex_min) = stof(argv(1)); MY(staintex_max) = stof(argv(2)); \
+ }, sprintf(" %s %s", ftos(MY(staintex_min)), ftos(MY(staintex_max)) \
+ )) \
+ on(stretchfactor, MY(stretchfactor) \
+ ,{ ASSERT(n == 1 && "stretchfactor"); MY(stretchfactor) = stof(argv(1)); \
+ }, sprintf(" %s", ftos(MY(stretchfactor)) \
+ )) \
+ on(tex, MY(tex_min) || MY(tex_max) \
+ ,{ ASSERT(n == 2 && "tex"); MY(tex_min) = stof(argv(1)); MY(tex_max) = stof(argv(2)); \
+ }, sprintf(" %s %s", ftos(MY(tex_min)), ftos(MY(tex_max)) \
+ )) \
+ on(time, MY(time_min) || MY(time_max) \
+ ,{ ASSERT(n == 2 && "time"); MY(time_min) = stof(argv(1)); MY(time_max) = stof(argv(2)); \
+ }, sprintf(" %s %s", ftos(MY(time_min)), ftos(MY(time_max)) \
+ )) \
+ on(trailspacing, MY(trailspacing) \
+ ,{ ASSERT(n == 1 && "trailspacing"); MY(trailspacing) = stof(argv(1)); \
+ }, sprintf(" %s", ftos(MY(trailspacing)) \
+ )) \
+ on(underwater, MY(underwater) \
+ ,{ ASSERT(n == 0 && "underwater"); MY(underwater) = true; \
+ }, "" \
+ ) \
+ on(velocityjitter, MY(velocityjitter) \
+ ,{ ASSERT(n == 3 && "velocityjitter"); MY(velocityjitter) = vec3(stof(argv(1)), stof(argv(2)), stof(argv(3))); \
+ }, sprintf(" %v", (MY(velocityjitter)) \
+ )) \
+ on(velocitymultiplier, MY(velocitymultiplier) \
+ ,{ ASSERT(n == 1 && "velocitymultiplier"); MY(velocitymultiplier) = stof(argv(1)); \
+ }, sprintf(" %s", ftos(MY(velocitymultiplier)) \
+ )) \
+ on(velocityoffset, MY(velocityoffset) \
+ ,{ ASSERT(n == 3 && "velocityoffset"); MY(velocityoffset) = vec3(stof(argv(1)), stof(argv(2)), stof(argv(3))); \
+ }, sprintf(" %v", (MY(velocityoffset)) \
+ )) \
+ /**/
+
+CLASS(EffectInfo, Object)
+ ATTRIB(EffectInfo, effectinfo_name, string, string_null)
+ CONSTRUCTOR(EffectInfo, string s) {
+ CONSTRUCT(EffectInfo);
+ this.effectinfo_name = s;
+ }
+
+ #define FIELDS(MY) \
+ MY(airfriction, float, 0) \
+ MY(alpha_min, float, 0) \
+ MY(alpha_max, float, 0) \
+ MY(alpha_fade, float, 0) \
+ MY(blend, string, string_null) \
+ MY(bounce, float, 0) \
+ MY(color_min, string, string_null) \
+ MY(color_max, string, string_null) \
+ MY(countabsolute, float, 0) \
+ MY(count, float, 0) \
+ MY(gravity, float, 0) \
+ MY(lightcolor, vector, '0 0 0') \
+ MY(lightradiusfade, float, 0) \
+ MY(lightradius, float, 0) \
+ MY(lighttime, float, 0) \
+ MY(liquidfriction, float, 0) \
+ MY(notunderwater, bool, false) \
+ MY(orientation, string, string_null) \
+ MY(originjitter, vector, '0 0 0') \
+ MY(originoffset, vector, '0 0 0') \
+ MY(relativeoriginoffset, vector, '0 0 0') \
+ MY(relativevelocityoffset, vector, '0 0 0') \
+ MY(startangle_min, float, 0) \
+ MY(startangle_max, float, 0) \
+ MY(spin_min, float, 0) \
+ MY(spin_max, float, 0) \
+ MY(sizeincrease, float, 0) \
+ MY(size_min, float, 0) \
+ MY(size_max, float, 0) \
+ MY(staincolor_min, string, string_null) \
+ MY(staincolor_max, string, string_null) \
+ MY(stainsize_min, float, 0) \
+ MY(stainsize_max, float, 0) \
+ MY(staintex_min, float, 0) \
+ MY(staintex_max, float, 0) \
+ MY(stretchfactor, float, 0) \
+ MY(tex_min, float, 0) \
+ MY(tex_max, float, 0) \
+ MY(time_min, float, 0) \
+ MY(time_max, float, 0) \
+ MY(trailspacing, float, 0) \
+ MY(type, string, string_null) \
+ MY(underwater, bool, false) \
+ MY(velocityjitter, vector, '0 0 0') \
+ MY(velocitymultiplier, float, 0) \
+ MY(velocityoffset, vector, '0 0 0') \
+ /**/
+
+ #define MY(f, type, val) ATTRIB(EffectInfo, effectinfo_##f, type, val)
+ FIELDS(MY)
+ #undef MY
+
+ METHOD(EffectInfo, describe, string(EffectInfo this)) {
+ string s = sprintf("SUB(%s) {\n", this.effectinfo_name);
+ #define str_bool(it) (it ? "true" : "false")
+ #define str_float(it) ftos(it)
+ #define str_vector(it) vtos(it)
+ #define str_string(it) strcat("\"", it, "\"")
+ #define p(f, type, default) if (this.effectinfo_##f) { s = strcat(s, "\t", "MY("#f") = ", str_##type(this.effectinfo_##f), ";\n"); }
+ FIELDS(p)
+ #undef p
+ #undef MY
+ return strcat(s, "}\n");
+ }
+
+ METHOD(EffectInfo, dump, string(EffectInfo this)) {
+ string s = sprintf("effect %s\n", this.effectinfo_name);
+ #define MY(f) this.effectinfo_##f
+ #define p(k, isset, parse, unparse) if (isset) { s = strcat(s, "\t", #k, unparse, "\n"); }
+ EFFECTINFO_PARSER(p)
+ #undef p
+ #undef MY
+ return s;
+ }
+
+ #undef FIELDS
+ENDCLASS(EffectInfo)
+
+CLASS(EffectInfoGroup, Object)
+ ATTRIBARRAY(EffectInfoGroup, children, EffectInfo, 16)
+ ATTRIB(EffectInfoGroup, children_count, int, 0)
+ENDCLASS(EffectInfoGroup)
+
+void effectinfo_read()
+{
+ int fh = fopen("effectinfo.txt", FILE_READ);
+ EffectInfo info = NULL;
+ for (string line; (line = fgets(fh)); ) {
+ int n = tokenize_console(line);
+ if (n == 0) continue;
+ n--;
+ string k = argv(0);
+ if (k == "effect") {
+ ASSERT(n == 1);
+ info = NEW(EffectInfo, strzone(argv(1)));
+ continue;
+ }
+ ASSERT(info != NULL);
+ switch (k) {
+ #define MY(f) info.effectinfo_##f
+ #define p(k, isset, parse, unparse) case #k: parse break;
+ EFFECTINFO_PARSER(p)
+ #undef p
+ #undef MY
+ default:
+ LOG_WARNINGF("Unknown property '%s'\n", k);
+ break;
+ }
+ }
+ fclose(fh);
+}
+
+void effectinfo_dump(int fh, bool alsoprint)
+{
+ #define WRITE(s) do { \
+ fputs(fh, s); \
+ if (alsoprint) LOG_INFO(s); \
+ } while (0)
+ WRITE("// ********************************************** //\n");
+ WRITE("// ** WARNING - DO NOT MANUALLY EDIT THIS FILE ** //\n");
+ WRITE("// ** ** //\n");
+ WRITE("// ** This file is automatically generated by ** //\n");
+ WRITE("// ** code with the command 'dumpeffectinfo'. ** //\n");
+ WRITE("// ** ** //\n");
+ WRITE("// ** If you modify an effect, please ** //\n");
+ WRITE("// ** regenerate this file with that command. ** //\n");
+ WRITE("// ** ** //\n");
+ WRITE("// ********************************************** //\n");
+ WRITE("\n");
+
+ for (EffectInfo it = NULL; (it = findfloat(it, instanceOfEffectInfo, true)); ) {
+ if (it.classname == "vtbl") continue;
+ string s = it.dump(it);
+ WRITE(s);
+ }
+ #undef WRITE
+}
+
+
+REGISTRY(EffectInfos, BIT(9))
+REGISTER_REGISTRY(RegisterEffectInfos)
+#define EFFECTINFO(name) \
+ [[accumulate]] void effectinfo_##name(EffectInfoGroup parent, EffectInfo this) { } \
+ REGISTER(RegisterEffectInfos, EFFECTINFO, EffectInfos, name, m_id, NEW(EffectInfoGroup)) { \
+ effectinfo_##name(this, NULL); \
+ }
+
+#define MY(f) this.effectinfo_##f
+#define DEF(name) EFFECTINFO(name)
+#define SUB(name) \
+ [[accumulate]] void effectinfo_##name(EffectInfoGroup parent, EffectInfo this) { parent = EFFECTINFO_##name; parent.children[parent.children_count++] = this = NEW(EffectInfo, #name); } \
+ [[accumulate]] void effectinfo_##name(EffectInfoGroup parent, EffectInfo this)
+#include "effectinfo.inc"
+#undef MY
+#undef DEF
+#undef SUB
--- /dev/null
+DEF(relic_resistance);
+SUB(relic_resistance) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0x00ff80";
+ MY(color_max) = "0x00ff80";
+ MY(count) = 20;
+ MY(gravity) = -0.100000;
+ MY(liquidfriction) = 0.800000;
+ MY(originjitter) = '8.0 8.0 32.0';
+ MY(size_min) = 1.500000;
+ MY(size_max) = 1.500000;
+ MY(type) = "static";
+ MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_regeneration);
+SUB(relic_regeneration) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0x00ffff";
+ MY(color_max) = "0x00ffff";
+ MY(count) = 1;
+ MY(gravity) = -0.100000;
+ MY(liquidfriction) = 0.800000;
+ MY(originjitter) = '8.0 8.0 32.0';
+ MY(size_min) = 1.500000;
+ MY(size_max) = 1.500000;
+ MY(type) = "static";
+ MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_vampire);
+SUB(relic_vampire) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0xff00ff";
+ MY(color_max) = "0xff00ff";
+ MY(count) = 20;
+ MY(gravity) = -0.100000;
+ MY(liquidfriction) = 0.800000;
+ MY(originjitter) = '8.0 8.0 32.0';
+ MY(size_min) = 1.500000;
+ MY(size_max) = 1.500000;
+ MY(type) = "static";
+ MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_ammo);
+SUB(relic_ammo) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0x80ff00";
+ MY(color_max) = "0x80ff00";
+ MY(count) = 1;
+ MY(gravity) = -0.100000;
+ MY(liquidfriction) = 0.800000;
+ MY(originjitter) = '8.0 8.0 32.0';
+ MY(size_min) = 1.500000;
+ MY(size_max) = 1.500000;
+ MY(type) = "static";
+ MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_damage);
+SUB(relic_damage) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0xff0000";
+ MY(color_max) = "0xff0000";
+ MY(count) = 20;
+ MY(gravity) = -0.100000;
+ MY(liquidfriction) = 0.800000;
+ MY(originjitter) = '8.0 8.0 32.0';
+ MY(size_min) = 1.500000;
+ MY(size_max) = 1.500000;
+ MY(type) = "static";
+ MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_ssplashdamage);
+SUB(relic_ssplashdamage) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0xff8000";
+ MY(color_max) = "0xff8000";
+ MY(count) = 20;
+ MY(gravity) = -0.100000;
+ MY(liquidfriction) = 0.800000;
+ MY(originjitter) = '8.0 8.0 32.0';
+ MY(size_min) = 1.500000;
+ MY(size_max) = 1.500000;
+ MY(type) = "static";
+ MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_firingspeed);
+SUB(relic_firingspeed) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0xffff00";
+ MY(color_max) = "0xffff00";
+ MY(count) = 20;
+ MY(gravity) = -0.100000;
+ MY(liquidfriction) = 0.800000;
+ MY(originjitter) = '8.0 8.0 32.0';
+ MY(size_min) = 1.500000;
+ MY(size_max) = 1.500000;
+ MY(type) = "static";
+ MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_disability);
+SUB(relic_disability) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0x0000ff";
+ MY(color_max) = "0x0000ff";
+ MY(count) = 20;
+ MY(gravity) = -0.100000;
+ MY(liquidfriction) = 0.800000;
+ MY(originjitter) = '8.0 8.0 32.0';
+ MY(size_min) = 1.500000;
+ MY(size_max) = 1.500000;
+ MY(type) = "static";
+ MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_disability_curse);
+SUB(relic_disability_curse) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0x000080";
+ MY(color_max) = "0x000080";
+ MY(count) = 1;
+ MY(gravity) = -0.100000;
+ MY(liquidfriction) = 0.800000;
+ MY(originjitter) = '8.0 8.0 32.0';
+ MY(size_min) = 1.500000;
+ MY(size_max) = 1.500000;
+ MY(type) = "static";
+ MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_teamboost);
+SUB(relic_teamboost) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0xffffff";
+ MY(color_max) = "0xffffff";
+ MY(count) = 20;
+ MY(gravity) = -0.100000;
+ MY(liquidfriction) = 0.800000;
+ MY(originjitter) = '8.0 8.0 32.0';
+ MY(size_min) = 1.500000;
+ MY(size_max) = 1.500000;
+ MY(type) = "static";
+ MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_teamboost_boost);
+SUB(relic_teamboost_boost) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0x808080";
+ MY(color_max) = "0x808080";
+ MY(count) = 1;
+ MY(gravity) = -0.100000;
+ MY(liquidfriction) = 0.800000;
+ MY(originjitter) = '8.0 8.0 32.0';
+ MY(size_min) = 1.500000;
+ MY(size_max) = 1.500000;
+ MY(type) = "static";
+ MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_speed);
+SUB(relic_speed) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0x80ffff";
+ MY(color_max) = "0x80ffff";
+ MY(count) = 1;
+ MY(gravity) = -0.100000;
+ MY(liquidfriction) = 0.800000;
+ MY(originjitter) = '8.0 8.0 32.0';
+ MY(size_min) = 1.500000;
+ MY(size_max) = 1.500000;
+ MY(type) = "static";
+ MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_jump);
+SUB(relic_jump) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0xffff80";
+ MY(color_max) = "0xffff80";
+ MY(count) = 20;
+ MY(gravity) = -0.100000;
+ MY(liquidfriction) = 0.800000;
+ MY(originjitter) = '8.0 8.0 32.0';
+ MY(size_min) = 1.500000;
+ MY(size_max) = 1.500000;
+ MY(type) = "static";
+ MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_flight);
+SUB(relic_flight) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0x8080ff";
+ MY(color_max) = "0x8080ff";
+ MY(count) = 1;
+ MY(gravity) = -0.100000;
+ MY(liquidfriction) = 0.800000;
+ MY(originjitter) = '8.0 8.0 32.0';
+ MY(size_min) = 1.500000;
+ MY(size_max) = 1.500000;
+ MY(type) = "static";
+ MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_radioactive);
+SUB(relic_radioactive) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0x00ff00";
+ MY(color_max) = "0x00ff00";
+ MY(count) = 20;
+ MY(gravity) = -0.100000;
+ MY(liquidfriction) = 0.800000;
+ MY(originjitter) = '8.0 8.0 32.0';
+ MY(size_min) = 1.500000;
+ MY(size_max) = 1.500000;
+ MY(type) = "static";
+ MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_resurrection);
+SUB(relic_resurrection) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0xff0080";
+ MY(color_max) = "0xff0080";
+ MY(count) = 20;
+ MY(gravity) = -0.100000;
+ MY(liquidfriction) = 0.800000;
+ MY(originjitter) = '8.0 8.0 32.0';
+ MY(size_min) = 1.500000;
+ MY(size_max) = 1.500000;
+ MY(type) = "static";
+ MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_vengeance);
+SUB(relic_vengeance) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 256;
+ MY(color_min) = "0xff8080";
+ MY(color_max) = "0xff8080";
+ MY(count) = 20;
+ MY(gravity) = -0.100000;
+ MY(liquidfriction) = 0.800000;
+ MY(originjitter) = '8.0 8.0 32.0';
+ MY(size_min) = 1.500000;
+ MY(size_max) = 1.500000;
+ MY(type) = "static";
+ MY(velocityjitter) = '64.0 64.0 32.0';
+}
--- /dev/null
+// flag_touch -- effects for touching the flag
+#define flag_touch(name, colormin, colormax) \
+ DEF(name##flag_touch); \
+ SUB(name##flag_touch) { \
+ MY(airfriction) = 3; \
+ MY(alpha_max) = 256; \
+ MY(alpha_fade) = 556; \
+ MY(bounce) = 1.500000; \
+ MY(color_min) = colormin; \
+ MY(color_max) = colormax; \
+ MY(count) = 35; \
+ MY(gravity) = 1; \
+ MY(originjitter) = '1.0 1.0 1.0'; \
+ MY(size_min) = 1; \
+ MY(size_max) = 3; \
+ MY(tex_min) = 40; \
+ MY(tex_max) = 40; \
+ MY(type) = "spark"; \
+ MY(velocityjitter) = '300.0 300.0 300.0'; \
+ MY(velocitymultiplier) = 0.500000; \
+ }
+
+flag_touch(red, "0xFF0000", "0x970000")
+flag_touch(blue, "0x0000FF", "0x000097")
+flag_touch(yellow, "0xFFFF0F", "0xFFFF0F")
+flag_touch(pink, "0xFF0FFF", "0xFF0FFF")
+flag_touch(neutral, "0xFFFFFF", "0xFFFFFF")
+#undef flag_touch
+
+#define pass(name, colormin, colormax) \
+ DEF(name##_pass); \
+ SUB(name##_pass) { \
+ MY(airfriction) = 5; \
+ MY(alpha_min) = 64; \
+ MY(alpha_max) = 128; \
+ MY(alpha_fade) = 64; \
+ MY(color_min) = colormin; \
+ MY(color_max) = colormax; \
+ MY(sizeincrease) = 2; \
+ MY(size_min) = 2; \
+ MY(size_max) = 2; \
+ MY(tex_min) = 32; \
+ MY(tex_max) = 32; \
+ MY(trailspacing) = 64; \
+ MY(type) = "static"; \
+ } \
+ SUB(name##_pass) { \
+ MY(airfriction) = 9; \
+ MY(alpha_min) = 32; \
+ MY(alpha_max) = 64; \
+ MY(alpha_fade) = 32; \
+ MY(color_min) = colormin; \
+ MY(color_max) = colormax; \
+ MY(sizeincrease) = 8; \
+ MY(size_min) = 1; \
+ MY(size_max) = 1; \
+ MY(tex_max) = 8; \
+ MY(trailspacing) = 12; \
+ MY(type) = "static"; \
+ MY(velocityjitter) = '64.0 64.0 64.0'; \
+ } \
+ SUB(name##_pass) { \
+ MY(alpha_min) = 256; \
+ MY(alpha_max) = 256; \
+ MY(alpha_fade) = 1280; \
+ MY(color_min) = colormin; \
+ MY(color_max) = colormax; \
+ MY(size_min) = 4; \
+ MY(size_max) = 4; \
+ MY(trailspacing) = 12; \
+ MY(type) = "static"; \
+ } \
+ /**/
+
+pass(red, "0xFF0000", "0x970000")
+pass(blue, "0x0000FF", "0x000097")
+pass(yellow, "0xFFFF0F", "0xFFFF0F")
+pass(pink, "0xFFFFFF", "0xFFFFFF")
+pass(neutral, "0xFFFFFF", "0xFFFFFF")
+#undef pass
+
+// cap -- team capture effect
+#define cap(name, colormin, colormax) \
+ DEF(name##_cap); \
+ SUB(name##_cap) { \
+ MY(airfriction) = 2; \
+ MY(alpha_max) = 256; \
+ MY(alpha_fade) = 100; \
+ MY(bounce) = 1.500000; \
+ MY(color_min) = colormin; \
+ MY(color_max) = colormax; \
+ MY(count) = 500; \
+ MY(originjitter) = '1.0 1.0 1.0'; \
+ MY(size_min) = 1; \
+ MY(size_max) = 1; \
+ MY(stretchfactor) = 0.600000; \
+ MY(tex_min) = 64; \
+ MY(tex_max) = 64; \
+ MY(type) = "spark"; \
+ MY(velocityjitter) = '1000.0 1000.0 1500.0'; \
+ MY(velocitymultiplier) = 0.500000; \
+ } \
+ SUB(name##_cap) { \
+ MY(alpha_min) = 190; \
+ MY(alpha_max) = 190; \
+ MY(alpha_fade) = 180; \
+ MY(color_min) = colormin; \
+ MY(color_max) = colormax; \
+ MY(countabsolute) = 1; \
+ MY(sizeincrease) = -80; \
+ MY(size_min) = 150; \
+ MY(size_max) = 150; \
+ MY(tex_min) = 65; \
+ MY(tex_max) = 65; \
+ MY(type) = "smoke"; \
+ } \
+ /**/
+
+cap(red, "0xFF0000", "0x970000")
+cap(blue, "0x0000FF", "0x000097")
+cap(yellow, "0xFFFF0F", "0xFFFF0F")
+cap(pink, "0xFF0FFF", "0xFF0FFF")
+#undef cap
--- /dev/null
+// cl_gentle impact effect indicating damage
+// NOTE: maintained by div0, make your own new effect instead of changing this one without asking!
+DEF(damage_hit);
+SUB(damage_hit) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 192;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x00FFFF";
+ MY(color_max) = "0xFF00FF";
+ MY(count) = 0.500000;
+ MY(gravity) = -0.400000;
+ MY(liquidfriction) = 10;
+ MY(sizeincrease) = -24;
+ MY(size_min) = 16;
+ MY(size_max) = 16;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '256.0 256.0 256.0';
+}
+SUB(damage_hit) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 192;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0xFF00FF";
+ MY(color_max) = "0xFFFF00";
+ MY(count) = 0.500000;
+ MY(gravity) = -0.400000;
+ MY(liquidfriction) = 10;
+ MY(sizeincrease) = -24;
+ MY(size_min) = 16;
+ MY(size_max) = 16;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '256.0 256.0 256.0';
+}
+SUB(damage_hit) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 192;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0xFFFF00";
+ MY(color_max) = "0x00FFFF";
+ MY(count) = 0.500000;
+ MY(gravity) = -0.400000;
+ MY(liquidfriction) = 10;
+ MY(sizeincrease) = -24;
+ MY(size_min) = 16;
+ MY(size_max) = 16;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '256.0 256.0 256.0';
+}
+
+// effect for removing player model
+DEF(damage_dissolve);
+// large sparks
+SUB(damage_dissolve) {
+ MY(airfriction) = 3;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 128;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x00FFFF";
+ MY(color_max) = "0xFF00FF";
+ MY(count) = 15;
+ MY(gravity) = -0.400000;
+ MY(liquidfriction) = 6;
+ MY(sizeincrease) = -16;
+ MY(size_min) = 32;
+ MY(size_max) = 32;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '512.0 512.0 512.0';
+}
+SUB(damage_dissolve) {
+ MY(airfriction) = 3;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 128;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0xFF00FF";
+ MY(color_max) = "0xFFFF00";
+ MY(count) = 15;
+ MY(gravity) = -0.400000;
+ MY(liquidfriction) = 6;
+ MY(sizeincrease) = -16;
+ MY(size_min) = 32;
+ MY(size_max) = 32;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '512.0 512.0 512.0';
+}
+SUB(damage_dissolve) {
+ MY(airfriction) = 3;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 128;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0xFFFF00";
+ MY(color_max) = "0x00FFFF";
+ MY(count) = 15;
+ MY(gravity) = -0.400000;
+ MY(liquidfriction) = 6;
+ MY(sizeincrease) = -16;
+ MY(size_min) = 32;
+ MY(size_max) = 32;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '512.0 512.0 512.0';
+}
--- /dev/null
+// happy death fx for cl_gentle
+DEF(happy_damage_dissolve);
+SUB(happy_damage_dissolve) {
+ MY(airfriction) = 3;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 228;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x00FFFF";
+ MY(color_max) = "0xFF00FF";
+ MY(count) = 15;
+ MY(gravity) = -0.400000;
+ MY(liquidfriction) = 6;
+ MY(sizeincrease) = -10;
+ MY(size_min) = 32;
+ MY(size_max) = 32;
+ MY(tex_min) = 69;
+ MY(tex_max) = 69;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '312.0 312.0 312.0';
+}
+SUB(happy_damage_dissolve) {
+ MY(airfriction) = 3;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 228;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0xFF00FF";
+ MY(color_max) = "0xFFFF00";
+ MY(count) = 15;
+ MY(gravity) = -0.400000;
+ MY(liquidfriction) = 6;
+ MY(sizeincrease) = -10;
+ MY(size_min) = 32;
+ MY(size_max) = 32;
+ MY(tex_min) = 69;
+ MY(tex_max) = 69;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '312.0 312.0 312.0';
+}
+SUB(happy_damage_dissolve) {
+ MY(airfriction) = 3;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 228;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0xFFFF00";
+ MY(color_max) = "0x00FFFF";
+ MY(count) = 15;
+ MY(gravity) = -0.400000;
+ MY(liquidfriction) = 6;
+ MY(sizeincrease) = -10;
+ MY(size_min) = 32;
+ MY(size_max) = 32;
+ MY(tex_min) = 69;
+ MY(tex_max) = 69;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '312.0 312.0 312.0';
+}
+
+// happy damage fx for cl_gentle
+DEF(happy_damage_hit);
+SUB(happy_damage_hit) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 192;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x00FFFF";
+ MY(color_max) = "0xFF00FF";
+ MY(count) = 0.100000;
+ MY(gravity) = -0.400000;
+ MY(liquidfriction) = 10;
+ MY(sizeincrease) = -28;
+ MY(size_min) = 26;
+ MY(size_max) = 26;
+ MY(tex_min) = 69;
+ MY(tex_max) = 69;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '156.0 156.0 156.0';
+}
+SUB(happy_damage_hit) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 192;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0xFF00FF";
+ MY(color_max) = "0xFFFF00";
+ MY(count) = 0.100000;
+ MY(gravity) = -0.400000;
+ MY(liquidfriction) = 10;
+ MY(sizeincrease) = -28;
+ MY(size_min) = 26;
+ MY(size_max) = 26;
+ MY(tex_min) = 69;
+ MY(tex_max) = 69;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '156.0 156.0 156.0';
+}
+SUB(happy_damage_hit) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 192;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0xFFFF00";
+ MY(color_max) = "0x00FFFF";
+ MY(count) = 0.100000;
+ MY(gravity) = -0.400000;
+ MY(liquidfriction) = 10;
+ MY(sizeincrease) = -28;
+ MY(size_min) = 26;
+ MY(size_max) = 26;
+ MY(tex_min) = 69;
+ MY(tex_max) = 69;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '156.0 156.0 156.0';
+}
--- /dev/null
+// cl_gentle impact effect indicating damage
+DEF(morphed_damage_hit);
+SUB(morphed_damage_hit) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 292;
+ MY(color_min) = "0xffffff";
+ MY(color_max) = "0x9271fb";
+ MY(count) = 0.500000;
+ MY(gravity) = -0.400000;
+ MY(liquidfriction) = 10;
+ MY(sizeincrease) = -24;
+ MY(size_min) = 14;
+ MY(size_max) = 24;
+ MY(tex_min) = 43;
+ MY(tex_max) = 43;
+ MY(type) = "spark";
+ MY(velocityjitter) = '356.0 356.0 456.0';
+}
+SUB(morphed_damage_hit) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 128;
+ MY(alpha_fade) = 292;
+ MY(color_min) = "0xffffff";
+ MY(color_max) = "0x9271fb";
+ MY(count) = 0.500000;
+ MY(liquidfriction) = 10;
+ MY(originjitter) = '10.0 10.0 10.0';
+ MY(sizeincrease) = -24;
+ MY(size_min) = 24;
+ MY(size_max) = 24;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+}
+
+// effect for removing player model
+DEF(morphed_damage_dissolve);
+SUB(morphed_damage_dissolve) {
+ MY(airfriction) = 8;
+ MY(alpha_min) = 456;
+ MY(alpha_max) = 456;
+ MY(alpha_fade) = 1828;
+ MY(color_min) = "0xffffff";
+ MY(color_max) = "0x9271fb";
+ MY(count) = 10;
+ MY(gravity) = -1.900000;
+ MY(liquidfriction) = 6;
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -399;
+ MY(spin_max) = -99;
+ MY(sizeincrease) = -16;
+ MY(size_min) = 40;
+ MY(size_max) = 40;
+ MY(tex_min) = 43;
+ MY(tex_max) = 43;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '256.0 256.0 512.0';
+}
+SUB(morphed_damage_dissolve) {
+ MY(airfriction) = 9;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 628;
+ MY(color_min) = "0x7bdbff";
+ MY(color_max) = "0xbed2ff";
+ MY(count) = 2.500000;
+ MY(gravity) = -0.800000;
+ MY(liquidfriction) = 6;
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(sizeincrease) = -16;
+ MY(size_min) = 40;
+ MY(size_max) = 40;
+ MY(tex_min) = 43;
+ MY(tex_max) = 43;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '256.0 256.0 512.0';
+}
+SUB(morphed_damage_dissolve) {
+ MY(airfriction) = 3;
+ MY(alpha_min) = 156;
+ MY(alpha_max) = 156;
+ MY(alpha_fade) = 128;
+ MY(color_min) = "0xffffff";
+ MY(color_max) = "0x9271fb";
+ MY(count) = 5;
+ MY(liquidfriction) = 6;
+ MY(originjitter) = '22.0 22.0 76.0';
+ MY(sizeincrease) = -16;
+ MY(size_min) = 44;
+ MY(size_max) = 44;
+ MY(tex_min) = 65;
+ MY(tex_max) = 65;
+ MY(type) = "smoke";
+}
+SUB(morphed_damage_dissolve) {
+ MY(airfriction) = 3;
+ MY(alpha_min) = 56;
+ MY(alpha_max) = 56;
+ MY(alpha_fade) = 128;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0xffffff";
+ MY(color_max) = "0x9271fb";
+ MY(count) = 15;
+ MY(gravity) = 1;
+ MY(liquidfriction) = 6;
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = 999;
+ MY(spin_max) = -999;
+ MY(sizeincrease) = -16;
+ MY(size_min) = 32;
+ MY(size_max) = 32;
+ MY(tex_min) = 46;
+ MY(tex_max) = 46;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '400.0 400.0 0.0';
+}
--- /dev/null
+// cl_gentle impact effect indicating damage
+DEF(particlegibs_damage_hit);
+// core decal
+SUB(particlegibs_damage_hit) {
+ MY(airfriction) = 3;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 428;
+ MY(bounce) = -1;
+ MY(color_min) = "0xA8FFFF";
+ MY(color_max) = "0xA8FFFFF";
+ MY(count) = 0.500000;
+ MY(gravity) = 1;
+ MY(liquidfriction) = 6;
+ MY(size_min) = 5;
+ MY(size_max) = 10;
+ MY(staincolor_min) = "0x808080";
+ MY(staincolor_max) = "0x808080";
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(tex_max) = 8;
+ MY(type) = "blood";
+ MY(velocityjitter) = '156.0 156.0 212.0';
+}
+// front blood
+SUB(particlegibs_damage_hit) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 328;
+ MY(bounce) = -1;
+ MY(color_min) = "0xA8FFFF";
+ MY(color_max) = "0xA8FFFFF";
+ MY(count) = 0.100000;
+ MY(gravity) = 0.500000;
+ MY(liquidfriction) = 3;
+ MY(sizeincrease) = -15;
+ MY(size_min) = 10;
+ MY(size_max) = 20;
+ MY(staincolor_min) = "0x808080";
+ MY(staincolor_max) = "0x808080";
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(type) = "blood";
+ MY(velocityjitter) = '6.0 6.0 30.0';
+ MY(velocitymultiplier) = -1;
+}
+// back blood
+SUB(particlegibs_damage_hit) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 328;
+ MY(bounce) = -1;
+ MY(color_min) = "0xA8FFFF";
+ MY(color_max) = "0xA8FFFFF";
+ MY(count) = 0.100000;
+ MY(gravity) = 1;
+ MY(liquidfriction) = 3;
+ MY(originjitter) = '3.0 3.0 3.0';
+ MY(sizeincrease) = 10;
+ MY(size_min) = 5;
+ MY(size_max) = 15;
+ MY(staincolor_min) = "0x808080";
+ MY(staincolor_max) = "0x808080";
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(type) = "blood";
+ MY(velocityjitter) = '26.0 26.0 112.0';
+ MY(velocitymultiplier) = 2;
+}
+
+// effect for removing player model
+DEF(particlegibs_damage_dissolve);
+// small core blood no decals
+SUB(particlegibs_damage_dissolve) {
+ MY(airfriction) = 3;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 328;
+ MY(color_min) = "0x00ffff";
+ MY(color_max) = "0x82ffff";
+ MY(count) = 32;
+ MY(gravity) = 1;
+ MY(liquidfriction) = 6;
+ MY(originjitter) = '10.0 10.0 25.0';
+ MY(size_min) = 15;
+ MY(size_max) = 20;
+ MY(staincolor_min) = "0x808080";
+ MY(staincolor_max) = "0x808080";
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(tex_max) = 8;
+ MY(type) = "blood";
+ MY(velocityjitter) = '256.0 256.0 312.0';
+}
+// core decal
+SUB(particlegibs_damage_dissolve) {
+ MY(airfriction) = 2;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 528;
+ MY(bounce) = -1;
+ MY(color_min) = "0xA8FFFF";
+ MY(color_max) = "0xA8FFFFF";
+ MY(count) = 12;
+ MY(gravity) = 2;
+ MY(liquidfriction) = 6;
+ MY(originjitter) = '10.0 10.0 25.0';
+ MY(size_min) = 20;
+ MY(size_max) = 40;
+ MY(staincolor_min) = "0x808080";
+ MY(staincolor_max) = "0x808080";
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(tex_max) = 8;
+ MY(type) = "blood";
+ MY(velocityjitter) = '356.0 356.0 412.0';
+}
+// front blood
+SUB(particlegibs_damage_dissolve) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 328;
+ MY(bounce) = -1;
+ MY(color_min) = "0xA8FFFF";
+ MY(color_max) = "0xA8FFFFF";
+ MY(count) = 32;
+ MY(gravity) = 0.500000;
+ MY(liquidfriction) = 3;
+ MY(originjitter) = '5.0 5.0 10.0';
+ MY(sizeincrease) = -15;
+ MY(size_min) = 10;
+ MY(size_max) = 20;
+ MY(staincolor_min) = "0x808080";
+ MY(staincolor_max) = "0x808080";
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(type) = "blood";
+ MY(velocityjitter) = '56.0 56.0 212.0';
+ MY(velocitymultiplier) = -0.300000;
+}
+// back blood
+SUB(particlegibs_damage_dissolve) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 328;
+ MY(bounce) = -1;
+ MY(color_min) = "0xA8FFFF";
+ MY(color_max) = "0xA8FFFFF";
+ MY(count) = 32;
+ MY(gravity) = 1;
+ MY(liquidfriction) = 3;
+ MY(originjitter) = '5.0 5.0 10.0';
+ MY(sizeincrease) = 10;
+ MY(size_min) = 5;
+ MY(size_max) = 15;
+ MY(staincolor_min) = "0x808080";
+ MY(staincolor_max) = "0x808080";
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(type) = "blood";
+ MY(velocityjitter) = '56.0 56.0 212.0';
+ MY(velocitymultiplier) = 0.500000;
+}
+// small bits
+SUB(particlegibs_damage_dissolve) {
+ MY(airfriction) = 1.500000;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 328;
+ MY(color_min) = "0xA8FFFF";
+ MY(color_max) = "0xA8FFFFF";
+ MY(count) = 75;
+ MY(gravity) = 1;
+ MY(liquidfriction) = 3;
+ MY(originjitter) = '10.0 10.0 25.0';
+ MY(sizeincrease) = 10;
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(staincolor_min) = "0x808080";
+ MY(staincolor_max) = "0x808080";
+ MY(staintex_min) = 16;
+ MY(staintex_max) = 24;
+ MY(tex_min) = 24;
+ MY(tex_max) = 32;
+ MY(type) = "blood";
+ MY(velocityjitter) = '656.0 656.0 912.0';
+}
--- /dev/null
+#define rocketminsta_laser(name, color) \
+ DEF(rocketminsta_laser_##name); \
+ SUB(rocketminsta_laser_##name) { \
+ MY(alpha_min) = 256; \
+ MY(alpha_max) = 256; \
+ MY(alpha_fade) = 968; \
+ MY(color_min) = color; \
+ MY(color_max) = color; \
+ MY(lightcolor) = '1.5 3.0 6.0'; \
+ MY(lightradius) = 90; \
+ MY(size_min) = 3; \
+ MY(size_max) = 3; \
+ MY(tex_min) = 38; \
+ MY(tex_max) = 38; \
+ MY(trailspacing) = 2; \
+ MY(type) = "static"; \
+ MY(velocitymultiplier) = -0.100000; \
+ } \
+ SUB(rocketminsta_laser_##name) /* bright sparks */ { \
+ MY(airfriction) = 12; \
+ MY(alpha_min) = 444; \
+ MY(alpha_max) = 512; \
+ MY(alpha_fade) = 1866; \
+ MY(bounce) = 1; \
+ MY(color_min) = color; \
+ MY(color_max) = color; \
+ MY(count) = 1.500000; \
+ MY(originjitter) = '1.0 1.0 1.0'; \
+ MY(sizeincrease) = -20; \
+ MY(size_min) = 2; \
+ MY(size_max) = 4; \
+ MY(tex_min) = 42; \
+ MY(tex_max) = 42; \
+ MY(trailspacing) = 12; \
+ MY(type) = "snow"; \
+ MY(velocityjitter) = '50.0 50.0 50.0'; \
+ MY(velocityoffset) = '0.0 0.0 15.0'; \
+ } \
+ /**/
+
+rocketminsta_laser(red, "0xFF0F0F")
+rocketminsta_laser(blue, "0x0F0FFF")
+rocketminsta_laser(yellow, "0xFFFF0F")
+rocketminsta_laser(pink, "0xFF0FFF")
+rocketminsta_laser(neutral, "0xFFFFFF")
+#undef rocketminsta_laser
--- /dev/null
+#define nade(name, colormin1, colormax1, colormin2, colormax2) \
+ DEF(nade_##name); \
+ SUB(nade_##name) { \
+ MY(alpha_min) = 100; \
+ MY(alpha_max) = 100; \
+ MY(alpha_fade) = 250; \
+ MY(color_min) = colormin1; \
+ MY(color_max) = colormax1; \
+ MY(sizeincrease) = -1; \
+ MY(size_min) = 3; \
+ MY(size_max) = 3; \
+ MY(tex_min) = 65; \
+ MY(tex_max) = 65; \
+ MY(trailspacing) = 1; \
+ MY(type) = "smoke"; \
+ } \
+ SUB(nade_##name) /* fire */ { \
+ MY(alpha_min) = 30; \
+ MY(alpha_max) = 30; \
+ MY(alpha_fade) = 150; \
+ MY(color_min) = colormin2; \
+ MY(color_max) = colormax2; \
+ MY(notunderwater) = true; \
+ MY(sizeincrease) = -10; \
+ MY(size_min) = 15; \
+ MY(size_max) = 25; \
+ MY(tex_min) = 65; \
+ MY(tex_max) = 65; \
+ MY(trailspacing) = 8; \
+ MY(type) = "smoke"; \
+ } \
+ SUB(nade_##name) /* bubbles */ { \
+ MY(alpha_min) = 256; \
+ MY(alpha_max) = 256; \
+ MY(alpha_fade) = 256; \
+ MY(bounce) = 1.500000; \
+ MY(color_min) = colormin1; \
+ MY(color_max) = colormax1; \
+ MY(gravity) = -0.125000; \
+ MY(liquidfriction) = 4; \
+ MY(size_min) = 1; \
+ MY(size_max) = 1; \
+ MY(tex_min) = 62; \
+ MY(tex_max) = 62; \
+ MY(trailspacing) = 16; \
+ MY(type) = "bubble"; \
+ MY(underwater) = true; \
+ MY(velocityjitter) = '16.0 16.0 16.0'; \
+ } \
+ /**/
+
+nade(blue, "0x006cff", "0x0600ff", "0x0600ff", "0x9794ff")
+nade(red, "0xff0000", "0xff3c00", "0xff0000", "0xffa2a2")
+nade(yellow, "0xFFFF0F", "0xFFFF0F", "0xFFFF0F", "0xFFFF0F")
+nade(pink, "0xFF0FFF", "0xFF0FFF", "0xFF0FFF", "0xFF0FFF")
+nade(neutral, "0xFFFFFF", "0xFFFFFF", "0xFFFFFF", "0xFFFFFF")
+#undef nade
+
+#define nade_burn(name, colormin1, colormax1, colormin2, colormax2) \
+ DEF(nade_##name##_burn); \
+ SUB(nade_##name##_burn) { \
+ MY(alpha_min) = 100; \
+ MY(alpha_max) = 100; \
+ MY(alpha_fade) = 250; \
+ MY(color_min) = colormin1; \
+ MY(color_max) = colormax1; \
+ MY(sizeincrease) = -1; \
+ MY(size_min) = 5; \
+ MY(size_max) = 5; \
+ MY(tex_min) = 65; \
+ MY(tex_max) = 65; \
+ MY(trailspacing) = 1; \
+ MY(type) = "smoke"; \
+ } \
+ SUB(nade_##name##_burn) /* fire */ { \
+ MY(alpha_min) = 200; \
+ MY(alpha_max) = 200; \
+ MY(alpha_fade) = 1000; \
+ MY(color_min) = colormin2; \
+ MY(color_max) = colormax2; \
+ MY(notunderwater) = true; \
+ MY(sizeincrease) = -30; \
+ MY(size_min) = 45; \
+ MY(size_max) = 25; \
+ MY(tex_min) = 65; \
+ MY(tex_max) = 65; \
+ MY(trailspacing) = 64; \
+ MY(type) = "smoke"; \
+ } \
+ SUB(nade_##name##_burn) /* bubbles */ { \
+ MY(alpha_min) = 256; \
+ MY(alpha_max) = 256; \
+ MY(alpha_fade) = 256; \
+ MY(bounce) = 1.500000; \
+ MY(color_min) = colormin1; \
+ MY(color_max) = colormax1; \
+ MY(gravity) = -0.125000; \
+ MY(liquidfriction) = 4; \
+ MY(size_min) = 1; \
+ MY(size_max) = 1; \
+ MY(tex_min) = 62; \
+ MY(tex_max) = 62; \
+ MY(trailspacing) = 16; \
+ MY(type) = "bubble"; \
+ MY(underwater) = true; \
+ MY(velocityjitter) = '16.0 16.0 16.0'; \
+ } \
+ SUB(nade_##name##_burn) { \
+ MY(alpha_min) = 300; \
+ MY(alpha_max) = 900; \
+ MY(alpha_fade) = 1500; \
+ MY(color_min) = colormin1; \
+ MY(color_max) = colormax1; \
+ MY(originjitter) = '2.0 2.0 2.0'; \
+ MY(startangle_min) = -180; \
+ MY(startangle_max) = 180; \
+ MY(spin_min) = 20; \
+ MY(spin_max) = -20; \
+ MY(sizeincrease) = -40; \
+ MY(size_min) = 15; \
+ MY(size_max) = 25; \
+ MY(tex_min) = 71; \
+ MY(tex_max) = 73; \
+ MY(trailspacing) = 16; \
+ MY(type) = "smoke"; \
+ MY(velocityjitter) = '10.0 10.0 10.0'; \
+ } \
+ /**/
+
+nade_burn(red, "0xff0000", "0xff3c00", "0xff0000", "0xffa2a2")
+nade_burn(blue, "0x006cff", "0x0600ff", "0x0600ff", "0x9794ff")
+nade_burn(yellow, "0xFFFF0F", "0xFFFF0F", "0xFFFF0F", "0xFFFF0F")
+nade_burn(pink, "0xFF0FFF", "0xFF0FFF", "0xFF0FFF", "0xFF0FFF")
+nade_burn(neutral, "0xFFFFFF", "0xFFFFFF", "0xFFFFFF", "0xFFFFFF")
+#undef nade_burn
+
+#define nade_explode(name, colorlight, colormin1, colormax1, colormin2, colormax2, colormin3, colormax3) \
+ DEF(nade_##name##_explode); \
+ SUB(nade_##name##_explode) { \
+ MY(alpha_min) = 256; \
+ MY(alpha_max) = 256; \
+ MY(countabsolute) = 1; \
+ MY(lightcolor) = colorlight; \
+ MY(lightradiusfade) = 1500; \
+ MY(lightradius) = 300; \
+ MY(originjitter) = '26.0 26.0 26.0'; \
+ MY(size_min) = 88; \
+ MY(size_max) = 88; \
+ MY(tex_min) = 8; \
+ MY(tex_max) = 16; \
+ MY(type) = "decal"; \
+ } \
+ SUB(nade_##name##_explode) /* shockwave */ { \
+ MY(alpha_min) = 80; \
+ MY(alpha_max) = 80; \
+ MY(alpha_fade) = 650; \
+ MY(color_min) = colormin1; \
+ MY(color_max) = colormax1; \
+ MY(countabsolute) = 1; \
+ MY(sizeincrease) = 1800; \
+ MY(size_min) = 32; \
+ MY(size_max) = 32; \
+ MY(tex_min) = 33; \
+ MY(tex_max) = 33; \
+ MY(type) = "smoke"; \
+ MY(velocitymultiplier) = 44; \
+ } \
+ SUB(nade_##name##_explode) /* fire */ { \
+ MY(airfriction) = 30; \
+ MY(alpha_min) = 400; \
+ MY(alpha_max) = 656; \
+ MY(alpha_fade) = 2000; \
+ MY(color_min) = colormin2; \
+ MY(color_max) = colormax2; \
+ MY(count) = 16; \
+ MY(notunderwater) = true; \
+ MY(originjitter) = '50.0 50.0 50.0'; \
+ MY(startangle_min) = -180; \
+ MY(startangle_max) = 180; \
+ MY(spin_min) = -9; \
+ MY(spin_max) = 9; \
+ MY(sizeincrease) = 555; \
+ MY(size_min) = 20; \
+ MY(size_max) = 24; \
+ MY(tex_min) = 48; \
+ MY(tex_max) = 55; \
+ MY(type) = "smoke"; \
+ MY(velocityjitter) = '320.0 320.0 320.0'; \
+ } \
+ SUB(nade_##name##_explode) /* fire stretched */ { \
+ MY(airfriction) = -9; \
+ MY(alpha_min) = 1500; \
+ MY(alpha_max) = 3000; \
+ MY(alpha_fade) = 13000; \
+ MY(color_min) = colormin2; \
+ MY(color_max) = colormax2; \
+ MY(count) = 8; \
+ MY(sizeincrease) = 40; \
+ MY(size_min) = 60; \
+ MY(size_max) = 90; \
+ MY(stretchfactor) = 80; \
+ MY(tex_min) = 48; \
+ MY(tex_max) = 55; \
+ MY(type) = "spark"; \
+ MY(velocityjitter) = '30.0 30.0 30.0'; \
+ } \
+ SUB(nade_##name##_explode) /* smoke */ { \
+ MY(airfriction) = 0.040000; \
+ MY(alpha_min) = 128; \
+ MY(alpha_max) = 328; \
+ MY(alpha_fade) = 390; \
+ MY(blend) = "alpha"; \
+ MY(color_min) = "0x222222"; \
+ MY(color_max) = "0x000000"; \
+ MY(count) = 32; \
+ MY(gravity) = 0.400000; \
+ MY(originjitter) = '50.0 50.0 10.0'; \
+ MY(startangle_min) = -180; \
+ MY(startangle_max) = 180; \
+ MY(spin_min) = 2; \
+ MY(spin_max) = -2; \
+ MY(sizeincrease) = 50; \
+ MY(size_min) = 60; \
+ MY(size_max) = 30; \
+ MY(tex_max) = 7; \
+ MY(type) = "smoke"; \
+ MY(velocityjitter) = '200.0 200.0 200.0'; \
+ MY(velocityoffset) = '0.0 0.0 180.0'; \
+ } \
+ SUB(nade_##name##_explode) /* underwater bubbles */ { \
+ MY(alpha_min) = 128; \
+ MY(alpha_max) = 256; \
+ MY(alpha_fade) = 64; \
+ MY(bounce) = 1.500000; \
+ MY(color_min) = "0x404040"; \
+ MY(color_max) = "0x808080"; \
+ MY(count) = 32; \
+ MY(gravity) = -0.125000; \
+ MY(liquidfriction) = 0.250000; \
+ MY(originjitter) = '16.0 16.0 16.0'; \
+ MY(size_min) = 3; \
+ MY(size_max) = 6; \
+ MY(tex_min) = 62; \
+ MY(tex_max) = 62; \
+ MY(type) = "bubble"; \
+ MY(underwater) = true; \
+ MY(velocityjitter) = '196.0 196.0 196.0'; \
+ } \
+ SUB(nade_##name##_explode) /* bouncing sparks */ { \
+ MY(airfriction) = 1; \
+ MY(alpha_min) = 644; \
+ MY(alpha_max) = 956; \
+ MY(alpha_fade) = 484; \
+ MY(bounce) = 1.600000; \
+ MY(color_min) = colormin3; \
+ MY(color_max) = colormax3; \
+ MY(count) = 8; \
+ MY(gravity) = 1; \
+ MY(liquidfriction) = 0.800000; \
+ MY(notunderwater) = true; \
+ MY(originjitter) = '16.0 16.0 16.0'; \
+ MY(size_min) = 1; \
+ MY(size_max) = 2; \
+ MY(tex_min) = 40; \
+ MY(tex_max) = 40; \
+ MY(type) = "spark"; \
+ MY(velocityjitter) = '424.0 424.0 624.0'; \
+ MY(velocityoffset) = '0.0 0.0 80.0'; \
+ } \
+ SUB(nade_##name##_explode) /* notbouncing sparks */ { \
+ MY(airfriction) = 0.700000; \
+ MY(alpha_min) = 644; \
+ MY(alpha_max) = 956; \
+ MY(alpha_fade) = 684; \
+ MY(color_min) = colormin3; \
+ MY(color_max) = colormax3; \
+ MY(count) = 16; \
+ MY(gravity) = 0.500000; \
+ MY(liquidfriction) = 0.800000; \
+ MY(originjitter) = '16.0 16.0 16.0'; \
+ MY(size_min) = 1; \
+ MY(size_max) = 2; \
+ MY(tex_min) = 40; \
+ MY(tex_max) = 40; \
+ MY(type) = "spark"; \
+ MY(velocityjitter) = '424.0 424.0 624.0'; \
+ MY(velocityoffset) = '0.0 0.0 80.0'; \
+ } \
+ SUB(nade_##name##_explode) /* debris */ { \
+ MY(alpha_min) = 644; \
+ MY(alpha_max) = 956; \
+ MY(alpha_fade) = 2500; \
+ MY(color_min) = colormin3; \
+ MY(color_max) = colormax3; \
+ MY(count) = 8; \
+ MY(notunderwater) = true; \
+ MY(originjitter) = '64.0 64.0 64.0'; \
+ MY(startangle_min) = -180; \
+ MY(startangle_max) = 180; \
+ MY(spin_min) = -100; \
+ MY(spin_max) = 100; \
+ MY(size_min) = 20; \
+ MY(size_max) = 40; \
+ MY(tex_min) = 71; \
+ MY(tex_max) = 73; \
+ MY(type) = "smoke"; \
+ MY(velocityjitter) = '324.0 324.0 324.0'; \
+ } \
+ /**/
+
+nade_explode(blue, '20.0 20.0 100.0', "0x80C0FF", "0x80C0FF", "0x629dff", "0x0018ff", "0x006cff", "0x0600ff")
+nade_explode(red, '100.0 20.0 20.0', "0xff0000", "0xffa2a2", "0xff0000", "0xff4200", "0xff0000", "0xffa2a2")
+nade_explode(yellow, '100.0 20.0 20.0', "0xff0000", "0xffa2a2", "0xFFFF0F", "0xFFFF0F", "0xff0000", "0xffa2a2")
+nade_explode(pink, '100.0 20.0 20.0', "0xff0000", "0xffa2a2", "0xFF0FFF", "0xFF0FFF", "0xff0000", "0xffa2a2")
+nade_explode(neutral, '100.0 20.0 20.0', "0xff0000", "0xffa2a2", "0xFFFFFF", "0xFFFFFF", "0xff0000", "0xffa2a2")
+#undef nade_explode
--- /dev/null
+DEF(onslaught_generator_gib_explode);
+// fire effect which expands then slows
+SUB(onslaught_generator_gib_explode) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 356;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 17;
+ MY(liquidfriction) = 8;
+ MY(notunderwater) = true;
+ MY(originjitter) = '8.0 8.0 8.0';
+ MY(sizeincrease) = 45;
+ MY(size_min) = 20;
+ MY(size_max) = 26;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "static";
+ MY(velocityjitter) = '286.0 286.0 286.0';
+}
+// smoke
+SUB(onslaught_generator_gib_explode) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 500;
+ MY(alpha_fade) = 600;
+ MY(bounce) = 2;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x111111";
+ MY(count) = 6;
+ MY(gravity) = -0.300000;
+ MY(notunderwater) = true;
+ MY(sizeincrease) = 90;
+ MY(size_min) = 1;
+ MY(size_max) = 10;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '244.0 244.0 244.0';
+}
+// underwater bubbles
+SUB(onslaught_generator_gib_explode) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x808080";
+ MY(count) = 16;
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 0.250000;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '96.0 96.0 96.0';
+}
+
+DEF(onslaught_generator_gib_flame);
+// fire effect which expands then slows
+SUB(onslaught_generator_gib_flame) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 356;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 15;
+ MY(gravity) = -0.500000;
+ MY(liquidfriction) = 8;
+ MY(notunderwater) = true;
+ MY(originjitter) = '3.0 3.0 3.0';
+ MY(sizeincrease) = 25;
+ MY(size_min) = 5;
+ MY(size_max) = 10;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "static";
+ MY(velocityjitter) = '86.0 86.0 86.0';
+}
+// smoke
+SUB(onslaught_generator_gib_flame) {
+ MY(airfriction) = 5;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 500;
+ MY(alpha_fade) = 600;
+ MY(bounce) = 2;
+ MY(color_min) = "0x000000";
+ MY(color_max) = "0x111111";
+ MY(count) = 1;
+ MY(gravity) = -0.800000;
+ MY(notunderwater) = true;
+ MY(sizeincrease) = 30;
+ MY(size_min) = 10;
+ MY(size_max) = 20;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '44.0 44.0 44.0';
+}
+// underwater bubbles
+SUB(onslaught_generator_gib_flame) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x808080";
+ MY(count) = 16;
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 0.250000;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '96.0 96.0 96.0';
+}
--- /dev/null
+DEF(spiderbot_minigun_trail);
+SUB(spiderbot_minigun_trail) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 20;
+ MY(alpha_max) = 50;
+ MY(alpha_fade) = 100;
+ MY(color_min) = "0xd0d0a0";
+ MY(color_max) = "0xffffff";
+ MY(gravity) = -0.030000;
+ MY(notunderwater) = true;
+ MY(sizeincrease) = 2;
+ MY(size_min) = 1;
+ MY(size_max) = 2;
+ MY(tex_max) = 8;
+ MY(trailspacing) = 10;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '5.0 5.0 5.0';
+}
+
+DEF(spiderbot_minigun_muzzleflash);
+SUB(spiderbot_minigun_muzzleflash) {
+ MY(airfriction) = 10;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 512;
+ MY(alpha_fade) = 6280;
+ MY(color_min) = "0xff9c00";
+ MY(color_max) = "0xff8400";
+ MY(count) = 3;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = 4000;
+ MY(spin_max) = -4000;
+ MY(sizeincrease) = -100;
+ MY(size_min) = 10;
+ MY(size_max) = 15;
+ MY(stretchfactor) = 1.300000;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "spark";
+ MY(velocityjitter) = '150.0 150.0 150.0';
+ MY(velocitymultiplier) = 0.350000;
+}
+// fire
+SUB(spiderbot_minigun_muzzleflash) {
+ MY(airfriction) = 12;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 512;
+ MY(alpha_fade) = 6280;
+ MY(color_min) = "0xff9c00";
+ MY(color_max) = "0xff8400";
+ MY(count) = 6;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(sizeincrease) = -10;
+ MY(size_min) = 5;
+ MY(size_max) = 7;
+ MY(stretchfactor) = 0.800000;
+ MY(tex_min) = 8;
+ MY(tex_max) = 15;
+ MY(type) = "spark";
+ MY(velocityjitter) = '200.0 200.0 200.0';
+ MY(velocitymultiplier) = 0.200000;
+}
+SUB(spiderbot_minigun_muzzleflash) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 512;
+ MY(alpha_fade) = 6680;
+ MY(color_min) = "0xff9c00";
+ MY(color_max) = "0xff8400";
+ MY(countabsolute) = 2;
+ MY(lightcolor) = '3.0 3.0 0.0';
+ MY(lightradiusfade) = 8000;
+ MY(lightradius) = 120;
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = 4000;
+ MY(spin_max) = -4000;
+ MY(sizeincrease) = -100;
+ MY(size_min) = 32;
+ MY(size_max) = 32;
+ MY(stretchfactor) = 0.100000;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "static";
+}
+
+DEF(spiderbot_minigun_impact);
+SUB(spiderbot_minigun_impact) {
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 100;
+ MY(alpha_fade) = 1680;
+ MY(color_min) = "0xff9c00";
+ MY(color_max) = "0xf6ff00";
+ MY(countabsolute) = 1;
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = 4000;
+ MY(spin_max) = -4000;
+ MY(sizeincrease) = -100;
+ MY(size_min) = 52;
+ MY(size_max) = 52;
+ MY(stretchfactor) = 0.100000;
+ MY(tex_min) = 65;
+ MY(tex_max) = 65;
+ MY(type) = "static";
+}
+// fire
+SUB(spiderbot_minigun_impact) {
+ MY(airfriction) = 6;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 512;
+ MY(alpha_fade) = 6280;
+ MY(color_min) = "0xff9c00";
+ MY(color_max) = "0xff8400";
+ MY(count) = 7;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = 4000;
+ MY(spin_max) = -4000;
+ MY(sizeincrease) = 100;
+ MY(size_min) = 9;
+ MY(size_max) = 15;
+ MY(stretchfactor) = 3;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "spark";
+ MY(velocityjitter) = '250.0 250.0 150.0';
+ MY(velocitymultiplier) = 0.200000;
+}
+// smoke
+SUB(spiderbot_minigun_impact) {
+ MY(airfriction) = 10;
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 50;
+ MY(alpha_fade) = 190;
+ MY(color_min) = "0xd0d0a0";
+ MY(color_max) = "0xffffff";
+ MY(count) = 6;
+ MY(gravity) = 1.300000;
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(sizeincrease) = 80;
+ MY(size_min) = 10;
+ MY(size_max) = 20;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '100.0 100.0 250.0';
+ MY(velocitymultiplier) = 0.490000;
+}
+// smoke 2
+SUB(spiderbot_minigun_impact) {
+ MY(airfriction) = 6;
+ MY(alpha_min) = 25;
+ MY(alpha_max) = 51;
+ MY(alpha_fade) = 128;
+ MY(color_min) = "0xd0d0a0";
+ MY(color_max) = "0xffffff";
+ MY(count) = 7;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(sizeincrease) = 100;
+ MY(size_min) = 15;
+ MY(size_max) = 19;
+ MY(stretchfactor) = 7.600000;
+ MY(tex_max) = 8;
+ MY(type) = "spark";
+ MY(velocityjitter) = '250.0 250.0 150.0';
+ MY(velocitymultiplier) = 0.200000;
+}
+// debris
+SUB(spiderbot_minigun_impact) {
+ MY(airfriction) = 0.400000;
+ MY(alpha_min) = 644;
+ MY(alpha_max) = 756;
+ MY(alpha_fade) = 1484;
+ MY(color_min) = "0x99977D";
+ MY(color_max) = "0xFFFFFF";
+ MY(count) = 3;
+ MY(gravity) = 1.100000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -1000;
+ MY(spin_max) = 1000;
+ MY(sizeincrease) = -10;
+ MY(size_min) = 6;
+ MY(size_max) = 8;
+ MY(tex_min) = 66;
+ MY(tex_max) = 68;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '124.0 124.0 224.0';
+ MY(velocitymultiplier) = 0.150000;
+}
+// decal
+SUB(spiderbot_minigun_impact) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(size_min) = 20;
+ MY(size_max) = 25;
+ MY(tex_min) = 56;
+ MY(tex_max) = 59;
+ MY(type) = "decal";
+}
+
+DEF(spiderbot_rocket_explode);
+SUB(spiderbot_rocket_explode) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '8.0 4.0 0.0';
+ MY(lightradiusfade) = 1750;
+ MY(lightradius) = 300;
+ MY(originjitter) = '23.0 23.0 23.0';
+ MY(size_min) = 72;
+ MY(size_max) = 72;
+ MY(tex_min) = 8;
+ MY(tex_max) = 16;
+ MY(type) = "decal";
+}
+// shockwave
+SUB(spiderbot_rocket_explode) {
+ MY(alpha_min) = 56;
+ MY(alpha_max) = 56;
+ MY(alpha_fade) = 230;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 2400;
+ MY(size_min) = 22;
+ MY(size_max) = 22;
+ MY(tex_min) = 33;
+ MY(tex_max) = 33;
+ MY(type) = "static";
+}
+// glow
+SUB(spiderbot_rocket_explode) {
+ MY(alpha_min) = 156;
+ MY(alpha_max) = 156;
+ MY(alpha_fade) = 830;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 240;
+ MY(size_min) = 120;
+ MY(size_max) = 120;
+ MY(tex_min) = 64;
+ MY(tex_max) = 64;
+ MY(type) = "static";
+}
+// fire effect
+SUB(spiderbot_rocket_explode) {
+ MY(airfriction) = 8;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 812;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 32;
+ MY(liquidfriction) = 8;
+ MY(notunderwater) = true;
+ MY(originjitter) = '100.0 100.0 100.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -50;
+ MY(spin_max) = 50;
+ MY(sizeincrease) = 495;
+ MY(size_min) = 12;
+ MY(size_max) = 21;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "static";
+ MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// fire effect 2
+SUB(spiderbot_rocket_explode) {
+ MY(airfriction) = -2;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 912;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 16;
+ MY(liquidfriction) = 8;
+ MY(notunderwater) = true;
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -150;
+ MY(spin_max) = 150;
+ MY(sizeincrease) = 120;
+ MY(size_min) = 3;
+ MY(size_max) = 3;
+ MY(stretchfactor) = 10;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "spark";
+ MY(velocityjitter) = '412.0 412.0 412.0';
+}
+// fire rays
+SUB(spiderbot_rocket_explode) {
+ MY(airfriction) = -3;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1600;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 10;
+ MY(liquidfriction) = 8;
+ MY(notunderwater) = true;
+ MY(originjitter) = '40.0 40.0 40.0';
+ MY(sizeincrease) = 120;
+ MY(size_min) = 13;
+ MY(size_max) = 54;
+ MY(stretchfactor) = 10;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "spark";
+ MY(velocityjitter) = '712.0 712.0 712.0';
+}
+// smoke
+SUB(spiderbot_rocket_explode) {
+ MY(airfriction) = 3;
+ MY(alpha_min) = 300;
+ MY(alpha_max) = 650;
+ MY(alpha_fade) = 756;
+ MY(color_min) = "0x4F4B46";
+ MY(color_max) = "0x000000";
+ MY(count) = 10;
+ MY(notunderwater) = true;
+ MY(originjitter) = '100.0 100.0 100.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -20;
+ MY(spin_max) = 20;
+ MY(sizeincrease) = 280;
+ MY(size_min) = 10;
+ MY(size_max) = 15;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '200.0 200.0 200.0';
+}
+// smoke2
+SUB(spiderbot_rocket_explode) {
+ MY(airfriction) = 2;
+ MY(alpha_min) = 300;
+ MY(alpha_max) = 650;
+ MY(alpha_fade) = 556;
+ MY(color_min) = "0x4F4B46";
+ MY(color_max) = "0x000000";
+ MY(count) = 3;
+ MY(gravity) = -0.500000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '10.0 10.0 10.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -20;
+ MY(spin_max) = 20;
+ MY(sizeincrease) = 30;
+ MY(size_min) = 100;
+ MY(size_max) = 150;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '200.0 200.0 200.0';
+}
+// underwater bubbles
+SUB(spiderbot_rocket_explode) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x808080";
+ MY(count) = 32;
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 0.250000;
+ MY(originjitter) = '160.0 160.0 160.0';
+ MY(size_min) = 1;
+ MY(size_max) = 3;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '144.0 144.0 144.0';
+}
+// underwatershockwave
+SUB(spiderbot_rocket_explode) {
+ MY(alpha_min) = 40;
+ MY(alpha_max) = 40;
+ MY(alpha_fade) = 300;
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 1200;
+ MY(size_min) = 30;
+ MY(size_max) = 30;
+ MY(tex_min) = 33;
+ MY(tex_max) = 33;
+ MY(type) = "smoke";
+ MY(underwater) = true;
+}
+
+DEF(spiderbot_rocket_thrust);
+SUB(spiderbot_rocket_thrust) {
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1600;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 3;
+ MY(notunderwater) = true;
+ MY(sizeincrease) = -40;
+ MY(size_min) = 5;
+ MY(size_max) = 10;
+ MY(stretchfactor) = 0.900000;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "spark";
+ MY(velocityjitter) = '20.0 20.0 20.0';
+ MY(velocitymultiplier) = -1.400000;
+}
+SUB(spiderbot_rocket_thrust) {
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 200;
+ MY(alpha_fade) = 9000;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 4;
+ MY(notunderwater) = true;
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -500;
+ MY(spin_max) = 500;
+ MY(sizeincrease) = -3000;
+ MY(size_min) = 25;
+ MY(size_max) = 25;
+ MY(stretchfactor) = 1;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "static";
+ MY(velocityjitter) = '60.0 60.0 60.0';
+ MY(velocitymultiplier) = -1.400000;
+}
+
+DEF(spiderbot_rocket_launch);
+// long lasting smoke
+SUB(spiderbot_rocket_launch) {
+ MY(airfriction) = 0.300000;
+ MY(alpha_min) = 100;
+ MY(alpha_max) = 156;
+ MY(alpha_fade) = 60;
+ MY(color_min) = "0xFFFFFF";
+ MY(color_max) = "0xD9C4B0";
+ MY(count) = 8;
+ MY(gravity) = -0.010000;
+ MY(notunderwater) = true;
+ MY(sizeincrease) = 20;
+ MY(size_min) = 30;
+ MY(size_max) = 30;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '60.0 60.0 60.0';
+ MY(velocitymultiplier) = -0.100000;
+}
+// fast smoke
+SUB(spiderbot_rocket_launch) {
+ MY(airfriction) = 0.300000;
+ MY(alpha_min) = 100;
+ MY(alpha_max) = 156;
+ MY(alpha_fade) = 260;
+ MY(color_min) = "0xFFFFFF";
+ MY(color_max) = "0xD9C4B0";
+ MY(count) = 14;
+ MY(gravity) = -0.300000;
+ MY(notunderwater) = true;
+ MY(sizeincrease) = 20;
+ MY(size_min) = 30;
+ MY(size_max) = 30;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '160.0 160.0 60.0';
+}
+// fire
+SUB(spiderbot_rocket_launch) {
+ MY(airfriction) = 0.300000;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1960;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 14;
+ MY(notunderwater) = true;
+ MY(sizeincrease) = 40;
+ MY(size_min) = 30;
+ MY(size_max) = 30;
+ MY(stretchfactor) = 3;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "spark";
+ MY(velocityjitter) = '60.0 60.0 60.0';
+ MY(velocitymultiplier) = 0.500000;
+}
+// sparks
+SUB(spiderbot_rocket_launch) {
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1000;
+ MY(color_min) = "0xFFFFFF";
+ MY(color_max) = "0xD9C4B0";
+ MY(count) = 10;
+ MY(notunderwater) = true;
+ MY(size_min) = 1;
+ MY(size_max) = 4;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '160.0 160.0 160.0';
+ MY(velocitymultiplier) = -0.500000;
+}
+
+DEF(wakizashi_gun_impact);
+SUB(wakizashi_gun_impact) {
+ MY(airfriction) = 4;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 512;
+ MY(alpha_fade) = 1180;
+ MY(color_min) = "0xff0000";
+ MY(color_max) = "0xc03535";
+ MY(count) = 15;
+ MY(gravity) = 3;
+ MY(originjitter) = '40.0 40.0 10.0';
+ MY(size_min) = 4;
+ MY(size_max) = 7;
+ MY(stretchfactor) = 0.900000;
+ MY(tex_min) = 41;
+ MY(tex_max) = 41;
+ MY(type) = "spark";
+ MY(velocityjitter) = '350.0 350.0 550.0';
+ MY(velocityoffset) = '0.0 0.0 700.0';
+}
+SUB(wakizashi_gun_impact) {
+ MY(airfriction) = 4;
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 90;
+ MY(alpha_fade) = 150;
+ MY(color_min) = "0xd0d0a0";
+ MY(color_max) = "0xc03535";
+ MY(count) = 24;
+ MY(originjitter) = '40.0 40.0 10.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(sizeincrease) = 80;
+ MY(size_min) = 10;
+ MY(size_max) = 20;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '250.0 250.0 450.0';
+ MY(velocityoffset) = '0.0 0.0 600.0';
+}
+SUB(wakizashi_gun_impact) {
+ MY(alpha_min) = 250;
+ MY(alpha_max) = 300;
+ MY(alpha_fade) = 680;
+ MY(color_min) = "0xff0000";
+ MY(color_max) = "0xc03535";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = -180;
+ MY(size_min) = 82;
+ MY(size_max) = 82;
+ MY(tex_min) = 65;
+ MY(tex_max) = 65;
+ MY(type) = "smoke";
+}
+SUB(wakizashi_gun_impact) {
+ MY(alpha_min) = 50;
+ MY(alpha_max) = 100;
+ MY(alpha_fade) = 620;
+ MY(color_min) = "0xff0000";
+ MY(color_max) = "0xc03535";
+ MY(countabsolute) = 1;
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = 400;
+ MY(spin_max) = -400;
+ MY(sizeincrease) = 900;
+ MY(size_min) = 40;
+ MY(size_max) = 40;
+ MY(tex_min) = 33;
+ MY(tex_max) = 33;
+ MY(type) = "smoke";
+}
+SUB(wakizashi_gun_impact) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(size_min) = 14;
+ MY(size_max) = 14;
+ MY(tex_min) = 59;
+ MY(tex_max) = 59;
+ MY(type) = "decal";
+}
+
+DEF(wakizashi_gun_muzzleflash);
+SUB(wakizashi_gun_muzzleflash) {
+ MY(airfriction) = 12;
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 512;
+ MY(alpha_fade) = 6280;
+ MY(color_min) = "0xff0000";
+ MY(color_max) = "0xc03535";
+ MY(count) = 16;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(sizeincrease) = -10;
+ MY(size_min) = 5;
+ MY(size_max) = 7;
+ MY(stretchfactor) = 0.700000;
+ MY(tex_min) = 8;
+ MY(tex_max) = 15;
+ MY(type) = "spark";
+ MY(velocityjitter) = '200.0 200.0 200.0';
+ MY(velocitymultiplier) = 0.200000;
+}
+
+DEF(wakizashi_rocket_explode);
+SUB(wakizashi_rocket_explode) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '8.0 4.0 0.0';
+ MY(lightradiusfade) = 1750;
+ MY(lightradius) = 300;
+ MY(originjitter) = '23.0 23.0 23.0';
+ MY(size_min) = 72;
+ MY(size_max) = 72;
+ MY(tex_min) = 8;
+ MY(tex_max) = 16;
+ MY(type) = "decal";
+}
+// shockwave
+SUB(wakizashi_rocket_explode) {
+ MY(alpha_min) = 56;
+ MY(alpha_max) = 56;
+ MY(alpha_fade) = 230;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 2400;
+ MY(size_min) = 22;
+ MY(size_max) = 22;
+ MY(tex_min) = 33;
+ MY(tex_max) = 33;
+ MY(type) = "static";
+}
+// glow
+SUB(wakizashi_rocket_explode) {
+ MY(alpha_min) = 156;
+ MY(alpha_max) = 156;
+ MY(alpha_fade) = 830;
+ MY(color_min) = "0x8f0d00";
+ MY(color_max) = "0xff5a00";
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 240;
+ MY(size_min) = 120;
+ MY(size_max) = 120;
+ MY(tex_min) = 64;
+ MY(tex_max) = 64;
+ MY(type) = "static";
+}
+// fire effect
+SUB(wakizashi_rocket_explode) {
+ MY(airfriction) = 2;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 512;
+ MY(color_min) = "0xFFAE00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 64;
+ MY(liquidfriction) = 8;
+ MY(notunderwater) = true;
+ MY(originjitter) = '10.0 10.0 10.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -50;
+ MY(spin_max) = 50;
+ MY(sizeincrease) = 195;
+ MY(size_min) = 12;
+ MY(size_max) = 21;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "static";
+ MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// fire rays
+SUB(wakizashi_rocket_explode) {
+ MY(airfriction) = -3;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1600;
+ MY(color_min) = "0xFFEA00";
+ MY(color_max) = "0xff5a00";
+ MY(count) = 10;
+ MY(liquidfriction) = 8;
+ MY(notunderwater) = true;
+ MY(originjitter) = '40.0 40.0 40.0';
+ MY(sizeincrease) = 120;
+ MY(size_min) = 43;
+ MY(size_max) = 54;
+ MY(stretchfactor) = 10;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "spark";
+ MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// smoke
+SUB(wakizashi_rocket_explode) {
+ MY(airfriction) = 3;
+ MY(alpha_min) = 300;
+ MY(alpha_max) = 450;
+ MY(alpha_fade) = 556;
+ MY(color_min) = "0x4F4B46";
+ MY(color_max) = "0x000000";
+ MY(count) = 32;
+ MY(notunderwater) = true;
+ MY(originjitter) = '100.0 100.0 100.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -20;
+ MY(spin_max) = 20;
+ MY(sizeincrease) = 230;
+ MY(size_min) = 10;
+ MY(size_max) = 15;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '200.0 200.0 200.0';
+}
+// bouncing sparks
+SUB(wakizashi_rocket_explode) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 644;
+ MY(alpha_max) = 956;
+ MY(alpha_fade) = 884;
+ MY(color_min) = "0xffa35b";
+ MY(color_max) = "0xfff2be";
+ MY(count) = 14;
+ MY(gravity) = 1;
+ MY(liquidfriction) = 0.800000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '60.0 60.0 60.0';
+ MY(size_min) = 1;
+ MY(size_max) = 2;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '524.0 524.0 524.0';
+ MY(velocityoffset) = '0.0 0.0 170.0';
+}
+// underwater bubbles
+SUB(wakizashi_rocket_explode) {
+ MY(alpha_min) = 128;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 64;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0x404040";
+ MY(color_max) = "0x808080";
+ MY(count) = 32;
+ MY(gravity) = -0.125000;
+ MY(liquidfriction) = 0.250000;
+ MY(originjitter) = '160.0 160.0 160.0';
+ MY(size_min) = 1;
+ MY(size_max) = 3;
+ MY(tex_min) = 62;
+ MY(tex_max) = 62;
+ MY(type) = "bubble";
+ MY(underwater) = true;
+ MY(velocityjitter) = '144.0 144.0 144.0';
+}
+// underwatershockwave
+SUB(wakizashi_rocket_explode) {
+ MY(alpha_min) = 40;
+ MY(alpha_max) = 40;
+ MY(alpha_fade) = 300;
+ MY(countabsolute) = 1;
+ MY(sizeincrease) = 1200;
+ MY(size_min) = 30;
+ MY(size_max) = 30;
+ MY(tex_min) = 33;
+ MY(tex_max) = 33;
+ MY(type) = "smoke";
+ MY(underwater) = true;
+}
+
+DEF(wakizashi_rocket_thrust);
+SUB(wakizashi_rocket_thrust) {
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1600;
+ MY(color_min) = "0x00FFDD";
+ MY(color_max) = "0x6200FF";
+ MY(countabsolute) = 3;
+ MY(notunderwater) = true;
+ MY(sizeincrease) = -2;
+ MY(size_min) = 14;
+ MY(size_max) = 19;
+ MY(stretchfactor) = 1;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "spark";
+ MY(velocityjitter) = '60.0 60.0 60.0';
+ MY(velocitymultiplier) = -1.100000;
+}
+SUB(wakizashi_rocket_thrust) {
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1900;
+ MY(color_min) = "0xFFFF33";
+ MY(color_max) = "0xFFEE00";
+ MY(countabsolute) = 2;
+ MY(notunderwater) = true;
+ MY(sizeincrease) = -2;
+ MY(size_min) = 5;
+ MY(size_max) = 10;
+ MY(stretchfactor) = 3;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "spark";
+ MY(velocityjitter) = '60.0 60.0 60.0';
+ MY(velocitymultiplier) = -0.300000;
+}
+
+DEF(wakizashi_rocket_launch);
+// long lasting smoke
+SUB(wakizashi_rocket_launch) {
+ MY(airfriction) = 0.300000;
+ MY(alpha_min) = 100;
+ MY(alpha_max) = 156;
+ MY(alpha_fade) = 60;
+ MY(color_min) = "0xFFFFFF";
+ MY(color_max) = "0xD9C4B0";
+ MY(count) = 8;
+ MY(notunderwater) = true;
+ MY(sizeincrease) = 20;
+ MY(size_min) = 3;
+ MY(size_max) = 30;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '160.0 160.0 60.0';
+ MY(velocitymultiplier) = -0.100000;
+}
+// fast smoke
+SUB(wakizashi_rocket_launch) {
+ MY(airfriction) = 0.300000;
+ MY(alpha_min) = 100;
+ MY(alpha_max) = 156;
+ MY(alpha_fade) = 260;
+ MY(color_min) = "0xFFFFFF";
+ MY(color_max) = "0xD9C4B0";
+ MY(count) = 14;
+ MY(notunderwater) = true;
+ MY(sizeincrease) = 20;
+ MY(size_min) = 30;
+ MY(size_max) = 30;
+ MY(tex_max) = 8;
+ MY(type) = "smoke";
+ MY(velocityjitter) = '160.0 160.0 60.0';
+ MY(velocitymultiplier) = 0.400000;
+}
+//sparks
+SUB(wakizashi_rocket_launch) {
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 1000;
+ MY(color_min) = "0xFFFFFF";
+ MY(color_max) = "0xD9C4B0";
+ MY(count) = 10;
+ MY(notunderwater) = true;
+ MY(size_min) = 1;
+ MY(size_max) = 4;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '60.0 60.0 60.0';
+ MY(velocitymultiplier) = -1.500000;
+}
+
+DEF(wakizashi_booster_smoke);
+SUB(wakizashi_booster_smoke) {
+ MY(airfriction) = 2;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 750;
+ MY(alpha_fade) = 200;
+ MY(color_min) = "0xA69A80";
+ MY(color_max) = "0xB3B39F";
+ MY(count) = 3;
+ MY(gravity) = -0.100000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '60.0 60.0 60.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = -20;
+ MY(spin_max) = 20;
+ MY(sizeincrease) = 10;
+ MY(size_min) = 60;
+ MY(size_max) = 100;
+ MY(tex_max) = 8;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '40.0 40.0 40.0';
+}
+
+DEF(raptor_cannon_impact);
+// decal
+SUB(raptor_cannon_impact) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(size_min) = 24;
+ MY(size_max) = 24;
+ MY(tex_min) = 47;
+ MY(tex_max) = 47;
+ MY(type) = "decal";
+}
+// spark
+SUB(raptor_cannon_impact) {
+ MY(airfriction) = 0.200000;
+ MY(alpha_min) = 644;
+ MY(alpha_max) = 956;
+ MY(alpha_fade) = 784;
+ MY(color_min) = "0xD400FF";
+ MY(color_max) = "0x571863";
+ MY(count) = 6;
+ MY(gravity) = 1;
+ MY(notunderwater) = true;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(size_min) = 1;
+ MY(size_max) = 1;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '124.0 124.0 524.0';
+ MY(velocityoffset) = '0.0 0.0 150.0';
+}
+// smoke
+SUB(raptor_cannon_impact) {
+ MY(airfriction) = 2;
+ MY(alpha_min) = 428;
+ MY(alpha_max) = 428;
+ MY(alpha_fade) = 600;
+ MY(color_min) = "0x646364";
+ MY(color_max) = "0x151515";
+ MY(count) = 4;
+ MY(gravity) = 0.700000;
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(size_min) = 50;
+ MY(size_max) = 50;
+ MY(tex_max) = 7;
+ MY(type) = "alphastatic";
+ MY(velocityjitter) = '200.0 200.0 300.0';
+ MY(velocityoffset) = '0.0 0.0 340.0';
+}
+// fire
+SUB(raptor_cannon_impact) {
+ MY(airfriction) = 8;
+ MY(alpha_min) = 200;
+ MY(alpha_max) = 256;
+ MY(alpha_fade) = 812;
+ MY(bounce) = 1.500000;
+ MY(color_min) = "0xD400FF";
+ MY(color_max) = "0x571863";
+ MY(count) = 10;
+ MY(liquidfriction) = 8;
+ MY(notunderwater) = true;
+ MY(originjitter) = '8.0 8.0 8.0';
+ MY(sizeincrease) = 25;
+ MY(size_min) = 33;
+ MY(size_max) = 44;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "static";
+ MY(velocityjitter) = '312.0 312.0 312.0';
+}
+
+DEF(raptor_cannon_muzzleflash);
+SUB(raptor_cannon_muzzleflash) {
+ MY(airfriction) = 12;
+ MY(alpha_min) = 1256;
+ MY(alpha_max) = 1512;
+ MY(alpha_fade) = 56280;
+ MY(color_min) = "0xD400FF";
+ MY(color_max) = "0x571863";
+ MY(count) = 16;
+ MY(originjitter) = '2.0 2.0 2.0';
+ MY(sizeincrease) = -10;
+ MY(size_min) = 10;
+ MY(size_max) = 17;
+ MY(stretchfactor) = 0.600000;
+ MY(tex_min) = 8;
+ MY(tex_max) = 15;
+ MY(type) = "spark";
+ MY(velocityjitter) = '200.0 200.0 200.0';
+ MY(velocitymultiplier) = 0.200000;
+}
+SUB(raptor_cannon_muzzleflash) {
+ MY(alpha_min) = 6056;
+ MY(alpha_max) = 20112;
+ MY(alpha_fade) = 406280;
+ MY(color_min) = "0xD400FF";
+ MY(color_max) = "0x571863";
+ MY(countabsolute) = 1;
+ MY(lightcolor) = '3.0 0.0 6.0';
+ MY(lightradiusfade) = 6000;
+ MY(lightradius) = 150;
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(spin_min) = 4000;
+ MY(spin_max) = -4000;
+ MY(sizeincrease) = -100;
+ MY(size_min) = 32;
+ MY(size_max) = 32;
+ MY(stretchfactor) = 0.100000;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "static";
+}
+
+DEF(raptor_bomb_impact);
+// decal
+SUB(raptor_bomb_impact) {
+ MY(alpha_min) = 256;
+ MY(alpha_max) = 256;
+ MY(countabsolute) = 1;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(size_min) = 84;
+ MY(size_max) = 84;
+ MY(tex_min) = 8;
+ MY(tex_max) = 16;
+ MY(type) = "decal";
+}
+// spark vertical
+SUB(raptor_bomb_impact) {
+ MY(alpha_min) = 300;
+ MY(alpha_max) = 300;
+ MY(alpha_fade) = 600;
+ MY(color_min) = "0xff9c00";
+ MY(color_max) = "0xff3c00";
+ MY(count) = 3;
+ MY(originjitter) = '10.0 10.0 10.0';
+ MY(sizeincrease) = 50;
+ MY(size_min) = 20;
+ MY(size_max) = 40;
+ MY(stretchfactor) = 210;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "spark";
+ MY(velocityjitter) = '40.0 40.0 120.0';
+}
+// fire
+SUB(raptor_bomb_impact) {
+ MY(airfriction) = 2;
+ MY(alpha_min) = 300;
+ MY(alpha_max) = 300;
+ MY(alpha_fade) = 500;
+ MY(color_min) = "0xff9c00";
+ MY(color_max) = "0xff3c00";
+ MY(count) = 4;
+ MY(originjitter) = '10.0 10.0 10.0';
+ MY(sizeincrease) = 230;
+ MY(size_min) = 30;
+ MY(size_max) = 120;
+ MY(tex_min) = 48;
+ MY(tex_max) = 55;
+ MY(type) = "static";
+ MY(velocityjitter) = '950.0 950.0 0.0';
+}
+// smoke
+SUB(raptor_bomb_impact) {
+ MY(alpha_min) = 428;
+ MY(alpha_max) = 428;
+ MY(alpha_fade) = 600;
+ MY(blend) = "alpha";
+ MY(color_min) = "0x646364";
+ MY(color_max) = "0x151515";
+ MY(count) = 4;
+ MY(originjitter) = '30.0 30.0 10.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(size_min) = 120;
+ MY(size_max) = 180;
+ MY(stretchfactor) = 10;
+ MY(tex_max) = 7;
+ MY(type) = "spark";
+ MY(velocityjitter) = '200.0 200.0 280.0';
+ MY(velocityoffset) = '0.0 0.0 280.0';
+}
+// smoke 2
+SUB(raptor_bomb_impact) {
+ MY(airfriction) = 0.600000;
+ MY(alpha_min) = 328;
+ MY(alpha_max) = 328;
+ MY(alpha_fade) = 350;
+ MY(blend) = "alpha";
+ MY(color_min) = "0x646364";
+ MY(color_max) = "0x151515";
+ MY(count) = 4;
+ MY(gravity) = 2;
+ MY(originjitter) = '30.0 30.0 10.0';
+ MY(startangle_min) = -180;
+ MY(startangle_max) = 180;
+ MY(sizeincrease) = 60;
+ MY(size_min) = 40;
+ MY(size_max) = 100;
+ MY(tex_max) = 7;
+ MY(type) = "spark";
+ MY(velocityjitter) = '200.0 200.0 300.0';
+ MY(velocityoffset) = '0.0 0.0 580.0';
+}
+// sparks
+SUB(raptor_bomb_impact) {
+ MY(airfriction) = 0.300000;
+ MY(alpha_min) = 644;
+ MY(alpha_max) = 956;
+ MY(alpha_fade) = 984;
+ MY(color_min) = "0xffa35b";
+ MY(color_max) = "0xfff2be";
+ MY(count) = 5;
+ MY(gravity) = 1;
+ MY(notunderwater) = true;
+ MY(originjitter) = '16.0 16.0 16.0';
+ MY(size_min) = 3;
+ MY(size_max) = 5;
+ MY(stretchfactor) = 2;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '174.0 174.0 924.0';
+ MY(velocityoffset) = '0.0 0.0 350.0';
+}
+
+DEF(raptor_bomb_spread);
+SUB(raptor_bomb_spread) {
+ MY(airfriction) = 1;
+ MY(alpha_min) = 644;
+ MY(alpha_max) = 956;
+ MY(alpha_fade) = 1284;
+ MY(color_min) = "0xffa35b";
+ MY(color_max) = "0xfff2be";
+ MY(count) = 34;
+ MY(gravity) = 1;
+ MY(liquidfriction) = 0.800000;
+ MY(notunderwater) = true;
+ MY(originjitter) = '110.0 110.0 110.0';
+ MY(size_min) = 1;
+ MY(size_max) = 2;
+ MY(tex_min) = 40;
+ MY(tex_max) = 40;
+ MY(type) = "spark";
+ MY(velocityjitter) = '324.0 324.0 324.0';
+}
--- /dev/null
+// Global list of effects, networked to CSQC by ID to save bandwidth and to use client particle numbers (allows mismatching effectinfos to some degree)
+// Not too concerned about the order of this list, just keep the weapon effects together!
+
+// EFFECT(istrail, EFFECT_NAME, "effectinfo_string")
+EFFECT(0, EXPLOSION_SMALL, "explosion_small")
+EFFECT(0, EXPLOSION_MEDIUM, "explosion_medium")
+EFFECT(0, EXPLOSION_BIG, "explosion_big")
+
+EFFECT(0, SMOKE_SMALL, "smoke_small")
+EFFECT(0, SMOKE_LARGE, "smoke_large")
+
+
+
+EFFECT(0, BLASTER_IMPACT, "laser_impact")
+EFFECT(0, BLASTER_MUZZLEFLASH, "laser_muzzleflash")
+
+EFFECT(0, SHOTGUN_IMPACT, "shotgun_impact")
+EFFECT(0, SHOTGUN_MUZZLEFLASH, "shotgun_muzzleflash")
+
+EFFECT(0, ARC_BEAM, "arc_beam")
+EFFECT(0, ARC_BEAM_HEAL, "arc_beam_heal")
+EFFECT(0, ARC_BEAM_HEAL_IMPACT, "arc_beam_healimpact")
+EFFECT(0, ARC_BEAM_HEAL_IMPACT2, "healray_impact")
+EFFECT(0, ARC_LIGHTNING, "arc_lightning")
+EFFECT(0, ARC_LIGHTNING2, "electro_lightning")
+
+EFFECT(0, MACHINEGUN_IMPACT, "machinegun_impact")
+EFFECT(0, MACHINEGUN_MUZZLEFLASH, "uzi_muzzleflash")
+
+EFFECT(0, GRENADE_EXPLODE, "grenade_explode")
+EFFECT(0, GRENADE_MUZZLEFLASH, "grenadelauncher_muzzleflash")
+
+EFFECT(0, ELECTRO_BALLEXPLODE, "electro_ballexplode")
+EFFECT(0, ELECTRO_COMBO, "electro_combo")
+EFFECT(0, ELECTRO_IMPACT, "electro_impact")
+EFFECT(0, ELECTRO_MUZZLEFLASH, "electro_muzzleflash")
+
+EFFECT(0, CRYLINK_IMPACT, "crylink_impactbig")
+EFFECT(0, CRYLINK_IMPACT2, "crylink_impact")
+EFFECT(0, CRYLINK_JOINEXPLODE, "crylink_joinexplode")
+EFFECT(0, CRYLINK_MUZZLEFLASH, "crylink_muzzleflash")
+
+EFFECT(0, VORTEX_BEAM, "nex_beam")
+EFFECT(0, VORTEX_BEAM_OLD, "TE_TEI_G3")
+EFFECT(0, VORTEX_IMPACT, "nex_impact")
+EFFECT(0, VORTEX_MUZZLEFLASH, "nex_muzzleflash")
+
+EFFECT(1, VAPORIZER_RED, "TE_TEI_G3RED")
+EFFECT(1, VAPORIZER_HIT_RED, "TE_TEI_G3RED_HIT")
+EFFECT(1, VAPORIZER_BLUE, "TE_TEI_G3BLUE")
+EFFECT(1, VAPORIZER_HIT_BLUE, "TE_TEI_G3BLUE_HIT")
+EFFECT(1, VAPORIZER_YELLOW, "TE_TEI_G3YELLOW")
+EFFECT(1, VAPORIZER_HIT_YELLOW, "TE_TEI_G3YELLOW_HIT")
+EFFECT(1, VAPORIZER_PINK, "TE_TEI_G3PINK")
+EFFECT(1, VAPORIZER_HIT_PINK, "TE_TEI_G3PINK_HIT")
+EFFECT(1, VAPORIZER_NEUTRAL, "TE_TEI_G3")
+EFFECT(1, VAPORIZER_HIT_NEUTRAL, "TE_TEI_G3_HIT")
+entity EFFECT_VAPORIZER(int teamid)
+{
+ switch (teamid) {
+ case NUM_TEAM_1: return EFFECT_VAPORIZER_RED;
+ case NUM_TEAM_2: return EFFECT_VAPORIZER_BLUE;
+ case NUM_TEAM_3: return EFFECT_VAPORIZER_YELLOW;
+ case NUM_TEAM_4: return EFFECT_VAPORIZER_PINK;
+ default: return EFFECT_VAPORIZER_NEUTRAL;
+ }
+}
+entity EFFECT_VAPORIZER_HIT(int teamid)
+{
+ switch (teamid) {
+ case NUM_TEAM_1: return EFFECT_VAPORIZER_HIT_RED;
+ case NUM_TEAM_2: return EFFECT_VAPORIZER_HIT_BLUE;
+ case NUM_TEAM_3: return EFFECT_VAPORIZER_HIT_YELLOW;
+ case NUM_TEAM_4: return EFFECT_VAPORIZER_HIT_PINK;
+ default: return EFFECT_VAPORIZER_HIT_NEUTRAL;
+ }
+}
+
+EFFECT(0, RIFLE_IMPACT, "machinegun_impact")
+EFFECT(0, RIFLE_MUZZLEFLASH, "rifle_muzzleflash")
+EFFECT(1, RIFLE, "tr_rifle")
+EFFECT(1, RIFLE_WEAK, "tr_rifle_weak")
+
+EFFECT(0, HAGAR_BOUNCE, "hagar_bounce")
+EFFECT(0, HAGAR_EXPLODE, "hagar_explode")
+EFFECT(0, HAGAR_MUZZLEFLASH, "hagar_muzzleflash")
+EFFECT(1, HAGAR_ROCKET, "tr_hagar")
+
+EFFECT(0, ROCKET_EXPLODE, "rocket_explode")
+EFFECT(0, ROCKET_GUIDE, "rocket_guide")
+EFFECT(0, ROCKET_MUZZLEFLASH, "rocketlauncher_muzzleflash")
+
+EFFECT(0, HOOK_EXPLODE, "hookbomb_explode")
+EFFECT(0, HOOK_IMPACT, "grapple_impact")
+EFFECT(0, HOOK_MUZZLEFLASH, "grapple_muzzleflash")
+
+EFFECT(0, SEEKER_MUZZLEFLASH, "seeker_muzzleflash")
+
+EFFECT(0, FLAK_BOUNCE, "flak_bounce")
+
+EFFECT(1, FIREBALL, "fireball")
+EFFECT(0, FIREBALL_BFGDAMAGE, "fireball_bfgdamage")
+EFFECT(0, FIREBALL_EXPLODE, "fireball_explode")
+EFFECT(0, FIREBALL_LASER, "fireball_laser")
+EFFECT(0, FIREBALL_MUZZLEFLASH, "fireball_muzzleflash")
+EFFECT(0, FIREBALL_PRE_MUZZLEFLASH, "fireball_preattack_muzzleflash")
+
+
+
+EFFECT(0, RAPTOR_CANNON_IMPACT, "raptor_cannon_impact")
+EFFECT(0, RAPTOR_BOMB_IMPACT, "raptor_bomb_impact")
+EFFECT(0, RAPTOR_BOMB_SPREAD, "raptor_bomb_spread")
+EFFECT(0, RAPTOR_MUZZLEFLASH, "raptor_cannon_muzzleflash")
+
+EFFECT(0, RACER_BOOSTER, "wakizashi_booster_smoke")
+EFFECT(0, RACER_IMPACT, "wakizashi_gun_impact")
+EFFECT(0, RACER_MUZZLEFLASH, "wakizashi_gun_muzzleflash")
+EFFECT(0, RACER_ROCKETLAUNCH, "wakizashi_rocket_launch")
+EFFECT(0, RACER_ROCKET_EXPLODE, "wakizashi_rocket_launch")
+EFFECT(1, RACER_ROCKET_TRAIL, "wakizashi_rocket_thrust")
+
+EFFECT(0, SPIDERBOT_ROCKETLAUNCH, "spiderbot_rocket_launch")
+EFFECT(1, SPIDERBOT_ROCKET_TRAIL, "spiderbot_rocket_thrust")
+EFFECT(0, SPIDERBOT_ROCKET_EXPLODE, "spiderbot_rocket_explode")
+EFFECT(0, SPIDERBOT_MINIGUN_IMPACT, "spiderbot_minigun_impact")
+EFFECT(0, SPIDERBOT_MINIGUN_MUZZLEFLASH, "spiderbot_minigun_muzzleflash")
+
+EFFECT(0, BUMBLEBEE_HEAL_MUZZLEFLASH, "healray_muzzleflash")
+EFFECT(0, BUMBLEBEE_HEAL_IMPACT, "healray_impact")
+
+EFFECT(0, BIGPLASMA_IMPACT, "bigplasma_impact")
+EFFECT(0, BIGPLASMA_MUZZLEFLASH, "bigplasma_muzzleflash")
+
+EFFECT(0, TELEPORT, "teleport")
+
+EFFECT(0, SPAWNPOINT_RED, "spawn_point_red")
+EFFECT(0, SPAWN_RED, "spawn_event_red")
+EFFECT(0, SPAWNPOINT_BLUE, "spawn_point_blue")
+EFFECT(0, SPAWN_BLUE, "spawn_event_blue")
+EFFECT(0, SPAWNPOINT_YELLOW, "spawn_point_yellow")
+EFFECT(0, SPAWN_YELLOW, "spawn_event_yellow")
+EFFECT(0, SPAWNPOINT_PINK, "spawn_point_pink")
+EFFECT(0, SPAWN_PINK, "spawn_event_pink")
+EFFECT(0, SPAWNPOINT_NEUTRAL, "spawn_point_neutral")
+EFFECT(0, SPAWN_NEUTRAL, "spawn_event_neutral")
+
+EFFECT(0, NADE_EXPLODE_RED, "nade_red_explode")
+EFFECT(0, NADE_EXPLODE_BLUE, "nade_blue_explode")
+EFFECT(0, NADE_EXPLODE_YELLOW, "nade_yellow_explode")
+EFFECT(0, NADE_EXPLODE_PINK, "nade_pink_explode")
+EFFECT(0, NADE_EXPLODE_NEUTRAL, "nade_neutral_explode")
+entity EFFECT_NADE_EXPLODE(int teamid)
+{
+ switch (teamid) {
+ case NUM_TEAM_1: return EFFECT_NADE_EXPLODE_RED;
+ case NUM_TEAM_2: return EFFECT_NADE_EXPLODE_BLUE;
+ case NUM_TEAM_3: return EFFECT_NADE_EXPLODE_YELLOW;
+ case NUM_TEAM_4: return EFFECT_NADE_EXPLODE_PINK;
+ default: return EFFECT_NADE_EXPLODE_NEUTRAL;
+ }
+}
+
+EFFECT(1, NADE_TRAIL_RED, "nade_red")
+EFFECT(1, NADE_TRAIL_BLUE, "nade_blue")
+EFFECT(1, NADE_TRAIL_YELLOW, "nade_yellow")
+EFFECT(1, NADE_TRAIL_PINK, "nade_pink")
+EFFECT(1, NADE_TRAIL_NEUTRAL, "nade_neutral")
+entity EFFECT_NADE_TRAIL(int teamid)
+{
+ switch (teamid) {
+ case NUM_TEAM_1: return EFFECT_NADE_TRAIL_RED;
+ case NUM_TEAM_2: return EFFECT_NADE_TRAIL_BLUE;
+ case NUM_TEAM_3: return EFFECT_NADE_TRAIL_YELLOW;
+ case NUM_TEAM_4: return EFFECT_NADE_TRAIL_PINK;
+ default: return EFFECT_NADE_TRAIL_NEUTRAL;
+ }
+}
+
+EFFECT(1, NADE_TRAIL_BURN_RED, "nade_red_burn")
+EFFECT(1, NADE_TRAIL_BURN_BLUE, "nade_blue_burn")
+EFFECT(1, NADE_TRAIL_BURN_YELLOW, "nade_yellow_burn")
+EFFECT(1, NADE_TRAIL_BURN_PINK, "nade_pink_burn")
+EFFECT(1, NADE_TRAIL_BURN_NEUTRAL, "nade_neutral_burn")
+entity EFFECT_NADE_TRAIL_BURN(int teamid)
+{
+ switch (teamid) {
+ case NUM_TEAM_1: return EFFECT_NADE_TRAIL_BURN_RED;
+ case NUM_TEAM_2: return EFFECT_NADE_TRAIL_BURN_BLUE;
+ case NUM_TEAM_3: return EFFECT_NADE_TRAIL_BURN_YELLOW;
+ case NUM_TEAM_4: return EFFECT_NADE_TRAIL_BURN_PINK;
+ default: return EFFECT_NADE_TRAIL_BURN_NEUTRAL;
+ }
+}
+
+EFFECT(0, ICEORGLASS, "iceorglass")
+EFFECT(0, ICEFIELD, "icefield")
+EFFECT(0, FIREFIELD, "firefield")
+EFFECT(0, HEALING, "healing_fx")
+EFFECT(1, LASER_BEAM_FAST, "nex242_misc_laser_beam_fast")
+EFFECT(0, RESPAWN_GHOST, "respawn_ghost")
+
+EFFECT(0, FLAG_TOUCH_RED, "redflag_touch")
+EFFECT(0, FLAG_TOUCH_BLUE, "blueflag_touch")
+EFFECT(0, FLAG_TOUCH_YELLOW, "yellowflag_touch")
+EFFECT(0, FLAG_TOUCH_PINK, "pinkflag_touch")
+EFFECT(0, FLAG_TOUCH_NEUTRAL, "neutralflag_touch")
+entity EFFECT_FLAG_TOUCH(int teamid)
+{
+ switch (teamid) {
+ case NUM_TEAM_1: return EFFECT_FLAG_TOUCH_RED;
+ case NUM_TEAM_2: return EFFECT_FLAG_TOUCH_BLUE;
+ case NUM_TEAM_3: return EFFECT_FLAG_TOUCH_YELLOW;
+ case NUM_TEAM_4: return EFFECT_FLAG_TOUCH_PINK;
+ default: return EFFECT_FLAG_TOUCH_NEUTRAL;
+ }
+}
+
+EFFECT(1, PASS_RED, "red_pass")
+EFFECT(1, PASS_BLUE, "blue_pass")
+EFFECT(1, PASS_YELLOW, "yellow_pass")
+EFFECT(1, PASS_PINK, "pink_pass")
+EFFECT(1, PASS_NEUTRAL, "neutral_pass")
+
+EFFECT(0, CAP_RED, "red_cap")
+EFFECT(0, CAP_BLUE, "blue_cap")
+EFFECT(0, CAP_YELLOW, "yellow_cap")
+EFFECT(0, CAP_PINK, "pink_cap")
+EFFECT(0, CAP_NEUTRAL, "neutral_cap")
+entity EFFECT_CAP(int teamid)
+{
+ switch (teamid) {
+ case NUM_TEAM_1: return EFFECT_CAP_RED;
+ case NUM_TEAM_2: return EFFECT_CAP_BLUE;
+ case NUM_TEAM_3: return EFFECT_CAP_YELLOW;
+ case NUM_TEAM_4: return EFFECT_CAP_PINK;
+ default: return EFFECT_CAP_NEUTRAL;
+ }
+}
+
+EFFECT(0, ITEM_PICKUP, "item_pickup")
+EFFECT(0, ITEM_RESPAWN, "item_respawn")
+
+EFFECT(0, ONS_GENERATOR_DAMAGED, "torch_small")
+EFFECT(0, ONS_GENERATOR_GIB, "onslaught_generator_gib_explode")
+EFFECT(0, ONS_GENERATOR_EXPLODE, "onslaught_generator_smallexplosion")
+EFFECT(0, ONS_GENERATOR_EXPLODE2, "onslaught_generator_finalexplosion")
+
+
+
+EFFECT(0, LASER_DEADLY, "laser_deadly")
+EFFECT(1, FLAC_TRAIL, "TR_SEEKER")
+EFFECT(1, SEEKER_TRAIL, "TR_SEEKER")
+EFFECT(1, FIREMINE, "firemine")
+EFFECT(0, BALL_SPARKS, "kaball_sparks")
+EFFECT(0, ELECTRIC_SPARKS, "electricity_sparks")
+EFFECT(0, SPARKS, "sparks")
+EFFECT(0, RAGE, "rage")
+EFFECT(0, SMOKING, "smoking")
+EFFECT(0, SMOKE_RING, "smoke_ring")
+EFFECT(0, JUMPPAD, "jumppad_activate")
+EFFECT(1, BULLET, "tr_bullet")
+EFFECT(0, EF_FLAME, "EF_FLAME")
+EFFECT(0, EF_STARDUST, "EF_STARDUST")
+EFFECT(0, TE_EXPLOSION, "TE_EXPLOSION")
+EFFECT(1, TR_NEXUIZPLASMA, "TR_NEXUIZPLASMA")
+EFFECT(1, TR_CRYLINKPLASMA, "TR_CRYLINKPLASMA")
+EFFECT(1, TR_ROCKET, "TR_ROCKET")
+EFFECT(1, TR_GRENADE, "TR_GRENADE")
+EFFECT(1, TR_BLOOD, "TR_BLOOD")
+EFFECT(1, TR_WIZSPIKE, "TR_WIZSPIKE")
+EFFECT(1, TR_SLIGHTBLOOD, "TR_SLIGHTBLOOD")
+EFFECT(1, TR_KNIGHTSPIKE, "TR_KNIGHTSPIKE")
+EFFECT(1, TR_VORESPIKE, "TR_VORESPIKE")
+EFFECT(0, TE_SPARK, "TE_SPARK")
+
+EFFECT(1, ROCKETMINSTA_LASER_RED, "rocketminsta_laser_red")
+EFFECT(1, ROCKETMINSTA_LASER_BLUE, "rocketminsta_laser_blue")
+EFFECT(1, ROCKETMINSTA_LASER_YELLOW, "rocketminsta_laser_yellow")
+EFFECT(1, ROCKETMINSTA_LASER_PINK, "rocketminsta_laser_pink")
+EFFECT(1, ROCKETMINSTA_LASER_NEUTRAL, "rocketminsta_laser_neutral")
+entity EFFECT_ROCKETMINSTA_LASER(int teamid)
+{
+ entity e;
+ switch (teamid) {
+ case NUM_TEAM_1: e = EFFECT_ROCKETMINSTA_LASER_RED; break;
+ case NUM_TEAM_2: e = EFFECT_ROCKETMINSTA_LASER_BLUE; break;
+ case NUM_TEAM_3: e = EFFECT_ROCKETMINSTA_LASER_YELLOW; break;
+ case NUM_TEAM_4: e = EFFECT_ROCKETMINSTA_LASER_PINK; break;
+ default: e = EFFECT_ROCKETMINSTA_LASER_NEUTRAL; break;
+ }
+ if (particleeffectnum(e) < 0 || Team_TeamToNumber(teamid) == -1) { e = EFFECT_TR_NEXUIZPLASMA; }
+ return e;
+}
--- /dev/null
+#ifdef CSQC
+void Read_Effect(bool is_new)
+{
+ int net_name = (Effects_COUNT >= 255) ? ReadShort() : ReadByte();
+
+ entity eff = Effects[net_name];
+
+ vector v, vel = '0 0 0';
+ int eff_cnt = 1;
+ bool eff_trail = eff.eent_eff_trail;
+ v_x = ReadCoord();
+ v_y = ReadCoord();
+ v_z = ReadCoord();
+
+ bool use_vel = ReadByte();
+ if(use_vel)
+ {
+ vel_x = ReadCoord();
+ vel_y = ReadCoord();
+ vel_z = ReadCoord();
+ }
+
+ if(!eff_trail)
+ eff_cnt = ReadByte();
+
+ if(is_new)
+ {
+ if(eff_trail)
+ WarpZone_TrailParticles(world, particleeffectnum(eff), v, vel);
+ else
+ pointparticles(particleeffectnum(eff), v, vel, eff_cnt);
+ }
+}
+#endif
+
+#ifdef SVQC
+bool Net_Write_Effect(entity this, entity client, int sf)
+{
+ WriteByte(MSG_ENTITY, ENT_CLIENT_EFFECT);
+ (Effects_COUNT >= 255)
+ ? WriteShort(MSG_ENTITY, self.m_id)
+ : WriteByte(MSG_ENTITY, self.m_id);
+ WriteCoord(MSG_ENTITY, self.eent_net_location_x);
+ WriteCoord(MSG_ENTITY, self.eent_net_location_y);
+ WriteCoord(MSG_ENTITY, self.eent_net_location_z);
+
+ // attempt to save a tiny bit more bandwidth by not sending velocity if it isn't set
+ if(self.eent_net_velocity)
+ {
+ WriteByte(MSG_ENTITY, true);
+ WriteCoord(MSG_ENTITY, self.eent_net_velocity_x);
+ WriteCoord(MSG_ENTITY, self.eent_net_velocity_y);
+ WriteCoord(MSG_ENTITY, self.eent_net_velocity_z);
+ }
+ else { WriteByte(MSG_ENTITY, false); }
+
+ if(!self.eent_eff_trail) { WriteByte(MSG_ENTITY, self.eent_net_count); }
+ return true;
+}
+
+void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt)
+{
+ if(!eff) { return; }
+ if(!eff.eent_eff_trail && !eff_cnt) { return; } // effect has no count!
+ entity net_eff = spawn();
+ net_eff.owner = eff;
+ net_eff.classname = "net_effect";
+ //net_eff.eent_broadcast = broadcast;
+ net_eff.m_id = eff.m_id;
+ net_eff.eent_net_velocity = eff_vel;
+ net_eff.eent_net_location = eff_loc;
+ net_eff.eent_net_count = eff_cnt;
+ net_eff.eent_eff_trail = eff.eent_eff_trail;
+
+ net_eff.think = SUB_Remove;
+ net_eff.nextthink = time + 0.2; // don't need to keep this long
+
+ Net_LinkEntity(net_eff, false, 0, Net_Write_Effect);
+}
+
+void Send_Effect_(string eff_name, vector eff_loc, vector eff_vel, int eff_cnt)
+{
+ // problem with this is, we might not have all the available effects for it
+ FOREACH(Effects, it.eent_eff_name == eff_name, LAMBDA(
+ Send_Effect(it, eff_loc, eff_vel, eff_cnt);
+ return;
+ ));
+ // revert to engine handling
+ pointparticles(_particleeffectnum(eff_name), eff_loc, eff_vel, eff_cnt);
+}
+#endif
--- /dev/null
+#ifndef P_EFFECTS_H
+#define P_EFFECTS_H
+
+#ifdef CSQC
+void Read_Effect(bool is_new);
+#elif defined(SVQC)
+void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt);
+void Send_Effect_(string eff_name, vector eff_loc, vector eff_vel, int eff_cnt);
+#endif
+
+#define particleeffectnum(e) _particleeffectnum(e.eent_eff_name)
+
+REGISTRY(Effects, BIT(8))
+REGISTER_REGISTRY(RegisterEffects)
+#define EFFECT(istrail, name, realname) \
+ REGISTER(RegisterEffects, EFFECT, Effects, name, m_id, Create_Effect_Entity(realname, istrail));
+
+.int m_id;
+.string eent_eff_name;
+.int eent_eff_trail;
+
+.vector eent_net_location;
+.vector eent_net_velocity;
+.int eent_net_count;
+
+entity Create_Effect_Entity(string eff_name, bool eff_trail)
+{
+ entity this = new(effect_entity);
+ this.eent_eff_name = eff_name;
+ this.eent_eff_trail = eff_trail;
+ return this;
+}
+
+void RegisterEffects_First()
+{
+ #ifdef SVQC
+ #define dedi (server_is_dedicated ? "a dedicated " : "")
+ #else
+ #define dedi ""
+ #endif
+
+ LOG_TRACEF("Beginning effect initialization on %s%s program...\n", dedi, PROGNAME);
+ #undef dedi
+}
+
+void RegisterEffects_Done()
+{
+ LOG_TRACE("Effects initialization successful!\n");
+}
+
+// NOW we actually activate the declarations
+ACCUMULATE_FUNCTION(RegisterEffects, RegisterEffects_First)
+EFFECT(0, Null, string_null)
+#include "effects.inc"
+ACCUMULATE_FUNCTION(RegisterEffects, RegisterEffects_Done)
+
+#endif
void Dump_Items()
{
- FOREACH(ITEMS, true, LAMBDA(
+ FOREACH(Items, true, LAMBDA(
ITEM_HANDLE(Show, it);
));
}
+string Item_Model(string item_mdl)
+{
+ string output = strcat("models/items/", item_mdl);
+#ifdef SVQC
+ MUTATOR_CALLHOOK(ItemModel, item_mdl, output);
+ output = item_model_output;
+#endif
+ return output;
+}
+
#endif
#ifndef ITEMS_ALL_H
#define ITEMS_ALL_H
-void RegisterItems();
-const int MAX_ITEMS = 24;
-entity ITEMS[MAX_ITEMS], ITEMS_first, ITEMS_last;
-int ITEM_COUNT;
-/** If you register a new item, make sure to add it to all.inc */
-#define REGISTER_ITEM(id, class) REGISTER(RegisterItems, ITEM, ITEMS, ITEM_COUNT, id, m_id, NEW(class))
+#include "item.qh"
+
+REGISTRY(Items, BIT(5))
REGISTER_REGISTRY(RegisterItems)
+/** If you register a new item, make sure to add it to all.inc */
+#define REGISTER_ITEM(id, class) REGISTER(RegisterItems, ITEM, Items, id, m_id, NEW(class))
void Dump_Items();
+#ifndef MENUQC
+string Item_Model(string item_mdl);
+#endif
+
#endif
#include "inventory.qh"
entityclass(Inventory);
/** Stores counts of items, the id being the index */
-class(Inventory) .int inv_items[MAX_ITEMS];
+class(Inventory) .int inv_items[Items_MAX];
/** Player inventory; Inventories also have one inventory for storing the previous state */
.Inventory inventory;
void Inventory_Read(Inventory data)
{
const int bits = ReadInt24_t();
- FOREACH(ITEMS, bits & BIT(i), LAMBDA(
- .int fld = inv_items[i];
+ FOREACH(Items, bits & BIT(it.m_id), LAMBDA(
+ .int fld = inv_items[it.m_id];
int prev = data.(fld);
int next = data.(fld) = ReadByte();
- LOG_TRACEF("%s: %.0f -> %.0f\n", ITEMS[i].m_name, prev, next);
+ LOG_TRACEF("%s: %.0f -> %.0f\n", it.m_name, prev, next);
));
}
#endif
void Inventory_Write(Inventory data)
{
int bits = 0;
- FOREACH(ITEMS, true, LAMBDA(
- .int fld = inv_items[i];
- bits = BITSET(bits, BIT(i), data.inventory.(fld) != (data.inventory.(fld) = data.(fld)));
+ FOREACH(Items, true, LAMBDA(
+ .int fld = inv_items[it.m_id];
+ bits = BITSET(bits, BIT(it.m_id), data.inventory.(fld) != (data.inventory.(fld) = data.(fld)));
));
WriteInt24_t(MSG_ENTITY, bits);
- FOREACH(ITEMS, bits & BIT(i), LAMBDA(
- WriteByte(MSG_ENTITY, data.inv_items[i]);
+ FOREACH(Items, bits & BIT(it.m_id), LAMBDA(
+ WriteByte(MSG_ENTITY, data.inv_items[it.m_id]);
));
}
#endif
#ifdef SVQC
-bool Inventory_Send(entity to, int sf)
+bool Inventory_Send(entity this, entity to, int sf)
{
WriteByte(MSG_ENTITY, ENT_CLIENT_INVENTORY);
entity e = self.owner;
#include "../../../server/t_items.qh"
#endif
+#ifndef MENUQC
+MODEL(Bullets_ITEM, Item_Model("a_bullets.mdl"));
+#endif
+
REGISTER_ITEM(Bullets, Ammo) {
- this.m_model = "a_bullets.mdl";
+#ifndef MENUQC
+ this.m_model = MDL_Bullets_ITEM;
+#endif
this.m_name = "bullets";
this.m_icon = "ammo_bullets";
#ifdef SVQC
this.m_itemid = IT_NAILS;
#endif
}
+
+#ifndef MENUQC
+MODEL(Cells_ITEM, Item_Model("a_cells.md3"));
+#endif
+
REGISTER_ITEM(Cells, Ammo) {
- this.m_model = "a_cells.md3";
+#ifndef MENUQC
+ this.m_model = MDL_Cells_ITEM;
+#endif
this.m_name = "cells";
this.m_icon = "ammo_cells";
#ifdef SVQC
this.m_itemid = IT_CELLS;
#endif
}
+
+#ifndef MENUQC
+MODEL(Plasma_ITEM, Item_Model("a_cells.md3"));
+#endif
+
REGISTER_ITEM(Plasma, Ammo) {
- this.m_model = "a_cells.md3";
+#ifndef MENUQC
+ this.m_model = MDL_Plasma_ITEM;
+#endif
this.m_name = "plasma";
this.m_icon = "ammo_plasma";
#ifdef SVQC
this.m_itemid = IT_PLASMA;
#endif
}
+
+#ifndef MENUQC
+MODEL(Rockets_ITEM, Item_Model("a_rockets.md3"));
+#endif
+
REGISTER_ITEM(Rockets, Ammo) {
- this.m_model = "a_rockets.md3";
+#ifndef MENUQC
+ this.m_model = MDL_Rockets_ITEM;
+#endif
this.m_name = "rockets";
this.m_icon = "ammo_rockets";
#ifdef SVQC
this.m_itemid = IT_ROCKETS;
#endif
}
+
+#ifndef MENUQC
+MODEL(Shells_ITEM, Item_Model("a_shells.md3"));
+#endif
+
REGISTER_ITEM(Shells, Ammo) {
- this.m_model = "a_shells.md3";
+#ifndef MENUQC
+ this.m_model = MDL_Shells_ITEM;
+#endif
this.m_name = "shells";
this.m_icon = "ammo_shells";
#ifdef SVQC
#include "../../../server/t_items.qh"
#endif
+#ifndef MENUQC
+MODEL(ArmorSmall_ITEM, Item_Model("item_armor_small.md3"));
+#endif
+
REGISTER_ITEM(ArmorSmall, Armor) {
- this.m_model = "item_armor_small.md3";
+#ifndef MENUQC
+ this.m_model = MDL_ArmorSmall_ITEM;
+#endif
this.m_sound = "misc/armor1.wav";
this.m_name = "5 Armor";
this.m_icon = "armor";
#endif
}
+#ifndef MENUQC
+MODEL(ArmorMedium_ITEM, Item_Model("item_armor_medium.md3"));
+#endif
+
REGISTER_ITEM(ArmorMedium, Armor) {
- this.m_model = "item_armor_medium.md3";
+#ifndef MENUQC
+ this.m_model = MDL_ArmorMedium_ITEM;
+#endif
this.m_sound = "misc/armor10.wav";
this.m_name = "25 Armor";
this.m_icon = "armor";
#endif
}
+#ifndef MENUQC
+MODEL(ArmorLarge_ITEM, Item_Model("item_armor_big.md3"));
+#endif
+
REGISTER_ITEM(ArmorLarge, Armor) {
- this.m_model = "item_armor_big.md3";
+#ifndef MENUQC
+ this.m_model = MDL_ArmorLarge_ITEM;
+#endif
this.m_sound = "misc/armor17_5.wav";
this.m_name = "50 Armor";
this.m_icon = "armor";
#endif
}
+#ifndef MENUQC
+MODEL(ArmorMega_ITEM, Item_Model("item_armor_large.md3"));
+#endif
+
REGISTER_ITEM(ArmorMega, Armor) {
- this.m_model = "item_armor_large.md3";
+#ifndef MENUQC
+ this.m_model = MDL_ArmorMega_ITEM;
+#endif
this.m_sound = "misc/armor25.wav";
this.m_name = "100 Armor";
this.m_icon = "item_large_armor";
#include "../../../server/t_items.qh"
#endif
+#ifndef MENUQC
+MODEL(HealthSmall_ITEM, Item_Model("g_h1.md3"));
+#endif
+
REGISTER_ITEM(HealthSmall, Health) {
- this.m_model = "g_h1.md3";
+#ifndef MENUQC
+ this.m_model = MDL_HealthSmall_ITEM;
+#endif
this.m_sound = "misc/minihealth.wav";
this.m_name = "5 Health";
this.m_icon = "health";
#endif
}
+#ifndef MENUQC
+MODEL(HealthMedium_ITEM, Item_Model("g_h25.md3"));
+#endif
+
REGISTER_ITEM(HealthMedium, Health) {
- this.m_model = "g_h25.md3";
+#ifndef MENUQC
+ this.m_model = MDL_HealthMedium_ITEM;
+#endif
this.m_sound = "misc/mediumhealth.wav";
this.m_name = "25 Health";
this.m_icon = "health";
#endif
}
+#ifndef MENUQC
+MODEL(HealthLarge_ITEM, Item_Model("g_h50.md3"));
+#endif
+
REGISTER_ITEM(HealthLarge, Health) {
- this.m_model = "g_h50.md3";
+#ifndef MENUQC
+ this.m_model = MDL_HealthLarge_ITEM;
+#endif
this.m_sound = "misc/mediumhealth.wav";
this.m_name = "50 Health";
this.m_icon = "health";
#endif
}
+#ifndef MENUQC
+MODEL(HealthMega_ITEM, Item_Model("g_h100.md3"));
+#endif
+
REGISTER_ITEM(HealthMega, Health) {
- this.m_model = "g_h100.md3";
+#ifndef MENUQC
+ this.m_model = MDL_HealthMega_ITEM;
+#endif
this.m_sound = "misc/megahealth.wav";
this.m_name = "100 Health";
this.m_icon = "item_mega_health";
#include "ammo.qh"
#include "powerup.qh"
+#ifndef MENUQC
+MODEL(Jetpack_ITEM, Item_Model("g_jetpack.md3"));
+#endif
+
REGISTER_ITEM(Jetpack, Powerup) {
- this.m_model = "g_jetpack.md3";
+#ifndef MENUQC
+ this.m_model = MDL_Jetpack_ITEM;
+#endif
this.m_name = "Jet pack";
this.m_icon = "jetpack";
this.m_color = '0.5 0.5 0.5';
#endif
}
+#ifndef MENUQC
+MODEL(JetpackFuel_ITEM, Item_Model("g_fuel.md3"));
+#endif
+
REGISTER_ITEM(JetpackFuel, Ammo) {
- this.m_model = "g_fuel.md3";
+#ifndef MENUQC
+ this.m_model = MDL_JetpackFuel_ITEM;
+#endif
this.m_name = "Fuel";
this.m_icon = "ammo_fuel";
#ifdef SVQC
#endif
}
+#ifndef MENUQC
+MODEL(JetpackRegen_ITEM, Item_Model("g_fuelregen.md3"));
+#endif
+
REGISTER_ITEM(JetpackRegen, Pickup) {
- this.m_model = "g_fuelregen.md3";
+#ifndef MENUQC
+ this.m_model = MDL_JetpackRegen_ITEM;
+#endif
this.m_name = "Fuel regenerator";
this.m_icon = "fuelregen";
this.m_color = '1 0.5 0';
#define PICKUP_H
#include "../item.qh"
CLASS(Pickup, GameItem)
- ATTRIB(Pickup, m_model, string, string_null)
+#ifndef MENUQC
+ ATTRIB(Pickup, m_model, Model, NULL)
+#endif
ATTRIB(Pickup, m_sound, string, "misc/itempickup.wav")
ATTRIB(Pickup, m_name, string, string_null)
METHOD(Pickup, show, void(entity this));
#ifndef SVQC
.int m_itemid;
#endif
+
+#ifndef MENUQC
+MODEL(Strength_ITEM, Item_Model("g_strength.md3"));
+#endif
+
REGISTER_ITEM(Strength, Powerup) {
- this.m_model = "g_strength.md3";
+#ifndef MENUQC
+ this.m_model = MDL_Strength_ITEM;
+#endif
this.m_sound = "misc/powerup.wav";
this.m_name = "Strength Powerup";
this.m_icon = "strength";
this.m_waypointblink = 2;
this.m_itemid = IT_STRENGTH;
}
+
+#ifndef MENUQC
+MODEL(Shield_ITEM, Item_Model("g_invincible.md3"));
+#endif
+
REGISTER_ITEM(Shield, Powerup) {
- this.m_model = "g_invincible.md3";
+#ifndef MENUQC
+ this.m_model = MDL_Shield_ITEM;
+#endif
this.m_sound = "misc/powerup_shield.wav";
this.m_name = "Shield";
this.m_icon = "shield";
#include "../dpdefs/csprogsdefs.qh"
#include "../client/defs.qh"
#include "util.qh"
- #include "buffs.qh"
+ #include "buffs/all.qh"
#include "weapons/all.qh"
#include "mapinfo.qh"
#elif defined(MENUQC)
#include "../dpdefs/progsdefs.qh"
#include "../dpdefs/dpextensions.qh"
#include "util.qh"
- #include "buffs.qh"
+ #include "buffs/all.qh"
#include "monsters/all.qh"
#include "mapinfo.qh"
#endif
string _MapInfo_GetDefaultEx(float t)
{
- FOREACH(MAPINFO_TYPES, it.items == t, LAMBDA(return it.model2));
+ FOREACH(Gametypes, it.items == t, LAMBDA(return it.model2));
return "";
}
float _MapInfo_GetTeamPlayBool(float t)
{
- FOREACH(MAPINFO_TYPES, it.items == t, LAMBDA(return it.team));
+ FOREACH(Gametypes, it.items == t, LAMBDA(return it.team));
return false;
}
}
}
-float MapInfo_Type_FromString(string t)
+int MapInfo_Type_FromString(string t)
{
- if(t == "nexball")
- {
- LOG_INFO("MapInfo_Type_FromString (probably ", MapInfo_Map_bspname, "): using deprecated name '", t);
- t = "nb";
- LOG_INFO("'. Should use '", t, "'.\n");
- }
- if(t == "freezetag")
- {
- LOG_INFO("MapInfo_Type_FromString (probably ", MapInfo_Map_bspname, "): using deprecated name '", t);
- t = "ft";
- LOG_INFO("'. Should use '", t, "'.\n");
- }
- if(t == "keepaway")
- {
- LOG_INFO("MapInfo_Type_FromString (probably ", MapInfo_Map_bspname, "): using deprecated name '", t);
- t = "ka";
- LOG_INFO("'. Should use '", t, "'.\n");
- }
- if(t == "invasion")
- {
- LOG_INFO("MapInfo_Type_FromString (probably ", MapInfo_Map_bspname, "): using deprecated name '", t);
- t = "inv";
- LOG_INFO("'. Should use '", t, "'.\n");
- }
- if(t == "assault")
- {
- LOG_INFO("MapInfo_Type_FromString (probably ", MapInfo_Map_bspname, "): using deprecated name '", t);
- t = "as";
- LOG_INFO("'. Should use '", t, "'.\n");
- }
- if(t == "race")
- {
- LOG_INFO("MapInfo_Type_FromString (probably ", MapInfo_Map_bspname, "): using deprecated name '", t);
- t = "rc";
- LOG_INFO("'. Should use '", t, "'.\n");
- }
- if(t == "all")
- return MAPINFO_TYPE_ALL;
- FOREACH(MAPINFO_TYPES, it.mdl == t, LAMBDA(return it.items));
+#define deprecate(from, to) do { \
+ if (t == #from) { \
+ string replacement = #to; \
+ LOG_WARNINGF("MapInfo_Type_FromString (probably %s): using deprecated name '%s'. Should use '%s'.\n", MapInfo_Map_bspname, t, replacement); \
+ t = replacement; \
+ } \
+} while (0)
+ deprecate(nexball, nb);
+ deprecate(freezetag, ft);
+ deprecate(keepaway, ka);
+ deprecate(invasion, inv);
+ deprecate(assault, as);
+ deprecate(race, rc);
+ if (t == "all") return MAPINFO_TYPE_ALL;
+ FOREACH(Gametypes, it.mdl == t, LAMBDA(return it.items));
return 0;
+#undef deprecate
}
string MapInfo_Type_Description(float t)
{
- FOREACH(MAPINFO_TYPES, it.items == t, LAMBDA(return it.gametype_description));
+ FOREACH(Gametypes, it.items == t, LAMBDA(return it.gametype_description));
return "";
}
{
if(t == MAPINFO_TYPE_ALL)
return "all";
- FOREACH(MAPINFO_TYPES, it.items == t, LAMBDA(return it.mdl));
+ FOREACH(Gametypes, it.items == t, LAMBDA(return it.mdl));
return "";
}
string MapInfo_Type_ToText(float t)
{
- FOREACH(MAPINFO_TYPES, it.items == t, LAMBDA(return it.message));
+ FOREACH(Gametypes, it.items == t, LAMBDA(return it.message));
/* xgettext:no-c-format */
return _("@!#%'n Tuba Throwing");
}
{
t = car(s); s = cdr(s);
f = MapInfo_Type_FromString(t);
- LOG_TRACE("Map ", pFilename, " contains the legacy 'type' keyword which is deprecated and will be removed in the future. Please migrate the mapinfo file to 'gametype'.\n");
+ LOG_WARNING("Map ", pFilename, " contains the legacy 'type' keyword which is deprecated and will be removed in the future. Please migrate the mapinfo file to 'gametype'.\n");
if(f)
_MapInfo_Map_ApplyGametype (s, pGametypeToSet, f, true);
else
int MapInfo_CurrentGametype()
{
int prev = cvar("gamecfg");
- FOREACH(MAPINFO_TYPES, cvar(it.netname) && it.items != prev, LAMBDA(return it.items));
+ FOREACH(Gametypes, cvar(it.netname) && it.items != prev, LAMBDA(return it.items));
if (prev) return prev;
return MAPINFO_TYPE_DEATHMATCH;
}
void MapInfo_SwitchGameType(int t)
{
- FOREACH(MAPINFO_TYPES, true, LAMBDA(
+ FOREACH(Gametypes, true, LAMBDA(
cvar_set(it.netname, (it.items == t) ? "1" : "0")
));
}
}
ENDCLASS(Gametype)
-void RegisterGametypes();
-const int MAX_MAPINFO_TYPES = 24;
-entity MAPINFO_TYPES[MAX_MAPINFO_TYPES], MAPINFO_TYPES_first, MAPINFO_TYPES_last;
-int MAPINFO_TYPE_COUNT;
+REGISTRY(Gametypes, BIT(4))
+REGISTER_REGISTRY(RegisterGametypes)
int MAPINFO_TYPE_ALL;
-
#define REGISTER_GAMETYPE(hname, sname, g_name, NAME, gteamplay, defaults, gdescription) \
int MAPINFO_TYPE_##NAME; \
- REGISTER(RegisterGametypes, MAPINFO_TYPE, MAPINFO_TYPES, MAPINFO_TYPE_COUNT, g_name, m_id, \
+ REGISTER(RegisterGametypes, MAPINFO_TYPE, Gametypes, g_name, m_id, \
NEW(Gametype, hname, #sname, #g_name, gteamplay, defaults, gdescription) \
) { \
/* same as `1 << m_id` */ \
MAPINFO_TYPE_##NAME = MAPINFO_TYPE_ALL + 1; MAPINFO_TYPE_ALL |= MAPINFO_TYPE_##NAME; \
this.items = MAPINFO_TYPE_##NAME; \
}
-REGISTER_REGISTRY(RegisterGametypes)
#define IS_GAMETYPE(NAME) \
(MapInfo_LoadedGametype == MAPINFO_TYPE_##NAME)
void minigame_hud_simpleboard(vector pos, vector mySize, string board_texture)
{
if(panel.current_panel_bg != "0" && panel.current_panel_bg != "")
- draw_BorderPicture(pos - '1 1 0' * panel_bg_border,
- panel.current_panel_bg,
- mySize + '1 1 0' * 2 * panel_bg_border,
- panel_bg_color, panel_bg_alpha,
+ draw_BorderPicture(pos - '1 1 0' * panel_bg_border,
+ panel.current_panel_bg,
+ mySize + '1 1 0' * 2 * panel_bg_border,
+ panel_bg_color, panel_bg_alpha,
'1 1 0' * (panel_bg_border/BORDER_MULTIPLIER));
drawpic(pos, board_texture, mySize, '1 1 1', panel_bg_alpha, DRAWFLAG_NORMAL);
}
mousepos_y >= pos_y && mousepos_y < pos_y + sz_y ;
}
-void initialize_minigames()
-{
- entity last_minig = world;
- entity minig;
- #define MINIGAME(name,nicename) \
- minig = spawn(); \
- minig.classname = "minigame_descriptor"; \
- minig.netname = strzone(strtolower(#name)); \
- minig.message = nicename; \
- minig.minigame_hud_board = name##_hud_board; \
- minig.minigame_hud_status = name##_hud_status; \
- minig.minigame_event = name##_client_event; \
- if ( !last_minig ) minigame_descriptors = minig; \
- else last_minig.list_next = minig; \
- last_minig = minig;
-
- REGISTERED_MINIGAMES
-
- #undef MINIGAME
-}
-
string minigame_texture_skin(string skinname, string name)
{
return sprintf("gfx/hud/%s/minigames/%s", skinname, name);
#define MSLE_CLEAN_Vector2D(x)
#define MSLE(Name,Fields) \
- void msle_entremove_##Name() { strunzone(self.netname); Fields }
+ void msle_entremove_##Name() { SELFPARAM(); strunzone(self.netname); Fields }
MINIGAME_SIMPLELINKED_ENTITIES
#undef MSLE
#undef FIELD
void minigame_autoclean_entity(entity e)
{
- LOG_TRACE("CL Auto-cleaned: ",ftos(num_for_edict(e)), " (",e.classname,")\n");
+ LOG_DEBUG("CL Auto-cleaned: ",ftos(num_for_edict(e)), " (",e.classname,")\n");
remove(e);
}
}
void minigame_entremove()
-{
+{SELFPARAM();
if ( self == active_minigame )
deactivate_minigame();
}
deactivate_minigame();
return;
}
-
+
if ( !minigame.descriptor || minigame.classname != "minigame" )
{
LOG_TRACE("Trying to activate unregistered minigame ",minigame.netname," in client\n");
return;
}
-
+
if ( minigame == active_minigame )
return;
-
+
if ( active_minigame )
{
deactivate_minigame();
}
-
+
if ( minigame_self.owner != minigame )
minigame_self = world;
active_minigame = minigame;
active_minigame.minigame_event(active_minigame,"activate");
-
+
if ( HUD_MinigameMenu_IsOpened() )
HUD_MinigameMenu_CurrentButton();
else
}
void minigame_player_entremove()
-{
+{SELFPARAM();
if ( self.owner == active_minigame && self.minigame_playerslot == player_localentnum )
deactivate_minigame();
}
Fields \
}
void minigame_read_owner()
-{
+{SELFPARAM();
string owner_name = ReadString_Raw();
self.owner = world;
do
LOG_TRACE("Got a minigame entity without a minigame!\n");
}
void ent_read_minigame()
-{
+{SELFPARAM();
float sf = ReadByte();
if ( sf & MINIG_SF_CREATE )
{
self.classname = msle_classname(ReadShort());
self.netname = ReadString_Zoned();
}
-
+
entity minigame_ent = world;
-
+
if ( self.classname == "minigame" )
{
minigame_ent = self;
-
+
if ( sf & MINIG_SF_CREATE )
{
self.entremove = minigame_entremove;
minigame_read_owner();
float ent = ReadLong();
self.minigame_playerslot = ent;
- LOG_TRACE("Player: ",GetPlayerName(ent-1),"\n");
-
+ LOG_DEBUG("Player: ",GetPlayerName(ent-1),"\n");
+
activate = (ent == player_localnum+1 && self.owner && self.owner != active_minigame);
-
+
}
minigame_ent = self.owner;
-
+
if ( sf & MINIG_SF_UPDATE )
self.team = ReadByte();
-
+
if ( activate )
{
minigame_self = self;
}
}
MINIGAME_SIMPLELINKED_ENTITIES
-
+
if ( minigame_ent )
minigame_ent.minigame_event(minigame_ent,"network_receive",self,sf);
if ( sf & MINIG_SF_CREATE )
{
- LOG_TRACE("CL Reading entity: ",ftos(num_for_edict(self)),
+ LOG_DEBUG("CL Reading entity: ",ftos(num_for_edict(self)),
" classname:",self.classname," enttype:",ftos(self.enttype) );
- LOG_TRACE(" sf:",ftos(sf)," netname:",self.netname,"\n\n");
+ LOG_DEBUG(" sf:",ftos(sf)," netname:",self.netname,"\n\n");
}
}
#undef ReadString
}
take_until = textLengthUpToWidth(s, w, theFontSize, tw);
-
+
if ( take_until > strlen(s) )
take_until = strlen(s);
skip = 1;
break;
}
-
+
if ( take_until > 0 || skip > 0 )
{
if ( skip == 0 && take_until < strlen(s) )
skip = 1;
}
}
-
+
getWrappedLine_remaining = substring(s, take_until+skip, strlen(s) - (take_until+skip));
if(getWrappedLine_remaining == "")
getWrappedLine_remaining = string_null;
}
}
-vector minigame_drawstring_wrapped( float maxwidth, vector pos, string text,
+vector minigame_drawstring_wrapped( float maxwidth, vector pos, string text,
vector fontsize, vector color, float theAlpha, int drawflags, float align )
-{
+{
getWrappedLine_remaining = text;
vector mypos = pos;
while ( getWrappedLine_remaining )
return mypos;
}
-vector minigame_drawcolorcodedstring_wrapped( float maxwidth, vector pos,
+vector minigame_drawcolorcodedstring_wrapped( float maxwidth, vector pos,
string text, vector fontsize, float theAlpha, int drawflags, float align )
{
getWrappedLine_remaining = text;
return mypos;
}
-void minigame_drawstring_trunc(float maxwidth, vector pos, string text,
+void minigame_drawstring_trunc(float maxwidth, vector pos, string text,
vector fontsize, vector color, float theAlpha, int drawflags )
{
string line = textShortenToWidth(text,maxwidth,fontsize,stringwidth_nocolors);
drawstring(pos, line, fontsize, color, theAlpha, drawflags);
}
-void minigame_drawcolorcodedstring_trunc(float maxwidth, vector pos, string text,
+void minigame_drawcolorcodedstring_trunc(float maxwidth, vector pos, string text,
vector fontsize, float theAlpha, int drawflags )
{
string line = textShortenToWidth(text,maxwidth,fontsize,stringwidth_colors);
drawcolorcodedstring(pos, line, fontsize, theAlpha, drawflags);
}
-void minigame_drawpic_centered( vector pos, string texture, vector sz,
+void minigame_drawpic_centered( vector pos, string texture, vector sz,
vector color, float thealpha, int drawflags )
{
drawpic( pos-sz/2, texture, sz, color, thealpha, drawflags );
localcmd(strcat(cmd,"\n"));
}
-// Prompt the player to play in the current minigame
+// Prompt the player to play in the current minigame
// (ie: it's their turn and they should get back to the minigame)
void minigame_prompt()
{
// Like drawstring, but wrapping words to fit maxwidth
// returns the size of the drawn area
// align selects the string alignment (0 = left, 0.5 = center, 1 = right)
-vector minigame_drawstring_wrapped( float maxwidth, vector pos, string text,
+vector minigame_drawstring_wrapped( float maxwidth, vector pos, string text,
vector fontsize, vector color, float theAlpha, int drawflags, float align );
// Like drawcolorcodedstring, but wrapping words to fit maxwidth
// returns the size of the drawn area
// align selects the string alignment (0 = left, 0.5 = center, 1 = right)
-vector minigame_drawcolorcodedstring_wrapped( float maxwidth, vector pos,
+vector minigame_drawcolorcodedstring_wrapped( float maxwidth, vector pos,
string text, vector fontsize, float theAlpha, int drawflags, float align );
// Like drawstring but truncates the text to fit maxwidth
-void minigame_drawstring_trunc(float maxwidth, vector pos, string text,
+void minigame_drawstring_trunc(float maxwidth, vector pos, string text,
vector fontsize, vector color, float theAlpha, int drawflags );
// Like drawcolorcodedstring but truncates the text to fit maxwidth
-void minigame_drawcolorcodedstring_trunc(float maxwidth, vector pos, string text,
+void minigame_drawcolorcodedstring_trunc(float maxwidth, vector pos, string text,
vector fontsize, float theAlpha, int drawflags );
// like drawpic but pos represent the center rather than the topleft corner
-void minigame_drawpic_centered( vector pos, string texture, vector sz,
+void minigame_drawpic_centered( vector pos, string texture, vector sz,
vector color, float thealpha, int drawflags );
// Get full path of a minigame texture
// For minigame_player: player server slot, don't use for anything else
.float minigame_playerslot;
-// register all minigames
-void initialize_minigames();
-
// client-side minigame session cleanup
void deactivate_minigame();
// Read a minigame entity from the server
void ent_read_minigame();
-// Prompt the player to play in the current minigame
+// Prompt the player to play in the current minigame
// (ie: it's their turn and they should get back to the minigame)
void minigame_prompt();
#define FOREACH_MINIGAME_ENTITY(entityvar) \
entityvar=world; \
- while( (entityvar = findentity(entityvar,owner,active_minigame)) )
+ while( (entityvar = findentity(entityvar,owner,active_minigame)) )
+
+
+REGISTRY(Minigames, BIT(3))
+REGISTER_REGISTRY(RegisterMinigames)
+#define REGISTER_MINIGAME(name,nicename) \
+ REGISTER(RegisterMinigames, MINIGAME, Minigames, name, m_id, spawn()); \
+ void name##_hud_board(vector, vector); \
+ void name##_hud_status(vector, vector); \
+ int name##_client_event(entity, string, ...); \
+ REGISTER_INIT_POST(MINIGAME, name) { \
+ this.classname = "minigame_descriptor"; \
+ this.netname = strzone(strtolower(#name)); \
+ this.message = nicename; \
+ this.minigame_hud_board = name##_hud_board; \
+ this.minigame_hud_status = name##_hud_status; \
+ this.minigame_event = name##_client_event; \
+ } \
+ REGISTER_INIT(MINIGAME, name)
#endif
{
vector pos = stov(cvar_string(strcat("hud_panel_", somepanel.panel_name, "_pos")));
vector sz = stov(cvar_string(strcat("hud_panel_", somepanel.panel_name, "_size")));
- return mousepos_x >= pos_x*vid_conwidth && mousepos_x <= (pos_x+sz_x)*vid_conwidth &&
+ return mousepos_x >= pos_x*vid_conwidth && mousepos_x <= (pos_x+sz_x)*vid_conwidth &&
mousepos_y >= pos_y*vid_conheight && mousepos_y <= (pos_y+sz_y)*vid_conheight ;
}
void HUD_MinigameBoard ()
{
entity hud_minigame = world;
-
+
if(!autocvar__hud_configure)
hud_minigame = active_minigame.descriptor;
else
hud_minigame = minigame_get_descriptor("nmm");
-
+
if ( !hud_minigame )
return;
-
+
HUD_Panel_UpdateCvars();
-
-
+
+
vector pos, mySize;
pos = panel_pos;
mySize = panel_size;
-
+
hud_minigame.minigame_hud_board(pos,mySize);
}
void HUD_MinigameStatus ()
{
entity hud_minigame = world;
-
+
if(!autocvar__hud_configure)
hud_minigame = active_minigame.descriptor;
else
hud_minigame = minigame_get_descriptor("nmm");
-
+
if ( !hud_minigame )
return;
-
+
HUD_Panel_UpdateCvars();
-
-
+
+
vector pos, mySize;
pos = panel_pos;
mySize = panel_size;
-
+
if(panel_bg_padding)
{
pos += '1 1 0' * panel_bg_padding;
mySize -= '2 2 0' * panel_bg_padding;
}
-
+
hud_minigame.minigame_hud_status(pos,mySize);
}
HUD_MinigameMenu_last_entry = newentry;
return;
}
-
+
newentry.list_prev = prev;
newentry.list_next = prev.list_next;
if ( prev.list_next )
else
HUD_MinigameMenu_last_entry = newentry;
prev.list_next = newentry;
-
+
}
// Click the given item
void HUD_MinigameMenu_Click(entity menuitem)
-{
+{SELFPARAM();
if ( menuitem )
{
- entity e = self;
- self = menuitem;
- menuitem.use();
- self = e;
+ WITH(entity, self, menuitem, menuitem.use());
}
}
{
HUD_MinigameMenu_Click(e);
}
-
+
if ( e.list_prev )
e.list_prev.list_next = e.list_next;
else
HUD_MinigameMenu_entries = e.list_next;
-
+
if ( e.list_next )
e.list_next.list_prev = e.list_prev;
else
HUD_MinigameMenu_last_entry = e.list_prev;
-
+
if ( HUD_MinigameMenu_activeitem == e )
HUD_MinigameMenu_activeitem = world;
-
+
remove(e);
}
// Click action for Create sub-entries
void HUD_MinigameMenu_ClickCreate_Entry()
-{
+{SELFPARAM();
minigame_cmd("create ",self.netname);
}
// Helper click action for collapsible entries
// returns true when you have to create the sub-entries
bool HUD_MinigameMenu_Click_ExpandCollapse()
-{
+{SELFPARAM();
entity e;
if ( self.flags & 2 )
{
- if ( HUD_MinigameMenu_activeitem &&
+ if ( HUD_MinigameMenu_activeitem &&
HUD_MinigameMenu_activeitem.owner == self )
HUD_MinigameMenu_activeitem = world;
self.flags &= ~2;
if ( e.flags & 2 && e.origin_x == self.origin_x)
HUD_MinigameMenu_Click(e);
}
-
+
self.flags |= 2;
-
+
return true;
}
return false;
// Click action for the Create menu
void HUD_MinigameMenu_ClickCreate()
-{
+{SELFPARAM();
if ( HUD_MinigameMenu_Click_ExpandCollapse() )
{
- entity e;
entity curr;
entity prev = self;
- for ( e = minigame_descriptors; e != world; e = e.list_next )
+ FOREACH(Minigames, true, LAMBDA(
{
curr = HUD_MinigameMenu_SpawnSubEntry(
- e.message, HUD_MinigameMenu_ClickCreate_Entry, self );
- curr.netname = e.netname;
- curr.model = strzone(minigame_texture(strcat(e.netname,"/icon")));
+ it.message, HUD_MinigameMenu_ClickCreate_Entry, self );
+ curr.netname = it.netname;
+ curr.model = strzone(minigame_texture(strcat(it.netname,"/icon")));
HUD_MinigameMenu_InsertEntry( curr, prev );
prev = curr;
- }
+ }));
}
}
// Click action for Join sub-entries
void HUD_MinigameMenu_ClickJoin_Entry()
-{
+{SELFPARAM();
minigame_cmd("join ",self.netname);
HUD_MinigameMenu_EraseEntry(self);
}
// Click action for the Join menu
void HUD_MinigameMenu_ClickJoin()
-{
+{SELFPARAM();
if ( HUD_MinigameMenu_Click_ExpandCollapse() )
{
entity e = world;
// Click action for Invite sub-entries
void HUD_MinigameMenu_ClickInvite_Entry()
-{
+{SELFPARAM();
minigame_cmd("invite #",self.netname);
}
// Click action for the Invite menu
void HUD_MinigameMenu_ClickInvite()
-{
+{SELFPARAM();
if ( HUD_MinigameMenu_Click_ExpandCollapse() )
{
entity e;
}
void HUD_MinigameMenu_ClickCustomEntry()
-{
+{SELFPARAM();
if ( active_minigame )
active_minigame.minigame_event(active_minigame,"menu_click",self.netname);
}
// Click action for the Current Game menu
void HUD_MinigameMenu_ClickCurrentGame()
-{
+{SELFPARAM();
if ( HUD_MinigameMenu_Click_ExpandCollapse() )
{
HUD_MinigameMenu_InsertEntry( HUD_MinigameMenu_SpawnSubEntry(
_("Quit"), HUD_MinigameMenu_ClickQuit, self ), self);
-
+
active_minigame.minigame_event(active_minigame,"menu_show",self);
-
+
HUD_MinigameMenu_InsertEntry( HUD_MinigameMenu_SpawnSubEntry(
_("Invite"), HUD_MinigameMenu_ClickInvite, self), self);
}
HUD_MinigameMenu_InsertEntry(currb,HUD_MinigameMenu_last_entry);
HUD_MinigameMenu_Click(currb);
}
- else
+ else
{
entity p;
for ( e = HUD_MinigameMenu_last_entry; e != world; e = p.list_prev )
panel_pos += '1 1 0' * panel_bg_padding;
panel_size -= '2 2 0' * panel_bg_padding;
}
-
+
entity e;
-
+
panel_pos_y += hud_fontsize_y*2;
-
+
HUD_MinigameMenu_activeitem = world;
vector sz;
for ( e = HUD_MinigameMenu_entries; e != world; e = e.list_next )
// Minigame menu panel UI
void HUD_MinigameMenu ()
-{
+{
if ( !HUD_MinigameMenu_IsOpened() )
return;
-
+
HUD_Panel_UpdateCvars();
-
+
HUD_Panel_DrawBg(1);
-
+
if(panel_bg_padding)
{
panel_pos += '1 1 0' * panel_bg_padding;
for ( entity e = HUD_MinigameMenu_entries; e != world; e = e.list_next )
{
color = e.colormod;
-
+
offset = e.origin;
itemh = e.size_y;
-
+
if ( e.model )
itemh = imgsz_y;
-
+
if ( e.flags & 2 )
{
- drawfill(panel_pos, eX*panel_size_x + eY*itemh, e.colormod,
+ drawfill(panel_pos, eX*panel_size_x + eY*itemh, e.colormod,
panel_fg_alpha, DRAWFLAG_NORMAL);
color = '0 0 0';
}
offset_x += imgsz_x;
offset_y = (imgsz_y-e.size_y) / 2;
}
-
+
if ( e.flags & 1 )
HUD_MinigameMenu_DrawColoredEntry(panel_pos+offset,e.message,e.size);
else
HUD_MinigameMenu_DrawEntry(panel_pos+offset,e.message,e.size,color);
-
+
if ( e == HUD_MinigameMenu_activeitem )
drawfill(panel_pos, eX*panel_size_x + eY*itemh,'1 1 1', 0.25, DRAWFLAG_ADDITIVE);
-
+
panel_pos_y += itemh;
}
}
void HUD_MinigameHelp()
{
string help_message;
-
+
if(!autocvar__hud_configure)
help_message = active_minigame.message;
else
help_message = "Minigame message";
-
+
if ( !help_message )
return;
-
+
HUD_Panel_UpdateCvars();
-
-
+
+
vector pos, mySize;
pos = panel_pos;
mySize = panel_size;
-
+
if(panel_bg_padding)
{
pos += '1 1 0' * panel_bg_padding;
mySize -= '2 2 0' * panel_bg_padding;
}
-
- minigame_drawcolorcodedstring_wrapped( mySize_x, pos, help_message,
+
+ minigame_drawcolorcodedstring_wrapped( mySize_x, pos, help_message,
hud_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL, 0.5 );
}
// ====================================================================
float HUD_Minigame_InputEvent(float bInputType, float nPrimary, float nSecondary)
{
-
+
if( !HUD_MinigameMenu_IsOpened() || autocvar__hud_configure )
return false;
if ( minigame_isactive() && HUD_mouse_over(HUD_PANEL(MINIGAME_BOARD)) )
active_minigame.minigame_event(active_minigame,"mouse_moved",mousepos);
return true;
-
+
}
else
{
if(nPrimary == K_MOUSE1) mouseClicked -= (mouseClicked & S_MOUSE1);
if(nPrimary == K_MOUSE2) mouseClicked -= (mouseClicked & S_MOUSE2);
}
-
+
// allow some binds
string con_keys;
con_keys = findkeysforcommand("toggleconsole", 0);
if(nPrimary == stof(argv(i)))
return false;
}
-
+
if ( minigame_isactive() && ( bInputType == 0 || bInputType == 1 ) )
{
string device = "";
}
else
device = "key";
-
+
if ( device && active_minigame.minigame_event(
active_minigame,strcat(device,"_",action),nPrimary) )
return true;
-
+
/// TODO: bInputType == 2?
}
-
+
if ( bInputType == 0 )
{
if ( nPrimary == K_MOUSE1 && HUD_MinigameMenu_activeitem &&
}
}
}
-
+
return false;
}
void HUD_Minigame_Mouse()
-{
+{
if( !HUD_MinigameMenu_IsOpened() || autocvar__hud_configure || mv_active )
return;
-
+
if(!autocvar_hud_cursormode)
{
mousepos = mousepos + getmousepos() * autocvar_menu_mouse_speed;
mousepos_x = bound(0, mousepos_x, vid_conwidth);
mousepos_y = bound(0, mousepos_y, vid_conheight);
}
-
+
if ( HUD_MinigameMenu_IsOpened() && HUD_mouse_over(HUD_PANEL(MINIGAME_MENU)) )
HUD_MinigameMenu_MouseInput();
-
+
vector cursorsize = '32 32 0';
- drawpic(mousepos-'8 4 0', strcat("gfx/menu/", autocvar_menu_skin, "/cursor.tga"),
+ drawpic(mousepos-'8 4 0', strcat("gfx/menu/", autocvar_menu_skin, "/cursor.tga"),
cursorsize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
}
* MINIG_SF_UPDATE
A miscellaneous update, can be safely used if the entity has just a few fields
* MINIG_SF_CUSTOM
- Starting value for custom flags, since there are bit-wise flags,
+ Starting value for custom flags, since there are bit-wise flags,
the following values shall be MINIG_SF_CUSTOM*2, MINIG_SF_CUSTOM*4 and MINIG_SF_CUSTOM*8.
* MINIG_SF_MAX
Maximum flag value that will be networked
#include "ttt.qc"
#include "c4.qc"
#include "pong.qc"
-#include "qto.qc"
#include "ps.qc"
#include "pp.qc"
-
-/**
- * Registration:
- * MINIGAME(id,"Name")
- * id (QuakeC symbol) Game identifier, used to find the functions explained above
- * "Name"(String) Human readable name for the game, shown in the UI
- */
-#define REGISTERED_MINIGAMES \
- MINIGAME(nmm, "Nine Men's Morris") \
- MINIGAME(ttt, "Tic Tac Toe") \
- MINIGAME(pong,"Pong") \
- MINIGAME(c4, "Connect Four") \
- MINIGAME(qto, "Quinto") \
- MINIGAME(ps, "Peg Solitaire") \
- MINIGAME(pp, "Push-Pull") \
- /*empty line*/
+#include "snake.qc"
/**
* Set up automatic entity read/write functionality
* To ensure that everything is handled automatically, spawn on the server using msle_spawn
* Syntax:
- * MSLE(classname,Field...) \
+ * MSLE(classname,Field...) \
* classname: Identifier used to recognize the type of the entity
* (must be set as .classname on the sent entities)
* Field... : List of FIELD calls
MSLE(pong_paddle,FIELD(MINIG_SF_CREATE,Byte,team) FIELD(MINIG_SF_CREATE,Float,pong_length) FIELD(MINIG_SF_UPDATE,Vector2D,origin)) \
MSLE(pong_ball,FIELD(MINIG_SF_CREATE,Float,pong_length) FIELD(PONG_SF_BALLTEAM,Byte,team) FIELD(MINIG_SF_UPDATE, Vector2D, velocity) FIELD(MINIG_SF_UPDATE, Vector2D, origin)) \
MSLE(pong_ai, FIELD(MINIG_SF_CREATE,Byte,team) FIELD(PONG_SF_PLAYERSCORE, Long, pong_score)) \
- /*empty line*/
+ /*empty line*/
+REGISTER_MINIGAME(c4, "Connect Four");
+
const float C4_TURN_PLACE = 0x0100; // player has to place a piece on the board
const float C4_TURN_WIN = 0x0200; // player has won
const float C4_TURN_DRAW = 0x0400; // no moves are possible
-const float C4_TURN_TYPE = 0x0f00; // turn type mask
const float C4_TURN_TEAM1 = 0x0001;
const float C4_TURN_TEAM2 = 0x0002;
if(found >= C4_WIN_CNT)
return true;
-
+
return false;
}
{
switch(argv(0))
{
- case "move":
- c4_move(minigame, ...(0,entity), ...(1,int) == 2 ? argv(1) : string_null );
+ case "move":
+ c4_move(minigame, ...(0,entity), ...(1,int) == 2 ? argv(1) : string_null );
return true;
}
return false;
}
}
-
+
return false;
}
minigame_hud_fitsqare(pos, mySize);
c4_boardpos = pos;
c4_boardsize = mySize;
-
+
minigame_hud_simpleboard(pos,mySize,minigame_texture("c4/board_under"));
drawpic(pos, minigame_texture("c4/board_over"), mySize, '1 1 1', 1, 0);
{
tile_pos = minigame_tile_pos(c4_curr_pos,C4_NUM_CNT,C4_LET_CNT);
tile_pos = minigame_hud_denormalize(tile_pos,pos,mySize);
- minigame_drawpic_centered( tile_pos,
+ minigame_drawpic_centered( tile_pos,
minigame_texture(strcat("c4/piece",ftos(minigame_self.team))),
tile_size, '1 1 1', panel_fg_alpha/2, DRAWFLAG_NORMAL );
}
-
+
entity e;
FOREACH_MINIGAME_ENTITY(e)
{
{
tile_pos = minigame_tile_pos(e.netname,C4_NUM_CNT,C4_LET_CNT);
tile_pos = minigame_hud_denormalize(tile_pos,pos,mySize);
-
+
if ( active_minigame.minigame_flags & C4_TURN_WIN )
if ( !e.c4_checkwin )
e.c4_checkwin = c4_winning_piece(e) ? 1 : -1;
-
+
float icon_color = 1;
if ( e.c4_checkwin == -1 )
icon_color = 0.4;
minigame_drawpic_centered( tile_pos, minigame_texture("c4/winglow"),
tile_size, '1 1 1', panel_fg_alpha, DRAWFLAG_ADDITIVE );
}
-
- minigame_drawpic_centered( tile_pos,
+
+ minigame_drawpic_centered( tile_pos,
minigame_texture(strcat("c4/piece",ftos(e.team))),
tile_size, '1 1 1'*icon_color, panel_fg_alpha, DRAWFLAG_NORMAL );
}
vector winfs = hud_fontsize*2;
string playername = "";
FOREACH_MINIGAME_ENTITY(e)
- if ( e.classname == "minigame_player" &&
+ if ( e.classname == "minigame_player" &&
e.team == (active_minigame.minigame_flags & C4_TURN_TEAM) )
playername = GetPlayerName(e.minigame_playerslot-1);
-
+
vector win_pos = pos+eY*(mySize_y-winfs_y)/2;
vector win_sz;
win_sz = minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
- sprintf("%s^7 won the game!",playername),
+ sprintf("%s^7 won the game!",playername),
winfs, 0, DRAWFLAG_NORMAL, 0.5);
-
+
drawfill(win_pos-eY*hud_fontsize_y,win_sz+2*eY*hud_fontsize_y,'1 1 1',0.5,DRAWFLAG_ADDITIVE);
-
+
minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
- sprintf("%s^7 won the game!",playername),
+ sprintf("%s^7 won the game!",playername),
winfs, panel_fg_alpha, DRAWFLAG_NORMAL, 0.5);
}
}
vector ts;
ts = minigame_drawstring_wrapped(mySize_x,pos,active_minigame.descriptor.message,
hud_fontsize * 2, '0.25 0.47 0.72', panel_fg_alpha, DRAWFLAG_NORMAL,0.5);
-
+
pos_y += ts_y;
mySize_y -= ts_y;
-
+
vector player_fontsize = hud_fontsize * 1.75;
ts_y = ( mySize_y - 2*player_fontsize_y ) / 2;
ts_x = mySize_x;
minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
GetPlayerName(e.minigame_playerslot-1),
player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
-
+
mypos_y += player_fontsize_y;
- drawpic( mypos,
+ drawpic( mypos,
minigame_texture(strcat("c4/piece",ftos(e.team))),
tile_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL );
-
+
mypos_x += tile_size_x;
}
}
{
if ( turnflags & C4_TURN_DRAW )
return _("Draw");
-
+
if ( turnflags & C4_TURN_WIN )
{
if ( (turnflags&C4_TURN_TEAM) != minigame_self.team )
return _("You lost the game!");
return _("You win!");
}
-
+
if ( (turnflags & C4_TURN_TEAM) != minigame_self.team )
return _("Wait for your opponent to make their move");
-
+
if ( turnflags & C4_TURN_PLACE )
return _("Click on the game board to place your piece");
-
+
return "";
}
return false;
}
-#endif
\ No newline at end of file
+#endif
+REGISTER_MINIGAME(nmm, "Nine Men's Morris");
+
const int NMM_TURN_PLACE = 0x0100; // player has to place a piece on the board
const int NMM_TURN_MOVE = 0x0200; // player has to move a piece by one tile
const int NMM_TURN_FLY = 0x0400; // player has to move a piece anywhere
// Create an new tile
// \param id Tile index (eg: a1)
-// \param minig Owner minigame instance
+// \param minig Owner minigame instance
// \param distance Distance from adjacent tiles
void nmm_spawn_tile(string id, entity minig, int distance)
{
}
// Create a tile square and recursively create inner squares
-// \param minig Owner minigame instance
+// \param minig Owner minigame instance
// \param offset Index offset (eg: 1 to start the square at b2, 0 at a1 etc.)
// \param skip Number of indices to skip between tiles (eg 1: a1, a3)
void nmm_spawn_tile_square( entity minig, int offset, int skip )
}
letter += skip+1;
}
-
+
if ( skip > 0 )
nmm_spawn_tile_square(minig,offset+1,skip-1);
}
// Check whether two tiles are adjacent
bool nmm_tile_adjacent(entity tile1, entity tile2)
{
-
+
int dnumber = fabs ( minigame_tile_number(tile1.netname) - minigame_tile_number(tile2.netname) );
int dletter = fabs ( minigame_tile_letter(tile1.netname) - minigame_tile_letter(tile2.netname) );
-
+
return ( dnumber == 0 && ( dletter == 1 || dletter == tile1.nmm_tile_distance ) ) ||
( dletter == 0 && ( dnumber == 1 || dnumber == tile1.nmm_tile_distance ) );
}
{
entity e = world;
while ( ( e = findentity(e,owner,tile.owner) ) )
- if ( e.classname == "minigame_nmm_tile" && !e.nmm_tile_piece
+ if ( e.classname == "minigame_nmm_tile" && !e.nmm_tile_piece
&& nmm_tile_adjacent(e,tile) )
{
return true;
// Check if a tile is in a mill
bool nmm_in_mill(entity tile)
{
- return tile.nmm_tile_piece && (
+ return tile.nmm_tile_piece && (
nmm_in_mill_string(tile,tile.nmm_tile_hmill) ||
nmm_in_mill_string(tile,tile.nmm_tile_vmill) );
}
{
entity e = start;
while ( ( e = findentity(e,owner,minigame) ) )
- if ( e.classname == "minigame_board_piece" &&
+ if ( e.classname == "minigame_board_piece" &&
(e.minigame_flags & pieceflags) && e.team == teamn )
return e;
return world;
e.team = 2;
e.minigame_flags = NMM_PIECE_HOME;
}
-
+
return 1;
}
else if ( event == "end" )
entity tile = world;
entity piece = world;
bool move_ok = false;
-
- if ( e && argc >= 2 && argv(0) == "move" &&
+
+ if ( e && argc >= 2 && argv(0) == "move" &&
( minigame.minigame_flags & NMM_TURN_TEAM ) == e.team )
{
tile = nmm_find_tile(minigame,argv(1));
move_ok = true;
}
}
-
+
}
else if ( minigame.minigame_flags & NMM_TURN_FLY )
{
move_ok = true;
}
}
-
+
}
else if ( minigame.minigame_flags & NMM_TURN_TAKE )
{
move_ok = true;
}
}
-
+
int nextteam = e.team % 2 + 1;
int npieces = nmm_count_pieces(minigame,nextteam,NMM_PIECE_HOME|NMM_PIECE_BOARD);
-
+
if ( npieces < 3 )
{
minigame.minigame_flags = NMM_TURN_WIN | e.team;
nmm_boardpos = pos;
nmm_boardsize = mySize;
minigame_hud_simpleboard(pos,mySize,minigame_texture("nmm/board"));
-
+
vector tile_size = minigame_hud_denormalize_size('1 1 0'/7,pos,mySize);
vector tile_pos;
entity e;
if ( e.classname == "minigame_nmm_tile" )
{
tile_pos = minigame_hud_denormalize(e.origin,pos,mySize);
-
+
if ( e == nmm_fromtile )
{
minigame_drawpic_centered( tile_pos, minigame_texture("nmm/tile_active"),
minigame_drawpic_centered( tile_pos, minigame_texture("nmm/tile_available"),
tile_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL );
}
-
+
if ( e == nmm_currtile )
{
minigame_drawpic_centered( tile_pos, minigame_texture("nmm/tile_selected"),
tile_size, '1 1 1', panel_fg_alpha, DRAWFLAG_ADDITIVE );
}
-
+
if ( e.nmm_tile_piece )
{
- minigame_drawpic_centered( tile_pos,
+ minigame_drawpic_centered( tile_pos,
minigame_texture(strcat("nmm/piece",ftos(e.nmm_tile_piece.team))),
tile_size*0.8, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL );
}
-
+
//drawstring(tile_pos, e.netname, hud_fontsize, '1 0 0', 1, DRAWFLAG_NORMAL);
}
}
-
+
if ( active_minigame.minigame_flags & NMM_TURN_WIN )
{
vector winfs = hud_fontsize*2;
string playername = "";
FOREACH_MINIGAME_ENTITY(e)
- if ( e.classname == "minigame_player" &&
+ if ( e.classname == "minigame_player" &&
e.team == (active_minigame.minigame_flags & NMM_TURN_TEAM) )
playername = GetPlayerName(e.minigame_playerslot-1);
-
+
vector win_pos = pos+eY*(mySize_y-winfs_y)/2;
vector win_sz;
win_sz = minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
- sprintf("%s^7 won the game!",playername),
+ sprintf("%s^7 won the game!",playername),
winfs, 0, DRAWFLAG_NORMAL, 0.5);
-
+
drawfill(win_pos-eY*hud_fontsize_y,win_sz+2*eY*hud_fontsize_y,'1 1 1',0.5,DRAWFLAG_ADDITIVE);
-
+
minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
- sprintf("%s^7 won the game!",playername),
+ sprintf("%s^7 won the game!",playername),
winfs, panel_fg_alpha, DRAWFLAG_NORMAL, 0.5);
}
}
{
HUD_Panel_DrawBg(1);
vector ts;
-
+
ts = minigame_drawstring_wrapped(mySize_x,pos,active_minigame.descriptor.message,
hud_fontsize * 2, '0.25 0.47 0.72', panel_fg_alpha, DRAWFLAG_NORMAL,0.5);
pos_y += ts_y;
mySize_y -= ts_y;
-
+
vector player_fontsize = hud_fontsize * 1.75;
ts_y = ( mySize_y - 2*player_fontsize_y ) / 2;
ts_x = mySize_x;
-
+
float player1x = 0;
float player2x = 0;
vector piece_sz = '48 48 0';
vector mypos;
float piece_light = 1;
entity e = world;
-
+
mypos = pos;
if ( (active_minigame.minigame_flags&NMM_TURN_TEAM) == 2 )
mypos_y += player_fontsize_y + ts_y;
drawfill(mypos,eX*mySize_x+eY*player_fontsize_y,'1 1 1',0.5,DRAWFLAG_ADDITIVE);
mypos_y += player_fontsize_y;
drawfill(mypos,eX*mySize_x+eY*piece_sz_y,'1 1 1',0.25,DRAWFLAG_ADDITIVE);
-
+
FOREACH_MINIGAME_ENTITY(e)
{
if ( e.classname == "minigame_player" )
piece_light = 1;
else
piece_light = 0.15;
-
+
drawpic(mypos, minigame_texture(strcat("nmm/piece",ftos(e.team))), piece_sz,
'1 1 1'*piece_light, panel_fg_alpha, DRAWFLAG_NORMAL );
}
return _("You lost the game!");
return _("You win!");
}
-
+
if ( (turnflags&NMM_TURN_TEAM) != minigame_self.team )
return _("Wait for your opponent to make their move");
if ( turnflags & NMM_TURN_PLACE )
return _("You can select one of your pieces to move it anywhere on the board");
if ( turnflags & NMM_TURN_TAKE )
return _("You can take one of the opponent's pieces");
-
+
return "";
}
// Required function, handle client events
int nmm_client_event(entity minigame, string event, ...)
-{
+{SELFPARAM();
if ( event == "activate" )
{
nmm_fromtile = world;
else
{
string tileid = nmm_currtile.netname;
- nmm_currtile = world;
+ nmm_currtile = world;
while ( !nmm_currtile )
{
tileid = minigame_relative_tile(tileid,1,0,7,7);
else
{
string tileid = nmm_currtile.netname;
- nmm_currtile = world;
+ nmm_currtile = world;
while ( !nmm_currtile )
{
tileid = minigame_relative_tile(tileid,-1,0,7,7);
else
{
string tileid = nmm_currtile.netname;
- nmm_currtile = world;
+ nmm_currtile = world;
while ( !nmm_currtile )
{
tileid = minigame_relative_tile(tileid,0,1,7,7);
else
{
string tileid = nmm_currtile.netname;
- nmm_currtile = world;
+ nmm_currtile = world;
while ( !nmm_currtile )
{
tileid = minigame_relative_tile(tileid,0,-1,7,7);
}
}
}
- else if ( self.classname == "minigame" && ( ...(1,int) & MINIG_SF_UPDATE ) )
+ else if ( self.classname == "minigame" && ( ...(1,int) & MINIG_SF_UPDATE ) )
{
self.message = nmm_turn_to_string(self.minigame_flags);
if ( self.minigame_flags & minigame_self.team )
minigame_prompt();
}
}
-
+
return 0;
}
-#endif
+#endif
+REGISTER_MINIGAME(pong, "Pong");
+
// minigame flags
const int PONG_STATUS_WAIT = 0x0010; // waiting for players to join
const int PONG_STATUS_PLAY = 0x0020; // playing
// Think equivalent of pong_ball_throw, used to delay throws
void pong_ball_throwthink()
-{
+{SELFPARAM();
pong_ball_throw(self);
}
{
if ( !minigame )
return;
-
+
if ( team_thrower == 0 )
team_thrower = team_receiver;
-
+
if ( team_thrower == team_receiver )
delta *= -1;
-
+
entity paddle_thrower = minigame.pong_paddles[team_thrower-1];
if ( paddle_thrower.realowner.minigame_players )
{
case 3: ball.velocity_y = fabs(ball.velocity_y); break;
case 4: ball.velocity_y = -fabs(ball.velocity_y); break;
}
-
+
float angle = atan2(ball.velocity_y, ball.velocity_x);
angle += ( random() - 0.5 ) * 2 * M_PI/6;
float speed = vlen(ball.velocity);
-
+
ball.velocity_y = speed * sin(angle);
ball.velocity_x = speed * cos(angle);
}
entity paddle = ball.owner.pong_paddles[pteam-1];
if (!paddle)
return false;
- vector near_point = box_nearest(paddle.mins+paddle.origin,
+ vector near_point = box_nearest(paddle.mins+paddle.origin,
paddle.maxs+paddle.origin, ball.origin);
return vlen(near_point-ball.origin) <= ball.pong_length ;
}
entity paddle = ball.owner.pong_paddles[pteam-1];
if (!paddle)
return false;
-
+
if ( !pong_paddle_hit(ball, pteam) )
{
pong_add_score(ball.owner ,ball.team, pteam, 1);
pong_ball_reset(ball);
return true;
}
-
+
return false;
}
// Moves the ball around
void pong_ball_think()
-{
+{SELFPARAM();
float think_speed = autocvar_sys_ticrate;
self.nextthink = time + think_speed;
-
+
self.origin_x += self.velocity_x * think_speed;
self.origin_y += self.velocity_y * think_speed;
self.SendFlags |= MINIG_SF_UPDATE;
-
+
int i;
for ( i = 1; i <= PONG_MAX_PLAYERS; i++ )
if ( pong_paddle_hit(self, i) )
self.SendFlags |= PONG_SF_BALLTEAM;
return;
}
-
+
if ( self.origin_y <= self.pong_length )
{
if ( !pong_goal(self,3) )
self.velocity_y *= -1;
}
}
-
+
if ( self.origin_x <= self.pong_length )
{
if ( !pong_goal(self,2) )
self.velocity_x *= -1;
}
}
-
+
}
// AI action
void pong_ai_think()
-{
+{SELFPARAM();
float think_speed = autocvar_sv_minigames_pong_ai_thinkspeed;
self.nextthink = time + think_speed;
-
+
float distance;
float next_distance;
float min_distance = 1;
ball = mayball;
}
}
-
+
float target = 0.5;
float self_pos;
-
-
+
+
if ( self.team <= 2 )
{
if ( ball )
target = ball.origin_x + ball.velocity_x*think_speed;
self_pos = self.pong_ai_paddle.origin_x;
}
-
+
distance = self.pong_length/2 * autocvar_sv_minigames_pong_ai_tolerance
+ autocvar_sv_minigames_pong_paddle_speed * think_speed;
ai.think = pong_ai_think;
ai.nextthink = time;
ai.pong_ai_paddle = paddle;
-
+
paddle.realowner = ai;
-
+
return ai;
}
// Moves the paddle
void pong_paddle_think()
-{
+{SELFPARAM();
float think_speed = autocvar_sys_ticrate;
self.nextthink = time + think_speed;
- if ( self.realowner.minigame_players.pong_keys == PONG_KEY_INCREASE ||
+ if ( self.realowner.minigame_players.pong_keys == PONG_KEY_INCREASE ||
self.realowner.minigame_players.pong_keys == PONG_KEY_DECREASE )
{
float movement = autocvar_sv_minigames_pong_paddle_speed * think_speed;
float halflen = self.pong_length/2;
-
+
if ( self.realowner.minigame_players.pong_keys == PONG_KEY_DECREASE )
movement *= -1;
-
+
if ( self.team > 2 )
self.origin_x = bound(halflen, self.origin_x+movement, 1-halflen);
else
self.origin_y = bound(halflen, self.origin_y+movement, 1-halflen);
-
+
self.SendFlags |= MINIG_SF_UPDATE;
}
}
paddle.team = pl_team;
paddle.mins = pong_team_to_box_halfsize(pl_team,-paddle.pong_length,-1/16);
paddle.maxs = pong_team_to_box_halfsize(pl_team,paddle.pong_length,1/16);
-
+
if ( real_player == world )
pong_ai_spawn(paddle);
else
paddle.realowner = real_player;
-
+
minigame.pong_paddles[pl_team-1] = paddle;
-
+
return paddle;
}
// Don't allow joining a match that is already running
if ( minigame.minigame_flags & PONG_STATUS_PLAY )
return false;
-
+
entity player = ...(0,entity);
int i;
for ( i = 0; i < PONG_MAX_PLAYERS; i++ )
return i+1;
}
}
-
+
return false;
}
case "part":
ai.pong_score = player.minigame_players.pong_score;
break;
}
-
+
}
return false;
}
minigame.minigame_flags = PONG_STATUS_PLAY |
(minigame.minigame_flags & ~PONG_STATUS_WAIT);
minigame.SendFlags |= MINIG_SF_UPDATE;
-
+
int i;
entity ball;
for ( i = 0; i < autocvar_sv_minigames_pong_ball_number; i++ )
for ( i = PONG_MAX_PLAYERS-1; i >= 0; i-- )
{
paddle = minigame.pong_paddles[i];
- if ( paddle != world &&
+ if ( paddle != world &&
paddle.realowner.classname == "pong_ai" )
{
minigame.pong_paddles[i] = world;
sprint(player.minigame_players,"Cannot remove AI\n");
return true;
}
-
+
}
return false;
}
{
minigame_hud_fitsqare(pos, mySize);
minigame_hud_simpleboard(pos,mySize,minigame_texture("pong/board"));
-
+
entity e;
vector obj_pos;
vector obj_size;
// Note: 4*radius = 2*diameter because the image is large enough to fit the glow around the ball
obj_size = minigame_hud_denormalize_size('4 4 0'*e.pong_length,pos,mySize);
obj_pos = minigame_hud_denormalize(e.origin,pos,mySize);
-
+
minigame_drawpic_centered( obj_pos, minigame_texture("pong/ball"),
obj_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL );
-
+
minigame_drawpic_centered( obj_pos, minigame_texture("pong/ball-glow"),
- obj_size, pong_team_to_color(e.team),
+ obj_size, pong_team_to_color(e.team),
panel_fg_alpha, DRAWFLAG_ADDITIVE );
}
else if ( e.classname == "pong_paddle" )
{
obj_pos = minigame_hud_denormalize(e.origin,pos,mySize);
obj_size = minigame_hud_denormalize_size(eX / 16 + eY*e.pong_length,pos,mySize);
-
- drawrotpic(obj_pos, pong_team_to_angle(e.team), minigame_texture("pong/paddle-glow"),
- obj_size, obj_size/2, pong_team_to_color(e.team),
+
+ drawrotpic(obj_pos, pong_team_to_angle(e.team), minigame_texture("pong/paddle-glow"),
+ obj_size, obj_size/2, pong_team_to_color(e.team),
panel_fg_alpha, DRAWFLAG_ADDITIVE );
-
- drawrotpic(obj_pos, pong_team_to_angle(e.team), minigame_texture("pong/paddle"),
- obj_size, obj_size/2, '1 1 1',
+
+ drawrotpic(obj_pos, pong_team_to_angle(e.team), minigame_texture("pong/paddle"),
+ obj_size, obj_size/2, '1 1 1',
panel_fg_alpha, DRAWFLAG_NORMAL );
-
+
}
}
}
ts_y += hud_fontsize_y;
pos_y += ts_y;
mySize_y -= ts_y;
-
+
vector player_fontsize = hud_fontsize * 1.75;
ts_y = ( mySize_y - PONG_MAX_PLAYERS*player_fontsize_y ) / PONG_MAX_PLAYERS;
ts_x = mySize_x;
{
mypos = pos;
mypos_y += (e.team-1) * (player_fontsize_y + ts_y);
-
+
drawfill(mypos, ts, pong_team_to_color(e.team), 0.25, DRAWFLAG_ADDITIVE);
-
+
minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
(e.minigame_playerslot ? GetPlayerName(e.minigame_playerslot-1) : _("AI")),
player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
-
+
drawstring(mypos+eY*player_fontsize_y,ftos(e.pong_score),'48 48 0',
'0.7 0.84 1', panel_fg_alpha, DRAWFLAG_NORMAL);
-
+
if ( e == minigame_self )
drawborderlines(1, mypos, ts, pong_team_to_color(e.team), 1, DRAWFLAG_NORMAL);
}
+REGISTER_MINIGAME(pp, "Push-Pull");
+
const int PP_TURN_PLACE = 0x0100; // player has to place a piece on the board
const int PP_TURN_WIN = 0x0200; // player has won
const int PP_TURN_DRAW = 0x0400; // players have equal scores
if(!pp_valid_tile(minigame_tile_buildname(letter+1,number-1)) || pp_find_piece(piece.owner,minigame_tile_buildname(letter+1,number-1)).team == 5)
if(!pp_valid_tile(minigame_tile_buildname(letter-1,number+1)) || pp_find_piece(piece.owner,minigame_tile_buildname(letter-1,number+1)).team == 5)
return true;
-
+
return false;
}
{
switch(argv(0))
{
- case "move":
- pp_move(minigame, ...(0,entity), ...(1,int) == 2 ? argv(1) : string_null );
+ case "move":
+ pp_move(minigame, ...(0,entity), ...(1,int) == 2 ? argv(1) : string_null );
return true;
case "next":
pp_next_match(minigame,...(0,entity));
return false;
}
}
-
+
return false;
}
minigame_hud_fitsqare(pos, mySize);
pp_boardpos = pos;
pp_boardsize = mySize;
-
+
minigame_hud_simpleboard(pos,mySize,minigame_texture("pp/board"));
vector tile_size = minigame_hud_denormalize_size('1 1 0'/PP_TILE_SIZE,pos,mySize);
case 2: tile_color = '0.3 0.3 1'; break;
// 3, 4 coming later?
}
-
+
string tile_name = strcat("pp/piece",ftos(e.team));
if(e.team == 5) { tile_name = "pp/piece_taken"; }
tile_name = "pp/piece_current";
// draw the splat too
- minigame_drawpic_centered( tile_pos,
+ minigame_drawpic_centered( tile_pos,
minigame_texture("pp/piece_taken"),
tile_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL );
}
- minigame_drawpic_centered( tile_pos,
+ minigame_drawpic_centered( tile_pos,
minigame_texture(tile_name),
tile_size, tile_color, panel_fg_alpha, DRAWFLAG_NORMAL );
}
{
tile_pos = minigame_tile_pos(pp_curr_pos,PP_LET_CNT,PP_NUM_CNT);
tile_pos = minigame_hud_denormalize(tile_pos,pos,mySize);
- minigame_drawpic_centered( tile_pos,
+ minigame_drawpic_centered( tile_pos,
minigame_texture("pp/piece_current"),
tile_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL );
}
{
tile_pos = minigame_tile_pos(pp_curr_pos,PP_LET_CNT,PP_NUM_CNT);
tile_pos = minigame_hud_denormalize(tile_pos,pos,mySize);
- minigame_drawpic_centered( tile_pos,
+ minigame_drawpic_centered( tile_pos,
minigame_texture("pp/piece_selected"),
tile_size, '1 1 1', panel_fg_alpha / 2, DRAWFLAG_NORMAL );
}
vector winfs = hud_fontsize*2;
string playername = "";
FOREACH_MINIGAME_ENTITY(e)
- if ( e.classname == "minigame_player" &&
+ if ( e.classname == "minigame_player" &&
e.team == (active_minigame.minigame_flags & PP_TURN_TEAM) )
playername = GetPlayerName(e.minigame_playerslot-1);
-
+
vector win_pos = pos+eY*(mySize_y-winfs_y)/2;
vector win_sz;
win_sz = minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
- sprintf("%s^7 won the game!",playername),
+ sprintf("%s^7 won the game!",playername),
winfs, 0, DRAWFLAG_NORMAL, 0.5);
-
+
drawfill(win_pos-eY*hud_fontsize_y,win_sz+2*eY*hud_fontsize_y,'1 1 1',0.5,DRAWFLAG_ADDITIVE);
-
+
minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
- sprintf("%s^7 won the game!",playername),
+ sprintf("%s^7 won the game!",playername),
winfs, panel_fg_alpha, DRAWFLAG_NORMAL, 0.5);
}
}
vector ts;
ts = minigame_drawstring_wrapped(mySize_x,pos,active_minigame.descriptor.message,
hud_fontsize * 2, '0.25 0.47 0.72', panel_fg_alpha, DRAWFLAG_NORMAL,0.5);
-
+
pos_y += ts_y;
mySize_y -= ts_y;
-
+
vector player_fontsize = hud_fontsize * 1.75;
ts_y = ( mySize_y - 2*player_fontsize_y ) / 2;
ts_x = mySize_x;
minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
GetPlayerName(e.minigame_playerslot-1),
player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
-
+
mypos_y += player_fontsize_y;
- drawpic( mypos,
+ drawpic( mypos,
minigame_texture(strcat("pp/piece",ftos(e.team))),
tile_size, tile_color, panel_fg_alpha, DRAWFLAG_NORMAL );
-
+
mypos_x += tile_size_x;
int myscore = 0;
if(e.team == 1) { myscore = active_minigame.pp_team1_score; }
if(e.team == 2) { myscore = active_minigame.pp_team2_score; }
-
+
drawstring(mypos,ftos(myscore),tile_size,
'0.7 0.84 1', panel_fg_alpha, DRAWFLAG_NORMAL);
}
{
if ( turnflags & PP_TURN_DRAW )
return _("Draw");
-
+
if ( turnflags & PP_TURN_WIN )
{
if ( (turnflags&PP_TURN_TEAM) != minigame_self.team )
return _("You lost the game!\nSelect \"^1Next Match^7\" on the menu for a rematch!");
return _("You win!\nSelect \"^1Next Match^7\" on the menu to start a new match!");
}
-
+
if ( turnflags & PP_TURN_NEXT )
{
if ( (turnflags&PP_TURN_TEAM) != minigame_self.team )
return _("Select \"^1Next Match^7\" on the menu to start a new match!");
return _("Wait for your opponent to confirm the rematch");
}
-
+
if ( (turnflags & PP_TURN_TEAM) != minigame_self.team )
return _("Wait for your opponent to make their move");
-
+
if ( turnflags & PP_TURN_PLACE )
return _("Click on the game board to place your piece");
-
+
return "";
}
return false;
}
-#endif
\ No newline at end of file
+#endif
+REGISTER_MINIGAME(ps, "Peg Solitaire");
+
const float PS_TURN_MOVE = 0x0100; // player has to click on a piece on the board
const float PS_TURN_WIN = 0x0200; // player has won
const float PS_TURN_DRAW = 0x0400; // player can make no more moves
return false; // a move is valid, abort!
}
}
-
+
return true;
}
{
switch(argv(0))
{
- case "move":
+ case "move":
ps_move(minigame, ...(0,entity), (...(1,int) == 3 ? argv(1) : string_null), (...(1,int) == 3 ? argv(2) : string_null));
return true;
return false;
}
}
-
+
return false;
}
minigame_hud_fitsqare(pos, mySize);
ps_boardpos = pos;
ps_boardsize = mySize;
-
+
minigame_hud_simpleboard(pos,mySize,minigame_texture("ps/board"));
vector tile_size = minigame_hud_denormalize_size('1 1 0' / PS_TILE_SIZE,pos,mySize);
draw_pos = true;
}
}
-
+
entity e;
FOREACH_MINIGAME_ENTITY(e)
{
if(e.netname == ps_curr_pos)
if(ps_curr_piece.netname != ps_curr_pos)
{
- minigame_drawpic_centered( tile_pos,
+ minigame_drawpic_centered( tile_pos,
minigame_texture("ps/tile_available"),
tile_size, tile_color, panel_fg_alpha, DRAWFLAG_NORMAL );
}
if(e == ps_curr_piece)
{
- minigame_drawpic_centered( tile_pos,
+ minigame_drawpic_centered( tile_pos,
minigame_texture("ps/tile_selected"),
tile_size, tile_color, panel_fg_alpha, DRAWFLAG_ADDITIVE );
}
- minigame_drawpic_centered( tile_pos,
+ minigame_drawpic_centered( tile_pos,
minigame_texture("ps/piece"),
tile_size * 0.8, tile_color, panel_fg_alpha, DRAWFLAG_NORMAL );
}
remaining_text = "All pieces cleared!";
else
remaining_text = strcat("Remaining pieces: ", ftos(remaining));
-
+
vector win_pos = pos+eY*(mySize_y-winfs_y)/2;
vector win_sz;
win_sz = minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
- sprintf("Game over! %s", remaining_text),
+ sprintf("Game over! %s", remaining_text),
winfs, 0, DRAWFLAG_NORMAL, 0.5);
-
+
drawfill(win_pos-eY*hud_fontsize_y,win_sz+2*eY*hud_fontsize_y,'1 1 1',0.5,DRAWFLAG_ADDITIVE);
-
+
minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
- sprintf("Game over! %s", remaining_text),
+ sprintf("Game over! %s", remaining_text),
winfs, panel_fg_alpha, DRAWFLAG_NORMAL, 0.5);
}
}
vector ts;
ts = minigame_drawstring_wrapped(mySize_x,pos,active_minigame.descriptor.message,
hud_fontsize * 2, '0.25 0.47 0.72', panel_fg_alpha, DRAWFLAG_NORMAL,0.5);
-
+
pos_y += ts_y;
mySize_y -= ts_y;
-
+
vector player_fontsize = hud_fontsize * 1.75;
ts_y = ( mySize_y - 2*player_fontsize_y ) / 2;
ts_x = mySize_x;
minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
GetPlayerName(e.minigame_playerslot-1),
player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
-
+
mypos_y += player_fontsize_y;
- //drawpic( mypos,
+ //drawpic( mypos,
// minigame_texture("ps/piece"),
// tile_size, '1 0 0', panel_fg_alpha, DRAWFLAG_NORMAL );
-
+
//mypos_x += tile_size_x;
drawstring(mypos,sprintf(_("Pieces left: %s"), ftos(remaining)),'28 28 0',
if ( turnflags & PS_TURN_WIN )
return _("Well done, you win!");
-
+
if ( turnflags & PS_TURN_MOVE )
return _("Jump a piece over another to capture it");
-
+
return "";
}
return false;
}
-#endif
\ No newline at end of file
+#endif
+++ /dev/null
-const float QTO_TURN_MOVE = 0x0100; // player has to click on a piece on the board
-const float QTO_TURN_WIN = 0x0200; // player has won
-const float QTO_TURN_TYPE = 0x0f00; // turn type mask
-
-const int QTO_SF_PLAYERSCORE = MINIG_SF_CUSTOM;
-
-const int QTO_LET_CNT = 5;
-const int QTO_NUM_CNT = 5;
-
-const int QTO_TILE_SIZE = 8;
-
-.int qto_moves;
-
-// find same game piece given its tile name
-entity qto_find_piece(entity minig, string tile)
-{
- entity e = world;
- while ( ( e = findentity(e,owner,minig) ) )
- if ( e.classname == "minigame_board_piece" && e.netname == tile )
- return e;
- return world;
-}
-
-// Checks if the given piece completes a row
-bool qto_winning_piece(entity minigame)
-{
- //int number = minigame_tile_number(piece.netname);
- //int letter = minigame_tile_letter(piece.netname);
-
- entity e = world;
- while ( ( e = findentity(e,owner,minigame) ) )
- if ( e.classname == "minigame_board_piece" )
- {
- if(!e.cnt)
- return false;
- }
-
- return true;
-}
-
-// check if the tile name is valid (5x5 grid)
-bool qto_valid_tile(string tile)
-{
- if ( !tile )
- return false;
- float number = minigame_tile_number(tile);
- float letter = minigame_tile_letter(tile);
- return 0 <= number && number < QTO_NUM_CNT && 0 <= letter && letter < QTO_LET_CNT;
-}
-
-void qto_setup_pieces(entity minigame)
-{
- int i, t;
- for(i = 0; i < QTO_NUM_CNT; ++i)
- for(t = 0; t < QTO_LET_CNT; ++t)
- {
- entity piece = msle_spawn(minigame,"minigame_board_piece");
- piece.team = 1; // init default team?
- piece.cnt = 0; // initialize cnt
- piece.netname = strzone(minigame_tile_buildname(t,i));
- minigame_server_sendflags(piece,MINIG_SF_ALL);
- }
-
- minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
-}
-
-void qto_add_score(entity minigame, int thescore)
-{
-#ifdef SVQC
- if(!minigame)
- return;
- if(minigame.minigame_players)
- {
- minigame.minigame_players.qto_moves += thescore;
- minigame.minigame_players.SendFlags |= QTO_SF_PLAYERSCORE;
- }
-#endif
-}
-
-// make a move
-void qto_move(entity minigame, entity player, string pos )
-{
- if ( minigame.minigame_flags & QTO_TURN_MOVE )
- if ( pos )
- {
- if ( qto_valid_tile(pos) )
- if ( qto_find_piece(minigame, pos) )
- {
- entity piece;
- #define DO_JUNK \
- if(piece) \
- { \
- piece.cnt = (piece.cnt) ? 0 : 1; \
- minigame_server_sendflags(piece,MINIG_SF_UPDATE); \
- }
-
- int number = minigame_tile_number(pos);
- int letter = minigame_tile_letter(pos);
- piece = qto_find_piece(minigame, pos);
- DO_JUNK
- piece = qto_find_piece(minigame, minigame_tile_buildname(letter-1,number));
- DO_JUNK
- piece = qto_find_piece(minigame, minigame_tile_buildname(letter+1,number));
- DO_JUNK
- piece = qto_find_piece(minigame, minigame_tile_buildname(letter,number-1));
- DO_JUNK
- piece = qto_find_piece(minigame, minigame_tile_buildname(letter,number+1));
- DO_JUNK
-
- qto_add_score(minigame,1); // add 1 move score
-
- minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
-
- if ( qto_winning_piece(minigame) )
- {
- minigame.minigame_flags = QTO_TURN_WIN;
- }
- else
- minigame.minigame_flags = QTO_TURN_MOVE;
- }
- }
-}
-
-// restart match
-void qto_restart_match(entity minigame, entity player)
-{
- minigame.minigame_flags = QTO_TURN_MOVE;
- minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
- entity e = world;
- while ( ( e = findentity(e,owner,minigame) ) )
- if ( e.classname == "minigame_board_piece" )
- remove(e);
-
- qto_setup_pieces(minigame);
-#ifdef SVQC
- if(minigame.minigame_players)
- {
- minigame.minigame_players.qto_moves = 0;
- minigame.minigame_players.SendFlags |= QTO_SF_PLAYERSCORE;
- }
-#endif
-}
-
-#ifdef SVQC
-
-
-// required function, handle server side events
-int qto_server_event(entity minigame, string event, ...)
-{
- switch(event)
- {
- case "start":
- {
- qto_setup_pieces(minigame);
- minigame.minigame_flags = QTO_TURN_MOVE;
- return true;
- }
- case "end":
- {
- entity e = world;
- while( (e = findentity(e, owner, minigame)) )
- if(e.classname == "minigame_board_piece")
- {
- if(e.netname) { strunzone(e.netname); }
- remove(e);
- }
- return false;
- }
- case "join":
- {
- int pl_num = minigame_count_players(minigame);
-
- // Don't allow more than 1 player
- if(pl_num >= 1) { return false; }
-
- // Team 1 by default
- return 1;
- }
- case "cmd":
- {
- switch(argv(0))
- {
- case "move":
- qto_move(minigame, ...(0,entity), ...(1,int) == 2 ? argv(1) : string_null );
- return true;
- case "restart":
- qto_restart_match(minigame,...(0,entity));
- return true;
- }
-
- return false;
- }
- case "network_send":
- {
- entity sent = ...(0,entity);
- int sf = ...(1,int);
- if ( sent.classname == "minigame_board_piece" && (sf & MINIG_SF_UPDATE) )
- {
- WriteByte(MSG_ENTITY,sent.cnt);
- }
- else if ( sent.classname == "minigame_player" && (sf & QTO_SF_PLAYERSCORE ) )
- {
- WriteLong(MSG_ENTITY,sent.qto_moves);
- }
- return false;
- }
- }
-
- return false;
-}
-
-
-#elif defined(CSQC)
-
-string qto_curr_pos; // identifier of the tile under the mouse
-vector qto_boardpos; // HUD board position
-vector qto_boardsize;// HUD board size
-
-// Required function, draw the game board
-void qto_hud_board(vector pos, vector mySize)
-{
- minigame_hud_fitsqare(pos, mySize);
- qto_boardpos = pos;
- qto_boardsize = mySize;
-
- minigame_hud_simpleboard(pos,mySize,minigame_texture("qto/board"));
-
- vector tile_size = minigame_hud_denormalize_size('1 1 0' / QTO_TILE_SIZE,pos,mySize);
- vector tile_pos;
-
- bool valid = qto_valid_tile(qto_curr_pos);
- int number = minigame_tile_number(qto_curr_pos);
- int letter = minigame_tile_letter(qto_curr_pos);
- string pos1 = minigame_tile_buildname(letter-1,number);
- string pos2 = minigame_tile_buildname(letter+1,number);
- string pos3 = minigame_tile_buildname(letter,number-1);
- string pos4 = minigame_tile_buildname(letter,number+1);
-
- entity e;
- FOREACH_MINIGAME_ENTITY(e)
- {
- if ( e.classname == "minigame_board_piece" )
- {
- tile_pos = minigame_tile_pos(e.netname,QTO_NUM_CNT,QTO_LET_CNT);
- tile_pos = minigame_hud_denormalize(tile_pos,pos,mySize);
-
- vector tile_color = '0.4 0.4 0.4';
-
- if(valid)
- switch(e.netname)
- {
- case qto_curr_pos:
- case pos1: case pos2: case pos3: case pos4:
- tile_color = '0.8 0.8 0.8';
- break;
- }
-
- minigame_drawpic_centered( tile_pos,
- minigame_texture(strcat("qto/piece", ftos(e.cnt))),
- tile_size, tile_color, panel_fg_alpha, DRAWFLAG_NORMAL );
- }
- }
-}
-
-
-// Required function, draw the game status panel
-void qto_hud_status(vector pos, vector mySize)
-{
- HUD_Panel_DrawBg(1);
- vector ts;
- ts = minigame_drawstring_wrapped(mySize_x,pos,active_minigame.descriptor.message,
- hud_fontsize * 2, '0.25 0.47 0.72', panel_fg_alpha, DRAWFLAG_NORMAL,0.5);
-
- pos_y += ts_y;
- mySize_y -= ts_y;
-
- vector player_fontsize = hud_fontsize * 1.75;
- ts_y = ( mySize_y - 2*player_fontsize_y ) / 2;
- ts_x = mySize_x;
- vector mypos;
- vector tile_size = '48 48 0';
-
- mypos = pos;
- drawfill(mypos,eX*mySize_x+eY*player_fontsize_y,'1 1 1',0.5,DRAWFLAG_ADDITIVE);
- mypos_y += player_fontsize_y;
- drawfill(mypos,eX*mySize_x+eY*tile_size_y,'1 1 1',0.25,DRAWFLAG_ADDITIVE);
-
- entity e;
- FOREACH_MINIGAME_ENTITY(e)
- {
- if ( e.classname == "minigame_player" )
- {
- mypos = pos;
- minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
- GetPlayerName(e.minigame_playerslot-1),
- player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
-
- mypos_y += player_fontsize_y;
- //drawpic( mypos,
- // minigame_texture("qto/piece"),
- // tile_size, '1 0 0', panel_fg_alpha, DRAWFLAG_NORMAL );
-
- //mypos_x += tile_size_x;
-
- drawstring(mypos,sprintf(_("Moves: %s"), ftos(e.qto_moves)),'32 32 0',
- '0.7 0.84 1', panel_fg_alpha, DRAWFLAG_NORMAL);
- }
- }
-}
-
-// Turn a set of flags into a help message
-string qto_turn_to_string(int turnflags)
-{
- if ( turnflags & QTO_TURN_WIN )
- return _("Well done, you win!");
-
- if ( turnflags & QTO_TURN_MOVE )
- return _("Turn all the angry faces into happy faces");
-
- return "";
-}
-
-// Make the correct move
-void qto_make_move(entity minigame)
-{
- if ( minigame.minigame_flags == QTO_TURN_MOVE )
- {
- minigame_cmd("move ",qto_curr_pos);
- }
-}
-
-void qto_set_curr_pos(string s)
-{
- if ( qto_curr_pos )
- strunzone(qto_curr_pos);
- if ( s )
- s = strzone(s);
- qto_curr_pos = s;
-}
-
-// Required function, handle client events
-int qto_client_event(entity minigame, string event, ...)
-{
- switch(event)
- {
- case "activate":
- {
- qto_set_curr_pos("");
- minigame.message = qto_turn_to_string(minigame.minigame_flags);
- return false;
- }
- case "key_pressed":
- {
- //if((minigame.minigame_flags & QTO_TURN_TEAM) == minigame_self.team)
- {
- switch ( ...(0,int) )
- {
- case K_RIGHTARROW:
- case K_KP_RIGHTARROW:
- if ( ! qto_curr_pos )
- qto_set_curr_pos("a3");
- else
- qto_set_curr_pos( minigame_relative_tile(qto_curr_pos,1,0,QTO_NUM_CNT,QTO_LET_CNT));
- return true;
- case K_LEFTARROW:
- case K_KP_LEFTARROW:
- if ( ! qto_curr_pos )
- qto_set_curr_pos("c3");
- else
- qto_set_curr_pos(minigame_relative_tile(qto_curr_pos,-1,0,QTO_NUM_CNT,QTO_LET_CNT));
- return true;
- case K_UPARROW:
- case K_KP_UPARROW:
- if ( ! qto_curr_pos )
- qto_set_curr_pos("a1");
- else
- qto_set_curr_pos(minigame_relative_tile(qto_curr_pos,0,1,QTO_NUM_CNT,QTO_LET_CNT));
- return true;
- case K_DOWNARROW:
- case K_KP_DOWNARROW:
- if ( ! qto_curr_pos )
- qto_set_curr_pos("a3");
- else
- qto_set_curr_pos(minigame_relative_tile(qto_curr_pos,0,-1,QTO_NUM_CNT,QTO_LET_CNT));
- return true;
- case K_ENTER:
- case K_KP_ENTER:
- case K_SPACE:
- qto_make_move(minigame);
- return true;
- }
- }
-
- return false;
- }
- case "mouse_pressed":
- {
- if(...(0,int) == K_MOUSE1)
- {
- qto_make_move(minigame);
- return true;
- }
-
- return false;
- }
- case "mouse_moved":
- {
- vector mouse_pos = minigame_hud_normalize(mousepos,qto_boardpos,qto_boardsize);
- if ( minigame.minigame_flags == QTO_TURN_MOVE )
- {
- qto_set_curr_pos(minigame_tile_name(mouse_pos,QTO_NUM_CNT,QTO_LET_CNT));
- }
- if ( ! qto_valid_tile(qto_curr_pos) )
- qto_set_curr_pos("");
-
- return true;
- }
- case "network_receive":
- {
- entity sent = ...(0,entity);
- int sf = ...(1,int);
- if ( sent.classname == "minigame" )
- {
- if ( sf & MINIG_SF_UPDATE )
- {
- sent.message = qto_turn_to_string(sent.minigame_flags);
- if ( sent.minigame_flags & minigame_self.team )
- minigame_prompt();
- }
- }
- else if(sent.classname == "minigame_board_piece")
- {
- if(sf & MINIG_SF_UPDATE)
- {
- sent.cnt = ReadByte();
- }
- }
- else if ( sent.classname == "minigame_player" && (sf & QTO_SF_PLAYERSCORE ) )
- {
- sent.qto_moves = ReadLong();
- }
-
- return false;
- }
- case "menu_show":
- {
- HUD_MinigameMenu_CustomEntry(...(0,entity),_("Restart"),"restart");
- return false;
- }
- case "menu_click":
- {
- if(...(0,string) == "restart")
- minigame_cmd("restart");
- return false;
- }
- }
-
- return false;
-}
-
-#endif
\ No newline at end of file
--- /dev/null
+REGISTER_MINIGAME(snake, "Snake"); // SNAAAAKE
+
+const float SNAKE_TURN_MOVE = 0x0100; // the snake is moving, player must control it
+const float SNAKE_TURN_WIN = 0x0200; // multiplayer victory
+const float SNAKE_TURN_LOSS = 0x0400; // they did it?!
+const float SNAKE_TURN_TYPE = 0x0f00; // turn type mask
+
+const int SNAKE_TURN_TEAM = 0x000f; // turn team mask
+
+const int SNAKE_SF_PLAYERSCORE = MINIG_SF_CUSTOM;
+
+const int SNAKE_LET_CNT = 15;
+const int SNAKE_NUM_CNT = 15;
+
+const int SNAKE_TILE_SIZE = 15;
+
+const int SNAKE_TEAMS = 6;
+
+bool autocvar_sv_minigames_snake_wrap = false;
+float autocvar_sv_minigames_snake_delay_initial = 0.7;
+float autocvar_sv_minigames_snake_delay_multiplier = 50;
+float autocvar_sv_minigames_snake_delay_min = 0.1;
+int autocvar_sv_minigames_snake_lives = 3;
+
+.int snake_score;
+
+.float snake_delay;
+.vector snake_dir;
+
+.entity snake_next, snake_last, snake_prev;
+
+.bool snake_tail;
+
+.int snake_lives[SNAKE_TEAMS + 1];
+
+.int snake_lost_teams;
+
+bool snake_alone(entity minig)
+{
+ int headcount = 0;
+ entity e = world;
+ while ( ( e = findentity(e,owner,minig) ) )
+ if ( e.classname == "minigame_board_piece" && e.cnt == 1 )
+ ++headcount;
+
+ return headcount <= 1;
+}
+
+// find same game piece given its tile name
+entity snake_find_piece(entity minig, string tile)
+{
+ entity e = world;
+ while ( ( e = findentity(e,owner,minig) ) )
+ if ( e.classname == "minigame_board_piece" && e.netname == tile )
+ return e;
+ return world;
+}
+
+// find same game piece given its cnt
+entity snake_find_cnt(entity minig, int steam, int tile)
+{
+ entity e = world;
+ while ( ( e = findentity(e,owner,minig) ) )
+ if ( e.classname == "minigame_board_piece" && e.cnt == tile && e.team == steam )
+ return e;
+ return world;
+}
+
+// check if the tile name is valid (15x15 grid)
+bool snake_valid_tile(string tile)
+{
+ if ( !tile )
+ return false;
+ int number = minigame_tile_number(tile);
+ int letter = minigame_tile_letter(tile);
+ return 0 <= number && number < SNAKE_NUM_CNT && 0 <= letter && letter < SNAKE_LET_CNT;
+}
+
+entity snake_find_head(entity minig, int steam)
+{
+ entity e = world;
+ while ( ( e = findentity(e,owner,minig) ) )
+ if ( e.classname == "minigame_board_piece" && e.cnt == 1 && e.team == steam )
+ return e;
+ return world;
+}
+
+void snake_new_mouse(entity minigame)
+{
+ RandomSelection_Init();
+ int i, j;
+ for(i = 0; i < SNAKE_LET_CNT; ++i)
+ for(j = 0; j < SNAKE_NUM_CNT; ++j)
+ {
+ string pos = minigame_tile_buildname(i, j);
+ if(!snake_find_piece(minigame, pos))
+ RandomSelection_Add(world, 0, pos, 1, 1);
+ }
+
+ entity piece = msle_spawn(minigame,"minigame_board_piece");
+ piece.team = 0;
+ piece.netname = strzone(RandomSelection_chosen_string);
+ minigame_server_sendflags(piece,MINIG_SF_ALL);
+
+ minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+}
+
+entity snake_get_player(entity minigame, int pteam);
+int snake_winning_team(entity minigame)
+{
+ int winning_team = 0;
+ for(int i = 1; i <= SNAKE_TEAMS; ++i)
+ {
+ entity pl = snake_get_player(minigame, i);
+ if(pl && minigame.snake_lives[i] > 0)
+ {
+ if(winning_team)
+ return 0;
+ winning_team = i;
+ }
+ }
+
+ return winning_team;
+}
+
+void snake_check_winner(entity minigame)
+{
+ if(snake_alone(minigame) && !minigame.snake_lost_teams)
+ return;
+
+ int winner = snake_winning_team(minigame);
+
+ int alivecnt = 0;
+ for(int i = 1; i <= SNAKE_TEAMS; ++i)
+ {
+ entity pl = snake_get_player(minigame, i);
+ if(pl && minigame.snake_lives[i] > 0)
+ ++alivecnt;
+ }
+
+ if(!alivecnt)
+ {
+ minigame.minigame_flags = SNAKE_TURN_LOSS;
+ minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+ return;
+ }
+
+ if(winner)
+ {
+ minigame.minigame_flags = SNAKE_TURN_WIN | winner;
+ minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+ }
+}
+
+void snake_move_head(entity minigame, entity head);
+void snake_head_think()
+{
+ entity minigame = self.owner;
+
+ if(minigame.minigame_flags & SNAKE_TURN_MOVE)
+ snake_move_head(minigame, self);
+
+ snake_check_winner(minigame);
+
+ self.nextthink = time + self.snake_delay;
+}
+
+void minigame_setup_snake(entity minigame, int pteam)
+{
+ RandomSelection_Init();
+ int i, j;
+ for(i = 1; i < SNAKE_LET_CNT - 1; ++i)
+ for(j = 1; j < SNAKE_NUM_CNT - 1; ++j)
+ {
+ string pos = minigame_tile_buildname(i, j);
+ if(!snake_find_piece(minigame, pos))
+ RandomSelection_Add(world, 0, pos, 1, 1);
+ }
+
+ entity piece = msle_spawn(minigame,"minigame_board_piece");
+ piece.team = pteam;
+ piece.netname = strzone(RandomSelection_chosen_string);
+ piece.cnt = 1;
+ piece.snake_next = world;
+ piece.snake_prev = world;
+ piece.snake_last = piece;
+ piece.think = snake_head_think;
+ piece.snake_delay = autocvar_sv_minigames_snake_delay_initial;
+ piece.nextthink = time + 0.1;
+ minigame_server_sendflags(piece,MINIG_SF_ALL);
+}
+
+void snake_setup_pieces(entity minigame)
+{
+ snake_new_mouse(minigame);
+
+ minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+}
+
+entity snake_get_player(entity minigame, int pteam)
+{
+ entity e;
+#ifdef SVQC
+ for(e = minigame.minigame_players; e; e = e.list_next)
+#elif defined(CSQC)
+ e = world;
+ while( (e = findentity(e,owner,minigame)) )
+ if ( e.classname == "minigame_player" )
+#endif
+ if(e.team == pteam)
+ return e;
+ return world;
+}
+
+void snake_add_score(entity minigame, int pteam, int thescore)
+{
+#ifdef SVQC
+ if(!minigame)
+ return;
+ entity pl = snake_get_player(minigame, pteam);
+ if(pl)
+ {
+ pl.snake_score += thescore;
+ pl.SendFlags |= SNAKE_SF_PLAYERSCORE;
+ }
+#endif
+}
+
+void snake_move_body(entity minigame, entity head, bool ate_mouse)
+{
+ for(entity e = head.snake_last; e; e = e.snake_prev)
+ {
+ if(!e || e == head) { break; }
+
+ entity nextpiece = e.snake_prev; // can be head
+
+ if(e.netname) { strunzone(e.netname); }
+ e.netname = strzone(nextpiece.netname);
+ e.snake_dir = nextpiece.snake_dir;
+ minigame_server_sendflags(e, MINIG_SF_UPDATE);
+ }
+
+ if(ate_mouse)
+ {
+ entity tail = head.snake_last;
+
+ tail.snake_tail = false;
+
+ int newcnt = tail.cnt + 1;
+ head.snake_delay = max(autocvar_sv_minigames_snake_delay_min, autocvar_sv_minigames_snake_delay_initial - (newcnt / autocvar_sv_minigames_snake_delay_multiplier));
+ snake_add_score(minigame, head.team, 1);
+
+ entity piece = msle_spawn(minigame,"minigame_board_piece");
+ piece.cnt = newcnt;
+ piece.team = head.team;
+ piece.snake_prev = tail;
+ piece.snake_dir = tail.snake_dir;
+ piece.snake_next = world;
+ piece.snake_tail = true;
+ piece.netname = strzone(tail.netname);
+
+ tail.snake_next = piece;
+ head.snake_last = piece;
+
+ minigame_server_sendflags(piece,MINIG_SF_UPDATE);
+
+ //minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+ }
+}
+
+void snake_eat_team(entity minigame, int pteam)
+{
+ entity head = snake_find_head(minigame, pteam);
+ if(!head) { return; }
+
+ minigame.snake_lives[pteam] -= 1;
+
+ entity pl = snake_get_player(minigame, pteam);
+#ifdef SVQC
+ pl.SendFlags |= SNAKE_SF_PLAYERSCORE;
+#endif
+
+ head.nextthink = time + 1; // make sure they don't to eat us somehow
+
+ entity e = world;
+ while ( ( e = findentity(e,owner,minigame) ) )
+ if ( e.classname == "minigame_board_piece" && e.cnt && e.team == pteam )
+ {
+ if(e.netname) { strunzone(e.netname); }
+ remove(e);
+ }
+
+ if(minigame.snake_lives[pteam] <= 0)
+ minigame.snake_lost_teams |= BIT(pteam);
+
+ if(pl && minigame.snake_lives[pteam] > 0)
+ minigame_setup_snake(minigame, pteam);
+}
+
+void snake_move_head(entity minigame, entity head)
+{
+ if(!head.snake_dir_x && !head.snake_dir_y)
+ return; // nope!
+
+ string newpos;
+
+ if(autocvar_sv_minigames_snake_wrap)
+ newpos = minigame_relative_tile(head.netname, head.snake_dir_x, head.snake_dir_y, SNAKE_NUM_CNT, SNAKE_LET_CNT);
+ else
+ {
+ int myx = minigame_tile_letter(head.netname);
+ int myy = minigame_tile_number(head.netname);
+
+ myx += head.snake_dir_x;
+ myy += head.snake_dir_y;
+
+ newpos = minigame_tile_buildname(myx, myy);
+ }
+
+ entity hit = snake_find_piece(minigame, newpos);
+
+ if(!snake_valid_tile(newpos) || (hit && hit.cnt && hit.team == head.team))
+ {
+ if(snake_alone(minigame))
+ {
+ minigame.minigame_flags = SNAKE_TURN_LOSS;
+ minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+ }
+ else
+ {
+ snake_add_score(minigame, head.team, -1);
+ snake_eat_team(minigame, head.team);
+ }
+
+ return;
+ }
+
+ bool ate_mouse = (hit && !hit.cnt);
+
+ // move the body first, then set the new head position?
+ snake_move_body(minigame, head, ate_mouse);
+
+ if(head.netname) { strunzone(head.netname); }
+ head.netname = strzone(newpos);
+ minigame_server_sendflags(head,MINIG_SF_UPDATE);
+
+ // above check makes sure it's not our team
+ if(hit.cnt)
+ {
+ snake_eat_team(minigame, hit.team);
+ snake_add_score(minigame, head.team, 1);
+ }
+
+ if(ate_mouse)
+ {
+ if(hit.netname) { strunzone(hit.netname); }
+ remove(hit);
+
+ snake_new_mouse(minigame);
+ }
+}
+
+// make a move
+void snake_move(entity minigame, entity player, string dxs, string dys )
+{
+ if ( minigame.minigame_flags & SNAKE_TURN_MOVE )
+ if ( dxs || dys )
+ {
+ //if ( snake_valid_tile(pos) )
+ //if ( snake_find_piece(minigame, pos) )
+ {
+ entity head = snake_find_head(minigame, player.team);
+ if(!head)
+ return; // their head is already dead
+
+ int dx = ((dxs) ? bound(-1, stof(dxs), 1) : 0);
+ int dy = ((dys) ? bound(-1, stof(dys), 1) : 0);
+
+ int myl = minigame_tile_letter(head.netname);
+ int myn = minigame_tile_number(head.netname);
+
+ entity check_piece = snake_find_piece(minigame, minigame_tile_buildname(myl + dx, myn + dy));
+ if(check_piece && check_piece.cnt == 2)
+ return; // nope!
+
+ if(head.snake_dir == '0 0 0')
+ head.nextthink = time; // TODO: make sure this can't be exploited!
+ head.snake_dir_x = dx;
+ head.snake_dir_y = dy;
+ head.snake_dir_z = 0;
+ minigame_server_sendflags(head,MINIG_SF_UPDATE);
+ minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+ }
+ }
+}
+
+#ifdef SVQC
+
+
+// required function, handle server side events
+int snake_server_event(entity minigame, string event, ...)
+{
+ switch(event)
+ {
+ case "start":
+ {
+ snake_setup_pieces(minigame);
+ minigame.minigame_flags = SNAKE_TURN_MOVE;
+ minigame.snake_lost_teams = 0;
+
+ if(SNAKE_TEAMS > 1)
+ {
+ for(int i = 1; i <= SNAKE_TEAMS; ++i)
+ minigame.snake_lives[i] = autocvar_sv_minigames_snake_lives;
+ }
+ else
+ minigame.snake_lives[1] = 1;
+
+ return true;
+ }
+ case "end":
+ {
+ entity e = world;
+ while( (e = findentity(e, owner, minigame)) )
+ if(e.classname == "minigame_board_piece")
+ {
+ if(e.netname) { strunzone(e.netname); }
+ remove(e);
+ }
+ return false;
+ }
+ case "join":
+ {
+ int pl_num = minigame_count_players(minigame);
+
+ if(pl_num >= SNAKE_TEAMS) { return false; }
+
+ int t = 1; // Team 1 by default
+
+ for(int i = 1; i <= SNAKE_TEAMS; ++i)
+ {
+ entity e = snake_get_player(minigame, i);
+ if(!e)
+ {
+ t = i;
+ break;
+ }
+ }
+
+ if(!snake_find_head(minigame, t) && !(minigame.snake_lost_teams & BIT(t)))
+ {
+ entity pl = ...(1,entity);
+ if(pl)
+ {
+ //pl.snake_lives = ((SNAKE_TEAMS > 1) ? autocvar_sv_minigames_snake_lives : 1);
+ // send score anyway, lives are set
+ pl.SendFlags |= SNAKE_SF_PLAYERSCORE;
+ }
+ minigame_setup_snake(minigame, t);
+ }
+
+ return t;
+ }
+ case "cmd":
+ {
+ switch(argv(0))
+ {
+ case "move":
+ snake_move(minigame, ...(0,entity), ((...(1,int)) >= 2 ? argv(1) : string_null), ((...(1,int)) == 3 ? argv(2) : string_null));
+ return true;
+ }
+
+ return false;
+ }
+ case "network_send":
+ {
+ entity sent = ...(0,entity);
+ int sf = ...(1,int);
+ if ( sent.classname == "minigame_board_piece" && (sf & MINIG_SF_UPDATE) )
+ {
+ int letter = minigame_tile_letter(sent.netname);
+ int number = minigame_tile_number(sent.netname);
+
+ WriteByte(MSG_ENTITY,letter);
+ WriteByte(MSG_ENTITY,number);
+
+ WriteByte(MSG_ENTITY,sent.cnt);
+ WriteByte(MSG_ENTITY,sent.snake_tail);
+
+ int dx = sent.snake_dir_x;
+ int dy = sent.snake_dir_y;
+ if(dx == -1) dx = 2;
+ if(dy == -1) dy = 2;
+ WriteByte(MSG_ENTITY,dx);
+ WriteByte(MSG_ENTITY,dy);
+ }
+ else if ( sent.classname == "minigame_player" && (sf & SNAKE_SF_PLAYERSCORE ) )
+ {
+ WriteLong(MSG_ENTITY,sent.snake_score);
+ WriteByte(MSG_ENTITY,max(0, minigame.snake_lives[sent.team]));
+ }
+ else if ( sent.classname == "minigame" && (sf & MINIG_SF_UPDATE ) )
+ {
+ WriteByte(MSG_ENTITY,autocvar_sv_minigames_snake_wrap);
+ }
+ return false;
+ }
+ }
+
+ return false;
+}
+
+
+#elif defined(CSQC)
+
+vector snake_boardpos; // HUD board position
+vector snake_boardsize;// HUD board size
+
+bool snake_wrap;
+
+vector snake_teamcolor(int steam)
+{
+ switch(steam)
+ {
+ case 1: return '1 0 0';
+ case 2: return '0 0 1';
+ case 3: return '1 1 0';
+ case 4: return '1 0 1';
+ case 5: return '0 1 0';
+ case 6: return '0 1 1';
+ }
+
+ return '1 1 1';
+}
+
+// Required function, draw the game board
+void snake_hud_board(vector pos, vector mySize)
+{
+ minigame_hud_fitsqare(pos, mySize);
+ snake_boardpos = pos;
+ snake_boardsize = mySize;
+
+ minigame_hud_simpleboard(pos,mySize,minigame_texture("snake/board"));
+
+ vector tile_size = minigame_hud_denormalize_size('1 1 0' / SNAKE_TILE_SIZE,pos,mySize);
+ vector tile_pos;
+
+ entity e;
+ FOREACH_MINIGAME_ENTITY(e)
+ {
+ if ( e.classname == "minigame_board_piece" )
+ {
+ tile_pos = minigame_tile_pos(e.netname,SNAKE_NUM_CNT,SNAKE_LET_CNT);
+ tile_pos = minigame_hud_denormalize(tile_pos,pos,mySize);
+
+ vector tile_color = snake_teamcolor(e.team);
+
+ string thepiece = "snake/mouse";
+ if(e.cnt)
+ thepiece = "snake/body";
+ if(e.snake_tail)
+ thepiece = "snake/tail";
+ if(e.cnt == 1)
+ {
+ int dx = minigame_tile_letter(e.netname) + e.snake_dir_x * 2;
+ int dy = minigame_tile_number(e.netname) + e.snake_dir_y * 2;
+ entity mouse = snake_find_piece(active_minigame, minigame_tile_buildname(dx, dy));
+ thepiece = "snake/head";
+ if(mouse && mouse.team != e.team)
+ {
+ float myang = 0;
+ int myx = minigame_tile_letter(e.netname);
+ int myy = minigame_tile_number(e.netname);
+ if(myx - 2 == dx)
+ myang = M_PI*3/2;
+ if(myx + 2 == dx)
+ myang = M_PI/2;
+ if(myy - 2 == dy)
+ myang = M_PI;
+
+ int newx = minigame_tile_letter(e.netname) + e.snake_dir_x;
+ int newy = minigame_tile_number(e.netname) + e.snake_dir_y;
+ string newpos = minigame_tile_buildname(newx, newy);
+
+ vector my_pos = minigame_tile_pos(newpos,SNAKE_NUM_CNT,SNAKE_LET_CNT);
+ my_pos = minigame_hud_denormalize(my_pos,pos,mySize);
+
+ drawrotpic(my_pos, myang, minigame_texture("snake/tongue"),
+ tile_size, tile_size/2, tile_color,
+ panel_fg_alpha, DRAWFLAG_NORMAL );
+ }
+ }
+
+ if(e.cnt == 1 || e.snake_tail)
+ {
+ vector thedir = e.snake_dir;
+ float theang = 0;
+ if(e.snake_tail)
+ {
+ int thex = minigame_tile_letter(e.netname);
+ int they = minigame_tile_number(e.netname);
+ entity t = snake_find_cnt(active_minigame, e.team, e.cnt - 1);
+ int tx = minigame_tile_letter(t.netname);
+ int ty = minigame_tile_number(t.netname);
+
+ if(thex - 1 == tx)
+ {
+ thedir_y = 0;
+ thedir_x = -1;
+ }
+ if(they + 1 == ty)
+ {
+ thedir_x = 0;
+ thedir_y = 1;
+ }
+ if(they - 1 == ty)
+ {
+ thedir_x = 0;
+ thedir_y = -1;
+ }
+ }
+
+ if(thedir_y == -1)
+ theang = M_PI;
+ if(thedir_x == 1)
+ theang = M_PI/2;
+ if(thedir_x == -1)
+ theang = M_PI*3/2;
+
+ drawrotpic(tile_pos, theang, minigame_texture(thepiece),
+ tile_size, tile_size/2, tile_color,
+ panel_fg_alpha, DRAWFLAG_NORMAL );
+ }
+ else
+ {
+ minigame_drawpic_centered( tile_pos,
+ minigame_texture(thepiece),
+ tile_size, tile_color, panel_fg_alpha, DRAWFLAG_NORMAL );
+ }
+ }
+ }
+
+ if ( (active_minigame.minigame_flags & SNAKE_TURN_LOSS) || (active_minigame.minigame_flags & SNAKE_TURN_WIN) || (active_minigame.snake_lives[minigame_self.team] <= 0) )
+ {
+ int scores = minigame_self.snake_score;
+
+ vector winfs = hud_fontsize*2;
+ string scores_text, victory_text;
+ victory_text = "Game over!";
+ scores_text = strcat("Score: ", ftos(scores));
+
+ if(active_minigame.minigame_flags & SNAKE_TURN_WIN)
+ if((active_minigame.minigame_flags & SNAKE_TURN_TEAM) == minigame_self.team)
+ victory_text = "You win!";
+ if(active_minigame.snake_lives[minigame_self.team] <= 0)
+ victory_text = "You ran out of lives!";
+
+ vector win_pos = pos+eY*(mySize_y-winfs_y)/2;
+ vector win_sz;
+ win_sz = minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
+ sprintf("%s %s", victory_text, scores_text),
+ winfs, 0, DRAWFLAG_NORMAL, 0.5);
+
+ drawfill(win_pos-eY*hud_fontsize_y,win_sz+2*eY*hud_fontsize_y,'0.3 0.3 1',0.8,DRAWFLAG_ADDITIVE);
+
+ minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
+ sprintf("%s %s", victory_text, scores_text),
+ winfs, panel_fg_alpha, DRAWFLAG_NORMAL, 0.5);
+ }
+}
+
+
+// Required function, draw the game status panel
+void snake_hud_status(vector pos, vector mySize)
+{
+ HUD_Panel_DrawBg(1);
+ vector ts;
+ ts = minigame_drawstring_wrapped(mySize_x,pos,active_minigame.descriptor.message,
+ hud_fontsize * 2, '0.25 0.47 0.72', panel_fg_alpha, DRAWFLAG_NORMAL,0.5);
+
+ pos_y += ts_y;
+ mySize_y -= ts_y;
+
+ vector player_fontsize = hud_fontsize * 1.75;
+ ts_y = ( mySize_y - 2*player_fontsize_y ) / SNAKE_TEAMS;
+ ts_x = mySize_x;
+ vector mypos;
+ vector tile_size = '48 48 0';
+
+ mypos = pos;
+ if ( minigame_self.team > 1 )
+ mypos_y += player_fontsize_y + (ts_y * (minigame_self.team - 1));
+ drawfill(mypos,eX*mySize_x+eY*player_fontsize_y,'1 1 1',0.5,DRAWFLAG_ADDITIVE);
+ mypos_y += player_fontsize_y;
+ drawfill(mypos,eX*mySize_x+eY*tile_size_y,'1 1 1',0.25,DRAWFLAG_ADDITIVE);
+
+ entity e;
+ FOREACH_MINIGAME_ENTITY(e)
+ {
+ if ( e.classname == "minigame_player" )
+ {
+ mypos = pos;
+ if ( e.team > 1 )
+ mypos_y += player_fontsize_y + (ts_y * (e.team - 1));
+ minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
+ GetPlayerName(e.minigame_playerslot-1),
+ player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+
+ vector tile_color = snake_teamcolor(e.team);
+
+ mypos_y += player_fontsize_y;
+ drawpic( mypos,
+ minigame_texture("snake/head"),
+ tile_size * 0.7, tile_color, panel_fg_alpha, DRAWFLAG_NORMAL );
+
+ mypos_x += tile_size_x;
+
+ drawstring(mypos,ftos(e.snake_score),tile_size,
+ '0.7 0.84 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+
+ mypos_x += tile_size_x;
+
+ drawstring(mypos,strcat("1UP: ", ftos(active_minigame.snake_lives[e.team])),tile_size * 0.6,
+ '0.7 0.84 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ }
+ }
+}
+
+// Turn a set of flags into a help message
+string snake_turn_to_string(int turnflags)
+{
+ if ( turnflags & SNAKE_TURN_LOSS )
+ return _("Game over!");
+
+ if ( turnflags & SNAKE_TURN_WIN )
+ {
+ if ( (turnflags&SNAKE_TURN_TEAM) != minigame_self.team )
+ return _("You ran out of lives!");
+ return _("You win!");
+ }
+
+ if(active_minigame.snake_lives[minigame_self.team] <= 0)
+ return _("You ran out of lives!");
+
+ if ( (snake_find_head(active_minigame, minigame_self.team)).snake_dir == '0 0 0' )
+ return _("Press an arrow key to begin the game");
+
+ if ( turnflags & SNAKE_TURN_MOVE )
+ if(snake_wrap)
+ return _("Avoid the snake's body, collect the mice!");
+ else
+ return _("Avoid the screen edges and the snake's body, collect the mice!");
+
+ return "";
+}
+
+// Make the correct move
+void snake_set_direction(entity minigame, int dx, int dy)
+{
+ //if ( minigame.minigame_flags == SNAKE_TURN_MOVE )
+ //{
+ minigame_cmd("move ",ftos(dx), " ", ftos(dy));
+ //}
+}
+
+// Required function, handle client events
+int snake_client_event(entity minigame, string event, ...)
+{
+ switch(event)
+ {
+ case "activate":
+ {
+ minigame.message = snake_turn_to_string(minigame.minigame_flags);
+ return false;
+ }
+ case "key_pressed":
+ {
+ //if((minigame.minigame_flags & SNAKE_TURN_TEAM) == minigame_self.team)
+ {
+ switch ( ...(0,int) )
+ {
+ case K_RIGHTARROW:
+ case K_KP_RIGHTARROW:
+ snake_set_direction(minigame, 1, 0);
+ return true;
+ case K_LEFTARROW:
+ case K_KP_LEFTARROW:
+ snake_set_direction(minigame, -1, 0);
+ return true;
+ case K_UPARROW:
+ case K_KP_UPARROW:
+ snake_set_direction(minigame, 0, 1);
+ return true;
+ case K_DOWNARROW:
+ case K_KP_DOWNARROW:
+ snake_set_direction(minigame, 0, -1);
+ return true;
+ }
+ }
+
+ return false;
+ }
+ case "network_receive":
+ {
+ entity sent = ...(0,entity);
+ int sf = ...(1,int);
+ if ( sent.classname == "minigame" )
+ {
+ if ( sf & MINIG_SF_UPDATE )
+ {
+ snake_wrap = ReadByte();
+ sent.message = snake_turn_to_string(sent.minigame_flags);
+ //if ( sent.minigame_flags & minigame_self.team )
+ minigame_prompt();
+ }
+ }
+ else if(sent.classname == "minigame_board_piece")
+ {
+ if(sf & MINIG_SF_UPDATE)
+ {
+ int letter = ReadByte();
+ int number = ReadByte();
+ if(sent.netname) { strunzone(sent.netname); }
+ sent.netname = strzone(minigame_tile_buildname(letter, number));
+
+ sent.cnt = ReadByte();
+ sent.snake_tail = ReadByte();
+
+ int dx = ReadByte();
+ int dy = ReadByte();
+
+ if(dx == 2) dx = -1;
+ if(dy == 2) dy = -1;
+
+ sent.snake_dir_x = dx;
+ sent.snake_dir_y = dy;
+ sent.snake_dir_z = 0;
+ }
+ }
+ else if ( sent.classname == "minigame_player" && (sf & SNAKE_SF_PLAYERSCORE ) )
+ {
+ sent.snake_score = ReadLong();
+ minigame.snake_lives[sent.team] = ReadByte();
+ }
+
+ return false;
+ }
+ }
+
+ return false;
+}
+
+#endif
\ No newline at end of file
+REGISTER_MINIGAME(ttt, "Tic Tac Toe");
+
const int TTT_TURN_PLACE = 0x0100; // player has to place a piece on the board
const int TTT_TURN_WIN = 0x0200; // player has won
const int TTT_TURN_DRAW = 0x0400; // no moves are possible
{
int number = minigame_tile_number(piece.netname);
int letter = minigame_tile_letter(piece.netname);
-
+
if ( ttt_find_piece(piece.owner,minigame_tile_buildname(0,number)).team == piece.team )
if ( ttt_find_piece(piece.owner,minigame_tile_buildname(1,number)).team == piece.team )
if ( ttt_find_piece(piece.owner,minigame_tile_buildname(2,number)).team == piece.team )
return true;
-
+
if ( ttt_find_piece(piece.owner,minigame_tile_buildname(letter,0)).team == piece.team )
if ( ttt_find_piece(piece.owner,minigame_tile_buildname(letter,1)).team == piece.team )
if ( ttt_find_piece(piece.owner,minigame_tile_buildname(letter,2)).team == piece.team )
return true;
-
+
if ( number == letter )
if ( ttt_find_piece(piece.owner,minigame_tile_buildname(0,0)).team == piece.team )
if ( ttt_find_piece(piece.owner,minigame_tile_buildname(1,1)).team == piece.team )
if ( ttt_find_piece(piece.owner,minigame_tile_buildname(2,2)).team == piece.team )
return true;
-
+
if ( number == 2-letter )
if ( ttt_find_piece(piece.owner,minigame_tile_buildname(0,2)).team == piece.team )
if ( ttt_find_piece(piece.owner,minigame_tile_buildname(1,1)).team == piece.team )
if ( ttt_find_piece(piece.owner,minigame_tile_buildname(2,0)).team == piece.team )
return true;
-
+
return false;
}
case "join":
{
int pl_num = minigame_count_players(minigame);
-
+
// Don't allow joining a single player match
if ( (minigame.ttt_ai) && pl_num > 0 )
return false;
{
switch(argv(0))
{
- case "move":
- ttt_move(minigame, ...(0,entity), ...(1,int) == 2 ? argv(1) : string_null );
+ case "move":
+ ttt_move(minigame, ...(0,entity), ...(1,int) == 2 ? argv(1) : string_null );
return true;
case "next":
ttt_next_match(minigame,...(0,entity));
return false;
}
}
-
+
return false;
}
minigame_hud_fitsqare(pos, mySize);
ttt_boardpos = pos;
ttt_boardsize = mySize;
-
+
minigame_hud_simpleboard(pos,mySize,minigame_texture("ttt/board"));
vector tile_size = minigame_hud_denormalize_size('1 1 0'/TTT_TILE_SIZE,pos,mySize);
{
tile_pos = minigame_tile_pos(ttt_curr_pos,TTT_LET_CNT,TTT_NUM_CNT);
tile_pos = minigame_hud_denormalize(tile_pos,pos,mySize);
- minigame_drawpic_centered( tile_pos,
+ minigame_drawpic_centered( tile_pos,
minigame_texture(strcat("ttt/piece",ftos(minigame_self.team))),
tile_size, '1 1 1', panel_fg_alpha/2, DRAWFLAG_NORMAL );
}
-
+
entity e;
FOREACH_MINIGAME_ENTITY(e)
{
{
tile_pos = minigame_tile_pos(e.netname,TTT_LET_CNT,TTT_NUM_CNT);
tile_pos = minigame_hud_denormalize(tile_pos,pos,mySize);
-
+
if ( active_minigame.minigame_flags & TTT_TURN_WIN )
if ( !e.ttt_checkwin )
e.ttt_checkwin = ttt_winning_piece(e) ? 1 : -1;
-
+
float icon_color = 1;
if ( e.ttt_checkwin == -1 )
icon_color = 0.4;
minigame_drawpic_centered( tile_pos, minigame_texture("ttt/winglow"),
tile_size, '1 1 1', panel_fg_alpha, DRAWFLAG_ADDITIVE );
}
-
- minigame_drawpic_centered( tile_pos,
+
+ minigame_drawpic_centered( tile_pos,
minigame_texture(strcat("ttt/piece",ftos(e.team))),
tile_size, '1 1 1'*icon_color, panel_fg_alpha, DRAWFLAG_NORMAL );
}
vector ts;
ts = minigame_drawstring_wrapped(mySize_x,pos,active_minigame.descriptor.message,
hud_fontsize * 2, '0.25 0.47 0.72', panel_fg_alpha, DRAWFLAG_NORMAL,0.5);
-
+
pos_y += ts_y;
mySize_y -= ts_y;
-
+
vector player_fontsize = hud_fontsize * 1.75;
ts_y = ( mySize_y - 2*player_fontsize_y ) / 2;
ts_x = mySize_x;
minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
(e.minigame_playerslot ? GetPlayerName(e.minigame_playerslot-1) : _("AI")),
player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
-
+
mypos_y += player_fontsize_y;
- drawpic( mypos,
+ drawpic( mypos,
minigame_texture(strcat("ttt/piece",ftos(e.team))),
tile_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL );
-
+
mypos_x += tile_size_x;
-
+
drawstring(mypos,ftos(e.minigame_flags),tile_size,
'0.7 0.84 1', panel_fg_alpha, DRAWFLAG_NORMAL);
}
{
if ( turnflags & TTT_TURN_DRAW )
return _("Draw");
-
+
if ( turnflags & TTT_TURN_WIN )
{
if ( (turnflags&TTT_TURN_TEAM) != minigame_self.team )
return _("You lost the game!\nSelect \"^1Next Match^7\" on the menu for a rematch!");
return _("You win!\nSelect \"^1Next Match^7\" on the menu to start a new match!");
}
-
+
if ( turnflags & TTT_TURN_NEXT )
{
if ( (turnflags&TTT_TURN_TEAM) != minigame_self.team )
return _("Select \"^1Next Match^7\" on the menu to start a new match!");
return _("Wait for your opponent to confirm the rematch");
}
-
+
if ( (turnflags & TTT_TURN_TEAM) != minigame_self.team )
return _("Wait for your opponent to make their move");
-
+
if ( turnflags & TTT_TURN_PLACE )
return _("Click on the game board to place your piece");
-
+
return "";
}
return "a2";
case TTT_AI_POSFLAG_A3:
return "a3";
-
+
case TTT_AI_POSFLAG_B1:
return "b1";
case TTT_AI_POSFLAG_B2:
return "b2";
case TTT_AI_POSFLAG_B3:
return "b3";
-
+
case TTT_AI_POSFLAG_C1:
return "c1";
case TTT_AI_POSFLAG_C2:
return "c2";
case TTT_AI_POSFLAG_C3:
return "c3";
-
+
default:
return string_null;
}
{
if ( ttt_ai_checkmask(piecemask,flag1|flag2|flag3) )
return 0;
-
+
if ( ttt_ai_checkmask(piecemask,flag1|flag2) )
return flag3;
-
+
if ( ttt_ai_checkmask(piecemask,flag3|flag2) )
return flag1;
-
+
if ( ttt_ai_checkmask(piecemask,flag3|flag1) )
return flag2;
{
if ( !piecemask )
return 0;
-
+
int f = 1;
-
+
RandomSelection_Init();
-
+
for ( int i = 0; i < 9; i++ )
{
if ( piecemask & f )
RandomSelection_Add(world, f, string_null, 1, 1);
f <<= 1;
}
-
+
LOG_TRACE(sprintf("TTT AI: selected %x from %x\n",
RandomSelection_chosen_float, piecemask) );
return RandomSelection_chosen_float;
int ttt_ai_block3 ( int piecemask, int piecemask_free )
{
int r = 0;
-
+
r |= ttt_ai_1of3(piecemask,TTT_AI_POSFLAG_A1,TTT_AI_POSFLAG_A2,TTT_AI_POSFLAG_A3);
r |= ttt_ai_1of3(piecemask,TTT_AI_POSFLAG_B1,TTT_AI_POSFLAG_B2,TTT_AI_POSFLAG_B3);
r |= ttt_ai_1of3(piecemask,TTT_AI_POSFLAG_C1,TTT_AI_POSFLAG_C2,TTT_AI_POSFLAG_C3);
string ttt_ai_choose_simple(int piecemask_self, int piecemask_opponent, int piecemask_free )
{
int move = 0;
-
+
LOG_TRACE("TTT AI: checking winning move\n");
if (( move = ttt_ai_block3(piecemask_self,piecemask_free) ))
return ttt_ai_piece_flag2pos(move); // place winning move
-
+
LOG_TRACE("TTT AI: checking opponent's winning move\n");
if (( move = ttt_ai_block3(piecemask_opponent,piecemask_free) ))
return ttt_ai_piece_flag2pos(move); // block opponent
-
+
LOG_TRACE("TTT AI: random move\n");
return ttt_ai_piece_flag2pos(ttt_ai_random(piecemask_free));
}
while ( ( aiplayer = findentity(aiplayer,owner,minigame) ) )
if ( aiplayer.classname == "minigame_player" && !aiplayer.minigame_playerslot )
break;
-
+
/*
* Build bit masks for the board pieces
* .---.---.---.
* | 4 | 32|256| 3
- * |---+---+---|
+ * |---+---+---|
* | 2 | 16|128| 2
- * |---+---+---|
+ * |---+---+---|
* | 1 | 8 | 64| 1
* '---'---'---'
* A B C
pieceflag <<= 1;
}
}
-
+
// TODO multiple AI difficulties
LOG_TRACE(sprintf("TTT AI: self: %x opponent: %x free: %x\n",
piecemask_self, piecemask_opponent, piecemask_free));
if ( sent.minigame_flags & minigame_self.team )
minigame_prompt();
}
-
+
if ( (sf & TTT_SF_SINGLEPLAYER) )
{
int ai = ReadByte();
bool spawnai = ai && !sent.ttt_ai;
sent.ttt_ai = ai;
-
+
if ( spawnai )
{
entity aiplayer = spawn();
aiplayer.minigame_autoclean = 1;
ttt_aimove(minigame);
}
-
+
}
}
else if ( sent.classname == "minigame_player" && (sf & TTT_SF_PLAYERSCORE ) )
entity minigame_get_descriptor(string id)
{
- entity e;
- for ( e = minigame_descriptors; e != world; e = e.list_next )
- if ( e.netname == id )
- return e;
+ FOREACH(Minigames, true, LAMBDA(
+ {
+ if(it.netname == id)
+ return it;
+ }));
return world;
}
// Get number index of a tile name
// Note: this is 0 based, useful for mathematical operations
-// Note: Since the tile notation starts from the bottom left,
+// Note: Since the tile notation starts from the bottom left,
// you may want to do number_of_rows - what_this_function_returns or something
int minigame_tile_number(string id)
{
// Get relative position of the center of a given tile
vector minigame_tile_pos(string id, int rows, int columns)
{
- return eX*(minigame_tile_letter(id)+0.5)/columns +
+ return eX*(minigame_tile_letter(id)+0.5)/columns +
eY - eY*(minigame_tile_number(id)+0.5)/rows;
}
{
if ( pos_x < 0 || pos_x > 1 || pos_y < 0 || pos_y > 1 )
return ""; // no tile
-
+
int letter = floor(pos_x * columns);
int number = floor((1-pos_y) * rows);
return minigame_tile_buildname(letter, number);
#ifndef MINIGAMES_H
#define MINIGAMES_H
-entity minigame_descriptors;
-
// previous node in a doubly linked list
.entity list_prev;
// next node in a linked list
// Get number index of a tile name
// Note: this is 0 based, useful for mathematical operations
-// Note: Since the tile notation starts from the bottom left,
+// Note: Since the tile notation starts from the bottom left,
// you may want to do number_of_rows - what_this_function_returns or something
int minigame_tile_number(string id);
/// IMPORTANT: always read in client everything you send from the server!
/// cmd(entity minigame_player, int argc, string command)
/// self = client entity triggering this
-/// argv(n) = console token
+/// argv(n) = console token
/// argc: number of console tokens
/// command: full command string
/// triggered when a player does "cmd minigame ..." with some unrecognized command
{
entity e;
entity p = minigame_session.minigame_players;
-
+
if ( p.minigame_players == player )
{
if ( p.list_next == world )
// Send an entity to a client
// only use on minigame entities or entities with a minigame owner
-bool minigame_SendEntity(entity to, int sf)
+bool minigame_SendEntity(entity this, entity to, int sf)
{
WriteByte(MSG_ENTITY, ENT_CLIENT_MINIGAME);
WriteByte(MSG_ENTITY, sf);
-
+
if ( sf & MINIG_SF_CREATE )
{
WriteShort(MSG_ENTITY,msle_id(self.classname));
WriteString(MSG_ENTITY,self.netname);
}
-
+
entity minigame_ent = self.owner;
-
+
if ( self.classname == "minigame" )
{
minigame_ent = self;
-
+
if ( sf & MINIG_SF_CREATE )
WriteString(MSG_ENTITY,self.descriptor.netname);
-
+
if ( sf & MINIG_SF_UPDATE )
WriteLong(MSG_ENTITY,self.minigame_flags);
}
WriteByte(MSG_ENTITY,self.team);
}
MINIGAME_SIMPLELINKED_ENTITIES
-
+
minigame_ent.minigame_event(minigame_ent,"network_send",self,sf);
-
+
return true;
-
+
}
#undef FIELD
#undef MSLE
}
bool minigame_CheckSend()
-{
+{SELFPARAM();
entity e;
for ( e = self.owner.minigame_players; e != world; e = e.list_next )
if ( e.minigame_players == other )
}
int minigame_addplayer(entity minigame_session, entity player)
-{
+{SELFPARAM();
if ( player.active_minigame )
{
if ( player.active_minigame == minigame_session )
return 0;
minigame_rmplayer(player.active_minigame,player);
}
-
- int mgteam = minigame_session.minigame_event(minigame_session,"join",player);
-
+ entity player_pointer = spawn();
+ int mgteam = minigame_session.minigame_event(minigame_session,"join",player,player_pointer);
+
if ( mgteam )
{
- entity player_pointer = spawn();
player_pointer.classname = "minigame_player";
player_pointer.owner = minigame_session;
player_pointer.minigame_players = player;
if ( !IS_OBSERVER(player) && autocvar_sv_minigames_observer )
{
- entity e = self;
- self = player;
- PutObserverInServer();
- self = e;
+ WITH(entity, self, player, PutObserverInServer());
}
if ( autocvar_sv_minigames_observer == 2 )
player.team_forced = -1;
-
+
minigame_resend(minigame_session);
}
+ else { remove(player_pointer); }
GameLogEcho(strcat(":minigame:join",(mgteam?"":"fail"),":",minigame_session.netname,":",
ftos(num_for_edict(player)),":",player.netname));
-
+
return mgteam;
}
{
if ( !autocvar_sv_minigames || !IS_REAL_CLIENT(player) )
return world;
-
+
entity e = minigame_get_descriptor(minigame);
- if ( e )
+ if ( e )
{
entity minig = spawn();
minig.classname = "minigame";
return world;
}
Net_LinkEntity(minig, false, 0, minigame_SendEntity);
-
+
if ( !minigame_sessions )
minigame_sessions = minig;
else
}
return minig;
}
-
+
return world;
}
{
if ( !autocvar_sv_minigames || !IS_REAL_CLIENT(player) )
return world;
-
+
entity minig;
for ( minig = minigame_sessions; minig != world; minig = minig.list_next )
{
if ( minigame_addplayer(minig,player) )
return minig;
}
-
+
return world;
}
void part_minigame(entity player )
{
entity minig = player.active_minigame;
-
+
if ( minig && minig.classname == "minigame" )
minigame_rmplayer(minig,player);
}
minigame_session.owner.list_next = minigame_session.list_next;
else
minigame_sessions = minigame_session.list_next;
-
+
minigame_session.minigame_event(minigame_session,"end");
GameLogEcho(strcat(":minigame:end:",minigame_session.netname));
-
-
+
+
entity e = world;
while( (e = findentity(e, owner, minigame_session)) )
if ( e.minigame_autoclean )
LOG_TRACE("SV Auto-cleaned: ",ftos(num_for_edict(e)), " (",e.classname,")\n");
remove(e);
}
-
+
entity p;
for ( e = minigame_session.minigame_players; e != world; e = p )
{
player_clear_minigame(e.minigame_players);
remove(e);
}
-
+
strunzone(minigame_session.netname);
remove(minigame_session);
}
}
}
-void initialize_minigames()
-{
- entity last_minig = world;
- entity minig;
- #define MINIGAME(name,nicename) \
- minig = spawn(); \
- minig.classname = "minigame_descriptor"; \
- minig.netname = #name; \
- minig.message = nicename; \
- minig.minigame_event = name##_server_event; \
- if ( !last_minig ) minigame_descriptors = minig; \
- else last_minig.list_next = minig; \
- last_minig = minig;
-
- REGISTERED_MINIGAMES
-
- #undef MINIGAME
-}
-
string invite_minigame(entity inviter, entity player)
{
if ( !inviter || !inviter.active_minigame )
return "You can't invite yourself";
if ( player.active_minigame == inviter.active_minigame )
return strcat(player.netname," is already playing");
-
- Send_Notification(NOTIF_ONE, player, MSG_INFO, INFO_MINIGAME_INVITE,
+
+ Send_Notification(NOTIF_ONE, player, MSG_INFO, INFO_MINIGAME_INVITE,
inviter.active_minigame.netname, inviter.netname );
-
+
GameLogEcho(strcat(":minigame:invite:",inviter.active_minigame.netname,":",
ftos(num_for_edict(player)),":",player.netname));
-
+
return "";
}
}
bool MinigameImpulse(int imp)
-{
+{SELFPARAM();
entity e = minigame_find_player(self);
if ( imp && self.active_minigame && e )
{
void ClientCommand_minigame(int request, int argc, string command)
-{
+{SELFPARAM();
if ( !autocvar_sv_minigames )
{
sprint(self,"Minigames are not enabled!\n");
return;
}
-
+
if (request == CMD_REQUEST_COMMAND )
{
string minig_cmd = argv(1);
}
else if ( minig_cmd == "list" )
{
- entity e;
- for ( e = minigame_descriptors; e != world; e = e.list_next )
- sprint(self,e.netname," (",e.message,") ","\n");
+ FOREACH(Minigames, true, LAMBDA(
+ {
+ sprint(self,it.netname," (",it.message,") ","\n");
+ }));
return;
}
else if ( minig_cmd == "list-sessions" )
int arg_c = tokenize_console(subcommand);
if ( self.active_minigame.minigame_event(self.active_minigame,"cmd",e,arg_c,subcommand) )
return;
-
+
}
else sprint(self,strcat("Wrong command:^1 ",command,"\n"));
}
-
+
sprint(self, "\nUsage:^3 cmd minigame create <minigame>\n");
sprint(self, " Start a new minigame session\n");
sprint(self, "Usage:^3 cmd minigame join <session>\n");
#ifndef SV_MINIGAMES_H
#define SV_MINIGAMES_H
-/// Initialize the minigame system
-void initialize_minigames();
-
/// Create a new minigame session
/// \return minigame session entity
entity start_minigame(entity player, string minigame );
entity minigame_sessions;
-bool minigame_SendEntity(entity to, int sf);
+bool minigame_SendEntity(entity this, entity to, int sf);
+
+REGISTRY(Minigames, BIT(3))
+REGISTER_REGISTRY(RegisterMinigames)
+#define REGISTER_MINIGAME(name,nicename) \
+ REGISTER(RegisterMinigames, MINIGAME, Minigames, name, m_id, spawn()); \
+ int name##_server_event(entity, string, ...); \
+ REGISTER_INIT_POST(MINIGAME, name) { \
+ this.classname = "minigame_descriptor"; \
+ this.netname = strzone(strtolower(#name)); \
+ this.message = nicename; \
+ this.minigame_event = name##_server_event; \
+ } \
+ REGISTER_INIT(MINIGAME, name)
#endif
--- /dev/null
+// Global list of models
+// TODO: remove uses of _setmodel
+
+string W_Model(string w_mdl);
+
+MODEL(CTF_SHIELD, "models/ctf/shield.md3");
+MODEL(CTF_CAPTURE, "models/ctf/shockwavetransring.md3");
+
+MODEL(DOM_NEUTRAL, "models/domination/dom_unclaimed.md3");
+MODEL(DOM_RED, "models/domination/dom_red.md3");
+MODEL(DOM_BLUE, "models/domination/dom_blue.md3");
+MODEL(DOM_YELLOW, "models/domination/dom_yellow.md3");
+MODEL(DOM_PINK, "models/domination/dom_pink.md3");
+
+MODEL(ICE, "models/ice/ice.md3");
+
+MODEL(KH_KEY, "models/keyhunt/key.md3");
+#ifdef KH_PLAYER_USE_CARRIEDMODEL
+MODEL(KH_KEY_CARRIED, "models/keyhunt/key-carried.md3");
+#endif
+
+MODEL(OK_HMG, W_Model("g_ok_hmg.md3"));
+
+MODEL(OK_RPC, W_Model("g_ok_rl.md3"));
+
+MODEL(OK_MG_VIEW, W_Model("h_ok_mg.iqm"));
+MODEL(OK_MG_WORLD, W_Model("v_ok_mg.md3"));
+MODEL(OK_MG_ITEM, W_Model("g_ok_mg.md3"));
+
+MODEL(OK_SHOTGUN_VIEW, W_Model("h_ok_shotgun.iqm"));
+MODEL(OK_SHOTGUN_WORLD, W_Model("v_ok_shotgun.md3"));
+MODEL(OK_SHOTGUN_ITEM, W_Model("g_ok_shotgun.md3"));
+
+MODEL(OK_SNIPER_VIEW, W_Model("h_ok_sniper.iqm"));
+MODEL(OK_SNIPER_WORLD, W_Model("v_ok_sniper.md3"));
+MODEL(OK_SNIPER_ITEM, W_Model("g_ok_sniper.md3"));
+
+MODEL(ONS_CP, "models/onslaught/controlpoint_icon.md3");
+MODEL(ONS_CP_SHIELD, "models/onslaught/controlpoint_shield.md3");
+MODEL(ONS_CP_PAD1, "models/onslaught/controlpoint_pad.md3");
+MODEL(ONS_CP_PAD2, "models/onslaught/controlpoint_pad2.md3");
+MODEL(ONS_CP1, "models/onslaught/controlpoint_icon_dmg1.md3");
+MODEL(ONS_CP1_GIB, "models/onslaught/controlpoint_icon_gib1.md3");
+MODEL(ONS_CP2, "models/onslaught/controlpoint_icon_dmg2.md3");
+MODEL(ONS_CP2_GIB, "models/onslaught/controlpoint_icon_gib2.md3");
+MODEL(ONS_CP3, "models/onslaught/controlpoint_icon_dmg3.md3");
+MODEL(ONS_CP3_GIB, "models/onslaught/controlpoint_icon_gib4.md3");
+MODEL(ONS_RAY, "models/onslaught/ons_ray.md3");
+MODEL(ONS_GEN, "models/onslaught/generator.md3");
+MODEL(ONS_GEN_SHIELD, "models/onslaught/generator_shield.md3");
+MODEL(ONS_GEN_GIB1, "models/onslaught/gen_gib1.md3");
+MODEL(ONS_GEN_GIB2, "models/onslaught/gen_gib2.md3");
+MODEL(ONS_GEN_GIB3, "models/onslaught/gen_gib3.md3");
+MODEL(ONS_GEN1, "models/onslaught/generator_dmg1.md3");
+MODEL(ONS_GEN2, "models/onslaught/generator_dmg2.md3");
+MODEL(ONS_GEN3, "models/onslaught/generator_dmg3.md3");
+MODEL(ONS_GEN4, "models/onslaught/generator_dmg4.md3");
+MODEL(ONS_GEN5, "models/onslaught/generator_dmg5.md3");
+MODEL(ONS_GEN6, "models/onslaught/generator_dmg6.md3");
+MODEL(ONS_GEN7, "models/onslaught/generator_dmg7.md3");
+MODEL(ONS_GEN8, "models/onslaught/generator_dmg8.md3");
+MODEL(ONS_GEN9, "models/onslaught/generator_dmg9.md3");
+MODEL(ONS_GEN_DEAD, "models/onslaught/generator_dead.md3");
+
+MODEL(PROJECTILE_ELECTRO, "models/ebomb.mdl");
+MODEL(PROJECTILE_ELECTRO_BEAM, "models/elaser.mdl");
+
+MODEL(PROJECTILE_ROCKET, "models/rocket.md3");
+
+MODEL(PROJECTILE_CRYLINK, "models/plasmatrail.mdl");
+MODEL(PROJECTILE_CRYLINK_BOUNCING, "models/plasmatrail.mdl");
+
+MODEL(PROJECTILE_GRENADE, "models/grenademodel.md3");
+MODEL(PROJECTILE_GRENADE_BOUNCING, "models/grenademodel.md3");
+
+MODEL(PROJECTILE_MINE, "models/mine.md3");
+
+MODEL(PROJECTILE_BLASTER, "models/laser.mdl");
+
+MODEL(PROJECTILE_HLAC, "models/hlac_bullet.md3");
+
+MODEL(PROJECTILE_PORTO_RED, "models/grenademodel.md3");
+MODEL(PROJECTILE_PORTO_BLUE, "models/grenademodel.md3");
+
+MODEL(PROJECTILE_HOOKBOMB, "models/grenademodel.md3");
+
+MODEL(PROJECTILE_HAGAR, "models/hagarmissile.mdl");
+MODEL(PROJECTILE_HAGAR_BOUNCING, "models/hagarmissile.mdl");
+
+// napalm grenade
+MODEL(PROJECTILE_NAPALM_FOUNTAIN, "null");
+// fireball primary
+MODEL(PROJECTILE_FIREBALL, "null");
+// fireball secondary
+MODEL(PROJECTILE_FIREMINE, "null");
+
+MODEL(PROJECTILE_TAG, "models/laser.mdl");
+
+MODEL(PROJECTILE_FLAC, "models/hagarmissile.mdl");
+
+MODEL(PROJECTILE_SEEKER, "models/tagrocket.md3");
+
+MODEL(PROJECTILE_MAGE_SPIKE, "models/ebomb.mdl");
+MODEL(PROJECTILE_SHAMBLER_LIGHTNING, "models/ebomb.mdl");
+
+MODEL(PROJECTILE_RAPTORBOMB, "models/vehicles/clusterbomb.md3");
+MODEL(PROJECTILE_RAPTORBOMBLET, "models/vehicles/bomblet.md3");
+MODEL(PROJECTILE_RAPTORCANNON, "models/plasmatrail.mdl");
+
+MODEL(PROJECTILE_SPIDERROCKET, "models/vehicles/rocket02.md3");
+
+MODEL(PROJECTILE_WAKIROCKET, "models/vehicles/rocket01.md3");
+MODEL(PROJECTILE_WAKICANNON, "models/laser.mdl");
+
+MODEL(PROJECTILE_BUMBLE_GUN, "models/elaser.mdl");
+MODEL(PROJECTILE_BUMBLE_BEAM, "models/elaser.mdl");
+
+MODEL(PROJECTILE_RPC, W_Model("ok_rocket.md3"));
+
+MODEL(PROJECTILE_ROCKETMINSTA_LASER, "models/elaser.mdl");
+
+MODEL(PROJECTILE_NADE, W_Model("v_ok_grenade.md3"));
+MODEL(NADE_VIEW, W_Model("h_ok_grenade.iqm"));
+MODEL(NADE_TIMER, "models/ok_nade_counter/ok_nade_counter.md3");
+MODEL(NADE_HEAL, "models/ctf/shield.md3");
+
+MODEL(GIB_CHUNK, "models/gibs/chunk.mdl");
+MODEL(GIB_LEG1, "models/gibs/leg1.md3");
+MODEL(GIB_LEG2, "models/gibs/leg2.md3");
+MODEL(GIB_CHEST, "models/gibs/chest.md3");
+MODEL(GIB_SMALLCHEST, "models/gibs/smallchest.md3");
+MODEL(GIB_ARM, "models/gibs/arm.md3");
+MODEL(GIB_BLOODYSKULL, "models/gibs/bloodyskull.md3");
+MODEL(GIB_EYE, "models/gibs/eye.md3");
+
+MODEL(GIB_ROBO, "models/gibs/robo.md3");
+MODEL(GIB_ROBO_1, "models/gibs/robo1.md3");
+MODEL(GIB_ROBO_2, "models/gibs/robo2.md3");
+MODEL(GIB_ROBO_3, "models/gibs/robo3.md3");
+MODEL(GIB_ROBO_4, "models/gibs/robo4.md3");
+MODEL(GIB_ROBO_5, "models/gibs/robo5.md3");
+MODEL(GIB_ROBO_6, "models/gibs/robo6.md3");
+MODEL(GIB_ROBO_7, "models/gibs/robo7.md3");
+MODEL(GIB_ROBO_8, "models/gibs/robo8.md3");
+Model MDL_GIB_ROBO_RANDOM() {
+ int i = floor(random() * 8);
+ return Models[MDL_GIB_ROBO_1.m_id + i];
+}
+
+MODEL(CASING_SHELL, "models/casing_shell.mdl");
+MODEL(CASING_BULLET, "models/casing_bronze.iqm");
+
+MODEL(BUFF, "models/relics/relic.md3");
+
+MODEL(BLASTER_VIEW, W_Model("h_laser.iqm"));
+MODEL(BLASTER_WORLD, W_Model("v_laser.md3"));
+MODEL(BLASTER_ITEM, W_Model("g_laser.md3"));
+
+MODEL(SHOTGUN_MUZZLEFLASH, "models/uziflash.md3");
+MODEL(SHOTGUN_VIEW, W_Model("h_shotgun.iqm"));
+MODEL(SHOTGUN_WORLD, W_Model("v_shotgun.md3"));
+MODEL(SHOTGUN_ITEM, W_Model("g_shotgun.md3"));
+
+MODEL(MACHINEGUN_MUZZLEFLASH, "models/uziflash.md3");
+MODEL(MACHINEGUN_VIEW, W_Model("h_uzi.iqm"));
+MODEL(MACHINEGUN_WORLD, W_Model("v_uzi.md3"));
+MODEL(MACHINEGUN_ITEM, W_Model("g_uzi.md3"));
+
+MODEL(MORTAR_VIEW, W_Model("h_gl.iqm"));
+MODEL(MORTAR_WORLD, W_Model("v_gl.md3"));
+MODEL(MORTAR_ITEM, W_Model("g_gl.md3"));
+
+MODEL(MINELAYER_MUZZLEFLASH, "models/flash.md3");
+MODEL(MINELAYER_MINE, "models/mine.md3");
+MODEL(MINELAYER_VIEW, W_Model("h_minelayer.iqm"));
+MODEL(MINELAYER_WORLD, W_Model("v_minelayer.md3"));
+MODEL(MINELAYER_ITEM, W_Model("g_minelayer.md3"));
+
+MODEL(ELECTRO_VIEW, W_Model("h_electro.iqm"));
+MODEL(ELECTRO_WORLD, W_Model("v_electro.md3"));
+MODEL(ELECTRO_ITEM, W_Model("g_electro.md3"));
+
+MODEL(CRYLINK_VIEW, W_Model("h_crylink.iqm"));
+MODEL(CRYLINK_WORLD, W_Model("v_crylink.md3"));
+MODEL(CRYLINK_ITEM, W_Model("g_crylink.md3"));
+
+MODEL(VORTEX_MUZZLEFLASH, "models/nexflash.md3");
+MODEL(VORTEX_VIEW, W_Model("h_nex.iqm"));
+MODEL(VORTEX_WORLD, W_Model("v_nex.md3"));
+MODEL(VORTEX_ITEM, W_Model("g_nex.md3"));
+
+MODEL(HAGAR_VIEW, W_Model("h_hagar.iqm"));
+MODEL(HAGAR_WORLD, W_Model("v_hagar.md3"));
+MODEL(HAGAR_ITEM, W_Model("g_hagar.md3"));
+
+MODEL(DEVASTATOR_MUZZLEFLASH, "models/flash.md3");
+MODEL(DEVASTATOR_VIEW, W_Model("h_rl.iqm"));
+MODEL(DEVASTATOR_WORLD, W_Model("v_rl.md3"));
+MODEL(DEVASTATOR_ITEM, W_Model("g_rl.md3"));
+
+MODEL(PORTAL, "models/portal.md3");
+MODEL(PORTO_VIEW, W_Model("h_porto.iqm"));
+MODEL(PORTO_WORLD, W_Model("v_porto.md3"));
+MODEL(PORTO_ITEM, W_Model("g_porto.md3"));
+
+MODEL(VAPORIZER_MUZZLEFLASH, "models/nexflash.md3");
+MODEL(VAPORIZER_VIEW, W_Model("h_minstanex.iqm"));
+MODEL(VAPORIZER_WORLD, W_Model("v_minstanex.md3"));
+MODEL(VAPORIZER_ITEM, W_Model("g_minstanex.md3"));
+
+MODEL(HOOK, "models/hook.md3");
+MODEL(HOOK_VIEW, W_Model("h_hookgun.iqm"));
+MODEL(HOOK_WORLD, W_Model("v_hookgun.md3"));
+MODEL(HOOK_ITEM, W_Model("g_hookgun.md3"));
+
+MODEL(HLAC_VIEW, W_Model("h_hlac.iqm"));
+MODEL(HLAC_WORLD, W_Model("v_hlac.md3"));
+MODEL(HLAC_ITEM, W_Model("g_hlac.md3"));
+
+MODEL(TUBA_VIEW, W_Model("h_tuba.iqm"));
+MODEL(TUBA_WORLD, W_Model("v_tuba.md3"));
+MODEL(TUBA_ITEM, W_Model("g_tuba.md3"));
+MODEL(ACCORDION_VIEW, W_Model("h_akordeon.iqm"));
+MODEL(ACCORDION_WORLD, W_Model("v_akordeon.md3"));
+MODEL(KLEINBOTTLE_VIEW, W_Model("h_kleinbottle.iqm"));
+MODEL(KLEINBOTTLE_WORLD, W_Model("v_kleinbottle.md3"));
+
+MODEL(RIFLE_VIEW, W_Model("h_campingrifle.iqm"));
+MODEL(RIFLE_WORLD, W_Model("v_campingrifle.md3"));
+MODEL(RIFLE_ITEM, W_Model("g_campingrifle.md3"));
+
+MODEL(FIREBALL_SPHERE, "models/sphere/sphere.md3");
+MODEL(FIREBALL_VIEW, W_Model("h_fireball.iqm"));
+MODEL(FIREBALL_WORLD, W_Model("v_fireball.md3"));
+MODEL(FIREBALL_ITEM, W_Model("g_fireball.md3"));
+
+MODEL(SEEKER_VIEW, W_Model("h_seeker.iqm"));
+MODEL(SEEKER_WORLD, W_Model("v_seeker.md3"));
+MODEL(SEEKER_ITEM, W_Model("g_seeker.md3"));
+
+MODEL(SHOCKWAVE_MUZZLEFLASH, "models/uziflash.md3");
+MODEL(SHOCKWAVE_VIEW, W_Model("h_shotgun.iqm"));
+MODEL(SHOCKWAVE_WORLD, W_Model("v_shotgun.md3"));
+MODEL(SHOCKWAVE_ITEM, W_Model("g_shotgun.md3"));
+
+MODEL(ARC_MUZZLEFLASH, "models/flash.md3");
+MODEL(ARC_VIEW, W_Model("h_arc.iqm"));
+MODEL(ARC_WORLD, W_Model("v_arc.md3"));
+MODEL(ARC_ITEM, W_Model("g_arc.md3"));
+
+MODEL(HMG_MUZZLEFLASH, "models/uziflash.md3");
+MODEL(HMG_VIEW, W_Model("h_ok_hmg.iqm"));
+MODEL(HMG_WORLD, W_Model("v_ok_hmg.md3"));
+MODEL(HMG_ITEM, W_Model("g_ok_hmg.md3"));
+
+MODEL(RPC_MUZZLEFLASH, "models/flash.md3");
+MODEL(RPC_VIEW, W_Model("h_ok_rl.iqm"));
+MODEL(RPC_WORLD, W_Model("v_ok_rl.md3"));
+MODEL(RPC_ITEM, W_Model("g_ok_rl.md3"));
+
+MODEL(TUR_GIB_BASE1, "models/turrets/base-gib1.md3");
+MODEL(TUR_GIB_BASE2, "models/turrets/base-gib2.md3");
+MODEL(TUR_GIB_BASE3, "models/turrets/base-gib3.md3");
+MODEL(TUR_GIB_BASE4, "models/turrets/base-gib4.md3");
+MODEL(TUR_GIB_HEAD1, "models/turrets/head-gib1.md3");
+MODEL(TUR_GIB_HEAD2, "models/turrets/head-gib2.md3");
+MODEL(TUR_GIB_HEAD3, "models/turrets/head-gib3.md3");
+MODEL(TUR_GIB_HEAD4, "models/turrets/head-gib4.md3");
+MODEL(TUR_BASE, "models/turrets/base.md3");
+
+MODEL(TUR_EWHEEL_BASE, "models/turrets/ewheel-base2.md3");
+MODEL(TUR_EWHEEL_HEAD, "models/turrets/ewheel-gun1.md3");
+
+MODEL(TUR_FLAC_BASE, "models/turrets/base.md3");
+MODEL(TUR_FLAC_HEAD, "models/turrets/flac.md3");
+
+MODEL(TUR_FUSIONREACTOR_BASE, "models/turrets/base.md3");
+MODEL(TUR_FUSIONREACTOR_HEAD, "models/turrets/reactor.md3");
+
+MODEL(TUR_HELLION_BASE, "models/turrets/base.md3");
+MODEL(TUR_HELLION_HEAD, "models/turrets/hellion.md3");
+
+MODEL(TUR_HK_BASE, "models/turrets/base.md3");
+MODEL(TUR_HK_HEAD, "models/turrets/hk.md3");
+
+MODEL(TUR_MACHINEGUN_BASE, "models/turrets/base.md3");
+MODEL(TUR_MACHINEGUN_HEAD, "models/turrets/machinegun.md3");
+
+MODEL(TUR_MIRS_BASE, "models/turrets/base.md3");
+MODEL(TUR_MIRS_HEAD, "models/turrets/mlrs.md3");
+
+MODEL(TUR_PHASER_BASE, "models/turrets/base.md3");
+MODEL(TUR_PHASER_BEAM, "models/turrets/phaser_beam.md3");
+MODEL(TUR_PHASER_HEAD, "models/turrets/phaser.md3");
+
+MODEL(TUR_PLASMA_BASE, "models/turrets/base.md3");
+MODEL(TUR_PLASMA_HEAD, "models/turrets/plasma.md3");
+
+MODEL(TUR_PLASMA_DUAL_BASE, "models/turrets/base.md3");
+MODEL(TUR_PLASMA_DUAL_HEAD, "models/turrets/plasmad.md3");
+
+MODEL(TUR_TESLA_BASE, "models/turrets/tesla_base.md3");
+MODEL(TUR_TESLA_HEAD, "models/turrets/tesla_head.md3");
+
+MODEL(TUR_WALKER_BASE, "models/turrets/walker_body.md3");
+MODEL(TUR_WALKER_HEAD, "models/turrets/walker_head_minigun.md3");
+
+MODEL(VEH_SHIELD, "models/vhshield.md3");
+
+MODEL(VEH_BUMBLEBEE_BODY, "models/vehicles/bumblebee_body.dpm");
+MODEL(VEH_BUMBLEBEE_CANNON_CENTER, "models/vehicles/bumblebee_ray.dpm");
+MODEL(VEH_BUMBLEBEE_CANNON_LEFT, "models/vehicles/bumblebee_plasma_left.dpm");
+MODEL(VEH_BUMBLEBEE_CANNON_RIGHT, "models/vehicles/bumblebee_plasma_right.dpm");
+MODEL(VEH_BUMBLEBEE_SHIELD, "models/vhshield.md3");
+
+MODEL(VEH_RACER_BODY, "models/vehicles/wakizashi.dpm");
+MODEL(VEH_RACER_VIEW, "models/vehicles/wakizashi_cockpit.dpm");
+
+MODEL(VEH_RAPTOR_BODY, "models/vehicles/raptor.dpm");
+MODEL(VEH_RAPTOR_CB_FOLDED, "models/vehicles/clusterbomb_folded.md3");
+MODEL(VEH_RAPTOR_CB_FRAGMENT, "models/vehicles/clusterbomb_fragment.md3");
+MODEL(VEH_RAPTOR_FLARE, "models/runematch/rune.mdl");
+MODEL(VEH_RAPTOR_GUN, "models/vehicles/raptor_gun.dpm");
+MODEL(VEH_RAPTOR_PROP, "models/vehicles/spinner.dpm");
+MODEL(VEH_RAPTOR_TAIL, "models/vehicles/raptor_body.dpm");
+MODEL(VEH_RAPTOR_VIEW, "models/vehicles/raptor_cockpit.dpm");
+
+MODEL(VEH_SPIDERBOT_BODY, "models/vehicles/spiderbot.dpm");
+MODEL(VEH_SPIDERBOT_GUN, "models/vehicles/spiderbot_barrels.dpm");
+MODEL(VEH_SPIDERBOT_MUZZLEFLASH, "models/uziflash.md3");
+MODEL(VEH_SPIDERBOT_TOP, "models/vehicles/spiderbot_top.dpm");
+MODEL(VEH_SPIDERBOT_VIEW, "models/vehicles/spiderbot_cockpit.dpm");
+
+MODEL(CHAT, "models/misc/chatbubble.spr");
+
+MODEL(0, "models/sprites/0.spr32");
+MODEL(1, "models/sprites/1.spr32");
+MODEL(2, "models/sprites/2.spr32");
+MODEL(3, "models/sprites/3.spr32");
+MODEL(4, "models/sprites/4.spr32");
+MODEL(5, "models/sprites/5.spr32");
+MODEL(6, "models/sprites/6.spr32");
+MODEL(7, "models/sprites/7.spr32");
+MODEL(8, "models/sprites/8.spr32");
+MODEL(9, "models/sprites/9.spr32");
+MODEL(10, "models/sprites/10.spr32");
+Model MDL_NUM(int i) {
+ if ((i >= 0 && i <= 10))
+ return Models[MDL_0.m_id + i];
+ return MDL_Null;
+}
+
+MODEL(WAYPOINT, "models/runematch/rune.mdl");
+MODEL(MARKER, "models/marker.md3");
--- /dev/null
+#ifndef MODELS_ALL_H
+#define MODELS_ALL_H
+
+#define setmodel(e, m) _setmodel((e), (m).model_str())
+
+REGISTRY(Models, BIT(9))
+REGISTER_REGISTRY(RegisterModels)
+
+CLASS(Model, Object)
+ ATTRIB(Model, m_id, int, 0)
+ ATTRIB(Model, model_str, string(), func_null)
+ CONSTRUCTOR(Model, string() path)
+ {
+ CONSTRUCT(Model);
+ this.model_str = path;
+ }
+ METHOD(Model, model_precache, void(entity this)) {
+ string s = this.model_str();
+ if (s != "" && s != "null" && !fexists(s)) {
+ LOG_WARNINGF("Missing model: \"%s\"\n", s);
+ return;
+ }
+ LOG_TRACEF("precache_model(\"%s\")\n", s);
+ precache_model(s);
+ }
+ENDCLASS(Model)
+
+#define MODEL(name, path) \
+ string MDL_##name##_get() { return path; } \
+ REGISTER(RegisterModels, MDL, Models, name, m_id, NEW(Model, MDL_##name##_get))
+
+STATIC_INIT(RegisterModels_precache) {
+ FOREACH(Models, true, LAMBDA({
+ it.model_precache(it);
+ }));
+}
+
+MODEL(Null, "null");
+#include "all.inc"
+
+#endif
#ifndef MONSTERS_ALL_C
#define MONSTERS_ALL_C
-#include "all.qh"
-REGISTER_MONSTER(Null, Monster) {
- this.netname = "";
- this.monster_name = "Monster";
- this.monster_func = m_null;
- this.mdl = "";
- this.mins = '-0 -0 -0';
- this.maxs = '0 0 0';
- this.model = "";
-}
+#include "all.qh"
+#define IMPLEMENTATION
#include "all.inc"
-
-entity get_monsterinfo(int id)
-{
- if (id >= MON_FIRST && id <= MON_LAST)
- {
- entity m = monster_info[id];
- if (m) return m;
- }
- return MON_Null;
-}
+#undef IMPLEMENTATION
#endif
#ifndef MONSTERS_ALL_H
#define MONSTERS_ALL_H
-void RegisterMonsters();
-const int MON_MAXCOUNT = 24;
-entity monster_info[MON_MAXCOUNT], monster_info_first, monster_info_last;
-entity get_monsterinfo(float id);
-int MON_COUNT;
-const int MON_FIRST = 1;
-#define MON_LAST (MON_FIRST + MON_COUNT - 1)
-/** If you register a new monster, make sure to add it to all.inc */
-#define REGISTER_MONSTER(id, class) REGISTER(RegisterMonsters, MON, monster_info, MON_COUNT, id, monsterid, NEW(class))
#include "monster.qh"
-#define REGISTER_MONSTER_SIMPLE(id, monsterflags, min_s, max_s, modelname, shortname, mname) \
- REGISTER_MONSTER(id, Monster) { \
- this.netname = shortname; \
- this.monster_name = mname; \
- this.mdl = modelname; \
- this.spawnflags = monsterflags; \
- this.mins = min_s; \
- this.maxs = max_s; \
- this.model = strzone(strcat("models/monsters/", modelname)); \
- } \
- REGISTER_INIT(MON, id)
-REGISTER_REGISTRY(RegisterMonsters)
-
-#include "../util.qh"
-// monster requests
-const int MR_SETUP = 1; // (SERVER) setup monster data
-const int MR_THINK = 2; // (SERVER) logic to run every frame
-const int MR_DEATH = 3; // (SERVER) called when monster dies
-const int MR_PRECACHE = 4; // (BOTH) precaches models/sounds used by this monster
-const int MR_PAIN = 5; // (SERVER) called when monster is damaged
-const int MR_ANIM = 6; // (BOTH?) sets animations for monster
-
-// special spawn flags
-const int MONSTER_RESPAWN_DEATHPOINT = 16; // re-spawn where we died
-const int MONSTER_TYPE_FLY = 32;
-const int MONSTER_TYPE_SWIM = 64;
-const int MONSTER_SIZE_BROKEN = 128; // TODO: remove when bad models are replaced
-const int MON_FLAG_SUPERMONSTER = 256; // incredibly powerful monster
-const int MON_FLAG_RANGED = 512; // monster shoots projectiles
-const int MON_FLAG_MELEE = 1024;
-const int MON_FLAG_CRUSH = 2048; // monster can be stomped in special modes
-const int MON_FLAG_RIDE = 4096; // monster can be ridden in special modes
+REGISTRY(Monsters, BIT(3))
+REGISTER_REGISTRY(RegisterMonsters)
+const int MON_FIRST = 1;
+#define MON_LAST (Monsters_COUNT - 1)
+/** If you register a new monster, make sure to add it to all.inc */
+#define REGISTER_MONSTER(id, inst) REGISTER(RegisterMonsters, MON, Monsters, id, monsterid, inst)
-// entity properties of monsterinfo:
-.string netname; // short name
-.string mdl; // currently a copy of the model
-.string model; // full name of model
-.int spawnflags;
-.vector mins, maxs; // monster hitbox size
-.bool(int) monster_attackfunc;
+REGISTER_MONSTER(Null, NEW(Monster));
-// animations
-.vector anim_blockend;
-.vector anim_blockstart;
-.vector anim_melee1;
-.vector anim_melee2;
-.vector anim_melee3;
-.vector anim_pain3;
-.vector anim_pain4;
-.vector anim_pain5;
-.vector anim_walk;
-.vector anim_spawn;
+Monster get_monsterinfo(int id)
+{
+ if (id >= MON_FIRST && id <= MON_LAST) {
+ Monster m = Monsters[id];
+ if (m) return m;
+ }
+ return MON_Null;
+}
-// other useful macros
-#define MON_ACTION(monstertype,mrequest) (get_monsterinfo(monstertype)).monster_func(mrequest)
+#include "all.inc"
#endif
#ifndef MONSTER_H
#define MONSTER_H
-bool m_null(int) { return false; }
+// special spawn flags
+const int MONSTER_RESPAWN_DEATHPOINT = 16; // re-spawn where we died
+const int MONSTER_TYPE_FLY = 32;
+const int MONSTER_TYPE_SWIM = 64;
+const int MONSTER_SIZE_BROKEN = 128; // TODO: remove when bad models are replaced
+const int MON_FLAG_SUPERMONSTER = 256; // incredibly powerful monster
+const int MON_FLAG_RANGED = 512; // monster shoots projectiles
+const int MON_FLAG_MELEE = 1024;
+const int MON_FLAG_CRUSH = 2048; // monster can be stomped in special modes
+const int MON_FLAG_RIDE = 4096; // monster can be ridden in special modes
+
+// entity properties of monsterinfo:
+.bool(int, entity targ) monster_attackfunc;
+
+// animations
+.vector anim_blockend;
+.vector anim_blockstart;
+.vector anim_melee1;
+.vector anim_melee2;
+.vector anim_melee3;
+.vector anim_pain3;
+.vector anim_pain4;
+.vector anim_pain5;
+.vector anim_walk;
+.vector anim_spawn;
/** If you register a new monster, make sure to add it to all.inc */
CLASS(Monster, Object)
ATTRIB(Monster, monsterid, int, 0)
- ATTRIB(Monster, classname, string, "monster_info")
+ /** attributes */
+ ATTRIB(Monster, spawnflags, int, 0)
/** human readable name */
- ATTRIB(Monster, monster_name, string, string_null)
- ATTRIB(Monster, monster_func, bool(int), m_null)
+ ATTRIB(Monster, monster_name, string, "Monster")
+ /** short name */
+ ATTRIB(Monster, netname, string, "")
+ /** model */
+ ATTRIB(Monster, m_model, entity, NULL)
+ /** hitbox size */
+ ATTRIB(Monster, mins, vector, '-0 -0 -0')
+ /** hitbox size */
+ ATTRIB(Monster, maxs, vector, '0 0 0')
+
+ /** (SERVER) setup monster data */
+ METHOD(Monster, mr_setup, bool(Monster this)) { return false; }
+ /** (SERVER) logic to run every frame */
+ METHOD(Monster, mr_think, bool(Monster this)) { return false; }
+ /** (SERVER) called when monster dies */
+ METHOD(Monster, mr_death, bool(Monster this)) { return false; }
+ /** (BOTH) precaches models/sounds used by this monster */
+ METHOD(Monster, mr_precache, bool(Monster this)) { return false; }
+ /** (SERVER) called when monster is damaged */
+ METHOD(Monster, mr_pain, bool(Monster this)) { return false; }
+ /** (BOTH?) sets animations for monster */
+ METHOD(Monster, mr_anim, bool(Monster this)) { return false; }
+
ENDCLASS(Monster)
#endif
+#ifndef MAGE_H
+#define MAGE_H
+
#ifndef MENUQC
-bool M_Mage(int);
+MODEL(MON_MAGE, "models/monsters/mage.dpm");
#endif
-REGISTER_MONSTER_SIMPLE(
-/* MON_##id */ MAGE,
-/* spawnflags */ MON_FLAG_MELEE | MON_FLAG_RANGED,
-/* mins,maxs */ '-36 -36 -24', '36 36 50',
-/* model */ "mage.dpm",
-/* netname */ "mage",
-/* fullname */ _("Mage")
-) {
+
+CLASS(Mage, Monster)
+ ATTRIB(Mage, spawnflags, int, MON_FLAG_MELEE | MON_FLAG_RANGED);
+ ATTRIB(Mage, mins, vector, '-36 -36 -24');
+ ATTRIB(Mage, maxs, vector, '36 36 50');
+#ifndef MENUQC
+ ATTRIB(Mage, m_model, Model, MDL_MON_MAGE);
+#endif
+ ATTRIB(Mage, netname, string, "mage");
+ ATTRIB(Mage, monster_name, string, _("Mage"));
+ENDCLASS(Mage)
+
+REGISTER_MONSTER(MAGE, NEW(Mage)) {
#ifndef MENUQC
- this.monster_func = M_Mage;
- this.monster_func(MR_PRECACHE);
+ this.mr_precache(this);
#endif
}
+#include "../../weapons/all.qh"
+
+CLASS(MageSpike, PortoLaunch)
+/* flags */ ATTRIB(MageSpike, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse */ ATTRIB(MageSpike, impulse, int, 9);
+/* refname */ ATTRIB(MageSpike, netname, string, "magespike");
+/* wepname */ ATTRIB(MageSpike, message, string, _("Mage spike"));
+ENDCLASS(MageSpike)
+REGISTER_WEAPON(MAGE_SPIKE, NEW(MageSpike));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
#ifdef SVQC
+
+void M_Mage_Attack_Spike(vector dir);
+void M_Mage_Attack_Push();
+METHOD(MageSpike, wr_think, void(MageSpike thiswep, entity actor, bool fire1, bool fire2)) {
+ if (fire1)
+ if (!IS_PLAYER(actor) || weapon_prepareattack(thiswep, actor, false, 0.2)) {
+ if (!actor.target_range) actor.target_range = autocvar_g_monsters_target_range;
+ actor.enemy = Monster_FindTarget(actor);
+ W_SetupShot_Dir(actor, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+ if (!IS_PLAYER(actor)) w_shotdir = normalize((actor.enemy.origin + '0 0 10') - actor.origin);
+ M_Mage_Attack_Spike(w_shotdir);
+ weapon_thinkf(actor, WFRAME_FIRE1, 0, w_ready);
+ }
+ if (fire2)
+ if (!IS_PLAYER(actor) || weapon_prepareattack(thiswep, actor, true, 0.5)) {
+ M_Mage_Attack_Push();
+ weapon_thinkf(actor, WFRAME_FIRE2, 0, w_ready);
+ }
+}
+
+void M_Mage_Attack_Teleport();
+
+CLASS(OffhandMageTeleport, OffhandWeapon)
+ .bool OffhandMageTeleport_key_pressed;
+ METHOD(OffhandMageTeleport, offhand_think, void(OffhandMageTeleport this, entity player, bool key_pressed))
+ {
+ if (key_pressed && !player.OffhandMageTeleport_key_pressed)
+ WITH(entity, self, player, M_Mage_Attack_Teleport());
+ player.OffhandMageTeleport_key_pressed = key_pressed;
+ }
+ENDCLASS(OffhandMageTeleport)
+OffhandMageTeleport OFFHAND_MAGE_TELEPORT; STATIC_INIT(OFFHAND_MAGE_TELEPORT) { OFFHAND_MAGE_TELEPORT = NEW(OffhandMageTeleport); }
+
float autocvar_g_monster_mage_health;
float autocvar_g_monster_mage_damageforcescale = 0.5;
float autocvar_g_monster_mage_attack_spike_damage;
.float mage_shield_time;
float M_Mage_Defend_Heal_Check(entity e)
-{
+{SELFPARAM();
if(e == world)
return false;
if(e.health <= 0)
}
void M_Mage_Attack_Spike_Explode()
-{
+{SELFPARAM();
self.event_damage = func_null;
- sound(self, CH_SHOTS, W_Sound("grenade_impact"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_GRENADE_IMPACT, VOL_BASE, ATTEN_NORM);
self.realowner.mage_spike = world;
// copied from W_Seeker_Think
void M_Mage_Attack_Spike_Think()
-{
- entity e;
- vector desireddir, olddir, newdir, eorg;
- float turnrate;
- float dist;
- float spd;
-
- if (time > self.ltime || self.enemy.health <= 0 || self.owner.health <= 0)
- {
+{SELFPARAM();
+ if (time > self.ltime || (self.enemy && self.enemy.health <= 0) || self.owner.health <= 0) {
self.projectiledeathtype |= HITTYPE_SPLASH;
M_Mage_Attack_Spike_Explode();
}
- spd = vlen(self.velocity);
+ float spd = vlen(self.velocity);
spd = bound(
spd - (autocvar_g_monster_mage_attack_spike_decel) * frametime,
(autocvar_g_monster_mage_attack_spike_speed_max),
if (self.enemy != world)
{
- e = self.enemy;
- eorg = 0.5 * (e.absmin + e.absmax);
- turnrate = (autocvar_g_monster_mage_attack_spike_turnrate); // how fast to turn
- desireddir = normalize(eorg - self.origin);
- olddir = normalize(self.velocity); // get my current direction
- dist = vlen(eorg - self.origin);
+ entity e = self.enemy;
+ vector eorg = 0.5 * (e.absmin + e.absmax);
+ float turnrate = (autocvar_g_monster_mage_attack_spike_turnrate); // how fast to turn
+ vector desireddir = normalize(eorg - self.origin);
+ vector olddir = normalize(self.velocity); // get my current direction
+ float dist = vlen(eorg - self.origin);
// Do evasive maneuvers for world objects? ( this should be a cpu hog. :P )
if ((autocvar_g_monster_mage_attack_spike_smart) && (dist > (autocvar_g_monster_mage_attack_spike_smart_mindist)))
desireddir = normalize(((trace_plane_normal * (1 - trace_fraction)) + (desireddir * trace_fraction)) * 0.5);
}
- newdir = normalize(olddir + desireddir * turnrate); // take the average of the 2 directions; not the best method but simple & easy
+ vector newdir = normalize(olddir + desireddir * turnrate); // take the average of the 2 directions; not the best method but simple & easy
self.velocity = newdir * spd; // make me fly in the new direction at my flight speed
}
- else
- dist = 0;
///////////////
UpdateCSQCProjectile(self);
}
-void M_Mage_Attack_Spike()
+void M_Mage_Attack_Spike(vector dir)
{
- entity missile;
- vector dir = normalize((self.enemy.origin + '0 0 10') - self.origin);
-
+ SELFPARAM();
makevectors(self.angles);
- missile = spawn ();
+ entity missile = spawn();
missile.owner = missile.realowner = self;
missile.think = M_Mage_Attack_Spike_Think;
missile.ltime = time + 7;
missile.movetype = MOVETYPE_FLYMISSILE;
missile.flags = FL_PROJECTILE;
setorigin(missile, self.origin + v_forward * 14 + '0 0 30' + v_right * -14);
- setsize (missile, '0 0 0', '0 0 0');
+ setsize(missile, '0 0 0', '0 0 0');
missile.velocity = dir * 400;
missile.avelocity = '300 300 300';
missile.enemy = self.enemy;
}
void M_Mage_Defend_Heal()
-{
+{SELFPARAM();
entity head;
float washealed = false;
}
void M_Mage_Attack_Push()
-{
- sound(self, CH_SHOTS, W_Sound("tagexp1"), 1, ATTEN_NORM);
+{SELFPARAM();
+ sound(self, CH_SHOTS, SND_TAGEXP1, 1, ATTEN_NORM);
RadiusDamage (self, self, (autocvar_g_monster_mage_attack_push_damage), (autocvar_g_monster_mage_attack_push_damage), (autocvar_g_monster_mage_attack_push_radius), world, world, (autocvar_g_monster_mage_attack_push_force), DEATH_MONSTER_MAGE, self.enemy);
Send_Effect(EFFECT_TE_EXPLOSION, self.origin, '0 0 0', 1);
}
void M_Mage_Attack_Teleport()
-{
- if(vlen(self.enemy.origin - self.origin) >= 500)
- return;
+{SELFPARAM();
+ entity targ = self.enemy;
+ if (!targ) return;
+ if (vlen(targ.origin - self.origin) > 1500) return;
- makevectors(self.enemy.angles);
- tracebox(self.enemy.origin + ((v_forward * -1) * 200), self.mins, self.maxs, self.origin, MOVE_NOMONSTERS, self);
+ makevectors(targ.angles);
+ tracebox(targ.origin + ((v_forward * -1) * 200), self.mins, self.maxs, self.origin, MOVE_NOMONSTERS, self);
if(trace_fraction < 1)
return;
Send_Effect(EFFECT_SPAWN_NEUTRAL, self.origin, '0 0 0', 1);
- setorigin(self, self.enemy.origin + ((v_forward * -1) * 200));
+ setorigin(self, targ.origin + ((v_forward * -1) * 200));
+
+ vector a = vectoangles(targ.origin - self.origin);
+ a.x = -a.x;
+ self.angles_x = a.x;
+ self.angles_y = a.y;
+ self.fixangle = true;
+ self.velocity *= 0.5;
self.attack_finished_single = time + 0.2;
}
void M_Mage_Defend_Shield_Remove()
-{
+{SELFPARAM();
self.effects &= ~(EF_ADDITIVE | EF_BLUE);
self.armorvalue = autocvar_g_monsters_armor_blockpercent;
}
void M_Mage_Defend_Shield()
-{
+{SELFPARAM();
self.effects |= (EF_ADDITIVE | EF_BLUE);
self.mage_shield_delay = time + (autocvar_g_monster_mage_shield_delay);
self.armorvalue = (autocvar_g_monster_mage_shield_blockpercent);
self.anim_finished = time + 1;
}
-float M_Mage_Attack(float attack_type)
-{
+float M_Mage_Attack(float attack_type, entity targ)
+{SELFPARAM();
switch(attack_type)
{
case MONSTER_ATTACK_MELEE:
{
if(random() <= 0.7)
{
- M_Mage_Attack_Push();
+ Weapon wep = WEP_MAGE_SPIKE;
+ wep.wr_think(wep, self, false, true);
return true;
}
{
if(random() <= 0.4)
{
- M_Mage_Attack_Teleport();
+ OffhandWeapon off = OFFHAND_MAGE_TELEPORT;
+ off.offhand_think(off, self, true);
return true;
}
else
setanim(self, self.anim_shoot, true, true, true);
self.attack_finished_single = time + (autocvar_g_monster_mage_attack_spike_delay);
self.anim_finished = time + 1;
- Monster_Delay(1, 0, 0.2, M_Mage_Attack_Spike);
+ Weapon wep = WEP_MAGE_SPIKE;
+ wep.wr_think(wep, self, true, false);
return true;
}
}
return false;
}
-void spawnfunc_monster_mage() { Monster_Spawn(MON_MAGE.monsterid); }
+spawnfunc(monster_mage) { Monster_Spawn(MON_MAGE.monsterid); }
#endif // SVQC
-bool M_Mage(int req)
-{
- switch(req)
- {
#ifdef SVQC
- case MR_THINK:
+ METHOD(Mage, mr_think, bool(Monster thismon))
{
+ SELFPARAM();
entity head;
bool need_help = false;
return true;
}
- case MR_PAIN:
+ METHOD(Mage, mr_pain, bool(Monster thismon))
{
return true;
}
- case MR_DEATH:
+ METHOD(Mage, mr_death, bool(Monster thismon))
{
+ SELFPARAM();
setanim(self, self.anim_die1, false, true, true);
return true;
}
#endif
#ifndef MENUQC
- case MR_ANIM:
+ METHOD(Mage, mr_anim, bool(Monster thismon))
{
+ SELFPARAM();
vector none = '0 0 0';
self.anim_die1 = animfixfps(self, '4 1 0.5', none); // 2 seconds
self.anim_walk = animfixfps(self, '1 1 1', none);
}
#endif
#ifdef SVQC
- case MR_SETUP:
+ METHOD(Mage, mr_setup, bool(Monster thismon))
{
+ SELFPARAM();
if(!self.health) self.health = (autocvar_g_monster_mage_health);
if(!self.speed) { self.speed = (autocvar_g_monster_mage_speed_walk); }
if(!self.speed2) { self.speed2 = (autocvar_g_monster_mage_speed_run); }
return true;
}
- case MR_PRECACHE:
+ METHOD(Mage, mr_precache, bool(Monster thismon))
{
- precache_model("models/monsters/mage.dpm");
- precache_sound (W_Sound("grenade_impact"));
- precache_sound (W_Sound("tagexp1"));
return true;
}
#endif
- }
- return true;
-}
+#endif
+#ifndef SHAMBLER_H
+#define SHAMBLER_H
+
+#ifndef MENUQC
+MODEL(MON_SHAMBLER, "models/monsters/shambler.mdl");
+#endif
+
+CLASS(Shambler, Monster)
+ ATTRIB(Shambler, spawnflags, int, MONSTER_SIZE_BROKEN | MON_FLAG_SUPERMONSTER | MON_FLAG_MELEE | MON_FLAG_RANGED);
+ ATTRIB(Shambler, mins, vector, '-41 -41 -31');
+ ATTRIB(Shambler, maxs, vector, '41 41 65');
#ifndef MENUQC
-bool M_Shambler(int);
+ ATTRIB(Shambler, m_model, Model, MDL_MON_SHAMBLER);
#endif
-REGISTER_MONSTER_SIMPLE(
-/* MON_##id */ SHAMBLER,
-/* spawnflags */ MONSTER_SIZE_BROKEN | MON_FLAG_SUPERMONSTER | MON_FLAG_MELEE | MON_FLAG_RANGED,
-/* mins,maxs */ '-41 -41 -31', '41 41 65',
-/* model */ "shambler.mdl",
-/* netname */ "shambler",
-/* fullname */ _("Shambler")
-) {
+ ATTRIB(Shambler, netname, string, "shambler");
+ ATTRIB(Shambler, monster_name, string, _("Shambler"));
+ENDCLASS(Shambler)
+
+REGISTER_MONSTER(SHAMBLER, NEW(Shambler)) {
#ifndef MENUQC
- this.monster_func = M_Shambler;
- this.monster_func(MR_PRECACHE);
+ this.mr_precache(this);
#endif
}
+#endif
+
+#ifdef IMPLEMENTATION
+
#ifdef SVQC
float autocvar_g_monster_shambler_health;
float autocvar_g_monster_shambler_damageforcescale = 0.1;
.float shambler_lastattack; // delay attacks separately
void M_Shambler_Attack_Smash()
-{
+{SELFPARAM();
makevectors(self.angles);
Send_Effect(EFFECT_EXPLOSION_MEDIUM, (self.origin + (v_forward * 150)) - ('0 0 1' * self.maxs.z), '0 0 0', 1);
- sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
// RadiusDamage does NOT support custom starting location, which means we must use this hack...
}
void M_Shambler_Attack_Swing()
-{
+{SELFPARAM();
float r = (random() < 0.5);
if(r && Monster_Attack_Melee(self.enemy, (autocvar_g_monster_shambler_attack_claw_damage), ((r) ? self.anim_melee2 : self.anim_melee3), self.attack_range, 0.8, DEATH_MONSTER_SHAMBLER_CLAW, true))
{
}
void M_Shambler_Attack_Lightning_Explode()
-{
+{SELFPARAM();
entity head;
- sound(self, CH_SHOTS, W_Sound("electro_impact"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_ELECTRO_IMPACT, VOL_BASE, ATTEN_NORM);
Send_Effect(EFFECT_ELECTRO_IMPACT, '0 0 0', '0 0 0', 1);
self.event_damage = func_null;
}
void M_Shambler_Attack_Lightning_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
if (self.health <= 0)
return;
}
void M_Shambler_Attack_Lightning_Touch()
-{
+{SELFPARAM();
PROJECTILE_TOUCH;
self.use ();
}
void M_Shambler_Attack_Lightning_Think()
-{
+{SELFPARAM();
self.nextthink = time;
if (time > self.cnt)
{
}
void M_Shambler_Attack_Lightning()
-{
+{SELFPARAM();
entity gren;
monster_makevectors(self.enemy);
CSQCProjectile(gren, true, PROJECTILE_SHAMBLER_LIGHTNING, true);
}
-float M_Shambler_Attack(float attack_type)
-{
+float M_Shambler_Attack(float attack_type, entity targ)
+{SELFPARAM();
switch(attack_type)
{
case MONSTER_ATTACK_MELEE:
return false;
}
-void spawnfunc_monster_shambler() { Monster_Spawn(MON_SHAMBLER.monsterid); }
+spawnfunc(monster_shambler) { Monster_Spawn(MON_SHAMBLER.monsterid); }
#endif // SVQC
-bool M_Shambler(int req)
-{
- switch(req)
- {
#ifdef SVQC
- case MR_THINK:
+ METHOD(Shambler, mr_think, bool(Shambler thismon))
{
return true;
}
- case MR_PAIN:
+ METHOD(Shambler, mr_pain, bool(Shambler thismon))
{
+ SELFPARAM();
self.pain_finished = time + 0.5;
setanim(self, self.anim_pain1, true, true, false);
return true;
}
- case MR_DEATH:
+ METHOD(Shambler, mr_death, bool(Shambler thismon))
{
+ SELFPARAM();
setanim(self, self.anim_die1, false, true, true);
return true;
}
#endif
#ifndef MENUQC
- case MR_ANIM:
+ METHOD(Shambler, mr_anim, bool(Shambler thismon))
{
+ SELFPARAM();
vector none = '0 0 0';
self.anim_die1 = animfixfps(self, '8 1 0.5', none); // 2 seconds
self.anim_walk = animfixfps(self, '1 1 1', none);
}
#endif
#ifdef SVQC
- case MR_SETUP:
+ METHOD(Shambler, mr_setup, bool(Shambler thismon))
{
+ SELFPARAM();
if(!self.health) self.health = (autocvar_g_monster_shambler_health);
if(!self.attack_range) self.attack_range = 150;
if(!self.speed) { self.speed = (autocvar_g_monster_shambler_speed_walk); }
return true;
}
- case MR_PRECACHE:
+ METHOD(Shambler, mr_precache, bool(Shambler thismon))
{
- precache_model("models/monsters/shambler.mdl");
return true;
}
#endif
- }
- return true;
-}
+#endif
+#ifndef SPIDER_H
+#define SPIDER_H
+
#ifndef MENUQC
-bool M_Spider(int);
+MODEL(MON_SPIDER, "models/monsters/spider.dpm");
#endif
-REGISTER_MONSTER_SIMPLE(
-/* MON_##id */ SPIDER,
-/* spawnflags */ MON_FLAG_MELEE | MON_FLAG_RANGED | MON_FLAG_RIDE,
-/* mins,maxs */ '-18 -18 -25', '18 18 30',
-/* model */ "spider.dpm",
-/* netname */ "spider",
-/* fullname */ _("Spider")
-) {
+
+CLASS(Spider, Monster)
+ ATTRIB(Spider, spawnflags, int, MON_FLAG_MELEE | MON_FLAG_RANGED | MON_FLAG_RIDE);
+ ATTRIB(Spider, mins, vector, '-18 -18 -25');
+ ATTRIB(Spider, maxs, vector, '18 18 30');
+#ifndef MENUQC
+ ATTRIB(Spider, m_model, Model, MDL_MON_SPIDER);
+#endif
+ ATTRIB(Spider, netname, string, "spider");
+ ATTRIB(Spider, monster_name, string, _("Spider"));
+ENDCLASS(Spider)
+
+REGISTER_MONSTER(SPIDER, NEW(Spider)) {
#ifndef MENUQC
- this.monster_func = M_Spider;
- this.monster_func(MR_PRECACHE);
+ this.mr_precache(this);
#endif
}
+#include "../../weapons/all.qh"
+
+CLASS(SpiderAttack, PortoLaunch)
+/* flags */ ATTRIB(SpiderAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse */ ATTRIB(SpiderAttack, impulse, int, 9);
+/* refname */ ATTRIB(SpiderAttack, netname, string, "spider");
+/* wepname */ ATTRIB(SpiderAttack, message, string, _("Spider attack"));
+ENDCLASS(SpiderAttack)
+REGISTER_WEAPON(SPIDER_ATTACK, NEW(SpiderAttack));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
#ifdef SVQC
-float autocvar_g_monster_spider_health;
-float autocvar_g_monster_spider_damageforcescale = 0.6;
-float autocvar_g_monster_spider_attack_bite_damage;
-float autocvar_g_monster_spider_attack_bite_delay;
+
+.float spider_web_delay;
+
float autocvar_g_monster_spider_attack_web_damagetime;
float autocvar_g_monster_spider_attack_web_speed;
float autocvar_g_monster_spider_attack_web_speed_up;
float autocvar_g_monster_spider_attack_web_delay;
+
+float autocvar_g_monster_spider_attack_bite_damage;
+float autocvar_g_monster_spider_attack_bite_delay;
+
+void M_Spider_Attack_Web();
+
+METHOD(SpiderAttack, wr_think, void(SpiderAttack thiswep, entity actor, bool fire1, bool fire2)) {
+ bool isPlayer = IS_PLAYER(actor);
+ if (fire1)
+ if ((!isPlayer && time >= actor.spider_web_delay) || weapon_prepareattack(thiswep, actor, false, autocvar_g_monster_spider_attack_web_delay)) {
+ if (!isPlayer) {
+ actor.spider_web_delay = time + 3;
+ setanim(actor, actor.anim_shoot, true, true, true);
+ actor.attack_finished_single = time + (autocvar_g_monster_spider_attack_web_delay);
+ actor.anim_finished = time + 1;
+ }
+ if (isPlayer) actor.enemy = Monster_FindTarget(actor);
+ W_SetupShot_Dir(actor, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+ if (!isPlayer) w_shotdir = normalize((actor.enemy.origin + '0 0 10') - actor.origin);
+ M_Spider_Attack_Web();
+ weapon_thinkf(actor, WFRAME_FIRE1, 0, w_ready);
+ return;
+ }
+ if (fire2)
+ if (!isPlayer || weapon_prepareattack(thiswep, actor, true, 0.5)) {
+ if (isPlayer) {
+ actor.enemy = Monster_FindTarget(actor);
+ actor.attack_range = 60;
+ }
+ Monster_Attack_Melee(actor.enemy, (autocvar_g_monster_spider_attack_bite_damage), ((random() > 0.5) ? self.anim_melee : self.anim_shoot), self.attack_range, (autocvar_g_monster_spider_attack_bite_delay), DEATH_MONSTER_SPIDER, true);
+ weapon_thinkf(actor, WFRAME_FIRE2, 0, w_ready);
+ }
+}
+
+float autocvar_g_monster_spider_health;
+float autocvar_g_monster_spider_damageforcescale = 0.6;
float autocvar_g_monster_spider_speed_stop;
float autocvar_g_monster_spider_speed_run;
float autocvar_g_monster_spider_speed_walk;
const float spider_anim_attack2 = 3;
*/
-.float spider_web_delay;
-
void M_Spider_Attack_Web_Explode()
-{
+{SELFPARAM();
entity e;
if(self)
{
}
void M_Spider_Attack_Web()
-{
+{SELFPARAM();
monster_makevectors(self.enemy);
- sound(self, CH_SHOTS, W_Sound("electro_fire2"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_ELECTRO_FIRE2, VOL_BASE, ATTEN_NORM);
entity proj = spawn ();
proj.classname = "plasma";
CSQCProjectile(proj, true, PROJECTILE_ELECTRO, true);
}
-bool M_Spider_Attack(int attack_type)
-{
+bool M_Spider_Attack(int attack_type, entity targ)
+{SELFPARAM();
switch(attack_type)
{
+ Weapon wep = WEP_SPIDER_ATTACK;
case MONSTER_ATTACK_MELEE:
{
- return Monster_Attack_Melee(self.enemy, (autocvar_g_monster_spider_attack_bite_damage), ((random() > 0.5) ? self.anim_melee : self.anim_shoot), self.attack_range, (autocvar_g_monster_spider_attack_bite_delay), DEATH_MONSTER_SPIDER, true);
+ wep.wr_think(wep, self, false, true);
+ return true;
}
case MONSTER_ATTACK_RANGED:
{
- if(time >= self.spider_web_delay)
- {
- setanim(self, self.anim_shoot, true, true, true);
- self.attack_finished_single = time + (autocvar_g_monster_spider_attack_web_delay);
- self.anim_finished = time + 1;
- M_Spider_Attack_Web();
- self.spider_web_delay = time + 3;
- return true;
- }
-
- return false;
+ wep.wr_think(wep, self, true, false);
+ return true;
}
}
return false;
}
-void spawnfunc_monster_spider() { Monster_Spawn(MON_SPIDER.monsterid); }
+spawnfunc(monster_spider) { Monster_Spawn(MON_SPIDER.monsterid); }
#endif // SVQC
-bool M_Spider(int req)
-{
- switch(req)
- {
#ifdef SVQC
- case MR_THINK:
+ METHOD(Spider, mr_think, bool(Spider thismon))
{
return true;
}
- case MR_PAIN:
+ METHOD(Spider, mr_pain, bool(Spider thismon))
{
return true;
}
- case MR_DEATH:
+ METHOD(Spider, mr_death, bool(Spider thismon))
{
+ SELFPARAM();
setanim(self, self.anim_melee, false, true, true);
self.angles_x = 180;
return true;
}
#endif
#ifndef MENUQC
- case MR_ANIM:
+ METHOD(Spider, mr_anim, bool(Spider thismon))
{
+ SELFPARAM();
vector none = '0 0 0';
self.anim_walk = animfixfps(self, '1 1 1', none);
self.anim_idle = animfixfps(self, '0 1 1', none);
}
#endif
#ifdef SVQC
- case MR_SETUP:
+ METHOD(Spider, mr_setup, bool(Spider thismon))
{
+ SELFPARAM();
if(!self.health) self.health = (autocvar_g_monster_spider_health);
if(!self.speed) { self.speed = (autocvar_g_monster_spider_speed_walk); }
if(!self.speed2) { self.speed2 = (autocvar_g_monster_spider_speed_run); }
return true;
}
- case MR_PRECACHE:
+ METHOD(Spider, mr_precache, bool(Spider thismon))
{
- precache_model("models/monsters/spider.dpm");
- precache_sound (W_Sound("electro_fire2"));
return true;
}
#endif
- }
- return true;
-}
+#endif
+#ifndef WYVERN_H
+#define WYVERN_H
+
#ifndef MENUQC
-bool M_Wyvern(int);
+MODEL(MON_WYVERN, "models/monsters/wizard.mdl");
#endif
-REGISTER_MONSTER_SIMPLE(
-/* MON_##id */ WYVERN,
-/* spawnflags */ MONSTER_TYPE_FLY | MONSTER_SIZE_BROKEN | MON_FLAG_RANGED | MON_FLAG_RIDE,
-/* mins,maxs */ '-20 -20 -58', '20 20 20',
-/* model */ "wizard.mdl",
-/* netname */ "wyvern",
-/* fullname */ _("Wyvern")
-) {
+
+CLASS(Wyvern, Monster)
+ ATTRIB(Wyvern, spawnflags, int, MONSTER_TYPE_FLY | MONSTER_SIZE_BROKEN | MON_FLAG_RANGED | MON_FLAG_RIDE);
+ ATTRIB(Wyvern, mins, vector, '-20 -20 -58');
+ ATTRIB(Wyvern, maxs, vector, '20 20 20');
+#ifndef MENUQC
+ ATTRIB(Wyvern, m_model, Model, MDL_MON_WYVERN);
+#endif
+ ATTRIB(Wyvern, netname, string, "wyvern");
+ ATTRIB(Wyvern, monster_name, string, _("Wyvern"));
+ENDCLASS(Wyvern)
+
+REGISTER_MONSTER(WYVERN, NEW(Wyvern)) {
#ifndef MENUQC
- this.monster_func = M_Wyvern;
- this.monster_func(MR_PRECACHE);
+ this.mr_precache(this);
#endif
}
+#include "../../weapons/all.qh"
+
+CLASS(WyvernAttack, PortoLaunch)
+/* flags */ ATTRIB(WyvernAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse */ ATTRIB(WyvernAttack, impulse, int, 9);
+/* refname */ ATTRIB(WyvernAttack, netname, string, "wyvern");
+/* wepname */ ATTRIB(WyvernAttack, message, string, _("Wyvern attack"));
+ENDCLASS(WyvernAttack)
+REGISTER_WEAPON(WYVERN_ATTACK, NEW(WyvernAttack));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
#ifdef SVQC
-float autocvar_g_monster_wyvern_health;
-float autocvar_g_monster_wyvern_damageforcescale = 0.6;
+
float autocvar_g_monster_wyvern_attack_fireball_damage;
float autocvar_g_monster_wyvern_attack_fireball_edgedamage;
float autocvar_g_monster_wyvern_attack_fireball_damagetime;
float autocvar_g_monster_wyvern_attack_fireball_force;
float autocvar_g_monster_wyvern_attack_fireball_radius;
float autocvar_g_monster_wyvern_attack_fireball_speed;
+
+void M_Wyvern_Attack_Fireball_Explode();
+void M_Wyvern_Attack_Fireball_Touch();
+
+METHOD(WyvernAttack, wr_think, void(WyvernAttack thiswep, entity actor, bool fire1, bool fire2)) {
+ if (fire1)
+ if (time > actor.attack_finished_single || weapon_prepareattack(thiswep, actor, false, 1.2)) {
+ if (IS_PLAYER(actor)) W_SetupShot_Dir(actor, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+ if (IS_MONSTER(actor)) {
+ actor.attack_finished_single = time + 1.2;
+ actor.anim_finished = time + 1.2;
+ monster_makevectors(actor.enemy);
+ }
+
+ entity missile = spawn();
+ missile.owner = missile.realowner = actor;
+ missile.solid = SOLID_TRIGGER;
+ missile.movetype = MOVETYPE_FLYMISSILE;
+ missile.projectiledeathtype = DEATH_MONSTER_WYVERN;
+ setsize(missile, '-6 -6 -6', '6 6 6');
+ setorigin(missile, actor.origin + actor.view_ofs + v_forward * 14);
+ missile.flags = FL_PROJECTILE;
+ missile.velocity = w_shotdir * (autocvar_g_monster_wyvern_attack_fireball_speed);
+ missile.avelocity = '300 300 300';
+ missile.nextthink = time + 5;
+ missile.think = M_Wyvern_Attack_Fireball_Explode;
+ missile.touch = M_Wyvern_Attack_Fireball_Touch;
+ CSQCProjectile(missile, true, PROJECTILE_FIREMINE, true);
+
+ weapon_thinkf(actor, WFRAME_FIRE1, 0, w_ready);
+ }
+}
+
+METHOD(WyvernAttack, wr_checkammo1, bool(WyvernAttack thiswep)) {
+ return true;
+}
+
+float autocvar_g_monster_wyvern_health;
+float autocvar_g_monster_wyvern_damageforcescale = 0.6;
float autocvar_g_monster_wyvern_speed_stop;
float autocvar_g_monster_wyvern_speed_run;
float autocvar_g_monster_wyvern_speed_walk;
void M_Wyvern_Attack_Fireball_Explode()
{
- entity e;
- if(self)
- {
- Send_Effect(EFFECT_FIREBALL_EXPLODE, self.origin, '0 0 0', 1);
+ SELFPARAM();
+ Send_Effect(EFFECT_FIREBALL_EXPLODE, self.origin, '0 0 0', 1);
- RadiusDamage(self, self.realowner, (autocvar_g_monster_wyvern_attack_fireball_damage), (autocvar_g_monster_wyvern_attack_fireball_edgedamage), (autocvar_g_monster_wyvern_attack_fireball_force), world, world, (autocvar_g_monster_wyvern_attack_fireball_radius), self.projectiledeathtype, world);
+ entity owner = self.realowner;
- for(e = world; (e = findfloat(e, takedamage, DAMAGE_AIM)); ) if(vlen(e.origin - self.origin) <= (autocvar_g_monster_wyvern_attack_fireball_radius))
- Fire_AddDamage(e, self, 5 * MONSTER_SKILLMOD(self), (autocvar_g_monster_wyvern_attack_fireball_damagetime), self.projectiledeathtype);
+ RadiusDamage(self, owner, autocvar_g_monster_wyvern_attack_fireball_damage, autocvar_g_monster_wyvern_attack_fireball_edgedamage, autocvar_g_monster_wyvern_attack_fireball_force, world, world, autocvar_g_monster_wyvern_attack_fireball_radius, self.projectiledeathtype, world);
- remove(self);
- }
+ for (entity e = world; (e = findfloat(e, takedamage, DAMAGE_AIM)); )
+ if (vlen(e.origin - self.origin) <= (autocvar_g_monster_wyvern_attack_fireball_radius))
+ Fire_AddDamage(e, owner, 5 * MONSTER_SKILLMOD(owner), (autocvar_g_monster_wyvern_attack_fireball_damagetime), self.projectiledeathtype);
+
+ remove(self);
}
void M_Wyvern_Attack_Fireball_Touch()
M_Wyvern_Attack_Fireball_Explode();
}
-void M_Wyvern_Attack_Fireball()
-{
- entity missile = spawn();
- vector dir = normalize((self.enemy.origin + '0 0 10') - self.origin);
-
- monster_makevectors(self.enemy);
-
- missile.owner = missile.realowner = self;
- missile.solid = SOLID_TRIGGER;
- missile.movetype = MOVETYPE_FLYMISSILE;
- missile.projectiledeathtype = DEATH_MONSTER_WYVERN;
- setsize(missile, '-6 -6 -6', '6 6 6');
- setorigin(missile, self.origin + self.view_ofs + v_forward * 14);
- missile.flags = FL_PROJECTILE;
- missile.velocity = dir * (autocvar_g_monster_wyvern_attack_fireball_speed);
- missile.avelocity = '300 300 300';
- missile.nextthink = time + 5;
- missile.think = M_Wyvern_Attack_Fireball_Explode;
- missile.enemy = self.enemy;
- missile.touch = M_Wyvern_Attack_Fireball_Touch;
- CSQCProjectile(missile, true, PROJECTILE_FIREMINE, true);
-}
-
-float M_Wyvern_Attack(float attack_type)
+float M_Wyvern_Attack(float attack_type, entity targ)
{
+ SELFPARAM();
switch(attack_type)
{
case MONSTER_ATTACK_MELEE:
case MONSTER_ATTACK_RANGED:
{
- self.attack_finished_single = time + 1.2;
- self.anim_finished = time + 1.2;
-
- M_Wyvern_Attack_Fireball();
-
+ w_shotdir = normalize((self.enemy.origin + '0 0 10') - self.origin);
+ Weapon wep = WEP_WYVERN_ATTACK;
+ wep.wr_think(wep, self, true, false);
return true;
}
}
return false;
}
-void spawnfunc_monster_wyvern() { Monster_Spawn(MON_WYVERN.monsterid); }
+spawnfunc(monster_wyvern) { Monster_Spawn(MON_WYVERN.monsterid); }
#endif // SVQC
-bool M_Wyvern(int req)
-{
- switch(req)
- {
#ifdef SVQC
- case MR_THINK:
+ METHOD(Wyvern, mr_think, bool(Wyvern thismon))
{
return true;
}
- case MR_PAIN:
+ METHOD(Wyvern, mr_pain, bool(Wyvern thismon))
{
+ SELFPARAM();
self.pain_finished = time + 0.5;
setanim(self, self.anim_pain1, true, true, false);
return true;
}
- case MR_DEATH:
+ METHOD(Wyvern, mr_death, bool(Wyvern thismon))
{
+ SELFPARAM();
setanim(self, self.anim_die1, false, true, true);
self.velocity_x = -200 + 400 * random();
self.velocity_y = -200 + 400 * random();
}
#endif
#ifndef MENUQC
- case MR_ANIM:
+ METHOD(Wyvern, mr_anim, bool(Wyvern thismon))
{
+ SELFPARAM();
vector none = '0 0 0';
self.anim_die1 = animfixfps(self, '4 1 0.5', none); // 2 seconds
self.anim_walk = animfixfps(self, '1 1 1', none);
}
#endif
#ifdef SVQC
- case MR_SETUP:
+ METHOD(Wyvern, mr_setup, bool(Wyvern thismon))
{
+ SELFPARAM();
if(!self.health) self.health = (autocvar_g_monster_wyvern_health);
if(!self.speed) { self.speed = (autocvar_g_monster_wyvern_speed_walk); }
if(!self.speed2) { self.speed2 = (autocvar_g_monster_wyvern_speed_run); }
return true;
}
- case MR_PRECACHE:
+ METHOD(Wyvern, mr_precache, bool(Wyvern thismon))
{
- precache_model("models/monsters/wizard.mdl");
return true;
}
#endif
- }
- return true;
-}
+#endif
+#ifndef ZOMBIE_H
+#define ZOMBIE_H
+
#ifndef MENUQC
-bool M_Zombie(int);
+MODEL(MON_ZOMBIE, "models/monsters/zombie.dpm");
#endif
-REGISTER_MONSTER_SIMPLE(
-/* MON_##id */ ZOMBIE,
-/* spawnflags */ MON_FLAG_MELEE | MON_FLAG_RIDE,
-/* mins,maxs */ '-18 -18 -25', '18 18 47',
-/* model */ "zombie.dpm",
-/* netname */ "zombie",
-/* fullname */ _("Zombie")
-) {
+
+CLASS(Zombie, Monster)
+ ATTRIB(Zombie, spawnflags, int, MON_FLAG_MELEE | MON_FLAG_RIDE);
+ ATTRIB(Zombie, mins, vector, '-18 -18 -25');
+ ATTRIB(Zombie, maxs, vector, '18 18 47');
#ifndef MENUQC
- this.monster_func = M_Zombie;
- this.monster_func(MR_PRECACHE);
+ ATTRIB(Zombie, m_model, Model, MDL_MON_ZOMBIE);
+#endif
+ ATTRIB(Zombie, netname, string, "zombie");
+ ATTRIB(Zombie, monster_name, string, _("Zombie"));
+ENDCLASS(Zombie)
+
+REGISTER_MONSTER(ZOMBIE, NEW(Zombie)) {
+#ifndef MENUQC
+ this.mr_precache(this);
#endif
}
+#endif
+
+#ifdef IMPLEMENTATION
+
#ifdef SVQC
float autocvar_g_monster_zombie_health;
float autocvar_g_monster_zombie_damageforcescale = 0.55;
*/
void M_Zombie_Attack_Leap_Touch()
-{
+{SELFPARAM();
if (self.health <= 0)
return;
}
void M_Zombie_Defend_Block_End()
-{
+{SELFPARAM();
if(self.health <= 0)
return;
}
float M_Zombie_Defend_Block()
-{
+{SELFPARAM();
self.armorvalue = 0.9;
self.state = MONSTER_ATTACK_MELEE; // freeze monster
self.attack_finished_single = time + 2.1;
return true;
}
-float M_Zombie_Attack(float attack_type)
-{
+float M_Zombie_Attack(float attack_type, entity targ)
+{SELFPARAM();
switch(attack_type)
{
case MONSTER_ATTACK_MELEE:
return false;
}
-void spawnfunc_monster_zombie() { Monster_Spawn(MON_ZOMBIE.monsterid); }
+spawnfunc(monster_zombie) { Monster_Spawn(MON_ZOMBIE.monsterid); }
#endif // SVQC
-bool M_Zombie(int req)
-{
- switch(req)
- {
#ifdef SVQC
- case MR_THINK:
+ METHOD(Zombie, mr_think, bool(Zombie thismon))
{
+ SELFPARAM();
if(time >= self.spawn_time)
self.damageforcescale = autocvar_g_monster_zombie_damageforcescale;
return true;
}
- case MR_PAIN:
+ METHOD(Zombie, mr_pain, bool(Zombie thismon))
{
+ SELFPARAM();
self.pain_finished = time + 0.34;
setanim(self, ((random() > 0.5) ? self.anim_pain1 : self.anim_pain2), true, true, false);
return true;
}
- case MR_DEATH:
+ METHOD(Zombie, mr_death, bool(Zombie thismon))
{
+ SELFPARAM();
self.armorvalue = autocvar_g_monsters_armor_blockpercent;
setanim(self, ((random() > 0.5) ? self.anim_die1 : self.anim_die2), false, true, true);
}
#endif
#ifndef MENUQC
- case MR_ANIM:
+ METHOD(Zombie, mr_anim, bool(Zombie thismon))
{
+ SELFPARAM();
vector none = '0 0 0';
self.anim_die1 = animfixfps(self, '9 1 0.5', none); // 2 seconds
self.anim_die2 = animfixfps(self, '12 1 0.5', none); // 2 seconds
}
#endif
#ifdef SVQC
- case MR_SETUP:
+ METHOD(Zombie, mr_setup, bool(Zombie thismon))
{
if(!self.health) self.health = (autocvar_g_monster_zombie_health);
if(!self.speed) { self.speed = (autocvar_g_monster_zombie_speed_walk); }
return true;
}
- case MR_PRECACHE:
+ METHOD(Zombie, mr_precache, bool(Zombie thismon))
{
- precache_model("models/monsters/zombie.dpm");
return true;
}
#endif
- }
- return true;
-}
+#endif
#include "../../server/defs.qh"
#endif
entity spawnmonster (string monster, float monster_id, entity spawnedby, entity own, vector orig, float respwn, float invincible, float moveflag)
-{
+{SELFPARAM();
float i;
entity e = spawn();
e.angles_y = spawnedby.angles_y;
}
-
+
// Monster_Spawn checks if monster is valid
- entity oldself = self;
- self = e;
- Monster_Spawn(monster_id);
- self = oldself;
+ WITH(entity, self, e, Monster_Spawn(monster_id));
return e;
}
#endif
void monsters_setstatus()
-{
+{SELFPARAM();
self.stat_monsters_total = monsters_total;
self.stat_monsters_killed = monsters_killed;
}
void monster_dropitem()
-{
+{SELFPARAM();
if(!self.candrop || !self.monster_loot)
return;
vector org = self.origin + ((self.mins + self.maxs) * 0.5);
- entity e = spawn(), oldself = self;
+ entity e = spawn();
+ e.spawnfunc_checked = true;
e.monster_loot = self.monster_loot;
if(e && e.monster_loot)
{
- self = e;
+ setself(e);
e.noalign = true;
- e.monster_loot();
+ e.monster_loot(e);
e.gravity = 1;
e.movetype = MOVETYPE_TOSS;
e.reset = SUB_Remove;
e.item_spawnshieldtime = time + 0.7;
e.classname = "droppedweapon"; // use weapon handling to remove it on touch
SUB_SetFade(e, time + autocvar_g_monsters_drop_time, 1);
- self = oldself;
+ setself(this);
}
}
void monster_makevectors(entity e)
-{
+{SELFPARAM();
if(IS_MONSTER(self))
{
vector v;
// ===============
bool Monster_ValidTarget(entity mon, entity player)
-{
+{SELFPARAM();
// ensure we're not checking nonexistent monster/target
if(!mon || !player) { return false; }
makevectors (mon.angles);
dot = normalize (player.origin - mon.origin) * v_forward;
- if(dot <= 0.3) { return false; }
+ if(dot <= autocvar_g_monsters_target_infront_range) { return false; }
}
return true; // this target is valid!
void monster_changeteam(entity ent, float newteam)
{
if(!teamplay) { return; }
-
+
ent.team = newteam;
ent.monster_attack = true; // new team, activate attacking
monster_setupcolors(ent);
-
+
if(ent.sprite)
{
WaypointSprite_UpdateTeamRadar(ent.sprite, RADARICON_DANGER, ((newteam) ? Team_ColorRGB(newteam) : '1 0 0'));
}
void Monster_Delay_Action()
-{
+{SELFPARAM();
entity oldself = self;
- self = self.owner;
+ setself(self.owner);
if(Monster_ValidTarget(self, self.enemy)) { oldself.use(); }
if(oldself.cnt > 0)
}
void Monster_Delay(float repeat_count, float repeat_defer, float defer_amnt, void() func)
-{
+{SELFPARAM();
// deferred attacking, checks if monster is still alive and target is still valid before attacking
entity e = spawn();
}
void Monster_Sounds_Precache()
-{
- string m = (get_monsterinfo(self.monsterid)).model;
+{SELFPARAM();
+ string m = (get_monsterinfo(self.monsterid)).m_model.model_str();
float globhandle, n, i;
string f;
}
void Monster_Sounds_Clear()
-{
+{SELFPARAM();
#define _MSOUND(m) if(self.monstersound_##m) { strunzone(self.monstersound_##m); self.monstersound_##m = string_null; }
ALLMONSTERSOUNDS
#undef _MSOUND
}
bool Monster_Sounds_Load(string f, int first)
-{
+{SELFPARAM();
float fh;
string s;
var .string field;
.int skin_for_monstersound;
void Monster_Sounds_Update()
-{
+{SELFPARAM();
if(self.skin == self.skin_for_monstersound) { return; }
self.skin_for_monstersound = self.skin;
}
void Monster_Sound(.string samplefield, float sound_delay, float delaytoo, float chan)
-{
+{SELFPARAM();
if(!autocvar_g_monsters_sounds) { return; }
if(delaytoo)
// =======================
float Monster_Attack_Melee(entity targ, float damg, vector anim, float er, float animtime, int deathtype, float dostop)
-{
+{SELFPARAM();
if(dostop && (self.flags & FL_MONSTER)) { self.state = MONSTER_ATTACK_MELEE; }
setanim(self, anim, false, true, false);
}
float Monster_Attack_Leap_Check(vector vel)
-{
+{SELFPARAM();
if(self.state && (self.flags & FL_MONSTER))
return false; // already attacking
if(!(self.flags & FL_ONGROUND))
}
bool Monster_Attack_Leap(vector anm, void() touchfunc, vector vel, float animtime)
-{
+{SELFPARAM();
if(!Monster_Attack_Leap_Check(vel))
return false;
if(targ_vlen <= e.attack_range)
{
- float attack_success = e.monster_attackfunc(MONSTER_ATTACK_MELEE);
+ float attack_success = e.monster_attackfunc(MONSTER_ATTACK_MELEE, targ);
if(attack_success == 1)
Monster_Sound(monstersound_melee, 0, false, CH_VOICE);
else if(attack_success > 0)
if(targ_vlen > e.attack_range)
{
- float attack_success = e.monster_attackfunc(MONSTER_ATTACK_RANGED);
+ float attack_success = e.monster_attackfunc(MONSTER_ATTACK_RANGED, targ);
if(attack_success == 1)
Monster_Sound(monstersound_melee, 0, false, CH_VOICE);
else if(attack_success > 0)
// ======================
void Monster_UpdateModel()
-{
+{SELFPARAM();
// assume some defaults
/*self.anim_idle = animfixfps(self, '0 1 0.01', '0 0 0');
self.anim_walk = animfixfps(self, '1 1 0.01', '0 0 0');
self.anim_die2 = animfixfps(self, '9 1 0.01', '0 0 0');*/
// then get the real values
- MON_ACTION(self.monsterid, MR_ANIM);
+ Monster mon = get_monsterinfo(self.monsterid);
+ mon.mr_anim(mon);
}
void Monster_Touch()
-{
+{SELFPARAM();
if(other == world) { return; }
if(other.monster_attack)
}
void Monster_Miniboss_Check()
-{
+{SELFPARAM();
if(MUTATOR_CALLHOOK(MonsterCheckBossFlag))
return;
}
bool Monster_Respawn_Check()
-{
+{SELFPARAM();
if(self.deadflag == DEAD_DEAD) // don't call when monster isn't dead
if(MUTATOR_CALLHOOK(MonsterRespawn, self))
return true; // enabled by a mutator
return true;
}
-void Monster_Respawn() { Monster_Spawn(self.monsterid); }
+void Monster_Respawn() { SELFPARAM(); Monster_Spawn(self.monsterid); }
void Monster_Dead_Fade()
-{
+{SELFPARAM();
if(Monster_Respawn_Check())
{
self.spawnflags |= MONSTERFLAG_RESPAWNED;
setorigin(self, self.pos1);
self.angles = self.pos2;
self.health = self.max_health;
- setmodel(self, "null");
+ setmodel(self, MDL_Null);
}
else
{
}
void Monster_Use()
-{
+{SELFPARAM();
if(Monster_ValidTarget(self, activator)) { self.enemy = activator; }
}
vector Monster_Move_Target(entity targ)
-{
+{SELFPARAM();
// enemy is always preferred target
if(self.enemy)
{
}
void Monster_CalculateVelocity(entity mon, vector to, vector from, float turnrate, float movespeed)
-{
+{SELFPARAM();
float current_distance = vlen((('1 0 0' * to.x) + ('0 1 0' * to.y)) - (('1 0 0' * from.x) + ('0 1 0' * from.y))); // for the sake of this check, exclude Z axis
float initial_height = 0; //min(50, (targ_distance * tanh(20)));
float current_height = (initial_height * min(1, (self.pass_distance) ? (current_distance / self.pass_distance) : current_distance));
}
void Monster_Move(float runspeed, float walkspeed, float stpspeed)
-{
+{SELFPARAM();
if(self.target2) { self.goalentity = find(world, targetname, self.target2); }
entity targ;
self.moveto = WarpZone_RefSys_TransformOrigin(self.enemy, self, (0.5 * (self.enemy.absmin + self.enemy.absmax)));
self.monster_moveto = '0 0 0';
self.monster_face = '0 0 0';
-
+
self.pass_distance = vlen((('1 0 0' * self.enemy.origin_x) + ('0 1 0' * self.enemy.origin_y)) - (('1 0 0' * self.origin_x) + ('0 1 0' * self.origin_y)));
Monster_Sound(monstersound_sight, 0, false, CH_VOICE);
}
}
void Monster_Dead_Think()
-{
+{SELFPARAM();
self.nextthink = time + self.ticrate;
if(self.monster_lifetime != 0)
}
void Monster_Appear()
-{
+{SELFPARAM();
self.enemy = activator;
self.spawnflags &= ~MONSTERFLAG_APPEAR; // otherwise, we get an endless loop
Monster_Spawn(self.monsterid);
}
void Monster_Reset()
-{
+{SELFPARAM();
setorigin(self, self.pos1);
self.angles = self.pos2;
}
void Monster_Dead_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
self.health -= damage;
Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);
}
void Monster_Dead(entity attacker, float gibbed)
-{
+{SELFPARAM();
self.think = Monster_Dead_Think;
self.nextthink = time;
self.monster_lifetime = time + 5;
if(!((self.flags & FL_FLY) || (self.flags & FL_SWIM)))
self.velocity = '0 0 0';
- CSQCModel_UnlinkEntity();
+ CSQCModel_UnlinkEntity(self);
- MON_ACTION(self.monsterid, MR_DEATH);
+ Monster mon = get_monsterinfo(self.monsterid);
+ mon.mr_death(mon);
if(self.candrop && self.weapon)
W_ThrowNewWeapon(self, self.weapon, 0, self.origin, randomvec() * 150 + '0 0 325');
}
void Monster_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
- if((self.spawnflags & MONSTERFLAG_INVINCIBLE) && deathtype != DEATH_KILL)
+{SELFPARAM();
+ if((self.spawnflags & MONSTERFLAG_INVINCIBLE) && deathtype != DEATH_KILL && !ITEM_DAMAGE_NEEDKILL(deathtype))
return;
if(self.frozen && deathtype != DEATH_KILL && deathtype != DEATH_NADE_ICE_FREEZE)
damage_take = take;
frag_attacker = attacker;
frag_deathtype = deathtype;
- MON_ACTION(self.monsterid, MR_PAIN);
+ Monster mon = get_monsterinfo(self.monsterid);
+ mon.mr_pain(mon);
take = damage_take;
if(take)
self.dmg_time = time;
if(sound_allowed(MSG_BROADCAST, attacker) && deathtype != DEATH_DROWN)
- spamsound (self, CH_PAIN, "misc/bodyimpact1.wav", VOL_BASE, ATTEN_NORM); // FIXME: PLACEHOLDER
+ spamsound (self, CH_PAIN, SND(BODYIMPACT1), VOL_BASE, ATTEN_NORM); // FIXME: PLACEHOLDER
self.velocity += force * self.damageforcescale;
// don't check for enemies, just keep walking in a straight line
void Monster_Move_2D(float mspeed, float allow_jumpoff)
-{
+{SELFPARAM();
if(gameover || (round_handler_IsActive() && !round_handler_IsRoundStarted()) || self.draggedby != world || time < game_starttime || (autocvar_g_campaign && !campaign_bots_may_start) || time < self.spawn_time)
{
mspeed = 0;
float reverse = FALSE;
vector a, b;
-
+
makevectors(self.angles);
a = self.origin + '0 0 16';
b = self.origin + '0 0 16' + v_forward * 32;
-
+
traceline(a, b, MOVE_NORMAL, self);
-
+
if(trace_fraction != 1.0)
{
reverse = TRUE;
-
+
if(trace_ent)
if(IS_PLAYER(trace_ent) && !(trace_ent.items & IT_STRENGTH))
reverse = FALSE;
}
-
+
// TODO: fix this... tracing is broken if the floor is thin
/*
if(!allow_jumpoff)
if(trace_fraction == 1.0)
reverse = TRUE;
} */
-
+
if(reverse)
{
self.angles_y = anglemods(self.angles_y - 180);
makevectors(self.angles);
}
-
+
movelib_move_simple_gravity(v_forward, mspeed, 1);
if(time > self.pain_finished)
}
void Monster_Anim()
-{
+{SELFPARAM();
int deadbits = (self.anim_state & (ANIMSTATE_DEAD1 | ANIMSTATE_DEAD2));
if(self.deadflag)
{
}
void Monster_Think()
-{
+{SELFPARAM();
self.think = Monster_Think;
self.nextthink = self.ticrate;
return;
}
- if(MON_ACTION(self.monsterid, MR_THINK))
+ Monster mon = get_monsterinfo(self.monsterid);
+ if(mon.mr_think(mon))
Monster_Move(self.speed2, self.speed, self.stopspeed);
Monster_Anim();
- CSQCMODEL_AUTOUPDATE();
+ CSQCMODEL_AUTOUPDATE(self);
}
float Monster_Spawn_Setup()
-{
- MON_ACTION(self.monsterid, MR_SETUP);
+{SELFPARAM();
+ Monster mon = get_monsterinfo(self.monsterid);
+ mon.mr_setup(mon);
// ensure some basic needs are met
if(!self.health) { self.health = 100; }
}
bool Monster_Spawn(int mon_id)
-{
+{SELFPARAM();
// setup the basic required properties for a monster
entity mon = get_monsterinfo(mon_id);
if(!mon.monsterid) { return false; } // invalid monster
if(!autocvar_g_monsters) { Monster_Remove(self); return false; }
- self.mdl = mon.model;
if(Monster_Appear_Check(self, mon_id)) { return true; } // return true so the monster isn't removed
if(!self.monster_skill)
if(!(self.spawnflags & MONSTERFLAG_RESPAWNED)) // don't count re-spawning monsters either
monsters_total += 1;
- setmodel(self, self.mdl);
+ setmodel(self, mon.m_model);
self.flags = FL_MONSTER;
self.classname = "monster";
self.takedamage = DAMAGE_AIM;
self.monster_moveto = '0 0 0';
self.monster_face = '0 0 0';
self.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_BOTCLIP | DPCONTENTS_MONSTERCLIP;
-
+
if(!self.scale) { self.scale = 1; }
if(autocvar_g_monsters_edit) { self.grab = 1; }
if(autocvar_g_fullbrightplayers) { self.effects |= EF_FULLBRIGHT; }
if(!(self.spawnflags & MONSTERFLAG_RESPAWNED))
monster_setupcolors(self);
- CSQCMODEL_AUTOINIT();
+ CSQCMODEL_AUTOINIT(self);
return true;
}
void _Movetype_Physics_Follow() // SV_Physics_Follow
-{
+{SELFPARAM();
entity e = self.move_aiment; // TODO: networking?
// LordHavoc: implemented rotation on MOVETYPE_FOLLOW objects
vector planes[MAX_CLIP_PLANES];
int _Movetype_FlyMove(float dt, bool applygravity, vector stepnormal, float stepheight) // SV_FlyMove
-{
+{SELFPARAM();
int blocked = 0, bumpcount;
int i, j, numplanes = 0;
float time_left = dt, grav = 0;
vector push;
- vector primal_velocity, original_velocity, new_velocity = '0 0 0', restore_velocity;
+ vector primal_velocity, original_velocity, restore_velocity;
- for(i = 0; i <= MAX_CLIP_PLANES; ++i)
+ for(i = 0; i < MAX_CLIP_PLANES; ++i)
planes[i] = '0 0 0';
- grav = 0;
-
- restore_velocity = self.move_velocity;
-
if(applygravity)
{
self.move_didgravity = 1;
}
}
- original_velocity = primal_velocity = self.move_velocity;
+ original_velocity = primal_velocity = restore_velocity = self.move_velocity;
for(bumpcount = 0;bumpcount < MAX_CLIP_PLANES;bumpcount++)
{
- if(!self.move_velocity_x && !self.move_velocity_y && !self.move_velocity_z)
+ if(self.move_velocity == '0 0 0')
break;
push = self.move_velocity * time_left;
- if(!_Movetype_PushEntity(push, false))
+ vector prev_origin = self.move_origin;
+ _Movetype_PushEntity(push, true);
+ if(trace_startsolid && self.move_origin != prev_origin)
{
// we got teleported by a touch function
// let's abort the move
if(trace_fraction == 1)
break;
+
+ float my_trace_fraction = trace_fraction;
+ vector my_trace_plane_normal = trace_plane_normal;
+
if(trace_plane_normal_z)
{
if(trace_plane_normal_z > 0.7)
else if(stepheight)
{
// step - handle it immediately
- vector org;
- vector steppush;
- //Con_Printf("step %f %f %f : ", self.move_origin_x, PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
- steppush = '0 0 1' * stepheight;
- org = self.move_origin;
- if(!_Movetype_PushEntity(steppush, false))
+ vector org = self.move_origin;
+ vector steppush = '0 0 1' * stepheight;
+
+ _Movetype_PushEntity(steppush, true);
+ if(trace_startsolid && self.move_origin != org)
{
blocked |= 8;
break;
}
- //Con_Printf("%f %f %f : ", self.move_origin_x, PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
- if(!_Movetype_PushEntity(push, false))
+ _Movetype_PushEntity(push, true);
+ if(trace_startsolid && self.move_origin != org)
{
blocked |= 8;
break;
}
float trace2_fraction = trace_fraction;
- //Con_Printf("%f %f %f : ", self.move_origin_x, PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
steppush = '0 0 1' * (org_z - self.move_origin_z);
- if(!_Movetype_PushEntity(steppush, false))
+ _Movetype_PushEntity(steppush, true);
+ if(trace_startsolid && self.move_origin != org)
{
blocked |= 8;
break;
}
- //Con_Printf("%f %f %f : ", self.move_origin_x, PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
+
// accept the new position if it made some progress...
if(fabs(self.move_origin_x - org_x) >= 0.03125 || fabs(self.move_origin_y - org_y) >= 0.03125)
{
- //Con_Printf("accepted (delta %f %f %f)\n", self.move_origin_x - org_x, PRVM_serveredictvector(ent, origin)[1] - org[1], PRVM_serveredictvector(ent, origin)[2] - org[2]);
trace_endpos = self.move_origin;
time_left *= 1 - trace2_fraction;
numplanes = 0;
continue;
}
else
- {
- //Con_Printf("REJECTED (delta %f %f %f)\n", self.move_origin_x - org_x, PRVM_serveredictvector(ent, origin)[1] - org[1], PRVM_serveredictvector(ent, origin)[2] - org[2]);
self.move_origin = org;
- }
}
else
{
if(stepnormal)
stepnormal = trace_plane_normal;
}
- if(trace_fraction >= 0.001)
+
+ if(my_trace_fraction >= 0.001)
{
// actually covered some distance
original_velocity = self.move_velocity;
numplanes = 0;
}
- time_left *= 1 - trace_fraction;
+ time_left *= 1 - my_trace_fraction;
// clipped to another plane
if(numplanes >= MAX_CLIP_PLANES)
break;
}
- planes[numplanes] = trace_plane_normal;
+ planes[numplanes] = my_trace_plane_normal;
numplanes++;
// modify original_velocity so it parallels all of the clip planes
+ vector new_velocity = '0 0 0';
for (i = 0;i < numplanes;i++)
{
new_velocity = _Movetype_ClipVelocity(original_velocity, planes[i], 1);
blocked = 7;
break;
}
- vector dir;
- dir.x = planes[0].y * planes[1].z - planes[0].z * planes[1].y;
- dir.y = planes[0].z * planes[1].x - planes[0].x * planes[1].z;
- dir.z = planes[0].x * planes[1].y - planes[0].y * planes[1].x;
+ vector dir = cross(planes[0], planes[1]);
// LordHavoc: thanks to taniwha of QuakeForge for pointing out this fix for slowed falling in corners
float ilength = sqrt((dir * dir));
if(ilength)
}
void _Movetype_Impact(entity oth) // SV_Impact
-{
- entity oldself = self;
+{SELFPARAM();
entity oldother = other;
if(self.move_touch)
if(oth.move_touch)
{
other = self;
- self = oth;
- self.move_touch();
+ WITH(entity, self, oth, oth.move_touch());
- self = oldself;
other = oldother;
}
}
void _Movetype_LinkEdict_TouchAreaGrid() // SV_LinkEdict_TouchAreaGrid
-{
- entity oldself = self;
+{SELFPARAM();
entity oldother = other;
for (entity e = findradius(0.5 * (self.absmin + self.absmax), 0.5 * vlen(self.absmax - self.absmin)); e; e = e.chain)
{
- if(e.move_touch && boxesoverlap(e.absmin, e.absmax, oldself.absmin, oldself.absmax))
+ if(e.move_touch && boxesoverlap(e.absmin, e.absmax, this.absmin, this.absmax))
{
- self = e;
- other = oldself;
+ setself(e);
+ other = this;
trace_allsolid = false;
trace_startsolid = false;
trace_endpos = e.origin;
trace_plane_normal = '0 0 1';
trace_plane_dist = 0;
- trace_ent = oldself;
+ trace_ent = this;
e.move_touch();
}
}
other = oldother;
- self = oldself;
+ setself(this);
}
void _Movetype_LinkEdict(bool touch_triggers) // SV_LinkEdict
-{
+{SELFPARAM();
vector mi, ma;
if(self.solid == SOLID_BSP)
{
}
bool _Movetype_TestEntityPosition(vector ofs) // SV_TestEntityPosition
-{
+{SELFPARAM();
// vector org = self.move_origin + ofs;
int cont = self.dphitcontentsmask;
}
bool _Movetype_UnstickEntity() // SV_UnstickEntity
-{
+{SELFPARAM();
if(!_Movetype_TestEntityPosition('0 0 0')) return true;
if(!_Movetype_TestEntityPosition('-1 0 0')) goto success;
if(!_Movetype_TestEntityPosition('1 0 0')) goto success;
}
void _Movetype_PushEntityTrace(vector push)
-{
+{SELFPARAM();
vector end = self.move_origin + push;
int type;
if(self.move_nomonsters)
}
float _Movetype_PushEntity(vector push, bool failonstartsolid) // SV_PushEntity
-{
+{SELFPARAM();
_Movetype_PushEntityTrace(push);
if(trace_startsolid && failonstartsolid)
}
void _Movetype_Physics_Frame(float movedt)
-{
+{SELFPARAM();
self.move_didgravity = -1;
switch (self.move_movetype)
{
}
void Movetype_Physics_NoMatchServer() // optimized
-{
+{SELFPARAM();
float movedt = time - self.move_time;
self.move_time = time;
}
void Movetype_Physics_MatchTicrate(float tr, bool sloppy) // SV_Physics_Entity
-{
+{SELFPARAM();
if(tr <= 0)
{
Movetype_Physics_NoMatchServer();
void _Movetype_PushMove(float dt) // SV_PushMove
-{
+{SELFPARAM();
if (self.move_velocity == '0 0 0' && self.move_avelocity == '0 0 0')
{
self.move_ltime += dt;
if (check.move_movetype == 32) // MOVETYPE_PHYSICS
{
check.move_origin = check.move_origin + move;
- entity oldself = self;
- self = check;
- _Movetype_LinkEdict(true);
- self = oldself;
+ WITH(entity, self, check, _Movetype_LinkEdict(true));
continue;
}
// try moving the contacted entity
self.solid = SOLID_NOT;
- entity oldself = self;
- self = check;
- if (!_Movetype_PushEntity(move, true))
+ bool flag;
+ WITH(entity, self, check, {
+ flag = _Movetype_PushEntity(move, true);
+ });
+ if (!flag)
{
- self = oldself;
// entity "check" got teleported
check.move_angles_y += trace_fraction * moveangle.y;
self.solid = savesolid;
continue; // pushed enough
}
- self = oldself;
// FIXME: turn players specially
check.move_angles_y += trace_fraction * moveangle.y;
self.solid = savesolid;
}
void _Movetype_Physics_Pusher(float dt) // SV_Physics_Pusher
-{
+{SELFPARAM();
float oldltime = self.move_ltime;
float thinktime = self.move_nextthink;
float movetime;
void _Movetype_Physics_Step(float dt) // SV_Physics_Step
-{
+{SELFPARAM();
if(self.move_flags & FL_ONGROUND)
{
if(self.velocity_z >= (1.0 / 32.0) && UPWARD_VELOCITY_CLEARS_ONGROUND)
#include "../physics.qh"
void _Movetype_Physics_Toss(float dt) // SV_Physics_Toss
-{
+{SELFPARAM();
if (self.move_flags & FL_ONGROUND)
{
if (self.move_velocity.z >= 1 / 32)
void _Movetype_Physics_Walk(float dt) // SV_WalkMove
-{
+{SELFPARAM();
vector stepnormal = '0 0 0';
// if frametime is 0 (due to client sending the same timestamp twice), don't move
// move up
vector upmove = '0 0 1' * PHYS_STEPHEIGHT;
- if (!_Movetype_PushEntity(upmove, true))
+ vector prev_origin = self.move_origin;
+ _Movetype_PushEntity(upmove, true);
+ if(wasfreed(self))
+ return;
+ if(trace_startsolid && self.move_origin != prev_origin)
{
// we got teleported when upstepping... must abort the move
return;
// Con_Printf("step - ");
// extra friction based on view angle
- if (clip & 2 && PHYS_WALLFRICTION)
+ if ((clip & 2) && PHYS_WALLFRICTION)
_Movetype_WallFriction(stepnormal);
}
// don't do the down move if stepdown is disabled, moving upward, not in water, or the move started offground or ended onground
// move down
vector downmove = '0 0 1' * (-PHYS_STEPHEIGHT + start_velocity.z * dt);
- if (!_Movetype_PushEntity(downmove, true))
+ vector prev_origin = self.move_origin;
+ _Movetype_PushEntity(downmove, true);
+ if(wasfreed(self))
+ return;
+
+ if(trace_startsolid && self.move_origin != prev_origin)
{
// we got teleported when downstepping... must abort the move
return;
}
ENDCLASS(Mutator)
-const int MAX_MUTATORS = 15;
+const int MAX_MUTATORS = 30;
Mutator loaded_mutators[MAX_MUTATORS];
bool Mutator_Add(Mutator mut)
bool ret = MUTATORFUNCTION_##id##_hooks(mode); if (ret) return ret; \
} \
bool MUTATOR_##id##_check() { return dependence; } \
- REGISTER(RegisterMutators, MUTATOR, MUTATORS, MUTATORS_COUNT, id, m_id, NEW(Mutator, #id, MUTATORFUNCTION_##id)) \
+ REGISTER(RegisterMutators, MUTATOR, MUTATORS, id, m_id, NEW(Mutator, #id, MUTATORFUNCTION_##id)) \
{ this.mutatorcheck = MUTATOR_##id##_check; } \
[[accumulate]] bool MUTATORFUNCTION_##id(int mode)
[[accumulate]] void RegisterCallbacks() { CALLBACK_##name = NEW(Callback, func); }
#define MUTATOR_HOOKFUNCTION(...) \
- OVERLOAD(MUTATOR_HOOKFUNCTION, __VA_ARGS__)
+ EVAL(OVERLOAD(MUTATOR_HOOKFUNCTION, __VA_ARGS__))
#define MUTATOR_HOOKFUNCTION_1(name) \
_MUTATOR_CALLBACK(name, HOOKFUNCTION_##name) \
bool HOOKFUNCTION_##name()
#define MUTATOR_HOOKFUNCTION_2(mut, cb) \
- MUTATOR_HOOKFUNCTION(mut, cb, CBC_ORDER_ANY)
+ MUTATOR_HOOKFUNCTION_3(mut, cb, CBC_ORDER_ANY)
#define MUTATOR_HOOKFUNCTION_3(mut, cb, order) \
_MUTATOR_CALLBACK(mut##_##cb, mut##_##cb) \
#ifdef SVQC
void SpawnCasing(vector vel, float randomvel, vector ang, vector avel, float randomavel, int casingtype, entity casingowner)
-{
+{SELFPARAM();
vector org = self.origin + self.view_ofs + self.weaponentity.spawnorigin.x * v_forward - self.weaponentity.spawnorigin.y * v_right + self.weaponentity.spawnorigin.z * v_up;
if (!sound_allowed(MSG_BROADCAST, casingowner))
class(Casing) .float cnt;
void Casing_Delete()
-{
+{SELFPARAM();
remove(self);
}
-void Casing_Draw()
+void Casing_Draw(entity this)
{
if (self.move_flags & FL_ONGROUND)
{
}
}
+SOUND(BRASS1, W_Sound("brass1"));
+SOUND(BRASS2, W_Sound("brass2"));
+SOUND(BRASS3, W_Sound("brass3"));
+Sound SND_BRASS_RANDOM() {
+ return Sounds[SND_BRASS1.m_id + floor(prandom() * 3)];
+}
+SOUND(CASINGS1, W_Sound("casings1"));
+SOUND(CASINGS2, W_Sound("casings2"));
+SOUND(CASINGS3, W_Sound("casings3"));
+Sound SND_CASINGS_RANDOM() {
+ return Sounds[SND_CASINGS1.m_id + floor(prandom() * 3)];
+}
+
void Casing_Touch()
-{
+{SELFPARAM();
if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
{
Casing_Delete();
{
if (time >= self.nextthink)
{
- string s;
- int f = floor(prandom() * 3) + 1;
-
+ Sound s;
switch (self.state)
{
case 1:
- s = W_Sound(strcat("casings", itos(f)));
+ s = SND_CASINGS_RANDOM();
break;
default:
- s = W_Sound(strcat("brass", itos(f)));
+ s = SND_BRASS_RANDOM();
break;
}
}
void Casing_Damage(float thisdmg, int hittype, vector org, vector thisforce)
-{
+{SELFPARAM();
if (thisforce.z < 0)
thisforce.z = 0;
self.move_velocity = self.move_velocity + thisforce + '0 0 100';
switch (casing.state)
{
case 1:
- setmodel(casing, "models/casing_shell.mdl");
+ setmodel(casing, MDL_CASING_SHELL);
casing.cnt = time + autocvar_cl_casings_shell_time;
break;
default:
- setmodel(casing, "models/casing_bronze.iqm");
+ setmodel(casing, MDL_CASING_BULLET);
casing.cnt = time + autocvar_cl_casings_bronze_time;
break;
}
RubbleLimit("casing", autocvar_cl_casings_maxcount, Casing_Delete);
}
-STATIC_INIT(Casings)
-{
- precache_model("models/casing_shell.mdl");
- precache_model("models/casing_bronze.iqm");
- precache_sound(W_Sound("brass1"));
- precache_sound(W_Sound("brass2"));
- precache_sound(W_Sound("brass3"));
- precache_sound(W_Sound("casings1"));
- precache_sound(W_Sound("casings2"));
- precache_sound(W_Sound("casings3"));
-}
#endif
ATTRIB(DamageText, m_armordamage, int, 0)
ATTRIB(DamageText, time_prev, float, time)
- void DamageText_draw() {
- entity this = self;
+ void DamageText_draw2d(DamageText this) {
float dt = time - this.time_prev;
this.time_prev = time;
setorigin(this, this.origin + dt * this.velocity);
drawcolorcodedstring2(pos, s, this.m_size * '1 1 0', this.m_color, this.alpha, DRAWFLAG_NORMAL);
}
}
- ATTRIB(DamageText, draw2d, void(), DamageText_draw)
+ ATTRIB(DamageText, draw2d, void(DamageText), DamageText_draw2d)
void DamageText_update(DamageText this, vector _origin, int _health, int _armor) {
this.m_damage = _health;
#endif
#ifdef CSQC
-float ItemsTime_time[MAX_ITEMS];
-float ItemsTime_availableTime[MAX_ITEMS];
+float ItemsTime_time[Items_MAX];
+float ItemsTime_availableTime[Items_MAX];
MUTATOR_HOOKFUNCTION(itemstime, CSQC_Parse_TempEntity) {
if (MUTATOR_RETURNVALUE) return false;
if (!ReadMutatorEquals(mutator_argv_int_0, itemstime)) return false;
#ifdef SVQC
-float it_times[MAX_ITEMS];
+float it_times[Items_MAX];
void Item_ItemsTime_Init()
{
- FOREACH(ITEMS, true, LAMBDA(
+ FOREACH(Items, true, LAMBDA(
it_times[it.m_id] = -1;
));
}
void Item_ItemsTime_ResetTimes()
{
- FOREACH(ITEMS, true, LAMBDA(
+ FOREACH(Items, true, LAMBDA(
it_times[it.m_id] = (it_times[it.m_id] == -1) ? -1 : 0;
));
}
void Item_ItemsTime_ResetTimesForPlayer(entity e)
{
- FOREACH(ITEMS, true, LAMBDA(
+ FOREACH(Items, true, LAMBDA(
IT_Write(e, it.m_id, (it_times[it.m_id] == -1) ? -1 : 0);
));
}
void Item_ItemsTime_SetTimesForPlayer(entity e)
{
- FOREACH(ITEMS, true, LAMBDA(
+ FOREACH(Items, true, LAMBDA(
IT_Write(e, it.m_id, it_times[it.m_id]);
));
}
{
for (entity head = world; (head = nextent(head)); )
{
- if (clienttype(head) != CLIENTTYPE_NOTACLIENT || !(head.weapons & WEPSET_SUPERWEAPONS) || head.classname == "weapon_info")
+ if (clienttype(head) != CLIENTTYPE_NOTACLIENT || !(head.weapons & WEPSET_SUPERWEAPONS) || head.instanceOfWeapon)
continue;
if (e == head)
continue;
return t;
}
-MUTATOR_HOOKFUNCTION(itemstime, reset_map_global) {
+MUTATOR_HOOKFUNCTION(itemstime, reset_map_global)
+{SELFPARAM();
Item_ItemsTime_ResetTimes();
// ALL the times need to be reset before .reset()ing each item
// since Item_Reset schedules respawn of superweapons and powerups
- for (self = world; (self = nextent(self)); )
- if (IS_NOT_A_CLIENT(self))
+ for (entity e = NULL; (e = nextent(e)); )
+ if (IS_NOT_A_CLIENT(e))
{
+ setself(e);
if (self.reset)
Item_ItemsTime_SetTime(self, 0);
}
Item_ItemsTime_SetTimesForAllPlayers();
}
-MUTATOR_HOOKFUNCTION(itemstime, MakePlayerObserver) {
+MUTATOR_HOOKFUNCTION(itemstime, MakePlayerObserver)
+{SELFPARAM();
Item_ItemsTime_SetTimesForPlayer(self);
}
-MUTATOR_HOOKFUNCTION(itemstime, PlayerSpawn) {
+MUTATOR_HOOKFUNCTION(itemstime, PlayerSpawn)
+{SELFPARAM();
if (warmup_stage) return;
Item_ItemsTime_ResetTimesForPlayer(self);
}
HUD_Panel_DrawProgressBar(p_pos, p_size, autocvar_hud_panel_itemstime_progressbar_name, t/autocvar_hud_panel_itemstime_progressbar_maxtime, 0, autocvar_hud_panel_itemstime_iconalign, color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
}
- if (t > 0 && autocvar_hud_panel_itemstime_text)
- drawstring_aspect(numpos, ftos(t), eX * ((ar - 1)/ar) * mySize_x + eY * mySize_y, color, panel_fg_alpha, DRAWFLAG_NORMAL);
- else
- picpos.x = myPos.x + mySize.x / 2 - mySize.y / 2;
+ if(autocvar_hud_panel_itemstime_text)
+ {
+ if(t > 0)
+ drawstring_aspect(numpos, ftos(t), eX * ((ar - 1)/ar) * mySize_x + eY * mySize_y, color, panel_fg_alpha, DRAWFLAG_NORMAL);
+ else if(precache_pic("gfx/hud/default/checkmark")) // COMPAT: check if this image exists, as 0.8.1 clients lack it
+ drawpic_aspect_skin(numpos, "checkmark", eX * (ar - 1) * mySize_y + eY * mySize_y, '1 1 1', panel_fg_alpha * picalpha, DRAWFLAG_NORMAL);
+ else // legacy code, if the image is missing just center the icon
+ picpos.x = myPos.x + mySize.x / 2 - mySize.y / 2;
+ }
if (item_availableTime)
drawpic_aspect_skin_expanding(picpos, item.m_icon, '1 1 0' * mySize_y, '1 1 1', panel_fg_alpha * picalpha, DRAWFLAG_NORMAL, item_availableTime);
drawpic_aspect_skin(picpos, item.m_icon, '1 1 0' * mySize_y, '1 1 1', panel_fg_alpha * picalpha, DRAWFLAG_NORMAL);
int count = 0;
if (autocvar_hud_panel_itemstime_hidespawned == 1)
- FOREACH(ITEMS, Item_ItemsTime_Allow(it, '0 0 0'), LAMBDA(
- count += (ItemsTime_time[i] > time || -ItemsTime_time[i] > time);
+ FOREACH(Items, Item_ItemsTime_Allow(it, '0 0 0'), LAMBDA(
+ count += (ItemsTime_time[it.m_id] > time || -ItemsTime_time[it.m_id] > time);
));
else if (autocvar_hud_panel_itemstime_hidespawned == 2)
- FOREACH(ITEMS, Item_ItemsTime_Allow(it, '0 0 0'), LAMBDA(
- count += (ItemsTime_time[i] > time);
+ FOREACH(Items, Item_ItemsTime_Allow(it, '0 0 0'), LAMBDA(
+ count += (ItemsTime_time[it.m_id] > time);
));
else
- FOREACH(ITEMS, Item_ItemsTime_Allow(it, '0 0 0'), LAMBDA(
- count += (ItemsTime_time[i] != -1);
+ FOREACH(Items, Item_ItemsTime_Allow(it, '0 0 0'), LAMBDA(
+ count += (ItemsTime_time[it.m_id] != -1);
));
if (count == 0)
return;
float row = 0, column = 0;
bool item_available;
- FOREACH(ITEMS, Item_ItemsTime_Allow(it, '0 0 0') && ItemsTime_time[i] != -1, LAMBDA(
- float item_time = ItemsTime_time[i];
+ FOREACH(Items, Item_ItemsTime_Allow(it, '0 0 0') && ItemsTime_time[it.m_id] != -1, LAMBDA(
+ float item_time = ItemsTime_time[it.m_id];
if (item_time < -1)
{
item_available = true;
else
item_available = (item_time <= time);
- if (ItemsTime_time[i] >= 0)
+ if (ItemsTime_time[it.m_id] >= 0)
{
- if (time <= ItemsTime_time[i])
- ItemsTime_availableTime[i] = 0;
- else if (ItemsTime_availableTime[i] == 0)
- ItemsTime_availableTime[i] = time;
+ if (time <= ItemsTime_time[it.m_id])
+ ItemsTime_availableTime[it.m_id] = 0;
+ else if (ItemsTime_availableTime[it.m_id] == 0)
+ ItemsTime_availableTime[it.m_id] = time;
}
- else if (ItemsTime_availableTime[i] == 0)
- ItemsTime_availableTime[i] = time;
+ else if (ItemsTime_availableTime[it.m_id] == 0)
+ ItemsTime_availableTime[it.m_id] = time;
- float f = (time - ItemsTime_availableTime[i]) * 2;
+ float f = (time - ItemsTime_availableTime[it.m_id]) * 2;
f = (f > 1) ? 0 : bound(0, f, 1);
if (autocvar_hud_panel_itemstime_hidespawned == 1)
- if (!(ItemsTime_time[i] > time || -ItemsTime_time[i] > time))
+ if (!(ItemsTime_time[it.m_id] > time || -ItemsTime_time[it.m_id] > time))
continue;
if (autocvar_hud_panel_itemstime_hidespawned == 2)
- if (!(ItemsTime_time[i] > time))
+ if (!(ItemsTime_time[it.m_id] > time))
continue;
DrawItemsTimeItem(pos + eX * column * (itemstime_size.x + offset.x) + eY * row * (itemstime_size.y + offset.y), itemstime_size, ar, it, item_time, item_available, f);
/** If you register a new waypoint, make sure to add it to this list */
-REGISTER_WAYPOINT(, "", '0 0 0', 1);
-#define WP_Null WP_
REGISTER_WAYPOINT(Waypoint, _("Waypoint"), '0 1 1', 1);
REGISTER_WAYPOINT(Helpme, _("Help me!"), '1 0.5 0', 1);
#include "waypointsprites.qh"
-void RegisterWaypoints();
-const int MAX_WAYPOINTS = 240;
-entity WAYPOINTS[MAX_WAYPOINTS], WAYPOINTS_first, WAYPOINTS_last;
-int WAYPOINT_COUNT;
-/** If you register a new waypoint, make sure to add it to all.inc */
-#define REGISTER_WAYPOINT_(id, init) REGISTER(RegisterWaypoints, WP, WAYPOINTS, WAYPOINT_COUNT, id, m_id, init)
+REGISTRY(Waypoints, BIT(6))
REGISTER_REGISTRY(RegisterWaypoints)
+/** If you register a new waypoint, make sure to add it to all.inc */
+#define REGISTER_WAYPOINT_(id, init) REGISTER(RegisterWaypoints, WP, Waypoints, id, m_id, init)
CLASS(Waypoint, Object)
ATTRIB(Waypoint, m_id, int, 0)
#define REGISTER_WAYPOINT(id, text, color, blink) REGISTER_WAYPOINT_(id, NEW(Waypoint, #id, text, color, blink))
+REGISTRY(RadarIcons, BITS(7))
+REGISTER_REGISTRY(RegisterRadarIcons)
+.int m_radaricon;
+#define REGISTER_RADARICON(id, num) REGISTER(RegisterRadarIcons, RADARICON, RadarIcons, id, m_id, new(RadarIcon)) { this.m_radaricon = num; this.netname = #id; }
+
+REGISTER_WAYPOINT(Null, "", '0 0 0', 1);
+
+REGISTER_RADARICON(NONE, 0);
+REGISTER_RADARICON(FLAG, 1);
+REGISTER_RADARICON(FLAGCARRIER, 1);
+
+// TODO make these 3 and 4, and make images for them
+REGISTER_RADARICON(HERE, 1);
+REGISTER_RADARICON(DANGER, 1);
+
+REGISTER_RADARICON(WAYPOINT, 1);
+REGISTER_RADARICON(HELPME, 1);
+REGISTER_RADARICON(CONTROLPOINT, 1);
+REGISTER_RADARICON(GENERATOR, 1);
+REGISTER_RADARICON(OBJECTIVE, 1);
+REGISTER_RADARICON(DOMPOINT, 1);
+REGISTER_RADARICON(TAGGED, 1);
+
+REGISTER_RADARICON(Buff, 1);
+REGISTER_RADARICON(Item, 1);
+REGISTER_RADARICON(Vehicle, 1);
+REGISTER_RADARICON(Weapon, 1);
+
#include "all.inc"
#endif
#ifdef SVQC
/** flags origin [team displayrule] [spritename] [spritename2] [spritename3] [lifetime maxdistance hideable] */
-float WaypointSprite_SendEntity(entity to, float sendflags)
+bool WaypointSprite_SendEntity(entity this, entity to, float sendflags)
{
WriteMutator(MSG_ENTITY, waypointsprites);
}
void Ent_RemoveWaypointSprite()
-{
+{SELFPARAM();
if (self.netname) strunzone(self.netname);
if (self.netname2) strunzone(self.netname2);
if (self.netname3) strunzone(self.netname3);
/** flags origin [team displayrule] [spritename] [spritename2] [spritename3] [lifetime maxdistance hideable] */
void Ent_WaypointSprite()
-{
+{SELFPARAM();
int sendflags = ReadByte();
self.wp_extra = ReadByte();
if (sendflags & 32)
{
int f = ReadByte();
- self.teamradar_icon = (f & 0x7F);
- if (f & 0x80)
+ self.teamradar_icon = f & BITS(7);
+ if (f & BIT(7))
{
self.(teamradar_times[self.teamradar_time_index]) = time;
self.teamradar_time_index = (self.teamradar_time_index + 1) % MAX_TEAMRADAR_TIMES;
#ifdef CSQC
float spritelookupblinkvalue(string s)
-{
+{SELFPARAM();
if (s == WP_Weapon.netname) {
if (get_weaponinfo(self.wp_extra).spawnflags & WEP_FLAG_SUPERWEAPON)
return 2;
}
- if (s == WP_Item.netname) return ITEMS[self.wp_extra].m_waypointblink;
+ if (s == WP_Item.netname) return Items[self.wp_extra].m_waypointblink;
- switch (s)
- {
- case "item-invis": return 2;
- case "item-extralife": return 2;
- case "item-speed": return 2;
- default: return 1;
- }
+ return 1;
}
-vector spritelookupcolor(string s, vector def)
+vector spritelookupcolor(entity this, string s, vector def)
{
- if (s == WP_Weapon.netname) return get_weaponinfo(self.wp_extra).wpcolor;
- if (s == WP_Item.netname) return ITEMS[self.wp_extra].m_color;
- if (s == WP_Buff.netname) return BUFFS[self.wp_extra].m_color;
+ if (s == WP_Weapon.netname || s == RADARICON_Weapon.netname) return get_weaponinfo(this.wp_extra).wpcolor;
+ if (s == WP_Item.netname || s == RADARICON_Item.netname) return Items[this.wp_extra].m_color;
+ if (s == WP_Buff.netname || s == RADARICON_Buff.netname) return Buffs[this.wp_extra].m_color;
return def;
}
string spritelookuptext(string s)
-{
+{SELFPARAM();
if (s == WP_RaceStartFinish.netname) return (race_checkpointtime || race_mycheckpointtime) ? _("Finish") : _("Start");
if (s == WP_Weapon.netname) return get_weaponinfo(self.wp_extra).message;
- if (s == WP_Item.netname) return ITEMS[self.wp_extra].m_waypoint;
- if (s == WP_Buff.netname) return BUFFS[self.wp_extra].m_prettyName;
+ if (s == WP_Item.netname) return Items[self.wp_extra].m_waypoint;
+ if (s == WP_Buff.netname) return Buffs[self.wp_extra].m_prettyName;
if (s == WP_Monster.netname) return get_monsterinfo(self.wp_extra).monster_name;
// need to loop, as our netname could be one of three
- FOREACH(WAYPOINTS, it.netname == s, LAMBDA(
+ FOREACH(Waypoints, it.netname == s, LAMBDA(
return it.m_name;
));
- switch (s)
- {
- case "item-invis": return _("Invisibility");
- case "item-extralife": return _("Extra life");
- case "item-speed": return _("Speed");
- default: return s;
- }
+ return s;
}
#endif
return rgb;
}
-void Draw_WaypointSprite()
+void Draw_WaypointSprite(entity this)
{
if (self.lifetime)
self.alpha = pow(bound(0, (self.fadetime - time) / self.lifetime, 1), waypointsprite_timealphaexponent);
else if (self.maxdistance > 0)
a *= pow(bound(0, (waypointsprite_fadedistance - dist) / (waypointsprite_fadedistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent) * (1 - waypointsprite_minalpha) + waypointsprite_minalpha;
- vector rgb = spritelookupcolor(spriteimage, self.teamradar_color);
+ vector rgb = spritelookupcolor(self, spriteimage, self.teamradar_color);
if (rgb == '0 0 0')
{
self.teamradar_color = '1 0 1';
e.SendFlags |= 1;
}
-void WaypointSprite_UpdateTeamRadar(entity e, float icon, vector col)
+void WaypointSprite_UpdateTeamRadar(entity e, entity icon, vector col)
{
// no check, as this is never called without doing an actual change (usually only once)
- e.cnt = (icon & 0x7F) | (e.cnt & 0x80);
+ int i = icon.m_id;
+ e.cnt = (e.cnt & BIT(7)) | (i & BITS(7));
e.colormod = col;
e.SendFlags |= 32;
}
if (time < e.waypointsprite_pingtime) return;
e.waypointsprite_pingtime = time + 0.3;
// ALWAYS sends (this causes a radar circle), thus no check
- e.cnt |= 0x80;
+ e.cnt |= BIT(7);
e.SendFlags |= 32;
}
}
void WaypointSprite_Think()
-{
+{SELFPARAM();
bool doremove = false;
if (self.fade_time && time >= self.teleport_time)
}
float WaypointSprite_visible_for_player(entity e)
-{
+{SELFPARAM();
// personal waypoints
if (self.enemy && self.enemy != e)
return false;
}
float WaypointSprite_Customize()
-{
+{SELFPARAM();
// this is not in SendEntity because it shall run every frame, not just every update
// make spectators see what the player would see
return self.waypointsprite_visible_for_player(e);
}
-float WaypointSprite_SendEntity(entity to, float sendflags);
+bool WaypointSprite_SendEntity(entity this, entity to, float sendflags);
void WaypointSprite_Reset()
-{
+{SELFPARAM();
// if a WP wants to time out, let it time out immediately; other WPs ought to be reset/killed by their owners
if (self.fade_time) // there was there before: || g_keyhunt, do we really need this?
entity showto, float t, // show to whom? Use a flag to indicate a team
entity own, .entity ownfield, // remove when own gets killed
float hideable, // true when it should be controlled by cl_hidewaypoints
- float icon // initial icon
+ entity icon // initial icon
)
{
entity wp = new(sprite_waypoint);
wp.customizeentityforclient = WaypointSprite_Customize;
wp.waypointsprite_visible_for_player = WaypointSprite_visible_for_player;
wp.reset2 = WaypointSprite_Reset;
- wp.cnt = icon;
+ wp.cnt = icon.m_id;
wp.colormod = spr.m_color;
Net_LinkEntity(wp, false, 0, WaypointSprite_SendEntity);
return wp;
vector ofs,
entity own,
.entity ownfield,
- float icon // initial icon
+ entity icon // initial icon
)
{
return WaypointSprite_Spawn(spr, 0, 0, world, ofs, world, 0, own, ownfield, true, icon);
entity spr,
float limited_range,
vector ofs,
- float icon // initial icon
+ entity icon // initial icon
)
-{
+{SELFPARAM();
float t;
if (teamplay)
t = self.team;
entity WaypointSprite_DeployPersonal(
entity spr,
vector ofs,
- float icon // initial icon
+ entity icon // initial icon
)
-{
+{SELFPARAM();
return WaypointSprite_Spawn(spr, 0, 0, world, ofs, world, 0, self, waypointsprite_deployed_personal, false, icon);
}
entity WaypointSprite_Attach(
entity spr,
float limited_range,
- float icon // initial icon
+ entity icon // initial icon
)
-{
+{SELFPARAM();
float t;
if (self.waypointsprite_attachedforcarrier)
return world; // can't attach to FC
entity WaypointSprite_AttachCarrier(
entity spr,
entity carrier,
- float icon // initial icon and color
+ entity icon // initial icon and color
)
{
WaypointSprite_Kill(carrier.waypointsprite_attached); // FC overrides attached
}
void WaypointSprite_ClearPersonal()
-{
+{SELFPARAM();
WaypointSprite_Kill(self.waypointsprite_deployed_personal);
}
void WaypointSprite_ClearOwned()
-{
+{SELFPARAM();
WaypointSprite_Kill(self.waypointsprite_deployed_fixed);
WaypointSprite_Kill(self.waypointsprite_deployed_personal);
WaypointSprite_Kill(self.waypointsprite_attached);
}
void WaypointSprite_PlayerDead()
-{
+{SELFPARAM();
WaypointSprite_Disown(self.waypointsprite_attached, waypointsprite_deadlifetime);
WaypointSprite_DetachCarrier(self);
}
void WaypointSprite_PlayerGone()
-{
+{SELFPARAM();
WaypointSprite_Disown(self.waypointsprite_deployed_fixed, waypointsprite_deadlifetime);
WaypointSprite_Kill(self.waypointsprite_deployed_personal);
WaypointSprite_Disown(self.waypointsprite_attached, waypointsprite_deadlifetime);
vector drawspritetext(vector o, float ang, float minwidth, vector rgb, float a, vector fontsize, string s);
float spritelookupblinkvalue(string s);
-vector spritelookupcolor(string s, vector def);
+vector spritelookupcolor(entity this, string s, vector def);
string spritelookuptext(string s);
vector fixrgbexcess_move(vector rgb, vector src, vector dst);
void WaypointSprite_Load();
.float alpha;
-void Draw_WaypointSprite();
+void Draw_WaypointSprite(entity this);
#endif
#ifdef SVQC
void WaypointSprite_UpdateRule(entity e, float t, float r);
-void WaypointSprite_UpdateTeamRadar(entity e, float icon, vector col);
+void WaypointSprite_UpdateTeamRadar(entity e, entity icon, vector col);
.float waypointsprite_pingtime;
.float waypointsprite_helpmetime;
float WaypointSprite_Customize();
-float WaypointSprite_SendEntity(entity to, float sendflags);
+bool WaypointSprite_SendEntity(entity this, entity to, float sendflags);
void WaypointSprite_Reset();
entity showto, float t, // show to whom? Use a flag to indicate a team
entity own, .entity ownfield, // remove when own gets killed
float hideable, // true when it should be controlled by cl_hidewaypoints
- float icon // initial icon
+ entity icon // initial icon
);
entity WaypointSprite_SpawnFixed(
vector ofs,
entity own,
.entity ownfield,
- float icon // initial icon
+ entity icon // initial icon
);
.entity waypointsprite_deployed_fixed;
entity spr,
float limited_range,
vector ofs,
- float icon // initial icon
+ entity icon // initial icon
);
.entity waypointsprite_deployed_personal;
entity WaypointSprite_DeployPersonal(
entity spr,
vector ofs,
- float icon // initial icon
+ entity icon // initial icon
);
.entity waypointsprite_attached;
entity WaypointSprite_Attach(
entity spr,
float limited_range,
- float icon // initial icon
+ entity icon // initial icon
);
entity WaypointSprite_AttachCarrier(
entity spr,
entity carrier,
- float icon // initial icon
+ entity icon // initial icon
);
void WaypointSprite_DetachCarrier(entity carrier);
+++ /dev/null
-#if defined(CSQC)
- #include "../dpdefs/csprogsdefs.qh"
- #include "../client/defs.qh"
- #include "nades.qh"
- #include "buffs.qh"
- #include "../common/movetypes/movetypes.qh"
- #include "../client/main.qh"
- #include "../csqcmodellib/cl_model.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
- #include "../dpdefs/progsdefs.qh"
- #include "constants.qh"
- #include "../server/constants.qh"
- #include "../common/turrets/sv_turrets.qh"
-#endif
-
-
-#ifdef SVQC
-float healer_send(entity to, int sf)
-{
- WriteByte(MSG_ENTITY, ENT_CLIENT_HEALING_ORB);
- WriteByte(MSG_ENTITY, sf);
-
- if(sf & 1)
- {
- WriteCoord(MSG_ENTITY, self.origin.x);
- WriteCoord(MSG_ENTITY, self.origin.y);
- WriteCoord(MSG_ENTITY, self.origin.z);
-
- WriteByte(MSG_ENTITY, self.healer_lifetime);
- //WriteByte(MSG_ENTITY, self.ltime - time + 1);
- WriteShort(MSG_ENTITY, self.healer_radius);
- // round time delta to a 1/10th of a second
- WriteByte(MSG_ENTITY, (self.ltime - time)*10.0+0.5);
- }
-
- return true;
-}
-#endif // SVQC
-
-#ifdef CSQC
-.float ltime;
-void healer_draw()
-{
- float dt = time - self.move_time;
- self.move_time = time;
- if(dt <= 0)
- return;
-
- self.alpha = (self.ltime - time) / self.healer_lifetime;
- self.scale = min((1 - self.alpha)*self.healer_lifetime*4,1)*self.healer_radius;
-
-}
-
-void healer_setup()
-{
- setmodel(self, "models/ctf/shield.md3");
-
- setorigin(self, self.origin);
-
- float model_radius = self.maxs.x;
- vector size = '1 1 1' * self.healer_radius / 2;
- setsize(self,-size,size);
- self.healer_radius = self.healer_radius/model_radius*0.6;
-
- self.draw = healer_draw;
- self.health = 255;
- self.movetype = MOVETYPE_NONE;
- self.solid = SOLID_NOT;
- self.drawmask = MASK_NORMAL;
- self.scale = 0.01;
- self.avelocity = self.move_avelocity = '7 0 11';
- self.colormod = '1 0 0';
- self.renderflags |= RF_ADDITIVE;
-}
-
-void ent_healer()
-{
- int sf = ReadByte();
-
- if(sf & TNSF_SETUP)
- {
- self.origin_x = ReadCoord();
- self.origin_y = ReadCoord();
- self.origin_z = ReadCoord();
- setorigin(self, self.origin);
-
- self.healer_lifetime = ReadByte();
- self.healer_radius = ReadShort();
- self.ltime = time + ReadByte()/10.0;
- //self.ltime = time + self.healer_lifetime;
-
- healer_setup();
- }
-}
-#endif // CSQC
+++ /dev/null
-#ifndef NADES_H
-#define NADES_H
-
-#include "teams.qh"
-
-.float healer_lifetime;
-.float healer_radius;
-
-// use slots 70-100
-const int PROJECTILE_NADE = 71;
-const int PROJECTILE_NADE_BURN = 72;
-const int PROJECTILE_NADE_NAPALM = 73;
-const int PROJECTILE_NADE_NAPALM_BURN = 74;
-const int PROJECTILE_NAPALM_FOUNTAIN = 75;
-const int PROJECTILE_NADE_ICE = 76;
-const int PROJECTILE_NADE_ICE_BURN = 77;
-const int PROJECTILE_NADE_TRANSLOCATE = 78;
-const int PROJECTILE_NADE_SPAWN = 79;
-const int PROJECTILE_NADE_HEAL = 80;
-const int PROJECTILE_NADE_HEAL_BURN = 81;
-const int PROJECTILE_NADE_MONSTER = 82;
-const int PROJECTILE_NADE_MONSTER_BURN = 83;
-
-void RegisterNades();
-const int NADES_MAX = 8;
-entity NADES[NADES_MAX], NADES_first, NADES_last;
-int NADES_COUNT;
-#define REGISTER_NADE(id) REGISTER(RegisterNades, NADE_TYPE, NADES, NADES_COUNT, id, m_id, NEW(Nade))
-REGISTER_REGISTRY(RegisterNades)
-
-CLASS(Nade, Object)
- ATTRIB(Nade, m_id, int, 0)
- ATTRIB(Nade, m_color, vector, '0 0 0')
- ATTRIB(Nade, m_name, string, _("Grenade"))
- ATTRIB(Nade, m_icon, string, "nade_normal")
- ATTRIBARRAY(Nade, m_projectile, int, 2)
- ATTRIBARRAY(Nade, m_trail, string, 2)
- METHOD(Nade, display, void(entity this, void(string name, string icon) returns)) {
- returns(this.m_name, sprintf("/gfx/hud/%s/%s", cvar_string("menu_skin"), this.m_icon));
- }
-ENDCLASS(Nade)
-
-REGISTER_NADE(NULL);
-
-#define NADE_PROJECTILE(i, projectile, trail) do { \
- this.m_projectile[i] = projectile; \
- this.m_trail[i] = trail; \
-} while (0)
-
-REGISTER_NADE(NORMAL) {
- this.m_color = '1 1 1';
- NADE_PROJECTILE(0, PROJECTILE_NADE, string_null);
- NADE_PROJECTILE(1, PROJECTILE_NADE_BURN, string_null);
-}
-
-REGISTER_NADE(NAPALM) {
- this.m_color = '2 0.5 0';
- this.m_name = _("Napalm grenade");
- this.m_icon = "nade_napalm";
- NADE_PROJECTILE(0, PROJECTILE_NADE_NAPALM, "TR_ROCKET");
- NADE_PROJECTILE(1, PROJECTILE_NADE_NAPALM_BURN, "spiderbot_rocket_thrust");
-}
-
-REGISTER_NADE(ICE) {
- this.m_color = '0 0.5 2';
- this.m_name = _("Ice grenade");
- this.m_icon = "nade_ice";
- NADE_PROJECTILE(0, PROJECTILE_NADE_ICE, "TR_NEXUIZPLASMA");
- NADE_PROJECTILE(1, PROJECTILE_NADE_ICE_BURN, "wakizashi_rocket_thrust");
-}
-
-REGISTER_NADE(TRANSLOCATE) {
- this.m_color = '1 0 1';
- this.m_name = _("Translocate grenade");
- this.m_icon = "nade_translocate";
- NADE_PROJECTILE(0, PROJECTILE_NADE_TRANSLOCATE, "TR_CRYLINKPLASMA");
- NADE_PROJECTILE(1, PROJECTILE_NADE_TRANSLOCATE, "TR_CRYLINKPLASMA");
-}
-
-REGISTER_NADE(SPAWN) {
- this.m_color = '1 0.9 0';
- this.m_name = _("Spawn grenade");
- this.m_icon = "nade_spawn";
- NADE_PROJECTILE(0, PROJECTILE_NADE_SPAWN, "nade_yellow");
- NADE_PROJECTILE(1, PROJECTILE_NADE_SPAWN, "nade_yellow");
-}
-
-REGISTER_NADE(HEAL) {
- this.m_color = '1 0 0';
- this.m_name = _("Heal grenade");
- this.m_icon = "nade_heal";
- NADE_PROJECTILE(0, PROJECTILE_NADE_HEAL, "nade_red");
- NADE_PROJECTILE(1, PROJECTILE_NADE_HEAL_BURN, "nade_red_burn");
-}
-
-REGISTER_NADE(MONSTER) {
- this.m_color = '0.25 0.75 0';
- this.m_name = _("Monster grenade");
- this.m_icon = "nade_monster";
- NADE_PROJECTILE(0, PROJECTILE_NADE_MONSTER, "nade_red");
- NADE_PROJECTILE(1, PROJECTILE_NADE_MONSTER_BURN, "nade_red_burn");
-}
-
-entity Nade_FromProjectile(float proj)
-{
- FOREACH(NADES, true, LAMBDA(
- for (int j = 0; j < 2; j++)
- {
- if (it.m_projectile[j] == proj) return it;
- }
- ));
- return NADE_TYPE_NULL;
-}
-
-string Nade_TrailEffect(float proj, float nade_team)
-{
- FOREACH(NADES, true, LAMBDA(
- for (int j = 0; j < 2; j++)
- {
- if (it.m_projectile[j] == proj)
- {
- string trail = it.m_trail[j];
- if (trail) return trail;
- break;
- }
- }
- ));
- switch (proj)
- {
- case PROJECTILE_NADE: return strcat("nade_", Static_Team_ColorName_Lower(nade_team));
- case PROJECTILE_NADE_BURN: return strcat("nade_", Static_Team_ColorName_Lower(nade_team), "_burn");
- }
- return "";
-}
-
-#ifdef SVQC
-float healer_send(entity to, int sf);
-#endif
-
-#ifdef CSQC
-// misc functions
-void ent_healer();
-#endif // CSQC
-#endif
--- /dev/null
+#define NADE_PROJECTILE(i, projectile, trail) do { \
+ this.m_projectile[i] = projectile; \
+ this.m_trail[i] = trail; \
+} while (0)
+
+REGISTER_NADE(NORMAL) {
+ this.m_color = '1 1 1';
+ NADE_PROJECTILE(0, PROJECTILE_NADE, EFFECT_Null);
+ NADE_PROJECTILE(1, PROJECTILE_NADE_BURN, EFFECT_Null);
+}
+
+REGISTER_NADE(NAPALM) {
+ this.m_color = '2 0.5 0';
+ this.m_name = _("Napalm grenade");
+ this.m_icon = "nade_napalm";
+ NADE_PROJECTILE(0, PROJECTILE_NADE_NAPALM, EFFECT_TR_ROCKET);
+ NADE_PROJECTILE(1, PROJECTILE_NADE_NAPALM_BURN, EFFECT_SPIDERBOT_ROCKET_TRAIL);
+}
+
+REGISTER_NADE(ICE) {
+ this.m_color = '0 0.5 2';
+ this.m_name = _("Ice grenade");
+ this.m_icon = "nade_ice";
+ NADE_PROJECTILE(0, PROJECTILE_NADE_ICE, EFFECT_TR_NEXUIZPLASMA);
+ NADE_PROJECTILE(1, PROJECTILE_NADE_ICE_BURN, EFFECT_RACER_ROCKET_TRAIL);
+}
+
+REGISTER_NADE(TRANSLOCATE) {
+ this.m_color = '1 0 1';
+ this.m_name = _("Translocate grenade");
+ this.m_icon = "nade_translocate";
+ NADE_PROJECTILE(0, PROJECTILE_NADE_TRANSLOCATE, EFFECT_TR_CRYLINKPLASMA);
+ NADE_PROJECTILE(1, PROJECTILE_NADE_TRANSLOCATE, EFFECT_TR_CRYLINKPLASMA);
+}
+
+REGISTER_NADE(SPAWN) {
+ this.m_color = '1 0.9 0';
+ this.m_name = _("Spawn grenade");
+ this.m_icon = "nade_spawn";
+ NADE_PROJECTILE(0, PROJECTILE_NADE_SPAWN, EFFECT_NADE_TRAIL_YELLOW);
+ NADE_PROJECTILE(1, PROJECTILE_NADE_SPAWN, EFFECT_NADE_TRAIL_YELLOW);
+}
+
+REGISTER_NADE(HEAL) {
+ this.m_color = '1 0 0';
+ this.m_name = _("Heal grenade");
+ this.m_icon = "nade_heal";
+ NADE_PROJECTILE(0, PROJECTILE_NADE_HEAL, EFFECT_NADE_TRAIL_RED);
+ NADE_PROJECTILE(1, PROJECTILE_NADE_HEAL_BURN, EFFECT_NADE_TRAIL_BURN_RED);
+}
+
+REGISTER_NADE(MONSTER) {
+ this.m_color = '0.25 0.75 0';
+ this.m_name = _("Monster grenade");
+ this.m_icon = "nade_monster";
+ NADE_PROJECTILE(0, PROJECTILE_NADE_MONSTER, EFFECT_NADE_TRAIL_RED);
+ NADE_PROJECTILE(1, PROJECTILE_NADE_MONSTER_BURN, EFFECT_NADE_TRAIL_BURN_RED);
+}
--- /dev/null
+#if defined(CSQC)
+ #include "../../dpdefs/csprogsdefs.qh"
+ #include "../../client/defs.qh"
+ #include "all.qh"
+ #include "../buffs/all.qh"
+ #include "../movetypes/movetypes.qh"
+ #include "../../client/main.qh"
+ #include "../../csqcmodellib/cl_model.qh"
+#elif defined(MENUQC)
+#elif defined(SVQC)
+ #include "../../dpdefs/progsdefs.qh"
+ #include "../constants.qh"
+ #include "../../server/constants.qh"
+ #include "../turrets/sv_turrets.qh"
+#endif
+
+
+#ifdef CSQC
+.float ltime;
+void healer_draw(entity this)
+{
+ float dt = time - self.move_time;
+ self.move_time = time;
+ if(dt <= 0)
+ return;
+
+ self.alpha = (self.ltime - time) / self.healer_lifetime;
+ self.scale = min((1 - self.alpha)*self.healer_lifetime*4,1)*self.healer_radius;
+}
+
+void healer_setup(entity e)
+{
+ setmodel(e, MDL_NADE_HEAL);
+
+ setorigin(e, e.origin);
+
+ float model_radius = e.maxs.x;
+ vector size = '1 1 1' * e.healer_radius / 2;
+ setsize(e,-size,size);
+ e.healer_radius = e.healer_radius/model_radius*0.6;
+
+ e.draw = healer_draw;
+ e.health = 255;
+ e.movetype = MOVETYPE_NONE;
+ e.solid = SOLID_NOT;
+ e.drawmask = MASK_NORMAL;
+ e.scale = 0.01;
+ e.avelocity = e.move_avelocity = '7 0 11';
+ e.colormod = '1 0 0';
+ e.renderflags |= RF_ADDITIVE;
+}
+#endif // CSQC
+
+REGISTER_NET_LINKED(Nade_Heal, bool isNew)
+#ifdef CSQC
+{
+ Net_Accept();
+ int sf = ReadByte();
+ if (sf & 1) {
+ this.origin_x = ReadCoord();
+ this.origin_y = ReadCoord();
+ this.origin_z = ReadCoord();
+ setorigin(this, this.origin);
+ this.healer_lifetime = ReadByte();
+ this.healer_radius = ReadShort();
+ this.ltime = time + ReadByte()/10.0;
+ // this.ltime = time + this.healer_lifetime;
+ healer_setup(this);
+ }
+}
+#endif
+
+#ifdef SVQC
+bool healer_send(entity this, entity to, int sf)
+{
+ int channel = MSG_ENTITY;
+ WriteHeader(channel, Nade_Heal);
+ WriteByte(channel, sf);
+ if (sf & 1) {
+ WriteCoord(channel, this.origin.x);
+ WriteCoord(channel, this.origin.y);
+ WriteCoord(channel, this.origin.z);
+
+ WriteByte(channel, this.healer_lifetime);
+ //WriteByte(MSG_ENTITY, this.ltime - time + 1);
+ WriteShort(channel, this.healer_radius);
+ // round time delta to a 1/10th of a second
+ WriteByte(channel, (this.ltime - time)*10.0+0.5);
+ }
+ return true;
+}
+#endif // SVQC
--- /dev/null
+#ifndef NADES_ALL_H
+#define NADES_ALL_H
+
+#include "../teams.qh"
+
+.float healer_lifetime;
+.float healer_radius;
+
+// use slots 70-100
+const int PROJECTILE_NADE = 71;
+const int PROJECTILE_NADE_BURN = 72;
+const int PROJECTILE_NADE_NAPALM = 73;
+const int PROJECTILE_NADE_NAPALM_BURN = 74;
+const int PROJECTILE_NAPALM_FOUNTAIN = 75;
+const int PROJECTILE_NADE_ICE = 76;
+const int PROJECTILE_NADE_ICE_BURN = 77;
+const int PROJECTILE_NADE_TRANSLOCATE = 78;
+const int PROJECTILE_NADE_SPAWN = 79;
+const int PROJECTILE_NADE_HEAL = 80;
+const int PROJECTILE_NADE_HEAL_BURN = 81;
+const int PROJECTILE_NADE_MONSTER = 82;
+const int PROJECTILE_NADE_MONSTER_BURN = 83;
+
+REGISTRY(Nades, BIT(3))
+REGISTER_REGISTRY(RegisterNades)
+#define REGISTER_NADE(id) REGISTER(RegisterNades, NADE_TYPE, Nades, id, m_id, NEW(Nade))
+
+CLASS(Nade, Object)
+ ATTRIB(Nade, m_id, int, 0)
+ ATTRIB(Nade, m_color, vector, '0 0 0')
+ ATTRIB(Nade, m_name, string, _("Grenade"))
+ ATTRIB(Nade, m_icon, string, "nade_normal")
+ ATTRIBARRAY(Nade, m_projectile, int, 2)
+ ATTRIBARRAY(Nade, m_trail, entity, 2)
+ METHOD(Nade, display, void(entity this, void(string name, string icon) returns)) {
+ returns(this.m_name, sprintf("/gfx/hud/%s/%s", cvar_string("menu_skin"), this.m_icon));
+ }
+ENDCLASS(Nade)
+
+REGISTER_NADE(Null);
+
+#ifdef SVQC
+bool healer_send(entity this, entity to, int sf);
+#endif
+
+entity Nade_FromProjectile(float proj)
+{
+ FOREACH(Nades, true, LAMBDA(
+ for (int j = 0; j < 2; j++)
+ {
+ if (it.m_projectile[j] == proj) return it;
+ }
+ ));
+ return NADE_TYPE_Null;
+}
+
+entity Nade_TrailEffect(int proj, int nade_team)
+{
+ switch (proj)
+ {
+ case PROJECTILE_NADE: return EFFECT_NADE_TRAIL(nade_team);
+ case PROJECTILE_NADE_BURN: return EFFECT_NADE_TRAIL_BURN(nade_team);
+ }
+
+ FOREACH(Nades, true, LAMBDA(
+ for (int j = 0; j < 2; j++)
+ {
+ if (it.m_projectile[j] == proj)
+ {
+ string trail = it.m_trail[j].eent_eff_name;
+ if (trail) return it.m_trail[j];
+ break;
+ }
+ }
+ ));
+
+ return EFFECT_Null;
+}
+
+#include "all.inc"
+
+#endif
#ifdef SVQC
void sv_notice_join_think()
-{
+{SELFPARAM();
//NextLevel();
float argc = tokenizebyseparator(autocvar_sv_join_notices, "|");
if(argc > 0)
}
void sv_notice_join()
-{
+{SELFPARAM();
// to-do: make sv_join_notices support per-entry times
if(autocvar_sv_join_notices == "")
return;
{
// check supplied type and name for errors
string checkargs = "";
- #define CHECKARG_TYPENAME(type) case MSG_##type##: \
+ #define CHECKARG_TYPENAME(type) case MSG_##type: \
{ if(!net_name || (net_name > NOTIF_##type##_COUNT)) \
{ checkargs = sprintf("Improper name: %d!", net_name); } break; }
switch(net_type)
));
#endif
- sound(
+ _sound(
world,
soundchannel,
sprintf(
case MSG_INFO:
{
- LOG_INFO(
+ print(
Local_Notification_sprintf(
notif.nent_string,
notif.nent_args,
#ifdef SVQC
void Net_Notification_Remove()
-{
+{SELFPARAM();
if (!self) { backtrace(sprintf("Net_Notification_Remove() at %f: Missing self!?\n", time)); return; }
#ifdef NOTIFICATIONS_DEBUG
remove(self);
}
-float Net_Write_Notification(entity client, int sf)
+bool Net_Write_Notification(entity this, entity client, int sf)
{
if(Notification_ShouldSend(self.nent_broadcast, client, self.nent_client))
{
ARG_CASE(ARG_CS_SV, "spree_end", (autocvar_notification_show_sprees ? notif_arg_spree_inf(-1, "", "", f1) : "")) \
ARG_CASE(ARG_CS_SV, "spree_lost", (autocvar_notification_show_sprees ? notif_arg_spree_inf(-2, "", "", f1) : "")) \
ARG_CASE(ARG_CS_SV, "item_wepname", WEP_NAME(f1)) \
- ARG_CASE(ARG_CS_SV, "item_buffname", sprintf("%s%s", rgb_to_hexcolor(BUFFS[f1].m_color), BUFFS[f1].m_prettyName)) \
- ARG_CASE(ARG_CS_SV, "f3buffname", sprintf("%s%s", rgb_to_hexcolor(BUFFS[f3].m_color), BUFFS[f3].m_prettyName)) \
+ ARG_CASE(ARG_CS_SV, "item_buffname", sprintf("%s%s", rgb_to_hexcolor(Buffs[f1].m_color), Buffs[f1].m_prettyName)) \
+ ARG_CASE(ARG_CS_SV, "f3buffname", sprintf("%s%s", rgb_to_hexcolor(Buffs[f3].m_color), Buffs[f3].m_prettyName)) \
ARG_CASE(ARG_CS_SV, "item_wepammo", (s1 != "" ? sprintf(_(" with %s"), s1) : "")) \
ARG_CASE(ARG_DC, "item_centime", ftos(autocvar_notification_item_centerprinttime)) \
ARG_CASE(ARG_SV, "death_team", Team_ColoredFullName(f1)) \
NO_MSG, /* optiona */ \
NO_MSG); /* optionb */ \
} \
- ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name);
+ ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
#define MSG_INFO_NOTIF(default,name,strnum,flnum,args,hudargs,icon,normal,gentle) \
NOTIF_ADD_AUTOCVAR(name, default) \
NO_MSG, /* optiona */ \
NO_MSG); /* optionb */ \
} \
- ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name);
+ ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
.string nent_iconargs;
#define MULTIICON_INFO(default,name,strnum,flnum,args,hudargs,iconargs,icon,normal,gentle) \
NO_MSG); /* optionb */ \
msg_info_notifs[name - 1].nent_iconargs = iconargs; \
} \
- ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name);
+ ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
#define MSG_CENTER_NOTIF(default,name,strnum,flnum,args,cpid,durcnt,normal,gentle) \
NOTIF_ADD_AUTOCVAR(name, default) \
NO_MSG, /* optiona */ \
NO_MSG); /* optionb */ \
} \
- ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name);
+ ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
#define MSG_MULTI_NOTIF(default,name,anncename,infoname,centername) \
NOTIF_ADD_AUTOCVAR(name, default) \
NO_MSG, /* optiona */ \
NO_MSG); /* optionb */ \
} \
- ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name);
+ ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
#define ACVNN(name) autocvar_notification_##name
optiona, /* optiona */ \
optionb); /* optionb */ \
} \
- ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name);
+ ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
void RegisterNotifications_First()
{
}
// NOW we actually activate the declarations
-ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotifications_First);
+ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotifications_First)
#include "notifications.inc"
-ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotifications_Done);
+ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotifications_Done)
#endif
{
if(Physics_Valid(pl.cvar_cl_physics))
{
- string var = sprintf("g_physics_%s_%s", pl.cvar_cl_physics, option);
- if(cvar_type(var) & CVAR_TYPEFLAG_EXISTS)
- return cvar(var);
+ string s = sprintf("g_physics_%s_%s", pl.cvar_cl_physics, option);
+ if(cvar_type(s) & CVAR_TYPEFLAG_EXISTS)
+ return cvar(s);
}
if(autocvar_g_physics_clientselect && autocvar_g_physics_clientselect_default)
{
- string var = sprintf("g_physics_%s_%s", autocvar_g_physics_clientselect_default, option);
- if(cvar_type(var) & CVAR_TYPEFLAG_EXISTS)
- return cvar(var);
+ string s = sprintf("g_physics_%s_%s", autocvar_g_physics_clientselect_default, option);
+ if(cvar_type(s) & CVAR_TYPEFLAG_EXISTS)
+ return cvar(s);
}
return cvar(strcat("sv_", option));
}
addstat(STAT_JETPACK_MAXSPEED_SIDE, AS_FLOAT, stat_jetpack_maxspeed_side);
// hack to fix track_canjump
- addstat(STAT_MOVEVARS_TRACK_CANJUMP, AS_INT, cvar_cl_movement_track_canjump);
+ addstat(STAT_MOVEVARS_CL_TRACK_CANJUMP, AS_INT, cvar_cl_movement_track_canjump);
+ addstat(STAT_MOVEVARS_TRACK_CANJUMP, AS_INT, stat_sv_track_canjump);
// double jump
addstat(STAT_DOUBLEJUMP, AS_INT, stat_doublejump);
}
void Physics_UpdateStats(float maxspd_mod)
-{
+{SELFPARAM();
// blah
self.stat_pl_view_ofs = PL_VIEW_OFS;
self.stat_pl_crouch_view_ofs = PL_CROUCH_VIEW_OFS;
self.stat_sv_airstopaccelerate = Physics_ClientOption(self, "airstopaccelerate");
self.stat_sv_jumpvelocity = Physics_ClientOption(self, "jumpvelocity");
+ self.stat_sv_track_canjump = Physics_ClientOption(self, "track_canjump");
+
self.stat_gameplayfix_upvelocityclearsonground = UPWARD_VELOCITY_CLEARS_ONGROUND;
}
#endif
};
void PM_ClientMovement_Unstick()
-{
+{SELFPARAM();
float i;
for (i = 0; i < unstick_count; i++)
{
}
void PM_ClientMovement_UpdateStatus(bool ground)
-{
+{SELFPARAM();
// make sure player is not stuck
PM_ClientMovement_Unstick();
}
void PM_ClientMovement_Move()
-{
+{SELFPARAM();
#ifdef CSQC
int bump;
float t;
}
void CPM_PM_Aircontrol(vector wishdir, float wishspeed)
-{
+{SELFPARAM();
float k = 32 * (2 * IsMoveInDirection(self.movement, 0) - 1);
if (k <= 0)
return;
// prvm_globalset server speedclamp_mode 1
// (or 2)
void PM_Accelerate(vector wishdir, float wishspeed, float wishspeed0, float accel, float accelqw, float stretchfactor, float sidefric, float speedlimit)
-{
+{SELFPARAM();
float speedclamp = stretchfactor > 0 ? stretchfactor
: accelqw < 0 ? 1 // full clamping, no stretch
: -1; // no clamping
}
void PM_AirAccelerate(vector wishdir, float wishspeed)
-{
+{SELFPARAM();
if (wishspeed == 0)
return;
=============
*/
bool PlayerJump (void)
-{
+{SELFPARAM();
if (PHYS_FROZEN(self))
return true; // no jumping in freezetag when frozen
if (!IS_ONGROUND(self))
return IS_JUMP_HELD(self);
- if (PHYS_TRACK_CANJUMP(self))
+ bool track_jump = PHYS_CL_TRACK_CANJUMP(self);
+ if(PHYS_TRACK_CANJUMP(self))
+ track_jump = true;
+
+ if (track_jump)
if (IS_JUMP_HELD(self))
return true;
}
void CheckWaterJump()
-{
+{SELFPARAM();
// check for a jump-out-of-water
makevectors(self.v_angle);
vector start = self.origin;
// Hack: shouldn't need to know about this
.float multijump_count;
void CheckPlayerJump()
-{
+{SELFPARAM();
#ifdef SVQC
float was_flying = ITEMS_STAT(self) & IT_USING_JETPACK;
#endif
}
void RaceCarPhysics()
-{
+{SELFPARAM();
#ifdef SVQC
// using this move type for "big rigs"
// the engine does not push the entity!
}
void PM_check_race_movetime(void)
-{
+{SELFPARAM();
#ifdef SVQC
self.race_movetime_frac += PHYS_INPUT_TIMELENGTH;
float f = floor(self.race_movetime_frac);
}
float PM_check_specialcommand(float buttons)
-{
+{SELFPARAM();
#ifdef SVQC
string c;
if (!buttons)
}
void PM_check_nickspam(void)
-{
+{SELFPARAM();
#ifdef SVQC
if (time >= self.nickspamtime)
return;
}
void PM_check_punch()
-{
+{SELFPARAM();
#ifdef SVQC
if (self.punchangle != '0 0 0')
{
}
void PM_check_spider(void)
-{
+{SELFPARAM();
#ifdef SVQC
if (time >= self.spider_slowness)
return;
// predict frozen movement, as frozen players CAN move in some cases
void PM_check_frozen(void)
-{
+{SELFPARAM();
if (!PHYS_FROZEN(self))
return;
if (PHYS_DODGING_FROZEN
}
void PM_check_hitground()
-{
+{SELFPARAM();
#ifdef SVQC
if (IS_ONGROUND(self))
if (IS_PLAYER(self)) // no fall sounds for observers thank you very much
}
void PM_check_blocked(void)
-{
+{SELFPARAM();
#ifdef SVQC
if (!self.player_blocked)
return;
float speedaward_lastupdate;
#endif
void PM_check_race(void)
-{
+{SELFPARAM();
#ifdef SVQC
if(!(g_cts || g_race))
return;
}
void PM_check_vortex(void)
-{
+{SELFPARAM();
#ifdef SVQC
// WEAPONTODO
float xyspeed = vlen(vec2(self.velocity));
}
void PM_fly(float maxspd_mod)
-{
+{SELFPARAM();
// noclipping or flying
UNSET_ONGROUND(self);
}
void PM_swim(float maxspd_mod)
-{
+{SELFPARAM();
// swimming
UNSET_ONGROUND(self);
}
void PM_ladder(float maxspd_mod)
-{
+{SELFPARAM();
// on a spawnfunc_func_ladder or swimming in spawnfunc_func_water
UNSET_ONGROUND(self);
}
void PM_jetpack(float maxspd_mod)
-{
+{SELFPARAM();
//makevectors(self.v_angle.y * '0 1 0');
makevectors(self.v_angle);
vector wishvel = v_forward * self.movement_x
}
void PM_walk(float buttons_prev, float maxspd_mod)
-{
+{SELFPARAM();
if (!WAS_ONGROUND(self))
{
#ifdef SVQC
}
void PM_air(float buttons_prev, float maxspd_mod)
-{
+{SELFPARAM();
makevectors(self.v_angle.y * '0 1 0');
vector wishvel = v_forward * self.movement.x
+ v_right * self.movement.y;
}
void PM_Main()
-{
+{SELFPARAM();
int buttons = PHYS_INPUT_BUTTON_MASK(self);
#ifdef CSQC
self.items = getstati(STAT_ITEMS, 0, 24);
#elif defined(CSQC)
void CSQC_ClientMovement_PlayerMove_Frame(void)
#endif
-{
+{SELFPARAM();
PM_Main();
#ifdef CSQC
#define PHYS_JUMPSPEEDCAP_MAX cvar_string("cl_jumpspeedcap_max")
#define PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS getstati(STAT_MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS)
+ #define PHYS_CL_TRACK_CANJUMP(s) getstati(STAT_MOVEVARS_CL_TRACK_CANJUMP)
#define PHYS_TRACK_CANJUMP(s) getstati(STAT_MOVEVARS_TRACK_CANJUMP)
#define PHYS_ACCELERATE getstatf(STAT_MOVEVARS_ACCELERATE)
#define PHYS_AIRACCEL_QW(s) getstatf(STAT_MOVEVARS_AIRACCEL_QW)
.float stat_nostep;
.float stat_jumpstep;
+ .bool stat_sv_track_canjump;
+
#define PHYS_INPUT_ANGLES(s) s.v_angle
#define PHYS_WORLD_ANGLES(s) s.angles
#define PHYS_JUMPSPEEDCAP_MAX autocvar_sv_jumpspeedcap_max
#define PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS autocvar_sv_jumpspeedcap_max_disable_on_ramps
- #define PHYS_TRACK_CANJUMP(s) s.cvar_cl_movement_track_canjump
+ #define PHYS_CL_TRACK_CANJUMP(s) s.cvar_cl_movement_track_canjump
+ #define PHYS_TRACK_CANJUMP(s) s.stat_sv_track_canjump
#define PHYS_ACCELERATE self.stat_sv_accelerate
#define PHYS_AIRACCEL_QW(s) s.stat_sv_airaccel_qw
#define PHYS_AIRACCEL_QW_STRETCHFACTOR(s) self.stat_sv_airaccel_qw_stretchfactor
#endif
#ifdef CSQC
-/*
- * FIXME - crypto_* builtin functions missing in CSQC (csprogsdefs.qh:885)
+// FIXME - crypto_* builtin functions missing in CSQC (csprogsdefs.qh:885)
void PlayerInfo_Details()
{
print("-- Getting detailed PlayerInfo for local player (CSQC)\n");
--- /dev/null
+// Global list of sounds
+// TODO: remove uses of _sound
+
+string W_Sound(string w_snd);
+
+SOUND(ARC_FIRE, W_Sound("arc_fire"));
+SOUND(ARC_LOOP, W_Sound("arc_loop"));
+SOUND(ARC_LOOP_OVERHEAT, W_Sound("arc_loop_overheat"));
+SOUND(ARC_STOP, W_Sound("arc_stop"));
+SOUND(CAMPINGRIFLE_FIRE2, W_Sound("campingrifle_fire2"));
+SOUND(CAMPINGRIFLE_FIRE, W_Sound("campingrifle_fire"));
+SOUND(CRYLINK_FIRE2, W_Sound("crylink_fire2"));
+SOUND(CRYLINK_FIRE, W_Sound("crylink_fire"));
+SOUND(CRYLINK_IMPACT2, W_Sound("crylink_impact2"));
+SOUND(CRYLINK_IMPACT, W_Sound("crylink_impact"));
+SOUND(CRYLINK_LINKJOIN, W_Sound("crylink_linkjoin"));
+SOUND(DRYFIRE, W_Sound("dryfire"));
+SOUND(ELECTRO_BOUNCE, W_Sound("electro_bounce"));
+SOUND(ELECTRO_FIRE2, W_Sound("electro_fire2"));
+SOUND(ELECTRO_FIRE, W_Sound("electro_fire"));
+SOUND(ELECTRO_FLY, W_Sound("electro_fly"));
+SOUND(ELECTRO_IMPACT, W_Sound("electro_impact"));
+SOUND(ELECTRO_IMPACT_COMBO, W_Sound("electro_impact_combo"));
+SOUND(FIREBALL_FIRE2, W_Sound("fireball_fire2"));
+SOUND(FIREBALL_FIRE, W_Sound("fireball_fire"));
+SOUND(FIREBALL_FLY2, W_Sound("fireball_fly2"));
+SOUND(FIREBALL_FLY, W_Sound("fireball_fly"));
+SOUND(FIREBALL_IMPACT2, W_Sound("fireball_impact2"));
+SOUND(FIREBALL_PREFIRE2, W_Sound("fireball_prefire2"));
+SOUND(FLAC_FIRE, W_Sound("flac_fire"));
+SOUND(GRENADE_BOUNCE1, W_Sound("grenade_bounce1"));
+SOUND(GRENADE_BOUNCE2, W_Sound("grenade_bounce2"));
+SOUND(GRENADE_BOUNCE3, W_Sound("grenade_bounce3"));
+SOUND(GRENADE_BOUNCE4, W_Sound("grenade_bounce4"));
+SOUND(GRENADE_BOUNCE5, W_Sound("grenade_bounce5"));
+SOUND(GRENADE_BOUNCE6, W_Sound("grenade_bounce6"));
+Sound SND_GRENADE_BOUNCE_RANDOM() {
+ return Sounds[SND_GRENADE_BOUNCE1.m_id + rint(random() * 5)];
+}
+SOUND(GRENADE_FIRE, W_Sound("grenade_fire"));
+SOUND(GRENADE_IMPACT, W_Sound("grenade_impact"));
+SOUND(GRENADE_STICK, W_Sound("grenade_stick"));
+SOUND(HAGAR_BEEP, W_Sound("hagar_beep"));
+SOUND(HAGAR_FIRE, W_Sound("hagar_fire"));
+SOUND(HAGAR_LOAD, W_Sound("hagar_load"));
+SOUND(HAGEXP1, W_Sound("hagexp1"));
+SOUND(HAGEXP2, W_Sound("hagexp2"));
+SOUND(HAGEXP3, W_Sound("hagexp3"));
+Sound SND_HAGEXP_RANDOM() {
+ return Sounds[SND_HAGEXP1.m_id + rint(random() * 2)];
+}
+
+SOUND(HOOKBOMB_FIRE, W_Sound("hookbomb_fire"));
+SOUND(HOOKBOMB_IMPACT, W_Sound("hookbomb_impact"));
+SOUND(HOOK_FIRE, W_Sound("hook_fire"));
+SOUND(HOOK_IMPACT, W_Sound("hook_impact"));
+SOUND(LASERGUN_FIRE, W_Sound("lasergun_fire"));
+SOUND(LASERIMPACT, W_Sound("laserimpact"));
+SOUND(LGBEAM_FLY, W_Sound("lgbeam_fly"));
+SOUND(MINE_DET, W_Sound("mine_det"));
+SOUND(MINE_EXP, W_Sound("mine_exp"));
+SOUND(MINE_FIRE, W_Sound("mine_fire"));
+SOUND(MINE_STICK, W_Sound("mine_stick"));
+SOUND(MINE_TRIGGER, W_Sound("mine_trigger"));
+SOUND(MINSTANEXFIRE, W_Sound("minstanexfire"));
+SOUND(NEXCHARGE, W_Sound("nexcharge"));
+SOUND(NEXFIRE, W_Sound("nexfire"));
+SOUND(NEXIMPACT, W_Sound("neximpact"));
+SOUND(NEXWHOOSH1, W_Sound("nexwhoosh1"));
+SOUND(NEXWHOOSH2, W_Sound("nexwhoosh2"));
+SOUND(NEXWHOOSH3, W_Sound("nexwhoosh3"));
+Sound SND_NEXWHOOSH_RANDOM() {
+ return Sounds[SND_NEXWHOOSH1.m_id + rint(random() * 2)];
+}
+SOUND(RELOAD, W_Sound("reload")); // until weapons have individual reload sounds, precache the reload sound here
+
+SOUND(RIC1, W_Sound("ric1"));
+SOUND(RIC2, W_Sound("ric2"));
+SOUND(RIC3, W_Sound("ric3"));
+Sound SND_RIC_RANDOM() {
+ return Sounds[SND_RIC1.m_id + rint(random() * 2)];
+}
+
+SOUND(ROCKET_DET, W_Sound("rocket_det"));
+SOUND(ROCKET_FIRE, W_Sound("rocket_fire"));
+SOUND(ROCKET_FLY, W_Sound("rocket_fly"));
+SOUND(ROCKET_IMPACT, W_Sound("rocket_impact"));
+SOUND(ROCKET_MODE, W_Sound("rocket_mode"));
+SOUND(SEEKEREXP1, W_Sound("seekerexp1"));
+SOUND(SEEKEREXP2, W_Sound("seekerexp2"));
+SOUND(SEEKEREXP3, W_Sound("seekerexp3"));
+SOUND(SEEKER_FIRE, W_Sound("seeker_fire"));
+SOUND(SHOTGUN_FIRE, W_Sound("shotgun_fire"));
+SOUND(SHOTGUN_MELEE, W_Sound("shotgun_melee"));
+SOUND(STRENGTH_FIRE, W_Sound("strength_fire"));
+SOUND(TAGEXP1, W_Sound("tagexp1"));
+SOUND(TAGEXP2, W_Sound("tagexp2"));
+SOUND(TAGEXP3, W_Sound("tagexp3"));
+SOUND(TAG_FIRE, W_Sound("tag_fire"));
+SOUND(TAG_IMPACT, W_Sound("tag_impact"));
+SOUND(TAG_ROCKET_FLY, W_Sound("tag_rocket_fly"));
+SOUND(UNAVAILABLE, W_Sound("unavailable"));
+SOUND(UZI_FIRE, W_Sound("uzi_fire"));
+SOUND(WEAPONPICKUP, W_Sound("weaponpickup"));
+SOUND(WEAPONPICKUP_NEW_TOYS, W_Sound("weaponpickup_new_toys"));
+SOUND(WEAPON_SWITCH, W_Sound("weapon_switch"));
+
+SOUND(CTF_CAPTURE_NEUTRAL, "ctf/capture.ogg");
+SOUND(CTF_CAPTURE_RED, "ctf/red_capture.wav");
+SOUND(CTF_CAPTURE_BLUE, "ctf/blue_capture.wav");
+SOUND(CTF_CAPTURE_YELLOW, "ctf/yellow_capture.ogg");
+SOUND(CTF_CAPTURE_PINK, "ctf/pink_capture.ogg");
+Sound SND_CTF_CAPTURE(int teamid) {
+ switch (teamid) {
+ case NUM_TEAM_1: return SND_CTF_CAPTURE_RED;
+ case NUM_TEAM_2: return SND_CTF_CAPTURE_BLUE;
+ case NUM_TEAM_3: return SND_CTF_CAPTURE_YELLOW;
+ case NUM_TEAM_4: return SND_CTF_CAPTURE_PINK;
+ default: return SND_CTF_CAPTURE_NEUTRAL;
+ }
+}
+
+SOUND(CTF_DROPPED_NEUTRAL, "ctf/neutral_dropped.wav");
+SOUND(CTF_DROPPED_RED, "ctf/red_dropped.wav");
+SOUND(CTF_DROPPED_BLUE, "ctf/blue_dropped.wav");
+SOUND(CTF_DROPPED_YELLOW, "ctf/yellow_dropped.wav");
+SOUND(CTF_DROPPED_PINK, "ctf/pink_dropped.wav");
+Sound SND_CTF_DROPPED(int teamid) {
+ switch (teamid) {
+ case NUM_TEAM_1: return SND_CTF_DROPPED_RED;
+ case NUM_TEAM_2: return SND_CTF_DROPPED_BLUE;
+ case NUM_TEAM_3: return SND_CTF_DROPPED_YELLOW;
+ case NUM_TEAM_4: return SND_CTF_DROPPED_PINK;
+ default: return SND_CTF_DROPPED_NEUTRAL;
+ }
+}
+
+SOUND(CTF_PASS, "ctf/pass.wav");
+SOUND(CTF_RESPAWN, "ctf/flag_respawn.wav");
+
+SOUND(CTF_RETURNED_NEUTRAL, "ctf/return.wav");
+SOUND(CTF_RETURNED_RED, "ctf/red_returned.wav");
+SOUND(CTF_RETURNED_BLUE, "ctf/blue_returned.wav");
+SOUND(CTF_RETURNED_YELLOW, "ctf/yellow_returned.wav");
+SOUND(CTF_RETURNED_PINK, "ctf/pink_returned.wav");
+Sound SND_CTF_RETURNED(int teamid) {
+ switch (teamid) {
+ case NUM_TEAM_1: return SND_CTF_RETURNED_RED;
+ case NUM_TEAM_2: return SND_CTF_RETURNED_BLUE;
+ case NUM_TEAM_3: return SND_CTF_RETURNED_YELLOW;
+ case NUM_TEAM_4: return SND_CTF_RETURNED_PINK;
+ default: return SND_CTF_RETURNED_NEUTRAL;
+ }
+}
+
+SOUND(CTF_TAKEN_NEUTRAL, "ctf/neutral_taken.wav");
+SOUND(CTF_TAKEN_RED, "ctf/red_taken.wav");
+SOUND(CTF_TAKEN_BLUE, "ctf/blue_taken.wav");
+SOUND(CTF_TAKEN_YELLOW, "ctf/yellow_taken.wav");
+SOUND(CTF_TAKEN_PINK, "ctf/pink_taken.wav");
+Sound SND_CTF_TAKEN(int teamid) {
+ switch (teamid) {
+ case NUM_TEAM_1: return SND_CTF_TAKEN_RED;
+ case NUM_TEAM_2: return SND_CTF_TAKEN_BLUE;
+ case NUM_TEAM_3: return SND_CTF_TAKEN_YELLOW;
+ case NUM_TEAM_4: return SND_CTF_TAKEN_PINK;
+ default: return SND_CTF_TAKEN_NEUTRAL;
+ }
+}
+
+SOUND(CTF_TOUCH, "ctf/touch.wav");
+
+SOUND(DOM_CLAIM, "domination/claim.wav");
+
+SOUND(KA_DROPPED, "keepaway/dropped.wav");
+SOUND(KA_PICKEDUP, "keepaway/pickedup.wav");
+SOUND(KA_RESPAWN, "keepaway/respawn.wav");
+SOUND(KA_TOUCH, "keepaway/touch.wav");
+
+SOUND(KH_ALARM, "kh/alarm.wav");
+SOUND(KH_CAPTURE, "kh/capture.wav");
+SOUND(KH_COLLECT, "kh/collect.wav");
+SOUND(KH_DESTROY, "kh/destroy.wav");
+SOUND(KH_DROP, "kh/drop.wav");
+
+SOUND(NB_BOUNCE, "nexball/bounce.ogg");
+SOUND(NB_DROP, "nexball/drop.ogg");
+SOUND(NB_SHOOT1, "nexball/shoot1.ogg");
+SOUND(NB_SHOOT2, "nexball/shoot2.ogg");
+SOUND(NB_STEAL, "nexball/steal.ogg");
+
+SOUND(ONS_CONTROLPOINT_BUILD, "onslaught/controlpoint_build.ogg");
+SOUND(ONS_CONTROLPOINT_BUILT, "onslaught/controlpoint_built.ogg");
+SOUND(ONS_CONTROLPOINT_UNDERATTACK, "onslaught/controlpoint_underattack.ogg");
+SOUND(ONS_DAMAGEBLOCKEDBYSHIELD, "onslaught/damageblockedbyshield.wav");
+SOUND(ONS_ELECTRICITY_EXPLODE, "onslaught/electricity_explode.ogg");
+SOUND(ONS_GENERATOR_DECAY, "onslaught/generator_decay.ogg");
+SOUND(ONS_GENERATOR_UNDERATTACK, "onslaught/generator_underattack.ogg");
+SOUND(ONS_HIT1, "onslaught/ons_hit1.ogg");
+SOUND(ONS_HIT2, "onslaught/ons_hit2.ogg");
+SOUND(ONS_SPARK1, "onslaught/ons_spark1.ogg");
+SOUND(ONS_SPARK2, "onslaught/ons_spark2.ogg");
+SOUND(ONS_SHOCKWAVE, "onslaught/shockwave.ogg");
+
+SOUND(PORTO_BOUNCE, "porto/bounce.ogg");
+SOUND(PORTO_CREATE, "porto/create.ogg");
+SOUND(PORTO_EXPIRE, "porto/expire.ogg");
+SOUND(PORTO_EXPLODE, "porto/explode.ogg");
+SOUND(PORTO_FIRE, "porto/fire.ogg");
+SOUND(PORTO_UNSUPPORTED, "porto/unsupported.ogg");
+
+SOUND(TUR_PHASER, "turrets/phaser.ogg");
+
+SOUND(VEH_ALARM, "vehicles/alarm.wav");
+SOUND(VEH_ALARM_SHIELD, "vehicles/alarm_shield.wav");
+SOUND(VEH_MISSILE_ALARM, "vehicles/missile_alarm.wav");
+
+SOUND(VEH_BUMBLEBEE_FIRE, W_Sound("flacexp3"));
+
+SOUND(VEH_RACER_BOOST, "vehicles/racer_boost.wav");
+SOUND(VEH_RACER_IDLE, "vehicles/racer_idle.wav");
+SOUND(VEH_RACER_MOVE, "vehicles/racer_move.wav");
+
+SOUND(VEH_RAPTOR_FLY, "vehicles/raptor_fly.wav");
+SOUND(VEH_RAPTOR_SPEED, "vehicles/raptor_speed.wav");
+
+SOUND(VEH_SPIDERBOT_DIE, "vehicles/spiderbot_die.wav");
+SOUND(VEH_SPIDERBOT_IDLE, "vehicles/spiderbot_idle.wav");
+SOUND(VEH_SPIDERBOT_JUMP, "vehicles/spiderbot_jump.wav");
+SOUND(VEH_SPIDERBOT_LAND, "vehicles/spiderbot_land.wav");
+SOUND(VEH_SPIDERBOT_STRAFE, "vehicles/spiderbot_strafe.wav");
+SOUND(VEH_SPIDERBOT_WALK, "vehicles/spiderbot_walk.wav");
+
+SOUND(NADE_BEEP, "overkill/grenadebip.ogg");
+
+SOUND(BUFF_LOST, "relics/relic_effect.wav");
+
+SOUND(POWEROFF, "misc/poweroff.wav");
+SOUND(POWERUP, "misc/powerup.ogg");
+SOUND(SHIELD_RESPAWN, "misc/shield_respawn.wav");
+SOUND(STRENGTH_RESPAWN, "misc/strength_respawn.wav");
+
+SOUND(ARMOR25, "misc/armor25.wav");
+SOUND(ARMORIMPACT, "misc/armorimpact.wav");
+SOUND(BODYIMPACT1, "misc/bodyimpact1.wav");
+SOUND(BODYIMPACT2, "misc/bodyimpact2.wav");
+
+SOUND(ITEMPICKUP, "misc/itempickup.ogg");
+SOUND(ITEMRESPAWNCOUNTDOWN, "misc/itemrespawncountdown.ogg");
+SOUND(ITEMRESPAWN, "misc/itemrespawn.ogg");
+SOUND(MEGAHEALTH, "misc/megahealth.ogg");
+
+SOUND(LAVA, "player/lava.wav");
+SOUND(SLIME, "player/slime.wav");
+
+SOUND(GIB, "misc/gib.wav");
+SOUND(GIB_SPLAT01, "misc/gib_splat01.wav");
+SOUND(GIB_SPLAT02, "misc/gib_splat02.wav");
+SOUND(GIB_SPLAT03, "misc/gib_splat03.wav");
+SOUND(GIB_SPLAT04, "misc/gib_splat04.wav");
+Sound SND_GIB_SPLAT_RANDOM() {
+ return Sounds[SND_GIB_SPLAT01.m_id + floor(prandom() * 4)];
+}
+
+SOUND(HIT, "misc/hit.wav");
+SOUND(TYPEHIT, "misc/typehit.wav");
+
+SOUND(SPAWN, "misc/spawn.ogg");
+
+SOUND(TALK, "misc/talk.wav");
+
+SOUND(TELEPORT, "misc/teleport.ogg");
+
+SOUND(INVSHOT, "misc/invshot.wav");
+
+SOUND(JETPACK_FLY, "misc/jetpack_fly.ogg");
--- /dev/null
+#ifndef SOUNDS_ALL_H
+#define SOUNDS_ALL_H
+
+#include "../teams.qh"
+
+// Play all sounds via sound7, for access to the extra channels.
+// Otherwise, channels 8 to 15 would be blocked for a weird QW feature.
+#ifdef SVQC
+ #define _sound(e, c, s, v, a) do { \
+ entity __e = e; \
+ if (!sound_allowed(MSG_BROADCAST, __e)) break; \
+ sound7(__e, c, s, v, a, 0, 0); \
+ } while (0)
+#else
+ #define _sound(e, c, s, v, a) sound7(e, c, s, v, a, 0, 0)
+#endif
+#define sound(e, c, s, v, a) _sound(e, c, s.sound_str(), v, a)
+// Used in places where a string is required
+#define SND(id) (SND_##id.sound_str())
+
+REGISTRY(Sounds, BIT(8))
+REGISTER_REGISTRY(RegisterSounds)
+
+CLASS(Sound, Object)
+ ATTRIB(Sound, m_id, int, 0)
+ ATTRIB(Sound, sound_str, string(), func_null)
+ CONSTRUCTOR(Sound, string() path)
+ {
+ CONSTRUCT(Sound);
+ this.sound_str = path;
+ }
+ METHOD(Sound, sound_precache, void(entity this)) {
+ string s = this.sound_str();
+ if (s && s != "" && !fexists(strcat("sound/", s))) {
+ LOG_WARNINGF("Missing sound: \"%s\"\n", s);
+ return;
+ }
+ LOG_TRACEF("precache_sound(\"%s\")\n", s);
+ precache_sound(s);
+ }
+ENDCLASS(Sound)
+
+#define SOUND(name, path) \
+ string SND_##name##_get() { return path; } \
+ REGISTER(RegisterSounds, SND, Sounds, name, m_id, NEW(Sound, SND_##name##_get))
+
+STATIC_INIT(RegisterSounds_precache) {
+ FOREACH(Sounds, true, LAMBDA({
+ it.sound_precache(it);
+ }));
+}
+
+SOUND(Null, "misc/null.wav");
+#include "all.inc"
+
+#endif
const int STAT_MOVEVARS_FRICTION_SLICK = 191;
const int STAT_MOVEVARS_FRICTION_ONLAND = 192;
const int STAT_MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS = 193;
-// 194 empty?
+const int STAT_MOVEVARS_TRACK_CANJUMP = 194;
// 195 empty?
const int STAT_DOUBLEJUMP = 196;
-const int STAT_MOVEVARS_TRACK_CANJUMP = 197;
+const int STAT_MOVEVARS_CL_TRACK_CANJUMP = 197;
const int STAT_MULTIJUMP_ADD = 198;
const int STAT_MULTIJUMP_SPEED = 199;
const int STAT_MULTIJUMP = 200;
#ifdef SVQC
.float height;
void func_bobbing_controller_think()
-{
+{SELFPARAM();
vector v;
self.nextthink = time + 0.1;
dmg : Do this mutch dmg every .dmgtime intervall when blocked
dmgtime : See above.
*/
-void spawnfunc_func_bobbing()
+spawnfunc(func_bobbing)
{
entity controller;
if (self.noise != "")
#include "../../../server/g_subs.qh"
#include "../../../server/g_damage.qh"
#include "../../../server/bot/bot.qh"
-#include "../../common/csqcmodel_settings.qh"
+#include "../../../common/csqcmodel_settings.qh"
#include "../../../csqcmodellib/sv_model.qh"
#include "../../../server/weapons/common.qh"
// - basically func_assault_destructible for general gameplay use
//
void LaunchDebris (string debrisname, vector force)
-{
+{SELFPARAM();
entity dbr = spawn();
setorigin(dbr, self.absmin
+ '1 0 0' * random() * (self.absmax.x - self.absmin.x)
+ '0 1 0' * random() * (self.absmax.y - self.absmin.y)
+ '0 0 1' * random() * (self.absmax.z - self.absmin.z));
- setmodel (dbr, debrisname );
+ _setmodel (dbr, debrisname );
dbr.skin = self.debrisskin;
dbr.colormap = self.colormap; // inherit team colors
dbr.owner = self; // do not be affected by our own explosion
}
void func_breakable_colormod()
-{
+{SELFPARAM();
float h;
if (!(self.spawnflags & 2))
return;
else
self.colormod = '1 1 1';
- CSQCMODEL_AUTOUPDATE();
+ CSQCMODEL_AUTOUPDATE(self);
}
void func_breakable_look_destroyed()
-{
+{SELFPARAM();
float floorZ;
if(self.solid == SOLID_BSP) // in case a misc_follow moved me, save the current origin first
setorigin(self,((self.absmax+self.absmin)*.5));
self.origin_z = floorZ;
}
- setmodel(self, self.mdl_dead);
+ _setmodel(self, self.mdl_dead);
self.effects &= ~EF_NODRAW;
}
- CSQCMODEL_AUTOUPDATE();
+ CSQCMODEL_AUTOUPDATE(self);
self.solid = SOLID_NOT;
}
void func_breakable_look_restore()
-{
- setmodel(self, self.mdl);
+{SELFPARAM();
+ _setmodel(self, self.mdl);
self.effects &= ~EF_NODRAW;
if(self.mdl_dead != "") // only do this if we use mdl_dead, to behave better with misc_follow
setorigin(self, self.dropped_origin);
- CSQCMODEL_AUTOUPDATE();
+ CSQCMODEL_AUTOUPDATE(self);
self.solid = SOLID_BSP;
}
void func_breakable_behave_destroyed()
-{
+{SELFPARAM();
self.health = self.max_health;
self.takedamage = DAMAGE_NO;
self.bot_attack = false;
}
void func_breakable_behave_restore()
-{
+{SELFPARAM();
self.health = self.max_health;
if(self.sprite)
{
self.nextthink = 0; // cancel auto respawn
func_breakable_colormod();
if (self.noise1)
- sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
+ _sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
}
void func_breakable_init_for_player(entity player)
-{
+{SELFPARAM();
if (self.noise1 && self.state == 0 && clienttype(player) == CLIENTTYPE_REAL)
{
msg_entity = player;
}
void func_breakable_destroyed()
-{
+{SELFPARAM();
func_breakable_look_destroyed();
func_breakable_behave_destroyed();
- CSQCMODEL_AUTOUPDATE();
+ CSQCMODEL_AUTOUPDATE(self);
}
void func_breakable_restore()
-{
+{SELFPARAM();
func_breakable_look_restore();
func_breakable_behave_restore();
- CSQCMODEL_AUTOUPDATE();
+ CSQCMODEL_AUTOUPDATE(self);
}
vector debrisforce; // global, set before calling this
-void func_breakable_destroy() {
+void func_breakable_destroy()
+{SELFPARAM();
float n, i;
string oldmsg;
func_breakable_destroyed();
if(self.noise)
- sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
+ _sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
if(self.dmg)
RadiusDamage(self, activator, self.dmg, self.dmg_edge, self.dmg_radius, self, world, self.dmg_force, DEATH_HURTTRIGGER, world);
}
void func_breakable_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
if(self.state == 1)
return;
if(self.spawnflags & DOOR_NOSPLASH)
}
void func_breakable_reset()
-{
+{SELFPARAM();
self.team = self.team_saved;
func_breakable_look_restore();
if(self.spawnflags & 1)
else
func_breakable_behave_restore();
- CSQCMODEL_AUTOUPDATE();
+ CSQCMODEL_AUTOUPDATE(self);
}
// destructible walls that can be used to trigger target_objective_decrease
-void spawnfunc_func_breakable()
+spawnfunc(func_breakable)
{
float n, i;
if(!self.health)
self.init_for_player_needed = 1;
self.init_for_player = func_breakable_init_for_player;
- CSQCMODEL_AUTOINIT();
+ CSQCMODEL_AUTOINIT(self);
}
// for use in maps with a "model" key set
-void spawnfunc_misc_breakablemodel() {
- spawnfunc_func_breakable();
+spawnfunc(misc_breakablemodel) {
+ spawnfunc_func_breakable(this);
}
#endif
#define TRIGGERS_FUNC_BREAKABLE_H
#ifdef SVQC
-void spawnfunc_func_breakable();
+spawnfunc(func_breakable);
#endif
#endif
void() button_return;
void button_wait()
-{
+{SELFPARAM();
self.state = STATE_TOP;
self.SUB_NEXTTHINK = self.SUB_LTIME + self.wait;
self.SUB_THINK = button_return;
}
void button_done()
-{
+{SELFPARAM();
self.state = STATE_BOTTOM;
}
void button_return()
-{
+{SELFPARAM();
self.state = STATE_DOWN;
SUB_CalcMove (self.pos1, TSPEED_LINEAR, self.speed, button_done);
self.frame = 0; // use normal textures
void button_fire()
-{
+{SELFPARAM();
self.health = self.max_health;
self.takedamage = DAMAGE_NO; // will be reset upon return
return;
if (self.noise != "")
- sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
+ _sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
self.state = STATE_UP;
SUB_CalcMove (self.pos2, TSPEED_LINEAR, self.speed, button_wait);
}
void button_reset()
-{
+{SELFPARAM();
self.health = self.max_health;
setorigin(self, self.pos1);
self.frame = 0; // use normal textures
}
void button_use()
-{
+{SELFPARAM();
if(self.active != ACTIVE_ACTIVE)
return;
}
void button_touch()
-{
+{SELFPARAM();
if (!other)
return;
if (!other.iscreature)
}
void button_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
if(self.spawnflags & DOOR_NOSPLASH)
if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
return;
2) metallic click
3) in-out
*/
-void spawnfunc_func_button()
+spawnfunc(func_button)
{
SetMovedir ();
void conveyor_think()
-{
+{SELFPARAM();
#ifdef CSQC
// TODO: check if this is what is causing the glitchiness when switching between them
float dt = time - self.move_time;
#ifdef SVQC
void conveyor_use()
-{
+{SELFPARAM();
self.state = !self.state;
self.SendFlags |= 2;
}
void conveyor_reset()
-{
+{SELFPARAM();
self.state = (self.spawnflags & 1);
self.SendFlags |= 2;
}
-bool conveyor_send(entity to, int sf)
+bool conveyor_send(entity this, entity to, int sf)
{
WriteByte(MSG_ENTITY, ENT_CLIENT_CONVEYOR);
WriteByte(MSG_ENTITY, sf);
}
void conveyor_init()
-{
+{SELFPARAM();
if (!self.speed)
self.speed = 200;
self.movedir = self.movedir * self.speed;
self.SendFlags |= 1;
}
-void spawnfunc_trigger_conveyor()
+spawnfunc(trigger_conveyor)
{
SetMovedir();
EXACTTRIGGER_INIT;
conveyor_init();
}
-void spawnfunc_func_conveyor()
+spawnfunc(func_conveyor)
{
SetMovedir();
InitMovingBrushTrigger();
#elif defined(CSQC)
+void conveyor_draw(entity this) { WITH(entity, self, this, conveyor_think()); }
+
void conveyor_init()
-{
- self.draw = conveyor_think;
+{SELFPARAM();
+ self.draw = conveyor_draw;
self.drawmask = MASK_NORMAL;
self.movetype = MOVETYPE_NONE;
}
void ent_conveyor()
-{
+{SELFPARAM();
float sf = ReadByte();
if(sf & 1)
void() door_rotating_go_up;
void door_blocked()
-{
+{SELFPARAM();
if((self.spawnflags & 8)
#ifdef SVQC
&& (other.takedamage != DAMAGE_NO)
}
void door_hit_top()
-{
+{SELFPARAM();
if (self.noise1 != "")
- sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
+ _sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
self.state = STATE_TOP;
if (self.spawnflags & DOOR_TOGGLE)
return; // don't come down automatically
}
void door_hit_bottom()
-{
+{SELFPARAM();
if (self.noise1 != "")
- sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
+ _sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
self.state = STATE_BOTTOM;
}
void door_go_down()
-{
+{SELFPARAM();
if (self.noise2 != "")
- sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+ _sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
if (self.max_health)
{
self.takedamage = DAMAGE_YES;
}
void door_go_up()
-{
+{SELFPARAM();
if (self.state == STATE_UP)
return; // already going up
}
if (self.noise2 != "")
- sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+ _sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
self.state = STATE_UP;
SUB_CalcMove (self.pos2, TSPEED_LINEAR, self.speed, door_hit_top);
*/
float door_check_keys(void)
-{
+{SELFPARAM();
local entity door;
if (other.key_door_messagetime <= time)
{
- play2(other, "misc/talk.wav");
+ play2(other, SND(TALK));
Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_LOCKED_ALSONEED, item_keys_keylist(door.itemkeys));
other.key_door_messagetime = time + 2;
}
// no keys were used
if (other.key_door_messagetime <= time)
{
- play2(other, "misc/talk.wav");
+ play2(other, SND(TALK));
Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_LOCKED_NEED, item_keys_keylist(door.itemkeys));
other.key_door_messagetime = time + 2;
{
#ifdef SVQC
// door is now unlocked
- play2(other, "misc/talk.wav");
+ play2(other, SND(TALK));
Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_UNLOCKED);
#endif
return true;
}
void door_fire()
-{
- entity oself;
+{SELFPARAM();
entity starte;
if (self.owner != self)
objerror ("door_fire: self.owner != self");
- oself = self;
-
if (self.spawnflags & DOOR_TOGGLE)
{
if (self.state == STATE_UP || self.state == STATE_TOP)
{
door_rotating_go_down ();
}
- self = self.enemy;
+ setself(self.enemy);
} while ( (self != starte) && (self != world) );
- self = oself;
+ setself(this);
return;
}
}
door_rotating_go_up ();
}
}
- self = self.enemy;
+ setself(self.enemy);
} while ( (self != starte) && (self != world) );
- self = oself;
+ setself(this);
}
void door_use()
-{
- entity oself;
-
+{SELFPARAM();
//dprint("door_use (model: ");dprint(self.model);dprint(")\n");
if (self.owner)
{
- oself = self;
- self = self.owner;
- door_fire ();
- self = oself;
+ WITH(entity, self, self.owner, door_fire());
}
}
void door_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
- entity oself;
+{SELFPARAM();
if(self.spawnflags & DOOR_NOSPLASH)
if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
return;
if (self.health <= 0)
{
- oself = self;
- self = self.owner;
- self.health = self.max_health;
- self.takedamage = DAMAGE_NO; // wil be reset upon return
- door_use ();
- self = oself;
+ self.owner.health = self.owner.max_health;
+ self.owner.takedamage = DAMAGE_NO; // wil be reset upon return
+ WITH(entity, self, self.owner, door_use());
}
}
*/
void door_touch()
-{
+{SELFPARAM();
if (!IS_PLAYER(other))
return;
if (self.owner.attack_finished_single > time)
{
if (IS_CLIENT(other))
centerprint(other, self.owner.message);
- play2(other, "misc/talk.wav");
+ play2(other, SND(TALK));
}
#endif
}
void door_generic_plat_blocked()
-{
+{SELFPARAM();
if((self.spawnflags & 8) && (other.takedamage != DAMAGE_NO)) { // KIll Kill Kill!!
#ifdef SVQC
}
void door_rotating_hit_top()
-{
+{SELFPARAM();
if (self.noise1 != "")
- sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
+ _sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
self.state = STATE_TOP;
if (self.spawnflags & DOOR_TOGGLE)
return; // don't come down automatically
}
void door_rotating_hit_bottom()
-{
+{SELFPARAM();
if (self.noise1 != "")
- sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
+ _sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
if (self.lip==666) // self.lip is used to remember reverse opening direction for door_rotating
{
self.pos2 = '0 0 0' - self.pos2;
}
void door_rotating_go_down()
-{
+{SELFPARAM();
if (self.noise2 != "")
- sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+ _sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
if (self.max_health)
{
self.takedamage = DAMAGE_YES;
}
void door_rotating_go_up()
-{
+{SELFPARAM();
if (self.state == STATE_UP)
return; // already going up
return;
}
if (self.noise2 != "")
- sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+ _sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
self.state = STATE_UP;
SUB_CalcAngleMove (self.pos2, TSPEED_LINEAR, self.speed, door_rotating_hit_top);
*/
void door_trigger_touch()
-{
+{SELFPARAM();
if (other.health < 1)
#ifdef SVQC
if (!((other.iscreature || (other.flags & FL_PROJECTILE)) && !PHYS_DEAD(other)))
activator = other;
- self = self.owner;
+ setself(self.owner);
door_use ();
}
void spawn_field(vector fmins, vector fmaxs)
-{
+{SELFPARAM();
entity trigger;
vector t1 = fmins, t2 = fmaxs;
*/
entity LinkDoors_nextent(entity cur, entity near, entity pass)
-{
+{SELFPARAM();
while((cur = find(cur, classname, self.classname)) && ((cur.spawnflags & 4) || cur.enemy))
{
}
void door_link();
#endif
void LinkDoors()
-{
+{SELFPARAM();
entity t;
vector cmins, cmaxs;
*/
float door_send(entity to, float sf)
-{
+{SELFPARAM();
WriteByte(MSG_ENTITY, ENT_CLIENT_DOOR);
WriteByte(MSG_ENTITY, sf);
#endif
void door_init_startopen()
-{
+{SELFPARAM();
SUB_SETORIGIN(self, self.pos2);
self.pos2 = self.pos1;
self.pos1 = self.origin;
}
void door_reset()
-{
+{SELFPARAM();
SUB_SETORIGIN(self, self.pos1);
self.SUB_VELOCITY = '0 0 0';
self.state = STATE_BOTTOM;
#ifdef SVQC
// spawnflags require key (for now only func_door)
-void spawnfunc_func_door()
+spawnfunc(func_door)
{
// Quake 1 keys compatibility
if (self.spawnflags & SPAWNFLAGS_GOLD_KEY)
#elif defined(CSQC)
-void door_draw()
+void door_draw(entity this)
{
Movetype_Physics_NoMatchServer();
- trigger_draw_generic();
+ trigger_draw_generic(this);
}
void ent_door()
-{
+{SELFPARAM();
float sf = ReadByte();
if(sf & SF_TRIGGER_INIT)
self.spawnflags = ReadByte();
self.mdl = strzone(ReadString());
- setmodel(self, self.mdl);
+ _setmodel(self, self.mdl);
trigger_common_read(true);
*/
void door_rotating_reset()
-{
+{SELFPARAM();
self.angles = self.pos1;
self.avelocity = '0 0 0';
self.state = STATE_BOTTOM;
}
void door_rotating_init_startopen()
-{
+{SELFPARAM();
self.angles = self.movedir;
self.pos2 = '0 0 0';
self.pos1 = self.movedir;
}
-void spawnfunc_func_door_rotating()
+spawnfunc(func_door_rotating)
{
//if (!self.deathtype) // map makers can override this
const float SECRET_YES_SHOOT = 16; // shootable even if targeted
void fd_secret_use()
-{
+{SELFPARAM();
float temp;
string message_save;
// Make a sound, wait a little...
if (self.noise1 != "")
- sound(self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
+ _sound(self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
self.SUB_NEXTTHINK = self.SUB_LTIME + 0.1;
temp = 1 - (self.spawnflags & SECRET_1ST_LEFT); // 1 or -1
self.dest2 = self.dest1 + v_forward * self.t_length;
SUB_CalcMove(self.dest1, TSPEED_LINEAR, self.speed, fd_secret_move1);
if (self.noise2 != "")
- sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+ _sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
}
void fd_secret_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
// Wait after first movement...
void fd_secret_move1()
-{
+{SELFPARAM();
self.SUB_NEXTTHINK = self.SUB_LTIME + 1.0;
self.think = fd_secret_move2;
if (self.noise3 != "")
- sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM);
+ _sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM);
}
// Start moving sideways w/sound...
void fd_secret_move2()
-{
+{SELFPARAM();
if (self.noise2 != "")
- sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+ _sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
SUB_CalcMove(self.dest2, TSPEED_LINEAR, self.speed, fd_secret_move3);
}
// Wait here until time to go back...
void fd_secret_move3()
-{
+{SELFPARAM();
if (self.noise3 != "")
- sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM);
+ _sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM);
if (!(self.spawnflags & SECRET_OPEN_ONCE))
{
self.SUB_NEXTTHINK = self.SUB_LTIME + self.wait;
// Move backward...
void fd_secret_move4()
-{
+{SELFPARAM();
if (self.noise2 != "")
- sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+ _sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
SUB_CalcMove(self.dest1, TSPEED_LINEAR, self.speed, fd_secret_move5);
}
// Wait 1 second...
void fd_secret_move5()
-{
+{SELFPARAM();
self.SUB_NEXTTHINK = self.SUB_LTIME + 1.0;
self.think = fd_secret_move6;
if (self.noise3 != "")
- sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM);
+ _sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM);
}
void fd_secret_move6()
-{
+{SELFPARAM();
if (self.noise2 != "")
- sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+ _sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
SUB_CalcMove(self.oldorigin, TSPEED_LINEAR, self.speed, fd_secret_done);
}
void fd_secret_done()
-{
+{SELFPARAM();
if (self.spawnflags&SECRET_YES_SHOOT)
{
self.health = 10000;
//self.th_pain = fd_secret_use;
}
if (self.noise3 != "")
- sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM);
+ _sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM);
}
void secret_blocked()
-{
+{SELFPARAM();
if (time < self.attack_finished_single)
return;
self.attack_finished_single = time + 0.5;
================
*/
void secret_touch()
-{
+{SELFPARAM();
if (!other.iscreature)
return;
if (self.attack_finished_single > time)
{
if (IS_CLIENT(other))
centerprint(other, self.message);
- play2(other, "misc/talk.wav");
+ play2(other, SND(TALK));
}
}
void secret_reset()
-{
+{SELFPARAM();
if (self.spawnflags&SECRET_YES_SHOOT)
{
self.health = 10000;
3) base
*/
-void spawnfunc_func_door_secret()
+spawnfunc(func_door_secret)
{
/*if (!self.deathtype) // map makers can override this
self.deathtype = " got in the way";*/
*/
void func_fourier_controller_think()
-{
+{SELFPARAM();
vector v;
float n, i, t;
self.owner.velocity = (v - self.owner.origin) * 10;
}
-void spawnfunc_func_fourier()
+spawnfunc(func_fourier)
{
entity controller;
if (self.noise != "")
void func_ladder_touch()
-{
+{SELFPARAM();
#ifdef SVQC
if (!other.iscreature)
return;
}
#ifdef SVQC
-float func_ladder_send(entity to, float sf)
+bool func_ladder_send(entity this, entity to, float sf)
{
WriteByte(MSG_ENTITY, ENT_CLIENT_LADDER);
//self.model = "null";
}
-void spawnfunc_func_ladder()
+spawnfunc(func_ladder)
{
self.mdl = self.model;
EXACTTRIGGER_INIT;
func_ladder_link();
}
-void spawnfunc_func_water()
+spawnfunc(func_water)
{
self.mdl = self.model;
EXACTTRIGGER_INIT;
.float speed;
void ent_func_ladder()
-{
+{SELFPARAM();
self.classname = strzone(ReadString());
self.skin = ReadByte();
self.speed = ReadByte();
#ifdef SVQC
.float freq;
void func_pendulum_controller_think()
-{
+{SELFPARAM();
float v;
self.nextthink = time + 0.1;
}
}
-void spawnfunc_func_pendulum()
+spawnfunc(func_pendulum)
{
entity controller;
if (self.noise != "")
}
float plat_send(entity to, float sf)
-{
+{SELFPARAM();
WriteByte(MSG_ENTITY, ENT_CLIENT_PLAT);
WriteByte(MSG_ENTITY, sf);
//Net_LinkEntity(self, 0, false, plat_send);
}
-void spawnfunc_func_plat()
+spawnfunc(func_plat)
{
if (self.sounds == 0)
self.sounds = 2;
InitializeEntity(self, plat_delayedinit, INITPRIO_FINDTARGET);
}
#elif defined(CSQC)
-void plat_draw()
+void plat_draw(entity this)
{
Movetype_Physics_NoMatchServer();
//Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
}
void ent_plat()
-{
+{SELFPARAM();
float sf = ReadByte();
if(sf & SF_TRIGGER_INIT)
self.spawnflags = ReadByte();
self.model = strzone(ReadString());
- setmodel(self, self.model);
+ _setmodel(self, self.model);
trigger_common_read(true);
#ifdef SVQC
// NOTE: also contains func_sparks
-float pointparticles_SendEntity(entity to, float fl)
+bool pointparticles_SendEntity(entity this, entity to, float fl)
{
WriteByte(MSG_ENTITY, ENT_CLIENT_POINTPARTICLES);
}
void pointparticles_use()
-{
+{SELFPARAM();
self.state = !self.state;
self.SendFlags |= 2;
}
void pointparticles_think()
-{
+{SELFPARAM();
if(self.origin != self.oldorigin)
{
self.SendFlags |= 4;
}
void pointparticles_reset()
-{
+{SELFPARAM();
if(self.spawnflags & 1)
self.state = 1;
else
self.state = 0;
}
-void spawnfunc_func_pointparticles()
+spawnfunc(func_pointparticles)
{
if(self.model != "")
- setmodel(self, self.model);
+ _setmodel(self, self.model);
if(self.noise != "")
precache_sound (self.noise);
self.nextthink = time;
}
-void spawnfunc_func_sparks()
+spawnfunc(func_sparks)
{
// self.cnt is the amount of sparks that one burst will spawn
if(self.cnt < 1) {
self.wait = 0;
self.cnt = 0; // use mdl
- spawnfunc_func_pointparticles();
+ spawnfunc_func_pointparticles(this);
}
#elif defined(CSQC)
-void Draw_PointParticles()
+void Draw_PointParticles(entity this)
{
float n, i, fail;
vector p;
if(self.noise != "")
{
setorigin(self, p);
- sound(self, CH_AMBIENT, self.noise, VOL_BASE * self.volume, self.atten);
+ _sound(self, CH_AMBIENT, self.noise, VOL_BASE * self.volume, self.atten);
}
self.just_toggled = 0;
}
}
void Ent_PointParticles_Remove()
-{
+{SELFPARAM();
if(self.noise)
strunzone(self.noise);
self.noise = string_null;
}
void Ent_PointParticles()
-{
+{SELFPARAM();
float i;
vector v;
int f = ReadByte();
#ifdef SVQC
-float rainsnow_SendEntity(entity to, float sf)
+bool rainsnow_SendEntity(entity this, entity to, float sf)
{
WriteByte(MSG_ENTITY, ENT_CLIENT_RAINSNOW);
WriteByte(MSG_ENTITY, self.state);
WriteShort(MSG_ENTITY, compressShortVector(self.dest));
WriteShort(MSG_ENTITY, self.count);
WriteByte(MSG_ENTITY, self.cnt);
- return 1;
+ return true;
}
/*QUAKED spawnfunc_func_rain (0 .5 .8) ?
"count"
adjusts density, this many particles fall every second for a 1024x1024 area, default is 2000
*/
-void spawnfunc_func_rain()
+spawnfunc(func_rain)
{
self.dest = self.velocity;
self.velocity = '0 0 0';
"count"
adjusts density, this many particles fall every second for a 1024x1024 area, default is 2000
*/
-void spawnfunc_func_snow()
+spawnfunc(func_snow)
{
self.dest = self.velocity;
self.velocity = '0 0 0';
Net_LinkEntity(self, false, 0, rainsnow_SendEntity);
}
#elif defined(CSQC)
-void Draw_Rain()
+void Draw_Rain(entity this)
{
te_particlerain(self.origin + self.mins, self.origin + self.maxs, self.velocity, floor(self.count * drawframetime + random()), self.glow_color);
}
-void Draw_Snow()
+void Draw_Snow(entity this)
{
te_particlesnow(self.origin + self.mins, self.origin + self.maxs, self.velocity, floor(self.count * drawframetime + random()), self.glow_color);
}
void Ent_RainOrSnow()
-{
+{SELFPARAM();
self.impulse = ReadByte(); // Rain, Snow, or Whatever
self.origin_x = ReadCoord();
self.origin_y = ReadCoord();
#ifdef SVQC
void func_rotating_setactive(float astate)
-{
+{SELFPARAM();
if (astate == ACTIVE_TOGGLE)
{
dmgtime : See above.
*/
-void spawnfunc_func_rotating()
+spawnfunc(func_rotating)
{
if (self.noise != "")
{
#ifdef SVQC
-void spawnfunc_func_stardust()
+spawnfunc(func_stardust)
{
self.effects = EF_STARDUST;
- CSQCMODEL_AUTOINIT();
+ CSQCMODEL_AUTOINIT(self);
}
#endif
.float train_wait_turning;
void() train_next;
void train_wait()
-{
- entity oldself;
- oldself = self;
- self = self.enemy;
- SUB_UseTargets();
- self = oldself;
+{SELFPARAM();
+ WITH(entity, self, self.enemy, SUB_UseTargets());
self.enemy = world;
// if turning is enabled, the train will turn toward the next point while waiting
}
void train_next()
-{
+{SELFPARAM();
entity targ, cp = world;
vector cp_org = '0 0 0';
}
if(self.noise != "")
- sound(self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_IDLE);
+ _sound(self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_IDLE);
}
#ifdef SVQC
float train_send(entity to, float sf)
-{
+{SELFPARAM();
WriteByte(MSG_ENTITY, ENT_CLIENT_TRAIN);
WriteByte(MSG_ENTITY, sf);
}
void func_train_find()
-{
+{SELFPARAM();
entity targ;
targ = find(world, targetname, self.target);
self.target = targ.target;
target : targetname of first spawnfunc_path_corner (starts here)
*/
#ifdef SVQC
-void spawnfunc_func_train()
+spawnfunc(func_train)
{
if (self.noise != "")
precache_sound(self.noise);
// TODO make a reset function for this one
}
#elif defined(CSQC)
-void train_draw()
+void train_draw(entity this)
{
//Movetype_Physics_NoMatchServer();
Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
}
void ent_train()
-{
+{SELFPARAM();
float sf = ReadByte();
if(sf & SF_TRIGGER_INIT)
self.spawnflags = ReadByte();
self.model = strzone(ReadString());
- setmodel(self, self.model);
+ _setmodel(self, self.model);
trigger_common_read(true);
}
void func_vectormamamam_controller_think()
-{
+{SELFPARAM();
self.nextthink = time + 0.1;
if(self.owner.active != ACTIVE_ACTIVE)
}
void func_vectormamamam_findtarget()
-{
+{SELFPARAM();
if(self.target != "")
self.wp00 = find(world, targetname, self.target);
controller.think = func_vectormamamam_controller_think;
}
-void spawnfunc_func_vectormamamam()
+spawnfunc(func_vectormamamam)
{
if (self.noise != "")
{
#ifdef SVQC
bool corner_send(entity to, int sf)
-{
+{SELFPARAM();
WriteByte(MSG_ENTITY, ENT_CLIENT_CORNER);
WriteString(MSG_ENTITY, self.platmovetype);
//Net_LinkEntity(self, false, 0, corner_send);
}
-void spawnfunc_path_corner()
+spawnfunc(path_corner)
{
// setup values for overriding train movement
// if a second value does not exist, both start and end speeds are the single value specified
#elif defined(CSQC)
void corner_remove()
-{
+{SELFPARAM();
if(self.target) { strunzone(self.target); }
self.target = string_null;
}
void ent_corner()
-{
+{SELFPARAM();
self.platmovetype = strzone(ReadString());
self.origin_x = ReadCoord();
#ifdef SVQC
void follow_init()
-{
+{SELFPARAM();
entity src, dst;
src = world;
dst = world;
}
}
-void spawnfunc_misc_follow()
+spawnfunc(misc_follow)
{
InitializeEntity(self, follow_init, INITPRIO_FINDTARGET);
}
#if defined(CSQC)
#include "../../../client/_all.qh"
- #include "../../buffs.qh"
+ #include "../../buffs/all.qh"
#include "../../../csqcmodellib/interpolate.qh"
#include "../../../client/main.qh"
#include "../../../csqcmodellib/cl_model.qh"
#ifdef SVQC
.float modelscale;
void misc_laser_aim()
-{
+{SELFPARAM();
vector a;
if(self.enemy)
{
}
void misc_laser_init()
-{
+{SELFPARAM();
if(self.target != "")
self.enemy = find(world, targetname, self.target);
}
.entity pusher;
void misc_laser_think()
-{
+{SELFPARAM();
vector o;
- entity oldself;
entity hitent;
vector hitloc;
{
self.count = 1;
- oldself = self;
- self = self.enemy;
- activator = self.pusher;
- SUB_UseTargets();
- self = oldself;
+ activator = self.enemy.pusher;
+ WITH(entity, self, self.enemy, SUB_UseTargets());
}
}
else
{
self.count = 0;
- oldself = self;
- self = self.enemy;
- activator = self.pusher;
- SUB_UseTargets();
- self = oldself;
+ activator = self.enemy.pusher;
+ WITH(entity, self, self.enemy, SUB_UseTargets());
}
}
}
}
}
-float laser_SendEntity(entity to, float fl)
+bool laser_SendEntity(entity this, entity to, float fl)
{
WriteByte(MSG_ENTITY, ENT_CLIENT_LASER);
fl = fl - (fl & 0xF0); // use that bit to indicate finite length laser
damage per second (-1 for a laser that kills immediately)
*/
void laser_use()
-{
+{SELFPARAM();
self.state = !self.state;
self.SendFlags |= 4;
misc_laser_aim();
}
void laser_reset()
-{
+{SELFPARAM();
if(self.spawnflags & 1)
self.state = 1;
else
self.state = 0;
}
-void spawnfunc_misc_laser()
+spawnfunc(misc_laser)
{
if(self.mdl)
{
class(Laser) .float scale; // scaling factor of the thickness
class(Laser) .float modelscale; // scaling factor of the dlight
-void Draw_Laser()
+void Draw_Laser(entity this)
{
if(!self.state)
return;
}
void Ent_Laser()
-{
+{SELFPARAM();
InterpolateOrigin_Undo();
// 30 bytes, or 13 bytes for just moving
#ifdef SVQC
-void spawnfunc_info_teleport_destination (void)
+spawnfunc(info_teleport_destination)
{
self.classname = "info_teleport_destination";
objerror ("^3Teleport destination without a targetname");
}
-void spawnfunc_misc_teleporter_dest (void)
+spawnfunc(misc_teleporter_dest)
{
- spawnfunc_info_teleport_destination();
+ spawnfunc_info_teleport_destination(this);
}
-void spawnfunc_target_teleporter (void)
+spawnfunc(target_teleporter)
{
- spawnfunc_info_teleport_destination();
+ spawnfunc_info_teleport_destination(this);
}
#endif
void generic_plat_blocked()
-{
+{SELFPARAM();
#ifdef SVQC
if(self.dmg && other.takedamage != DAMAGE_NO)
{
}
void plat_spawn_inside_trigger()
-{
+{SELFPARAM();
entity trigger;
vector tmin, tmax;
}
void plat_hit_top()
-{
- sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
+{SELFPARAM();
+ _sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
self.state = 1;
self.SUB_THINK = plat_go_down;
}
void plat_hit_bottom()
-{
- sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
+{SELFPARAM();
+ _sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
self.state = 2;
}
void plat_go_down()
-{
- sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_NORM);
+{SELFPARAM();
+ _sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_NORM);
self.state = 3;
SUB_CalcMove (self.pos2, TSPEED_LINEAR, self.speed, plat_hit_bottom);
}
void plat_go_up()
-{
- sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_NORM);
+{SELFPARAM();
+ _sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_NORM);
self.state = 4;
SUB_CalcMove (self.pos1, TSPEED_LINEAR, self.speed, plat_hit_top);
}
void plat_center_touch()
-{
+{SELFPARAM();
#ifdef SVQC
if (!other.iscreature)
return;
return;
#endif
- self = self.enemy;
+ setself(self.enemy);
if (self.state == 2)
plat_go_up ();
else if (self.state == 1)
}
void plat_outside_touch()
-{
+{SELFPARAM();
#ifdef SVQC
if (!other.iscreature)
return;
return;
#endif
- self = self.enemy;
+ setself(self.enemy);
if (self.state == 1)
plat_go_down ();
}
void plat_trigger_use()
-{
+{SELFPARAM();
#ifdef SVQC
if (self.think)
return; // already activated
void plat_crush()
-{
+{SELFPARAM();
if((self.spawnflags & 4) && (other.takedamage != DAMAGE_NO))
{ // KIll Kill Kill!!
#ifdef SVQC
}
void plat_use()
-{
+{SELFPARAM();
self.use = func_null;
if (self.state != 4)
objerror ("plat_use: not in up state");
.string sound1, sound2;
void plat_reset()
-{
+{SELFPARAM();
IFTARGETED
{
setorigin (self, self.pos1);
*/
.float friction;
void SUB_Friction (void)
-{
+{SELFPARAM();
self.SUB_NEXTTHINK = time;
if(self.SUB_FLAGS & FL_ONGROUND)
self.SUB_VELOCITY = self.SUB_VELOCITY * (1 - frametime * self.friction);
}
void SUB_SetFade_Think (void)
-{
+{SELFPARAM();
if(self.alpha == 0)
self.alpha = 1;
self.SUB_THINK = SUB_SetFade_Think;
===============
*/
void SUB_CalcMoveDone (void)
-{
+{SELFPARAM();
// After moving, set origin to exact final destination
SUB_SETORIGIN (self, self.finaldest);
.float platmovetype_turn;
void SUB_CalcMove_controller_think (void)
-{
+{SELFPARAM();
entity oldself;
float traveltime;
float phasepos;
destangle_x = -destangle_x; // flip up / down orientation
// take the shortest distance for the angles
- SUB_ANGLES(self.owner)_x -= 360 * floor((SUB_ANGLES(self.owner)_x - destangle_x) / 360 + 0.5);
- SUB_ANGLES(self.owner)_y -= 360 * floor((SUB_ANGLES(self.owner)_y - destangle_y) / 360 + 0.5);
- SUB_ANGLES(self.owner)_z -= 360 * floor((SUB_ANGLES(self.owner)_z - destangle_z) / 360 + 0.5);
+ vector v = SUB_ANGLES(self.owner);
+ v.x -= 360 * floor((v.x - destangle_x) / 360 + 0.5);
+ v.y -= 360 * floor((v.y - destangle_y) / 360 + 0.5);
+ v.z -= 360 * floor((v.z - destangle_z) / 360 + 0.5);
+ SUB_ANGLES(self.owner) = v;
angloc = destangle - SUB_ANGLES(self.owner);
angloc = angloc * (1 / PHYS_INPUT_FRAMETIME); // so it arrives for the next frame
self.owner.SUB_AVELOCITY = angloc;
// derivative: delta + 2 * delta2 (e.g. for angle positioning)
oldself = self;
self.owner.SUB_THINK = self.think1;
- self = self.owner;
+ setself(self.owner);
remove(oldself);
self.SUB_THINK();
}
// TODO average too?
void SUB_CalcMove_Bezier (vector tcontrol, vector tdest, float tspeedtype, float tspeed, void() func)
-{
+{SELFPARAM();
float traveltime;
entity controller;
self.SUB_NEXTTHINK = self.SUB_LTIME + traveltime;
// invoke controller
- self = controller;
+ setself(controller);
self.think();
- self = self.owner;
+ setself(self.owner);
}
void SUB_CalcMove (vector tdest, float tspeedtype, float tspeed, void() func)
-{
+{SELFPARAM();
vector delta;
float traveltime;
}
void SUB_CalcMoveEnt (entity ent, vector tdest, float tspeedtype, float tspeed, void() func)
-{
- entity oldself;
-
- oldself = self;
- self = ent;
-
- SUB_CalcMove (tdest, tspeedtype, tspeed, func);
-
- self = oldself;
+{SELFPARAM();
+ WITH(entity, self, ent, SUB_CalcMove(tdest, tspeedtype, tspeed, func));
}
/*
===============
*/
void SUB_CalcAngleMoveDone (void)
-{
+{SELFPARAM();
// After rotating, set angle to exact final angle
self.angles = self.finalangle;
self.SUB_AVELOCITY = '0 0 0';
// FIXME: I fixed this function only for rotation around the main axes
void SUB_CalcAngleMove (vector destangle, float tspeedtype, float tspeed, void() func)
-{
+{SELFPARAM();
vector delta;
float traveltime;
}
void SUB_CalcAngleMoveEnt (entity ent, vector destangle, float tspeedtype, float tspeed, void() func)
-{
- entity oldself;
-
- oldself = self;
- self = ent;
-
- SUB_CalcAngleMove (destangle, tspeedtype, tspeed, func);
-
- self = oldself;
+{SELFPARAM();
+ WITH(entity, self, ent, SUB_CalcAngleMove (destangle, tspeedtype, tspeed, func));
}
#define SUB_FLAGS move_flags
void SUB_SETORIGIN(entity s, vector v)
- {
+ {SELFPARAM();
s.move_origin = v;
- entity oldself = self;
- self = s;
- _Movetype_LinkEdict(true);
- self = oldself;
+ WITH(entity, self, s, _Movetype_LinkEdict(true));
}
#endif
.entity chlevel_targ;
-void spawnfunc_target_changelevel_use()
+void target_changelevel_use()
{
+ SELFPARAM();
if(self.spawnflags & 2)
{
// simply don't react if a non-player triggers it
localcmd(strcat("changelevel ", self.chmap, "\n"));
}
-void spawnfunc_target_changelevel()
+spawnfunc(target_changelevel)
{
- self.use = spawnfunc_target_changelevel_use;
+ self.use = target_changelevel_use;
if(!self.count) { self.count = 0.7; }
}
#ifdef SVQC
-void spawnfunc_target_location()
+spawnfunc(target_location)
{
self.classname = "target_location";
// location name in netname
// eventually support: count, teamgame selectors, line of sight?
}
-void spawnfunc_info_location()
+spawnfunc(info_location)
{
self.classname = "target_location";
self.message = self.netname;
// when triggered, the music is overridden for activator until lifetime (or forever, if lifetime is 0)
// when targetname is not set, THIS ONE is default
void target_music_sendto(float to, float is)
-{
+{SELFPARAM();
WriteByte(to, SVC_TEMPENTITY);
WriteByte(to, TE_CSQC_TARGET_MUSIC);
WriteShort(to, num_for_edict(self));
WriteString(to, self.noise);
}
void target_music_reset()
-{
+{SELFPARAM();
if(self.targetname == "")
target_music_sendto(MSG_ALL, 1);
}
entity head;
FOR_EACH_SPEC(head) if(head.enemy == activator) { msg_entity = head; target_music_sendto(MSG_ONE, 1); }
}
-void spawnfunc_target_music()
+spawnfunc(target_music)
{
self.use = target_music_use;
self.reset = target_music_reset;
target_music_sendto(MSG_INIT, 0);
}
void TargetMusic_RestoreGame()
-{
- for(self = world; (self = find(self, classname, "target_music")); )
+{SELFPARAM();
+ for(entity e = world; (e = find(e, classname, "target_music")); )
{
+ setself(e);
if(self.targetname == "")
target_music_sendto(MSG_INIT, 1);
else
// spawnflags:
// 1 = START_OFF
// when triggered, it is disabled/enabled for everyone
-float trigger_music_SendEntity(entity to, float sf)
+bool trigger_music_SendEntity(entity this, entity to, float sf)
{
WriteByte(MSG_ENTITY, ENT_CLIENT_TRIGGER_MUSIC);
sf &= ~0x80;
return 1;
}
void trigger_music_reset()
-{
+{SELFPARAM();
self.cnt = !(self.spawnflags & 1);
self.SendFlags |= 0x80;
}
void trigger_music_use()
-{
+{SELFPARAM();
self.cnt = !self.cnt;
self.SendFlags |= 0x80;
}
-void spawnfunc_trigger_music()
+spawnfunc(trigger_music)
{
if(self.model != "")
- setmodel(self, self.model);
+ _setmodel(self, self.model);
if(!self.volume)
self.volume = 1;
if(!self.modelindex)
if(vol != vol0)
{
if(vol0 < 0)
- sound(e, CH_BGM_SINGLE, e.noise, vol, ATTEN_NONE); // restart
+ _sound(e, CH_BGM_SINGLE, e.noise, vol, ATTEN_NONE); // restart
else
- sound(e, CH_BGM_SINGLE, "", vol, ATTEN_NONE);
+ _sound(e, CH_BGM_SINGLE, "", vol, ATTEN_NONE);
e.lastvol = vol;
}
}
strunzone(e.noise);
e.noise = strzone(noi);
precache_sound(e.noise);
- sound(e, CH_BGM_SINGLE, e.noise, 0, ATTEN_NONE);
+ _sound(e, CH_BGM_SINGLE, e.noise, 0, ATTEN_NONE);
if(getsoundtime(e, CH_BGM_SINGLE) < 0)
{
LOG_TRACEF("Cannot initialize sound %s\n", e.noise);
}
void Ent_TriggerMusic_Think()
-{
+{SELFPARAM();
if(WarpZoneLib_BoxTouchesBrush(view_origin, view_origin, self, world))
{
music_trigger = self;
}
void Ent_TriggerMusic_Remove()
-{
+{SELFPARAM();
if(self.noise)
strunzone(self.noise);
self.noise = string_null;
}
void Ent_ReadTriggerMusic()
-{
+{SELFPARAM();
int f = ReadByte();
if(f & 4)
{
if(self.noise != s)
{
precache_sound(self.noise);
- sound(self, CH_BGM_SINGLE, self.noise, 0, ATTEN_NONE);
+ _sound(self, CH_BGM_SINGLE, self.noise, 0, ATTEN_NONE);
if(getsoundtime(self, CH_BGM_SINGLE) < 0)
{
LOG_TRACEF("Cannot initialize sound %s\n", self.noise);
float target_spawn_count;
void target_spawn_helper_setmodel()
-{
- setmodel(self, self.model);
+{SELFPARAM();
+ _setmodel(self, self.model);
}
void target_spawn_helper_setsize()
-{
+{SELFPARAM();
setsize(self, self.mins, self.maxs);
}
void target_spawn_edit_entity(entity e, string msg, entity kt, entity t2, entity t3, entity t4, entity act)
-{
+{SELFPARAM();
float i, n, valuefieldpos;
string key, value, valuefield, valueoffset, valueoffsetrandom;
entity valueent;
vector data, data2;
- entity oldself;
entity oldactivator;
n = tokenize_console(msg);
value = strcat("target_spawn_helper", value);
putentityfieldstring(target_spawn_spawnfunc_field, e, value);
- oldself = self;
oldactivator = activator;
- self = e;
activator = act;
-
- self.target_spawn_spawnfunc();
-
- self = oldself;
+ WITH(entity, self, e, e.target_spawn_spawnfunc());
activator = oldactivator;
// We called an external function, so we have to re-tokenize msg.
}
void target_spawn_useon(entity e)
-{
+{SELFPARAM();
self.target_spawn_activator = activator;
target_spawn_edit_entity(
e,
}
float target_spawn_cancreate()
-{
+{SELFPARAM();
float c;
entity e;
}
void target_spawn_use()
-{
+{SELFPARAM();
entity e;
if(self.target == "")
if(!target_spawn_cancreate())
return;
e = spawn();
+ e.spawnfunc_checked = true;
target_spawn_useon(e);
e.target_spawn_id = self.target_spawn_id;
}
}
void target_spawn_spawnfirst()
-{
+{SELFPARAM();
activator = self.target_spawn_activator;
if(self.spawnflags & 2)
target_spawn_use();
}
}
-void spawnfunc_target_spawn()
+spawnfunc(target_spawn)
{
initialize_field_db();
self.use = target_spawn_use;
// TODO add a way to do looped sounds with sound(); then complete this entity
void target_speaker_use_off();
void target_speaker_use_activator()
-{
+{SELFPARAM();
if (!IS_REAL_CLIENT(activator))
return;
string snd;
if(substring(self.noise, 0, 1) == "*")
{
- var .string sample;
- sample = GetVoiceMessageSampleField(substring(self.noise, 1, -1));
+ var .string sample = GetVoiceMessageSampleField(substring(self.noise, 1, -1));
if(GetPlayerSoundSampleField_notFound)
- snd = "misc/null.wav";
- else if(activator.sample == "")
- snd = "misc/null.wav";
+ snd = SND(Null);
+ else if(activator.(sample) == "")
+ snd = SND(Null);
else
{
- tokenize_console(activator.sample);
+ tokenize_console(activator.(sample));
float n;
n = stof(argv(1));
if(n > 0)
soundto(MSG_ONE, self, CH_TRIGGER, snd, VOL_BASE * self.volume, self.atten);
}
void target_speaker_use_on()
-{
+{SELFPARAM();
string snd;
if(substring(self.noise, 0, 1) == "*")
{
- var .string sample;
- sample = GetVoiceMessageSampleField(substring(self.noise, 1, -1));
+ var .string sample = GetVoiceMessageSampleField(substring(self.noise, 1, -1));
if(GetPlayerSoundSampleField_notFound)
- snd = "misc/null.wav";
- else if(activator.sample == "")
- snd = "misc/null.wav";
+ snd = SND(Null);
+ else if(activator.(sample) == "")
+ snd = SND(Null);
else
{
- tokenize_console(activator.sample);
+ tokenize_console(activator.(sample));
float n;
n = stof(argv(1));
if(n > 0)
}
else
snd = self.noise;
- sound(self, CH_TRIGGER_SINGLE, snd, VOL_BASE * self.volume, self.atten);
+ _sound(self, CH_TRIGGER_SINGLE, snd, VOL_BASE * self.volume, self.atten);
if(self.spawnflags & 3)
self.use = target_speaker_use_off;
}
void target_speaker_use_off()
-{
- sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASE * self.volume, self.atten);
+{SELFPARAM();
+ sound(self, CH_TRIGGER_SINGLE, SND_Null, VOL_BASE * self.volume, self.atten);
self.use = target_speaker_use_on;
}
void target_speaker_reset()
-{
+{SELFPARAM();
if(self.spawnflags & 1) // LOOPED_ON
{
if(self.use == target_speaker_use_on)
}
}
-void spawnfunc_target_speaker()
+spawnfunc(target_speaker)
{
// TODO: "*" prefix to sound file name
// TODO: wait and random (just, HOW? random is not a field)
}
void target_voicescript_use()
-{
+{SELFPARAM();
if(activator.voicescript != self)
{
activator.voicescript = self;
}
}
-void spawnfunc_target_voicescript()
+spawnfunc(target_voicescript)
{
// netname: directory of the sound files
// message: list of "sound file" duration "sound file" duration, a *, and again a list
}
void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax, float tflags)
-{
+{SELFPARAM();
entity telefragger;
vector from;
if(self.pushltime < time) // only show one teleport effect per teleporter per 0.2 seconds, for better fps
{
if(tflags & TELEPORT_FLAG_SOUND)
- sound (player, CH_TRIGGER, "misc/teleport.wav", VOL_BASE, ATTEN_NORM);
+ sound (player, CH_TRIGGER, SND_TELEPORT, VOL_BASE, ATTEN_NORM);
if(tflags & TELEPORT_FLAG_PARTICLES)
{
Send_Effect(EFFECT_TELEPORT, player.origin, '0 0 0', 1);
}
void teleport_findtarget (void)
-{
+{SELFPARAM();
entity e;
float n;
}
void WarpZone_PostTeleportPlayer_Callback(entity pl)
-{
+{SELFPARAM();
makevectors(pl.angles);
Reset_ArcBeam(pl, v_forward);
UpdateCSQCProjectileAfterTeleport(pl);
{
- entity oldself = self;
- self = pl;
- anticheat_fixangle();
- self = oldself;
+ WITH(entity, self, pl, anticheat_fixangle());
}
// "disown" projectiles after teleport
if(pl.owner)
#ifdef SVQC
void counter_use()
-{
+{SELFPARAM();
self.count -= 1;
if (self.count < 0)
return;
}
void counter_reset()
-{
+{SELFPARAM();
self.count = self.cnt;
multi_reset();
}
After the counter has been triggered "count" times (default 2), it will fire all of it's targets and remove itself.
*/
-void spawnfunc_trigger_counter()
+spawnfunc(trigger_counter)
{
self.wait = -1;
if (!self.count)
#ifdef SVQC
void delay_use()
-{
+{SELFPARAM();
self.think = SUB_UseTargets;
self.nextthink = self.wait;
}
void delay_reset()
-{
+{SELFPARAM();
self.think = func_null;
self.nextthink = 0;
}
-void spawnfunc_trigger_delay()
+spawnfunc(trigger_delay)
{
if(!self.wait)
self.wait = 1;
#ifdef SVQC
void trigger_disablerelay_use()
-{
+{SELFPARAM();
entity e;
float a, b;
LOG_INFO("Invalid use of trigger_disablerelay: ", ftos(a), " relays were on, ", ftos(b), " relays were off!\n");
}
-void spawnfunc_trigger_disablerelay()
+spawnfunc(trigger_disablerelay)
{
self.use = trigger_disablerelay_use;
}
"Flip-flop" trigger gate... lets only every second trigger event through
*/
void flipflop_use()
-{
+{SELFPARAM();
self.state = !self.state;
if(self.state)
SUB_UseTargets();
}
-void spawnfunc_trigger_flipflop()
+void _spawnfunc_trigger_flipflop();
+spawnfunc(trigger_flipflop)
{
if(self.spawnflags & 1)
self.state = 1;
self.use = flipflop_use;
- self.reset = spawnfunc_trigger_flipflop; // perfect resetter
+ self.reset = _spawnfunc_trigger_flipflop; // perfect resetter
}
+void _spawnfunc_trigger_flipflop() { SELFPARAM(); spawnfunc_trigger_flipflop(this); }
+
#endif
#ifdef SVQC
void gamestart_use()
-{
+{SELFPARAM();
activator = self;
SUB_UseTargets();
remove(self);
}
-void spawnfunc_trigger_gamestart()
+void _spawnfunc_trigger_gamestart();
+spawnfunc(trigger_gamestart)
{
self.use = gamestart_use;
- self.reset2 = spawnfunc_trigger_gamestart;
+ self.reset2 = _spawnfunc_trigger_gamestart;
if(self.wait)
{
else
InitializeEntity(self, gamestart_use, INITPRIO_FINDTARGET);
}
+void _spawnfunc_trigger_gamestart() { SELFPARAM(); spawnfunc_trigger_gamestart(this); }
+
#endif
own.trigger_gravity_check = world;
}
void trigger_gravity_check_think()
-{
+{SELFPARAM();
// This spawns when a player enters the gravity zone and checks if he left.
// Each frame, self.count is set to 2 by trigger_gravity_touch() and decreased by 1 here.
// It the player has left the gravity trigger, this will be allowed to reach 0 and indicate that.
}
void trigger_gravity_use()
-{
+{SELFPARAM();
self.state = !self.state;
}
void trigger_gravity_touch()
-{
+{SELFPARAM();
float g;
if(self.state != true)
{
other.gravity = g;
if(self.noise != "")
- sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
+ _sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
UpdateCSQCProjectile(self.owner);
}
}
-void spawnfunc_trigger_gravity()
+spawnfunc(trigger_gravity)
{
if(self.gravity == 1)
return;
#ifdef SVQC
.float triggerhealtime;
void trigger_heal_touch()
-{
+{SELFPARAM();
if (self.active != ACTIVE_ACTIVE)
return;
{
other.health = min(other.health + self.health, self.max_health);
other.pauserothealth_finished = max(other.pauserothealth_finished, time + autocvar_g_balance_pause_health_rot);
- sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
+ _sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
}
}
}
}
-void spawnfunc_trigger_heal()
+spawnfunc(trigger_heal)
{
self.active = ACTIVE_ACTIVE;
#ifdef SVQC
void trigger_hurt_use()
-{
+{SELFPARAM();
if(IS_PLAYER(activator))
self.enemy = activator;
else
.float triggerhurttime;
void trigger_hurt_touch()
-{
+{SELFPARAM();
if (self.active != ACTIVE_ACTIVE)
return;
.entity trigger_hurt_next;
entity trigger_hurt_last;
entity trigger_hurt_first;
-void spawnfunc_trigger_hurt()
+spawnfunc(trigger_hurt)
{
EXACTTRIGGER_INIT;
self.active = ACTIVE_ACTIVE;
// targeted (directional) mode
void trigger_impulse_touch1()
-{
+{SELFPARAM();
entity targ;
float pushdeltatime;
float str;
// Directionless (accelerator/decelerator) mode
void trigger_impulse_touch2()
-{
+{SELFPARAM();
float pushdeltatime;
if (self.active != ACTIVE_ACTIVE)
// Spherical (gravity/repulsor) mode
void trigger_impulse_touch3()
-{
+{SELFPARAM();
float pushdeltatime;
float str;
*/
#ifdef SVQC
bool trigger_impulse_send(entity to, int sf)
-{
+{SELFPARAM();
WriteByte(MSG_ENTITY, ENT_CLIENT_TRIGGER_IMPULSE);
WriteCoord(MSG_ENTITY, self.radius);
//Net_LinkEntity(self, 0, false, trigger_impulse_send);
}
-void spawnfunc_trigger_impulse()
+spawnfunc(trigger_impulse)
{
self.active = ACTIVE_ACTIVE;
}
#elif defined(CSQC)
void ent_trigger_impulse()
-{
+{SELFPARAM();
self.radius = ReadCoord();
self.strength = ReadCoord();
self.falloff = ReadByte();
#include "../../movetypes/movetypes.qh"
void trigger_push_use()
-{
+{SELFPARAM();
if(teamplay)
{
self.team = activator.team;
}
void trigger_push_touch()
-{
+{SELFPARAM();
if (self.active == ACTIVE_NOT)
return;
{
// flash when activated
Send_Effect(EFFECT_JUMPPAD, other.origin, other.velocity, 1);
- sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
+ _sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
self.pushltime = time + 0.2;
}
if(IS_REAL_CLIENT(other) || IS_BOT_CLIENT(other))
if(self.enemy.target)
{
- entity oldself;
- oldself = self;
activator = other;
- self = self.enemy;
- SUB_UseTargets();
- self = oldself;
+ WITH(entity, self, self.enemy, SUB_UseTargets());
}
if (other.flags & FL_PROJECTILE)
void trigger_push_updatelink();
#endif
void trigger_push_findtarget()
-{
+{SELFPARAM();
entity t;
vector org;
#ifdef SVQC
float trigger_push_send(entity to, float sf)
-{
+{SELFPARAM();
WriteByte(MSG_ENTITY, ENT_CLIENT_TRIGGER_PUSH);
WriteByte(MSG_ENTITY, sf);
}
void trigger_push_updatelink()
-{
+{SELFPARAM();
self.SendFlags |= 1;
}
* values to target a point on the ceiling.
* movedir: if target is not set, this * speed * 10 is the velocity to be reached.
*/
-void spawnfunc_trigger_push()
+spawnfunc(trigger_push)
{
SetMovedir ();
}
-float target_push_send(entity to, float sf)
+bool target_push_send(entity this, entity to, float sf)
{
WriteByte(MSG_ENTITY, ENT_CLIENT_TARGET_PUSH);
}
void target_push_link()
-{
+{SELFPARAM();
Net_LinkEntity(self, false, 0, target_push_send);
self.SendFlags |= 1; // update
}
-void spawnfunc_target_push() { target_push_link(); }
-void spawnfunc_info_notnull() { target_push_link(); }
-void spawnfunc_target_position() { target_push_link(); }
+spawnfunc(target_push) { target_push_link(); }
+spawnfunc(info_notnull) { target_push_link(); }
+spawnfunc(target_position) { target_push_link(); }
#endif
#ifdef CSQC
void ent_trigger_push()
-{
+{SELFPARAM();
float sf = ReadByte();
if(sf & 1)
}
void target_push_remove()
-{
+{SELFPARAM();
if(self.classname)
strunzone(self.classname);
self.classname = string_null;
}
void ent_target_push()
-{
+{SELFPARAM();
self.classname = "push_target";
self.cnt = ReadByte();
self.targetname = strzone(ReadString());
* movedir: if target is not set, this * speed * 10 is the velocity to be reached.
*/
#ifdef SVQC
-void spawnfunc_trigger_push();
+spawnfunc(trigger_push);
-void spawnfunc_target_push();
-void spawnfunc_info_notnull();
-void spawnfunc_target_position();
+spawnfunc(target_push);
+spawnfunc(info_notnull);
+spawnfunc(target_position);
#endif
#endif
* trigger given targets
*/
void trigger_keylock_trigger(string s)
-{
- entity stemp = self;
+{SELFPARAM();
entity otemp = other;
entity atemp = activator;
for(t = world; (t = find(t, targetname, s)); )
if(t.use)
{
- self = t;
- other = stemp;
+ setself(t);
+ other = this;
activator = atemp;
self.use();
}
- self = stemp;
+ setself(this);
other = otemp;
activator = atemp;
}
}
void trigger_keylock_touch()
-{
+{SELFPARAM();
bool key_used = false;
bool started_delay = false;
#ifdef SVQC
bool trigger_keylock_send(entity to, int sf)
-{
+{SELFPARAM();
WriteByte(MSG_ENTITY, ENT_CLIENT_KEYLOCK);
WriteInt24_t(MSG_ENTITY, self.itemkeys);
If spawned without any key specified in itemkeys, this trigger will display an error and remove itself.
message2 and noise2 will be resent to the player every 2 seconds while he is in the trigger zone.
*/
-void spawnfunc_trigger_keylock(void)
+spawnfunc(trigger_keylock)
{
if(!self.itemkeys) { remove(self); return; }
if(self.sounds == 1)
self.noise = "misc/secret.wav";
else if(self.sounds == 2)
- self.noise = "misc/talk.wav";
+ self.noise = SND(TALK);
else //if (self.sounds == 3) {
self.noise = "misc/trigger1.wav";
}
// set closed sourd
if(self.noise2 == "")
- self.noise2 = "misc/talk.wav";
+ self.noise2 = SND(TALK);
// delay between triggering message2 and trigger2
if(!self.wait) { self.wait = 5; }
}
#elif defined(CSQC)
void keylock_remove()
-{
+{SELFPARAM();
if(self.target) { strunzone(self.target); }
self.target = string_null;
}
void ent_keylock()
-{
+{SELFPARAM();
self.itemkeys = ReadInt24_t();
self.height = ReadByte();
float magicear_matched;
float W_Tuba_HasPlayed(entity pl, string melody, float instrument, float ignorepitch, float mintempo, float maxtempo);
string trigger_magicear_processmessage(entity ear, entity source, float teamsay, entity privatesay, string msgin)
-{
+{SELFPARAM();
float domatch, dotrigger, matchstart, l;
string s, msg;
- entity oldself;
string savemessage;
magicear_matched = false;
if(dotrigger)
{
- oldself = self;
activator = source;
- self = ear;
+ setself(ear);
savemessage = self.message;
self.message = string_null;
SUB_UseTargets();
self.message = savemessage;
- self = oldself;
+ setself(this);
}
if(ear.netname != "")
if(dotrigger)
{
- oldself = self;
activator = source;
- self = ear;
+ setself(ear);
savemessage = self.message;
self.message = string_null;
SUB_UseTargets();
self.message = savemessage;
- self = oldself;
+ setself(this);
}
if(ear.spawnflags & 16)
return msgin;
}
-void spawnfunc_trigger_magicear()
+spawnfunc(trigger_magicear)
{
self.enemy = magicears;
magicears = self;
"Mono-flop" trigger gate... turns one trigger event into one "on" and one "off" event, separated by a delay of "wait"
*/
void monoflop_use()
-{
+{SELFPARAM();
self.nextthink = time + self.wait;
self.enemy = activator;
if(self.state)
SUB_UseTargets();
}
void monoflop_fixed_use()
-{
+{SELFPARAM();
if(self.state)
return;
self.nextthink = time + self.wait;
}
void monoflop_think()
-{
+{SELFPARAM();
self.state = 0;
activator = self.enemy;
SUB_UseTargets();
}
void monoflop_reset()
-{
+{SELFPARAM();
self.state = 0;
self.nextthink = 0;
}
-void spawnfunc_trigger_monoflop()
+spawnfunc(trigger_monoflop)
{
if(!self.wait)
self.wait = 1;
#ifdef SVQC
// the wait time has passed, so set back up for another activation
void multi_wait()
-{
+{SELFPARAM();
if (self.max_health)
{
self.health = self.max_health;
// self.enemy should be set to the activator so it can be held through a delay
// so wait for the delay time before firing
void multi_trigger()
-{
+{SELFPARAM();
if (self.nextthink > time)
{
return; // allready been triggered
}
if (self.noise)
- sound (self.enemy, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
+ _sound (self.enemy, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
// don't trigger again until reset
self.takedamage = DAMAGE_NO;
}
void multi_use()
-{
+{SELFPARAM();
self.goalentity = other;
self.enemy = activator;
multi_trigger();
}
void multi_touch()
-{
+{SELFPARAM();
if(!(self.spawnflags & 2))
if(!other.iscreature)
return;
}
void multi_eventdamage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
if (!self.takedamage)
return;
if(self.spawnflags & DOOR_NOSPLASH)
}
void multi_reset()
-{
+{SELFPARAM();
if ( !(self.spawnflags & SPAWNFLAG_NOTOUCH) )
self.touch = multi_touch;
if (self.max_health)
4)
set "message" to text string
*/
-void spawnfunc_trigger_multiple()
+spawnfunc(trigger_multiple)
{
self.reset = multi_reset;
if (self.sounds == 1)
}
else if (self.sounds == 2)
{
- precache_sound ("misc/talk.wav");
- self.noise = "misc/talk.wav";
+ self.noise = SND(TALK);
}
else if (self.sounds == 3)
{
4)
set "message" to text string
*/
-void spawnfunc_trigger_once()
+spawnfunc(trigger_once)
{
- self.wait = -1;
- spawnfunc_trigger_multiple();
+ this.wait = -1;
+ spawnfunc_trigger_multiple(this);
}
#endif
void multi_trigger();
void multi_reset();
-void spawnfunc_trigger_once();
+spawnfunc(trigger_once);
#endif
#ifdef SVQC
void multivibrator_send()
-{
+{SELFPARAM();
float newstate;
float cyclestart;
}
void multivibrator_toggle()
-{
+{SELFPARAM();
if(self.nextthink == 0)
{
multivibrator_send();
}
void multivibrator_reset()
-{
+{SELFPARAM();
if(!(self.spawnflags & 1))
self.nextthink = 0; // wait for a trigger event
else
-------- SPAWNFLAGS --------
START_ON: assume it is already turned on (when targeted)
*/
-void spawnfunc_trigger_multivibrator()
+spawnfunc(trigger_multivibrator)
{
if(!self.wait)
self.wait = 1;
#ifdef SVQC
+void _spawnfunc_trigger_relay();
/*QUAKED spawnfunc_trigger_relay (.5 .5 .5) (-8 -8 -8) (8 8 8)
This fixed size trigger cannot be touched, it can only be fired by other events. It can contain killtargets, targets, delays, and messages.
*/
-void spawnfunc_trigger_relay()
+spawnfunc(trigger_relay)
{
self.use = SUB_UseTargets;
- self.reset = spawnfunc_trigger_relay; // this spawnfunc resets fully
+ self.reset = _spawnfunc_trigger_relay; // this spawnfunc resets fully
}
+void _spawnfunc_trigger_relay() { SELFPARAM(); spawnfunc_trigger_relay(this); }
#endif
#ifdef SVQC
void relay_activators_use()
-{
- entity trg, os;
-
- os = self;
-
- for(trg = world; (trg = find(trg, targetname, os.target)); )
+{SELFPARAM();
+ for(entity trg = world; (trg = find(trg, targetname, this.target)); )
{
- self = trg;
+ setself(trg);
if (trg.setactive)
- trg.setactive(os.cnt);
+ trg.setactive(this.cnt);
else
{
//bprint("Not using setactive\n");
- if(os.cnt == ACTIVE_TOGGLE)
+ if(this.cnt == ACTIVE_TOGGLE)
if(trg.active == ACTIVE_ACTIVE)
trg.active = ACTIVE_NOT;
else
trg.active = ACTIVE_ACTIVE;
else
- trg.active = os.cnt;
+ trg.active = this.cnt;
}
}
- self = os;
+ setself(this);
}
-void spawnfunc_relay_activate()
+spawnfunc(relay_activate)
{
self.cnt = ACTIVE_ACTIVE;
self.use = relay_activators_use;
}
-void spawnfunc_relay_deactivate()
+spawnfunc(relay_deactivate)
{
self.cnt = ACTIVE_NOT;
self.use = relay_activators_use;
}
-void spawnfunc_relay_activatetoggle()
+spawnfunc(relay_activatetoggle)
{
self.cnt = ACTIVE_TOGGLE;
self.use = relay_activators_use;
#ifdef SVQC
void trigger_relay_if_use()
-{
+{SELFPARAM();
float n;
n = self.count;
SUB_UseTargets();
}
-void spawnfunc_trigger_relay_if()
+spawnfunc(trigger_relay_if)
{
self.use = trigger_relay_if_use;
}
#ifdef SVQC
void trigger_relay_teamcheck_use()
-{
+{SELFPARAM();
if(activator.team)
{
if(self.spawnflags & 2)
}
void trigger_relay_teamcheck_reset()
-{
+{SELFPARAM();
self.team = self.team_saved;
}
-void spawnfunc_trigger_relay_teamcheck()
+spawnfunc(trigger_relay_teamcheck)
{
self.team_saved = self.team;
self.use = trigger_relay_teamcheck_use;
#ifdef SVQC
-void secrets_setstatus() {
+void secrets_setstatus()
+{SELFPARAM();
self.stat_secrets_total = secrets_total;
self.stat_secrets_found = secrets_found;
}
/**
* A secret has been found (maybe :P)
*/
-void trigger_secret_touch() {
+void trigger_secret_touch()
+{SELFPARAM();
// only a player can trigger this
if (!IS_PLAYER(other))
return;
You should create a common/trigger textured brush covering the entrance to a secret room/area.
Trigger secret can only be trigger by a player's touch and can not be a target itself.
*/
-void spawnfunc_trigger_secret() {
+spawnfunc(trigger_secret)
+{
// FIXME: should it be disabled in most modes?
// update secrets count
// convert this trigger to trigger_once
self.classname = "trigger_once";
- spawnfunc_trigger_once();
+ spawnfunc_trigger_once(this);
// take over the touch() function, so we can mark secret as found
self.touch = trigger_secret_touch;
.entity swampslug;
#ifdef SVQC
-void spawnfunc_trigger_swamp(void);
+spawnfunc(trigger_swamp);
#endif
void swamp_touch(void);
void swampslug_think();
* I do it this way becuz there is no "untouch" event.
*/
void swampslug_think(void)
-{
+{SELFPARAM();
//Slowly kill the slug
self.health = self.health - 1;
}
void swamp_touch(void)
-{
+{SELFPARAM();
// If whatever thats touching the swamp is not a player
// or if its a dead player, just dont care abt it.
if(!IS_PLAYER(other) || PHYS_DEAD(other))
#ifdef SVQC
float swamp_send(entity to, float sf)
-{
+{SELFPARAM();
WriteByte(MSG_ENTITY, ENT_CLIENT_LADDER);
WriteByte(MSG_ENTITY, self.dmg); // can probably get away with using a single byte here
}
void swamp_link()
-{
+{SELFPARAM();
Net_LinkEntity(self, false, 0, func_ladder_send);
}
Players gettin into the swamp will
get slowd down and damaged
*/
-void spawnfunc_trigger_swamp(void)
+spawnfunc(trigger_swamp)
{
// Init stuff
EXACTTRIGGER_INIT;
#elif defined(CSQC)
void ent_swamp()
-{
+{SELFPARAM();
self.dmg = ReadByte();
self.swamp_slowdown = ReadByte();
self.swamp_interval = ReadByte();
#ifdef SVQC
void trigger_teleport_use()
-{
+{SELFPARAM();
if(teamplay)
self.team = activator.team;
#ifdef SVQC
}
void Teleport_Touch (void)
-{
- entity oldself;
+{SELFPARAM();
string s;
if (self.active != ACTIVE_ACTIVE)
if(IS_PLAYER(other))
RemoveGrapplingHook(other);
- entity e;
- e = Simple_TeleportPlayer(self, other);
+ entity e = Simple_TeleportPlayer(self, other);
activator = other;
s = self.target; self.target = string_null;
SUB_UseTargets();
if (!self.target) self.target = s;
- oldself = self;
- self = e;
- SUB_UseTargets();
- self = oldself;
+ WITH(entity, self, e, SUB_UseTargets());
}
-void spawnfunc_trigger_teleport()
+spawnfunc(trigger_teleport)
{
self.angles = '0 0 0';
#ifdef SVQC
void viewloc_think()
-{
+{SELFPARAM();
entity e;
// we abuse this method, rather than using normal .touch, because touch isn't reliable with multiple clients inside the same trigger, and can't "untouch" entities
self.nextthink = time;
}
-bool trigger_viewloc_send(entity to, int sf)
+bool trigger_viewloc_send(entity this, entity to, int sf)
{
// CSQC doesn't need to know our origin (yet), as we're only available for referencing
WriteByte(MSG_ENTITY, ENT_CLIENT_VIEWLOC_TRIGGER);
}
void viewloc_init()
-{
+{SELFPARAM();
entity e;
for(e = world; (e = find(e, targetname, self.target)); )
if(e.classname == "target_viewlocation_start")
self.nextthink = time;
}
-void spawnfunc_trigger_viewlocation()
+spawnfunc(trigger_viewlocation)
{
// we won't check target2 here yet, as it may not even need to exist
if(self.target == "") { LOG_INFO("^1FAIL!\n"); remove(self); return; }
InitializeEntity(self, viewloc_init, INITPRIO_FINDTARGET);
}
-bool viewloc_send(entity to, int sf)
+bool viewloc_send(entity this, entity to, int sf)
{
WriteByte(MSG_ENTITY, ENT_CLIENT_VIEWLOC);
.float angle;
void viewloc_link()
-{
+{SELFPARAM();
if(self.angle)
self.angles_y = self.angle;
Net_LinkEntity(self, false, 0, viewloc_send);
}
-void spawnfunc_target_viewlocation_start()
+spawnfunc(target_viewlocation_start)
{
self.classname = "target_viewlocation_start";
self.cnt = 1;
viewloc_link();
}
-void spawnfunc_target_viewlocation_end()
+spawnfunc(target_viewlocation_end)
{
self.classname = "target_viewlocation_end";
self.cnt = 2;
}
// compatibility
-void spawnfunc_target_viewlocation() { spawnfunc_target_viewlocation_start(); }
+spawnfunc(target_viewlocation) { spawnfunc_target_viewlocation_start(this); }
#elif defined(CSQC)
void trigger_viewloc_updatelink()
-{
+{SELFPARAM();
self.enemy = findfloat(world, entnum, self.cnt);
self.goalentity = findfloat(world, entnum, self.count);
}
void ent_viewloc_trigger()
-{
+{SELFPARAM();
float point1 = ReadShort();
float point2 = ReadShort();
}
void ent_viewloc()
-{
+{SELFPARAM();
self.cnt = ReadByte();
self.origin_x = ReadCoord();
void() SUB_UseTargets;
void DelayThink()
-{
+{SELFPARAM();
activator = self.enemy;
SUB_UseTargets ();
remove(self);
#ifdef SVQC
void trigger_common_write(bool withtarget)
-{
+{SELFPARAM();
WriteByte(MSG_ENTITY, self.warpzone_isboxy);
WriteByte(MSG_ENTITY, self.scale);
#elif defined(CSQC)
void trigger_common_read(bool withtarget)
-{
+{SELFPARAM();
self.warpzone_isboxy = ReadByte();
self.scale = ReadByte();
}
void trigger_remove_generic()
-{
+{SELFPARAM();
if(self.target) { strunzone(self.target); }
self.target = string_null;
==============================
*/
void SUB_UseTargets()
-{
- entity t, stemp, otemp, act;
+{SELFPARAM();
+ entity t, otemp, act;
string s;
float i;
{
centerprint(activator, self.message);
if (self.noise == "")
- play2(activator, "misc/talk.wav");
+ play2(activator, SND(TALK));
}
//
// fire targets
//
act = activator;
- stemp = self;
otemp = other;
- if(stemp.target_random)
+ if(this.target_random)
RandomSelection_Init();
for(i = 0; i < 4; ++i)
switch(i)
{
default:
- case 0: s = stemp.target; break;
- case 1: s = stemp.target2; break;
- case 2: s = stemp.target3; break;
- case 3: s = stemp.target4; break;
+ case 0: s = this.target; break;
+ case 1: s = this.target2; break;
+ case 2: s = this.target3; break;
+ case 3: s = this.target4; break;
}
if (s != "")
{
for(t = world; (t = find(t, targetname, s)); )
if(t.use)
{
- if(stemp.target_random)
+ if(this.target_random)
{
RandomSelection_Add(t, 0, string_null, 1, 0);
}
{
if (t.classname == "func_clientwall" || t.classname == "func_clientillusionary")
t.antiwall_flag = aw_flag;
- self = t;
- other = stemp;
+ setself(t);
+ other = this;
activator = act;
self.use();
}
}
}
- if(stemp.target_random && RandomSelection_chosen_ent)
+ if(this.target_random && RandomSelection_chosen_ent)
{
- self = RandomSelection_chosen_ent;
- other = stemp;
+ setself(RandomSelection_chosen_ent);
+ other = this;
activator = act;
self.use();
}
activator = act;
- self = stemp;
+ setself(this);
other = otemp;
}
#ifdef CSQC
void trigger_touch_generic(void() touchfunc)
-{
+{SELFPARAM();
entity e;
for(e = findradius((self.absmin + self.absmax) * 0.5, vlen(self.absmax - self.absmin) * 0.5 + 1); e; e = e.chain)
if(e.isplayermodel || e.classname == "csqcprojectile")
}
}
}
-void trigger_draw_generic()
+void trigger_draw_generic(entity this)
{
float dt = time - self.move_time;
self.move_time = time;
--- /dev/null
+#include "turret/ewheel.qc"
+#include "turret/flac.qc"
+#include "turret/fusionreactor.qc"
+#include "turret/hellion.qc"
+#include "turret/hk.qc"
+#include "turret/machinegun.qc"
+#include "turret/mlrs.qc"
+#include "turret/phaser.qc"
+#include "turret/plasma.qc"
+#include "turret/plasma_dual.qc"
+#include "turret/tesla.qc"
+#include "turret/walker.qc"
--- /dev/null
+#include "all.qh"
+
+#ifdef SVQC
+#include "sv_turrets.qh"
+#endif
+
+#ifdef CSQC
+#include "cl_turrets.qh"
+#endif
+
+#define IMPLEMENTATION
+#include "all.inc"
+#undef IMPLEMENTATION
-#include "unit/ewheel.qc"
-#include "unit/flac.qc"
-#include "unit/fusionreactor.qc"
-#include "unit/hellion.qc"
-#include "unit/hk.qc"
-#include "unit/machinegun.qc"
-#include "unit/mlrs.qc"
-#include "unit/phaser.qc"
-#include "unit/plasma.qc"
-#include "unit/plasma_dual.qc"
-#include "unit/tesla.qc"
-#include "unit/walker.qc"
+#ifndef TURRETS_ALL_H
+#define TURRETS_ALL_H
+
+#include "turret.qh"
+
+REGISTRY(Turrets, BIT(5))
+REGISTER_REGISTRY(RegisterTurrets)
+const int TUR_FIRST = 1;
+#define TUR_LAST (Turrets_COUNT - 1)
+
+#define REGISTER_TURRET(id, inst) REGISTER(RegisterTurrets, TUR, Turrets, id, m_id, inst)
+
+REGISTER_TURRET(Null, NEW(Turret));
+
+Turret get_turretinfo(int id)
+{
+ if (id >= TUR_FIRST && id <= TUR_LAST) {
+ Turret t = Turrets[id];
+ if (t) return t;
+ }
+ return TUR_Null;
+}
+
+#include "all.inc"
+
+#endif
#if 0
void turret_checkpoint_think()
-{
+{SELFPARAM();
if(self.enemy)
te_lightning1(self,self.origin, self.enemy.origin);
*/
//float tc_acum;
void turret_checkpoint_init()
-{
+{SELFPARAM();
traceline(self.origin + '0 0 16', self.origin - '0 0 1024', MOVE_WORLDONLY, self);
setorigin(self, trace_endpos + '0 0 32');
//tc_acum += 0.25;
}
-void spawnfunc_turret_checkpoint()
+spawnfunc(turret_checkpoint)
{
setorigin(self,self.origin);
self.think = turret_checkpoint_init;
}
// Compat.
-void spawnfunc_walker_checkpoint()
+spawnfunc(walker_checkpoint)
{
self.classname = "turret_checkpoint";
- spawnfunc_turret_checkpoint();
+ spawnfunc_turret_checkpoint(this);
}
void turret_remove()
-{
+{SELFPARAM();
remove(self.tur_head);
//remove(self.enemy);
self.tur_head = world;
.vector glowmod;
void turret_changeteam()
-{
+{SELFPARAM();
self.glowmod = Team_ColorRGB(self.team - 1) * 2;
self.teamradar_color = Team_ColorRGB(self.team - 1);
}
void turret_head_draw()
-{
+{SELFPARAM();
self.drawmask = MASK_NORMAL;
}
-void turret_draw()
+void turret_draw(entity this)
{
float dt;
}
-void turret_draw2d()
+void turret_draw2d(entity this)
{
if(self.netname == "")
return;
o_z = 0;
if(hud != HUD_NORMAL)
{
- if((get_turretinfo(self.turretid)).spawnflags & TUR_FLAG_MOVE)
+ if((get_turretinfo(self.m_id)).spawnflags & TUR_FLAG_MOVE)
txt = "gfx/vehicles/turret_moving.tga";
else
txt = "gfx/vehicles/turret_stationary.tga";
string spriteimage = self.netname;
float a = self.alpha * autocvar_hud_panel_fg_alpha;
- vector rgb = spritelookupcolor(spriteimage, self.teamradar_color);
+ vector rgb = spritelookupcolor(self, spriteimage, self.teamradar_color);
if(self.maxdistance > waypointsprite_normdistance)
}
void turret_construct()
-{
- entity tur = get_turretinfo(self.turretid);
+{SELFPARAM();
+ entity tur = get_turretinfo(self.m_id);
if(self.tur_head == world)
self.tur_head = spawn();
- self.netname = TUR_NAME(self.turretid);
+ self.netname = tur.turret_name;
setorigin(self, self.origin);
- setmodel(self, tur.model);
- setmodel(self.tur_head, tur.head_model);
+ _setmodel(self, tur.model);
+ _setmodel(self.tur_head, tur.head_model);
setsize(self, tur.mins, tur.maxs);
setsize(self.tur_head, '0 0 0', '0 0 0');
- if(self.turretid == TUR_EWHEEL)
+ if(self.m_id == TUR_EWHEEL.m_id)
setattachment(self.tur_head, self, "");
else
setattachment(self.tur_head, self, "tag_head");
self.teamradar_color = '1 0 0';
self.alpha = 1;
- TUR_ACTION(self.turretid, TR_SETUP);
+ tur.tr_setup(tur, self);
}
entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, float _explode);
void turret_gibboom();
-void turret_gib_draw()
+void turret_gib_draw(entity this)
{
Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
}
void turret_gibboom()
-{
+{SELFPARAM();
float i;
- sound (self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+ sound (self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
pointparticles(particleeffectnum(EFFECT_ROCKET_EXPLODE), self.origin, '0 0 0', 1);
for (i = 1; i < 5; i = i + 1)
gib = spawn();
setorigin(gib, _from);
- setmodel(gib, _model);
+ _setmodel(gib, _model);
gib.colormod = _cmod;
gib.solid = SOLID_CORPSE;
gib.draw = turret_gib_draw;
}
void turret_die()
-{
- sound (self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+{SELFPARAM();
+ sound (self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
pointparticles(particleeffectnum(EFFECT_ROCKET_EXPLODE), self.origin, '0 0 0', 1);
if (!autocvar_cl_nogibs)
{
// Base
- if(self.turretid == TUR_EWHEEL)
- turret_gibtoss((get_turretinfo(self.turretid)).model, self.origin + '0 0 18', self.velocity + '0 0 400' + '0.1 0.1 1' * (random() * 400), '-1 -1 -1', true);
- else if (self.turretid == TUR_WALKER)
- turret_gibtoss((get_turretinfo(self.turretid)).model, self.origin + '0 0 18', self.velocity + '0 0 300' + '0.1 0.1 1' * (random() * 200), '-1 -1 -1', true);
- else if (self.turretid == TUR_TESLA)
- turret_gibtoss((get_turretinfo(self.turretid)).model, self.origin + '0 0 18', '0 0 200', '-1 -1 -1', false);
+ if(self.m_id == TUR_EWHEEL.m_id)
+ turret_gibtoss((get_turretinfo(self.m_id)).model, self.origin + '0 0 18', self.velocity + '0 0 400' + '0.1 0.1 1' * (random() * 400), '-1 -1 -1', true);
+ else if (self.m_id == TUR_WALKER.m_id)
+ turret_gibtoss((get_turretinfo(self.m_id)).model, self.origin + '0 0 18', self.velocity + '0 0 300' + '0.1 0.1 1' * (random() * 200), '-1 -1 -1', true);
+ else if (self.m_id == TUR_TESLA.m_id)
+ turret_gibtoss((get_turretinfo(self.m_id)).model, self.origin + '0 0 18', '0 0 200', '-1 -1 -1', false);
else
{
if (random() > 0.5)
else
turret_gibtoss("models/turrets/base-gib1.md3", self.origin + '0 0 8', '0 0 0', '0 0 0', true);
- entity headgib = turret_gibtoss((get_turretinfo(self.turretid)).head_model, self.origin + '0 0 32', '0 0 200' + randomvec() * 200, '-1 -1 -1', true);
+ entity headgib = turret_gibtoss((get_turretinfo(self.m_id)).head_model, self.origin + '0 0 32', '0 0 200' + randomvec() * 200, '-1 -1 -1', true);
if(headgib)
{
headgib.angles = headgib.move_angles = self.tur_head.angles;
}
}
- setmodel(self, "null");
- setmodel(self.tur_head, "null");
+ setmodel(self, MDL_Null);
+ setmodel(self.tur_head, MDL_Null);
}
void ent_turret()
-{
+{SELFPARAM();
float sf;
sf = ReadByte();
if(sf & TNSF_SETUP)
{
- self.turretid = ReadByte();
+ self.m_id = ReadByte();
self.origin_x = ReadCoord();
self.origin_y = ReadCoord();
void Dump_Turret_Settings(void)
{
- float i, x, totalsettings = 0;
- for(i = TUR_FIRST; i <= TUR_LAST; ++i)
- {
+ float x, totalsettings = 0;
+ FOREACH(Turrets, it != TUR_Null, LAMBDA({
// step 1: clear the queue
TUR_CONFIG_COUNT = 0;
for(x = 0; x <= MAX_TUR_CONFIG; ++x)
{ tur_config_queue[x] = string_null; }
// step 2: build new queue
- TUR_ACTION(i, TR_CONFIG);
+ it.tr_config(it);
// step 3: sort queue
heapsort(TUR_CONFIG_COUNT, T_Config_Queue_Swap, T_Config_Queue_Compare, world);
// step 4: write queue
- TUR_CONFIG_WRITETOFILE(sprintf("// {{{ #%d: %s\n", i, TUR_NAME(i)))
+ TUR_CONFIG_WRITETOFILE(sprintf("// {{{ #%d: %s\n", i, it.turret_name))
for(x = 0; x <= TUR_CONFIG_COUNT; ++x)
{ TUR_CONFIG_WRITETOFILE(tur_config_queue[x]) }
TUR_CONFIG_WRITETOFILE("// }}}\n")
// step 5: debug info
- LOG_INFO(sprintf("#%d: %s: %d settings...\n", i, TUR_NAME(i), TUR_CONFIG_COUNT));
+ LOG_INFO(sprintf("#%d: %s: %d settings...\n", i, it.turret_name, TUR_CONFIG_COUNT));
totalsettings += TUR_CONFIG_COUNT;
- }
+ }));
// clear queue now that we're finished
TUR_CONFIG_COUNT = 0;
{ tur_config_queue[x] = string_null; }
// extra information
- LOG_INFO(sprintf("Totals: %d turrets, %d settings\n", (i - 1), totalsettings));
+ LOG_INFO(sprintf("Totals: %d turrets, %d settings\n", (Turrets_COUNT - 1), totalsettings));
}
float tur_config_file;
float tur_config_alsoprint;
-#define MAX_TUR_CONFIG 256
+const int MAX_TUR_CONFIG = 256;
float TUR_CONFIG_COUNT;
string tur_config_queue[MAX_TUR_CONFIG];
-#define TUR_CONFIG_QUEUE(a) { \
- tur_config_queue[TUR_CONFIG_COUNT] = a; \
- ++TUR_CONFIG_COUNT; }
-
#define TUR_CONFIG_WRITETOFILE(a) { \
fputs(tur_config_file, a); \
if(tur_config_alsoprint) { LOG_INFO(a); } }
-#define TUR_CONFIG_WRITE_CVARS(turret,name) \
- { TUR_CONFIG_QUEUE( \
- sprintf("set g_turrets_unit_%s_%s %g\n", #turret, #name, \
- cvar(sprintf("g_turrets_unit_%s_%s", #turret, #name)))) } \
-
-#define TUR_CONFIG_SETTINGS(tursettings) \
- #define TUR_ADD_CVAR(turret,name) TUR_CONFIG_WRITE_CVARS(turret,name) \
- tursettings \
- #undef TUR_ADD_CVAR
#endif
// Generic aiming
vector turret_aim_generic()
-{
+{SELFPARAM();
vector pre_pos, prep;
float distance, impact_time = 0, i, mintime;
// Generic damage handling
void turret_hide()
-{
+{SELFPARAM();
self.effects |= EF_NODRAW;
self.nextthink = time + self.respawntime - 0.2;
self.think = turret_respawn;
}
void turret_die()
-{
+{SELFPARAM();
self.deadflag = DEAD_DEAD;
self.tur_head.deadflag = self.deadflag;
// Go boom
//RadiusDamage (self,self, min(self.ammo,50),min(self.ammo,50) * 0.25,250,world,min(self.ammo,50)*5,DEATH_TURRET,world);
+ Turret tur = get_turretinfo(self.m_id);
if(self.damage_flags & TFL_DMG_DEATH_NORESPAWN)
{
- TUR_ACTION(self.turretid, TR_DEATH);
+ tur.tr_death(tur, self);
remove(self.tur_head);
remove(self);
self.nextthink = time + 0.2;
self.think = turret_hide;
- TUR_ACTION(self.turretid, TR_DEATH);
+ tur.tr_death(tur, self);
}
}
void turret_damage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector vforce)
-{
+{SELFPARAM();
// Enough already!
if(self.deadflag == DEAD_DEAD)
return;
void() turret_think;
void turret_respawn()
-{
+{SELFPARAM();
// Make sure all parts belong to the same team since
// this function doubles as "teamchange" function.
self.tur_head.team = self.team;
self.SendFlags = TNSF_FULL_UPDATE;
- TUR_ACTION(self.turretid, TR_SETUP);
+ Turret tur = get_turretinfo(self.m_id);
+ tur.tr_setup(tur, self);
}
#define cvar_base "g_turrets_unit_"
.float clientframe;
void turrets_setframe(float _frame, float client_only)
-{
+{SELFPARAM();
if((client_only ? self.clientframe : self.frame ) != _frame)
{
self.SendFlags |= TNSF_ANIM;
}
-float turret_send(entity to, float sf)
+bool turret_send(entity this, entity to, float sf)
{
WriteByte(MSG_ENTITY, ENT_CLIENT_TURRET);
WriteByte(MSG_ENTITY, sf);
if(sf & TNSF_SETUP)
{
- WriteByte(MSG_ENTITY, self.turretid);
+ WriteByte(MSG_ENTITY, self.m_id);
WriteCoord(MSG_ENTITY, self.origin_x);
WriteCoord(MSG_ENTITY, self.origin_y);
return true;
}
-void load_unit_settings(entity ent, string unitname, float is_reload)
-{
+void load_unit_settings(entity ent, float is_reload)
+{SELFPARAM();
+ string unitname = ent.netname;
string sbase;
if (ent == world)
ent.track_accel_rotate = cvar(strcat(sbase,"_track_accel_rot"));
ent.track_blendrate = cvar(strcat(sbase,"_track_blendrate"));
- if(is_reload)
- TUR_ACTION(self.turretid, TR_SETUP);
+ if(is_reload) {
+ Turret tur = get_turretinfo(self.m_id);
+ tur.tr_setup(tur, self);
+ }
}
void turret_projectile_explode()
-{
+{SELFPARAM();
self.takedamage = DAMAGE_NO;
self.event_damage = func_null;
}
void turret_projectile_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector vforce)
-{
+{SELFPARAM();
self.velocity += vforce;
self.health -= damage;
//self.realowner = attacker; // Dont change realowner, it does not make much sense for turrets
}
entity turret_projectile(string _snd, float _size, float _health, float _death, float _proj_type, float _cull, float _cli_anim)
-{
+{SELFPARAM();
entity proj;
- sound (self, CH_WEAPON_A, _snd, VOL_BASE, ATTEN_NORM);
+ _sound (self, CH_WEAPON_A, _snd, VOL_BASE, ATTEN_NORM);
proj = spawn ();
setorigin(proj, self.tur_shotorg);
setsize(proj, '-0.5 -0.5 -0.5' * _size, '0.5 0.5 0.5' * _size);
** and updated aim<->predict impact distance.
**/
void turret_do_updates(entity t_turret)
-{
+{SELFPARAM();
vector enemy_pos;
- entity oldself;
- oldself = self;
- self = t_turret;
+ setself(t_turret);
enemy_pos = real_origin(self.enemy);
self.tur_impactent = trace_ent;
self.tur_impacttime = vlen(self.tur_shotorg - trace_endpos) / self.shot_speed;
- self = oldself;
+ setself(this);
}
/**
**/
.float turret_framecounter;
void turret_track()
-{
+{SELFPARAM();
vector target_angle; // This is where we want to aim
vector move_angle; // This is where we can aim
float f_tmp;
}
entity turret_select_target()
-{
+{SELFPARAM();
entity e; // target looper entity
float score; // target looper entity score
entity e_enemy; // currently best scoreing target
** Preforms pre-fire checks based on the uints firecheck_flags
**/
float turret_firecheck()
-{
+{SELFPARAM();
// This one just dont care =)
if (self.firecheck_flags & TFL_FIRECHECK_NO)
return 1;
}
bool turret_checkfire()
-{
+{SELFPARAM();
bool ret = false; // dummy
if(MUTATOR_CALLHOOK(Turret_CheckFire, ret))
return ret_bool;
}
void turret_fire()
-{
+{SELFPARAM();
if (autocvar_g_turrets_nofire != 0)
return;
if(MUTATOR_CALLHOOK(TurretFire, self))
return;
- TUR_ACTION(self.turretid, TR_ATTACK);
+ Turret info = get_turretinfo(self.m_id);
+ info.tr_attack(info);
self.attack_finished_single = time + self.shot_refire;
self.ammo -= self.shot_dmg;
}
void turret_think()
-{
+{SELFPARAM();
entity e;
self.nextthink = time + self.ticrate;
if (turret_checkfire())
turret_fire();
- TUR_ACTION(self.turretid, TR_THINK);
+ Turret tur = get_turretinfo(self.m_id);
+ tur.tr_think(tur);
return;
}
if(!(self.track_flags & TFL_TRACK_NO))
turret_track();
- TUR_ACTION(self.turretid, TR_THINK);
+ Turret tur = get_turretinfo(self.m_id);
+ tur.tr_think(tur);
// And bail.
return;
turret_fire();
}
- TUR_ACTION(self.turretid, TR_THINK);
+ Turret tur = get_turretinfo(self.m_id);
+ tur.tr_think(tur);
}
/*
If activator is world, the turret go inactive.
*/
void turret_use()
-{
+{SELFPARAM();
LOG_TRACE("Turret ",self.netname, " used by ", activator.classname, "\n");
self.team = activator.team;
}
void turret_link()
-{
+{SELFPARAM();
Net_LinkEntity(self, true, 0, turret_send);
self.think = turret_think;
self.nextthink = time;
}
void turrets_manager_think()
-{
+{SELFPARAM();
self.nextthink = time + 1;
entity e;
{
if (IS_TURRET(e))
{
- load_unit_settings(e,e.cvar_basename,1);
- TUR_ACTION(self.turretid, TR_THINK);
+ load_unit_settings(e,1);
+ Turret tur = get_turretinfo(self.m_id);
+ tur.tr_think(tur);
}
e = nextent(e);
}
}
-float turret_initialize(float tur_id)
+void turret_initparams(entity tur)
{
+ #define TRY(x) (x) ? (x)
+ tur.respawntime = max (-1, (TRY(tur.respawntime) : 60 ));
+ tur.shot_refire = bound(0.01, (TRY(tur.shot_refire) : 1 ), 9999);
+ tur.shot_dmg = max (1, (TRY(tur.shot_dmg) : tur.shot_refire * 50 ));
+ tur.shot_radius = max (1, (TRY(tur.shot_radius) : tur.shot_dmg * 0.5 ));
+ tur.shot_speed = max (1, (TRY(tur.shot_speed) : 2500 ));
+ tur.shot_spread = bound(0.0001, (TRY(tur.shot_spread) : 0.0125 ), 500);
+ tur.shot_force = bound(0.001, (TRY(tur.shot_force) : tur.shot_dmg * 0.5 + tur.shot_radius * 0.5 ), 5000);
+ tur.shot_volly = bound(1, (TRY(tur.shot_volly) : 1 ), floor(tur.ammo_max / tur.shot_dmg));
+ tur.shot_volly_refire = bound(tur.shot_refire, (TRY(tur.shot_volly_refire) : tur.shot_refire * tur.shot_volly ), 60);
+ tur.target_range = bound(0, (TRY(tur.target_range) : tur.shot_speed * 0.5 ), MAX_SHOT_DISTANCE);
+ tur.target_range_min = bound(0, (TRY(tur.target_range_min) : tur.shot_radius * 2 ), MAX_SHOT_DISTANCE);
+ tur.target_range_optimal = bound(0, (TRY(tur.target_range_optimal) : tur.target_range * 0.5 ), MAX_SHOT_DISTANCE);
+ tur.aim_maxrotate = bound(0, (TRY(tur.aim_maxrotate) : 90 ), 360);
+ tur.aim_maxpitch = bound(0, (TRY(tur.aim_maxpitch) : 20 ), 90);
+ tur.aim_speed = bound(0.1, (TRY(tur.aim_speed) : 36 ), 1000);
+ tur.aim_firetolerance_dist = bound(0.1, (TRY(tur.aim_firetolerance_dist) : 5 + (tur.shot_radius * 2) ), MAX_SHOT_DISTANCE);
+ tur.target_select_rangebias = bound(-10, (TRY(tur.target_select_rangebias) : 1 ), 10);
+ tur.target_select_samebias = bound(-10, (TRY(tur.target_select_samebias) : 1 ), 10);
+ tur.target_select_anglebias = bound(-10, (TRY(tur.target_select_anglebias) : 1 ), 10);
+ tur.target_select_missilebias = bound(-10, (TRY(tur.target_select_missilebias) : 1 ), 10);
+ tur.target_select_playerbias = bound(-10, (TRY(tur.target_select_playerbias) : 1 ), 10);
+ tur.ammo_max = max (tur.shot_dmg, (TRY(tur.ammo_max) : tur.shot_dmg * 10 ));
+ tur.ammo_recharge = max (0, (TRY(tur.ammo_recharge) : tur.shot_dmg * 0.5 ));
+ #undef TRY
+}
+
+float turret_initialize(Turret tur)
+{SELFPARAM();
if(!autocvar_g_turrets)
return false;
- entity e;
- entity tur = get_turretinfo(tur_id);
- if(tur.turretid == 0)
+ if(tur.m_id == 0)
return false; // invalid turret
- if(!self.tur_head) { TUR_ACTION(tur_id, TR_PRECACHE); } // if tur_head exists, we can assume this turret re-spawned
+ // if tur_head exists, we can assume this turret re-spawned
+ if(!self.tur_head) {
+ tur.tr_precache(tur);
+ }
- e = find(world, classname, "turret_manager");
+ entity e = find(world, classname, "turret_manager");
if(!e)
{
e = spawn();
if(!(self.spawnflags & TSF_SUSPENDED))
builtin_droptofloor();
- self.cvar_basename = tur.cvar_basename;
- load_unit_settings(self, self.cvar_basename, 0);
+ self.netname = tur.netname;
+ load_unit_settings(self, 0);
if(!self.team || !teamplay) { self.team = MAX_SHOT_DISTANCE; }
if(!self.ticrate) { self.ticrate = ((self.turret_flags & TUR_FLAG_SUPPORT) ? 0.2 : 0.1); }
if(!self.track_blendrate) { self.track_blendrate = 0.35; }
}
- self.respawntime = max(-1, ((!self.respawntime) ? 60 : self.respawntime));
- self.shot_refire = bound(0.01, ((!self.shot_refire) ? 1 : self.shot_refire), 9999);
- self.shot_dmg = max(1, ((!self.shot_dmg) ? self.shot_refire * 50 : self.shot_dmg));
- self.shot_radius = max(1, ((!self.shot_radius) ? self.shot_dmg * 0.5 : self.shot_radius));
- self.shot_speed = max(1, ((!self.shot_speed) ? 2500 : self.shot_speed));
- self.shot_spread = bound(0.0001, ((!self.shot_spread) ? 0.0125 : self.shot_spread), 500);
- self.shot_force = bound(0.001, ((!self.shot_force) ? self.shot_dmg * 0.5 + self.shot_radius * 0.5 : self.shot_force), 5000);
- self.shot_volly = bound(1, ((!self.shot_volly) ? 1 : self.shot_volly), floor(self.ammo_max / self.shot_dmg));
- self.shot_volly_refire = bound(self.shot_refire, ((!self.shot_volly_refire) ? self.shot_refire * self.shot_volly : self.shot_volly_refire), 60);
- self.target_range = bound(0, ((!self.target_range) ? self.shot_speed * 0.5 : self.target_range), MAX_SHOT_DISTANCE);
- self.target_range_min = bound(0, ((!self.target_range_min) ? self.shot_radius * 2 : self.target_range_min), MAX_SHOT_DISTANCE);
- self.target_range_optimal = bound(0, ((!self.target_range_optimal) ? self.target_range * 0.5 : self.target_range_optimal), MAX_SHOT_DISTANCE);
- self.aim_maxrotate = bound(0, ((!self.aim_maxrotate) ? 90 : self.aim_maxrotate), 360);
- self.aim_maxpitch = bound(0, ((!self.aim_maxpitch) ? 20 : self.aim_maxpitch), 90);
- self.aim_speed = bound(0.1, ((!self.aim_speed) ? 36 : self.aim_speed), 1000);
- self.aim_firetolerance_dist = bound(0.1, ((!self.aim_firetolerance_dist) ? 5 + (self.shot_radius * 2) : self.aim_firetolerance_dist), MAX_SHOT_DISTANCE);
- self.target_select_rangebias = bound(-10, ((!self.target_select_rangebias) ? 1 : self.target_select_rangebias), 10);
- self.target_select_samebias = bound(-10, ((!self.target_select_samebias) ? 1 : self.target_select_samebias), 10);
- self.target_select_anglebias = bound(-10, ((!self.target_select_anglebias) ? 1 : self.target_select_anglebias), 10);
- self.target_select_missilebias = bound(-10, ((!self.target_select_missilebias) ? 1 : self.target_select_missilebias), 10);
- self.target_select_playerbias = bound(-10, ((!self.target_select_playerbias) ? 1 : self.target_select_playerbias), 10);
- self.ammo_max = max(self.shot_dmg, ((!self.ammo_max) ? self.shot_dmg * 10 : self.ammo_max));
- self.ammo_recharge = max(0, ((!self.ammo_recharge) ? self.shot_dmg * 0.5 : self.ammo_recharge));
+ turret_initparams(self);
self.turret_flags = TUR_FLAG_ISTURRET | (tur.spawnflags);
++turret_count;
- setmodel(self, tur.model);
+ _setmodel(self, tur.model);
setsize(self, tur.mins, tur.maxs);
- self.turretid = tur_id;
+ self.m_id = tur.m_id;
self.classname = "turret_main";
self.active = ACTIVE_ACTIVE;
self.effects = EF_NODRAW;
- self.netname = TUR_NAME(tur_id);
+ self.netname = tur.turret_name;
self.ticrate = bound(sys_frametime, self.ticrate, 60);
self.max_health = self.health;
self.target_validate_flags = self.target_select_flags;
self.nextthink += turret_count * sys_frametime;
self.tur_head = spawn();
- setmodel(self.tur_head, tur.head_model);
+ _setmodel(self.tur_head, tur.head_model);
setsize(self.tur_head, '0 0 0', '0 0 0');
setorigin(self.tur_head, '0 0 0');
setattachment(self.tur_head, self, "tag_head");
turret_respawn();
turret_tag_fire_update();
- TUR_ACTION(tur_id, TR_SETUP);
+ tur.tr_setup(tur, self);
if(MUTATOR_CALLHOOK(TurretSpawn, self))
return false;
#ifndef SV_TURRETS_H
#define SV_TURRETS_H
+entity turret_projectile(string _snd, float _size, float _health, float _death, float _proj_type, float _cull, float _cli_anim);
+void turret_projectile_explode();
+float turret_validate_target(entity e_turret, entity e_target, float validate_flags);
+float turret_firecheck();
+entity turret_select_target();
+
// turret fields
.float ticrate; // interal ai think rate
.vector aim_idle; // where to aim while idle
void turrets_setframe(float _frame, float client_only);
-float turret_initialize(float tur_id);
+float turret_initialize(Turret tur);
/// Function to use for target evaluation. usualy turret_targetscore_generic
.float(entity _turret, entity _target) turret_score_target;
-void spawnfunc_turret_targettrigger();
+spawnfunc(turret_targettrigger);
void turret_targettrigger_touch();
void turret_targettrigger_touch()
-{
+{SELFPARAM();
entity e;
if (self.cnt > time) return;
- entity oldself;
- oldself = self;
+ entity oldself = this;
e = find(world, targetname, self.target);
while (e)
{
if (e.turret_flags & TUR_FLAG_RECIEVETARGETS)
{
- self = e;
+ setself(e);
if(e.turret_addtarget)
e.turret_addtarget(other,oldself);
}
oldself.cnt = time + 0.5;
- self = oldself;
+ setself(this);
}
/*QUAKED turret_targettrigger (.5 .5 .5) ?
*/
-void spawnfunc_turret_targettrigger()
+spawnfunc(turret_targettrigger)
{
if(!autocvar_g_turrets) { remove(self); return; }
--- /dev/null
+#ifndef TURRET_H
+#define TURRET_H
+
+#include "../weapons/all.qh"
+
+CLASS(Turret, Object)
+ ATTRIB(Turret, m_id, int, 0)
+
+ /** short name */
+ ATTRIB(Turret, netname, string, string_null)
+ /** human readable name */
+ ATTRIB(Turret, turret_name, string, _("Turret"))
+ /** currently a copy of the model */
+ ATTRIB(Turret, mdl, string, string_null)
+ /** full name of model */
+ ATTRIB(Turret, model, string, string_null)
+ /** full name of tur_head model */
+ ATTRIB(Turret, head_model, string, string_null)
+
+ ATTRIB(Turret, spawnflags, int, 0)
+ /** turret hitbox size */
+ ATTRIB(Turret, mins, vector, '-0 -0 -0')
+ /** turret hitbox size */
+ ATTRIB(Turret, maxs, vector, '0 0 0')
+
+ METHOD(Turret, display, void(entity this, void(string name, string icon) returns)) {
+ returns(this.turret_name, string_null);
+ }
+ /** (BOTH) setup turret data */
+ METHOD(Turret, tr_setup, void(Turret this, entity it)) {
+
+ }
+ /** (SERVER) logic to run every frame */
+ METHOD(Turret, tr_think, void(Turret this)) {
+
+ }
+ /** (SERVER) called when turret dies */
+ METHOD(Turret, tr_death, void(Turret this, entity it)) {
+
+ }
+ /** (BOTH) precaches models/sounds used by this turret */
+ METHOD(Turret, tr_precache, void(Turret this)) {
+
+ }
+ ATTRIB(Turret, m_weapon, Weapon, WEP_Null)
+ /** (SERVER) called when turret attacks */
+ METHOD(Turret, tr_attack, void(Turret this)) {
+ Weapon w = this.m_weapon;
+ w.wr_think(w, self, true, false);
+ }
+ /** (ALL) */
+ METHOD(Turret, tr_config, void(Turret this)) {
+ // TODO
+ }
+ENDCLASS(Turret)
+
+// fields:
+.entity tur_head;
+
+// target selection flags
+.int target_select_flags;
+.int target_validate_flags;
+const int TFL_TARGETSELECT_NO = 2; // don't automatically find targets
+const int TFL_TARGETSELECT_LOS = 4; // require line of sight to find targets
+const int TFL_TARGETSELECT_PLAYERS = 8; // target players
+const int TFL_TARGETSELECT_MISSILES = 16; // target projectiles
+const int TFL_TARGETSELECT_TRIGGERTARGET = 32; // respond to turret_trigger_target events
+const int TFL_TARGETSELECT_ANGLELIMITS = 64; // apply extra angular limits to target selection
+const int TFL_TARGETSELECT_RANGELIMITS = 128; // limit target selection range
+const int TFL_TARGETSELECT_TEAMCHECK = 256; // don't attack teammates
+const int TFL_TARGETSELECT_NOBUILTIN = 512; // only attack targets when triggered
+const int TFL_TARGETSELECT_OWNTEAM = 1024; // only attack teammates
+const int TFL_TARGETSELECT_NOTURRETS = 2048; // don't attack other turrets
+const int TFL_TARGETSELECT_FOV = 4096; // extra limits to attack range
+const int TFL_TARGETSELECT_MISSILESONLY = 8192; // only attack missiles
+
+// aim flags
+.int aim_flags;
+const int TFL_AIM_NO = 1; // no aiming
+const int TFL_AIM_SPLASH = 2; // aim for ground around the target's feet
+const int TFL_AIM_LEAD = 4; // try to predict target movement
+const int TFL_AIM_SHOTTIMECOMPENSATE = 8; // compensate for shot traveltime when leading
+const int TFL_AIM_ZPREDICT = 16; // predict target's z position at impact
+const int TFL_AIM_SIMPLE = 32; // aim at player's current location
+
+// tracking flags
+.int track_flags;
+const int TFL_TRACK_NO = 2; // don't move head
+const int TFL_TRACK_PITCH = 4; // pitch head
+const int TFL_TRACK_ROTATE = 8; // rotate head
+
+// prefire checks
+.int firecheck_flags;
+const int TFL_FIRECHECK_DEAD = 4; // don't attack dead targets (zombies?)
+const int TFL_FIRECHECK_DISTANCES = 8; // another range check
+const int TFL_FIRECHECK_LOS = 16; // line of sight
+const int TFL_FIRECHECK_AIMDIST = 32; // consider distance impactpoint<->aimspot
+const int TFL_FIRECHECK_REALDIST = 64; // consider enemy origin<->impactpoint
+const int TFL_FIRECHECK_ANGLEDIST = 128; // consider angular diff head<->aimspot
+const int TFL_FIRECHECK_TEAMCHECK = 256; // don't attack teammates
+const int TFL_FIRECHECK_AFF = 512; // try to avoid any friendly fire
+const int TFL_FIRECHECK_AMMO_OWN = 1024; // own ammo needs to be larger than damage dealt
+const int TFL_FIRECHECK_AMMO_OTHER = 2048; // target's ammo needs to be less than max
+const int TFL_FIRECHECK_REFIRE = 4096; // check single attack finished delays
+const int TFL_FIRECHECK_NO = 16384; // no prefire checks
+
+// attack flags
+.int shoot_flags;
+const int TFL_SHOOT_NO = 64; // no attacking
+const int TFL_SHOOT_VOLLY = 2; // fire in vollies
+const int TFL_SHOOT_VOLLYALWAYS = 4; // always do a full volly, even if target is lost
+const int TFL_SHOOT_HITALLVALID = 8; // loop through all valid targets
+const int TFL_SHOOT_CLEARTARGET = 16; // lose target after attack (after volly is done if in volly mode)
+const int TFL_SHOOT_CUSTOM = 32; // custom attacking
+
+// turret capabilities
+.int turret_flags;
+const int TUR_FLAG_NONE = 0; // no abilities
+const int TUR_FLAG_SNIPER = 2; // sniping turret
+const int TUR_FLAG_SPLASH = 4; // can deal splash damage
+const int TUR_FLAG_HITSCAN = 8; // hit scan
+const int TUR_FLAG_MULTIGUN = 16; // multiple guns
+const int TUR_FLAG_GUIDED = 32; // laser guided projectiles
+const int TUR_FLAG_SLOWPROJ = 64; // turret fires slow projectiles
+const int TUR_FLAG_MEDPROJ = 128; // turret fires medium projectiles
+const int TUR_FLAG_FASTPROJ = 256; // turret fires fast projectiles
+const int TUR_FLAG_PLAYER = 512; // can damage players
+const int TUR_FLAG_MISSILE = 1024; // can damage missiles
+const int TUR_FLAG_SUPPORT = 2048; // supports other units
+const int TUR_FLAG_AMMOSOURCE = 4096; // can provide ammunition
+const int TUR_FLAG_RECIEVETARGETS = 8192; // can recieve targets from external sources
+const int TUR_FLAG_MOVE = 16384; // can move
+const int TUR_FLAG_ROAM = 32768; // roams around if not attacking
+const int TUR_FLAG_ISTURRET = 65536; // identifies this unit as a turret
+
+// ammo types
+#define ammo_flags currentammo
+const int TFL_AMMO_NONE = 64; // doesn't use ammo
+const int TFL_AMMO_ENERGY = 2; // uses power
+const int TFL_AMMO_BULLETS = 4; // uses bullets
+const int TFL_AMMO_ROCKETS = 8; // uses explosives
+const int TFL_AMMO_RECHARGE = 16; // regenerates ammo
+const int TFL_AMMO_RECIEVE = 32; // can recieve ammo from support units
+
+// damage flags
+.int damage_flags;
+const int TFL_DMG_NO = 256; // doesn't take damage
+const int TFL_DMG_YES = 2; // can be damaged
+const int TFL_DMG_TEAM = 4; // can be damaged by teammates
+const int TFL_DMG_RETALIATE = 8; // target attackers
+const int TFL_DMG_RETALIATE_TEAM = 16; // target attackers, even if on same team
+const int TFL_DMG_TARGETLOSS = 32; // loses target when damaged
+const int TFL_DMG_AIMSHAKE = 64; // damage throws off aim
+const int TFL_DMG_HEADSHAKE = 128; // damage shakes head
+const int TFL_DMG_DEATH_NORESPAWN = 256; // no re-spawning
+
+// spawn flags
+const int TSF_SUSPENDED = 1;
+const int TSF_TERRAINBASE = 2; // currently unused
+const int TSF_NO_AMMO_REGEN = 4; // disable builtin ammo regeneration
+const int TSF_NO_PATHBREAK = 8; // don't break path to chase enemies, will still fire at them if possible
+const int TSL_NO_RESPAWN = 16; // don't re-spawn
+const int TSL_ROAM = 32; // roam while idle
+
+// send flags
+const int TNSF_UPDATE = 2;
+const int TNSF_STATUS = 4;
+const int TNSF_SETUP = 8;
+const int TNSF_ANG = 16;
+const int TNSF_AVEL = 32;
+const int TNSF_MOVE = 64;
+.float anim_start_time;
+const int TNSF_ANIM = 128;
+
+const int TNSF_FULL_UPDATE = 16777215;
+
+#endif
--- /dev/null
+#ifndef TURRET_EWHEEL_H
+#define TURRET_EWHEEL_H
+
+//#define EWHEEL_FANCYPATH
+
+#include "ewheel_weapon.qc"
+
+CLASS(EWheel, Turret)
+/* spawnflags */ ATTRIB(EWheel, spawnflags, int, TUR_FLAG_PLAYER | TUR_FLAG_MOVE | TUR_FLAG_ROAM);
+/* mins */ ATTRIB(EWheel, mins, vector, '-32 -32 0');
+/* maxs */ ATTRIB(EWheel, maxs, vector, '32 32 48');
+/* modelname */ ATTRIB(EWheel, mdl, string, "ewheel-base2.md3");
+/* model */ ATTRIB(EWheel, model, string, strzone(strcat("models/turrets/", this.mdl)));
+/* head_model */ ATTRIB(EWheel, head_model, string, strzone(strcat("models/turrets/", "ewheel-gun1.md3")));
+/* netname */ ATTRIB(EWheel, netname, string, "ewheel");
+/* fullname */ ATTRIB(EWheel, turret_name, string, _("eWheel Turret"));
+ ATTRIB(EWheel, m_weapon, Weapon, WEP_EWHEEL);
+ENDCLASS(EWheel)
+REGISTER_TURRET(EWHEEL, NEW(EWheel));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#include "ewheel_weapon.qc"
+
+#ifdef SVQC
+
+float autocvar_g_turrets_unit_ewheel_speed_fast;
+float autocvar_g_turrets_unit_ewheel_speed_slow;
+float autocvar_g_turrets_unit_ewheel_speed_slower;
+float autocvar_g_turrets_unit_ewheel_speed_stop;
+float autocvar_g_turrets_unit_ewheel_turnrate;
+
+const float ewheel_anim_stop = 0;
+const float ewheel_anim_fwd_slow = 1;
+const float ewheel_anim_fwd_fast = 2;
+const float ewheel_anim_bck_slow = 3;
+const float ewheel_anim_bck_fast = 4;
+
+void ewheel_move_path()
+{SELFPARAM();
+#ifdef EWHEEL_FANCYPATH
+ // Are we close enougth to a path node to switch to the next?
+ if (vlen(self.origin - self.pathcurrent.origin) < 64)
+ if (self.pathcurrent.path_next == world)
+ {
+ // Path endpoint reached
+ pathlib_deletepath(self.pathcurrent.owner);
+ self.pathcurrent = world;
+
+ if (self.pathgoal)
+ {
+ if (self.pathgoal.use)
+ self.pathgoal.use();
+
+ if (self.pathgoal.enemy)
+ {
+ self.pathcurrent = pathlib_astar(self.pathgoal.origin,self.pathgoal.enemy.origin);
+ self.pathgoal = self.pathgoal.enemy;
+ }
+ }
+ else
+ self.pathgoal = world;
+ }
+ else
+ self.pathcurrent = self.pathcurrent.path_next;
+
+#else
+ if (vlen(self.origin - self.pathcurrent.origin) < 64)
+ self.pathcurrent = self.pathcurrent.enemy;
+#endif
+
+ if (self.pathcurrent)
+ {
+
+ self.moveto = self.pathcurrent.origin;
+ self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
+
+ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_fast), 0.4);
+ }
+}
+
+void ewheel_move_enemy()
+{SELFPARAM();
+ float newframe;
+
+ self.steerto = steerlib_arrive(self.enemy.origin,self.target_range_optimal);
+
+ self.moveto = self.origin + self.steerto * 128;
+
+ if (self.tur_dist_enemy > self.target_range_optimal)
+ {
+ if ( self.tur_head.spawnshieldtime < 1 )
+ {
+ newframe = ewheel_anim_fwd_fast;
+ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_fast), 0.4);
+ }
+ else if (self.tur_head.spawnshieldtime < 2)
+ {
+
+ newframe = ewheel_anim_fwd_slow;
+ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_slow), 0.4);
+ }
+ else
+ {
+ newframe = ewheel_anim_fwd_slow;
+ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_slower), 0.4);
+ }
+ }
+ else if (self.tur_dist_enemy < self.target_range_optimal * 0.5)
+ {
+ newframe = ewheel_anim_bck_slow;
+ movelib_move_simple(v_forward * -1, (autocvar_g_turrets_unit_ewheel_speed_slow), 0.4);
+ }
+ else
+ {
+ newframe = ewheel_anim_stop;
+ movelib_beak_simple((autocvar_g_turrets_unit_ewheel_speed_stop));
+ }
+
+ turrets_setframe(newframe, false);
+}
+
+void ewheel_move_idle()
+{SELFPARAM();
+ if(self.frame != 0)
+ {
+ self.SendFlags |= TNSF_ANIM;
+ self.anim_start_time = time;
+ }
+
+ self.frame = 0;
+ if (vlen(self.velocity))
+ movelib_beak_simple((autocvar_g_turrets_unit_ewheel_speed_stop));
+}
+
+spawnfunc(turret_ewheel) { if(!turret_initialize(TUR_EWHEEL)) remove(self); }
+
+ METHOD(EWheel, tr_think, void(EWheel thistur))
+ {
+ SELFPARAM();
+ float vz;
+ vector wish_angle, real_angle;
+
+ vz = self.velocity_z;
+
+ self.angles_x = anglemods(self.angles_x);
+ self.angles_y = anglemods(self.angles_y);
+
+ fixedmakevectors(self.angles);
+
+ wish_angle = normalize(self.steerto);
+ wish_angle = vectoangles(wish_angle);
+ real_angle = wish_angle - self.angles;
+ real_angle = shortangle_vxy(real_angle, self.tur_head.angles);
+
+ self.tur_head.spawnshieldtime = fabs(real_angle_y);
+ real_angle_y = bound(-self.tur_head.aim_speed, real_angle_y, self.tur_head.aim_speed);
+ self.angles_y = (self.angles_y + real_angle_y);
+
+ if(self.enemy)
+ ewheel_move_enemy();
+ else if(self.pathcurrent)
+ ewheel_move_path();
+ else
+ ewheel_move_idle();
+
+ self.velocity_z = vz;
+
+ if(vlen(self.velocity))
+ self.SendFlags |= TNSF_MOVE;
+ }
+ METHOD(EWheel, tr_death, void(EWheel this, entity it))
+ {
+ it.velocity = '0 0 0';
+
+#ifdef EWHEEL_FANCYPATH
+ if (self.pathcurrent)
+ pathlib_deletepath(it.pathcurrent.owner);
+#endif
+ it.pathcurrent = NULL;
+ }
+ METHOD(EWheel, tr_setup, void(EWheel this, entity it))
+ {
+ entity e;
+
+ if(it.movetype == MOVETYPE_WALK)
+ {
+ it.velocity = '0 0 0';
+ it.enemy = world;
+
+ setorigin(it, it.pos1);
+
+ if (it.target != "")
+ {
+ e = find(world, targetname, it.target);
+ if (!e)
+ {
+ LOG_TRACE("Initital waypoint for ewheel does NOT exsist, fix your map!\n");
+ it.target = "";
+ }
+
+ if (e.classname != "turret_checkpoint")
+ LOG_TRACE("Warning: not a turrret path\n");
+ else
+ {
+
+#ifdef EWHEEL_FANCYPATH
+ it.pathcurrent = WALKER_PATH(it.origin,e.origin);
+ it.pathgoal = e;
+#else
+ it.pathcurrent = e;
+#endif
+ }
+ }
+ }
+
+ it.iscreature = true;
+ it.teleportable = TELEPORT_NORMAL;
+ it.damagedbycontents = true;
+ it.movetype = MOVETYPE_WALK;
+ it.solid = SOLID_SLIDEBOX;
+ it.takedamage = DAMAGE_AIM;
+ it.idle_aim = '0 0 0';
+ it.pos1 = it.origin;
+ it.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+ it.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+ it.frame = it.tur_head.frame = 1;
+ it.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+
+ // Convert from dgr / sec to dgr / tic
+ it.tur_head.aim_speed = (autocvar_g_turrets_unit_ewheel_turnrate);
+ it.tur_head.aim_speed = it.tur_head.aim_speed / (1 / it.ticrate);
+ }
+
+#endif // SVQC
+#ifdef CSQC
+
+void ewheel_draw(entity this)
+{
+ float dt;
+
+ dt = time - self.move_time;
+ self.move_time = time;
+ if(dt <= 0)
+ return;
+
+ fixedmakevectors(self.angles);
+ setorigin(self, self.origin + self.velocity * dt);
+ self.tur_head.angles += dt * self.tur_head.move_avelocity;
+ self.angles_y = self.move_angles_y;
+
+ if (self.health < 127)
+ if(random() < 0.05)
+ te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
+}
+
+ METHOD(EWheel, tr_setup, void(EWheel this, entity it))
+ {
+ it.gravity = 1;
+ it.movetype = MOVETYPE_BOUNCE;
+ it.move_movetype = MOVETYPE_BOUNCE;
+ it.move_origin = it.origin;
+ it.move_time = time;
+ it.draw = ewheel_draw;
+ }
+
+#endif // CSQC
+#endif
--- /dev/null
+#ifndef TURRET_EWHEEL_WEAPON_H
+#define TURRET_EWHEEL_WEAPON_H
+
+CLASS(EWheelAttack, PortoLaunch)
+/* flags */ ATTRIB(EWheelAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse */ ATTRIB(EWheelAttack, impulse, int, 5);
+/* refname */ ATTRIB(EWheelAttack, netname, string, "turret_ewheel");
+/* wepname */ ATTRIB(EWheelAttack, message, string, _("eWheel"));
+ENDCLASS(EWheelAttack)
+REGISTER_WEAPON(EWHEEL, NEW(EWheelAttack));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+void turret_initparams(entity);
+METHOD(EWheelAttack, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2)) {
+ bool isPlayer = IS_PLAYER(actor);
+ if (fire1)
+ if (!isPlayer || weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(electro, refire))) {
+ if (isPlayer) {
+ turret_initparams(actor);
+ W_SetupShot_Dir(actor, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+ actor.tur_shotdir_updated = w_shotdir;
+ actor.tur_shotorg = w_shotorg;
+ actor.tur_head = actor;
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready);
+ }
+
+ turret_do_updates(actor);
+
+ entity missile = turret_projectile(SND(LASERGUN_FIRE), 1, 0, DEATH_TURRET_EWHEEL, PROJECTILE_BLASTER, true, true);
+ missile.missile_flags = MIF_SPLASH;
+
+ Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, actor.tur_shotorg, actor.tur_shotdir_updated * 1000, 1);
+
+ if (!isPlayer) {
+ actor.tur_head.frame += 2;
+
+ if (actor.tur_head.frame > 3)
+ actor.tur_head.frame = 0;
+ }
+ }
+}
+
+#endif
+
+#endif
--- /dev/null
+#ifndef TURRET_FLAC_H
+#define TURRET_FLAC_H
+
+#include "flac_weapon.qc"
+
+CLASS(Flac, Turret)
+/* spawnflags */ ATTRIB(Flac, spawnflags, int, TUR_FLAG_SPLASH | TUR_FLAG_FASTPROJ | TUR_FLAG_MISSILE);
+/* mins */ ATTRIB(Flac, mins, vector, '-32 -32 0');
+/* maxs */ ATTRIB(Flac, maxs, vector, '32 32 64');
+/* modelname */ ATTRIB(Flac, mdl, string, "base.md3");
+/* model */ ATTRIB(Flac, model, string, strzone(strcat("models/turrets/", this.mdl)));
+/* head_model */ ATTRIB(Flac, head_model, string, strzone(strcat("models/turrets/", "flac.md3")));
+/* netname */ ATTRIB(Flac, netname, string, "flac");
+/* fullname */ ATTRIB(Flac, turret_name, string, _("FLAC Cannon"));
+ ATTRIB(Flac, m_weapon, Weapon, WEP_FLAC);
+ENDCLASS(Flac)
+REGISTER_TURRET(FLAC, NEW(Flac));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#include "flac_weapon.qc"
+
+#ifdef SVQC
+
+spawnfunc(turret_flac) { if (!turret_initialize(TUR_FLAC)) remove(self); }
+
+METHOD(Flac, tr_setup, void(Flac this, entity it))
+{
+ it.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
+ it.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
+ it.damage_flags |= TFL_DMG_HEADSHAKE;
+ it.target_select_flags |= TFL_TARGETSELECT_NOTURRETS | TFL_TARGETSELECT_MISSILESONLY;
+}
+
+#endif
+
+#endif
--- /dev/null
+#ifndef TURRET_FLAC_WEAPON_H
+#define TURRET_FLAC_WEAPON_H
+
+CLASS(FlacAttack, PortoLaunch)
+/* flags */ ATTRIB(FlacAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse */ ATTRIB(FlacAttack, impulse, int, 5);
+/* refname */ ATTRIB(FlacAttack, netname, string, "turret_flac");
+/* wepname */ ATTRIB(FlacAttack, message, string, _("FLAC"));
+ENDCLASS(FlacAttack)
+REGISTER_WEAPON(FLAC, NEW(FlacAttack));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+void turret_flac_projectile_think_explode();
+METHOD(FlacAttack, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2)) {
+ bool isPlayer = IS_PLAYER(actor);
+ if (fire1)
+ if (!isPlayer || weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(electro, refire))) {
+ if (isPlayer) {
+ turret_initparams(actor);
+ W_SetupShot_Dir(actor, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+ actor.tur_shotdir_updated = w_shotdir;
+ actor.tur_shotorg = w_shotorg;
+ actor.tur_head = actor;
+ actor.tur_impacttime = 10;
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready);
+ }
+
+ turret_tag_fire_update();
+
+ entity proj = turret_projectile(SND(HAGAR_FIRE), 5, 0, DEATH_TURRET_FLAC, PROJECTILE_HAGAR, true, true);
+ proj.missile_flags = MIF_SPLASH | MIF_PROXY;
+ proj.think = turret_flac_projectile_think_explode;
+ proj.nextthink = time + actor.tur_impacttime + (random() * 0.01 - random() * 0.01);
+ Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, actor.tur_shotorg, actor.tur_shotdir_updated * 1000, 1);
+
+ if (!isPlayer) {
+ actor.tur_head.frame = actor.tur_head.frame + 1;
+ if (actor.tur_head.frame >= 4)
+ actor.tur_head.frame = 0;
+ }
+ }
+}
+
+void turret_flac_projectile_think_explode()
+{
+ SELFPARAM();
+ if (self.enemy != world)
+ if (vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 3)
+ setorigin(self,self.enemy.origin + randomvec() * self.owner.shot_radius);
+
+#ifdef TURRET_DEBUG
+ float d = RadiusDamage (self, self.owner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world);
+ self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d;
+ self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
+#else
+ RadiusDamage (self, self.realowner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world);
+#endif
+ remove(self);
+}
+
+#endif
+
+#endif
--- /dev/null
+#ifndef TURRET_FUSIONREACTOR_H
+#define TURRET_FUSIONREACTOR_H
+
+CLASS(FusionReactor, Turret)
+/* spawnflags */ ATTRIB(FusionReactor, spawnflags, int, TUR_FLAG_SUPPORT | TUR_FLAG_AMMOSOURCE);
+/* mins */ ATTRIB(FusionReactor, mins, vector, '-34 -34 0');
+/* maxs */ ATTRIB(FusionReactor, maxs, vector, '34 34 90');
+/* modelname */ ATTRIB(FusionReactor, mdl, string, "base.md3");
+/* model */ ATTRIB(FusionReactor, model, string, strzone(strcat("models/turrets/", this.mdl)));
+/* head_model */ ATTRIB(FusionReactor, head_model, string, strzone(strcat("models/turrets/", "reactor.md3")));
+/* netname */ ATTRIB(FusionReactor, netname, string, "fusionreactor");
+/* fullname */ ATTRIB(FusionReactor, turret_name, string, _("Fusion Reactor"));
+ENDCLASS(FusionReactor)
+REGISTER_TURRET(FUSIONREACTOR, NEW(FusionReactor));
+
+#endif
+
+#ifdef IMPLEMENTATION
+#ifdef SVQC
+bool turret_fusionreactor_firecheck()
+{SELFPARAM();
+ if (self.attack_finished_single > time)
+ return false;
+
+ if (self.enemy.deadflag != DEAD_NO)
+ return false;
+
+ if (self.enemy == world)
+ return false;
+
+ if (self.ammo < self.shot_dmg)
+ return false;
+
+ if (self.enemy.ammo >= self.enemy.ammo_max)
+ return false;
+
+ if (vlen(self.enemy.origin - self.origin) > self.target_range)
+ return false;
+
+ if(self.team != self.enemy.team)
+ return false;
+
+ if(!(self.enemy.ammo_flags & TFL_AMMO_ENERGY))
+ return false;
+
+ return true;
+}
+
+spawnfunc(turret_fusionreactor) { if (!turret_initialize(TUR_FUSIONREACTOR)) remove(self); }
+
+METHOD(FusionReactor, tr_attack, void(FusionReactor this))
+{
+ self.enemy.ammo = min(self.enemy.ammo + self.shot_dmg,self.enemy.ammo_max);
+ vector fl_org = 0.5 * (self.enemy.absmin + self.enemy.absmax);
+ te_smallflash(fl_org);
+}
+METHOD(FusionReactor, tr_think, void(FusionReactor thistur))
+{
+ self.tur_head.avelocity = '0 250 0' * (self.ammo / self.ammo_max);
+}
+METHOD(FusionReactor, tr_setup, void(FusionReactor this, entity it))
+{
+ it.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE;
+ it.target_select_flags = TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_OWNTEAM | TFL_TARGETSELECT_RANGELIMITS;
+ it.firecheck_flags = TFL_FIRECHECK_AMMO_OWN | TFL_FIRECHECK_AMMO_OTHER | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_DEAD;
+ it.shoot_flags = TFL_SHOOT_HITALLVALID;
+ it.aim_flags = TFL_AIM_NO;
+ it.track_flags = TFL_TRACK_NO;
+
+ it.tur_head.scale = 0.75;
+ it.tur_head.avelocity = '0 50 0';
+
+ it.turret_firecheckfunc = turret_fusionreactor_firecheck;
+}
+
+#endif
+#endif
--- /dev/null
+#ifndef TURRET_HELLION_H
+#define TURRET_HELLION_H
+
+#include "hellion_weapon.qc"
+
+CLASS(Hellion, Turret)
+/* spawnflags */ ATTRIB(Hellion, spawnflags, int, TUR_FLAG_SPLASH | TUR_FLAG_FASTPROJ | TUR_FLAG_PLAYER | TUR_FLAG_MISSILE);
+/* mins */ ATTRIB(Hellion, mins, vector, '-32 -32 0');
+/* maxs */ ATTRIB(Hellion, maxs, vector, '32 32 64');
+/* modelname */ ATTRIB(Hellion, mdl, string, "base.md3");
+/* model */ ATTRIB(Hellion, model, string, strzone(strcat("models/turrets/", this.mdl)));
+/* head_model */ ATTRIB(Hellion, head_model, string, strzone(strcat("models/turrets/", "hellion.md3")));
+/* netname */ ATTRIB(Hellion, netname, string, "hellion");
+/* fullname */ ATTRIB(Hellion, turret_name, string, _("Hellion Missile Turret"));
+ ATTRIB(Hellion, m_weapon, Weapon, WEP_HELLION);
+ENDCLASS(Hellion)
+REGISTER_TURRET(HELLION, NEW(Hellion));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#include "hellion_weapon.qc"
+
+#ifdef SVQC
+
+spawnfunc(turret_hellion) { if (!turret_initialize(TUR_HELLION)) remove(self); }
+
+METHOD(Hellion, tr_think, void(Hellion thistur))
+{
+ if (self.tur_head.frame != 0)
+ self.tur_head.frame += 1;
+
+ if (self.tur_head.frame >= 7)
+ self.tur_head.frame = 0;
+}
+METHOD(Hellion, tr_setup, void(Hellion this, entity it))
+{
+ it.aim_flags = TFL_AIM_SIMPLE;
+ it.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK ;
+ it.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_TEAMCHECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF | TFL_FIRECHECK_AMMO_OWN;
+ it.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
+}
+
+#endif
+#endif
--- /dev/null
+#ifndef TURRET_HELLION_WEAPON_H
+#define TURRET_HELLION_WEAPON_H
+
+CLASS(HellionAttack, PortoLaunch)
+/* flags */ ATTRIB(HellionAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse */ ATTRIB(HellionAttack, impulse, int, 9);
+/* refname */ ATTRIB(HellionAttack, netname, string, "turret_hellion");
+/* wepname */ ATTRIB(HellionAttack, message, string, _("Hellion"));
+ENDCLASS(HellionAttack)
+REGISTER_WEAPON(HELLION, NEW(HellionAttack));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+float autocvar_g_turrets_unit_hellion_shot_speed_gain;
+float autocvar_g_turrets_unit_hellion_shot_speed_max;
+
+void turret_hellion_missile_think();
+METHOD(HellionAttack, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2)) {
+ bool isPlayer = IS_PLAYER(actor);
+ if (fire1)
+ if (!isPlayer || weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(electro, refire))) {
+ if (isPlayer) {
+ turret_initparams(actor);
+ W_SetupShot_Dir(actor, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+ actor.tur_shotdir_updated = w_shotdir;
+ actor.tur_shotorg = w_shotorg;
+ actor.tur_head = actor;
+ actor.shot_radius = 500;
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready);
+ }
+ if (!isPlayer) {
+ if (actor.tur_head.frame != 0)
+ actor.tur_shotorg = gettaginfo(actor.tur_head, gettagindex(actor.tur_head, "tag_fire"));
+ else
+ actor.tur_shotorg = gettaginfo(actor.tur_head, gettagindex(actor.tur_head, "tag_fire2"));
+ }
+
+ entity missile = turret_projectile(SND(ROCKET_FIRE), 6, 10, DEATH_TURRET_HELLION, PROJECTILE_ROCKET, FALSE, FALSE);
+ te_explosion (missile.origin);
+ missile.think = turret_hellion_missile_think;
+ missile.nextthink = time;
+ missile.flags = FL_PROJECTILE;
+ missile.max_health = time + 9;
+ missile.tur_aimpos = randomvec() * 128;
+ missile.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_HEAT;
+ if (!isPlayer) actor.tur_head.frame += 1;
+ }
+}
+
+void turret_hellion_missile_think()
+{SELFPARAM();
+ vector olddir,newdir;
+ vector pre_pos;
+ float itime;
+
+ self.nextthink = time + 0.05;
+
+ olddir = normalize(self.velocity);
+
+ if(self.max_health < time)
+ turret_projectile_explode();
+
+ // Enemy dead? just keep on the current heading then.
+ if ((self.enemy == world) || (self.enemy.deadflag != DEAD_NO))
+ {
+
+ // Make sure we dont return to tracking a respawned player
+ self.enemy = world;
+
+ // Turn model
+ self.angles = vectoangles(self.velocity);
+
+ if ( (vlen(self.origin - self.owner.origin)) > (self.owner.shot_radius * 5) )
+ turret_projectile_explode();
+
+ // Accelerate
+ self.velocity = olddir * min(vlen(self.velocity) * (autocvar_g_turrets_unit_hellion_shot_speed_gain), (autocvar_g_turrets_unit_hellion_shot_speed_max));
+
+ UpdateCSQCProjectile(self);
+
+ return;
+ }
+
+ // Enemy in range?
+ if (vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 0.2)
+ turret_projectile_explode();
+
+ // Predict enemy position
+ itime = vlen(self.enemy.origin - self.origin) / vlen(self.velocity);
+ pre_pos = self.enemy.origin + self.enemy.velocity * itime;
+
+ pre_pos = (pre_pos + self.enemy.origin) * 0.5;
+
+ // Find out the direction to that place
+ newdir = normalize(pre_pos - self.origin);
+
+ // Turn
+ newdir = normalize(olddir + newdir * 0.35);
+
+ // Turn model
+ self.angles = vectoangles(self.velocity);
+
+ // Accelerate
+ self.velocity = newdir * min(vlen(self.velocity) * (autocvar_g_turrets_unit_hellion_shot_speed_gain), (autocvar_g_turrets_unit_hellion_shot_speed_max));
+
+ if (itime < 0.05)
+ self.think = turret_projectile_explode;
+
+ UpdateCSQCProjectile(self);
+}
+
+#endif
+
+#endif
--- /dev/null
+#ifndef TURRET_HK_H
+#define TURRET_HK_H
+
+//#define TURRET_DEBUG_HK
+
+#include "hk_weapon.qc"
+
+CLASS(HunterKiller, Turret)
+/* spawnflags */ ATTRIB(HunterKiller, spawnflags, int, TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER | TUR_FLAG_RECIEVETARGETS);
+/* mins */ ATTRIB(HunterKiller, mins, vector, '-32 -32 0');
+/* maxs */ ATTRIB(HunterKiller, maxs, vector, '32 32 64');
+/* modelname */ ATTRIB(HunterKiller, mdl, string, "base.md3");
+/* model */ ATTRIB(HunterKiller, model, string, strzone(strcat("models/turrets/", this.mdl)));
+/* head_model */ ATTRIB(HunterKiller, head_model, string, strzone(strcat("models/turrets/", "hk.md3")));
+/* netname */ ATTRIB(HunterKiller, netname, string, "hk");
+/* fullname */ ATTRIB(HunterKiller, turret_name, string, _("Hunter-Killer Turret"));
+ ATTRIB(HunterKiller, m_weapon, Weapon, WEP_HK);
+ENDCLASS(HunterKiller)
+REGISTER_TURRET(HK, NEW(HunterKiller));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#include "hk_weapon.qc"
+
+#ifdef SVQC
+
+#ifdef TURRET_DEBUG_HK
+.float atime;
+#endif
+
+spawnfunc(turret_hk) { if(!turret_initialize(TUR_HK)) remove(self); }
+
+METHOD(HunterKiller, tr_think, void(HunterKiller thistur))
+{
+ if (self.tur_head.frame != 0)
+ self.tur_head.frame = self.tur_head.frame + 1;
+
+ if (self.tur_head.frame > 5)
+ self.tur_head.frame = 0;
+}
+
+float turret_hk_addtarget(entity e_target,entity e_sender);
+METHOD(HunterKiller, tr_setup, void(HunterKiller this, entity it))
+{
+ it.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
+ it.aim_flags = TFL_AIM_SIMPLE;
+ it.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TRIGGERTARGET | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
+ it.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_TEAMCHECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF;
+ it.shoot_flags = TFL_SHOOT_CLEARTARGET;
+ it.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TEAMCHECK;
+
+ it.turret_addtarget = turret_hk_addtarget;
+}
+
+float turret_hk_addtarget(entity e_target,entity e_sender)
+{SELFPARAM();
+ if (e_target)
+ {
+ if (turret_validate_target(self,e_target,self.target_validate_flags) > 0)
+ {
+ self.enemy = e_target;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+#endif // SVQC
+#endif
--- /dev/null
+#ifndef TURRET_HK_WEAPON_H
+#define TURRET_HK_WEAPON_H
+
+CLASS(HunterKillerAttack, PortoLaunch)
+/* flags */ ATTRIB(HunterKillerAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse */ ATTRIB(HunterKillerAttack, impulse, int, 9);
+/* refname */ ATTRIB(HunterKillerAttack, netname, string, "turret_hk");
+/* wepname */ ATTRIB(HunterKillerAttack, message, string, _("Hunter-Killer"));
+ENDCLASS(HunterKillerAttack)
+REGISTER_WEAPON(HK, NEW(HunterKillerAttack));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+float autocvar_g_turrets_unit_hk_shot_speed;
+float autocvar_g_turrets_unit_hk_shot_speed_accel;
+float autocvar_g_turrets_unit_hk_shot_speed_accel2;
+float autocvar_g_turrets_unit_hk_shot_speed_decel;
+float autocvar_g_turrets_unit_hk_shot_speed_max;
+float autocvar_g_turrets_unit_hk_shot_speed_turnrate;
+
+void turret_hk_missile_think();
+METHOD(HunterKillerAttack, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
+{
+ bool isPlayer = IS_PLAYER(actor);
+ if (fire1)
+ if (!isPlayer || weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(electro, refire))) {
+ if (isPlayer) {
+ turret_initparams(actor);
+ W_SetupShot_Dir(actor, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+ actor.tur_shotdir_updated = w_shotdir;
+ actor.tur_shotorg = w_shotorg;
+ actor.tur_head = actor;
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready);
+ }
+ entity missile = turret_projectile(SND(ROCKET_FIRE), 6, 10, DEATH_TURRET_HK, PROJECTILE_ROCKET, FALSE, FALSE);
+ te_explosion (missile.origin);
+
+ missile.think = turret_hk_missile_think;
+ missile.nextthink = time + 0.25;
+ missile.movetype = MOVETYPE_BOUNCEMISSILE;
+ missile.velocity = actor.tur_shotdir_updated * (actor.shot_speed * 0.75);
+ missile.angles = vectoangles(missile.velocity);
+ missile.cnt = time + 30;
+ missile.ticrate = max(autocvar_sys_ticrate, 0.05);
+ missile.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_AI;
+
+ if (!isPlayer)
+ if (actor.tur_head.frame == 0)
+ actor.tur_head.frame = actor.tur_head.frame + 1;
+ }
+}
+
+bool hk_is_valid_target(entity e_target);
+void turret_hk_missile_think()
+{SELFPARAM();
+ vector vu, vd, vf, vl, vr, ve; // Vector (direction)
+ float fu, fd, ff, fl, fr, fe; // Fraction to solid
+ vector olddir,wishdir,newdir; // Final direction
+ float lt_for; // Length of Trace FORwrad
+ float lt_seek; // Length of Trace SEEK (left, right, up down)
+ float pt_seek; // Pitch of Trace SEEK (How mutch to angele left, right up, down trace towards v_forward)
+ vector pre_pos;
+ float myspeed;
+ entity e;
+ float ad,edist;
+
+ self.nextthink = time + self.ticrate;
+
+ //if (self.cnt < time)
+ // turret_hk_missile_explode();
+
+ if (self.enemy.deadflag != DEAD_NO)
+ self.enemy = world;
+
+ // Pick the closest valid target.
+ if (!self.enemy)
+ {
+ e = findradius(self.origin, 5000);
+ while (e)
+ {
+ if (hk_is_valid_target(e))
+ {
+ if (!self.enemy)
+ self.enemy = e;
+ else
+ if (vlen(self.origin - e.origin) < vlen(self.origin - self.enemy.origin))
+ self.enemy = e;
+ }
+ e = e.chain;
+ }
+ }
+
+ self.angles = vectoangles(self.velocity);
+ self.angles_x = self.angles_x * -1;
+ makevectors(self.angles);
+ self.angles_x = self.angles_x * -1;
+
+ if (self.enemy)
+ {
+ edist = vlen(self.origin - self.enemy.origin);
+ // Close enougth to do decent damage?
+ if ( edist <= (self.owner.shot_radius * 0.25) )
+ {
+ turret_projectile_explode();
+ return;
+ }
+
+ // Get data on enemy position
+ pre_pos = self.enemy.origin +
+ self.enemy.velocity *
+ min((vlen(self.enemy.origin - self.origin) / vlen(self.velocity)),0.5);
+
+ traceline(self.origin, pre_pos,true,self.enemy);
+ ve = normalize(pre_pos - self.origin);
+ fe = trace_fraction;
+
+ }
+ else
+ {
+ edist = 0;
+ ve = '0 0 0';
+ fe = 0;
+ }
+
+ if ((fe != 1) || (self.enemy == world) || (edist > 1000))
+ {
+ myspeed = vlen(self.velocity);
+
+ lt_for = myspeed * 3;
+ lt_seek = myspeed * 2.95;
+
+ // Trace forward
+ traceline(self.origin, self.origin + v_forward * lt_for,false,self);
+ vf = trace_endpos;
+ ff = trace_fraction;
+
+ // Find angular offset
+ ad = vlen(vectoangles(normalize(self.enemy.origin - self.origin)) - self.angles);
+
+ // To close to something, Slow down!
+ if ( ((ff < 0.7) || (ad > 4)) && (myspeed > (autocvar_g_turrets_unit_hk_shot_speed)) )
+ myspeed = max(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_decel), (autocvar_g_turrets_unit_hk_shot_speed));
+
+ // Failry clear, accelerate.
+ if ( (ff > 0.7) && (myspeed < (autocvar_g_turrets_unit_hk_shot_speed_max)) )
+ myspeed = min(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_accel), (autocvar_g_turrets_unit_hk_shot_speed_max));
+
+ // Setup trace pitch
+ pt_seek = 1 - ff;
+ pt_seek = bound(0.15,pt_seek,0.8);
+ if (ff < 0.5) pt_seek = 1;
+
+ // Trace left
+ traceline(self.origin, self.origin + (-1 * (v_right * pt_seek) + (v_forward * ff)) * lt_seek,false,self);
+ vl = trace_endpos;
+ fl = trace_fraction;
+
+ // Trace right
+ traceline(self.origin, self.origin + ((v_right * pt_seek) + (v_forward * ff)) * lt_seek ,false,self);
+ vr = trace_endpos;
+ fr = trace_fraction;
+
+ // Trace up
+ traceline(self.origin, self.origin + ((v_up * pt_seek) + (v_forward * ff)) * lt_seek ,false,self);
+ vu = trace_endpos;
+ fu = trace_fraction;
+
+ // Trace down
+ traceline(self.origin, self.origin + (-1 * (v_up * pt_seek) + (v_forward * ff)) * lt_seek ,false,self);
+ vd = trace_endpos;
+ fd = trace_fraction;
+
+ vl = normalize(vl - self.origin);
+ vr = normalize(vr - self.origin);
+ vu = normalize(vu - self.origin);
+ vd = normalize(vd - self.origin);
+
+ // Panic tresh passed, find a single direction and turn as hard as we can
+ if (pt_seek == 1)
+ {
+ wishdir = v_right;
+ if (fl > fr) wishdir = -1 * v_right;
+ if (fu > fl) wishdir = v_up;
+ if (fd > fu) wishdir = -1 * v_up;
+ }
+ else
+ {
+ // Normalize our trace vectors to make a smooth path
+ wishdir = normalize( (vl * fl) + (vr * fr) + (vu * fu) + (vd * fd) );
+ }
+
+ if (self.enemy)
+ {
+ if (fe < 0.1) fe = 0.1; // Make sure we always try to move sligtly towards our target
+ wishdir = (wishdir * (1 - fe)) + (ve * fe);
+ }
+ }
+ else
+ {
+ // Got a clear path to target, speed up fast (if not at full speed) and go straight for it.
+ myspeed = vlen(self.velocity);
+ if (myspeed < (autocvar_g_turrets_unit_hk_shot_speed_max))
+ myspeed = min(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_accel2),(autocvar_g_turrets_unit_hk_shot_speed_max));
+
+ wishdir = ve;
+ }
+
+ if ((myspeed > (autocvar_g_turrets_unit_hk_shot_speed)) && (self.cnt > time))
+ myspeed = min(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_accel2),(autocvar_g_turrets_unit_hk_shot_speed_max));
+
+ // Ranoutagazfish?
+ if (self.cnt < time)
+ {
+ self.cnt = time + 0.25;
+ self.nextthink = 0;
+ self.movetype = MOVETYPE_BOUNCE;
+ return;
+ }
+
+ // Calculate new heading
+ olddir = normalize(self.velocity);
+ newdir = normalize(olddir + wishdir * (autocvar_g_turrets_unit_hk_shot_speed_turnrate));
+
+ // Set heading & speed
+ self.velocity = newdir * myspeed;
+
+ // Align model with new heading
+ self.angles = vectoangles(self.velocity);
+
+
+#ifdef TURRET_DEBUG_HK
+ //if(self.atime < time) {
+ if ((fe <= 0.99)||(edist > 1000))
+ {
+ te_lightning2(world,self.origin, self.origin + vr * lt_seek);
+ te_lightning2(world,self.origin, self.origin + vl * lt_seek);
+ te_lightning2(world,self.origin, self.origin + vu * lt_seek);
+ te_lightning2(world,self.origin, self.origin + vd * lt_seek);
+ te_lightning2(world,self.origin, vf);
+ }
+ else
+ {
+ te_lightning2(world,self.origin, self.enemy.origin);
+ }
+ bprint("Speed: ", ftos(rint(myspeed)), "\n");
+ bprint("Trace to solid: ", ftos(rint(ff * 100)), "%\n");
+ bprint("Trace to target:", ftos(rint(fe * 100)), "%\n");
+ self.atime = time + 0.2;
+ //}
+#endif
+
+ UpdateCSQCProjectile(self);
+}
+
+bool hk_is_valid_target(entity e_target)
+{SELFPARAM();
+ if (e_target == world)
+ return 0;
+
+ // If only this was used more..
+ if (e_target.flags & FL_NOTARGET)
+ return 0;
+
+ // Cant touch this
+ if ((e_target.takedamage == DAMAGE_NO) || (e_target.health < 0))
+ return 0;
+
+ // player
+ if (IS_CLIENT(e_target))
+ {
+ if (self.owner.target_select_playerbias < 0)
+ return 0;
+
+ if (e_target.deadflag != DEAD_NO)
+ return 0;
+ }
+
+ // Missile
+ if ((e_target.flags & FL_PROJECTILE) && (self.owner.target_select_missilebias < 0))
+ return 0;
+
+ // Team check
+ if ((e_target.team == self.owner.team) || (self.owner.team == e_target.owner.team))
+ return 0;
+
+ return 1;
+}
+
+#endif
+
+#endif
--- /dev/null
+#ifndef TURRET_MACHINEGUN_H
+#define TURRET_MACHINEGUN_H
+
+#include "machinegun_weapon.qc"
+
+CLASS(MachineGunTurret, Turret)
+/* spawnflags */ ATTRIB(MachineGunTurret, spawnflags, int, TUR_FLAG_PLAYER);
+/* mins */ ATTRIB(MachineGunTurret, mins, vector, '-32 -32 0');
+/* maxs */ ATTRIB(MachineGunTurret, maxs, vector, '32 32 64');
+/* modelname */ ATTRIB(MachineGunTurret, mdl, string, "base.md3");
+/* model */ ATTRIB(MachineGunTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
+/* head_model */ ATTRIB(MachineGunTurret, head_model, string, strzone(strcat("models/turrets/", "machinegun.md3")));
+/* netname */ ATTRIB(MachineGunTurret, netname, string, "machinegun");
+/* fullname */ ATTRIB(MachineGunTurret, turret_name, string, _("Machinegun Turret"));
+ ATTRIB(MachineGunTurret, m_weapon, Weapon, WEP_TUR_MACHINEGUN);
+ENDCLASS(MachineGunTurret)
+REGISTER_TURRET(MACHINEGUN, NEW(MachineGunTurret));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#include "machinegun_weapon.qc"
+
+#ifdef SVQC
+
+spawnfunc(turret_machinegun) { if (!turret_initialize(TUR_MACHINEGUN)) remove(self); }
+
+METHOD(MachineGunTurret, tr_setup, void(MachineGunTurret this, entity it))
+{
+ it.damage_flags |= TFL_DMG_HEADSHAKE;
+ it.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
+ it.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+ it.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
+ it.turret_flags |= TUR_FLAG_HITSCAN;
+}
+
+#endif // SVQC
+#endif
--- /dev/null
+#ifndef TURRET_MACHINEGUN_WEAPON_H
+#define TURRET_MACHINEGUN_WEAPON_H
+
+CLASS(MachineGunTurretAttack, PortoLaunch)
+/* flags */ ATTRIB(MachineGunTurretAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse */ ATTRIB(MachineGunTurretAttack, impulse, int, 9);
+/* refname */ ATTRIB(MachineGunTurretAttack, netname, string, "turret_machinegun");
+/* wepname */ ATTRIB(MachineGunTurretAttack, message, string, _("Machinegun"));
+ENDCLASS(MachineGunTurretAttack)
+REGISTER_WEAPON(TUR_MACHINEGUN, NEW(MachineGunTurretAttack));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+void W_MachineGun_MuzzleFlash();
+
+METHOD(MachineGunTurretAttack, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
+{
+ bool isPlayer = IS_PLAYER(actor);
+ if (fire1)
+ if (!isPlayer || weapon_prepareattack(thiswep, actor, false, WEP_CVAR(machinegun, sustained_refire))) {
+ if (isPlayer) {
+ turret_initparams(actor);
+ W_SetupShot_Dir(actor, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+ actor.tur_shotdir_updated = w_shotdir;
+ actor.tur_shotorg = w_shotorg;
+ actor.tur_head = actor;
+ weapon_thinkf(actor, WFRAME_FIRE1, 0, w_ready);
+ }
+ fireBullet (actor.tur_shotorg, actor.tur_shotdir_updated, actor.shot_spread, 0, actor.shot_dmg, actor.shot_force, DEATH_TURRET_MACHINEGUN, 0);
+ W_MachineGun_MuzzleFlash();
+ setattachment(actor.muzzle_flash, actor.tur_head, "tag_fire");
+ }
+}
+
+#endif
+
+#endif
--- /dev/null
+#ifndef TURRET_MLRS_H
+#define TURRET_MLRS_H
+
+#include "mlrs_weapon.qc"
+
+CLASS(MLRSTurret, Turret)
+/* spawnflags */ ATTRIB(MLRSTurret, spawnflags, int, TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER);
+/* mins */ ATTRIB(MLRSTurret, mins, vector, '-32 -32 0');
+/* maxs */ ATTRIB(MLRSTurret, maxs, vector, '32 32 64');
+/* modelname */ ATTRIB(MLRSTurret, mdl, string, "base.md3");
+/* model */ ATTRIB(MLRSTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
+/* head_model */ ATTRIB(MLRSTurret, head_model, string, strzone(strcat("models/turrets/", "mlrs.md3")));
+/* netname */ ATTRIB(MLRSTurret, netname, string, "mlrs");
+/* fullname */ ATTRIB(MLRSTurret, turret_name, string, _("MLRS Turret"));
+ ATTRIB(MLRSTurret, m_weapon, Weapon, WEP_TUR_MLRS);
+ENDCLASS(MLRSTurret)
+REGISTER_TURRET(MLRS, NEW(MLRSTurret));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#include "mlrs_weapon.qc"
+
+#ifdef SVQC
+
+spawnfunc(turret_mlrs) { if (!turret_initialize(TUR_MLRS)) remove(self); }
+
+METHOD(MLRSTurret, tr_think, void(MLRSTurret thistur))
+{
+ // 0 = full, 6 = empty
+ self.tur_head.frame = bound(0, 6 - floor(0.1 + self.ammo / self.shot_dmg), 6);
+ if(self.tur_head.frame < 0)
+ {
+ LOG_TRACE("ammo:",ftos(self.ammo),"\n");
+ LOG_TRACE("shot_dmg:",ftos(self.shot_dmg),"\n");
+ }
+}
+METHOD(MLRSTurret, tr_setup, void(MLRSTurret this, entity it))
+{
+ it.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
+ it.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
+
+ it.damage_flags |= TFL_DMG_HEADSHAKE;
+ it.shoot_flags |= TFL_SHOOT_VOLLYALWAYS;
+ it.volly_counter = it.shot_volly;
+}
+
+#endif // SVQC
+#endif
--- /dev/null
+#ifndef TURRET_MLRS_WEAPON_H
+#define TURRET_MLRS_WEAPON_H
+
+CLASS(MLRSTurretAttack, PortoLaunch)
+/* flags */ ATTRIB(MLRSTurretAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse */ ATTRIB(MLRSTurretAttack, impulse, int, 9);
+/* refname */ ATTRIB(MLRSTurretAttack, netname, string, "turret_mlrs");
+/* wepname */ ATTRIB(MLRSTurretAttack, message, string, _("MLRS"));
+ENDCLASS(MLRSTurretAttack)
+REGISTER_WEAPON(TUR_MLRS, NEW(MLRSTurretAttack));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+METHOD(MLRSTurretAttack, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
+{
+ bool isPlayer = IS_PLAYER(actor);
+ if (fire1)
+ if (!isPlayer || weapon_prepareattack(thiswep, actor, false, WEP_CVAR(machinegun, sustained_refire))) {
+ if (isPlayer) {
+ turret_initparams(actor);
+ W_SetupShot_Dir(actor, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+ actor.tur_shotdir_updated = w_shotdir;
+ actor.tur_shotorg = w_shotorg;
+ actor.tur_head = actor;
+ actor.shot_radius = 500;
+ weapon_thinkf(actor, WFRAME_FIRE1, 0, w_ready);
+ }
+ turret_tag_fire_update();
+ entity missile = turret_projectile(SND(ROCKET_FIRE), 6, 10, DEATH_TURRET_MLRS, PROJECTILE_ROCKET, TRUE, TRUE);
+ missile.nextthink = time + max(actor.tur_impacttime,(actor.shot_radius * 2) / actor.shot_speed);
+ missile.missile_flags = MIF_SPLASH;
+ te_explosion (missile.origin);
+ }
+}
+
+#endif
+
+#endif
--- /dev/null
+#ifndef TURRET_PHASER_H
+#define TURRET_PHASER_H
+
+#include "phaser_weapon.qc"
+
+CLASS(PhaserTurret, Turret)
+/* spawnflags */ ATTRIB(PhaserTurret, spawnflags, int, TUR_FLAG_SNIPER | TUR_FLAG_HITSCAN | TUR_FLAG_PLAYER);
+/* mins */ ATTRIB(PhaserTurret, mins, vector, '-32 -32 0');
+/* maxs */ ATTRIB(PhaserTurret, maxs, vector, '32 32 64');
+/* modelname */ ATTRIB(PhaserTurret, mdl, string, "base.md3");
+/* model */ ATTRIB(PhaserTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
+/* head_model */ ATTRIB(PhaserTurret, head_model, string, strzone(strcat("models/turrets/", "phaser.md3")));
+/* netname */ ATTRIB(PhaserTurret, netname, string, "phaser");
+/* fullname */ ATTRIB(PhaserTurret, turret_name, string, _("Phaser Cannon"));
+ ATTRIB(PhaserTurret, m_weapon, Weapon, WEP_PHASER);
+ENDCLASS(PhaserTurret)
+REGISTER_TURRET(PHASER, NEW(PhaserTurret));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#include "phaser_weapon.qc"
+
+#ifdef SVQC
+
+spawnfunc(turret_phaser) { if (!turret_initialize(TUR_PHASER)) remove(self); }
+
+METHOD(PhaserTurret, tr_think, void(PhaserTurret thistur))
+{
+ if (self.tur_head.frame != 0)
+ {
+ if (self.fireflag == 1)
+ {
+ if (self.tur_head.frame == 10)
+ self.tur_head.frame = 1;
+ else
+ self.tur_head.frame = self.tur_head.frame +1;
+ }
+ else if (self.fireflag == 2 )
+ {
+ self.tur_head.frame = self.tur_head.frame +1;
+ if (self.tur_head.frame == 15)
+ {
+ self.tur_head.frame = 0;
+ self.fireflag = 0;
+ }
+ }
+ }
+}
+float turret_phaser_firecheck();
+METHOD(PhaserTurret, tr_setup, void(PhaserTurret this, entity it))
+{
+ it.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+ it.aim_flags = TFL_AIM_LEAD;
+
+ it.turret_firecheckfunc = turret_phaser_firecheck;
+}
+float turret_phaser_firecheck()
+{
+ SELFPARAM();
+ if (self.fireflag != 0) return 0;
+ return turret_firecheck();
+}
+
+#endif
+#endif
--- /dev/null
+#ifndef TURRET_PHASER_WEAPON_H
+#define TURRET_PHASER_WEAPON_H
+
+CLASS(PhaserTurretAttack, PortoLaunch)
+/* flags */ ATTRIB(PhaserTurretAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse */ ATTRIB(PhaserTurretAttack, impulse, int, 9);
+/* refname */ ATTRIB(PhaserTurretAttack, netname, string, "turret_phaser");
+/* wepname */ ATTRIB(PhaserTurretAttack, message, string, _("Phaser"));
+ENDCLASS(PhaserTurretAttack)
+REGISTER_WEAPON(PHASER, NEW(PhaserTurretAttack));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+void beam_think();
+
+.int fireflag;
+
+METHOD(PhaserTurretAttack, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
+{
+ bool isPlayer = IS_PLAYER(actor);
+ if (fire1)
+ if (!isPlayer || weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(electro, refire))) {
+ if (isPlayer) {
+ turret_initparams(actor);
+ W_SetupShot_Dir(actor, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+ actor.tur_shotdir_updated = w_shotdir;
+ actor.tur_shotorg = w_shotorg;
+ actor.tur_head = actor;
+ actor.shot_speed = 1;
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready);
+ }
+ entity beam = spawn();
+ beam.ticrate = 0.1; //autocvar_sys_ticrate;
+ setmodel(beam, MDL_TUR_PHASER_BEAM);
+ beam.effects = EF_LOWPRECISION;
+ beam.solid = SOLID_NOT;
+ beam.think = beam_think;
+ beam.cnt = time + actor.shot_speed;
+ beam.shot_spread = time + 2;
+ beam.nextthink = time;
+ beam.owner = actor;
+ beam.shot_dmg = actor.shot_dmg / (actor.shot_speed / beam.ticrate);
+ beam.scale = actor.target_range / 256;
+ beam.movetype = MOVETYPE_NONE;
+ beam.enemy = actor.enemy;
+ beam.bot_dodge = true;
+ beam.bot_dodgerating = beam.shot_dmg;
+ sound (beam, CH_SHOTS_SINGLE, SND_TUR_PHASER, VOL_BASE, ATTEN_NORM);
+ actor.fireflag = 1;
+
+ beam.attack_finished_single = actor.attack_finished_single;
+ actor.attack_finished_single = time; // + autocvar_sys_ticrate;
+
+ setattachment(beam,actor.tur_head, "tag_fire");
+
+ soundat (actor, trace_endpos, CH_SHOTS, SND(NEXIMPACT), VOL_BASE, ATTEN_NORM);
+ if (!isPlayer)
+ if (actor.tur_head.frame == 0)
+ actor.tur_head.frame = 1;
+ }
+}
+
+void beam_think()
+{SELFPARAM();
+ if ((time > self.cnt) || (self.owner.deadflag != DEAD_NO))
+ {
+ self.owner.attack_finished_single = time + self.owner.shot_refire;
+ self.owner.fireflag = 2;
+ self.owner.tur_head.frame = 10;
+ sound (self, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
+ remove(self);
+ return;
+ }
+
+ turret_do_updates(self.owner);
+
+ if (time - self.shot_spread > 0)
+ {
+ self.shot_spread = time + 2;
+ sound (self, CH_SHOTS_SINGLE, SND_TUR_PHASER, VOL_BASE, ATTEN_NORM);
+ }
+
+
+ self.nextthink = time + self.ticrate;
+
+ self.owner.attack_finished_single = time + frametime;
+ setself(self.owner);
+ FireImoBeam ( self.tur_shotorg,
+ self.tur_shotorg + self.tur_shotdir_updated * self.target_range,
+ '-1 -1 -1' * self.shot_radius,
+ '1 1 1' * self.shot_radius,
+ self.shot_force,
+ this.shot_dmg,
+ 0.75,
+ DEATH_TURRET_PHASER);
+ setself(this);
+ self.scale = vlen(self.owner.tur_shotorg - trace_endpos) / 256;
+
+}
+
+#endif
+
+#endif
--- /dev/null
+#ifndef TURRET_PLASMA_H
+#define TURRET_PLASMA_H
+
+#include "plasma_weapon.qc"
+
+CLASS(PlasmaTurret, Turret)
+/* spawnflags */ ATTRIB(PlasmaTurret, spawnflags, int, TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER);
+/* mins */ ATTRIB(PlasmaTurret, mins, vector, '-32 -32 0');
+/* maxs */ ATTRIB(PlasmaTurret, maxs, vector, '32 32 64');
+/* modelname */ ATTRIB(PlasmaTurret, mdl, string, "base.md3");
+/* model */ ATTRIB(PlasmaTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
+/* head_model */ ATTRIB(PlasmaTurret, head_model, string, strzone(strcat("models/turrets/", "plasma.md3")));
+/* netname */ ATTRIB(PlasmaTurret, netname, string, "plasma");
+/* fullname */ ATTRIB(PlasmaTurret, turret_name, string, _("Plasma Cannon"));
+ ATTRIB(PlasmaTurret, m_weapon, Weapon, WEP_PLASMA);
+ENDCLASS(PlasmaTurret)
+REGISTER_TURRET(PLASMA, NEW(PlasmaTurret));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#include "plasma_weapon.qc"
+
+#ifdef SVQC
+
+spawnfunc(turret_plasma) { if (!turret_initialize(TUR_PLASMA)) remove(self); }
+
+METHOD(PlasmaTurret, tr_attack, void(PlasmaTurret this))
+{
+ if(g_instagib)
+ {
+ FireRailgunBullet (self.tur_shotorg, self.tur_shotorg + self.tur_shotdir_updated * MAX_SHOT_DISTANCE, 10000000000,
+ 800, 0, 0, 0, 0, DEATH_TURRET_PLASMA);
+
+ Send_Effect(EFFECT_VORTEX_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+
+ // teamcolor / hit beam effect
+ vector v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
+ WarpZone_TrailParticles(world, particleeffectnum(EFFECT_VAPORIZER(self.team)), self.tur_shotorg, v);
+ }
+ else
+ {
+ super.tr_attack(this);
+ }
+ if (self.tur_head.frame == 0)
+ self.tur_head.frame = 1;
+}
+METHOD(PlasmaTurret, tr_think, void(PlasmaTurret thistur))
+{
+ if (self.tur_head.frame != 0)
+ self.tur_head.frame = self.tur_head.frame + 1;
+
+ if (self.tur_head.frame > 5)
+ self.tur_head.frame = 0;
+}
+METHOD(PlasmaTurret, tr_setup, void(PlasmaTurret this, entity it))
+{
+ it.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+ it.damage_flags |= TFL_DMG_HEADSHAKE;
+ it.firecheck_flags |= TFL_FIRECHECK_AFF;
+ it.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_SPLASH;
+
+ turret_do_updates(it);
+}
+
+#endif
+#endif
--- /dev/null
+#ifndef TURRET_PLASMA_DUAL_H
+#define TURRET_PLASMA_DUAL_H
+
+CLASS(PlasmaDualAttack, PlasmaAttack)
+/* refname */ ATTRIB(PlasmaDualAttack, netname, string, "turret_plasma_dual");
+/* wepname */ ATTRIB(PlasmaDualAttack, message, string, _("Dual plasma"));
+ENDCLASS(PlasmaDualAttack)
+REGISTER_WEAPON(PLASMA_DUAL, NEW(PlasmaDualAttack));
+
+CLASS(DualPlasmaTurret, PlasmaTurret)
+/* spawnflags */ ATTRIB(DualPlasmaTurret, spawnflags, int, TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER);
+/* mins */ ATTRIB(DualPlasmaTurret, mins, vector, '-32 -32 0');
+/* maxs */ ATTRIB(DualPlasmaTurret, maxs, vector, '32 32 64');
+/* modelname */ ATTRIB(DualPlasmaTurret, mdl, string, "base.md3");
+/* model */ ATTRIB(DualPlasmaTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
+/* head_model */ ATTRIB(DualPlasmaTurret, head_model, string, strzone(strcat("models/turrets/", "plasmad.md3")));
+/* netname */ ATTRIB(DualPlasmaTurret, netname, string, "plasma_dual");
+/* fullname */ ATTRIB(DualPlasmaTurret, turret_name, string, _("Dual Plasma Cannon"));
+ ATTRIB(DualPlasmaTurret, m_weapon, Weapon, WEP_PLASMA_DUAL);
+ENDCLASS(DualPlasmaTurret)
+REGISTER_TURRET(PLASMA_DUAL, NEW(DualPlasmaTurret));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+spawnfunc(turret_plasma_dual) { if (!turret_initialize(TUR_PLASMA_DUAL)) remove(self); }
+
+METHOD(DualPlasmaTurret, tr_attack, void(DualPlasmaTurret this))
+{
+ if (g_instagib) {
+ FireRailgunBullet (self.tur_shotorg, self.tur_shotorg + self.tur_shotdir_updated * MAX_SHOT_DISTANCE, 10000000000,
+ 800, 0, 0, 0, 0, DEATH_TURRET_PLASMA);
+
+
+ Send_Effect(EFFECT_VORTEX_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+
+ // teamcolor / hit beam effect
+ vector v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
+ WarpZone_TrailParticles(world, particleeffectnum(EFFECT_VAPORIZER(self.team)), self.tur_shotorg, v);
+ } else {
+ super.vtblbase.tr_attack(this);
+ }
+ self.tur_head.frame += 1;
+}
+METHOD(DualPlasmaTurret, tr_think, void(DualPlasmaTurret thistur))
+{
+ if ((self.tur_head.frame != 0) && (self.tur_head.frame != 3))
+ self.tur_head.frame = self.tur_head.frame + 1;
+
+ if (self.tur_head.frame > 6)
+ self.tur_head.frame = 0;
+}
+
+#endif
+#endif
--- /dev/null
+#ifndef TURRET_PLASMA_WEAPON_H
+#define TURRET_PLASMA_WEAPON_H
+
+CLASS(PlasmaAttack, PortoLaunch)
+/* flags */ ATTRIB(PlasmaAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse */ ATTRIB(PlasmaAttack, impulse, int, 5);
+/* refname */ ATTRIB(PlasmaAttack, netname, string, "turret_plasma");
+/* wepname */ ATTRIB(PlasmaAttack, message, string, _("Plasma"));
+ENDCLASS(PlasmaAttack)
+REGISTER_WEAPON(PLASMA, NEW(PlasmaAttack));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+METHOD(PlasmaAttack, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2)) {
+ bool isPlayer = IS_PLAYER(actor);
+ if (fire1)
+ if (!isPlayer || weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(electro, refire))) {
+ if (isPlayer) {
+ turret_initparams(actor);
+ W_SetupShot_Dir(actor, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+ actor.tur_shotdir_updated = w_shotdir;
+ actor.tur_shotorg = w_shotorg;
+ actor.tur_head = actor;
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready);
+ }
+ entity missile = turret_projectile(SND(HAGAR_FIRE), 1, 0, DEATH_TURRET_PLASMA, PROJECTILE_ELECTRO_BEAM, true, true);
+ missile.missile_flags = MIF_SPLASH;
+ Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, actor.tur_shotorg, actor.tur_shotdir_updated * 1000, 1);
+ }
+}
+
+#endif
+
+#endif
--- /dev/null
+#ifndef TURRET_TESLA_H
+#define TURRET_TESLA_H
+
+#include "tesla_weapon.qc"
+
+CLASS(TeslaCoil, Turret)
+/* spawnflags */ ATTRIB(TeslaCoil, spawnflags, int, TUR_FLAG_HITSCAN | TUR_FLAG_PLAYER | TUR_FLAG_MISSILE);
+/* mins */ ATTRIB(TeslaCoil, mins, vector, '-60 -60 0');
+/* maxs */ ATTRIB(TeslaCoil, maxs, vector, '60 60 128');
+/* modelname */ ATTRIB(TeslaCoil, mdl, string, "tesla_base.md3");
+/* model */ ATTRIB(TeslaCoil, model, string, strzone(strcat("models/turrets/", this.mdl)));
+/* head_model */ ATTRIB(TeslaCoil, head_model, string, strzone(strcat("models/turrets/", "tesla_head.md3")));
+/* netname */ ATTRIB(TeslaCoil, netname, string, "tesla");
+/* fullname */ ATTRIB(TeslaCoil, turret_name, string, _("Tesla Coil"));
+ ATTRIB(TeslaCoil, m_weapon, Weapon, WEP_TESLA);
+ENDCLASS(TeslaCoil)
+REGISTER_TURRET(TESLA, NEW(TeslaCoil));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#include "tesla_weapon.qc"
+
+#ifdef SVQC
+
+spawnfunc(turret_tesla) { if (!turret_initialize(TUR_TESLA)) remove(self); }
+
+METHOD(TeslaCoil, tr_think, void(TeslaCoil thistur))
+{
+ if(!self.active)
+ {
+ self.tur_head.avelocity = '0 0 0';
+ return;
+ }
+
+ if(self.ammo < self.shot_dmg)
+ {
+ self.tur_head.avelocity = '0 45 0' * (self.ammo / self.shot_dmg);
+ }
+ else
+ {
+ self.tur_head.avelocity = '0 180 0' * (self.ammo / self.shot_dmg);
+
+ if(self.attack_finished_single > time)
+ return;
+
+ float f;
+ f = (self.ammo / self.ammo_max);
+ f = f * f;
+ if(f > random())
+ if(random() < 0.1)
+ te_csqc_lightningarc(self.tur_shotorg,self.tur_shotorg + (randomvec() * 350));
+ }
+}
+
+float turret_tesla_firecheck();
+METHOD(TeslaCoil, tr_setup, void(TeslaCoil this, entity it))
+{
+ it.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
+ TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
+
+ it.turret_firecheckfunc = turret_tesla_firecheck;
+ it.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
+ TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
+
+ it.firecheck_flags = TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AMMO_OWN;
+ it.shoot_flags = TFL_SHOOT_CUSTOM;
+ it.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+ it.aim_flags = TFL_AIM_NO;
+ it.track_flags = TFL_TRACK_NO;
+}
+
+float turret_tesla_firecheck()
+{SELFPARAM();
+ // g_turrets_targetscan_maxdelay forces a target re-scan at least this often
+ float do_target_scan = 0;
+
+ if((self.target_select_time + autocvar_g_turrets_targetscan_maxdelay) < time)
+ do_target_scan = 1;
+
+ // Old target (if any) invalid?
+ if(self.target_validate_time < time)
+ if (turret_validate_target(self, self.enemy, self.target_validate_flags) <= 0)
+ {
+ self.enemy = world;
+ self.target_validate_time = time + 0.5;
+ do_target_scan = 1;
+ }
+
+ // But never more often then g_turrets_targetscan_mindelay!
+ if (self.target_select_time + autocvar_g_turrets_targetscan_mindelay > time)
+ do_target_scan = 0;
+
+ if(do_target_scan)
+ {
+ self.enemy = turret_select_target();
+ self.target_select_time = time;
+ }
+
+ if(!turret_firecheck())
+ return 0;
+
+ if(self.enemy)
+ return 1;
+
+ return 0;
+}
+
+#endif
+#endif
--- /dev/null
+#ifndef TURRET_TESLA_WEAPON_H
+#define TURRET_TESLA_WEAPON_H
+
+CLASS(TeslaCoilTurretAttack, PortoLaunch)
+/* flags */ ATTRIB(TeslaCoilTurretAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse */ ATTRIB(TeslaCoilTurretAttack, impulse, int, 9);
+/* refname */ ATTRIB(TeslaCoilTurretAttack, netname, string, "turret_tesla");
+/* wepname */ ATTRIB(TeslaCoilTurretAttack, message, string, _("Tesla Coil"));
+ENDCLASS(TeslaCoilTurretAttack)
+REGISTER_WEAPON(TESLA, NEW(TeslaCoilTurretAttack));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+entity toast(entity from, float range, float damage);
+METHOD(TeslaCoilTurretAttack, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2)) {
+ bool isPlayer = IS_PLAYER(actor);
+ if (fire1)
+ if (!isPlayer || weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(electro, refire))) {
+ if (isPlayer) {
+ turret_initparams(actor);
+ W_SetupShot_Dir(actor, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+ actor.tur_shotdir_updated = w_shotdir;
+ actor.tur_shotorg = w_shotorg;
+ actor.tur_head = actor;
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready);
+ }
+
+ float d = actor.shot_dmg;
+ float r = actor.target_range;
+ entity e = spawn();
+ setorigin(e,actor.tur_shotorg);
+
+ actor.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
+
+ entity t = toast(e,r,d);
+ remove(e);
+
+ if (t == NULL) return;
+
+ actor.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | TFL_TARGETSELECT_TEAMCHECK;
+
+ actor.attack_finished_single = time + actor.shot_refire;
+ for (int i = 0; i < 10; ++i) {
+ d *= 0.75;
+ r *= 0.85;
+ t = toast(t, r, d);
+ if (t == world) break;
+
+ }
+
+ e = findchainfloat(railgunhit, 1);
+ while (e) {
+ e.railgunhit = 0;
+ e = e.chain;
+ }
+
+ }
+}
+
+entity toast(entity from, float range, float damage)
+{SELFPARAM();
+ entity e;
+ entity etarget = world;
+ float d,dd;
+ float r;
+
+ dd = range + 1;
+
+ e = findradius(from.origin,range);
+ while (e)
+ {
+ if ((e.railgunhit != 1) && (e != from))
+ {
+ r = turret_validate_target(self,e,self.target_validate_flags);
+ if (r > 0)
+ {
+ traceline(from.origin,0.5 * (e.absmin + e.absmax),MOVE_WORLDONLY,from);
+ if (trace_fraction == 1.0)
+ {
+ d = vlen(e.origin - from.origin);
+ if (d < dd)
+ {
+ dd = d;
+ etarget = e;
+ }
+ }
+ }
+ }
+ e = e.chain;
+ }
+
+ if (etarget)
+ {
+ te_csqc_lightningarc(from.origin,etarget.origin);
+ Damage(etarget, self, self, damage, DEATH_TURRET_TESLA, etarget.origin, '0 0 0');
+ etarget.railgunhit = 1;
+ }
+
+ return etarget;
+}
+
+#endif
+
+#endif
--- /dev/null
+#ifndef TURRET_WALKER_H
+#define TURRET_WALKER_H
+
+//#define WALKER_FANCYPATHING
+
+#include "walker_weapon.qc"
+
+CLASS(WalkerTurret, Turret)
+/* spawnflags */ ATTRIB(WalkerTurret, spawnflags, int, TUR_FLAG_PLAYER | TUR_FLAG_MOVE);
+/* mins */ ATTRIB(WalkerTurret, mins, vector, '-70 -70 0');
+/* maxs */ ATTRIB(WalkerTurret, maxs, vector, '70 70 95');
+/* modelname */ ATTRIB(WalkerTurret, mdl, string, "walker_body.md3");
+/* model */ ATTRIB(WalkerTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
+/* head_model */ ATTRIB(WalkerTurret, head_model, string, strzone(strcat("models/turrets/", "walker_head_minigun.md3")));
+/* netname */ ATTRIB(WalkerTurret, netname, string, "walker");
+/* fullname */ ATTRIB(WalkerTurret, turret_name, string, _("Walker Turret"));
+ ATTRIB(WalkerTurret, m_weapon, Weapon, WEP_WALKER);
+ENDCLASS(WalkerTurret)
+REGISTER_TURRET(WALKER, NEW(WalkerTurret));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#include "walker_weapon.qc"
+
+#ifdef SVQC
+
+float autocvar_g_turrets_unit_walker_melee_damage;
+float autocvar_g_turrets_unit_walker_melee_force;
+float autocvar_g_turrets_unit_walker_melee_range;
+float autocvar_g_turrets_unit_walker_rocket_damage;
+float autocvar_g_turrets_unit_walker_rocket_radius;
+float autocvar_g_turrets_unit_walker_rocket_force;
+float autocvar_g_turrets_unit_walker_rocket_speed;
+float autocvar_g_turrets_unit_walker_rocket_range;
+float autocvar_g_turrets_unit_walker_rocket_range_min;
+float autocvar_g_turrets_unit_walker_rocket_refire;
+float autocvar_g_turrets_unit_walker_rocket_turnrate;
+float autocvar_g_turrets_unit_walker_speed_stop;
+float autocvar_g_turrets_unit_walker_speed_walk;
+float autocvar_g_turrets_unit_walker_speed_run;
+float autocvar_g_turrets_unit_walker_speed_jump;
+float autocvar_g_turrets_unit_walker_speed_swim;
+float autocvar_g_turrets_unit_walker_speed_roam;
+float autocvar_g_turrets_unit_walker_turn;
+float autocvar_g_turrets_unit_walker_turn_walk;
+float autocvar_g_turrets_unit_walker_turn_strafe;
+float autocvar_g_turrets_unit_walker_turn_swim;
+float autocvar_g_turrets_unit_walker_turn_run;
+
+const int ANIM_NO = 0;
+const int ANIM_TURN = 1;
+const int ANIM_WALK = 2;
+const int ANIM_RUN = 3;
+const int ANIM_STRAFE_L = 4;
+const int ANIM_STRAFE_R = 5;
+const int ANIM_JUMP = 6;
+const int ANIM_LAND = 7;
+const int ANIM_PAIN = 8;
+const int ANIM_MELEE = 9;
+const int ANIM_SWIM = 10;
+const int ANIM_ROAM = 11;
+
+.float animflag;
+.float idletime;
+
+#define WALKER_PATH(s,e) pathlib_astar(s,e)
+
+float walker_firecheck()
+{SELFPARAM();
+ if (self.animflag == ANIM_MELEE)
+ return 0;
+
+ return turret_firecheck();
+}
+
+void walker_melee_do_dmg()
+{SELFPARAM();
+ vector where;
+ entity e;
+
+ makevectors(self.angles);
+ where = self.origin + v_forward * 128;
+
+ e = findradius(where,32);
+ while (e)
+ {
+ if (turret_validate_target(self, e, self.target_validate_flags))
+ if (e != self && e.owner != self)
+ Damage(e, self, self, (autocvar_g_turrets_unit_walker_melee_damage), DEATH_TURRET_WALK_MELEE, '0 0 0', v_forward * (autocvar_g_turrets_unit_walker_melee_force));
+
+ e = e.chain;
+ }
+}
+
+void walker_setnoanim()
+{SELFPARAM();
+ turrets_setframe(ANIM_NO, false);
+ self.animflag = self.frame;
+}
+void walker_rocket_explode()
+{SELFPARAM();
+ RadiusDamage (self, self.owner, (autocvar_g_turrets_unit_walker_rocket_damage), 0, (autocvar_g_turrets_unit_walker_rocket_radius), self, world, (autocvar_g_turrets_unit_walker_rocket_force), DEATH_TURRET_WALK_ROCKET, world);
+ remove (self);
+}
+
+void walker_rocket_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
+{SELFPARAM();
+ self.health = self.health - damage;
+ self.velocity = self.velocity + vforce;
+
+ if (self.health <= 0)
+ W_PrepareExplosionByDamage(self.owner, walker_rocket_explode);
+}
+
+#define WALKER_ROCKET_MOVE movelib_move_simple(newdir, (autocvar_g_turrets_unit_walker_rocket_speed), (autocvar_g_turrets_unit_walker_rocket_turnrate)); UpdateCSQCProjectile(self)
+void walker_rocket_loop();
+void walker_rocket_think()
+{SELFPARAM();
+ vector newdir;
+ float edist;
+ float itime;
+ float m_speed;
+
+ self.nextthink = time;
+
+ edist = vlen(self.enemy.origin - self.origin);
+
+ // Simulate crude guidance
+ if (self.cnt < time)
+ {
+ if (edist < 1000)
+ self.tur_shotorg = randomvec() * min(edist, 64);
+ else
+ self.tur_shotorg = randomvec() * min(edist, 256);
+
+ self.cnt = time + 0.5;
+ }
+
+ if (edist < 128)
+ self.tur_shotorg = '0 0 0';
+
+ if (self.max_health < time)
+ {
+ self.think = walker_rocket_explode;
+ self.nextthink = time;
+ return;
+ }
+
+ if (self.shot_dmg != 1337 && random() < 0.01)
+ {
+ walker_rocket_loop();
+ return;
+ }
+
+ m_speed = vlen(self.velocity);
+
+ // Enemy dead? just keep on the current heading then.
+ if (self.enemy == world || self.enemy.deadflag != DEAD_NO)
+ self.enemy = world;
+
+ if (self.enemy)
+ {
+ itime = max(edist / m_speed, 1);
+ newdir = steerlib_pull(self.enemy.origin + self.tur_shotorg);
+ }
+ else
+ newdir = normalize(self.velocity);
+
+ WALKER_ROCKET_MOVE;
+}
+
+void walker_rocket_loop3()
+{SELFPARAM();
+ vector newdir;
+ self.nextthink = time;
+
+ if (self.max_health < time)
+ {
+ self.think = walker_rocket_explode;
+ return;
+ }
+
+ if (vlen(self.origin - self.tur_shotorg) < 100 )
+ {
+ self.think = walker_rocket_think;
+ return;
+ }
+
+ newdir = steerlib_pull(self.tur_shotorg);
+ WALKER_ROCKET_MOVE;
+
+ self.angles = vectoangles(self.velocity);
+}
+
+void walker_rocket_loop2()
+{SELFPARAM();
+ vector newdir;
+
+ self.nextthink = time;
+
+ if (self.max_health < time)
+ {
+ self.think = walker_rocket_explode;
+ return;
+ }
+
+ if (vlen(self.origin - self.tur_shotorg) < 100 )
+ {
+ self.tur_shotorg = self.origin - '0 0 200';
+ self.think = walker_rocket_loop3;
+ return;
+ }
+
+ newdir = steerlib_pull(self.tur_shotorg);
+ WALKER_ROCKET_MOVE;
+}
+
+void walker_rocket_loop()
+{SELFPARAM();
+ self.nextthink = time;
+ self.tur_shotorg = self.origin + '0 0 300';
+ self.think = walker_rocket_loop2;
+ self.shot_dmg = 1337;
+}
+
+void walker_fire_rocket(vector org)
+{SELFPARAM();
+ entity rocket;
+
+ fixedmakevectors(self.angles);
+
+ te_explosion (org);
+
+ rocket = spawn ();
+ setorigin(rocket, org);
+
+ sound (self, CH_WEAPON_A, SND_HAGAR_FIRE, VOL_BASE, ATTEN_NORM);
+ setsize (rocket, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
+
+ rocket.classname = "walker_rocket";
+ rocket.owner = self;
+ rocket.bot_dodge = true;
+ rocket.bot_dodgerating = 50;
+ rocket.takedamage = DAMAGE_YES;
+ rocket.damageforcescale = 2;
+ rocket.health = 25;
+ rocket.tur_shotorg = randomvec() * 512;
+ rocket.cnt = time + 1;
+ rocket.enemy = self.enemy;
+
+ if (random() < 0.01)
+ rocket.think = walker_rocket_loop;
+ else
+ rocket.think = walker_rocket_think;
+
+ rocket.event_damage = walker_rocket_damage;
+
+ rocket.nextthink = time;
+ rocket.movetype = MOVETYPE_FLY;
+ rocket.velocity = normalize((v_forward + v_up * 0.5) + (randomvec() * 0.2)) * (autocvar_g_turrets_unit_walker_rocket_speed);
+ rocket.angles = vectoangles(rocket.velocity);
+ rocket.touch = walker_rocket_explode;
+ rocket.flags = FL_PROJECTILE;
+ rocket.solid = SOLID_BBOX;
+ rocket.max_health = time + 9;
+ rocket.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_HEAT;
+
+ CSQCProjectile(rocket, false, PROJECTILE_ROCKET, false); // no culling, has fly sound
+}
+
+.vector enemy_last_loc;
+.float enemy_last_time;
+void walker_move_to(vector _target, float _dist)
+{SELFPARAM();
+ switch (self.waterlevel)
+ {
+ case WATERLEVEL_NONE:
+ if (_dist > 500)
+ self.animflag = ANIM_RUN;
+ else
+ self.animflag = ANIM_WALK;
+ case WATERLEVEL_WETFEET:
+ case WATERLEVEL_SWIMMING:
+ if (self.animflag != ANIM_SWIM)
+ self.animflag = ANIM_WALK;
+ else
+ self.animflag = ANIM_SWIM;
+ break;
+ case WATERLEVEL_SUBMERGED:
+ self.animflag = ANIM_SWIM;
+ }
+
+ self.moveto = _target;
+ self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
+
+ if(self.enemy)
+ {
+ self.enemy_last_loc = _target;
+ self.enemy_last_time = time;
+ }
+}
+
+void walker_move_path()
+{SELFPARAM();
+#ifdef WALKER_FANCYPATHING
+ // Are we close enougth to a path node to switch to the next?
+ if (vlen(self.origin - self.pathcurrent.origin) < 64)
+ if (self.pathcurrent.path_next == world)
+ {
+ // Path endpoint reached
+ pathlib_deletepath(self.pathcurrent.owner);
+ self.pathcurrent = world;
+
+ if (self.pathgoal)
+ {
+ if (self.pathgoal.use)
+ self.pathgoal.use();
+
+ if (self.pathgoal.enemy)
+ {
+ self.pathcurrent = WALKER_PATH(self.pathgoal.origin,self.pathgoal.enemy.origin);
+ self.pathgoal = self.pathgoal.enemy;
+ }
+ }
+ else
+ self.pathgoal = world;
+ }
+ else
+ self.pathcurrent = self.pathcurrent.path_next;
+
+ self.moveto = self.pathcurrent.origin;
+ self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95);
+ walker_move_to(self.moveto, 0);
+
+#else
+ if (vlen(self.origin - self.pathcurrent.origin) < 64)
+ self.pathcurrent = self.pathcurrent.enemy;
+
+ if(!self.pathcurrent)
+ return;
+
+ self.moveto = self.pathcurrent.origin;
+ self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
+ walker_move_to(self.moveto, 0);
+#endif
+}
+
+spawnfunc(turret_walker) { if(!turret_initialize(TUR_WALKER)) remove(self); }
+
+ METHOD(WalkerTurret, tr_think, void(WalkerTurret thistur))
+ {
+ fixedmakevectors(self.angles);
+
+ if (self.spawnflags & TSF_NO_PATHBREAK && self.pathcurrent)
+ walker_move_path();
+ else if (self.enemy == world)
+ {
+ if(self.pathcurrent)
+ walker_move_path();
+ else
+ {
+ if(self.enemy_last_time != 0)
+ {
+ if(vlen(self.origin - self.enemy_last_loc) < 128 || time - self.enemy_last_time > 10)
+ self.enemy_last_time = 0;
+ else
+ walker_move_to(self.enemy_last_loc, 0);
+ }
+ else
+ {
+ if(self.animflag != ANIM_NO)
+ {
+ traceline(self.origin + '0 0 64', self.origin + '0 0 64' + v_forward * 128, MOVE_NORMAL, self);
+
+ if(trace_fraction != 1.0)
+ self.tur_head.idletime = -1337;
+ else
+ {
+ traceline(trace_endpos, trace_endpos - '0 0 256', MOVE_NORMAL, self);
+ if(trace_fraction == 1.0)
+ self.tur_head.idletime = -1337;
+ }
+
+ if(self.tur_head.idletime == -1337)
+ {
+ self.moveto = self.origin + randomvec() * 256;
+ self.tur_head.idletime = 0;
+ }
+
+ self.moveto = self.moveto * 0.9 + ((self.origin + v_forward * 500) + randomvec() * 400) * 0.1;
+ self.moveto_z = self.origin_z + 64;
+ walker_move_to(self.moveto, 0);
+ }
+
+ if(self.idletime < time)
+ {
+ if(random() < 0.5 || !(self.spawnflags & TSL_ROAM))
+ {
+ self.idletime = time + 1 + random() * 5;
+ self.moveto = self.origin;
+ self.animflag = ANIM_NO;
+ }
+ else
+ {
+ self.animflag = ANIM_WALK;
+ self.idletime = time + 4 + random() * 2;
+ self.moveto = self.origin + randomvec() * 256;
+ self.tur_head.moveto = self.moveto;
+ self.tur_head.idletime = 0;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (self.tur_dist_enemy < (autocvar_g_turrets_unit_walker_melee_range) && self.animflag != ANIM_MELEE)
+ {
+ vector wish_angle;
+
+ wish_angle = angleofs(self, self.enemy);
+ if (self.animflag != ANIM_SWIM)
+ if (fabs(wish_angle_y) < 15)
+ {
+ self.moveto = self.enemy.origin;
+ self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
+ self.animflag = ANIM_MELEE;
+ }
+ }
+ else if (self.tur_head.attack_finished_single < time)
+ {
+ if(self.tur_head.shot_volly)
+ {
+ self.animflag = ANIM_NO;
+
+ self.tur_head.shot_volly = self.tur_head.shot_volly -1;
+ if(self.tur_head.shot_volly == 0)
+ self.tur_head.attack_finished_single = time + (autocvar_g_turrets_unit_walker_rocket_refire);
+ else
+ self.tur_head.attack_finished_single = time + 0.2;
+
+ if(self.tur_head.shot_volly > 1)
+ walker_fire_rocket(gettaginfo(self, gettagindex(self, "tag_rocket01")));
+ else
+ walker_fire_rocket(gettaginfo(self, gettagindex(self, "tag_rocket02")));
+ }
+ else
+ {
+ if (self.tur_dist_enemy > (autocvar_g_turrets_unit_walker_rocket_range_min))
+ if (self.tur_dist_enemy < (autocvar_g_turrets_unit_walker_rocket_range))
+ self.tur_head.shot_volly = 4;
+ }
+ }
+ else
+ {
+ if (self.animflag != ANIM_MELEE)
+ walker_move_to(self.enemy.origin, self.tur_dist_enemy);
+ }
+ }
+
+ {
+ vector real_angle;
+ float turny = 0, turnx = 0;
+ float vz;
+
+ real_angle = vectoangles(self.steerto) - self.angles;
+ vz = self.velocity_z;
+
+ switch (self.animflag)
+ {
+ case ANIM_NO:
+ movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
+ break;
+
+ case ANIM_TURN:
+ turny = (autocvar_g_turrets_unit_walker_turn);
+ movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
+ break;
+
+ case ANIM_WALK:
+ turny = (autocvar_g_turrets_unit_walker_turn_walk);
+ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_walk), 0.6);
+ break;
+
+ case ANIM_RUN:
+ turny = (autocvar_g_turrets_unit_walker_turn_run);
+ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_run), 0.6);
+ break;
+
+ case ANIM_STRAFE_L:
+ turny = (autocvar_g_turrets_unit_walker_turn_strafe);
+ movelib_move_simple(v_right * -1, (autocvar_g_turrets_unit_walker_speed_walk), 0.8);
+ break;
+
+ case ANIM_STRAFE_R:
+ turny = (autocvar_g_turrets_unit_walker_turn_strafe);
+ movelib_move_simple(v_right, (autocvar_g_turrets_unit_walker_speed_walk), 0.8);
+ break;
+
+ case ANIM_JUMP:
+ self.velocity += '0 0 1' * (autocvar_g_turrets_unit_walker_speed_jump);
+ break;
+
+ case ANIM_LAND:
+ break;
+
+ case ANIM_PAIN:
+ if(self.frame != ANIM_PAIN)
+ defer(0.25, walker_setnoanim);
+
+ break;
+
+ case ANIM_MELEE:
+ if(self.frame != ANIM_MELEE)
+ {
+ defer(0.41, walker_setnoanim);
+ defer(0.21, walker_melee_do_dmg);
+ }
+
+ movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
+ break;
+
+ case ANIM_SWIM:
+ turny = (autocvar_g_turrets_unit_walker_turn_swim);
+ turnx = (autocvar_g_turrets_unit_walker_turn_swim);
+
+ self.angles_x += bound(-10, shortangle_f(real_angle_x, self.angles_x), 10);
+ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_swim), 0.3);
+ vz = self.velocity_z + sin(time * 4) * 8;
+ break;
+
+ case ANIM_ROAM:
+ turny = (autocvar_g_turrets_unit_walker_turn_walk);
+ movelib_move_simple(v_forward ,(autocvar_g_turrets_unit_walker_speed_roam), 0.5);
+ break;
+ }
+
+ if(turny)
+ {
+ turny = bound( turny * -1, shortangle_f(real_angle_y, self.angles_y), turny );
+ self.angles_y += turny;
+ }
+
+ if(turnx)
+ {
+ turnx = bound( turnx * -1, shortangle_f(real_angle_x, self.angles_x), turnx );
+ self.angles_x += turnx;
+ }
+
+ self.velocity_z = vz;
+ }
+
+
+ if(self.origin != self.oldorigin)
+ self.SendFlags |= TNSF_MOVE;
+
+ self.oldorigin = self.origin;
+ turrets_setframe(self.animflag, false);
+ }
+ METHOD(WalkerTurret, tr_death, void(WalkerTurret this, entity it))
+ {
+#ifdef WALKER_FANCYPATHING
+ if (it.pathcurrent)
+ pathlib_deletepath(it.pathcurrent.owner);
+#endif
+ it.pathcurrent = NULL;
+ }
+ METHOD(WalkerTurret, tr_setup, void(WalkerTurret this, entity it))
+ {
+ it.ticrate = 0.05;
+
+ entity e;
+
+ // Respawn is called & first spawn to, to set team. need to make sure we do not move the initial spawn.
+ if(it.movetype == MOVETYPE_WALK)
+ {
+ if(it.pos1)
+ setorigin(it, it.pos1);
+ if(it.pos2)
+ it.angles = it.pos2;
+ }
+
+ it.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+ it.aim_flags = TFL_AIM_LEAD;
+ it.turret_flags |= TUR_FLAG_HITSCAN;
+
+ it.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+ it.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+ it.iscreature = true;
+ it.teleportable = TELEPORT_NORMAL;
+ it.damagedbycontents = true;
+ it.solid = SOLID_SLIDEBOX;
+ it.takedamage = DAMAGE_AIM;
+ if(it.movetype != MOVETYPE_WALK)
+ {
+ setorigin(it, it.origin);
+ tracebox(it.origin + '0 0 128', it.mins, it.maxs, it.origin - '0 0 10000', MOVE_NORMAL, it);
+ setorigin(it, trace_endpos + '0 0 4');
+ it.pos1 = it.origin;
+ it.pos2 = it.angles;
+ }
+ it.movetype = MOVETYPE_WALK;
+ it.idle_aim = '0 0 0';
+ it.turret_firecheckfunc = walker_firecheck;
+
+ if (it.target != "")
+ {
+ e = find(world, targetname, it.target);
+ if (!e)
+ {
+ LOG_TRACE("Initital waypoint for walker does NOT exsist, fix your map!\n");
+ it.target = "";
+ }
+
+ if (e.classname != "turret_checkpoint")
+ LOG_TRACE("Warning: not a turrret path\n");
+ else
+ {
+#ifdef WALKER_FANCYPATHING
+ it.pathcurrent = WALKER_PATH(it.origin, e.origin);
+ it.pathgoal = e;
+#else
+ it.pathcurrent = e;
+#endif
+ }
+ }
+ }
+
+#endif // SVQC
+#ifdef CSQC
+
+#include "../../../client/movelib.qh"
+
+void walker_draw(entity this)
+{
+ float dt;
+
+ dt = time - self.move_time;
+ self.move_time = time;
+ if(dt <= 0)
+ return;
+
+ fixedmakevectors(self.angles);
+ movelib_groundalign4point(300, 100, 0.25, 45);
+ setorigin(self, self.origin + self.velocity * dt);
+ self.tur_head.angles += dt * self.tur_head.move_avelocity;
+ self.angles_y = self.move_angles_y;
+
+ if (self.health < 127)
+ if(random() < 0.15)
+ te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
+}
+
+ METHOD(WalkerTurret, tr_setup, void(WalkerTurret this, entity it))
+ {
+ it.gravity = 1;
+ it.movetype = MOVETYPE_BOUNCE;
+ it.move_movetype = MOVETYPE_BOUNCE;
+ it.move_origin = it.origin;
+ it.move_time = time;
+ it.draw = walker_draw;
+ }
+
+#endif // CSQC
+#endif
--- /dev/null
+#ifndef TURRET_WALKER_WEAPON_H
+#define TURRET_WALKER_WEAPON_H
+
+CLASS(WalkerTurretAttack, PortoLaunch)
+/* flags */ ATTRIB(WalkerTurretAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse */ ATTRIB(WalkerTurretAttack, impulse, int, 5);
+/* refname */ ATTRIB(WalkerTurretAttack, netname, string, "turret_walker");
+/* wepname */ ATTRIB(WalkerTurretAttack, message, string, _("Walker"));
+ENDCLASS(WalkerTurretAttack)
+REGISTER_WEAPON(WALKER, NEW(WalkerTurretAttack));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+METHOD(WalkerTurretAttack, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2)) {
+ bool isPlayer = IS_PLAYER(actor);
+ if (fire1)
+ if (!isPlayer || weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(electro, refire))) {
+ if (isPlayer) {
+ turret_initparams(actor);
+ W_SetupShot_Dir(actor, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+ actor.tur_shotdir_updated = w_shotdir;
+ actor.tur_shotorg = w_shotorg;
+ actor.tur_head = actor;
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready);
+ }
+ sound (actor, CH_WEAPON_A, SND_UZI_FIRE, VOL_BASE, ATTEN_NORM);
+ fireBullet (actor.tur_shotorg, actor.tur_shotdir_updated, actor.shot_spread, 0, actor.shot_dmg, actor.shot_force, DEATH_TURRET_WALK_GUN, 0);
+ Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, actor.tur_shotorg, actor.tur_shotdir_updated * 1000, 1);
+ }
+}
+
+#endif
+
+#endif
+++ /dev/null
-#include "all.qh"
-
-// TURRET PLUGIN SYSTEM
-entity turret_info[TUR_MAXCOUNT];
-entity dummy_turret_info;
-
-void turrets_common_precache()
-{
- precache_sound (W_Sound("rocket_impact"));
- precache_model ("models/turrets/base-gib1.md3");
- precache_model ("models/turrets/base-gib2.md3");
- precache_model ("models/turrets/base-gib3.md3");
- precache_model ("models/turrets/base-gib4.md3");
- precache_model ("models/turrets/head-gib1.md3");
- precache_model ("models/turrets/head-gib2.md3");
- precache_model ("models/turrets/head-gib3.md3");
- precache_model ("models/turrets/head-gib4.md3");
- precache_model ("models/turrets/base.md3");
- precache_model ("models/turrets/rocket.md3");
-
- precache_model ("models/turrets/c512.md3");
- precache_model ("models/marker.md3");
-
-#ifdef SVQC
- precache_sound(W_Sound("rocket_impact"));
-#endif
-
-#ifdef TURRET_DEBUG
- precache_model ("models/turrets/c512.md3");
- precache_model ("models/pathlib/goodsquare.md3");
- precache_model ("models/pathlib/badsquare.md3");
- precache_model ("models/pathlib/square.md3");
- precache_model ("models/pathlib/edge.md3");
-#endif
-}
-
-void register_turret(float id, float(float) func, float turretflags, vector min_s, vector max_s, string modelname, string headmodelname, string shortname, string mname)
-{
- entity e;
- turret_info[id - 1] = e = spawn();
- e.classname = "turret_info";
- e.turretid = id;
- e.netname = shortname;
- e.turret_name = mname;
- e.turret_func = func;
- e.mdl = modelname;
- e.cvar_basename = shortname;
- e.spawnflags = turretflags;
- e.mins = min_s;
- e.maxs = max_s;
- e.model = strzone(strcat("models/turrets/", modelname));
- e.head_model = strzone(strcat("models/turrets/", headmodelname));
-
- #ifndef MENUQC
- turrets_common_precache();
- #endif
-}
-float t_null(float dummy) { return 0; }
-void register_turrets_done()
-{
- dummy_turret_info = spawn();
- dummy_turret_info.classname = "turret_info";
- dummy_turret_info.turretid = 0; // you can recognize dummies by this
- dummy_turret_info.netname = "";
- dummy_turret_info.turret_name = "Turret";
- dummy_turret_info.turret_func = t_null;
- dummy_turret_info.mdl = "";
- dummy_turret_info.mins = '-0 -0 -0';
- dummy_turret_info.maxs = '0 0 0';
- dummy_turret_info.model = "";
-}
-entity get_turretinfo(float id)
-{
- entity m;
- if(id < TUR_FIRST || id > TUR_LAST)
- return dummy_turret_info;
- m = turret_info[id - 1];
- if(m)
- return m;
- return dummy_turret_info;
-}
+++ /dev/null
-#ifndef TURRETS_H
-#define TURRETS_H
-
-// turret requests
-#define TR_SETUP 1 // (BOTH) setup turret data
-#define TR_THINK 2 // (SERVER) logic to run every frame
-#define TR_DEATH 3 // (SERVER) called when turret dies
-#define TR_PRECACHE 4 // (BOTH) precaches models/sounds used by this turret
-#define TR_ATTACK 5 // (SERVER) called when turret attacks
-#define TR_CONFIG 6 // (ALL)
-
-// functions:
-entity get_turretinfo(int id);
-
-// fields:
-.entity tur_head;
-
-// target selection flags
-.int target_select_flags;
-.int target_validate_flags;
-const int TFL_TARGETSELECT_NO = 2; // don't automatically find targets
-const int TFL_TARGETSELECT_LOS = 4; // require line of sight to find targets
-const int TFL_TARGETSELECT_PLAYERS = 8; // target players
-const int TFL_TARGETSELECT_MISSILES = 16; // target projectiles
-const int TFL_TARGETSELECT_TRIGGERTARGET = 32; // respond to turret_trigger_target events
-const int TFL_TARGETSELECT_ANGLELIMITS = 64; // apply extra angular limits to target selection
-const int TFL_TARGETSELECT_RANGELIMITS = 128; // limit target selection range
-const int TFL_TARGETSELECT_TEAMCHECK = 256; // don't attack teammates
-const int TFL_TARGETSELECT_NOBUILTIN = 512; // only attack targets when triggered
-const int TFL_TARGETSELECT_OWNTEAM = 1024; // only attack teammates
-const int TFL_TARGETSELECT_NOTURRETS = 2048; // don't attack other turrets
-const int TFL_TARGETSELECT_FOV = 4096; // extra limits to attack range
-const int TFL_TARGETSELECT_MISSILESONLY = 8192; // only attack missiles
-
-// aim flags
-.int aim_flags;
-const int TFL_AIM_NO = 1; // no aiming
-const int TFL_AIM_SPLASH = 2; // aim for ground around the target's feet
-const int TFL_AIM_LEAD = 4; // try to predict target movement
-const int TFL_AIM_SHOTTIMECOMPENSATE = 8; // compensate for shot traveltime when leading
-const int TFL_AIM_ZPREDICT = 16; // predict target's z position at impact
-const int TFL_AIM_SIMPLE = 32; // aim at player's current location
-
-// tracking flags
-.int track_flags;
-const int TFL_TRACK_NO = 2; // don't move head
-const int TFL_TRACK_PITCH = 4; // pitch head
-const int TFL_TRACK_ROTATE = 8; // rotate head
-
-// prefire checks
-.int firecheck_flags;
-const int TFL_FIRECHECK_DEAD = 4; // don't attack dead targets (zombies?)
-const int TFL_FIRECHECK_DISTANCES = 8; // another range check
-const int TFL_FIRECHECK_LOS = 16; // line of sight
-const int TFL_FIRECHECK_AIMDIST = 32; // consider distance impactpoint<->aimspot
-const int TFL_FIRECHECK_REALDIST = 64; // consider enemy origin<->impactpoint
-const int TFL_FIRECHECK_ANGLEDIST = 128; // consider angular diff head<->aimspot
-const int TFL_FIRECHECK_TEAMCHECK = 256; // don't attack teammates
-const int TFL_FIRECHECK_AFF = 512; // try to avoid any friendly fire
-const int TFL_FIRECHECK_AMMO_OWN = 1024; // own ammo needs to be larger than damage dealt
-const int TFL_FIRECHECK_AMMO_OTHER = 2048; // target's ammo needs to be less than max
-const int TFL_FIRECHECK_REFIRE = 4096; // check single attack finished delays
-const int TFL_FIRECHECK_NO = 16384; // no prefire checks
-
-// attack flags
-.int shoot_flags;
-const int TFL_SHOOT_NO = 64; // no attacking
-const int TFL_SHOOT_VOLLY = 2; // fire in vollies
-const int TFL_SHOOT_VOLLYALWAYS = 4; // always do a full volly, even if target is lost
-const int TFL_SHOOT_HITALLVALID = 8; // loop through all valid targets
-const int TFL_SHOOT_CLEARTARGET = 16; // lose target after attack (after volly is done if in volly mode)
-const int TFL_SHOOT_CUSTOM = 32; // custom attacking
-
-// turret capabilities
-.int turret_flags;
-const int TUR_FLAG_NONE = 0; // no abilities
-const int TUR_FLAG_SNIPER = 2; // sniping turret
-const int TUR_FLAG_SPLASH = 4; // can deal splash damage
-const int TUR_FLAG_HITSCAN = 8; // hit scan
-const int TUR_FLAG_MULTIGUN = 16; // multiple guns
-const int TUR_FLAG_GUIDED = 32; // laser guided projectiles
-const int TUR_FLAG_SLOWPROJ = 64; // turret fires slow projectiles
-const int TUR_FLAG_MEDPROJ = 128; // turret fires medium projectiles
-const int TUR_FLAG_FASTPROJ = 256; // turret fires fast projectiles
-const int TUR_FLAG_PLAYER = 512; // can damage players
-const int TUR_FLAG_MISSILE = 1024; // can damage missiles
-const int TUR_FLAG_SUPPORT = 2048; // supports other units
-const int TUR_FLAG_AMMOSOURCE = 4096; // can provide ammunition
-const int TUR_FLAG_RECIEVETARGETS = 8192; // can recieve targets from external sources
-const int TUR_FLAG_MOVE = 16384; // can move
-const int TUR_FLAG_ROAM = 32768; // roams around if not attacking
-const int TUR_FLAG_ISTURRET = 65536; // identifies this unit as a turret
-
-// ammo types
-#define ammo_flags currentammo
-const int TFL_AMMO_NONE = 64; // doesn't use ammo
-const int TFL_AMMO_ENERGY = 2; // uses power
-const int TFL_AMMO_BULLETS = 4; // uses bullets
-const int TFL_AMMO_ROCKETS = 8; // uses explosives
-const int TFL_AMMO_RECHARGE = 16; // regenerates ammo
-const int TFL_AMMO_RECIEVE = 32; // can recieve ammo from support units
-
-// damage flags
-.int damage_flags;
-const int TFL_DMG_NO = 256; // doesn't take damage
-const int TFL_DMG_YES = 2; // can be damaged
-const int TFL_DMG_TEAM = 4; // can be damaged by teammates
-const int TFL_DMG_RETALIATE = 8; // target attackers
-const int TFL_DMG_RETALIATE_TEAM = 16; // target attackers, even if on same team
-const int TFL_DMG_TARGETLOSS = 32; // loses target when damaged
-const int TFL_DMG_AIMSHAKE = 64; // damage throws off aim
-const int TFL_DMG_HEADSHAKE = 128; // damage shakes head
-const int TFL_DMG_DEATH_NORESPAWN = 256; // no re-spawning
-
-// spawn flags
-const int TSF_SUSPENDED = 1;
-const int TSF_TERRAINBASE = 2; // currently unused
-const int TSF_NO_AMMO_REGEN = 4; // disable builtin ammo regeneration
-const int TSF_NO_PATHBREAK = 8; // don't break path to chase enemies, will still fire at them if possible
-const int TSL_NO_RESPAWN = 16; // don't re-spawn
-const int TSL_ROAM = 32; // roam while idle
-
-// send flags
-const int TNSF_UPDATE = 2;
-const int TNSF_STATUS = 4;
-const int TNSF_SETUP = 8;
-const int TNSF_ANG = 16;
-const int TNSF_AVEL = 32;
-const int TNSF_MOVE = 64;
-.float anim_start_time;
-const int TNSF_ANIM = 128;
-
-const int TNSF_FULL_UPDATE = 16777215;
-
-
-// entity properties of turretinfo:
-.int turretid; // TUR_...
-.string netname; // short name
-.string turret_name; // human readable name
-.float(float) turret_func; // m_...
-.string mdl; // currently a copy of the model
-.string model; // full name of model
-.string head_model; // full name of tur_head model
-.string cvar_basename; // TODO: deprecate!
-.float spawnflags;
-.vector mins, maxs; // turret hitbox size
-
-// other useful macros
-#define TUR_ACTION(turrettype,mrequest) (get_turretinfo(turrettype)).turret_func(mrequest)
-#define TUR_NAME(turrettype) (get_turretinfo(turrettype)).turret_name
-
-// =====================
-// Turret Registration
-// =====================
-
-float t_null(float dummy);
-void register_turret(float id, float(float) func, float turretflags, vector min_s, vector max_s, string modelname, string headmodelname, string shortname, string mname);
-void register_turrets_done();
-
-const float TUR_MAXCOUNT = 24;
-#define TUR_FIRST 1
-float TUR_COUNT;
-float TUR_LAST;
-
-#define REGISTER_TURRET_2(id,func,turretflags,min_s,max_s,modelname,headmodelname,shortname,mname) \
- float id; \
- float func(float); \
- void RegisterTurrets_##id() \
- { \
- TUR_LAST = (id = TUR_FIRST + TUR_COUNT); \
- ++TUR_COUNT; \
- register_turret(id,func,turretflags,min_s,max_s,modelname,headmodelname,shortname,mname); \
- } \
- ACCUMULATE_FUNCTION(RegisterTurrets, RegisterTurrets_##id)
-#ifdef MENUQC
-#define REGISTER_TURRET(id,func,turretflags,min_s,max_s,modelname,headmodelname,shortname,mname) \
- REGISTER_TURRET_2(TUR_##id,t_null,turretflags,min_s,max_s,modelname,headmodelname,shortname,mname)
-#else
-#define REGISTER_TURRET(id,func,turretflags,min_s,max_s,modelname,headmodelname,shortname,mname) \
- REGISTER_TURRET_2(TUR_##id,func,turretflags,min_s,max_s,modelname,headmodelname,shortname,mname)
-#endif
-
-#define TUR_DUPECHECK(dupecheck,cvar) \
- #ifndef dupecheck \
- #define dupecheck \
- float cvar; \
- #else \
- #error DUPLICATE TURRET CVAR: cvar \
- #endif
-
-#define TUR_ADD_CVAR(turret,name) \
- TUR_DUPECHECK(TUR_CVAR_##turret##_##name, autocvar_g_turrets_unit_##turret##_##name)
-
-#define TUR_CVAR(turret,name) autocvar_g_turrets_unit_##turret##_##name
-
-#include "all.qh"
-
-#undef TUR_ADD_CVAR
-#undef REGISTER_TURRET
-ACCUMULATE_FUNCTION(RegisterTurrets, register_turrets_done);
-
-#endif
+++ /dev/null
-#ifdef REGISTER_TURRET
-REGISTER_TURRET(
-/* TUR_##id */ EWHEEL,
-/* function */ t_ewheel,
-/* spawnflags */ TUR_FLAG_PLAYER | TUR_FLAG_MOVE | TUR_FLAG_ROAM,
-/* mins,maxs */ '-32 -32 0', '32 32 48',
-/* model */ "ewheel-base2.md3",
-/* head_model */ "ewheel-gun1.md3",
-/* netname */ "ewheel",
-/* fullname */ _("eWheel Turret")
-);
-#else
-#ifdef SVQC
-float autocvar_g_turrets_unit_ewheel_speed_fast;
-float autocvar_g_turrets_unit_ewheel_speed_slow;
-float autocvar_g_turrets_unit_ewheel_speed_slower;
-float autocvar_g_turrets_unit_ewheel_speed_stop;
-float autocvar_g_turrets_unit_ewheel_turnrate;
-
-const float ewheel_anim_stop = 0;
-const float ewheel_anim_fwd_slow = 1;
-const float ewheel_anim_fwd_fast = 2;
-const float ewheel_anim_bck_slow = 3;
-const float ewheel_anim_bck_fast = 4;
-
-//#define EWHEEL_FANCYPATH
-void ewheel_move_path()
-{
-#ifdef EWHEEL_FANCYPATH
- // Are we close enougth to a path node to switch to the next?
- if (vlen(self.origin - self.pathcurrent.origin) < 64)
- if (self.pathcurrent.path_next == world)
- {
- // Path endpoint reached
- pathlib_deletepath(self.pathcurrent.owner);
- self.pathcurrent = world;
-
- if (self.pathgoal)
- {
- if (self.pathgoal.use)
- self.pathgoal.use();
-
- if (self.pathgoal.enemy)
- {
- self.pathcurrent = pathlib_astar(self.pathgoal.origin,self.pathgoal.enemy.origin);
- self.pathgoal = self.pathgoal.enemy;
- }
- }
- else
- self.pathgoal = world;
- }
- else
- self.pathcurrent = self.pathcurrent.path_next;
-
-#else
- if (vlen(self.origin - self.pathcurrent.origin) < 64)
- self.pathcurrent = self.pathcurrent.enemy;
-#endif
-
- if (self.pathcurrent)
- {
-
- self.moveto = self.pathcurrent.origin;
- self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
-
- movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_fast), 0.4);
- }
-}
-
-void ewheel_move_enemy()
-{
- float newframe;
-
- self.steerto = steerlib_arrive(self.enemy.origin,self.target_range_optimal);
-
- self.moveto = self.origin + self.steerto * 128;
-
- if (self.tur_dist_enemy > self.target_range_optimal)
- {
- if ( self.tur_head.spawnshieldtime < 1 )
- {
- newframe = ewheel_anim_fwd_fast;
- movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_fast), 0.4);
- }
- else if (self.tur_head.spawnshieldtime < 2)
- {
-
- newframe = ewheel_anim_fwd_slow;
- movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_slow), 0.4);
- }
- else
- {
- newframe = ewheel_anim_fwd_slow;
- movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_slower), 0.4);
- }
- }
- else if (self.tur_dist_enemy < self.target_range_optimal * 0.5)
- {
- newframe = ewheel_anim_bck_slow;
- movelib_move_simple(v_forward * -1, (autocvar_g_turrets_unit_ewheel_speed_slow), 0.4);
- }
- else
- {
- newframe = ewheel_anim_stop;
- movelib_beak_simple((autocvar_g_turrets_unit_ewheel_speed_stop));
- }
-
- turrets_setframe(newframe, false);
-}
-
-void ewheel_move_idle()
-{
- if(self.frame != 0)
- {
- self.SendFlags |= TNSF_ANIM;
- self.anim_start_time = time;
- }
-
- self.frame = 0;
- if (vlen(self.velocity))
- movelib_beak_simple((autocvar_g_turrets_unit_ewheel_speed_stop));
-}
-
-void spawnfunc_turret_ewheel() { if(!turret_initialize(TUR_EWHEEL)) remove(self); }
-
-float t_ewheel(float req)
-{
- switch(req)
- {
- case TR_ATTACK:
- {
- float i;
- entity _mis;
-
- for (i = 0; i < 1; ++i)
- {
- turret_do_updates(self);
-
- _mis = turret_projectile(W_Sound("lasergun_fire"), 1, 0, DEATH_TURRET_EWHEEL, PROJECTILE_BLASTER, TRUE, TRUE);
- _mis.missile_flags = MIF_SPLASH;
-
- Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
-
- self.tur_head.frame += 2;
-
- if (self.tur_head.frame > 3)
- self.tur_head.frame = 0;
- }
-
- return true;
- }
- case TR_THINK:
- {
- float vz;
- vector wish_angle, real_angle;
-
- vz = self.velocity_z;
-
- self.angles_x = anglemods(self.angles_x);
- self.angles_y = anglemods(self.angles_y);
-
- fixedmakevectors(self.angles);
-
- wish_angle = normalize(self.steerto);
- wish_angle = vectoangles(wish_angle);
- real_angle = wish_angle - self.angles;
- real_angle = shortangle_vxy(real_angle, self.tur_head.angles);
-
- self.tur_head.spawnshieldtime = fabs(real_angle_y);
- real_angle_y = bound(-self.tur_head.aim_speed, real_angle_y, self.tur_head.aim_speed);
- self.angles_y = (self.angles_y + real_angle_y);
-
- if(self.enemy)
- ewheel_move_enemy();
- else if(self.pathcurrent)
- ewheel_move_path();
- else
- ewheel_move_idle();
-
- self.velocity_z = vz;
-
- if(vlen(self.velocity))
- self.SendFlags |= TNSF_MOVE;
-
- return true;
- }
- case TR_DEATH:
- {
- self.velocity = '0 0 0';
-
-#ifdef EWHEEL_FANCYPATH
- if (self.pathcurrent)
- pathlib_deletepath(self.pathcurrent.owner);
-#endif
- self.pathcurrent = world;
-
- return true;
- }
- case TR_SETUP:
- {
- entity e;
-
- if(self.movetype == MOVETYPE_WALK)
- {
- self.velocity = '0 0 0';
- self.enemy = world;
-
- setorigin(self, self.pos1);
-
- if (self.target != "")
- {
- e = find(world, targetname, self.target);
- if (!e)
- {
- LOG_TRACE("Initital waypoint for ewheel does NOT exsist, fix your map!\n");
- self.target = "";
- }
-
- if (e.classname != "turret_checkpoint")
- LOG_TRACE("Warning: not a turrret path\n");
- else
- {
-
-#ifdef EWHEEL_FANCYPATH
- self.pathcurrent = WALKER_PATH(self.origin,e.origin);
- self.pathgoal = e;
-#else
- self.pathcurrent = e;
-#endif
- }
- }
- }
-
- self.iscreature = true;
- self.teleportable = TELEPORT_NORMAL;
- self.damagedbycontents = true;
- self.movetype = MOVETYPE_WALK;
- self.solid = SOLID_SLIDEBOX;
- self.takedamage = DAMAGE_AIM;
- self.idle_aim = '0 0 0';
- self.pos1 = self.origin;
- self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
- self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
- self.frame = self.tur_head.frame = 1;
- self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
-
- // Convert from dgr / sec to dgr / tic
- self.tur_head.aim_speed = (autocvar_g_turrets_unit_ewheel_turnrate);
- self.tur_head.aim_speed = self.tur_head.aim_speed / (1 / self.ticrate);
-
- return true;
- }
- case TR_PRECACHE:
- {
- precache_model ("models/turrets/ewheel-base2.md3");
- precache_model ("models/turrets/ewheel-gun1.md3");
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-
-void ewheel_draw()
-{
- float dt;
-
- dt = time - self.move_time;
- self.move_time = time;
- if(dt <= 0)
- return;
-
- fixedmakevectors(self.angles);
- setorigin(self, self.origin + self.velocity * dt);
- self.tur_head.angles += dt * self.tur_head.move_avelocity;
- self.angles_y = self.move_angles_y;
-
- if (self.health < 127)
- if(random() < 0.05)
- te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
-}
-
-float t_ewheel(float req)
-{
- switch(req)
- {
- case TR_SETUP:
- {
- self.gravity = 1;
- self.movetype = MOVETYPE_BOUNCE;
- self.move_movetype = MOVETYPE_BOUNCE;
- self.move_origin = self.origin;
- self.move_time = time;
- self.draw = ewheel_draw;
-
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
+++ /dev/null
-#ifdef REGISTER_TURRET
-REGISTER_TURRET(
-/* TUR_##id */ FLAC,
-/* function */ t_flac,
-/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_FASTPROJ | TUR_FLAG_MISSILE,
-/* mins,maxs */ '-32 -32 0', '32 32 64',
-/* model */ "base.md3",
-/* head_model */ "flac.md3",
-/* netname */ "flac",
-/* fullname */ _("FLAC Cannon")
-);
-#else
-#ifdef SVQC
-void turret_flac_projectile_think_explode()
-{
- if(self.enemy != world)
- if(vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 3)
- setorigin(self,self.enemy.origin + randomvec() * self.owner.shot_radius);
-
-#ifdef TURRET_DEBUG
- float d;
- d = RadiusDamage (self, self.owner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world);
- self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d;
- self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
-#else
- RadiusDamage (self, self.realowner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world);
-#endif
- remove(self);
-}
-
-void spawnfunc_turret_flac() { if(!turret_initialize(TUR_FLAC)) remove(self); }
-
-float t_flac(float req)
-{
- switch(req)
- {
- case TR_ATTACK:
- {
- entity proj;
-
- turret_tag_fire_update();
-
- proj = turret_projectile(W_Sound("hagar_fire"), 5, 0, DEATH_TURRET_FLAC, PROJECTILE_HAGAR, TRUE, TRUE);
- Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
- proj.think = turret_flac_projectile_think_explode;
- proj.nextthink = time + self.tur_impacttime + (random() * 0.01 - random() * 0.01);
- proj.missile_flags = MIF_SPLASH | MIF_PROXY;
-
- self.tur_head.frame = self.tur_head.frame + 1;
- if (self.tur_head.frame >= 4)
- self.tur_head.frame = 0;
-
- return true;
- }
- case TR_THINK:
- {
- return true;
- }
- case TR_DEATH:
- {
- return true;
- }
- case TR_SETUP:
- {
- self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
- self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
- self.damage_flags |= TFL_DMG_HEADSHAKE;
- self.target_select_flags |= TFL_TARGETSELECT_NOTURRETS | TFL_TARGETSELECT_MISSILESONLY;
-
- return true;
- }
- case TR_PRECACHE:
- {
- precache_model ("models/turrets/base.md3");
- precache_model ("models/turrets/flac.md3");
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_flac(float req)
-{
- switch(req)
- {
- case TR_SETUP:
- {
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
+++ /dev/null
-#ifdef REGISTER_TURRET
-REGISTER_TURRET(
-/* TUR_##id */ FUSIONREACTOR,
-/* function */ t_fusionreactor,
-/* spawnflags */ TUR_FLAG_SUPPORT | TUR_FLAG_AMMOSOURCE,
-/* mins,maxs */ '-34 -34 0', '34 34 90',
-/* model */ "base.md3",
-/* head_model */ "reactor.md3",
-/* netname */ "fusionreactor",
-/* fullname */ _("Fusion Reactor")
-);
-#else
-#ifdef SVQC
-bool turret_fusionreactor_firecheck()
-{
- if (self.attack_finished_single > time)
- return false;
-
- if (self.enemy.deadflag != DEAD_NO)
- return false;
-
- if (self.enemy == world)
- return false;
-
- if (self.ammo < self.shot_dmg)
- return false;
-
- if (self.enemy.ammo >= self.enemy.ammo_max)
- return false;
-
- if (vlen(self.enemy.origin - self.origin) > self.target_range)
- return false;
-
- if(self.team != self.enemy.team)
- return false;
-
- if(!(self.enemy.ammo_flags & TFL_AMMO_ENERGY))
- return false;
-
- return true;
-}
-
-void spawnfunc_turret_fusionreactor() { if(!turret_initialize(TUR_FUSIONREACTOR)) remove(self); }
-
-float t_fusionreactor(float req)
-{
- switch(req)
- {
- case TR_ATTACK:
- {
- vector fl_org;
-
- self.enemy.ammo = min(self.enemy.ammo + self.shot_dmg,self.enemy.ammo_max);
- fl_org = 0.5 * (self.enemy.absmin + self.enemy.absmax);
- te_smallflash(fl_org);
-
- return true;
- }
- case TR_THINK:
- {
- self.tur_head.avelocity = '0 250 0' * (self.ammo / self.ammo_max);
-
- return true;
- }
- case TR_DEATH:
- {
- return true;
- }
- case TR_SETUP:
- {
- self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE;
- self.target_select_flags = TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_OWNTEAM | TFL_TARGETSELECT_RANGELIMITS;
- self.firecheck_flags = TFL_FIRECHECK_AMMO_OWN | TFL_FIRECHECK_AMMO_OTHER | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_DEAD;
- self.shoot_flags = TFL_SHOOT_HITALLVALID;
- self.aim_flags = TFL_AIM_NO;
- self.track_flags = TFL_TRACK_NO;
-
- self.tur_head.scale = 0.75;
- self.tur_head.avelocity = '0 50 0';
-
- self.turret_firecheckfunc = turret_fusionreactor_firecheck;
-
- return true;
- }
- case TR_PRECACHE:
- {
- precache_model ("models/turrets/base.md3");
- precache_model ("models/turrets/reactor.md3");
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_fusionreactor(float req)
-{
- switch(req)
- {
- case TR_SETUP:
- {
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
+++ /dev/null
-#ifdef REGISTER_TURRET
-REGISTER_TURRET(
-/* TUR_##id */ HELLION,
-/* function */ t_hellion,
-/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_FASTPROJ | TUR_FLAG_PLAYER | TUR_FLAG_MISSILE,
-/* mins,maxs */ '-32 -32 0', '32 32 64',
-/* model */ "base.md3",
-/* head_model */ "hellion.md3",
-/* netname */ "hellion",
-/* fullname */ _("Hellion Missile Turret")
-);
-#else
-#ifdef SVQC
-float autocvar_g_turrets_unit_hellion_shot_speed_gain;
-float autocvar_g_turrets_unit_hellion_shot_speed_max;
-
-void turret_hellion_missile_think()
-{
- vector olddir,newdir;
- vector pre_pos;
- float itime;
-
- self.nextthink = time + 0.05;
-
- olddir = normalize(self.velocity);
-
- if(self.max_health < time)
- turret_projectile_explode();
-
- // Enemy dead? just keep on the current heading then.
- if ((self.enemy == world) || (self.enemy.deadflag != DEAD_NO))
- {
-
- // Make sure we dont return to tracking a respawned player
- self.enemy = world;
-
- // Turn model
- self.angles = vectoangles(self.velocity);
-
- if ( (vlen(self.origin - self.owner.origin)) > (self.owner.shot_radius * 5) )
- turret_projectile_explode();
-
- // Accelerate
- self.velocity = olddir * min(vlen(self.velocity) * (autocvar_g_turrets_unit_hellion_shot_speed_gain), (autocvar_g_turrets_unit_hellion_shot_speed_max));
-
- UpdateCSQCProjectile(self);
-
- return;
- }
-
- // Enemy in range?
- if (vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 0.2)
- turret_projectile_explode();
-
- // Predict enemy position
- itime = vlen(self.enemy.origin - self.origin) / vlen(self.velocity);
- pre_pos = self.enemy.origin + self.enemy.velocity * itime;
-
- pre_pos = (pre_pos + self.enemy.origin) * 0.5;
-
- // Find out the direction to that place
- newdir = normalize(pre_pos - self.origin);
-
- // Turn
- newdir = normalize(olddir + newdir * 0.35);
-
- // Turn model
- self.angles = vectoangles(self.velocity);
-
- // Accelerate
- self.velocity = newdir * min(vlen(self.velocity) * (autocvar_g_turrets_unit_hellion_shot_speed_gain), (autocvar_g_turrets_unit_hellion_shot_speed_max));
-
- if (itime < 0.05)
- self.think = turret_projectile_explode;
-
- UpdateCSQCProjectile(self);
-}
-
-void spawnfunc_turret_hellion() { if(!turret_initialize(TUR_HELLION)) remove(self); }
-
-float t_hellion(float req)
-{
- switch(req)
- {
- case TR_ATTACK:
- {
- entity missile;
-
- if(self.tur_head.frame != 0)
- self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire"));
- else
- self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire2"));
-
- missile = turret_projectile(W_Sound("rocket_fire"), 6, 10, DEATH_TURRET_HELLION, PROJECTILE_ROCKET, FALSE, FALSE);
- te_explosion (missile.origin);
- missile.think = turret_hellion_missile_think;
- missile.nextthink = time;
- missile.flags = FL_PROJECTILE;
- missile.max_health = time + 9;
- missile.tur_aimpos = randomvec() * 128;
- missile.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_HEAT;
- self.tur_head.frame += 1;
-
- return true;
- }
- case TR_THINK:
- {
- if (self.tur_head.frame != 0)
- self.tur_head.frame += 1;
-
- if (self.tur_head.frame >= 7)
- self.tur_head.frame = 0;
-
- return true;
- }
- case TR_DEATH:
- {
- return true;
- }
- case TR_SETUP:
- {
- self.aim_flags = TFL_AIM_SIMPLE;
- self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK ;
- self.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_TEAMCHECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF | TFL_FIRECHECK_AMMO_OWN;
- self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
-
- return true;
- }
- case TR_PRECACHE:
- {
- precache_model ("models/turrets/base.md3");
- precache_model ("models/turrets/hellion.md3");
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_hellion(float req)
-{
- switch(req)
- {
- case TR_SETUP:
- {
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
+++ /dev/null
-#ifdef REGISTER_TURRET
-REGISTER_TURRET(
-/* TUR_##id */ HK,
-/* function */ t_hk,
-/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER | TUR_FLAG_RECIEVETARGETS,
-/* mins,maxs */ '-32 -32 0', '32 32 64',
-/* model */ "base.md3",
-/* head_model */ "hk.md3",
-/* netname */ "hk",
-/* fullname */ _("Hunter-Killer Turret")
-);
-#else
-#ifdef SVQC
-float autocvar_g_turrets_unit_hk_shot_speed;
-float autocvar_g_turrets_unit_hk_shot_speed_accel;
-float autocvar_g_turrets_unit_hk_shot_speed_accel2;
-float autocvar_g_turrets_unit_hk_shot_speed_decel;
-float autocvar_g_turrets_unit_hk_shot_speed_max;
-float autocvar_g_turrets_unit_hk_shot_speed_turnrate;
-
-//#define TURRET_DEBUG_HK
-
-#ifdef TURRET_DEBUG_HK
-.float atime;
-#endif
-
-float hk_is_valid_target(entity e_target)
-{
- if (e_target == world)
- return 0;
-
- // If only this was used more..
- if (e_target.flags & FL_NOTARGET)
- return 0;
-
- // Cant touch this
- if ((e_target.takedamage == DAMAGE_NO) || (e_target.health < 0))
- return 0;
-
- // player
- if (IS_CLIENT(e_target))
- {
- if (self.owner.target_select_playerbias < 0)
- return 0;
-
- if (e_target.deadflag != DEAD_NO)
- return 0;
- }
-
- // Missile
- if ((e_target.flags & FL_PROJECTILE) && (self.owner.target_select_missilebias < 0))
- return 0;
-
- // Team check
- if ((e_target.team == self.owner.team) || (self.owner.team == e_target.owner.team))
- return 0;
-
- return 1;
-}
-
-void turret_hk_missile_think()
-{
- vector vu, vd, vf, vl, vr, ve; // Vector (direction)
- float fu, fd, ff, fl, fr, fe; // Fraction to solid
- vector olddir,wishdir,newdir; // Final direction
- float lt_for; // Length of Trace FORwrad
- float lt_seek; // Length of Trace SEEK (left, right, up down)
- float pt_seek; // Pitch of Trace SEEK (How mutch to angele left, right up, down trace towards v_forward)
- vector pre_pos;
- float myspeed;
- entity e;
- float ad,edist;
-
- self.nextthink = time + self.ticrate;
-
- //if (self.cnt < time)
- // turret_hk_missile_explode();
-
- if (self.enemy.deadflag != DEAD_NO)
- self.enemy = world;
-
- // Pick the closest valid target.
- if (!self.enemy)
- {
- e = findradius(self.origin, 5000);
- while (e)
- {
- if (hk_is_valid_target(e))
- {
- if (!self.enemy)
- self.enemy = e;
- else
- if (vlen(self.origin - e.origin) < vlen(self.origin - self.enemy.origin))
- self.enemy = e;
- }
- e = e.chain;
- }
- }
-
- self.angles = vectoangles(self.velocity);
- self.angles_x = self.angles_x * -1;
- makevectors(self.angles);
- self.angles_x = self.angles_x * -1;
-
- if (self.enemy)
- {
- edist = vlen(self.origin - self.enemy.origin);
- // Close enougth to do decent damage?
- if ( edist <= (self.owner.shot_radius * 0.25) )
- {
- turret_projectile_explode();
- return;
- }
-
- // Get data on enemy position
- pre_pos = self.enemy.origin +
- self.enemy.velocity *
- min((vlen(self.enemy.origin - self.origin) / vlen(self.velocity)),0.5);
-
- traceline(self.origin, pre_pos,true,self.enemy);
- ve = normalize(pre_pos - self.origin);
- fe = trace_fraction;
-
- }
- else
- {
- edist = 0;
- ve = '0 0 0';
- fe = 0;
- }
-
- if ((fe != 1) || (self.enemy == world) || (edist > 1000))
- {
- myspeed = vlen(self.velocity);
-
- lt_for = myspeed * 3;
- lt_seek = myspeed * 2.95;
-
- // Trace forward
- traceline(self.origin, self.origin + v_forward * lt_for,false,self);
- vf = trace_endpos;
- ff = trace_fraction;
-
- // Find angular offset
- ad = vlen(vectoangles(normalize(self.enemy.origin - self.origin)) - self.angles);
-
- // To close to something, Slow down!
- if ( ((ff < 0.7) || (ad > 4)) && (myspeed > (autocvar_g_turrets_unit_hk_shot_speed)) )
- myspeed = max(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_decel), (autocvar_g_turrets_unit_hk_shot_speed));
-
- // Failry clear, accelerate.
- if ( (ff > 0.7) && (myspeed < (autocvar_g_turrets_unit_hk_shot_speed_max)) )
- myspeed = min(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_accel), (autocvar_g_turrets_unit_hk_shot_speed_max));
-
- // Setup trace pitch
- pt_seek = 1 - ff;
- pt_seek = bound(0.15,pt_seek,0.8);
- if (ff < 0.5) pt_seek = 1;
-
- // Trace left
- traceline(self.origin, self.origin + (-1 * (v_right * pt_seek) + (v_forward * ff)) * lt_seek,false,self);
- vl = trace_endpos;
- fl = trace_fraction;
-
- // Trace right
- traceline(self.origin, self.origin + ((v_right * pt_seek) + (v_forward * ff)) * lt_seek ,false,self);
- vr = trace_endpos;
- fr = trace_fraction;
-
- // Trace up
- traceline(self.origin, self.origin + ((v_up * pt_seek) + (v_forward * ff)) * lt_seek ,false,self);
- vu = trace_endpos;
- fu = trace_fraction;
-
- // Trace down
- traceline(self.origin, self.origin + (-1 * (v_up * pt_seek) + (v_forward * ff)) * lt_seek ,false,self);
- vd = trace_endpos;
- fd = trace_fraction;
-
- vl = normalize(vl - self.origin);
- vr = normalize(vr - self.origin);
- vu = normalize(vu - self.origin);
- vd = normalize(vd - self.origin);
-
- // Panic tresh passed, find a single direction and turn as hard as we can
- if (pt_seek == 1)
- {
- wishdir = v_right;
- if (fl > fr) wishdir = -1 * v_right;
- if (fu > fl) wishdir = v_up;
- if (fd > fu) wishdir = -1 * v_up;
- }
- else
- {
- // Normalize our trace vectors to make a smooth path
- wishdir = normalize( (vl * fl) + (vr * fr) + (vu * fu) + (vd * fd) );
- }
-
- if (self.enemy)
- {
- if (fe < 0.1) fe = 0.1; // Make sure we always try to move sligtly towards our target
- wishdir = (wishdir * (1 - fe)) + (ve * fe);
- }
- }
- else
- {
- // Got a clear path to target, speed up fast (if not at full speed) and go straight for it.
- myspeed = vlen(self.velocity);
- if (myspeed < (autocvar_g_turrets_unit_hk_shot_speed_max))
- myspeed = min(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_accel2),(autocvar_g_turrets_unit_hk_shot_speed_max));
-
- wishdir = ve;
- }
-
- if ((myspeed > (autocvar_g_turrets_unit_hk_shot_speed)) && (self.cnt > time))
- myspeed = min(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_accel2),(autocvar_g_turrets_unit_hk_shot_speed_max));
-
- // Ranoutagazfish?
- if (self.cnt < time)
- {
- self.cnt = time + 0.25;
- self.nextthink = 0;
- self.movetype = MOVETYPE_BOUNCE;
- return;
- }
-
- // Calculate new heading
- olddir = normalize(self.velocity);
- newdir = normalize(olddir + wishdir * (autocvar_g_turrets_unit_hk_shot_speed_turnrate));
-
- // Set heading & speed
- self.velocity = newdir * myspeed;
-
- // Align model with new heading
- self.angles = vectoangles(self.velocity);
-
-
-#ifdef TURRET_DEBUG_HK
- //if(self.atime < time) {
- if ((fe <= 0.99)||(edist > 1000))
- {
- te_lightning2(world,self.origin, self.origin + vr * lt_seek);
- te_lightning2(world,self.origin, self.origin + vl * lt_seek);
- te_lightning2(world,self.origin, self.origin + vu * lt_seek);
- te_lightning2(world,self.origin, self.origin + vd * lt_seek);
- te_lightning2(world,self.origin, vf);
- }
- else
- {
- te_lightning2(world,self.origin, self.enemy.origin);
- }
- bprint("Speed: ", ftos(rint(myspeed)), "\n");
- bprint("Trace to solid: ", ftos(rint(ff * 100)), "%\n");
- bprint("Trace to target:", ftos(rint(fe * 100)), "%\n");
- self.atime = time + 0.2;
- //}
-#endif
-
- UpdateCSQCProjectile(self);
-}
-
-float turret_hk_addtarget(entity e_target,entity e_sender)
-{
- if (e_target)
- {
- if (turret_validate_target(self,e_target,self.target_validate_flags) > 0)
- {
- self.enemy = e_target;
- return 1;
- }
- }
-
- return 0;
-}
-
-void spawnfunc_turret_hk() { if(!turret_initialize(TUR_HK)) remove(self); }
-
-float t_hk(float req)
-{
- switch(req)
- {
- case TR_ATTACK:
- {
- entity missile;
-
- missile = turret_projectile(W_Sound("rocket_fire"), 6, 10, DEATH_TURRET_HK, PROJECTILE_ROCKET, FALSE, FALSE);
- te_explosion (missile.origin);
-
- missile.think = turret_hk_missile_think;
- missile.nextthink = time + 0.25;
- missile.movetype = MOVETYPE_BOUNCEMISSILE;
- missile.velocity = self.tur_shotdir_updated * (self.shot_speed * 0.75);
- missile.angles = vectoangles(missile.velocity);
- missile.cnt = time + 30;
- missile.ticrate = max(autocvar_sys_ticrate, 0.05);
- missile.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_AI;
-
- if (self.tur_head.frame == 0)
- self.tur_head.frame = self.tur_head.frame + 1;
-
- return true;
- }
- case TR_THINK:
- {
- if (self.tur_head.frame != 0)
- self.tur_head.frame = self.tur_head.frame + 1;
-
- if (self.tur_head.frame > 5)
- self.tur_head.frame = 0;
-
- return true;
- }
- case TR_DEATH:
- {
- return true;
- }
- case TR_SETUP:
- {
- self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
- self.aim_flags = TFL_AIM_SIMPLE;
- self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TRIGGERTARGET | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
- self.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_TEAMCHECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF;
- self.shoot_flags = TFL_SHOOT_CLEARTARGET;
- self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TEAMCHECK;
-
- self.turret_addtarget = turret_hk_addtarget;
-
- return true;
- }
- case TR_PRECACHE:
- {
- precache_model ("models/turrets/base.md3");
- precache_model ("models/turrets/hk.md3");
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_hk(float req)
-{
- switch(req)
- {
- case TR_SETUP:
- {
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
+++ /dev/null
-#ifdef REGISTER_TURRET
-REGISTER_TURRET(
-/* TUR_##id */ MACHINEGUN,
-/* function */ t_machinegun,
-/* spawnflags */ TUR_FLAG_PLAYER,
-/* mins,maxs */ '-32 -32 0', '32 32 64',
-/* model */ "base.md3",
-/* head_model */ "machinegun.md3",
-/* netname */ "machinegun",
-/* fullname */ _("Machinegun Turret")
-);
-#else
-#ifdef SVQC
-void spawnfunc_turret_machinegun() { if(!turret_initialize(TUR_MACHINEGUN)) remove(self); }
-
-void W_MachineGun_MuzzleFlash(void);
-
-float t_machinegun(float req)
-{
- switch(req)
- {
- case TR_ATTACK:
- {
- fireBullet (self.tur_shotorg, self.tur_shotdir_updated, self.shot_spread, 0, self.shot_dmg, self.shot_force, DEATH_TURRET_MACHINEGUN, 0);
-
- W_MachineGun_MuzzleFlash();
- setattachment(self.muzzle_flash, self.tur_head, "tag_fire");
-
- return true;
- }
- case TR_THINK:
- {
- return true;
- }
- case TR_DEATH:
- {
- return true;
- }
- case TR_SETUP:
- {
- self.damage_flags |= TFL_DMG_HEADSHAKE;
- self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
- self.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
- self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
- self.turret_flags |= TUR_FLAG_HITSCAN;
-
- return true;
- }
- case TR_PRECACHE:
- {
- precache_model ("models/turrets/base.md3");
- precache_model ("models/turrets/machinegun.md3");
- precache_sound (W_Sound("uzi_fire"));
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_machinegun(float req)
-{
- switch(req)
- {
- case TR_SETUP:
- {
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
+++ /dev/null
-#ifdef REGISTER_TURRET
-REGISTER_TURRET(
-/* TUR_##id */ MLRS,
-/* function */ t_mlrs,
-/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER,
-/* mins,maxs */ '-32 -32 0', '32 32 64',
-/* model */ "base.md3",
-/* head_model */ "mlrs.md3",
-/* netname */ "mlrs",
-/* fullname */ _("MLRS Turret")
-);
-#else
-#ifdef SVQC
-void spawnfunc_turret_mlrs() { if(!turret_initialize(TUR_MLRS)) remove(self); }
-
-float t_mlrs(float req)
-{
- switch(req)
- {
- case TR_ATTACK:
- {
- entity missile;
-
- turret_tag_fire_update();
- missile = turret_projectile(W_Sound("rocket_fire"), 6, 10, DEATH_TURRET_MLRS, PROJECTILE_ROCKET, TRUE, TRUE);
- missile.nextthink = time + max(self.tur_impacttime,(self.shot_radius * 2) / self.shot_speed);
- missile.missile_flags = MIF_SPLASH;
- te_explosion (missile.origin);
-
- return true;
- }
- case TR_THINK:
- {
- // 0 = full, 6 = empty
- self.tur_head.frame = bound(0, 6 - floor(0.1 + self.ammo / self.shot_dmg), 6);
- if(self.tur_head.frame < 0)
- {
- LOG_TRACE("ammo:",ftos(self.ammo),"\n");
- LOG_TRACE("shot_dmg:",ftos(self.shot_dmg),"\n");
- }
-
- return true;
- }
- case TR_DEATH:
- {
- return true;
- }
- case TR_SETUP:
- {
- self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
- self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
-
- self.damage_flags |= TFL_DMG_HEADSHAKE;
- self.shoot_flags |= TFL_SHOOT_VOLLYALWAYS;
- self.volly_counter = self.shot_volly;
-
- return true;
- }
- case TR_PRECACHE:
- {
- precache_model ("models/turrets/base.md3");
- precache_model ("models/turrets/mlrs.md3");
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_mlrs(float req)
-{
- switch(req)
- {
- case TR_SETUP:
- {
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
+++ /dev/null
-#ifdef REGISTER_TURRET
-REGISTER_TURRET(
-/* TUR_##id */ PHASER,
-/* function */ t_phaser,
-/* spawnflags */ TUR_FLAG_SNIPER | TUR_FLAG_HITSCAN | TUR_FLAG_PLAYER,
-/* mins,maxs */ '-32 -32 0', '32 32 64',
-/* model */ "base.md3",
-/* head_model */ "phaser.md3",
-/* netname */ "phaser",
-/* fullname */ _("Phaser Cannon")
-);
-#else
-#ifdef SVQC
-.float fireflag;
-
-float turret_phaser_firecheck()
-{
- if (self.fireflag != 0) return 0;
- return turret_firecheck();
-}
-
-void beam_think()
-{
- if ((time > self.cnt) || (self.owner.deadflag != DEAD_NO))
- {
- self.owner.attack_finished_single = time + self.owner.shot_refire;
- self.owner.fireflag = 2;
- self.owner.tur_head.frame = 10;
- sound (self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTEN_NORM);
- remove(self);
- return;
- }
-
- turret_do_updates(self.owner);
-
- if (time - self.shot_spread > 0)
- {
- self.shot_spread = time + 2;
- sound (self, CH_SHOTS_SINGLE, "turrets/phaser.wav", VOL_BASE, ATTEN_NORM);
- }
-
-
- self.nextthink = time + self.ticrate;
-
- self.owner.attack_finished_single = time + frametime;
- entity oldself;
- oldself = self;
- self = self.owner;
- FireImoBeam ( self.tur_shotorg,
- self.tur_shotorg + self.tur_shotdir_updated * self.target_range,
- '-1 -1 -1' * self.shot_radius,
- '1 1 1' * self.shot_radius,
- self.shot_force,
- oldself.shot_dmg,
- 0.75,
- DEATH_TURRET_PHASER);
- self = oldself;
- self.scale = vlen(self.owner.tur_shotorg - trace_endpos) / 256;
-
-}
-
-void spawnfunc_turret_phaser() { if(!turret_initialize(TUR_PHASER)) remove(self); }
-
-float t_phaser(float req)
-{
- switch(req)
- {
- case TR_ATTACK:
- {
- entity beam;
-
- beam = spawn();
- beam.ticrate = 0.1; //autocvar_sys_ticrate;
- setmodel(beam,"models/turrets/phaser_beam.md3");
- beam.effects = EF_LOWPRECISION;
- beam.solid = SOLID_NOT;
- beam.think = beam_think;
- beam.cnt = time + self.shot_speed;
- beam.shot_spread = time + 2;
- beam.nextthink = time;
- beam.owner = self;
- beam.shot_dmg = self.shot_dmg / (self.shot_speed / beam.ticrate);
- beam.scale = self.target_range / 256;
- beam.movetype = MOVETYPE_NONE;
- beam.enemy = self.enemy;
- beam.bot_dodge = true;
- beam.bot_dodgerating = beam.shot_dmg;
- sound (beam, CH_SHOTS_SINGLE, "turrets/phaser.wav", VOL_BASE, ATTEN_NORM);
- self.fireflag = 1;
-
- beam.attack_finished_single = self.attack_finished_single;
- self.attack_finished_single = time; // + autocvar_sys_ticrate;
-
- setattachment(beam,self.tur_head,"tag_fire");
-
- soundat (self, trace_endpos, CH_SHOTS, W_Sound("neximpact"), VOL_BASE, ATTEN_NORM);
-
- if (self.tur_head.frame == 0)
- self.tur_head.frame = 1;
-
- return true;
- }
- case TR_THINK:
- {
- if (self.tur_head.frame != 0)
- {
- if (self.fireflag == 1)
- {
- if (self.tur_head.frame == 10)
- self.tur_head.frame = 1;
- else
- self.tur_head.frame = self.tur_head.frame +1;
- }
- else if (self.fireflag == 2 )
- {
- self.tur_head.frame = self.tur_head.frame +1;
- if (self.tur_head.frame == 15)
- {
- self.tur_head.frame = 0;
- self.fireflag = 0;
- }
- }
- }
-
- return true;
- }
- case TR_DEATH:
- {
- return true;
- }
- case TR_SETUP:
- {
- self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
- self.aim_flags = TFL_AIM_LEAD;
-
- self.turret_firecheckfunc = turret_phaser_firecheck;
-
- return true;
- }
- case TR_PRECACHE:
- {
- precache_model ("models/turrets/base.md3");
- precache_model ("models/turrets/phaser.md3");
- precache_model ("models/turrets/phaser_beam.md3");
- precache_sound ("turrets/phaser.wav");
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_phaser(float req)
-{
- switch(req)
- {
- case TR_SETUP:
- {
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
+++ /dev/null
-#ifdef REGISTER_TURRET
-REGISTER_TURRET(
-/* TUR_##id */ PLASMA,
-/* function */ t_plasma,
-/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER,
-/* mins,maxs */ '-32 -32 0', '32 32 64',
-/* model */ "base.md3",
-/* head_model */ "plasma.md3",
-/* netname */ "plasma",
-/* fullname */ _("Plasma Cannon")
-);
-#else
-#ifdef SVQC
-void spawnfunc_turret_plasma() { if(!turret_initialize(TUR_PLASMA)) remove(self); }
-
-float t_plasma(float req)
-{
- switch(req)
- {
- case TR_ATTACK:
- {
- if(g_instagib)
- {
- float flying;
- flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last
-
- FireRailgunBullet (self.tur_shotorg, self.tur_shotorg + self.tur_shotdir_updated * MAX_SHOT_DISTANCE, 10000000000,
- 800, 0, 0, 0, 0, DEATH_TURRET_PLASMA);
-
- Send_Effect(EFFECT_VORTEX_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
-
- // teamcolor / hit beam effect
- vector v;
- string s;
- v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
- s = strcat("TE_TEI_G3", ((self.team) ? Static_Team_ColorName_Upper(self.team) : ""));
-
- WarpZone_TrailParticles(world, _particleeffectnum(s), self.tur_shotorg, v);
-
- if (self.tur_head.frame == 0)
- self.tur_head.frame = 1;
- }
- else
- {
- entity missile = turret_projectile(W_Sound("hagar_fire"), 1, 0, DEATH_TURRET_PLASMA, PROJECTILE_ELECTRO_BEAM, TRUE, TRUE);
- missile.missile_flags = MIF_SPLASH;
-
- Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
- if (self.tur_head.frame == 0)
- self.tur_head.frame = 1;
- }
-
- return true;
- }
- case TR_THINK:
- {
- if (self.tur_head.frame != 0)
- self.tur_head.frame = self.tur_head.frame + 1;
-
- if (self.tur_head.frame > 5)
- self.tur_head.frame = 0;
-
- return true;
- }
- case TR_DEATH:
- {
- return true;
- }
- case TR_SETUP:
- {
- self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
- self.damage_flags |= TFL_DMG_HEADSHAKE;
- self.firecheck_flags |= TFL_FIRECHECK_AFF;
- self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_SPLASH;
-
- turret_do_updates(self);
-
- return true;
- }
- case TR_PRECACHE:
- {
- precache_model ("models/turrets/base.md3");
- precache_model ("models/turrets/plasma.md3");
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_plasma(float req)
-{
- switch(req)
- {
- case TR_SETUP:
- {
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
+++ /dev/null
-#ifdef REGISTER_TURRET
-REGISTER_TURRET(
-/* TUR_##id */ PLASMA_DUAL,
-/* function */ t_plasma_dual,
-/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER,
-/* mins,maxs */ '-32 -32 0', '32 32 64',
-/* model */ "base.md3",
-/* head_model */ "plasmad.md3",
-/* netname */ "plasma_dual",
-/* fullname */ _("Dual Plasma Cannon")
-);
-#else
-#ifdef SVQC
-void spawnfunc_turret_plasma_dual() { if(!turret_initialize(TUR_PLASMA_DUAL)) remove(self); }
-
-float t_plasma_dual(float req)
-{
- switch(req)
- {
- case TR_ATTACK:
- {
- if(g_instagib)
- {
- float flying;
- flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last
-
- FireRailgunBullet (self.tur_shotorg, self.tur_shotorg + self.tur_shotdir_updated * MAX_SHOT_DISTANCE, 10000000000,
- 800, 0, 0, 0, 0, DEATH_TURRET_PLASMA);
-
-
- Send_Effect(EFFECT_VORTEX_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
-
- // teamcolor / hit beam effect
- vector v;
- string s;
- v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
- s = strcat(EFFECT_VAPORIZER_NEUTRAL.eent_eff_name, ((self.team) ? Static_Team_ColorName_Upper(self.team) : ""));
-
- WarpZone_TrailParticles(world, _particleeffectnum(s), self.tur_shotorg, v);
-
- self.tur_head.frame += 1;
- }
- else
- {
- entity missile = turret_projectile(W_Sound("hagar_fire"), 1, 0, DEATH_TURRET_PLASMA, PROJECTILE_ELECTRO_BEAM, TRUE, TRUE);
- missile.missile_flags = MIF_SPLASH;
- Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
- self.tur_head.frame += 1;
- }
-
- return true;
- }
- case TR_THINK:
- {
- if ((self.tur_head.frame != 0) && (self.tur_head.frame != 3))
- self.tur_head.frame = self.tur_head.frame + 1;
-
- if (self.tur_head.frame > 6)
- self.tur_head.frame = 0;
-
- return true;
- }
- case TR_DEATH:
- {
- return true;
- }
- case TR_SETUP:
- {
- self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
- self.damage_flags |= TFL_DMG_HEADSHAKE;
- self.firecheck_flags |= TFL_FIRECHECK_AFF;
- self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_SPLASH;
-
- turret_do_updates(self);
-
- return true;
- }
- case TR_PRECACHE:
- {
- precache_model ("models/turrets/base.md3");
- precache_model ("models/turrets/plasmad.md3");
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_plasma_dual(float req)
-{
- switch(req)
- {
- case TR_SETUP:
- {
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
+++ /dev/null
-#ifdef REGISTER_TURRET
-REGISTER_TURRET(
-/* TUR_##id */ TESLA,
-/* function */ t_tesla,
-/* spawnflags */ TUR_FLAG_HITSCAN | TUR_FLAG_PLAYER | TUR_FLAG_MISSILE,
-/* mins,maxs */ '-60 -60 0', '60 60 128',
-/* model */ "tesla_base.md3",
-/* head_model */ "tesla_head.md3",
-/* netname */ "tesla",
-/* fullname */ _("Tesla Coil")
-);
-#else
-#ifdef SVQC
-entity toast(entity from, float range, float damage)
-{
- entity e;
- entity etarget = world;
- float d,dd;
- float r;
-
- dd = range + 1;
-
- e = findradius(from.origin,range);
- while (e)
- {
- if ((e.railgunhit != 1) && (e != from))
- {
- r = turret_validate_target(self,e,self.target_validate_flags);
- if (r > 0)
- {
- traceline(from.origin,0.5 * (e.absmin + e.absmax),MOVE_WORLDONLY,from);
- if (trace_fraction == 1.0)
- {
- d = vlen(e.origin - from.origin);
- if (d < dd)
- {
- dd = d;
- etarget = e;
- }
- }
- }
- }
- e = e.chain;
- }
-
- if (etarget)
- {
- te_csqc_lightningarc(from.origin,etarget.origin);
- Damage(etarget, self, self, damage, DEATH_TURRET_TESLA, etarget.origin, '0 0 0');
- etarget.railgunhit = 1;
- }
-
- return etarget;
-}
-
-float turret_tesla_firecheck()
-{
- // g_turrets_targetscan_maxdelay forces a target re-scan at least this often
- float do_target_scan = 0;
-
- if((self.target_select_time + autocvar_g_turrets_targetscan_maxdelay) < time)
- do_target_scan = 1;
-
- // Old target (if any) invalid?
- if(self.target_validate_time < time)
- if (turret_validate_target(self, self.enemy, self.target_validate_flags) <= 0)
- {
- self.enemy = world;
- self.target_validate_time = time + 0.5;
- do_target_scan = 1;
- }
-
- // But never more often then g_turrets_targetscan_mindelay!
- if (self.target_select_time + autocvar_g_turrets_targetscan_mindelay > time)
- do_target_scan = 0;
-
- if(do_target_scan)
- {
- self.enemy = turret_select_target();
- self.target_select_time = time;
- }
-
- if(!turret_firecheck())
- return 0;
-
- if(self.enemy)
- return 1;
-
- return 0;
-}
-
-void spawnfunc_turret_tesla() { if(!turret_initialize(TUR_TESLA)) remove(self); }
-
-float t_tesla(float req)
-{
- switch(req)
- {
- case TR_ATTACK:
- {
- entity e, t;
- float d, r, i;
-
- d = self.shot_dmg;
- r = self.target_range;
- e = spawn();
- setorigin(e,self.tur_shotorg);
-
- self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
-
- t = toast(e,r,d);
- remove(e);
-
- if (t == world) return true;
-
- self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | TFL_TARGETSELECT_TEAMCHECK;
-
- self.attack_finished_single = time + self.shot_refire;
- for (i = 0; i < 10; ++i)
- {
- d *= 0.75;
- r *= 0.85;
- t = toast(t, r, d);
- if (t == world) break;
-
- }
-
- e = findchainfloat(railgunhit, 1);
- while (e)
- {
- e.railgunhit = 0;
- e = e.chain;
- }
-
- return true;
- }
- case TR_THINK:
- {
- if(!self.active)
- {
- self.tur_head.avelocity = '0 0 0';
- return true;
- }
-
- if(self.ammo < self.shot_dmg)
- {
- self.tur_head.avelocity = '0 45 0' * (self.ammo / self.shot_dmg);
- }
- else
- {
- self.tur_head.avelocity = '0 180 0' * (self.ammo / self.shot_dmg);
-
- if(self.attack_finished_single > time)
- return true;
-
- float f;
- f = (self.ammo / self.ammo_max);
- f = f * f;
- if(f > random())
- if(random() < 0.1)
- te_csqc_lightningarc(self.tur_shotorg,self.tur_shotorg + (randomvec() * 350));
- }
-
- return true;
- }
- case TR_DEATH:
- {
- return true;
- }
- case TR_SETUP:
- {
- self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
- TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
-
- self.turret_firecheckfunc = turret_tesla_firecheck;
- self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
- TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
-
- self.firecheck_flags = TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AMMO_OWN;
- self.shoot_flags = TFL_SHOOT_CUSTOM;
- self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
- self.aim_flags = TFL_AIM_NO;
- self.track_flags = TFL_TRACK_NO;
-
- return true;
- }
- case TR_PRECACHE:
- {
- precache_model ("models/turrets/tesla_base.md3");
- precache_model ("models/turrets/tesla_head.md3");
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_tesla(float req)
-{
- switch(req)
- {
- case TR_SETUP:
- {
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
+++ /dev/null
-#ifdef REGISTER_TURRET
-REGISTER_TURRET(
-/* TUR_##id */ WALKER,
-/* function */ t_walker,
-/* spawnflags */ TUR_FLAG_PLAYER | TUR_FLAG_MOVE,
-/* mins,maxs */ '-70 -70 0', '70 70 95',
-/* model */ "walker_body.md3",
-/* head_model */ "walker_head_minigun.md3",
-/* netname */ "walker",
-/* fullname */ _("Walker Turret")
-);
-#else
-#ifdef SVQC
-float autocvar_g_turrets_unit_walker_melee_damage;
-float autocvar_g_turrets_unit_walker_melee_force;
-float autocvar_g_turrets_unit_walker_melee_range;
-float autocvar_g_turrets_unit_walker_rocket_damage;
-float autocvar_g_turrets_unit_walker_rocket_radius;
-float autocvar_g_turrets_unit_walker_rocket_force;
-float autocvar_g_turrets_unit_walker_rocket_speed;
-float autocvar_g_turrets_unit_walker_rocket_range;
-float autocvar_g_turrets_unit_walker_rocket_range_min;
-float autocvar_g_turrets_unit_walker_rocket_refire;
-float autocvar_g_turrets_unit_walker_rocket_turnrate;
-float autocvar_g_turrets_unit_walker_speed_stop;
-float autocvar_g_turrets_unit_walker_speed_walk;
-float autocvar_g_turrets_unit_walker_speed_run;
-float autocvar_g_turrets_unit_walker_speed_jump;
-float autocvar_g_turrets_unit_walker_speed_swim;
-float autocvar_g_turrets_unit_walker_speed_roam;
-float autocvar_g_turrets_unit_walker_turn;
-float autocvar_g_turrets_unit_walker_turn_walk;
-float autocvar_g_turrets_unit_walker_turn_strafe;
-float autocvar_g_turrets_unit_walker_turn_swim;
-float autocvar_g_turrets_unit_walker_turn_run;
-
-#define ANIM_NO 0
-#define ANIM_TURN 1
-#define ANIM_WALK 2
-#define ANIM_RUN 3
-#define ANIM_STRAFE_L 4
-#define ANIM_STRAFE_R 5
-#define ANIM_JUMP 6
-#define ANIM_LAND 7
-#define ANIM_PAIN 8
-#define ANIM_MELEE 9
-#define ANIM_SWIM 10
-#define ANIM_ROAM 11
-
-.float animflag;
-.float idletime;
-
-#define WALKER_PATH(s,e) pathlib_astar(s,e)
-
-float walker_firecheck()
-{
- if (self.animflag == ANIM_MELEE)
- return 0;
-
- return turret_firecheck();
-}
-
-void walker_melee_do_dmg()
-{
- vector where;
- entity e;
-
- makevectors(self.angles);
- where = self.origin + v_forward * 128;
-
- e = findradius(where,32);
- while (e)
- {
- if (turret_validate_target(self, e, self.target_validate_flags))
- if (e != self && e.owner != self)
- Damage(e, self, self, (autocvar_g_turrets_unit_walker_melee_damage), DEATH_TURRET_WALK_MELEE, '0 0 0', v_forward * (autocvar_g_turrets_unit_walker_melee_force));
-
- e = e.chain;
- }
-}
-
-void walker_setnoanim()
-{
- turrets_setframe(ANIM_NO, false);
- self.animflag = self.frame;
-}
-void walker_rocket_explode()
-{
- RadiusDamage (self, self.owner, (autocvar_g_turrets_unit_walker_rocket_damage), 0, (autocvar_g_turrets_unit_walker_rocket_radius), self, world, (autocvar_g_turrets_unit_walker_rocket_force), DEATH_TURRET_WALK_ROCKET, world);
- remove (self);
-}
-
-void walker_rocket_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
-{
- self.health = self.health - damage;
- self.velocity = self.velocity + vforce;
-
- if (self.health <= 0)
- W_PrepareExplosionByDamage(self.owner, walker_rocket_explode);
-}
-
-#define WALKER_ROCKET_MOVE movelib_move_simple(newdir, (autocvar_g_turrets_unit_walker_rocket_speed), (autocvar_g_turrets_unit_walker_rocket_turnrate)); UpdateCSQCProjectile(self)
-void walker_rocket_loop();
-void walker_rocket_think()
-{
- vector newdir;
- float edist;
- float itime;
- float m_speed;
-
- self.nextthink = time;
-
- edist = vlen(self.enemy.origin - self.origin);
-
- // Simulate crude guidance
- if (self.cnt < time)
- {
- if (edist < 1000)
- self.tur_shotorg = randomvec() * min(edist, 64);
- else
- self.tur_shotorg = randomvec() * min(edist, 256);
-
- self.cnt = time + 0.5;
- }
-
- if (edist < 128)
- self.tur_shotorg = '0 0 0';
-
- if (self.max_health < time)
- {
- self.think = walker_rocket_explode;
- self.nextthink = time;
- return;
- }
-
- if (self.shot_dmg != 1337 && random() < 0.01)
- {
- walker_rocket_loop();
- return;
- }
-
- m_speed = vlen(self.velocity);
-
- // Enemy dead? just keep on the current heading then.
- if (self.enemy == world || self.enemy.deadflag != DEAD_NO)
- self.enemy = world;
-
- if (self.enemy)
- {
- itime = max(edist / m_speed, 1);
- newdir = steerlib_pull(self.enemy.origin + self.tur_shotorg);
- }
- else
- newdir = normalize(self.velocity);
-
- WALKER_ROCKET_MOVE;
-}
-
-void walker_rocket_loop3()
-{
- vector newdir;
- self.nextthink = time;
-
- if (self.max_health < time)
- {
- self.think = walker_rocket_explode;
- return;
- }
-
- if (vlen(self.origin - self.tur_shotorg) < 100 )
- {
- self.think = walker_rocket_think;
- return;
- }
-
- newdir = steerlib_pull(self.tur_shotorg);
- WALKER_ROCKET_MOVE;
-
- self.angles = vectoangles(self.velocity);
-}
-
-void walker_rocket_loop2()
-{
- vector newdir;
-
- self.nextthink = time;
-
- if (self.max_health < time)
- {
- self.think = walker_rocket_explode;
- return;
- }
-
- if (vlen(self.origin - self.tur_shotorg) < 100 )
- {
- self.tur_shotorg = self.origin - '0 0 200';
- self.think = walker_rocket_loop3;
- return;
- }
-
- newdir = steerlib_pull(self.tur_shotorg);
- WALKER_ROCKET_MOVE;
-}
-
-void walker_rocket_loop()
-{
- self.nextthink = time;
- self.tur_shotorg = self.origin + '0 0 300';
- self.think = walker_rocket_loop2;
- self.shot_dmg = 1337;
-}
-
-void walker_fire_rocket(vector org)
-{
- entity rocket;
-
- fixedmakevectors(self.angles);
-
- te_explosion (org);
-
- rocket = spawn ();
- setorigin(rocket, org);
-
- sound (self, CH_WEAPON_A, W_Sound("hagar_fire"), VOL_BASE, ATTEN_NORM);
- setsize (rocket, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
-
- rocket.classname = "walker_rocket";
- rocket.owner = self;
- rocket.bot_dodge = true;
- rocket.bot_dodgerating = 50;
- rocket.takedamage = DAMAGE_YES;
- rocket.damageforcescale = 2;
- rocket.health = 25;
- rocket.tur_shotorg = randomvec() * 512;
- rocket.cnt = time + 1;
- rocket.enemy = self.enemy;
-
- if (random() < 0.01)
- rocket.think = walker_rocket_loop;
- else
- rocket.think = walker_rocket_think;
-
- rocket.event_damage = walker_rocket_damage;
-
- rocket.nextthink = time;
- rocket.movetype = MOVETYPE_FLY;
- rocket.velocity = normalize((v_forward + v_up * 0.5) + (randomvec() * 0.2)) * (autocvar_g_turrets_unit_walker_rocket_speed);
- rocket.angles = vectoangles(rocket.velocity);
- rocket.touch = walker_rocket_explode;
- rocket.flags = FL_PROJECTILE;
- rocket.solid = SOLID_BBOX;
- rocket.max_health = time + 9;
- rocket.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_HEAT;
-
- CSQCProjectile(rocket, false, PROJECTILE_ROCKET, false); // no culling, has fly sound
-}
-
-.vector enemy_last_loc;
-.float enemy_last_time;
-void walker_move_to(vector _target, float _dist)
-{
- switch (self.waterlevel)
- {
- case WATERLEVEL_NONE:
- if (_dist > 500)
- self.animflag = ANIM_RUN;
- else
- self.animflag = ANIM_WALK;
- case WATERLEVEL_WETFEET:
- case WATERLEVEL_SWIMMING:
- if (self.animflag != ANIM_SWIM)
- self.animflag = ANIM_WALK;
- else
- self.animflag = ANIM_SWIM;
- break;
- case WATERLEVEL_SUBMERGED:
- self.animflag = ANIM_SWIM;
- }
-
- self.moveto = _target;
- self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
-
- if(self.enemy)
- {
- self.enemy_last_loc = _target;
- self.enemy_last_time = time;
- }
-}
-
-//#define WALKER_FANCYPATHING
-
-void walker_move_path()
-{
-#ifdef WALKER_FANCYPATHING
- // Are we close enougth to a path node to switch to the next?
- if (vlen(self.origin - self.pathcurrent.origin) < 64)
- if (self.pathcurrent.path_next == world)
- {
- // Path endpoint reached
- pathlib_deletepath(self.pathcurrent.owner);
- self.pathcurrent = world;
-
- if (self.pathgoal)
- {
- if (self.pathgoal.use)
- self.pathgoal.use();
-
- if (self.pathgoal.enemy)
- {
- self.pathcurrent = WALKER_PATH(self.pathgoal.origin,self.pathgoal.enemy.origin);
- self.pathgoal = self.pathgoal.enemy;
- }
- }
- else
- self.pathgoal = world;
- }
- else
- self.pathcurrent = self.pathcurrent.path_next;
-
- self.moveto = self.pathcurrent.origin;
- self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95);
- walker_move_to(self.moveto, 0);
-
-#else
- if (vlen(self.origin - self.pathcurrent.origin) < 64)
- self.pathcurrent = self.pathcurrent.enemy;
-
- if(!self.pathcurrent)
- return;
-
- self.moveto = self.pathcurrent.origin;
- self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
- walker_move_to(self.moveto, 0);
-#endif
-}
-
-void spawnfunc_turret_walker() { if(!turret_initialize(TUR_WALKER)) remove(self); }
-
-float t_walker(float req)
-{
- switch(req)
- {
- case TR_ATTACK:
- {
- sound (self, CH_WEAPON_A, W_Sound("uzi_fire"), VOL_BASE, ATTEN_NORM);
- fireBullet (self.tur_shotorg, self.tur_shotdir_updated, self.shot_spread, 0, self.shot_dmg, self.shot_force, DEATH_TURRET_WALK_GUN, 0);
- Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
-
- return true;
- }
- case TR_THINK:
- {
- fixedmakevectors(self.angles);
-
- if (self.spawnflags & TSF_NO_PATHBREAK && self.pathcurrent)
- walker_move_path();
- else if (self.enemy == world)
- {
- if(self.pathcurrent)
- walker_move_path();
- else
- {
- if(self.enemy_last_time != 0)
- {
- if(vlen(self.origin - self.enemy_last_loc) < 128 || time - self.enemy_last_time > 10)
- self.enemy_last_time = 0;
- else
- walker_move_to(self.enemy_last_loc, 0);
- }
- else
- {
- if(self.animflag != ANIM_NO)
- {
- traceline(self.origin + '0 0 64', self.origin + '0 0 64' + v_forward * 128, MOVE_NORMAL, self);
-
- if(trace_fraction != 1.0)
- self.tur_head.idletime = -1337;
- else
- {
- traceline(trace_endpos, trace_endpos - '0 0 256', MOVE_NORMAL, self);
- if(trace_fraction == 1.0)
- self.tur_head.idletime = -1337;
- }
-
- if(self.tur_head.idletime == -1337)
- {
- self.moveto = self.origin + randomvec() * 256;
- self.tur_head.idletime = 0;
- }
-
- self.moveto = self.moveto * 0.9 + ((self.origin + v_forward * 500) + randomvec() * 400) * 0.1;
- self.moveto_z = self.origin_z + 64;
- walker_move_to(self.moveto, 0);
- }
-
- if(self.idletime < time)
- {
- if(random() < 0.5 || !(self.spawnflags & TSL_ROAM))
- {
- self.idletime = time + 1 + random() * 5;
- self.moveto = self.origin;
- self.animflag = ANIM_NO;
- }
- else
- {
- self.animflag = ANIM_WALK;
- self.idletime = time + 4 + random() * 2;
- self.moveto = self.origin + randomvec() * 256;
- self.tur_head.moveto = self.moveto;
- self.tur_head.idletime = 0;
- }
- }
- }
- }
- }
- else
- {
- if (self.tur_dist_enemy < (autocvar_g_turrets_unit_walker_melee_range) && self.animflag != ANIM_MELEE)
- {
- vector wish_angle;
-
- wish_angle = angleofs(self, self.enemy);
- if (self.animflag != ANIM_SWIM)
- if (fabs(wish_angle_y) < 15)
- {
- self.moveto = self.enemy.origin;
- self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
- self.animflag = ANIM_MELEE;
- }
- }
- else if (self.tur_head.attack_finished_single < time)
- {
- if(self.tur_head.shot_volly)
- {
- self.animflag = ANIM_NO;
-
- self.tur_head.shot_volly = self.tur_head.shot_volly -1;
- if(self.tur_head.shot_volly == 0)
- self.tur_head.attack_finished_single = time + (autocvar_g_turrets_unit_walker_rocket_refire);
- else
- self.tur_head.attack_finished_single = time + 0.2;
-
- if(self.tur_head.shot_volly > 1)
- walker_fire_rocket(gettaginfo(self, gettagindex(self, "tag_rocket01")));
- else
- walker_fire_rocket(gettaginfo(self, gettagindex(self, "tag_rocket02")));
- }
- else
- {
- if (self.tur_dist_enemy > (autocvar_g_turrets_unit_walker_rocket_range_min))
- if (self.tur_dist_enemy < (autocvar_g_turrets_unit_walker_rocket_range))
- self.tur_head.shot_volly = 4;
- }
- }
- else
- {
- if (self.animflag != ANIM_MELEE)
- walker_move_to(self.enemy.origin, self.tur_dist_enemy);
- }
- }
-
- {
- vector real_angle;
- float turny = 0, turnx = 0;
- float vz;
-
- real_angle = vectoangles(self.steerto) - self.angles;
- vz = self.velocity_z;
-
- switch (self.animflag)
- {
- case ANIM_NO:
- movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
- break;
-
- case ANIM_TURN:
- turny = (autocvar_g_turrets_unit_walker_turn);
- movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
- break;
-
- case ANIM_WALK:
- turny = (autocvar_g_turrets_unit_walker_turn_walk);
- movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_walk), 0.6);
- break;
-
- case ANIM_RUN:
- turny = (autocvar_g_turrets_unit_walker_turn_run);
- movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_run), 0.6);
- break;
-
- case ANIM_STRAFE_L:
- turny = (autocvar_g_turrets_unit_walker_turn_strafe);
- movelib_move_simple(v_right * -1, (autocvar_g_turrets_unit_walker_speed_walk), 0.8);
- break;
-
- case ANIM_STRAFE_R:
- turny = (autocvar_g_turrets_unit_walker_turn_strafe);
- movelib_move_simple(v_right, (autocvar_g_turrets_unit_walker_speed_walk), 0.8);
- break;
-
- case ANIM_JUMP:
- self.velocity += '0 0 1' * (autocvar_g_turrets_unit_walker_speed_jump);
- break;
-
- case ANIM_LAND:
- break;
-
- case ANIM_PAIN:
- if(self.frame != ANIM_PAIN)
- defer(0.25, walker_setnoanim);
-
- break;
-
- case ANIM_MELEE:
- if(self.frame != ANIM_MELEE)
- {
- defer(0.41, walker_setnoanim);
- defer(0.21, walker_melee_do_dmg);
- }
-
- movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
- break;
-
- case ANIM_SWIM:
- turny = (autocvar_g_turrets_unit_walker_turn_swim);
- turnx = (autocvar_g_turrets_unit_walker_turn_swim);
-
- self.angles_x += bound(-10, shortangle_f(real_angle_x, self.angles_x), 10);
- movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_swim), 0.3);
- vz = self.velocity_z + sin(time * 4) * 8;
- break;
-
- case ANIM_ROAM:
- turny = (autocvar_g_turrets_unit_walker_turn_walk);
- movelib_move_simple(v_forward ,(autocvar_g_turrets_unit_walker_speed_roam), 0.5);
- break;
- }
-
- if(turny)
- {
- turny = bound( turny * -1, shortangle_f(real_angle_y, self.angles_y), turny );
- self.angles_y += turny;
- }
-
- if(turnx)
- {
- turnx = bound( turnx * -1, shortangle_f(real_angle_x, self.angles_x), turnx );
- self.angles_x += turnx;
- }
-
- self.velocity_z = vz;
- }
-
-
- if(self.origin != self.oldorigin)
- self.SendFlags |= TNSF_MOVE;
-
- self.oldorigin = self.origin;
- turrets_setframe(self.animflag, false);
-
- return true;
- }
- case TR_DEATH:
- {
-#ifdef WALKER_FANCYPATHING
- if (self.pathcurrent)
- pathlib_deletepath(self.pathcurrent.owner);
-#endif
- self.pathcurrent = world;
-
- return true;
- }
- case TR_SETUP:
- {
- self.ticrate = 0.05;
-
- entity e;
-
- // Respawn is called & first spawn to, to set team. need to make sure we do not move the initial spawn.
- if(self.movetype == MOVETYPE_WALK)
- {
- if(self.pos1)
- setorigin(self, self.pos1);
- if(self.pos2)
- self.angles = self.pos2;
- }
-
- self.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
- self.aim_flags = TFL_AIM_LEAD;
- self.turret_flags |= TUR_FLAG_HITSCAN;
-
- self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
- self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
- self.iscreature = true;
- self.teleportable = TELEPORT_NORMAL;
- self.damagedbycontents = true;
- self.solid = SOLID_SLIDEBOX;
- self.takedamage = DAMAGE_AIM;
- if(self.movetype != MOVETYPE_WALK)
- {
- setorigin(self, self.origin);
- tracebox(self.origin + '0 0 128', self.mins, self.maxs, self.origin - '0 0 10000', MOVE_NORMAL, self);
- setorigin(self, trace_endpos + '0 0 4');
- self.pos1 = self.origin;
- self.pos2 = self.angles;
- }
- self.movetype = MOVETYPE_WALK;
- self.idle_aim = '0 0 0';
- self.turret_firecheckfunc = walker_firecheck;
-
- if (self.target != "")
- {
- e = find(world, targetname, self.target);
- if (!e)
- {
- LOG_TRACE("Initital waypoint for walker does NOT exsist, fix your map!\n");
- self.target = "";
- }
-
- if (e.classname != "turret_checkpoint")
- LOG_TRACE("Warning: not a turrret path\n");
- else
- {
-#ifdef WALKER_FANCYPATHING
- self.pathcurrent = WALKER_PATH(self.origin, e.origin);
- self.pathgoal = e;
-#else
- self.pathcurrent = e;
-#endif
- }
- }
-
- return true;
- }
- case TR_PRECACHE:
- {
- precache_model ("models/turrets/walker_body.md3");
- precache_model ("models/turrets/walker_head_minigun.md3");
- precache_model ("models/turrets/rocket.md3");
- precache_sound (W_Sound("rocket_impact"));
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-
-#include "../../../server/movelib.qh"
-
-void walker_draw()
-{
- float dt;
-
- dt = time - self.move_time;
- self.move_time = time;
- if(dt <= 0)
- return;
-
- fixedmakevectors(self.angles);
- movelib_groundalign4point(300, 100, 0.25, 45);
- setorigin(self, self.origin + self.velocity * dt);
- self.tur_head.angles += dt * self.tur_head.move_avelocity;
- self.angles_y = self.move_angles_y;
-
- if (self.health < 127)
- if(random() < 0.15)
- te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
-}
-
-float t_walker(float req)
-{
- switch(req)
- {
- case TR_SETUP:
- {
- self.gravity = 1;
- self.movetype = MOVETYPE_BOUNCE;
- self.move_movetype = MOVETYPE_BOUNCE;
- self.move_origin = self.origin;
- self.move_time = time;
- self.draw = walker_draw;
-
- return true;
- }
- case TR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
* NOTICE this func overwrites the global v_forward, v_right and v_up vectors.
*/
float turret_tag_fire_update()
-{
+{SELFPARAM();
if(!self.tur_head)
{
error("Call to turret_tag_fire_update with self.tur_head missing!\n");
void FireImoBeam (vector start, vector end, vector smin, vector smax,
float bforce, float f_dmg, float f_velfactor, int deathtype)
-{
+{SELFPARAM();
vector hitloc, force, endpoint, dir;
entity ent;
#ifdef TURRET_DEBUG
void SUB_Remove();
void marker_think()
-{
+{SELFPARAM();
if(self.cnt)
if(self.cnt < time)
{
err = spawn();
err.classname = "error_marker";
- setmodel(err,"models/marker.md3");
+ setmodel(err, MDL_MARKER);
setorigin(err,where);
err.movetype = MOVETYPE_NONE;
err.think = marker_think;
err = spawn();
err.classname = "info_marker";
- setmodel(err,"models/marker.md3");
+ setmodel(err, MDL_MARKER);
setorigin(err,where);
err.movetype = MOVETYPE_NONE;
err.think = marker_think;
err = spawn();
err.classname = "mark_misc";
- setmodel(err,"models/marker.md3");
+ setmodel(err, MDL_MARKER);
setorigin(err,where);
err.movetype = MOVETYPE_NONE;
err.think = marker_think;
return err;
}
+MODEL(TUR_C512, "models/turrets/c512.md3");
+
/*
* Paint a v_color colord circle on target onwho
* that fades away over f_time
entity e;
e = spawn();
- setmodel(e, "models/turrets/c512.md3"); // precision set above
+ setmodel(e, MDL_TUR_C512); // precision set above
e.scale = (f_size/512);
//setsize(e, '0 0 0', '0 0 0');
//setattachment(e,onwho,"");
entity e;
e = spawn();
- setmodel(e, "models/turrets/c512.md3"); // precision set above
+ setmodel(e, MDL_TUR_C512); // precision set above
e.scale = (f_size/512);
setsize(e, '0 0 0', '0 0 0');
{
entity e;
e = spawn();
- setmodel(e, "models/turrets/c512.md3"); // precision set above
+ setmodel(e, MDL_TUR_C512); // precision set above
e.scale = (f_size/512);
setsize(e, '0 0 0', '0 0 0');
setorigin(e,where+ '0 0 1');
#ifndef UTIL_POST_H
#define UTIL_POST_H
+[[alias("self")]] entity __self;
+
+// Can't wrap with do-while as block may contain continue or break
+#define WITH(type, name, value, block) { \
+ type __with_save = (name); \
+ name = (value); \
+ LAMBDA(block) \
+ name = __with_save; \
+} do { } while (0)
+
+// Transition from global 'self' to local 'this'
+
+// Step 1: auto oldself
+#if 1
+#define SELFPARAM() noref entity this = __self
+#define setself(s) (__self = s)
+#define self __self
+#endif
+
+// Step 2: check SELFPARAM() is present for functions that use self
+#if 0
+#define SELFPARAM() [[alias("__self")]] noref entity this = __self
+#define setself(s) (__self = s)
+#define self this
+#endif
+
+// Step 3: const self
+#if 0
+#define SELFPARAM() noref const entity this = __self
+entity setself(entity e) { return self = e; }
+entity getself() { return self; }
+#define self getself()
+#endif
+
+// Step 4: enable when possible
+// TODO: Remove SELFPARAM in favor of a parameter
+#if 0
+#define SELFPARAM() noref const entity this = __self
+#define self this
+#endif
+
#define spawn() new(entity)
#endif
#ifndef QCC_SUPPORT_NIL
#ifdef GMQCC
- #define QCC_SUPPORT_NIL
+ #define QCC_SUPPORT_NIL 1
#endif
#endif
#define FOREACH(list, cond, body) FOREACH_LIST(list, enemy, cond, body)
#ifdef GMQCC
- #define OVERLOAD(F, ...) F##_##__VA_COUNT__(__VA_ARGS__)
+ #define EVAL(...) __VA_ARGS__
+
+ #define OVERLOAD_(F, ...) F##_##__VA_COUNT__(__VA_ARGS__)
+ #define OVERLOAD(F, ...) F##_##__VA_COUNT__(__VA_ARGS__)
#else
- #define OVERLOAD_(F,_9,_8,_7,_6,_5,_4,_3,_2,_1,n,...) F##_##n
- #define OVERLOAD(F, ...) OVERLOAD_(F,__VA_ARGS__,9,8,7,6,5,4,3,2,1)(__VA_ARGS__)
+ #define EMPTY()
+ #define DEFER(id) id EMPTY()
+
+ #define EVAL(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__)))
+ #define EVAL1(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__)))
+ #define EVAL2(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__)))
+ #define EVAL3(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__)))
+ #define EVAL4(...) EVAL5(EVAL5(EVAL5(__VA_ARGS__)))
+ #define EVAL5(...) __VA_ARGS__
+
+ #define OVERLOAD___(F,_16,_15,_14,_13,_12,_11,_10,_9,_8,_7,_6,_5,_4,_3,_2,_1,n,...) F##_##n
+ #define OVERLOAD__(F, ...) OVERLOAD___(F,##__VA_ARGS__,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
+ #define OVERLOAD_(...) DEFER(OVERLOAD__(__VA_ARGS__))
+ #define OVERLOAD(F, ...) OVERLOAD_(F,##__VA_ARGS__)(__VA_ARGS__)
#endif
#define LAMBDA(...) { __VA_ARGS__ ; }
-#define MAP(f, ...) OVERLOAD(MAP, f, __VA_ARGS__)
+#define MAP(f, ...) EVAL(OVERLOAD(MAP, f, __VA_ARGS__))
#define MAP_2(f, it) f(it)
#define MAP_3(f, it, ...) f(it)MAP_2(f, __VA_ARGS__)
#define MAP_4(f, it, ...) f(it)MAP_3(f, __VA_ARGS__)
#define GET(name) name##get
#define GETTER(type, name) type GET(name)() { return name; }
-#define BIT(n) (1 << (n))
-#ifndef BRANCHLESS_BITSET
- #define BITSET(var, mask, flag) (flag ? (var) | (mask) : (var) &~ (mask))
-#else
- #define BITSET(var, mask, flag) ((var) ^ (-(flag) ^ (var)) & (mask))
-#endif
-
#endif
#ifndef MENUQC
#ifndef CSQC
void wordwrap_buffer_sprint(string s)
-{
+{SELFPARAM();
wordwrap_buffer = strcat(wordwrap_buffer, s);
if(s == "\n")
{
}
void wordwrap_sprint(string s, float l)
-{
+{SELFPARAM();
wordwrap_buffer = "";
wordwrap_cb(s, l, wordwrap_buffer_sprint);
if(wordwrap_buffer != "")
}
#endif
-string unescape(string in)
-{
- float i, len;
- string str, s;
-
- // but it doesn't seem to be necessary in my tests at least
- in = strzone(in);
-
- len = strlen(in);
- str = "";
- for(i = 0; i < len; ++i)
- {
- s = substring(in, i, 1);
- if(s == "\\")
- {
- s = substring(in, i+1, 1);
- if(s == "n")
- str = strcat(str, "\n");
- else if(s == "\\")
- str = strcat(str, "\\");
- else
- str = strcat(str, substring(in, i, 2));
- ++i;
- } else
- str = strcat(str, s);
- }
-
- strunzone(in);
- return str;
-}
-
void wordwrap_cb(string s, float l, void(string) callback)
{
string c;
strunzone(s);
}
-float dist_point_line(vector p, vector l0, vector ldir)
-{
- ldir = normalize(ldir);
-
- // remove the component in line direction
- p = p - (p * ldir) * ldir;
-
- // vlen of the remaining vector
- return vlen(p);
-}
-
void depthfirst(entity start, .entity up, .entity downleft, .entity right, void(entity, entity) funcPre, void(entity, entity) funcPost, entity pass)
{
entity e;
}
}
-float median(float a, float b, float c)
-{
- if(a < c)
- return bound(a, b, c);
- return bound(c, b, a);
-}
-
// converts a number to a string with the indicated number of decimals
// works for up to 10 decimals!
string ftos_decimals(float number, float decimals)
return sprintf("%.*f", decimals, number);
}
-vector colormapPaletteColor(float c, float isPants)
+vector colormapPaletteColor(float c, bool isPants)
{
- switch(c)
+ switch (c)
{
case 0: return '1.000000 1.000000 1.000000';
case 1: return '1.000000 0.333333 0.000000';
case 13: return '0.000000 0.333333 1.000000';
case 14: return '1.000000 0.666667 0.000000';
case 15:
- if(isPants)
+ if (isPants)
return
'1 0 0' * (0.502 + 0.498 * sin(time / 2.7182818285 + 0.0000000000))
+ '0 1 0' * (0.502 + 0.498 * sin(time / 2.7182818285 + 2.0943951024))
}
}
-// unzone the string, and return it as tempstring. Safe to be called on string_null
-string fstrunzone(string s)
-{
- string sc;
- if (!s)
- return s;
- sc = strcat(s, "");
- strunzone(s);
- return sc;
-}
-
-bool fexists(string f)
-{
- int fh = fopen(f, FILE_READ);
- if (fh < 0)
- return false;
- fclose(fh);
- return true;
-}
-
// Databases (hash tables)
const float DB_BUCKETS = 8192;
void db_save(float db, string pFilename)
return i;
}
-float almost_equals(float a, float b)
-{
- float eps;
- eps = (max(a, -a) + max(b, -b)) * 0.001;
- if(a - b < eps && b - a < eps)
- return true;
- return false;
-}
-
-float almost_in_bounds(float a, float b, float c)
-{
- float eps;
- eps = (max(a, -a) + max(c, -c)) * 0.001;
- if(a > c)
- eps = -eps;
- return b == median(a - eps, b, c + eps);
-}
-
-float power2of(float e)
-{
- return pow(2, e);
-}
-float log2of(float x)
-{
- // NOTE: generated code
- if(x > 2048)
- if(x > 131072)
- if(x > 1048576)
- if(x > 4194304)
- return 23;
- else
- if(x > 2097152)
- return 22;
- else
- return 21;
- else
- if(x > 524288)
- return 20;
- else
- if(x > 262144)
- return 19;
- else
- return 18;
- else
- if(x > 16384)
- if(x > 65536)
- return 17;
- else
- if(x > 32768)
- return 16;
- else
- return 15;
- else
- if(x > 8192)
- return 14;
- else
- if(x > 4096)
- return 13;
- else
- return 12;
- else
- if(x > 32)
- if(x > 256)
- if(x > 1024)
- return 11;
- else
- if(x > 512)
- return 10;
- else
- return 9;
- else
- if(x > 128)
- return 8;
- else
- if(x > 64)
- return 7;
- else
- return 6;
- else
- if(x > 4)
- if(x > 16)
- return 5;
- else
- if(x > 8)
- return 4;
- else
- return 3;
- else
- if(x > 2)
- return 2;
- else
- if(x > 1)
- return 1;
- else
- return 0;
-}
-
float rgb_mi_ma_to_hue(vector rgb, float mi, float ma)
{
if(mi == ma)
);
}
-// requires that m2>m1 in all coordinates, and that m4>m3
-float boxesoverlap(vector m1, vector m2, vector m3, vector m4) {return m2_x >= m3_x && m1_x <= m4_x && m2_y >= m3_y && m1_y <= m4_y && m2_z >= m3_z && m1_z <= m4_z;}
-
-// requires the same, but is a stronger condition
-float boxinsidebox(vector smins, vector smaxs, vector bmins, vector bmaxs) {return smins.x >= bmins.x && smaxs.x <= bmaxs.x && smins.y >= bmins.y && smaxs.y <= bmaxs.y && smins.z >= bmins.z && smaxs.z <= bmaxs.z;}
-
-#ifndef MENUQC
-#endif
-
float textLengthUpToWidth(string theText, float maxWidth, vector theSize, textLengthUpToWidth_widthFunction_t w)
{
// STOP.
return 1;
}
-void shuffle(float n, swapfunc_t swap, entity pass)
-{
- float i, j;
- for(i = 1; i < n; ++i)
- {
- // swap i-th item at a random position from 0 to i
- // proof for even distribution:
- // n = 1: obvious
- // n -> n+1:
- // item n+1 gets at any position with chance 1/(n+1)
- // all others will get their 1/n chance reduced by factor n/(n+1)
- // to be on place n+1, their chance will be 1/(n+1)
- // 1/n * n/(n+1) = 1/(n+1)
- // q.e.d.
- j = floor(random() * (i + 1));
- if(j != i)
- swap(j, i, pass);
- }
-}
-
-string substring_range(string s, float b, float e)
-{
- return substring(s, b, e - b);
-}
-
-string swapwords(string str, float i, float j)
-{
- float n;
- string s1, s2, s3, s4, s5;
- float si, ei, sj, ej, s0, en;
- n = tokenizebyseparator(str, " "); // must match g_maplist processing in ShuffleMaplist and "shuffle"
- si = argv_start_index(i);
- sj = argv_start_index(j);
- ei = argv_end_index(i);
- ej = argv_end_index(j);
- s0 = argv_start_index(0);
- en = argv_end_index(n-1);
- s1 = substring_range(str, s0, si);
- s2 = substring_range(str, si, ei);
- s3 = substring_range(str, ei, sj);
- s4 = substring_range(str, sj, ej);
- s5 = substring_range(str, ej, en);
- return strcat(s1, s4, s3, s2, s5);
-}
-
-string _shufflewords_str;
-void _shufflewords_swapfunc(float i, float j, entity pass)
-{
- _shufflewords_str = swapwords(_shufflewords_str, i, j);
-}
-string shufflewords(string str)
-{
- float n;
- _shufflewords_str = str;
- n = tokenizebyseparator(str, " ");
- shuffle(n, _shufflewords_swapfunc, world);
- str = _shufflewords_str;
- _shufflewords_str = string_null;
- return str;
-}
-
vector solve_quadratic(float a, float b, float c) // ax^2 + bx + c = 0
{
vector v;
return v;
}
-void heapsort(float n, swapfunc_t swap, comparefunc_t cmp, entity pass)
-{
- float start, end, root, child;
-
- // heapify
- start = floor((n - 2) / 2);
- while(start >= 0)
- {
- // siftdown(start, count-1);
- root = start;
- while(root * 2 + 1 <= n-1)
- {
- child = root * 2 + 1;
- if(child < n-1)
- if(cmp(child, child+1, pass) < 0)
- ++child;
- if(cmp(root, child, pass) < 0)
- {
- swap(root, child, pass);
- root = child;
- }
- else
- break;
- }
- // end of siftdown
- --start;
- }
-
- // extract
- end = n - 1;
- while(end > 0)
- {
- swap(0, end, pass);
- --end;
- // siftdown(0, end);
- root = 0;
- while(root * 2 + 1 <= end)
- {
- child = root * 2 + 1;
- if(child < end && cmp(child, child+1, pass) < 0)
- ++child;
- if(cmp(root, child, pass) < 0)
- {
- swap(root, child, pass);
- root = child;
- }
- else
- break;
- }
- // end of siftdown
- }
-}
-
-void RandomSelection_Init()
-{
- RandomSelection_totalweight = 0;
- RandomSelection_chosen_ent = world;
- RandomSelection_chosen_float = 0;
- RandomSelection_chosen_string = string_null;
- RandomSelection_best_priority = -1;
-}
-void RandomSelection_Add(entity e, float f, string s, float weight, float priority)
-{
- if(priority > RandomSelection_best_priority)
- {
- RandomSelection_best_priority = priority;
- RandomSelection_chosen_ent = e;
- RandomSelection_chosen_float = f;
- RandomSelection_chosen_string = s;
- RandomSelection_totalweight = weight;
- }
- else if(priority == RandomSelection_best_priority)
- {
- RandomSelection_totalweight += weight;
- if(random() * RandomSelection_totalweight <= weight)
- {
- RandomSelection_chosen_ent = e;
- RandomSelection_chosen_float = f;
- RandomSelection_chosen_string = s;
- }
- }
-}
-
#ifndef MENUQC
vector healtharmor_maxdamage(float h, float a, float armorblock, int deathtype)
{
return argv(n - 1);
}
-#ifndef MENUQC
-#ifdef CSQC
-int ReadInt24_t()
-{
- int v = ReadShort() * 256; // note: this is signed
- v += ReadByte(); // note: this is unsigned
- return v;
-}
-vector ReadInt48_t()
-{
- vector v;
- v.x = ReadInt24_t();
- v.y = ReadInt24_t();
- v.z = 0;
- return v;
-}
-vector ReadInt72_t()
-{
- vector v;
- v.x = ReadInt24_t();
- v.y = ReadInt24_t();
- v.z = ReadInt24_t();
- return v;
-}
-#else
-void WriteInt24_t(float dst, float val)
-{
- float v;
- WriteShort(dst, (v = floor(val / 256)));
- WriteByte(dst, val - v * 256); // 0..255
-}
-void WriteInt48_t(float dst, vector val)
-{
- WriteInt24_t(dst, val.x);
- WriteInt24_t(dst, val.y);
-}
-void WriteInt72_t(float dst, vector val)
-{
- WriteInt24_t(dst, val.x);
- WriteInt24_t(dst, val.y);
- WriteInt24_t(dst, val.z);
-}
-#endif
-#endif
-
-float float2range11(float f)
-{
- // continuous function mapping all reals into -1..1
- return f / (fabs(f) + 1);
-}
-
-float float2range01(float f)
-{
- // continuous function mapping all reals into 0..1
- return 0.5 + 0.5 * float2range11(f);
-}
-
// from the GNU Scientific Library
float gsl_ran_gaussian_lastvalue;
float gsl_ran_gaussian_lastvalue_set;
}
}
-string car(string s)
-{
- float o;
- o = strstrofs(s, " ", 0);
- if(o < 0)
- return s;
- return substring(s, 0, o);
-}
-string cdr(string s)
-{
- float o;
- o = strstrofs(s, " ", 0);
- if(o < 0)
- return string_null;
- return substring(s, o + 1, strlen(s) - (o + 1));
-}
float matchacl(string acl, string str)
{
string t, s;
}
return r;
}
-float startsWith(string haystack, string needle)
-{
- return substring(haystack, 0, strlen(needle)) == needle;
-}
-float startsWithNocase(string haystack, string needle)
-{
- return strcasecmp(substring(haystack, 0, strlen(needle)), needle) == 0;
-}
string get_model_datafilename(string m, float sk, string fil)
{
return 1;
}
-vector vec2(vector v)
-{
- v.z = 0;
- return v;
-}
-
-#ifndef MENUQC
-vector NearestPointOnBox(entity box, vector org)
-{
- vector m1, m2, nearest;
-
- m1 = box.mins + box.origin;
- m2 = box.maxs + box.origin;
-
- nearest.x = bound(m1_x, org.x, m2_x);
- nearest.y = bound(m1_y, org.y, m2_y);
- nearest.z = bound(m1_z, org.z, m2_z);
-
- return nearest;
-}
-#endif
-
float vercmp_recursive(string v1, string v2)
{
float dot1, dot2;
return vercmp_recursive(v1, v2);
}
-float u8_strsize(string s)
-{
- float l, i, c;
- l = 0;
- for(i = 0; ; ++i)
- {
- c = str2chr(s, i);
- if(c <= 0)
- break;
- ++l;
- if(c >= 0x80)
- ++l;
- if(c >= 0x800)
- ++l;
- if(c >= 0x10000)
- ++l;
- }
- return l;
-}
-
// x-encoding (encoding as zero length invisible string)
const string XENCODE_2 = "xX";
const string XENCODE_22 = "0123456789abcdefABCDEF";
return ((a * 22 + b) * 22 + c) * 22 + d;
}
-int lowestbit(int f)
-{
- f &= ~(f * 2);
- f &= ~(f * 4);
- f &= ~(f * 16);
- f &= ~(f * 256);
- f &= ~(f * 65536);
- return f;
-}
-
/*
string strlimitedlen(string input, string truncation, float strip_colors, float limit)
{
return strcat(substring(input, 0, (strlen(input) - strlen(truncation))), truncation);
}*/
-// escape the string to make it safe for consoles
-string MakeConsoleSafe(string input)
-{
- input = strreplace("\n", "", input);
- input = strreplace("\\", "\\\\", input);
- input = strreplace("$", "$$", input);
- input = strreplace("\"", "\\\"", input);
- return input;
-}
-
#ifdef CSQC
entity ReadCSQCEntity()
{
to_execute_next_frame = strzone(s);
}
-float cubic_speedfunc(float startspeedfactor, float endspeedfactor, float x)
-{
- return
- ((( startspeedfactor + endspeedfactor - 2
- ) * x - 2 * startspeedfactor - endspeedfactor + 3
- ) * x + startspeedfactor
- ) * x;
-}
-
-float cubic_speedfunc_is_sane(float startspeedfactor, float endspeedfactor)
-{
- if(startspeedfactor < 0 || endspeedfactor < 0)
- return false;
-
- /*
- // if this is the case, the possible zeros of the first derivative are outside
- // 0..1
- We can calculate this condition as condition
- if(se <= 3)
- return true;
- */
-
- // better, see below:
- if(startspeedfactor <= 3 && endspeedfactor <= 3)
- return true;
-
- // if this is the case, the first derivative has no zeros at all
- float se = startspeedfactor + endspeedfactor;
- float s_e = startspeedfactor - endspeedfactor;
- if(3 * (se - 4) * (se - 4) + s_e * s_e <= 12) // an ellipse
- return true;
-
- // Now let s <= 3, s <= 3, s+e >= 3 (triangle) then we get se <= 6 (top right corner).
- // we also get s_e <= 6 - se
- // 3 * (se - 4)^2 + (6 - se)^2
- // is quadratic, has value 12 at 3 and 6, and value < 12 in between.
- // Therefore, above "better" check works!
-
- return false;
-
- // known good cases:
- // (0, [0..3])
- // (0.5, [0..3.8])
- // (1, [0..4])
- // (1.5, [0..3.9])
- // (2, [0..3.7])
- // (2.5, [0..3.4])
- // (3, [0..3])
- // (3.5, [0.2..2.3])
- // (4, 1)
-
- /*
- On another note:
- inflection point is always at (2s + e - 3) / (3s + 3e - 6).
-
- s + e - 2 == 0: no inflection
-
- s + e > 2:
- 0 < inflection < 1 if:
- 0 < 2s + e - 3 < 3s + 3e - 6
- 2s + e > 3 and 2e + s > 3
-
- s + e < 2:
- 0 < inflection < 1 if:
- 0 > 2s + e - 3 > 3s + 3e - 6
- 2s + e < 3 and 2e + s < 3
-
- Therefore: there is an inflection point iff:
- e outside (3 - s)/2 .. 3 - s*2
-
- in other words, if (s,e) in triangle (1,1)(0,3)(0,1.5) or in triangle (1,1)(3,0)(1.5,0)
- */
-}
-
.float FindConnectedComponent_processing;
void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t nxt, isConnectedFunction_t iscon, entity pass)
{
queue_start.FindConnectedComponent_processing = 0;
}
-#ifdef SVQC
-vector combine_to_vector(float x, float y, float z)
-{
- vector result; result_x = x; result_y = y; result_z = z;
- return result;
-}
-
-vector get_corner_position(entity box, float corner)
-{
- switch(corner)
- {
- case 1: return combine_to_vector(box.absmin.x, box.absmin.y, box.absmin.z);
- case 2: return combine_to_vector(box.absmax.x, box.absmin.y, box.absmin.z);
- case 3: return combine_to_vector(box.absmin.x, box.absmax.y, box.absmin.z);
- case 4: return combine_to_vector(box.absmin.x, box.absmin.y, box.absmax.z);
- case 5: return combine_to_vector(box.absmax.x, box.absmax.y, box.absmin.z);
- case 6: return combine_to_vector(box.absmin.x, box.absmax.y, box.absmax.z);
- case 7: return combine_to_vector(box.absmax.x, box.absmin.y, box.absmax.z);
- case 8: return combine_to_vector(box.absmax.x, box.absmax.y, box.absmax.z);
- default: return '0 0 0';
- }
-}
-#endif
-
-// color code replace, place inside of sprintf and parse the string
-string CCR(string input)
-{
- // See the autocvar declarations in util.qh for default values
-
- // foreground/normal colors
- input = strreplace("^F1", strcat("^", autocvar_hud_colorset_foreground_1), input);
- input = strreplace("^F2", strcat("^", autocvar_hud_colorset_foreground_2), input);
- input = strreplace("^F3", strcat("^", autocvar_hud_colorset_foreground_3), input);
- input = strreplace("^F4", strcat("^", autocvar_hud_colorset_foreground_4), input);
-
- // "kill" colors
- input = strreplace("^K1", strcat("^", autocvar_hud_colorset_kill_1), input);
- input = strreplace("^K2", strcat("^", autocvar_hud_colorset_kill_2), input);
- input = strreplace("^K3", strcat("^", autocvar_hud_colorset_kill_3), input);
-
- // background colors
- input = strreplace("^BG", strcat("^", autocvar_hud_colorset_background), input);
- input = strreplace("^N", "^7", input); // "none"-- reset to white...
- return input;
-}
-
-vector vec3(float x, float y, float z)
-{
- vector v;
- v.x = x;
- v.y = y;
- v.z = z;
- return v;
-}
-
#ifndef MENUQC
vector animfixfps(entity e, vector a, vector b)
{
return CONTENT_EMPTY;
}
#endif
-
-vector bezier_quadratic_getpoint(vector a, vector b, vector c, float t)
-{
- return
- (c - 2 * b + a) * (t * t) +
- (b - a) * (2 * t) +
- a;
-}
-
-vector bezier_quadratic_getderivative(vector a, vector b, vector c, float t)
-{
- return
- (c - 2 * b + a) * (2 * t) +
- (b - a) * 2;
-}
float isGametypeInFilter(float gt, float tp, float ts, string pattern);
-typedef void(float i1, float i2, entity pass) swapfunc_t; // is only ever called for i1 < i2
-typedef float(float i1, float i2, entity pass) comparefunc_t; // <0 for <, ==0 for ==, >0 for > (like strcmp)
-void shuffle(float n, swapfunc_t swap, entity pass);
-void heapsort(float n, swapfunc_t swap, comparefunc_t cmp, entity pass);
-
string swapwords(string str, float i, float j);
string shufflewords(string str);
string records_reply[10];
#endif
-float RandomSelection_totalweight;
-float RandomSelection_best_priority;
-entity RandomSelection_chosen_ent;
-float RandomSelection_chosen_float;
-string RandomSelection_chosen_string;
-void RandomSelection_Init();
-void RandomSelection_Add(entity e, float f, string s, float weight, float priority);
-
#ifndef MENUQC
vector healtharmor_maxdamage(float h, float a, float armorblock, int deathtype); // returns vector: maxdamage, armorideal, 1 if fully armored
vector healtharmor_applydamage(float a, float armorblock, int deathtype, float damage); // returns vector: take, save, 0
string xencode(float f);
float xdecode(string s);
-// Play all sounds via sound7, for access to the extra channels.
-// Otherwise, channels 8 to 15 would be blocked for a weird QW feature.
-#define sound(e,c,s,v,a) sound7(e,c,s,v,a,0,0)
-
-int lowestbit(float f);
-
#ifdef CSQC
entity ReadCSQCEntity();
#endif
typedef float(entity a, entity b, entity pass) isConnectedFunction_t;
void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t nxt, isConnectedFunction_t iscon, entity pass);
-#ifdef SVQC
-vector combine_to_vector(float x, float y, float z);
-vector get_corner_position(entity box, float corner);
-#endif
-
// expand multiple arguments into one argument by stripping parenthesis
#define XPD(...) __VA_ARGS__
#define fprintf(file, ...) fputs(file, sprintf(__VA_ARGS__))
#define bprintf(...) bprint(sprintf(__VA_ARGS__))
-// color code replace, place inside of sprintf and parse the string... defaults described as constants
-// foreground/normal colors
-string autocvar_hud_colorset_foreground_1 = "2"; // F1 - Green // primary priority (important names, etc)
-string autocvar_hud_colorset_foreground_2 = "3"; // F2 - Yellow // secondary priority (items, locations, numbers, etc)
-string autocvar_hud_colorset_foreground_3 = "4"; // F3 - Blue // tertiary priority or relatively inconsequential text
-string autocvar_hud_colorset_foreground_4 = "1"; // F4 - Red // notice/attention grabbing texting
-// "kill" colors
-string autocvar_hud_colorset_kill_1 = "1"; // K1 - Red // "bad" or "dangerous" text (death messages against you, kill notifications, etc)
-string autocvar_hud_colorset_kill_2 = "3"; // K2 - Yellow // similar to above, but less important... OR, a highlight out of above message type
-string autocvar_hud_colorset_kill_3 = "4"; // K3 - Blue // "good" or "beneficial" text (you fragging someone, etc)
-// background color
-string autocvar_hud_colorset_background = "7"; // BG - White // neutral/unimportant text
-
string CCR(string input);
#ifndef MENUQC
-#include "unit/spiderbot.qc"
-#include "unit/raptor.qc"
-#include "unit/racer.qc"
+#include "vehicle/spiderbot.qc"
+#include "vehicle/raptor.qc"
+#include "vehicle/racer.qc"
#ifndef VEHICLES_NO_UNSTABLE
- #include "unit/bumblebee.qc"
+ #include "vehicle/bumblebee.qc"
#endif
#include "all.qh"
-#if defined(SVQC)
- #include "sv_vehicles.qc"
-#elif defined(CSQC)
- #include "cl_vehicles.qc"
-#endif
-
-#define IMPLEMENTATION
-#include "all.inc"
-#undef IMPLEMENTATION
-
#ifndef MENUQC
STATIC_INIT(vehicles_common_initialize)
{
-#ifdef CSQC
- precache_model("models/vehicles/bomblet.md3");
- precache_model("models/vehicles/clusterbomb.md3");
- precache_model("models/vehicles/clusterbomb_fragment.md3");
- precache_model("models/vehicles/rocket01.md3");
- precache_model("models/vehicles/rocket02.md3");
-
- precache_sound ("vehicles/alarm.wav");
- precache_sound ("vehicles/alarm_shield.wav");
-#endif // CSQC
#ifdef SVQC
- precache_sound("onslaught/ons_hit2.wav");
- precache_sound("onslaught/electricity_explode.wav");
-
addstat(STAT_HUD, AS_INT, hud);
addstat(STAT_VEHICLESTAT_HEALTH, AS_INT, vehicle_health);
addstat(STAT_VEHICLESTAT_SHIELD, AS_INT, vehicle_shield);
}
#endif
-entity get_vehicleinfo(int id)
-{
- if (id < VEH_FIRST || id > VEH_LAST) return VEH_NULL;
- entity m = vehicle_info[id];
- return m ? m : VEH_NULL;
-}
+#if defined(SVQC)
+ #include "sv_vehicles.qc"
+#elif defined(CSQC)
+ #include "cl_vehicles.qc"
+#endif
+
+#define IMPLEMENTATION
+#include "all.inc"
+#undef IMPLEMENTATION
#endif
#ifndef VEHICLES_ALL_H
#define VEHICLES_ALL_H
+#include "vehicle.qh"
+
+REGISTRY(Vehicles, BIT(3))
+REGISTER_REGISTRY(RegisterVehicles)
+const int VEH_FIRST = 1;
+#define VEH_LAST (Vehicles_COUNT - 1)
+
+/** If you register a new vehicle, make sure to add it to all.inc */
+#define REGISTER_VEHICLE(id, inst) REGISTER(RegisterVehicles, VEH, Vehicles, id, vehicleid, inst)
+
#if defined(SVQC)
#include "sv_vehicles.qh"
#elif defined(CSQC)
#include "cl_vehicles.qh"
#endif
+REGISTER_VEHICLE(Null, NEW(Vehicle));
-// vehicle requests
-const int VR_SETUP = 1; // (BOTH) setup vehicle data
-const int VR_THINK = 2; // (SERVER) logic to run every frame
-const int VR_DEATH = 3; // (SERVER) called when vehicle dies
-const int VR_PRECACHE = 4; // (BOTH) precaches models/sounds used by this vehicle
-const int VR_ENTER = 5; // (SERVER) called when a player enters this vehicle
-const int VR_SPAWN = 6; // (SERVER) called when the vehicle re-spawns
-const int VR_IMPACT = 7; // (SERVER) called when a vehicle hits something
-const int VR_HUD = 8; // (CLIENT) logic to run every frame
-
-// vehicle spawn flags (need them here for common registrations)
-const int VHF_ISVEHICLE = 2; /// Indicates vehicle
-const int VHF_HASSHIELD = 4; /// Vehicle has shileding
-const int VHF_SHIELDREGEN = 8; /// Vehicles shield regenerates
-const int VHF_HEALTHREGEN = 16; /// Vehicles health regenerates
-const int VHF_ENERGYREGEN = 32; /// Vehicles energy regenerates
-const int VHF_DEATHEJECT = 64; /// Vehicle ejects pilot upon fatal damage
-const int VHF_MOVE_GROUND = 128; /// Vehicle moves on gound
-const int VHF_MOVE_HOVER = 256; /// Vehicle hover close to gound
-const int VHF_MOVE_FLY = 512; /// Vehicle is airborn
-const int VHF_DMGSHAKE = 1024; /// Add random velocity each frame if health < 50%
-const int VHF_DMGROLL = 2048; /// Add random angles each frame if health < 50%
-const int VHF_DMGHEADROLL = 4096; /// Add random head angles each frame if health < 50%
-const int VHF_MULTISLOT = 8192; /// Vehicle has multiple player slots
-const int VHF_PLAYERSLOT = 16384; /// This ent is a player slot on a multi-person vehicle
-
-// functions:
-entity get_vehicleinfo(float id);
-
-// fields:
-.entity tur_head;
-
-
-// other useful macros
-#define VEH_ACTION(vehicletype,mrequest) (get_vehicleinfo(vehicletype)).vehicle_func(mrequest)
-#define VEH_NAME(vehicletype) (get_vehicleinfo(vehicletype)).vehicle_name
-
-// =====================
-// Vehicle Registration
-// =====================
-
-void RegisterVehicles();
-const int VEH_MAXCOUNT = 24;
-entity vehicle_info[VEH_MAXCOUNT], vehicle_info_first, vehicle_info_last;
-int VEH_COUNT;
-const int VEH_FIRST = 1;
-#define VEH_LAST (VEH_FIRST + VEH_COUNT - 1)
-/** If you register a new vehicle, make sure to add it to all.inc */
-#define REGISTER_VEHICLE(id, class) REGISTER(RegisterVehicles, VEH, vehicle_info, VEH_COUNT, id, vehicleid, NEW(class))
-#include "vehicle.qh"
-#define REGISTER_VEHICLE_SIMPLE(id, vehicleflags, min_s, max_s, modelname, headmodelname, hudmodelname, headtag, hudtag, viewtag, shortname, vname) \
- REGISTER_VEHICLE(id, Vehicle) { \
- this.netname = shortname; \
- this.vehicle_name = vname; \
- this.mdl = modelname; \
- this.spawnflags = vehicleflags; \
- this.mins = min_s; \
- this.maxs = max_s; \
- this.model = modelname; \
- this.head_model = headmodelname; \
- this.hud_model = hudmodelname; \
- this.tag_head = headtag; \
- this.tag_hud = hudtag; \
- this.tag_view = viewtag; \
- } \
- REGISTER_INIT(VEH, id)
-REGISTER_REGISTRY(RegisterVehicles)
-
-REGISTER_VEHICLE(NULL, Vehicle);
+Vehicle get_vehicleinfo(int id)
+{
+ if (id >= VEH_FIRST && id <= VEH_LAST) {
+ Vehicle v = Vehicles[id];
+ if (v) return v;
+ }
+ return VEH_Null;
+}
#include "all.inc"
if(!autocvar_cl_vehicles_alarm)
return;
- sound(e, ch, s0und, VOL_BASEVOICE, ATTEN_NONE);
+ _sound(e, ch, s0und, VOL_BASEVOICE, ATTEN_NONE);
}
-void AuxiliaryXhair_Draw2D()
+void AuxiliaryXhair_Draw2D(entity this)
{
if (scoreboard_showscores)
return;
}
void Net_VehicleSetup()
-{
+{SELFPARAM();
int hud_id = ReadByte();
// hud_id == 0 means we exited a vehicle, so stop alarm sound/s
if(hud_id == 0)
{
- sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
- sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
+ sound(self, CH_TRIGGER_SINGLE, SND_Null, VOL_BASEVOICE, ATTEN_NONE);
+ sound(self, CH_PAIN_SINGLE, SND_Null, VOL_BASEVOICE, ATTEN_NONE);
return;
}
{
AuxiliaryXhair[0].axh_image = vCROSS_BURST; // Plasma cannons
AuxiliaryXhair[1].axh_image = vCROSS_BURST; // Raygun
+ } else {
+ Vehicle info = get_vehicleinfo(hud_id);
+ info.vr_setup(info);
}
- else { VEH_ACTION(hud_id, VR_SETUP); }
}
void Vehicles_drawHUD(
string iconAmmo2,
vector colorAmmo2,
string crosshair)
-{
+{SELFPARAM();
if(autocvar_r_letterbox)
return;
if(alarm1time < time)
{
alarm1time = time + 2;
- vehicle_alarm(self, CH_PAIN_SINGLE, "vehicles/alarm.wav");
+ vehicle_alarm(self, CH_PAIN_SINGLE, SND(VEH_ALARM));
}
drawpic_skin(tmpPos, "vehicle_icon_health", tmpSize, '1 1 1', hudAlpha * blinkValue, DRAWFLAG_NORMAL);
}
{
if(alarm1time)
{
- vehicle_alarm(self, CH_PAIN_SINGLE, "misc/null.wav");
+ vehicle_alarm(self, CH_PAIN_SINGLE, SND(Null));
alarm1time = 0;
}
drawpic_skin(tmpPos, "vehicle_icon_health", tmpSize, '1 1 1', hudAlpha, DRAWFLAG_NORMAL);
if(alarm2time < time)
{
alarm2time = time + 1;
- vehicle_alarm(self, CH_TRIGGER_SINGLE, "vehicles/alarm_shield.wav");
+ vehicle_alarm(self, CH_TRIGGER_SINGLE, SND(VEH_ALARM_SHIELD));
}
drawpic_skin(tmpPos, "vehicle_icon_shield", tmpSize, '1 1 1', hudAlpha * blinkValue, DRAWFLAG_NORMAL);
}
{
if(alarm2time)
{
- vehicle_alarm(self, CH_TRIGGER_SINGLE, "misc/null.wav");
+ vehicle_alarm(self, CH_TRIGGER_SINGLE, SND(Null));
alarm2time = 0;
}
drawpic_skin(tmpPos, "vehicle_icon_shield", tmpSize, '1 1 1', hudAlpha, DRAWFLAG_NORMAL);
void Net_VehicleSetup();
-void RaptorCBShellfragDraw();
+void RaptorCBShellfragDraw(entity this);
void RaptorCBShellfragToss(vector _org, vector _vel, vector _ang);
#define weapon2mode getstati(STAT_VEHICLESTAT_W2MODE)
#include "sv_vehicles.qh"
-#include "../effects.qh"
+#include "../effects/effects.qh"
#if 0
bool vehicle_send(entity to, int sf)
}
#endif
-bool SendAuxiliaryXhair(entity to, int sf)
+bool SendAuxiliaryXhair(entity this, entity to, int sf)
{
WriteByte(MSG_ENTITY, ENT_CLIENT_AUXILIARYXHAIR);
}
vector targetdrone_getnewspot()
-{
+{SELFPARAM();
vector spot;
int i;
for(i = 0; i < 100; ++i)
}
void vehicles_locktarget(float incr, float decr, float _lock_time)
-{
+{SELFPARAM();
if(self.lock_target && self.lock_target.deadflag != DEAD_NO)
{
self.lock_target = world;
}
vector vehicles_force_fromtag_hover(string tag_name, float spring_length, float max_power)
-{
+{SELFPARAM();
force_fromtag_origin = gettaginfo(self, gettagindex(self, tag_name));
v_forward = normalize(v_forward) * -1;
traceline(force_fromtag_origin, force_fromtag_origin - (v_forward * spring_length), MOVE_NORMAL, self);
}
vector vehicles_force_fromtag_maglev(string tag_name, float spring_length, float max_power)
-{
+{SELFPARAM();
force_fromtag_origin = gettaginfo(self, gettagindex(self, tag_name));
v_forward = normalize(v_forward) * -1;
// projectile handling
void vehicles_projectile_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
// Ignore damage from oterh projectiles from my owner (dont mess up volly's)
if(inflictor.owner == self.owner)
return;
}
void vehicles_projectile_explode()
-{
+{SELFPARAM();
if(self.owner && other != world)
{
if(other == self.owner.vehicle)
float _dmg, float _radi, float _force, float _size,
int _deahtype, float _projtype, float _health,
bool _cull, bool _clianim, entity _owner)
-{
+{SELFPARAM();
entity proj;
proj = spawn();
proj.flags = FL_PROJECTILE | FL_NOTARGET;
if(_mzlsound)
- sound (self, CH_WEAPON_A, _mzlsound, VOL_BASE, ATTEN_NORM);
+ _sound (self, CH_WEAPON_A, _mzlsound, VOL_BASE, ATTEN_NORM);
if(_mzlfx)
Send_Effect_(_mzlfx, proj.origin, proj.velocity, 1);
}
void vehicles_gib_explode()
-{
- sound (self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+{SELFPARAM();
+ sound (self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
Send_Effect(EFFECT_EXPLOSION_SMALL, randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
Send_Effect(EFFECT_EXPLOSION_SMALL, self.wp00.origin + '0 0 64', '0 0 0', 1);
remove(self);
}
void vehicles_gib_think()
-{
+{SELFPARAM();
self.alpha -= 0.1;
if(self.cnt >= time)
remove(self);
}
entity vehicle_tossgib(entity _template, vector _vel, string _tag, bool _burn, bool _explode, float _maxtime, vector _rot)
-{
+{SELFPARAM();
entity _gib = spawn();
- setmodel(_gib, _template.model);
+ _setmodel(_gib, _template.model);
setorigin(_gib, gettaginfo(self, gettagindex(self, _tag)));
_gib.velocity = _vel;
_gib.movetype = MOVETYPE_TOSS;
_slot.vehicle_hudmodel.viewmodelforclient = _slot;
_slot.vehicle_viewport.effects = (EF_ADDITIVE | EF_DOUBLESIDED | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NOGUNBOB | EF_NOSHADOW | EF_LOWPRECISION | EF_SELECTABLE | EF_TELEPORT_BIT);
- setmodel(_slot.vehicle_hudmodel, _hud_model);
- setmodel(_slot.vehicle_viewport, "null");
+ _setmodel(_slot.vehicle_hudmodel, _hud_model);
+ setmodel(_slot.vehicle_viewport, MDL_Null);
setattachment(_slot.vehicle_hudmodel, _slot, "");
setattachment(_slot.vehicle_viewport, _slot.vehicle_hudmodel, "");
}
void vehicles_reset_colors()
-{
+{SELFPARAM();
entity e;
float _effects = 0, _colormap;
vector _glowmod, _colormod;
void vehicles_spawn();
void vehicles_return()
-{
+{SELFPARAM();
Send_Effect(EFFECT_TELEPORT, self.wp00.origin + '0 0 64', '0 0 0', 1);
self.wp00.think = vehicles_spawn;
}
void vehicles_showwp_goaway()
-{
+{SELFPARAM();
if(self.waypointsprite_attached)
WaypointSprite_Kill(self.waypointsprite_attached);
}
void vehicles_showwp()
-{
+{SELFPARAM();
entity oldself = world;
vector rgb;
self.nextthink = time +1;
oldself = self;
- self = spawn();
- setmodel(self, "null");
+ setself(spawn());
+ setmodel(self, MDL_Null);
self.team = oldself.wp00.team;
self.wp00 = oldself.wp00;
setorigin(self, oldself.wp00.pos1);
rgb = Team_ColorRGB(self.team);
else
rgb = '1 1 1';
- entity wp = WaypointSprite_Spawn(WP_Vehicle, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_POWERUP);
+ entity wp = WaypointSprite_Spawn(WP_Vehicle, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_Vehicle);
wp.colormod = rgb;
if(self.waypointsprite_attached)
{
WaypointSprite_UpdateRule(self.waypointsprite_attached, self.wp00.team, SPRITERULE_DEFAULT);
- if(oldself == world)
+ if(this == NULL)
WaypointSprite_UpdateBuildFinished(self.waypointsprite_attached, self.nextthink);
WaypointSprite_Ping(self.waypointsprite_attached);
}
- if(oldself != world)
- self = oldself;
+ if(this)
+ setself(this);
}
void vehicles_setreturn(entity veh)
ret.nextthink = min(time + veh.respawntime, time + veh.respawntime - 1);
}
- setmodel(ret, "null");
+ setmodel(ret, MDL_Null);
setorigin(ret, veh.pos1 + '0 0 96');
}
void vehicle_use()
-{
+{SELFPARAM();
LOG_TRACE("vehicle ",self.netname, " used by ", activator.classname, "\n");
self.tur_head.team = activator.team;
}
void vehicles_regen(float timer, .float regen_field, float field_max, float rpause, float regen, float delta_time, float _healthscale)
-{
- if(self.regen_field < field_max)
+{SELFPARAM();
+ if(self.(regen_field) < field_max)
if(timer + rpause < time)
{
if(_healthscale)
regen = regen * (self.vehicle_health / self.max_health);
- self.regen_field = min(self.regen_field + regen * delta_time, field_max);
+ self.(regen_field) = min(self.(regen_field) + regen * delta_time, field_max);
if(self.owner)
- self.owner.regen_field = (self.regen_field / field_max) * 100;
+ self.owner.(regen_field) = (self.(regen_field) / field_max) * 100;
}
}
void shieldhit_think()
-{
+{SELFPARAM();
self.alpha -= 0.1;
if (self.alpha <= 0)
{
- //setmodel(self, "");
+ // setmodel(self, MDL_Null);
self.alpha = -1;
self.effects |= EF_NODRAW;
}
}
void vehicles_painframe()
-{
+{SELFPARAM();
if(self.owner.vehicle_health <= 50)
if(self.pain_frame < time)
{
}
void vehicles_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
self.dmg_time = time;
// WEAPONTODO
self.vehicle_shieldent = spawn();
self.vehicle_shieldent.effects = EF_LOWPRECISION;
- setmodel(self.vehicle_shieldent, "models/vhshield.md3");
+ setmodel(self.vehicle_shieldent, MDL_VEH_SHIELD);
setattachment(self.vehicle_shieldent, self, "");
setorigin(self.vehicle_shieldent, real_origin(self) - self.origin);
self.vehicle_shieldent.scale = 256 / vlen(self.maxs - self.mins);
antilag_clear(self);
- VEH_ACTION(self.vehicleid, VR_DEATH);
+ Vehicle info = get_vehicleinfo(self.vehicleid);
+ info.vr_death(info);
vehicles_setreturn(self);
}
}
}
void vehicles_impact(float _minspeed, float _speedfac, float _maxpain)
-{
+{SELFPARAM();
if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
return;
// vehicle enter/exit handling
vector vehicles_findgoodexit(vector prefer_spot)
-{
+{SELFPARAM();
//vector exitspot;
float mysize;
}
void vehicles_exit(bool eject)
-{
+{SELFPARAM();
entity _vehicle;
entity _player;
- entity _oldself = self;
if(vehicles_exit_running)
{
if (_vehicle.vehicle_flags & VHF_PLAYERSLOT)
{
_vehicle.vehicle_exit(eject);
- self = _oldself;
+ setself(this);
vehicles_exit_running = false;
return;
}
_player = _vehicle.owner;
- self = _vehicle;
+ setself(_vehicle);
if (_player)
{
_vehicle.team = _vehicle.tur_head.team;
- sound (_vehicle, CH_TRIGGER_SINGLE, "misc/null.wav", 1, ATTEN_NORM);
+ sound (_vehicle, CH_TRIGGER_SINGLE, SND_Null, 1, ATTEN_NORM);
_vehicle.vehicle_hudmodel.viewmodelforclient = _vehicle;
_vehicle.phase = time + 1;
vehicles_reset_colors();
_vehicle.owner = world;
- CSQCMODEL_AUTOINIT();
-
- self = _oldself;
+ CSQCMODEL_AUTOINIT(self);
+ setself(this);
vehicles_exit_running = false;
}
void vehicles_touch()
-{
+{SELFPARAM();
if(MUTATOR_CALLHOOK(VehicleTouch, self, other))
return;
return; // Dont do selfdamage when hitting "soft targets".
}
- if(self.play_time < time)
- VEH_ACTION(self.vehicleid, VR_IMPACT);
+ if(self.play_time < time) {
+ Vehicle info = get_vehicleinfo(self.vehicleid);
+ info.vr_impact(info);
+ }
return;
}
}
bool vehicle_impulse(int imp)
-{
+{SELFPARAM();
switch(imp)
{
case 17:
}
void vehicles_enter(entity pl, entity veh)
-{
+{SELFPARAM();
// Remove this when bots know how to use vehicles
if((IS_BOT_CLIENT(pl) && !autocvar_g_vehicles_allow_bots))
return;
if(veh.vehicle_flags & VHF_MULTISLOT)
if(veh.owner)
{
- entity oldself = self;
- self = veh;
+ setself(veh);
other = pl; // TODO: fix
if(!veh.gunner1)
if(veh.gun1.vehicle_enter)
if(veh.gun1.vehicle_enter())
{
- self = oldself;
+ setself(this);
return;
}
if(veh.gun2.vehicle_enter)
if(veh.gun2.vehicle_enter())
{
- self = oldself;
+ setself(this);
return;
}
- self = oldself;
+ setself(this);
}
if(teamplay)
MUTATOR_CALLHOOK(VehicleEnter, pl, veh);
- entity oldself = self;
- self = veh;
- CSQCModel_UnlinkEntity();
- VEH_ACTION(veh.vehicleid, VR_ENTER);
- self = oldself;
+ setself(veh);
+ CSQCModel_UnlinkEntity(veh);
+ Vehicle info = get_vehicleinfo(veh.vehicleid);
+ info.vr_enter(info);
+ setself(this);
antilag_clear(pl);
}
void vehicles_think()
-{
+{SELFPARAM();
self.nextthink = time;
if(self.owner)
self.owner.vehicle_weapon2mode = self.vehicle_weapon2mode;
- VEH_ACTION(self.vehicleid, VR_THINK);
+ Vehicle info = get_vehicleinfo(self.vehicleid);
+ info.vr_think(info);
- CSQCMODEL_AUTOUPDATE();
+ CSQCMODEL_AUTOUPDATE(self);
}
// initialization
void vehicles_spawn()
-{
+{SELFPARAM();
LOG_TRACE("Spawning vehicle: ", self.classname, "\n");
// disown & reset
vehicles_reset_colors();
- VEH_ACTION(self.vehicleid, VR_SPAWN);
+ Vehicle info = get_vehicleinfo(self.vehicleid);
+ info.vr_spawn(info);
- CSQCMODEL_AUTOINIT();
+ CSQCMODEL_AUTOINIT(self);
}
bool vehicle_initialize(entity veh, bool nodrop)
-{
+{SELFPARAM();
if(!autocvar_g_vehicles)
return false;
if(!veh.vehicleid)
return false;
- if(!veh.tur_head) { VEH_ACTION(veh.vehicleid, VR_PRECACHE); }
+ if(!veh.tur_head) {
+ Vehicle info = get_vehicleinfo(veh.vehicleid);
+ info.vr_precache(info);
+ }
if(self.targetname && self.targetname != "")
{
self.team = 0;
if(self.mdl == "" || !self.mdl)
- setmodel(self, veh.model);
+ _setmodel(self, veh.model);
else
- setmodel(self, self.mdl);
+ _setmodel(self, self.mdl);
self.vehicle_flags |= VHF_ISVEHICLE;
if(autocvar_g_fullbrightplayers)
self.effects |= EF_FULLBRIGHT;
- setmodel(self.vehicle_hudmodel, veh.hud_model);
- setmodel(self.vehicle_viewport, "null");
+ _setmodel(self.vehicle_hudmodel, veh.hud_model);
+ setmodel(self.vehicle_viewport, MDL_Null);
if(veh.head_model != "")
{
- setmodel(self.tur_head, veh.head_model);
+ _setmodel(self.tur_head, veh.head_model);
setattachment(self.tur_head, self, veh.tag_head);
setattachment(self.vehicle_hudmodel, self.tur_head, veh.tag_hud);
setattachment(self.vehicle_viewport, self.vehicle_hudmodel, veh.tag_view);
self.pos2 = self.angles;
self.tur_head.team = self.team;
- VEH_ACTION(veh.vehicleid, VR_SETUP);
+ Vehicle info = get_vehicleinfo(veh.vehicleid);
+ info.vr_setup(info);
if(self.active == ACTIVE_NOT)
self.nextthink = 0; // wait until activated
+++ /dev/null
-#ifndef VEHICLE_BUMBLEBEE
-#define VEHICLE_BUMBLEBEE
-#include "bumblebee.qh"
-#ifndef MENUQC
-int v_bumblebee(int);
-#endif
-REGISTER_VEHICLE_SIMPLE(
-/* VEH_##id */ BUMBLEBEE,
-/* spawnflags */ VHF_DMGSHAKE,
-/* mins,maxs */ '-245 -130 -130', '230 130 130',
-/* model */ "models/vehicles/bumblebee_body.dpm",
-/* head_model */ "",
-/* hud_model */ "models/vehicles/spiderbot_cockpit.dpm",
-/* tags */ "", "", "tag_viewport",
-/* netname */ "bumblebee",
-/* fullname */ _("Bumblebee")
-) {
- this.m_icon = "vehicle_bumble";
-#ifndef MENUQC
- this.vehicle_func = v_bumblebee;
-#endif
-}
-#endif
-
-#ifdef IMPLEMENTATION
-
-const float BRG_SETUP = 2;
-const float BRG_START = 4;
-const float BRG_END = 8;
-
-#ifdef SVQC
-float autocvar_g_vehicle_bumblebee_speed_forward;
-float autocvar_g_vehicle_bumblebee_speed_strafe;
-float autocvar_g_vehicle_bumblebee_speed_up;
-float autocvar_g_vehicle_bumblebee_speed_down;
-float autocvar_g_vehicle_bumblebee_turnspeed;
-float autocvar_g_vehicle_bumblebee_pitchspeed;
-float autocvar_g_vehicle_bumblebee_pitchlimit;
-float autocvar_g_vehicle_bumblebee_friction;
-
-float autocvar_g_vehicle_bumblebee_energy;
-float autocvar_g_vehicle_bumblebee_energy_regen;
-float autocvar_g_vehicle_bumblebee_energy_regen_pause;
-
-float autocvar_g_vehicle_bumblebee_health;
-float autocvar_g_vehicle_bumblebee_health_regen;
-float autocvar_g_vehicle_bumblebee_health_regen_pause;
-
-float autocvar_g_vehicle_bumblebee_shield;
-float autocvar_g_vehicle_bumblebee_shield_regen;
-float autocvar_g_vehicle_bumblebee_shield_regen_pause;
-
-float autocvar_g_vehicle_bumblebee_cannon_cost;
-float autocvar_g_vehicle_bumblebee_cannon_damage;
-float autocvar_g_vehicle_bumblebee_cannon_radius;
-float autocvar_g_vehicle_bumblebee_cannon_refire;
-float autocvar_g_vehicle_bumblebee_cannon_speed;
-float autocvar_g_vehicle_bumblebee_cannon_spread;
-float autocvar_g_vehicle_bumblebee_cannon_force;
-
-float autocvar_g_vehicle_bumblebee_cannon_ammo;
-float autocvar_g_vehicle_bumblebee_cannon_ammo_regen;
-float autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause;
-
-float autocvar_g_vehicle_bumblebee_cannon_lock = 0;
-
-float autocvar_g_vehicle_bumblebee_cannon_turnspeed;
-float autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down;
-float autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up;
-float autocvar_g_vehicle_bumblebee_cannon_turnlimit_in;
-float autocvar_g_vehicle_bumblebee_cannon_turnlimit_out;
-
-
-float autocvar_g_vehicle_bumblebee_raygun_turnspeed;
-float autocvar_g_vehicle_bumblebee_raygun_pitchlimit_down;
-float autocvar_g_vehicle_bumblebee_raygun_pitchlimit_up;
-float autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides;
-
-float autocvar_g_vehicle_bumblebee_raygun_range;
-float autocvar_g_vehicle_bumblebee_raygun_dps;
-float autocvar_g_vehicle_bumblebee_raygun_aps;
-float autocvar_g_vehicle_bumblebee_raygun_fps;
-
-float autocvar_g_vehicle_bumblebee_raygun;
-float autocvar_g_vehicle_bumblebee_healgun_hps;
-float autocvar_g_vehicle_bumblebee_healgun_hmax;
-float autocvar_g_vehicle_bumblebee_healgun_aps;
-float autocvar_g_vehicle_bumblebee_healgun_amax;
-float autocvar_g_vehicle_bumblebee_healgun_sps;
-float autocvar_g_vehicle_bumblebee_healgun_locktime;
-
-float autocvar_g_vehicle_bumblebee_respawntime;
-
-float autocvar_g_vehicle_bumblebee_blowup_radius;
-float autocvar_g_vehicle_bumblebee_blowup_coredamage;
-float autocvar_g_vehicle_bumblebee_blowup_edgedamage;
-float autocvar_g_vehicle_bumblebee_blowup_forceintensity;
-vector autocvar_g_vehicle_bumblebee_bouncepain;
-
-bool autocvar_g_vehicle_bumblebee = 0;
-
-float bumble_raygun_send(entity to, int sf);
-
-void bumblebee_fire_cannon(entity _gun, string _tagname, entity _owner)
-{
- vector v = gettaginfo(_gun, gettagindex(_gun, _tagname));
- vehicles_projectile(EFFECT_BIGPLASMA_MUZZLEFLASH.eent_eff_name, W_Sound("flacexp3"),
- v, normalize(v_forward + randomvec() * autocvar_g_vehicle_bumblebee_cannon_spread) * autocvar_g_vehicle_bumblebee_cannon_speed,
- autocvar_g_vehicle_bumblebee_cannon_damage, autocvar_g_vehicle_bumblebee_cannon_radius, autocvar_g_vehicle_bumblebee_cannon_force, 0,
- DEATH_VH_BUMB_GUN, PROJECTILE_BUMBLE_GUN, 0, true, true, _owner);
-}
-
-float bumblebee_gunner_frame()
-{
- entity vehic = self.vehicle.owner;
- entity gun = self.vehicle;
- entity gunner = self;
- self = vehic;
-
- vehic.solid = SOLID_NOT;
- //setorigin(gunner, vehic.origin);
- gunner.velocity = vehic.velocity;
-
- float _in, _out;
- vehic.angles_x *= -1;
- makevectors(vehic.angles);
- vehic.angles_x *= -1;
- if(gun == vehic.gun1)
- {
- _in = autocvar_g_vehicle_bumblebee_cannon_turnlimit_in;
- _out = autocvar_g_vehicle_bumblebee_cannon_turnlimit_out;
- setorigin(gunner, vehic.origin + v_up * -16 + v_forward * -16 + v_right * 128);
- }
- else
- {
- _in = autocvar_g_vehicle_bumblebee_cannon_turnlimit_out;
- _out = autocvar_g_vehicle_bumblebee_cannon_turnlimit_in;
- setorigin(gunner, vehic.origin + v_up * -16 + v_forward * -16 + v_right * -128);
- }
-
- crosshair_trace(gunner);
- vector _ct = trace_endpos;
- vector ad;
-
- if(autocvar_g_vehicle_bumblebee_cannon_lock)
- {
- if(gun.lock_time < time)
- gun.enemy = world;
-
- if(trace_ent)
- if(trace_ent.movetype)
- if(trace_ent.takedamage)
- if(!trace_ent.deadflag)
- {
- if(DIFF_TEAM(trace_ent, gunner))
- {
- gun.enemy = trace_ent;
- gun.lock_time = time + 5;
- }
- }
- }
-
- if(gun.enemy)
- {
- float distance, impact_time;
-
- vector vf = real_origin(gun.enemy);
- vector _vel = gun.enemy.velocity;
- if(gun.enemy.movetype == MOVETYPE_WALK)
- _vel.z *= 0.1;
-
-
- ad = vf;
- distance = vlen(ad - gunner.origin);
- impact_time = distance / autocvar_g_vehicle_bumblebee_cannon_speed;
- ad = vf + _vel * impact_time;
- trace_endpos = ad;
-
-
- UpdateAuxiliaryXhair(gunner, ad, '1 0 1', 1);
- vehicle_aimturret(vehic, trace_endpos, gun, "fire",
- autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up,
- _out * -1, _in, autocvar_g_vehicle_bumblebee_cannon_turnspeed);
-
- }
- else
- vehicle_aimturret(vehic, _ct, gun, "fire",
- autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up,
- _out * -1, _in, autocvar_g_vehicle_bumblebee_cannon_turnspeed);
-
- if(!forbidWeaponUse(gunner))
- if(gunner.BUTTON_ATCK)
- if(time > gun.attack_finished_single)
- if(gun.vehicle_energy >= autocvar_g_vehicle_bumblebee_cannon_cost)
- {
- gun.vehicle_energy -= autocvar_g_vehicle_bumblebee_cannon_cost;
- bumblebee_fire_cannon(gun, "fire", gunner);
- gun.delay = time;
- gun.attack_finished_single = time + autocvar_g_vehicle_bumblebee_cannon_refire;
- }
-
- VEHICLE_UPDATE_PLAYER(gunner, health, bumblebee);
-
- if(vehic.vehicle_flags & VHF_HASSHIELD)
- VEHICLE_UPDATE_PLAYER(gunner, shield, bumblebee);
-
- ad = gettaginfo(gun, gettagindex(gun, "fire"));
- traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, gun);
-
- UpdateAuxiliaryXhair(gunner, trace_endpos, ('1 0 0' * gunner.vehicle_reload1) + ('0 1 0' *(1 - gunner.vehicle_reload1)), 0);
-
- if(vehic.owner)
- UpdateAuxiliaryXhair(vehic.owner, trace_endpos, ('1 0 0' * gunner.vehicle_reload1) + ('0 1 0' *(1 - gunner.vehicle_reload1)), ((gunner == vehic.gunner1) ? 1 : 2));
-
- vehic.solid = SOLID_BBOX;
- gunner.BUTTON_ATCK = gunner.BUTTON_ATCK2 = gunner.BUTTON_CROUCH = 0;
- gunner.vehicle_energy = (gun.vehicle_energy / autocvar_g_vehicle_bumblebee_cannon_ammo) * 100;
-
- self = gunner;
- return 1;
-}
-
-vector bumblebee_gunner_findgoodexit(vector prefer_spot, entity gunner, entity player)
-{
- //vector exitspot;
- float mysize;
-
- tracebox(gunner.origin + '0 0 32', PL_MIN, PL_MAX, prefer_spot, MOVE_NORMAL, player);
- if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
- return prefer_spot;
-
- mysize = 1.5 * vlen(PL_MAX - PL_MIN); // can't use gunner's size, as they don't have a size
- float i;
- vector v, v2;
- v2 = 0.5 * (gunner.absmin + gunner.absmax);
- for(i = 0; i < 100; ++i)
- {
- v = randomvec();
- v_z = 0;
- v = v2 + normalize(v) * mysize;
- tracebox(v2, PL_MIN, PL_MAX, v, MOVE_NORMAL, player);
- if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
- return v;
- }
-
- return prefer_spot; // this should be considered a fallback?!
-}
-
-void bumblebee_gunner_exit(int _exitflag)
-{
- entity player = self;
- entity gunner = player.vehicle;
- entity vehic = gunner.owner;
-
- if(IS_REAL_CLIENT(player))
- {
- msg_entity = player;
- WriteByte(MSG_ONE, SVC_SETVIEWPORT);
- WriteEntity(MSG_ONE, player);
-
- WriteByte(MSG_ONE, SVC_SETVIEWANGLES);
- WriteAngle(MSG_ONE, 0);
- WriteAngle(MSG_ONE, vehic.angles.y);
- WriteAngle(MSG_ONE, 0);
- }
-
- CSQCVehicleSetup(player, HUD_NORMAL);
- setsize(player, PL_MIN, PL_MAX);
-
- player.takedamage = DAMAGE_AIM;
- player.solid = SOLID_SLIDEBOX;
- player.movetype = MOVETYPE_WALK;
- player.effects &= ~EF_NODRAW;
- player.alpha = 1;
- player.PlayerPhysplug = func_null;
- player.view_ofs = PL_VIEW_OFS;
- player.event_damage = PlayerDamage;
- player.hud = HUD_NORMAL;
- player.teleportable = TELEPORT_NORMAL;
- player.switchweapon = gunner.switchweapon;
- player.vehicle_enter_delay = time + 2;
-
- fixedmakevectors(vehic.angles);
-
- if(player == vehic.gunner1) { vehic.gunner1 = world; }
- if(player == vehic.gunner2) { vehic.gunner2 = world; v_right *= -1; }
-
- vector spot = real_origin(gunner);
- spot = spot + v_up * 128 + v_forward * 300 + v_right * 150;
- spot = bumblebee_gunner_findgoodexit(spot, gunner, player);
-
- // TODO: figure a way to move player out of the gunner
-
- player.velocity = 0.75 * vehic.velocity + normalize(spot - vehic.origin) * 200;
- player.velocity_z += 10;
-
- gunner.phase = time + 5;
- gunner.vehicle_hudmodel.viewmodelforclient = gunner;
-
- MUTATOR_CALLHOOK(VehicleExit, player, gunner);
-
- player.vehicle = world;
-}
-
-bool bumblebee_gunner_enter()
-{
- entity vehic = self;
- entity player = other;
- entity gunner = world;
-
- if(!vehic.gunner1 && !vehic.gunner2 && ((time >= vehic.gun1.phase) + (time >= vehic.gun2.phase)) == 2)
- {
- // we can have some fun
- if(vlen(real_origin(vehic.gun2) - player.origin) < vlen(real_origin(vehic.gun1) - player.origin))
- {
- gunner = vehic.gun2;
- vehic.gunner2 = player;
- }
- else
- {
- gunner = vehic.gun1;
- vehic.gunner1 = player;
- }
- }
- else if(!vehic.gunner1 && time >= vehic.gun1.phase) { gunner = vehic.gun1; vehic.gunner1 = player; }
- else if(!vehic.gunner2 && time >= vehic.gun2.phase) { gunner = vehic.gun2; vehic.gunner2 = player; }
- else { LOG_TRACE("Vehicle is full, fail\n"); return false; }
-
- player.vehicle = gunner;
- player.angles = vehic.angles;
- player.takedamage = DAMAGE_NO;
- player.solid = SOLID_NOT;
- player.alpha = -1;
- player.movetype = MOVETYPE_NOCLIP;
- player.event_damage = func_null;
- player.view_ofs = '0 0 0';
- player.hud = gunner.hud;
- player.teleportable = false;
- player.PlayerPhysplug = gunner.PlayerPhysplug;
- player.vehicle_ammo1 = vehic.vehicle_ammo1;
- player.vehicle_ammo2 = vehic.vehicle_ammo2;
- player.vehicle_reload1 = vehic.vehicle_reload1;
- player.vehicle_reload2 = vehic.vehicle_reload2;
- player.vehicle_energy = vehic.vehicle_energy;
- player.flags &= ~FL_ONGROUND;
-
- RemoveGrapplingHook(player);
-
- gunner.switchweapon = player.switchweapon;
- gunner.vehicle_exit = bumblebee_gunner_exit;
- gunner.vehicle_hudmodel.viewmodelforclient = player;
-
- if(IS_REAL_CLIENT(player))
- {
- msg_entity = player;
- WriteByte(MSG_ONE, SVC_SETVIEWPORT);
- WriteEntity(MSG_ONE, gunner.vehicle_viewport);
-
- WriteByte(MSG_ONE, SVC_SETVIEWANGLES);
- WriteAngle(MSG_ONE, gunner.angles_x + vehic.angles_x); // tilt
- WriteAngle(MSG_ONE, gunner.angles_y + vehic.angles_y); // yaw
- WriteAngle(MSG_ONE, 0); // roll
- }
-
- CSQCVehicleSetup(player, player.hud);
-
- MUTATOR_CALLHOOK(VehicleEnter, player, gunner);
-
- return true;
-}
-
-bool vehicles_valid_pilot()
-{
- if(IS_BOT_CLIENT(other) && !autocvar_g_vehicles_allow_bots)
- return false;
-
- if((!IS_PLAYER(other))
- || (other.deadflag != DEAD_NO)
- || (other.vehicle)
- || (DIFF_TEAM(other, self))
- ) { return false; }
-
- return true;
-}
-
-void bumblebee_touch()
-{
- if(autocvar_g_vehicles_enter) { return; }
-
- if(self.gunner1 != world && self.gunner2 != world)
- {
- vehicles_touch();
- return;
- }
-
- if(vehicles_valid_pilot())
- {
- float phase_time = (time >= self.gun1.phase) + (time >= self.gun2.phase);
-
- if(time >= other.vehicle_enter_delay && phase_time)
- if(bumblebee_gunner_enter())
- return;
- }
-
- vehicles_touch();
-}
-
-void bumblebee_regen()
-{
- if(self.gun1.delay + autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause < time)
- self.gun1.vehicle_energy = min(autocvar_g_vehicle_bumblebee_cannon_ammo,
- self.gun1.vehicle_energy + autocvar_g_vehicle_bumblebee_cannon_ammo_regen * frametime);
-
- if(self.gun2.delay + autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause < time)
- self.gun2.vehicle_energy = min(autocvar_g_vehicle_bumblebee_cannon_ammo,
- self.gun2.vehicle_energy + autocvar_g_vehicle_bumblebee_cannon_ammo_regen * frametime);
-
- if(self.vehicle_flags & VHF_SHIELDREGEN)
- vehicles_regen(self.dmg_time, vehicle_shield, autocvar_g_vehicle_bumblebee_shield, autocvar_g_vehicle_bumblebee_shield_regen_pause, autocvar_g_vehicle_bumblebee_shield_regen, frametime, true);
-
- if(self.vehicle_flags & VHF_HEALTHREGEN)
- vehicles_regen(self.dmg_time, vehicle_health, autocvar_g_vehicle_bumblebee_health, autocvar_g_vehicle_bumblebee_health_regen_pause, autocvar_g_vehicle_bumblebee_health_regen, frametime, false);
-
- if(self.vehicle_flags & VHF_ENERGYREGEN)
- vehicles_regen(self.wait, vehicle_energy, autocvar_g_vehicle_bumblebee_energy, autocvar_g_vehicle_bumblebee_energy_regen_pause, autocvar_g_vehicle_bumblebee_energy_regen, frametime, false);
-
-}
-
-float bumblebee_pilot_frame()
-{
- entity pilot, vehic;
- vector newvel;
-
- if(intermission_running)
- {
- self.vehicle.velocity = '0 0 0';
- self.vehicle.avelocity = '0 0 0';
- return 1;
- }
-
- pilot = self;
- vehic = self.vehicle;
- self = vehic;
-
- if(vehic.deadflag != DEAD_NO)
- {
- self = pilot;
- pilot.BUTTON_ATCK = pilot.BUTTON_ATCK2 = 0;
- return 1;
- }
-
- bumblebee_regen();
-
- crosshair_trace(pilot);
-
- vector vang;
- float ftmp;
-
- vang = vehic.angles;
- newvel = vectoangles(normalize(trace_endpos - self.origin + '0 0 32'));
- vang.x *= -1;
- newvel.x *= -1;
- if(newvel.x > 180) newvel.x -= 360;
- if(newvel.x < -180) newvel.x += 360;
- if(newvel.y > 180) newvel.y -= 360;
- if(newvel.y < -180) newvel.y += 360;
-
- ftmp = shortangle_f(pilot.v_angle.y - vang.y, vang.y);
- if(ftmp > 180) ftmp -= 360;
- if(ftmp < -180) ftmp += 360;
- vehic.avelocity_y = bound(-autocvar_g_vehicle_bumblebee_turnspeed, ftmp + vehic.avelocity.y * 0.9, autocvar_g_vehicle_bumblebee_turnspeed);
-
- // Pitch
- ftmp = 0;
- if(pilot.movement.x > 0 && vang.x < autocvar_g_vehicle_bumblebee_pitchlimit)
- ftmp = 4;
- else if(pilot.movement.x < 0 && vang.x > -autocvar_g_vehicle_bumblebee_pitchlimit)
- ftmp = -8;
-
- newvel.x = bound(-autocvar_g_vehicle_bumblebee_pitchlimit, newvel.x , autocvar_g_vehicle_bumblebee_pitchlimit);
- ftmp = vang.x - bound(-autocvar_g_vehicle_bumblebee_pitchlimit, newvel.x + ftmp, autocvar_g_vehicle_bumblebee_pitchlimit);
- vehic.avelocity_x = bound(-autocvar_g_vehicle_bumblebee_pitchspeed, ftmp + vehic.avelocity.x * 0.9, autocvar_g_vehicle_bumblebee_pitchspeed);
-
- vehic.angles_x = anglemods(vehic.angles.x);
- vehic.angles_y = anglemods(vehic.angles.y);
- vehic.angles_z = anglemods(vehic.angles.z);
-
- makevectors('0 1 0' * vehic.angles.y);
- newvel = vehic.velocity * -autocvar_g_vehicle_bumblebee_friction;
-
- if(pilot.movement.x != 0)
- {
- if(pilot.movement.x > 0)
- newvel += v_forward * autocvar_g_vehicle_bumblebee_speed_forward;
- else if(pilot.movement.x < 0)
- newvel -= v_forward * autocvar_g_vehicle_bumblebee_speed_forward;
- }
-
- if(pilot.movement.y != 0)
- {
- if(pilot.movement.y < 0)
- newvel -= v_right * autocvar_g_vehicle_bumblebee_speed_strafe;
- else if(pilot.movement.y > 0)
- newvel += v_right * autocvar_g_vehicle_bumblebee_speed_strafe;
- ftmp = newvel * v_right;
- ftmp *= frametime * 0.1;
- vehic.angles_z = bound(-15, vehic.angles.z + ftmp, 15);
- }
- else
- {
- vehic.angles_z *= 0.95;
- if(vehic.angles.z >= -1 && vehic.angles.z <= -1)
- vehic.angles_z = 0;
- }
-
- if(pilot.BUTTON_CROUCH)
- newvel -= v_up * autocvar_g_vehicle_bumblebee_speed_down;
- else if(pilot.BUTTON_JUMP)
- newvel += v_up * autocvar_g_vehicle_bumblebee_speed_up;
-
- vehic.velocity += newvel * frametime;
- pilot.velocity = pilot.movement = vehic.velocity;
-
-
- if(autocvar_g_vehicle_bumblebee_healgun_locktime)
- {
- if(vehic.tur_head.lock_time < time || vehic.tur_head.enemy.deadflag)
- vehic.tur_head.enemy = world;
-
- if(trace_ent)
- if(trace_ent.movetype)
- if(trace_ent.takedamage)
- if(!trace_ent.deadflag)
- {
- if(teamplay)
- {
- if(trace_ent.team == pilot.team)
- {
- vehic.tur_head.enemy = trace_ent;
- vehic.tur_head.lock_time = time + autocvar_g_vehicle_bumblebee_healgun_locktime;
- }
- }
- else
- {
- vehic.tur_head.enemy = trace_ent;
- vehic.tur_head.lock_time = time + autocvar_g_vehicle_bumblebee_healgun_locktime;
- }
- }
-
- if(vehic.tur_head.enemy)
- {
- trace_endpos = real_origin(vehic.tur_head.enemy);
- UpdateAuxiliaryXhair(pilot, trace_endpos, '0 0.75 0', 0);
- }
- }
-
- vang = vehicle_aimturret(vehic, trace_endpos, self.gun3, "fire",
- autocvar_g_vehicle_bumblebee_raygun_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_raygun_pitchlimit_up,
- autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides * -1, autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides, autocvar_g_vehicle_bumblebee_raygun_turnspeed);
-
- if(!forbidWeaponUse(pilot))
- if((pilot.BUTTON_ATCK || pilot.BUTTON_ATCK2) && (vehic.vehicle_energy > autocvar_g_vehicle_bumblebee_raygun_dps * sys_frametime || autocvar_g_vehicle_bumblebee_raygun == 0))
- {
- vehic.gun3.enemy.realowner = pilot;
- vehic.gun3.enemy.effects &= ~EF_NODRAW;
-
- vehic.gun3.enemy.hook_start = gettaginfo(vehic.gun3, gettagindex(vehic.gun3, "fire"));
- vehic.gun3.enemy.SendFlags |= BRG_START;
-
- traceline(vehic.gun3.enemy.hook_start, vehic.gun3.enemy.hook_start + v_forward * autocvar_g_vehicle_bumblebee_raygun_range, MOVE_NORMAL, vehic);
-
- if(trace_ent)
- {
- if(autocvar_g_vehicle_bumblebee_raygun)
- {
- Damage(trace_ent, vehic, pilot, autocvar_g_vehicle_bumblebee_raygun_dps * sys_frametime, DEATH_GENERIC, trace_endpos, v_forward * autocvar_g_vehicle_bumblebee_raygun_fps * sys_frametime);
- vehic.vehicle_energy -= autocvar_g_vehicle_bumblebee_raygun_aps * sys_frametime;
- }
- else
- {
- if(trace_ent.deadflag == DEAD_NO)
- if((teamplay && trace_ent.team == pilot.team) || !teamplay)
- {
-
- if(trace_ent.vehicle_flags & VHF_ISVEHICLE)
- {
- if(autocvar_g_vehicle_bumblebee_healgun_sps && trace_ent.vehicle_health <= trace_ent.max_health)
- trace_ent.vehicle_shield = min(trace_ent.vehicle_shield + autocvar_g_vehicle_bumblebee_healgun_sps * frametime, trace_ent.tur_head.max_health);
-
- if(autocvar_g_vehicle_bumblebee_healgun_hps)
- trace_ent.vehicle_health = min(trace_ent.vehicle_health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, trace_ent.max_health);
- }
- else if(IS_CLIENT(trace_ent))
- {
- if(trace_ent.health <= autocvar_g_vehicle_bumblebee_healgun_hmax && autocvar_g_vehicle_bumblebee_healgun_hps)
- trace_ent.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, autocvar_g_vehicle_bumblebee_healgun_hmax);
-
- if(trace_ent.armorvalue <= autocvar_g_vehicle_bumblebee_healgun_amax && autocvar_g_vehicle_bumblebee_healgun_aps)
- trace_ent.armorvalue = min(trace_ent.armorvalue + autocvar_g_vehicle_bumblebee_healgun_aps * frametime, autocvar_g_vehicle_bumblebee_healgun_amax);
-
- trace_ent.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, autocvar_g_vehicle_bumblebee_healgun_hmax);
- }
- else if(IS_TURRET(trace_ent))
- {
- if(trace_ent.health <= trace_ent.max_health && autocvar_g_vehicle_bumblebee_healgun_hps)
- trace_ent.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, trace_ent.max_health);
- //else ..hmmm what? ammo?
-
- trace_ent.SendFlags |= TNSF_STATUS;
- }
- }
- }
- }
-
- vehic.gun3.enemy.hook_end = trace_endpos;
- setorigin(vehic.gun3.enemy, trace_endpos);
- vehic.gun3.enemy.SendFlags |= BRG_END;
-
- vehic.wait = time + 1;
- }
- else
- vehic.gun3.enemy.effects |= EF_NODRAW;
- /*{
- if(vehic.gun3.enemy)
- remove(vehic.gun3.enemy);
-
- vehic.gun3.enemy = world;
- }
- */
-
- VEHICLE_UPDATE_PLAYER(pilot, health, bumblebee);
- VEHICLE_UPDATE_PLAYER(pilot, energy, bumblebee);
-
- pilot.vehicle_ammo1 = (vehic.gun1.vehicle_energy / autocvar_g_vehicle_bumblebee_cannon_ammo) * 100;
- pilot.vehicle_ammo2 = (vehic.gun2.vehicle_energy / autocvar_g_vehicle_bumblebee_cannon_ammo) * 100;
-
- if(vehic.vehicle_flags & VHF_HASSHIELD)
- VEHICLE_UPDATE_PLAYER(pilot, shield, bumblebee);
-
- vehic.angles_x *= -1;
- makevectors(vehic.angles);
- vehic.angles_x *= -1;
- setorigin(pilot, vehic.origin + v_up * 48 + v_forward * 160);
-
- pilot.BUTTON_ATCK = pilot.BUTTON_ATCK2 = pilot.BUTTON_CROUCH = 0;
- self = pilot;
-
- return 1;
-}
-
-void bumblebee_land()
-{
- float hgt;
-
- hgt = raptor_altitude(512);
- self.velocity = (self.velocity * 0.9) + ('0 0 -1800' * (hgt / 256) * sys_frametime);
- self.angles_x *= 0.95;
- self.angles_z *= 0.95;
-
- if(hgt < 16)
- self.think = vehicles_think;
-
- self.nextthink = time;
-
- CSQCMODEL_AUTOUPDATE();
-}
-
-void bumblebee_exit(float eject)
-{
- if(self.owner.vehicleid == VEH_BUMBLEBEE.vehicleid)
- {
- bumblebee_gunner_exit(eject);
- return;
- }
-
- self.touch = vehicles_touch;
-
- if(self.deadflag == DEAD_NO)
- {
- self.think = bumblebee_land;
- self.nextthink = time;
- }
-
- self.movetype = MOVETYPE_TOSS;
-
- if(!self.owner)
- return;
-
- fixedmakevectors(self.angles);
- vector spot;
- if(vlen(self.velocity) > autocvar_g_vehicle_bumblebee_speed_forward * 0.5)
- spot = self.origin + v_up * 128 + v_forward * 300;
- else
- spot = self.origin + v_up * 128 - v_forward * 300;
-
- spot = vehicles_findgoodexit(spot);
-
- // Hide beam
- if(self.gun3.enemy || !wasfreed(self.gun3.enemy)) {
- self.gun3.enemy.effects |= EF_NODRAW;
- }
-
- self.owner.velocity = 0.75 * self.vehicle.velocity + normalize(spot - self.vehicle.origin) * 200;
- self.owner.velocity_z += 10;
- setorigin(self.owner, spot);
-
- antilag_clear(self.owner);
- self.owner = world;
-}
-
-void bumblebee_blowup()
-{
- RadiusDamage(self, self.enemy, autocvar_g_vehicle_bumblebee_blowup_coredamage,
- autocvar_g_vehicle_bumblebee_blowup_edgedamage,
- autocvar_g_vehicle_bumblebee_blowup_radius, self, world,
- autocvar_g_vehicle_bumblebee_blowup_forceintensity,
- DEATH_VH_BUMB_DEATH, world);
-
- sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
- Send_Effect(EFFECT_EXPLOSION_BIG, (self.origin + '0 0 100') + (randomvec() * 80), '0 0 0', 1);
-
- if(self.owner.deadflag == DEAD_DYING)
- self.owner.deadflag = DEAD_DEAD;
-
- remove(self);
-}
-
-void bumblebee_diethink()
-{
- if(time >= self.wait)
- self.think = bumblebee_blowup;
-
- if(random() < 0.1)
- {
- sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
- Send_Effect(EFFECT_EXPLOSION_SMALL, randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
- }
-
- self.nextthink = time + 0.1;
-}
-
-float bumble_raygun_send(entity to, float sf)
-{
- WriteByte(MSG_ENTITY, ENT_CLIENT_BUMBLE_RAYGUN);
-
- WriteByte(MSG_ENTITY, sf);
- if(sf & BRG_SETUP)
- {
- WriteByte(MSG_ENTITY, num_for_edict(self.realowner));
- WriteByte(MSG_ENTITY, self.realowner.team);
- WriteByte(MSG_ENTITY, self.cnt);
- }
-
- if(sf & BRG_START)
- {
- WriteCoord(MSG_ENTITY, self.hook_start_x);
- WriteCoord(MSG_ENTITY, self.hook_start_y);
- WriteCoord(MSG_ENTITY, self.hook_start_z);
- }
-
- if(sf & BRG_END)
- {
- WriteCoord(MSG_ENTITY, self.hook_end_x);
- WriteCoord(MSG_ENTITY, self.hook_end_y);
- WriteCoord(MSG_ENTITY, self.hook_end_z);
- }
-
- return true;
-}
-
-void spawnfunc_vehicle_bumblebee()
-{
- if(!autocvar_g_vehicle_bumblebee) { remove(self); return; }
- if(!vehicle_initialize(VEH_BUMBLEBEE, false)) { remove(self); return; }
-}
-
-float v_bumblebee(float req)
-{
- switch(req)
- {
- case VR_IMPACT:
- {
- if(autocvar_g_vehicle_bumblebee_bouncepain)
- vehicles_impact(autocvar_g_vehicle_bumblebee_bouncepain_x, autocvar_g_vehicle_bumblebee_bouncepain_y, autocvar_g_vehicle_bumblebee_bouncepain_z);
-
- return true;
- }
- case VR_ENTER:
- {
- self.touch = bumblebee_touch;
- self.nextthink = 0;
- self.movetype = MOVETYPE_BOUNCEMISSILE;
- return true;
- }
- case VR_THINK:
- {
- self.angles_z *= 0.8;
- self.angles_x *= 0.8;
-
- self.nextthink = time;
-
- if(!self.owner)
- {
- entity oldself = self;
- if(self.gunner1)
- {
- self = self.gunner1;
- oldself.gun1.vehicle_exit(VHEF_EJECT);
- entity oldother = other;
- other = self;
- self = oldself;
- self.phase = 0;
- self.touch();
- other = oldother;
- return true;
- }
-
- if(self.gunner2)
- {
- self = self.gunner2;
- oldself.gun2.vehicle_exit(VHEF_EJECT);
- entity oldother = other;
- other = self;
- self = oldself;
- self.phase = 0;
- self.touch();
- other = oldother;
- return true;
- }
- }
-
- return true;
- }
- case VR_DEATH:
- {
- entity oldself = self;
-
- CSQCModel_UnlinkEntity();
-
- // Hide beam
- if(self.gun3.enemy || !wasfreed(self.gun3.enemy))
- self.gun3.enemy.effects |= EF_NODRAW;
-
- if(self.gunner1)
- {
- self = self.gunner1;
- oldself.gun1.vehicle_exit(VHEF_EJECT);
- self = oldself;
- }
-
- if(self.gunner2)
- {
- self = self.gunner2;
- oldself.gun2.vehicle_exit(VHEF_EJECT);
- self = oldself;
- }
-
- self.vehicle_exit(VHEF_EJECT);
-
- fixedmakevectors(self.angles);
- vehicle_tossgib(self.gun1, self.velocity + v_right * 300 + v_up * 100 + randomvec() * 200, "cannon_right", rint(random()), rint(random()), 6, randomvec() * 200);
- vehicle_tossgib(self.gun2, self.velocity + v_right * -300 + v_up * 100 + randomvec() * 200, "cannon_left", rint(random()), rint(random()), 6, randomvec() * 200);
- vehicle_tossgib(self.gun3, self.velocity + v_forward * 300 + v_up * -100 + randomvec() * 200, "raygun", rint(random()), rint(random()), 6, randomvec() * 300);
-
- entity _body = vehicle_tossgib(self, self.velocity + randomvec() * 200, "", rint(random()), rint(random()), 6, randomvec() * 100);
-
- if(random() > 0.5)
- _body.touch = bumblebee_blowup;
- else
- _body.touch = func_null;
-
- _body.think = bumblebee_diethink;
- _body.nextthink = time;
- _body.wait = time + 2 + (random() * 8);
- _body.owner = self;
- _body.enemy = self.enemy;
- _body.scale = 1.5;
- _body.angles = self.angles;
-
- Send_Effect(EFFECT_EXPLOSION_MEDIUM, findbetterlocation(self.origin, 16), '0 0 0', 1);
-
- self.health = 0;
- self.event_damage = func_null;
- self.solid = SOLID_NOT;
- self.takedamage = DAMAGE_NO;
- self.deadflag = DEAD_DYING;
- self.movetype = MOVETYPE_NONE;
- self.effects = EF_NODRAW;
- self.colormod = '0 0 0';
- self.avelocity = '0 0 0';
- self.velocity = '0 0 0';
- self.touch = func_null;
- self.nextthink = 0;
-
- setorigin(self, self.pos1);
- return true;
- }
- case VR_SPAWN:
- {
- if(!self.gun1)
- {
- // for some reason, autosizing of the shield entity refuses to work for this one so set it up in advance.
- self.vehicle_shieldent = spawn();
- self.vehicle_shieldent.effects = EF_LOWPRECISION;
- setmodel(self.vehicle_shieldent, "models/vhshield.md3");
- setattachment(self.vehicle_shieldent, self, "");
- setorigin(self.vehicle_shieldent, real_origin(self) - self.origin);
- self.vehicle_shieldent.scale = 512 / vlen(self.maxs - self.mins);
- self.vehicle_shieldent.think = shieldhit_think;
- self.vehicle_shieldent.alpha = -1;
- self.vehicle_shieldent.effects = EF_LOWPRECISION | EF_NODRAW;
-
- self.gun1 = spawn();
- self.gun2 = spawn();
- self.gun3 = spawn();
-
- self.vehicle_flags |= VHF_MULTISLOT;
-
- self.gun1.owner = self;
- self.gun2.owner = self;
- self.gun3.owner = self;
-
- self.gun1.classname = self.gun2.classname = "vehicle_playerslot";
-
- setmodel(self.gun1, "models/vehicles/bumblebee_plasma_right.dpm");
- setmodel(self.gun2, "models/vehicles/bumblebee_plasma_left.dpm");
- setmodel(self.gun3, "models/vehicles/bumblebee_ray.dpm");
-
- setattachment(self.gun1, self, "cannon_right");
- setattachment(self.gun2, self, "cannon_left");
-
- // Angled bones are no fun, messes up gun-aim; so work arround it.
- self.gun3.pos1 = self.angles;
- self.angles = '0 0 0';
- vector ofs = gettaginfo(self, gettagindex(self, "raygun"));
- ofs -= self.origin;
- setattachment(self.gun3, self, "");
- setorigin(self.gun3, ofs);
- self.angles = self.gun3.pos1;
-
- vehicle_addplayerslot(self, self.gun1, HUD_BUMBLEBEE_GUN, "models/vehicles/wakizashi_cockpit.dpm", bumblebee_gunner_frame, bumblebee_gunner_exit, bumblebee_gunner_enter);
- vehicle_addplayerslot(self, self.gun2, HUD_BUMBLEBEE_GUN, "models/vehicles/wakizashi_cockpit.dpm", bumblebee_gunner_frame, bumblebee_gunner_exit, bumblebee_gunner_enter);
-
- setorigin(self.vehicle_hudmodel, '50 0 -5'); // Move cockpit forward - down.
- setorigin(self.vehicle_viewport, '5 0 2'); // Move camera forward up
-
- //fixme-model-bones
- setorigin(self.gun1.vehicle_hudmodel, '90 -27 -23');
- setorigin(self.gun1.vehicle_viewport, '-85 0 50');
- //fixme-model-bones
- setorigin(self.gun2.vehicle_hudmodel, '90 27 -23');
- setorigin(self.gun2.vehicle_viewport, '-85 0 50');
-
- self.scale = 1.5;
-
- // Raygun beam
- if(self.gun3.enemy == world)
- {
- self.gun3.enemy = spawn();
- Net_LinkEntity(self.gun3.enemy, true, 0, bumble_raygun_send);
- self.gun3.enemy.SendFlags = BRG_SETUP;
- self.gun3.enemy.cnt = autocvar_g_vehicle_bumblebee_raygun;
- self.gun3.enemy.effects = EF_NODRAW | EF_LOWPRECISION;
- }
- }
-
- self.vehicle_health = autocvar_g_vehicle_bumblebee_health;
- self.vehicle_shield = autocvar_g_vehicle_bumblebee_shield;
- self.solid = SOLID_BBOX;
- self.movetype = MOVETYPE_TOSS;
- self.damageforcescale = 0.025;
-
- self.PlayerPhysplug = bumblebee_pilot_frame;
-
- setorigin(self, self.origin + '0 0 25');
- return true;
- }
- case VR_SETUP:
- {
- if(autocvar_g_vehicle_bumblebee_energy)
- if(autocvar_g_vehicle_bumblebee_energy_regen)
- self.vehicle_flags |= VHF_ENERGYREGEN;
-
- if(autocvar_g_vehicle_bumblebee_shield)
- self.vehicle_flags |= VHF_HASSHIELD;
-
- if(autocvar_g_vehicle_bumblebee_shield_regen)
- self.vehicle_flags |= VHF_SHIELDREGEN;
-
- if(autocvar_g_vehicle_bumblebee_health_regen)
- self.vehicle_flags |= VHF_HEALTHREGEN;
-
- self.vehicle_exit = bumblebee_exit;
- self.respawntime = autocvar_g_vehicle_bumblebee_respawntime;
- self.vehicle_health = autocvar_g_vehicle_bumblebee_health;
- self.max_health = self.vehicle_health;
- self.vehicle_shield = autocvar_g_vehicle_bumblebee_shield;
-
- return true;
- }
- case VR_PRECACHE:
- {
- precache_model("models/vehicles/bumblebee_body.dpm");
- precache_model("models/vehicles/bumblebee_plasma_left.dpm");
- precache_model("models/vehicles/bumblebee_plasma_right.dpm");
- precache_model("models/vehicles/bumblebee_ray.dpm");
- precache_model("models/vehicles/wakizashi_cockpit.dpm");
- precache_model("models/vehicles/spiderbot_cockpit.dpm");
- precache_model("models/vehicles/raptor_cockpit.dpm");
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-
-void CSQC_BUMBLE_GUN_HUD()
-{
- Vehicles_drawHUD("vehicle_gunner", "vehicle_gunner_weapon1", string_null,
- "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
- string_null, '0 0 0',
- string_null);
-}
-
-void bumble_raygun_draw()
-{
- float _len;
- vector _dir;
- vector _vtmp1, _vtmp2;
-
- _len = vlen(self.origin - self.move_origin);
- _dir = normalize(self.move_origin - self.origin);
-
- if(self.total_damages < time)
- {
- boxparticles(self.traileffect, self, self.origin, self.origin + _dir * -64, _dir * -_len , _dir * -_len, 1, PARTICLES_USEALPHA);
- boxparticles(self.lip, self, self.move_origin, self.move_origin + _dir * -64, _dir * -200 , _dir * -200, 1, PARTICLES_USEALPHA);
- self.total_damages = time + 0.1;
- }
-
- float i, df, sz, al;
- for(i = -0.1; i < 0.2; i += 0.1)
- {
- df = DRAWFLAG_NORMAL; //((random() < 0.5) ? DRAWFLAG_ADDITIVE : DRAWFLAG_SCREEN);
- sz = 5 + random() * 5;
- al = 0.25 + random() * 0.5;
- _vtmp1 = self.origin + _dir * _len * (0.25 + i);
- _vtmp1 += (randomvec() * (_len * 0.2) * (frametime * 2)); //self.raygun_l1;
- Draw_CylindricLine(self.origin, _vtmp1, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin);
-
- _vtmp2 = self.origin + _dir * _len * (0.5 + i);
- _vtmp2 += (randomvec() * (_len * 0.2) * (frametime * 5)); //self.raygun_l2;
- Draw_CylindricLine(_vtmp1, _vtmp2, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin);
-
- _vtmp1 = self.origin + _dir * _len * (0.75 + i);
- _vtmp1 += randomvec() * (_len * 0.2) * (frametime * 10); //self.raygun_l3;
- Draw_CylindricLine(_vtmp2, _vtmp1, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin);
-
- Draw_CylindricLine(_vtmp1, self.move_origin + randomvec() * 32, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin);
- }
-}
-
-void bumble_raygun_read(bool bIsNew)
-{
- int sf = ReadByte();
-
- if(sf & BRG_SETUP)
- {
- self.cnt = ReadByte();
- self.team = ReadByte();
- self.cnt = ReadByte();
-
- if(self.cnt)
- self.colormod = '1 0 0';
- else
- self.colormod = '0 1 0';
-
- self.traileffect = particleeffectnum(EFFECT_BUMBLEBEE_HEAL_MUZZLEFLASH);
- self.lip = particleeffectnum(EFFECT_BUMBLEBEE_HEAL_IMPACT);
-
- self.draw = bumble_raygun_draw;
- }
-
-
- if(sf & BRG_START)
- {
- self.origin_x = ReadCoord();
- self.origin_y = ReadCoord();
- self.origin_z = ReadCoord();
- setorigin(self, self.origin);
- }
-
- if(sf & BRG_END)
- {
- self.move_origin_x = ReadCoord();
- self.move_origin_y = ReadCoord();
- self.move_origin_z = ReadCoord();
- }
-}
-
-float v_bumblebee(float req)
-{
- switch(req)
- {
- case VR_HUD:
- {
- Vehicles_drawHUD(VEH_BUMBLEBEE.m_icon, "vehicle_bumble_weapon1", "vehicle_bumble_weapon2",
- "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
- "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
- vCROSS_HEAL);
- return true;
- }
- case VR_SETUP:
- {
- AuxiliaryXhair[0].axh_image = vCROSS_LOCK; // Raygun-locked
- AuxiliaryXhair[1].axh_image = vCROSS_BURST; // Gunner1
- AuxiliaryXhair[2].axh_image = vCROSS_BURST; // Gunner2
- return true;
- }
- case VR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_VEHICLE
+++ /dev/null
-#ifndef BUMBLEBEE_H
-#define BUMBLEBEE_H
-
-#ifdef CSQC
-void bumble_raygun_read(bool bIsNew);
-
-void CSQC_BUMBLE_GUN_HUD();
-#endif
-
-#endif
+++ /dev/null
-#ifndef VEHICLE_RACER
-#define VEHICLE_RACER
-#ifndef MENUQC
-int v_racer(int);
-#endif
-REGISTER_VEHICLE_SIMPLE(
-/* VEH_##id */ RACER,
-/* spawnflags */ VHF_DMGSHAKE | VHF_DMGROLL,
-/* mins,maxs */ '-120 -120 -40' * 0.5, '120 120 40' * 0.5,
-/* model */ "models/vehicles/wakizashi.dpm",
-/* head_model */ "null",
-/* hud_model */ "models/vehicles/wakizashi_cockpit.dpm",
-/* tags */ "", "", "tag_viewport",
-/* netname */ "racer",
-/* fullname */ _("Racer")
-) {
- this.m_icon = "vehicle_racer";
-#ifndef MENUQC
- this.vehicle_func = v_racer;
-#endif
-}
-#endif
-
-#ifdef IMPLEMENTATION
-#ifdef SVQC
-#include "../../effects.qh"
-#include "../../triggers/trigger/impulse.qh"
-
-bool autocvar_g_vehicle_racer;
-
-float autocvar_g_vehicle_racer_speed_afterburn;
-float autocvar_g_vehicle_racer_afterburn_cost;
-
-float autocvar_g_vehicle_racer_waterburn_cost;
-float autocvar_g_vehicle_racer_waterburn_speed;
-
-float autocvar_g_vehicle_racer_water_speed_forward;
-float autocvar_g_vehicle_racer_water_speed_strafe;
-
-float autocvar_g_vehicle_racer_pitchlimit = 30;
-
-float autocvar_g_vehicle_racer_water_downforce = 0.03;
-float autocvar_g_vehicle_racer_water_upforcedamper = 15;
-
-float autocvar_g_vehicle_racer_anglestabilizer;
-float autocvar_g_vehicle_racer_downforce;
-
-float autocvar_g_vehicle_racer_speed_forward;
-float autocvar_g_vehicle_racer_speed_strafe;
-float autocvar_g_vehicle_racer_springlength;
-float autocvar_g_vehicle_racer_upforcedamper;
-float autocvar_g_vehicle_racer_friction;
-
-float autocvar_g_vehicle_racer_water_time = 5;
-
-float autocvar_g_vehicle_racer_hovertype;
-float autocvar_g_vehicle_racer_hoverpower;
-
-float autocvar_g_vehicle_racer_turnroll;
-float autocvar_g_vehicle_racer_turnspeed;
-float autocvar_g_vehicle_racer_pitchspeed;
-
-float autocvar_g_vehicle_racer_energy;
-float autocvar_g_vehicle_racer_energy_regen;
-float autocvar_g_vehicle_racer_energy_regen_pause;
-
-float autocvar_g_vehicle_racer_health;
-float autocvar_g_vehicle_racer_health_regen;
-float autocvar_g_vehicle_racer_health_regen_pause;
-
-float autocvar_g_vehicle_racer_shield;
-float autocvar_g_vehicle_racer_shield_regen;
-float autocvar_g_vehicle_racer_shield_regen_pause;
-
-float autocvar_g_vehicle_racer_cannon_cost;
-float autocvar_g_vehicle_racer_cannon_damage;
-float autocvar_g_vehicle_racer_cannon_radius;
-float autocvar_g_vehicle_racer_cannon_refire;
-float autocvar_g_vehicle_racer_cannon_speed;
-float autocvar_g_vehicle_racer_cannon_spread;
-float autocvar_g_vehicle_racer_cannon_force;
-
-float autocvar_g_vehicle_racer_rocket_accel;
-float autocvar_g_vehicle_racer_rocket_damage;
-float autocvar_g_vehicle_racer_rocket_radius;
-float autocvar_g_vehicle_racer_rocket_force;
-float autocvar_g_vehicle_racer_rocket_refire;
-float autocvar_g_vehicle_racer_rocket_speed;
-float autocvar_g_vehicle_racer_rocket_turnrate;
-
-float autocvar_g_vehicle_racer_rocket_locktarget;
-float autocvar_g_vehicle_racer_rocket_locking_time;
-float autocvar_g_vehicle_racer_rocket_locking_releasetime;
-float autocvar_g_vehicle_racer_rocket_locked_time;
-float autocvar_g_vehicle_racer_rocket_locked_maxangle;
-float autocvar_g_vehicle_racer_rocket_climbspeed;
-
-float autocvar_g_vehicle_racer_respawntime;
-
-float autocvar_g_vehicle_racer_blowup_radius;
-float autocvar_g_vehicle_racer_blowup_coredamage;
-float autocvar_g_vehicle_racer_blowup_edgedamage;
-float autocvar_g_vehicle_racer_blowup_forceintensity;
-
-float autocvar_g_vehicle_racer_bouncefactor;
-float autocvar_g_vehicle_racer_bouncestop;
-vector autocvar_g_vehicle_racer_bouncepain;
-
-.float racer_watertime;
-
-var vector racer_force_from_tag(string tag_name, float spring_length, float max_power);
-
-void racer_align4point(float _delta)
-{
- vector push_vector;
- float fl_push, fr_push, bl_push, br_push;
-
- push_vector = racer_force_from_tag("tag_engine_fr", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
- fr_push = force_fromtag_normpower;
- //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
-
- push_vector += racer_force_from_tag("tag_engine_fl", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
- fl_push = force_fromtag_normpower;
- //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
-
- push_vector += racer_force_from_tag("tag_engine_br", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
- br_push = force_fromtag_normpower;
- //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
-
- push_vector += racer_force_from_tag("tag_engine_bl", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
- bl_push = force_fromtag_normpower;
- //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
-
- self.velocity += push_vector * _delta;
-
- float uforce = autocvar_g_vehicle_racer_upforcedamper;
-
- int cont = pointcontents(self.origin - '0 0 64');
- if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
- {
- uforce = autocvar_g_vehicle_racer_water_upforcedamper;
-
- if(self.owner.BUTTON_CROUCH && time < self.air_finished)
- self.velocity_z += 30;
- else
- self.velocity_z += 200;
- }
-
-
- // Anti ocilation
- if(self.velocity_z > 0)
- self.velocity_z *= 1 - uforce * _delta;
-
- push_vector_x = (fl_push - bl_push);
- push_vector_x += (fr_push - br_push);
- push_vector_x *= 360;
-
- push_vector_z = (fr_push - fl_push);
- push_vector_z += (br_push - bl_push);
- push_vector_z *= 360;
-
- // Apply angle diffrance
- self.angles_z += push_vector_z * _delta;
- self.angles_x += push_vector_x * _delta;
-
- // Apply stabilizer
- self.angles_x *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * _delta);
- self.angles_z *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * _delta);
-}
-
-void racer_fire_cannon(string tagname)
-{
- vector v;
- entity bolt;
-
- v = gettaginfo(self, gettagindex(self, tagname));
- bolt = vehicles_projectile(EFFECT_RACER_MUZZLEFLASH.eent_eff_name, W_Sound("lasergun_fire"),
- v, normalize(v_forward + randomvec() * autocvar_g_vehicle_racer_cannon_spread) * autocvar_g_vehicle_racer_cannon_speed,
- autocvar_g_vehicle_racer_cannon_damage, autocvar_g_vehicle_racer_cannon_radius, autocvar_g_vehicle_racer_cannon_force, 0,
- DEATH_VH_WAKI_GUN, PROJECTILE_WAKICANNON, 0, true, true, self.owner);
-
- // Fix z-aim (for chase mode)
- v = normalize(trace_endpos - bolt.origin);
- v_forward_z = v_z * 0.5;
- bolt.velocity = v_forward * autocvar_g_vehicle_racer_cannon_speed;
-}
-
-void racer_rocket_groundhugger()
-{
- vector olddir, newdir;
- float oldvel, newvel;
-
- self.nextthink = time;
-
- if(self.owner.deadflag != DEAD_NO || self.cnt < time)
- {
- self.use();
- return;
- }
-
- if(!self.realowner.vehicle)
- {
- UpdateCSQCProjectile(self);
- return;
- }
-
- olddir = normalize(self.velocity);
- oldvel = vlen(self.velocity);
- newvel = oldvel + self.lip;
-
- tracebox(self.origin, self.mins, self.maxs, self.origin + olddir * 64, MOVE_WORLDONLY,self);
- if(trace_fraction <= 0.5)
- {
- // Hitting somethign soon, just speed ahead
- self.velocity = olddir * newvel;
- UpdateCSQCProjectile(self);
- return;
- }
-
- traceline(trace_endpos, trace_endpos - '0 0 64', MOVE_NORMAL, self);
- if(trace_fraction != 1.0)
- {
- newdir = normalize(trace_endpos + '0 0 64' - self.origin) * autocvar_g_vehicle_racer_rocket_turnrate;
- self.velocity = normalize(olddir + newdir) * newvel;
- }
- else
- {
- self.velocity = olddir * newvel;
- self.velocity_z -= 1600 * sys_frametime; // 2x grav looks better for this one
- }
-
- int cont = pointcontents(self.origin - '0 0 32');
- if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
- self.velocity_z += 200;
-
- UpdateCSQCProjectile(self);
- return;
-}
-
-void racer_rocket_tracker()
-{
- vector olddir, newdir;
- float oldvel, newvel;
-
- self.nextthink = time;
-
- if (self.owner.deadflag != DEAD_NO || self.cnt < time)
- {
- self.use();
- return;
- }
-
- if(!self.realowner.vehicle)
- {
- UpdateCSQCProjectile(self);
- return;
- }
-
- olddir = normalize(self.velocity);
- oldvel = vlen(self.velocity);
- newvel = oldvel + self.lip;
- makevectors(vectoangles(olddir));
-
- float time_to_impact = min(vlen(self.enemy.origin - self.origin) / vlen(self.velocity), 1);
- vector predicted_origin = self.enemy.origin + self.enemy.velocity * time_to_impact;
-
- traceline(self.origin, self.origin + v_forward * 64 - '0 0 32', MOVE_NORMAL, self);
- newdir = normalize(predicted_origin - self.origin);
-
- //vector
- float height_diff = predicted_origin_z - self.origin_z;
-
- if(vlen(newdir - v_forward) > autocvar_g_vehicle_racer_rocket_locked_maxangle)
- {
- //bprint("Target lost!\n");
- //dprint("OF:", ftos(vlen(newdir - v_forward)), "\n");
- self.think = racer_rocket_groundhugger;
- return;
- }
-
- if(trace_fraction != 1.0 && trace_ent != self.enemy)
- newdir_z += 16 * sys_frametime;
-
- self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_racer_rocket_turnrate) * newvel;
- self.velocity_z -= 800 * sys_frametime;
- self.velocity_z += max(height_diff, autocvar_g_vehicle_racer_rocket_climbspeed) * sys_frametime ;
-
- UpdateCSQCProjectile(self);
- return;
-}
-
-void racer_fire_rocket(string tagname, entity trg)
-{
- vector v = gettaginfo(self, gettagindex(self, tagname));
- entity rocket = vehicles_projectile(EFFECT_RACER_ROCKETLAUNCH.eent_eff_name, W_Sound("rocket_fire"),
- v, v_forward * autocvar_g_vehicle_racer_rocket_speed,
- autocvar_g_vehicle_racer_rocket_damage, autocvar_g_vehicle_racer_rocket_radius, autocvar_g_vehicle_racer_rocket_force, 3,
- DEATH_VH_WAKI_ROCKET, PROJECTILE_WAKIROCKET, 20, false, false, self.owner);
-
- rocket.lip = autocvar_g_vehicle_racer_rocket_accel * sys_frametime;
- rocket.wait = autocvar_g_vehicle_racer_rocket_turnrate;
- rocket.nextthink = time;
- rocket.enemy = trg;
- rocket.cnt = time + 15;
-
- if(trg)
- rocket.think = racer_rocket_tracker;
- else
- rocket.think = racer_rocket_groundhugger;
-}
-
-float racer_frame()
-{
- entity player, racer;
- vector df;
- float ftmp;
-
- if(intermission_running)
- {
- self.vehicle.velocity = '0 0 0';
- self.vehicle.avelocity = '0 0 0';
- return 1;
- }
-
- player = self;
- racer = self.vehicle;
- self = racer;
-
- vehicles_painframe();
-
- if(pointcontents(racer.origin) != CONTENT_WATER)
- racer.air_finished = time + autocvar_g_vehicle_racer_water_time;
-
- if(racer.deadflag != DEAD_NO)
- {
- self = player;
- player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
- return 1;
- }
-
- racer_align4point(PHYS_INPUT_TIMELENGTH);
-
- player.BUTTON_ZOOM = player.BUTTON_CROUCH = 0;
-
- crosshair_trace(player);
-
- racer.angles_x *= -1;
-
- // Yaw
- ftmp = autocvar_g_vehicle_racer_turnspeed * PHYS_INPUT_TIMELENGTH;
- ftmp = bound(-ftmp, shortangle_f(player.v_angle_y - racer.angles_y, racer.angles_y), ftmp);
- racer.angles_y = anglemods(racer.angles_y + ftmp);
-
- // Roll
- racer.angles_z += -ftmp * autocvar_g_vehicle_racer_turnroll * PHYS_INPUT_TIMELENGTH;
-
- // Pitch
- ftmp = autocvar_g_vehicle_racer_pitchspeed * PHYS_INPUT_TIMELENGTH;
- ftmp = bound(-ftmp, shortangle_f(player.v_angle_x - racer.angles_x, racer.angles_x), ftmp);
- racer.angles_x = bound(-autocvar_g_vehicle_racer_pitchlimit, anglemods(racer.angles_x + ftmp), autocvar_g_vehicle_racer_pitchlimit);
-
- makevectors(racer.angles);
- racer.angles_x *= -1;
-
- //ftmp = racer.velocity_z;
- df = racer.velocity * -autocvar_g_vehicle_racer_friction;
- //racer.velocity_z = ftmp;
-
- int cont = pointcontents(racer.origin);
- if(vlen(player.movement) != 0)
- {
- if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
- {
- if(player.movement_x) { df += v_forward * ((player.movement_x > 0) ? autocvar_g_vehicle_racer_water_speed_forward : -autocvar_g_vehicle_racer_water_speed_forward); }
- if(player.movement_y) { df += v_right * ((player.movement_y > 0) ? autocvar_g_vehicle_racer_water_speed_strafe : -autocvar_g_vehicle_racer_water_speed_strafe); }
- }
- else
- {
- if(player.movement_x) { df += v_forward * ((player.movement_x > 0) ? autocvar_g_vehicle_racer_speed_forward : -autocvar_g_vehicle_racer_speed_forward); }
- if(player.movement_y) { df += v_right * ((player.movement_y > 0) ? autocvar_g_vehicle_racer_speed_strafe : -autocvar_g_vehicle_racer_speed_strafe); }
- }
-
-#ifdef SVQC
- if(self.sound_nexttime < time || self.sounds != 1)
- {
- self.sounds = 1;
- self.sound_nexttime = time + 10.922667; //soundlength("vehicles/racer_move.wav");
- sound (self, CH_TRIGGER_SINGLE, "vehicles/racer_move.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
- }
-#endif
- }
-#ifdef SVQC
- else
- {
- if(self.sound_nexttime < time || self.sounds != 0)
- {
- self.sounds = 0;
- self.sound_nexttime = time + 11.888604; //soundlength("vehicles/racer_idle.wav");
- sound (self, CH_TRIGGER_SINGLE, "vehicles/racer_idle.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
- }
- }
-#endif
-
- // Afterburn
- if (PHYS_INPUT_BUTTON_JUMP(player) && racer.vehicle_energy >= (autocvar_g_vehicle_racer_afterburn_cost * PHYS_INPUT_TIMELENGTH))
- {
-#ifdef SVQC
- if(time - racer.wait > 0.2)
- pointparticles(particleeffectnum(EFFECT_RACER_BOOSTER), self.origin - v_forward * 32, v_forward * vlen(self.velocity), 1);
-#endif
-
- racer.wait = time;
-
- if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
- {
- racer.vehicle_energy -= autocvar_g_vehicle_racer_waterburn_cost * PHYS_INPUT_TIMELENGTH;
- df += (v_forward * autocvar_g_vehicle_racer_waterburn_speed);
- }
- else
- {
- racer.vehicle_energy -= autocvar_g_vehicle_racer_afterburn_cost * PHYS_INPUT_TIMELENGTH;
- df += (v_forward * autocvar_g_vehicle_racer_speed_afterburn);
- }
-
-#ifdef SVQC
- if(racer.invincible_finished < time)
- {
- traceline(racer.origin, racer.origin - '0 0 256', MOVE_NORMAL, self);
- if(trace_fraction != 1.0)
- pointparticles(particleeffectnum(EFFECT_SMOKE_SMALL), trace_endpos, '0 0 0', 1);
-
- racer.invincible_finished = time + 0.1 + (random() * 0.1);
- }
-
- if(racer.strength_finished < time)
- {
- racer.strength_finished = time + 10.922667; //soundlength("vehicles/racer_boost.wav");
- sound (racer.tur_head, CH_TRIGGER_SINGLE, "vehicles/racer_boost.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
- }
-#endif
- }
- else
- {
- racer.strength_finished = 0;
- sound (racer.tur_head, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
- }
-
- if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
- racer.racer_watertime = time;
-
- float dforce = autocvar_g_vehicle_racer_downforce;
- if(time - racer.racer_watertime <= 3)
- dforce = autocvar_g_vehicle_racer_water_downforce;
-
- df -= v_up * (vlen(racer.velocity) * dforce);
- player.movement = racer.velocity += df * PHYS_INPUT_TIMELENGTH;
-
-#ifdef SVQC
- if(!forbidWeaponUse(player))
- if(player.BUTTON_ATCK)
- if(time > racer.attack_finished_single)
- if(racer.vehicle_energy >= autocvar_g_vehicle_racer_cannon_cost)
- {
- racer.vehicle_energy -= autocvar_g_vehicle_racer_cannon_cost;
- racer.wait = time;
-
- crosshair_trace(player);
- if(racer.cnt)
- {
- racer_fire_cannon("tag_fire1");
- racer.cnt = 0;
- }
- else
- {
- racer_fire_cannon("tag_fire2");
- racer.cnt = 1;
- }
- racer.attack_finished_single = time + autocvar_g_vehicle_racer_cannon_refire;
- }
-
- if(autocvar_g_vehicle_racer_rocket_locktarget)
- {
- vehicles_locktarget((1 / autocvar_g_vehicle_racer_rocket_locking_time) * frametime,
- (1 / autocvar_g_vehicle_racer_rocket_locking_releasetime) * frametime,
- autocvar_g_vehicle_racer_rocket_locked_time);
-
- if(self.lock_target)
- {
- if(racer.lock_strength == 1)
- UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '1 0 0', 0);
- else if(self.lock_strength > 0.5)
- UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '0 1 0', 0);
- else if(self.lock_strength < 0.5)
- UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '0 0 1', 0);
- }
- }
-
- if(!forbidWeaponUse(player))
- if(time > racer.delay)
- if(player.BUTTON_ATCK2)
- {
- racer.misc_bulletcounter += 1;
- racer.delay = time + 0.3;
-
- if(racer.misc_bulletcounter == 1)
- {
- racer_fire_rocket("tag_rocket_r", (racer.lock_strength == 1 && racer.lock_target) ? racer.lock_target : world);
- player.vehicle_ammo2 = 50;
- }
- else if(racer.misc_bulletcounter == 2)
- {
- racer_fire_rocket("tag_rocket_l", (racer.lock_strength == 1 && racer.lock_target) ? racer.lock_target : world);
- racer.lock_strength = 0;
- racer.lock_target = world;
- racer.misc_bulletcounter = 0;
- racer.delay = time + autocvar_g_vehicle_racer_rocket_refire;
- racer.lip = time;
- player.vehicle_ammo2 = 0;
- }
- }
- else if(racer.misc_bulletcounter == 0)
- player.vehicle_ammo2 = 100;
-
- player.vehicle_reload2 = bound(0, 100 * ((time - racer.lip) / (racer.delay - racer.lip)), 100);
-
- if(racer.vehicle_flags & VHF_SHIELDREGEN)
- vehicles_regen(racer.dmg_time, vehicle_shield, autocvar_g_vehicle_racer_shield, autocvar_g_vehicle_racer_shield_regen_pause, autocvar_g_vehicle_racer_shield_regen, frametime, true);
-
- if(racer.vehicle_flags & VHF_HEALTHREGEN)
- vehicles_regen(racer.dmg_time, vehicle_health, autocvar_g_vehicle_racer_health, autocvar_g_vehicle_racer_health_regen_pause, autocvar_g_vehicle_racer_health_regen, frametime, false);
-
- if(racer.vehicle_flags & VHF_ENERGYREGEN)
- vehicles_regen(racer.wait, vehicle_energy, autocvar_g_vehicle_racer_energy, autocvar_g_vehicle_racer_energy_regen_pause, autocvar_g_vehicle_racer_energy_regen, frametime, false);
-
-
- VEHICLE_UPDATE_PLAYER(player, health, racer);
- VEHICLE_UPDATE_PLAYER(player, energy, racer);
-
- if(racer.vehicle_flags & VHF_HASSHIELD)
- VEHICLE_UPDATE_PLAYER(player, shield, racer);
-
- player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
-#endif
-
- setorigin(player,racer.origin + '0 0 32');
- player.velocity = racer.velocity;
-
- self = player;
- return 1;
-}
-
-void racer_think()
-{
- self.nextthink = time;
-
- float pushdeltatime = time - self.lastpushtime;
- if (pushdeltatime > 0.15) pushdeltatime = 0;
- self.lastpushtime = time;
- if(!pushdeltatime) return;
-
- tracebox(self.origin, self.mins, self.maxs, self.origin - ('0 0 1' * autocvar_g_vehicle_racer_springlength), MOVE_NOMONSTERS, self);
-
- vector df = self.velocity * -autocvar_g_vehicle_racer_friction;
- df_z += (1 - trace_fraction) * autocvar_g_vehicle_racer_hoverpower + sin(time * 2) * (autocvar_g_vehicle_racer_springlength * 2);
-
- float forced = autocvar_g_vehicle_racer_upforcedamper;
-
- int cont = pointcontents(self.origin - '0 0 64');
- if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
- {
- forced = autocvar_g_vehicle_racer_water_upforcedamper;
- self.velocity_z += 200;
- }
-
- self.velocity += df * pushdeltatime;
- if(self.velocity_z > 0)
- self.velocity_z *= 1 - forced * pushdeltatime;
-
- self.angles_x *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * pushdeltatime);
- self.angles_z *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * pushdeltatime);
-
- CSQCMODEL_AUTOUPDATE();
-}
-
-void racer_exit(float eject)
-{
- vector spot;
-
- self.think = racer_think;
- self.nextthink = time;
- self.movetype = MOVETYPE_BOUNCE;
- sound (self.tur_head, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
-
- if(!self.owner)
- return;
-
- makevectors(self.angles);
- if(eject)
- {
- spot = self.origin + v_forward * 100 + '0 0 64';
- spot = vehicles_findgoodexit(spot);
- setorigin(self.owner , spot);
- self.owner.velocity = (v_up + v_forward * 0.25) * 750;
- self.owner.oldvelocity = self.owner.velocity;
- }
- else
- {
- if(vlen(self.velocity) > 2 * autocvar_sv_maxairspeed)
- {
- self.owner.velocity = normalize(self.velocity) * autocvar_sv_maxairspeed * 2;
- self.owner.velocity_z += 200;
- spot = self.origin + v_forward * 32 + '0 0 32';
- spot = vehicles_findgoodexit(spot);
- }
- else
- {
- self.owner.velocity = self.velocity * 0.5;
- self.owner.velocity_z += 10;
- spot = self.origin - v_forward * 200 + '0 0 32';
- spot = vehicles_findgoodexit(spot);
- }
- self.owner.oldvelocity = self.owner.velocity;
- setorigin(self.owner , spot);
- }
- antilag_clear(self.owner);
- self.owner = world;
-}
-
-void racer_blowup()
-{
- self.deadflag = DEAD_DEAD;
- self.vehicle_exit(VHEF_NORMAL);
-
- RadiusDamage (self, self.enemy, autocvar_g_vehicle_racer_blowup_coredamage,
- autocvar_g_vehicle_racer_blowup_edgedamage,
- autocvar_g_vehicle_racer_blowup_radius, world, world,
- autocvar_g_vehicle_racer_blowup_forceintensity,
- DEATH_VH_WAKI_DEATH, world);
-
- self.nextthink = time + autocvar_g_vehicle_racer_respawntime;
- self.think = vehicles_spawn;
- self.movetype = MOVETYPE_NONE;
- self.effects = EF_NODRAW;
-
- self.colormod = '0 0 0';
- self.avelocity = '0 0 0';
- self.velocity = '0 0 0';
-
- setorigin(self, self.pos1);
-}
-
-void racer_blowup_think()
-{
- self.nextthink = time;
-
- if(time >= self.delay)
- racer_blowup();
-
- CSQCMODEL_AUTOUPDATE();
-}
-
-void racer_deadtouch()
-{
- self.avelocity_x *= 0.7;
- self.cnt -= 1;
- if(self.cnt <= 0)
- racer_blowup();
-}
-
-void spawnfunc_vehicle_racer()
-{
- if(!autocvar_g_vehicle_racer) { remove(self); return; }
- if(!vehicle_initialize(VEH_RACER, false)) { remove(self); return; }
-}
-
-#endif // SVQC
-
-#ifdef CSQC
-#if 0
-void racer_draw()
-{
- float pushdeltatime = time - self.lastpushtime;
- if (pushdeltatime > 0.15) pushdeltatime = 0;
- self.lastpushtime = time;
- if(!pushdeltatime) return;
-
- tracebox(self.move_origin, self.mins, self.maxs, self.move_origin - ('0 0 1' * getstatf(STAT_VEH_RACER_SPRINGLENGTH)), MOVE_NOMONSTERS, self);
-
- vector df = self.move_velocity * -getstatf(STAT_VEH_RACER_FRICTION);
- df_z += (1 - trace_fraction) * getstatf(STAT_VEH_RACER_HOVERPOWER) + sin(time * 2) * (getstatf(STAT_VEH_RACER_SPRINGLENGTH) * 2);
-
- float forced = getstatf(STAT_VEH_RACER_UPFORCEDAMPER);
-
- int cont = pointcontents(self.move_origin - '0 0 64');
- if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
- {
- forced = getstatf(STAT_VEH_RACER_WATER_UPFORCEDAMPER);
- self.move_velocity_z += 200;
- }
-
- self.move_velocity += df * pushdeltatime;
- if(self.move_velocity_z > 0)
- self.move_velocity_z *= 1 - forced * pushdeltatime;
-
- self.move_angles_x *= 1 - (getstatf(STAT_VEH_RACER_ANGLESTABILIZER) * pushdeltatime);
- self.move_angles_z *= 1 - (getstatf(STAT_VEH_RACER_ANGLESTABILIZER) * pushdeltatime);
-
- Movetype_Physics_MatchServer(false);
-}
-#endif
-#endif
-
-bool v_racer(int req)
-{
- switch(req)
- {
- case VR_IMPACT:
- {
- #ifdef SVQC
- if(autocvar_g_vehicle_racer_bouncepain)
- vehicles_impact(autocvar_g_vehicle_racer_bouncepain_x, autocvar_g_vehicle_racer_bouncepain_y, autocvar_g_vehicle_racer_bouncepain_z);
- #endif
- return true;
- }
-
- case VR_ENTER:
- {
- #ifdef SVQC
- self.movetype = MOVETYPE_BOUNCE;
- self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_racer_health) * 100;
- self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_racer_shield) * 100;
-
- if(self.owner.flagcarried)
- setorigin(self.owner.flagcarried, '-190 0 96');
- #elif defined(CSQC)
-
- self.move_movetype = MOVETYPE_BOUNCE;
- #endif
-
- return true;
- }
-
- case VR_SPAWN:
- {
- #ifdef SVQC
- if(self.scale != 0.5)
- {
- if(autocvar_g_vehicle_racer_hovertype != 0)
- racer_force_from_tag = vehicles_force_fromtag_maglev;
- else
- racer_force_from_tag = vehicles_force_fromtag_hover;
-
- // FIXME: this be hakkz, fix the models insted (scale body, add tag_viewport to the hudmodel).
- self.scale = 0.5;
- setattachment(self.vehicle_hudmodel, self, "");
- setattachment(self.vehicle_viewport, self, "tag_viewport");
-
- self.mass = 900;
- }
-
- self.think = racer_think;
- self.nextthink = time;
- self.vehicle_health = autocvar_g_vehicle_racer_health;
- self.vehicle_shield = autocvar_g_vehicle_racer_shield;
-
- self.movetype = MOVETYPE_TOSS;
- self.solid = SOLID_SLIDEBOX;
- self.delay = time;
- self.scale = 0.5;
-
- self.PlayerPhysplug = racer_frame;
-
- self.bouncefactor = autocvar_g_vehicle_racer_bouncefactor;
- self.bouncestop = autocvar_g_vehicle_racer_bouncestop;
- self.damageforcescale = 0.5;
- self.vehicle_health = autocvar_g_vehicle_racer_health;
- self.vehicle_shield = autocvar_g_vehicle_racer_shield;
- #endif
- return true;
- }
-
- case VR_DEATH:
- {
- #ifdef SVQC
- self.SendEntity = func_null; // stop networking this racer (for now)
- self.health = 0;
- self.event_damage = func_null;
- self.solid = SOLID_CORPSE;
- self.takedamage = DAMAGE_NO;
- self.deadflag = DEAD_DYING;
- self.movetype = MOVETYPE_BOUNCE;
- self.wait = time;
- self.delay = 2 + time + random() * 3;
- self.cnt = 1 + random() * 2;
- self.touch = racer_deadtouch;
-
- Send_Effect(EFFECT_EXPLOSION_MEDIUM, self.origin, '0 0 0', 1);
-
- if(random() < 0.5)
- self.avelocity_z = 32;
- else
- self.avelocity_z = -32;
-
- self.avelocity_x = -vlen(self.velocity) * 0.2;
- self.velocity += '0 0 700';
- self.colormod = '-0.5 -0.5 -0.5';
-
- self.think = racer_blowup_think;
- self.nextthink = time;
- #endif
- return true;
- }
-
-#ifdef CSQC
- case VR_HUD:
- {
- Vehicles_drawHUD(VEH_RACER.m_icon, "vehicle_racer_weapon1", "vehicle_racer_weapon2",
- "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
- "vehicle_icon_ammo2", autocvar_hud_progressbar_vehicles_ammo2_color,
- vCROSS_GUIDE);
- return true;
- }
-#endif
- case VR_SETUP:
- {
- #ifdef SVQC
- self.vehicle_exit = racer_exit;
- #endif
-
- #ifdef SVQC
- // we have no need to network energy
- if(autocvar_g_vehicle_racer_energy)
- if(autocvar_g_vehicle_racer_energy_regen)
- self.vehicle_flags |= VHF_ENERGYREGEN;
-
- if(autocvar_g_vehicle_racer_shield)
- self.vehicle_flags |= VHF_HASSHIELD;
-
- if(autocvar_g_vehicle_racer_shield_regen)
- self.vehicle_flags |= VHF_SHIELDREGEN;
-
- if(autocvar_g_vehicle_racer_health_regen)
- self.vehicle_flags |= VHF_HEALTHREGEN;
-
- self.respawntime = autocvar_g_vehicle_racer_respawntime;
- self.vehicle_health = autocvar_g_vehicle_racer_health;
- self.vehicle_shield = autocvar_g_vehicle_racer_shield;
- self.max_health = self.vehicle_health;
- #endif
-
- #ifdef CSQC
- AuxiliaryXhair[0].axh_image = vCROSS_LOCK; // Rocket
- #endif
- return true;
- }
-
- case VR_PRECACHE:
- {
- #ifdef SVQC
- precache_sound (W_Sound("lasergun_fire"));
- precache_sound (W_Sound("rocket_fire"));
-
- precache_sound ("vehicles/racer_idle.wav");
- precache_sound ("vehicles/racer_move.wav");
- precache_sound ("vehicles/racer_boost.wav");
-
- precache_model ("models/vhshield.md3");
- #endif
- #ifndef MENUQC
- precache_model ("models/vehicles/wakizashi.dpm");
- precache_model ("models/vehicles/wakizashi_cockpit.dpm");
- #endif
- return true;
- }
- }
-
- return true;
-}
-
-#endif // REGISTER_VEHICLE
+++ /dev/null
-#ifndef VEHICLE_RAPTOR
-#define VEHICLE_RAPTOR
-#include "raptor.qh"
-#ifndef MENUQC
-int v_raptor(int);
-#endif
-REGISTER_VEHICLE_SIMPLE(
-/* VEH_##id */ RAPTOR,
-/* spawnflags */ VHF_DMGSHAKE | VHF_DMGROLL,
-/* mins,maxs */ '-80 -80 0', '80 80 70',
-/* model */ "models/vehicles/raptor.dpm",
-/* head_model */ "",
-/* hud_model */ "models/vehicles/raptor_cockpit.dpm",
-/* tags */ "", "tag_hud", "tag_camera",
-/* netname */ "raptor",
-/* fullname */ _("Raptor")
-) {
- this.m_icon = "vehicle_raptor";
-#ifndef MENUQC
- this.vehicle_func = v_raptor;
-#endif
-}
-#endif
-
-#ifdef IMPLEMENTATION
-
-#ifdef SVQC
-bool autocvar_g_vehicle_raptor;
-
-float autocvar_g_vehicle_raptor_respawntime;
-float autocvar_g_vehicle_raptor_takeofftime;
-
-float autocvar_g_vehicle_raptor_movestyle;
-float autocvar_g_vehicle_raptor_turnspeed;
-float autocvar_g_vehicle_raptor_pitchspeed;
-float autocvar_g_vehicle_raptor_pitchlimit;
-
-float autocvar_g_vehicle_raptor_speed_forward;
-float autocvar_g_vehicle_raptor_speed_strafe;
-float autocvar_g_vehicle_raptor_speed_up;
-float autocvar_g_vehicle_raptor_speed_down;
-float autocvar_g_vehicle_raptor_friction;
-
-float autocvar_g_vehicle_raptor_bomblets;
-float autocvar_g_vehicle_raptor_bomblet_alt;
-float autocvar_g_vehicle_raptor_bomblet_time;
-float autocvar_g_vehicle_raptor_bomblet_damage;
-float autocvar_g_vehicle_raptor_bomblet_spread;
-float autocvar_g_vehicle_raptor_bomblet_edgedamage;
-float autocvar_g_vehicle_raptor_bomblet_radius;
-float autocvar_g_vehicle_raptor_bomblet_force;
-float autocvar_g_vehicle_raptor_bomblet_explode_delay;
-float autocvar_g_vehicle_raptor_bombs_refire;
-
-float autocvar_g_vehicle_raptor_flare_refire;
-float autocvar_g_vehicle_raptor_flare_lifetime;
-float autocvar_g_vehicle_raptor_flare_chase;
-float autocvar_g_vehicle_raptor_flare_range;
-
-float autocvar_g_vehicle_raptor_cannon_turnspeed;
-float autocvar_g_vehicle_raptor_cannon_turnlimit;
-float autocvar_g_vehicle_raptor_cannon_pitchlimit_up;
-float autocvar_g_vehicle_raptor_cannon_pitchlimit_down;
-
-float autocvar_g_vehicle_raptor_cannon_locktarget;
-float autocvar_g_vehicle_raptor_cannon_locking_time;
-float autocvar_g_vehicle_raptor_cannon_locking_releasetime;
-float autocvar_g_vehicle_raptor_cannon_locked_time;
-float autocvar_g_vehicle_raptor_cannon_predicttarget;
-
-float autocvar_g_vehicle_raptor_cannon_cost;
-float autocvar_g_vehicle_raptor_cannon_damage;
-float autocvar_g_vehicle_raptor_cannon_radius;
-float autocvar_g_vehicle_raptor_cannon_refire;
-float autocvar_g_vehicle_raptor_cannon_speed;
-float autocvar_g_vehicle_raptor_cannon_spread;
-float autocvar_g_vehicle_raptor_cannon_force;
-
-float autocvar_g_vehicle_raptor_energy;
-float autocvar_g_vehicle_raptor_energy_regen;
-float autocvar_g_vehicle_raptor_energy_regen_pause;
-
-float autocvar_g_vehicle_raptor_health;
-float autocvar_g_vehicle_raptor_health_regen;
-float autocvar_g_vehicle_raptor_health_regen_pause;
-
-float autocvar_g_vehicle_raptor_shield;
-float autocvar_g_vehicle_raptor_shield_regen;
-float autocvar_g_vehicle_raptor_shield_regen_pause;
-
-float autocvar_g_vehicle_raptor_bouncefactor;
-float autocvar_g_vehicle_raptor_bouncestop;
-vector autocvar_g_vehicle_raptor_bouncepain;
-
-.entity bomb1;
-.entity bomb2;
-
-float raptor_altitude(float amax)
-{
- tracebox(self.origin, self.mins, self.maxs, self.origin - ('0 0 1' * amax), MOVE_WORLDONLY, self);
- return vlen(self.origin - trace_endpos);
-}
-
-void raptor_bomblet_boom()
-{
- RadiusDamage (self, self.realowner, autocvar_g_vehicle_raptor_bomblet_damage,
- autocvar_g_vehicle_raptor_bomblet_edgedamage,
- autocvar_g_vehicle_raptor_bomblet_radius, world, world,
- autocvar_g_vehicle_raptor_bomblet_force, DEATH_VH_RAPT_BOMB, world);
- remove(self);
-}
-
-void raptor_bomblet_touch()
-{
- if(other == self.owner)
- return;
-
- PROJECTILE_TOUCH;
- self.think = raptor_bomblet_boom;
- self.nextthink = time + random() * autocvar_g_vehicle_raptor_bomblet_explode_delay;
-}
-
-void raptor_bomb_burst()
-{
- if(self.cnt > time)
- if(autocvar_g_vehicle_raptor_bomblet_alt)
- {
- self.nextthink = time;
- traceline(self.origin, self.origin + (normalize(self.velocity) * autocvar_g_vehicle_raptor_bomblet_alt), MOVE_NORMAL, self);
- if((trace_fraction == 1.0) || (vlen(self.origin - self.owner.origin) < autocvar_g_vehicle_raptor_bomblet_radius))
- {
- UpdateCSQCProjectile(self);
- return;
- }
- }
-
- entity bomblet;
- float i;
-
- Damage_DamageInfo(self.origin, 0, 0, 0, '0 0 0', DEATH_VH_RAPT_FRAGMENT, 0, self);
-
- for(i = 0; i < autocvar_g_vehicle_raptor_bomblets; ++i)
- {
- bomblet = spawn();
- setorigin(bomblet, self.origin);
-
- bomblet.movetype = MOVETYPE_TOSS;
- bomblet.touch = raptor_bomblet_touch;
- bomblet.think = raptor_bomblet_boom;
- bomblet.nextthink = time + 5;
- bomblet.owner = self.owner;
- bomblet.realowner = self.realowner;
- bomblet.velocity = normalize(normalize(self.velocity) + (randomvec() * autocvar_g_vehicle_raptor_bomblet_spread)) * vlen(self.velocity);
-
- PROJECTILE_MAKETRIGGER(bomblet);
- CSQCProjectile(bomblet, true, PROJECTILE_RAPTORBOMBLET, true);
- }
-
- remove(self);
-}
-
-void raptor_bombdrop()
-{
- entity bomb_1, bomb_2;
-
- bomb_1 = spawn();
- bomb_2 = spawn();
-
- setorigin(bomb_1, gettaginfo(self, gettagindex(self, "bombmount_left")));
- setorigin(bomb_2, gettaginfo(self, gettagindex(self, "bombmount_right")));
-
- bomb_1.movetype = bomb_2.movetype = MOVETYPE_BOUNCE;
- bomb_1.velocity = bomb_2.velocity = self.velocity;
- bomb_1.touch = bomb_2.touch = raptor_bomb_burst;
- bomb_1.think = bomb_2.think = raptor_bomb_burst;
- bomb_1.cnt = bomb_2.cnt = time + 10;
-
- if(autocvar_g_vehicle_raptor_bomblet_alt)
- bomb_1.nextthink = bomb_2.nextthink = time;
- else
- bomb_1.nextthink = bomb_2.nextthink = time + autocvar_g_vehicle_raptor_bomblet_time;
-
- bomb_1.owner = bomb_2.owner = self;
- bomb_1.realowner = bomb_2.realowner = self.owner;
- bomb_1.solid = bomb_2.solid = SOLID_BBOX;
- bomb_1.gravity = bomb_2.gravity = 1;
-
- PROJECTILE_MAKETRIGGER(bomb_1);
- PROJECTILE_MAKETRIGGER(bomb_2);
-
- CSQCProjectile(bomb_1, true, PROJECTILE_RAPTORBOMB, true);
- CSQCProjectile(bomb_2, true, PROJECTILE_RAPTORBOMB, true);
-}
-
-
-void raptor_fire_cannon(entity gun, string tagname)
-{
- vehicles_projectile(EFFECT_RAPTOR_MUZZLEFLASH.eent_eff_name, W_Sound("lasergun_fire"),
- gettaginfo(gun, gettagindex(gun, tagname)), normalize(v_forward + randomvec() * autocvar_g_vehicle_raptor_cannon_spread) * autocvar_g_vehicle_raptor_cannon_speed,
- autocvar_g_vehicle_raptor_cannon_damage, autocvar_g_vehicle_raptor_cannon_radius, autocvar_g_vehicle_raptor_cannon_force, 0,
- DEATH_VH_RAPT_CANNON, PROJECTILE_RAPTORCANNON, 0, true, true, self.owner);
-}
-
-void raptor_land()
-{
- float hgt;
-
- hgt = raptor_altitude(512);
- self.velocity = (self.velocity * 0.9) + ('0 0 -1800' * (hgt / 256) * sys_frametime);
- self.angles_x *= 0.95;
- self.angles_z *= 0.95;
-
- if(hgt < 128)
- if(hgt > 0)
- self.frame = (hgt / 128) * 25;
-
- self.bomb1.gun1.avelocity_y = 90 + ((self.frame / 25) * 2000);
- self.bomb1.gun2.avelocity_y = -self.bomb1.gun1.avelocity_y;
-
- if(hgt < 16)
- {
- self.movetype = MOVETYPE_TOSS;
- self.think = vehicles_think;
- self.frame = 0;
- }
-
- self.nextthink = time;
-
- CSQCMODEL_AUTOUPDATE();
-}
-
-void raptor_exit(float eject)
-{
- vector spot;
- self.tur_head.exteriormodeltoclient = world;
-
- if(self.deadflag == DEAD_NO)
- {
- self.think = raptor_land;
- self.nextthink = time;
- }
-
- if(!self.owner)
- return;
-
- makevectors(self.angles);
- if(eject)
- {
- spot = self.origin + v_forward * 100 + '0 0 64';
- spot = vehicles_findgoodexit(spot);
- setorigin(self.owner , spot);
- self.owner.velocity = (v_up + v_forward * 0.25) * 750;
- self.owner.oldvelocity = self.owner.velocity;
- }
- else
- {
- if(vlen(self.velocity) > 2 * autocvar_sv_maxairspeed)
- {
- self.owner.velocity = normalize(self.velocity) * autocvar_sv_maxairspeed * 2;
- self.owner.velocity_z += 200;
- spot = self.origin + v_forward * 32 + '0 0 64';
- spot = vehicles_findgoodexit(spot);
- }
- else
- {
- self.owner.velocity = self.velocity * 0.5;
- self.owner.velocity_z += 10;
- spot = self.origin - v_forward * 200 + '0 0 64';
- spot = vehicles_findgoodexit(spot);
- }
- self.owner.oldvelocity = self.owner.velocity;
- setorigin(self.owner , spot);
- }
-
- antilag_clear(self.owner);
- self.owner = world;
-}
-
-void raptor_flare_touch()
-{
- remove(self);
-}
-
-void raptor_flare_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
- self.health -= damage;
- if(self.health <= 0)
- remove(self);
-}
-
-void raptor_flare_think()
-{
- self.nextthink = time + 0.1;
- entity _missile = findchainentity(enemy, self.owner);
- while(_missile)
- {
- if(_missile.flags & FL_PROJECTILE)
- if(vlen(self.origin - _missile.origin) < autocvar_g_vehicle_raptor_flare_range)
- if(random() > autocvar_g_vehicle_raptor_flare_chase)
- _missile.enemy = self;
- _missile = _missile.chain;
- }
-
- if(self.tur_impacttime < time)
- remove(self);
-}
-
-float raptor_frame()
-{
- entity player, raptor;
- float ftmp = 0;
- vector df;
-
- if(intermission_running)
- {
- self.vehicle.velocity = '0 0 0';
- self.vehicle.avelocity = '0 0 0';
- return 1;
- }
-
- player = self;
- raptor = self.vehicle;
- self = raptor;
-
- vehicles_painframe();
- /*
- ftmp = vlen(self.velocity);
- if(ftmp > autocvar_g_vehicle_raptor_speed_forward)
- ftmp = 1;
- else
- ftmp = ftmp / autocvar_g_vehicle_raptor_speed_forward;
- */
-
- if(self.sound_nexttime < time)
- {
- self.sound_nexttime = time + 7.955812;
- //sound (self.tur_head, CH_TRIGGER_SINGLE, "vehicles/raptor_fly.wav", 1 - ftmp, ATTEN_NORM );
- sound (self, CH_TRIGGER_SINGLE, "vehicles/raptor_speed.wav", 1, ATTEN_NORM);
- self.wait = ftmp;
- }
- /*
- else if(fabs(ftmp - self.wait) > 0.2)
- {
- sound (self.tur_head, CH_TRIGGER_SINGLE, "", 1 - ftmp, ATTEN_NORM );
- sound (self, CH_TRIGGER_SINGLE, "", ftmp, ATTEN_NORM);
- self.wait = ftmp;
- }
- */
-
- if(raptor.deadflag != DEAD_NO)
- {
- self = player;
- player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
- return 1;
- }
- crosshair_trace(player);
-
- //if(time - self.lastteleporttime < 1)
- //{
- if(raptor.angles_z > 50 || raptor.angles_z < -50)
- {
- if(player.BUTTON_JUMP)
- {
- player.BUTTON_CROUCH = true;
- player.BUTTON_JUMP = false;
- }
- }
- //}
-
- vector vang;
- vang = raptor.angles;
- df = vectoangles(normalize(trace_endpos - self.origin + '0 0 32'));
- vang_x *= -1;
- df_x *= -1;
- if(df_x > 180) df_x -= 360;
- if(df_x < -180) df_x += 360;
- if(df_y > 180) df_y -= 360;
- if(df_y < -180) df_y += 360;
-
- ftmp = shortangle_f(player.v_angle_y - vang_y, vang_y);
- if(ftmp > 180) ftmp -= 360; if(ftmp < -180) ftmp += 360;
- raptor.avelocity_y = bound(-autocvar_g_vehicle_raptor_turnspeed, ftmp + raptor.avelocity_y * 0.9, autocvar_g_vehicle_raptor_turnspeed);
-
- // Pitch
- ftmp = 0;
- if(player.movement_x > 0 && vang_x < autocvar_g_vehicle_raptor_pitchlimit) ftmp = 5;
- else if(player.movement_x < 0 && vang_x > -autocvar_g_vehicle_raptor_pitchlimit) ftmp = -20;
-
- df_x = bound(-autocvar_g_vehicle_raptor_pitchlimit, df_x , autocvar_g_vehicle_raptor_pitchlimit);
- ftmp = vang_x - bound(-autocvar_g_vehicle_raptor_pitchlimit, df_x + ftmp, autocvar_g_vehicle_raptor_pitchlimit);
- raptor.avelocity_x = bound(-autocvar_g_vehicle_raptor_pitchspeed, ftmp + raptor.avelocity_x * 0.9, autocvar_g_vehicle_raptor_pitchspeed);
-
- raptor.angles_x = anglemods(raptor.angles_x);
- raptor.angles_y = anglemods(raptor.angles_y);
- raptor.angles_z = anglemods(raptor.angles_z);
-
- if(autocvar_g_vehicle_raptor_movestyle == 1)
- makevectors('0 1 0' * raptor.angles_y);
- else
- makevectors(player.v_angle);
-
- df = raptor.velocity * -autocvar_g_vehicle_raptor_friction;
-
- if(player.movement_x != 0)
- {
- if(player.movement_x > 0)
- df += v_forward * autocvar_g_vehicle_raptor_speed_forward;
- else if(player.movement_x < 0)
- df -= v_forward * autocvar_g_vehicle_raptor_speed_forward;
- }
-
- if(player.movement_y != 0)
- {
- if(player.movement_y < 0)
- df -= v_right * autocvar_g_vehicle_raptor_speed_strafe;
- else if(player.movement_y > 0)
- df += v_right * autocvar_g_vehicle_raptor_speed_strafe;
-
- raptor.angles_z = bound(-30,raptor.angles_z + (player.movement_y / autocvar_g_vehicle_raptor_speed_strafe),30);
- }
- else
- {
- raptor.angles_z *= 0.95;
- if(raptor.angles_z >= -1 && raptor.angles_z <= -1)
- raptor.angles_z = 0;
- }
-
- if(player.BUTTON_CROUCH)
- df -= v_up * autocvar_g_vehicle_raptor_speed_down;
- else if (player.BUTTON_JUMP)
- df += v_up * autocvar_g_vehicle_raptor_speed_up;
-
- raptor.velocity += df * frametime;
- player.velocity = player.movement = raptor.velocity;
- setorigin(player, raptor.origin + '0 0 32');
-
- player.vehicle_weapon2mode = raptor.vehicle_weapon2mode;
-
- vector vf, ad;
- // Target lock & predict
- if(autocvar_g_vehicle_raptor_cannon_locktarget == 2)
- {
- if(raptor.gun1.lock_time < time || raptor.gun1.enemy.deadflag)
- raptor.gun1.enemy = world;
-
- if(trace_ent)
- if(trace_ent.movetype)
- if(trace_ent.takedamage)
- if(!trace_ent.deadflag)
- {
- if(teamplay)
- {
- if(trace_ent.team != player.team)
- {
- raptor.gun1.enemy = trace_ent;
- raptor.gun1.lock_time = time + 5;
- }
- }
- else
- {
- raptor.gun1.enemy = trace_ent;
- raptor.gun1.lock_time = time + 0.5;
- }
- }
-
- if(raptor.gun1.enemy)
- {
- float distance, impact_time;
-
- vf = real_origin(raptor.gun1.enemy);
- UpdateAuxiliaryXhair(player, vf, '1 0 0', 1);
- vector _vel = raptor.gun1.enemy.velocity;
- if(raptor.gun1.enemy.movetype == MOVETYPE_WALK)
- _vel_z *= 0.1;
-
- if(autocvar_g_vehicle_raptor_cannon_predicttarget)
- {
- ad = vf;
- distance = vlen(ad - player.origin);
- impact_time = distance / autocvar_g_vehicle_raptor_cannon_speed;
- ad = vf + _vel * impact_time;
- trace_endpos = ad;
- }
- else
- trace_endpos = vf;
- }
- }
- else if(autocvar_g_vehicle_raptor_cannon_locktarget == 1)
- {
-
- vehicles_locktarget((1 / autocvar_g_vehicle_raptor_cannon_locking_time) * frametime,
- (1 / autocvar_g_vehicle_raptor_cannon_locking_releasetime) * frametime,
- autocvar_g_vehicle_raptor_cannon_locked_time);
-
- if(self.lock_target != world)
- if(autocvar_g_vehicle_raptor_cannon_predicttarget)
- if(self.lock_strength == 1)
- {
- float i, distance, impact_time;
-
- vf = real_origin(raptor.lock_target);
- ad = vf;
- for(i = 0; i < 4; ++i)
- {
- distance = vlen(ad - raptor.origin);
- impact_time = distance / autocvar_g_vehicle_raptor_cannon_speed;
- ad = vf + raptor.lock_target.velocity * impact_time;
- }
- trace_endpos = ad;
- }
-
- if(self.lock_target)
- {
- if(raptor.lock_strength == 1)
- UpdateAuxiliaryXhair(player, real_origin(raptor.lock_target), '1 0 0', 1);
- else if(self.lock_strength > 0.5)
- UpdateAuxiliaryXhair(player, real_origin(raptor.lock_target), '0 1 0', 1);
- else if(self.lock_strength < 0.5)
- UpdateAuxiliaryXhair(player, real_origin(raptor.lock_target), '0 0 1', 1);
- }
- }
-
-
- vehicle_aimturret(raptor, trace_endpos, raptor.gun1, "fire1",
- autocvar_g_vehicle_raptor_cannon_pitchlimit_down * -1, autocvar_g_vehicle_raptor_cannon_pitchlimit_up,
- autocvar_g_vehicle_raptor_cannon_turnlimit * -1, autocvar_g_vehicle_raptor_cannon_turnlimit, autocvar_g_vehicle_raptor_cannon_turnspeed);
-
- vehicle_aimturret(raptor, trace_endpos, raptor.gun2, "fire1",
- autocvar_g_vehicle_raptor_cannon_pitchlimit_down * -1, autocvar_g_vehicle_raptor_cannon_pitchlimit_up,
- autocvar_g_vehicle_raptor_cannon_turnlimit * -1, autocvar_g_vehicle_raptor_cannon_turnlimit, autocvar_g_vehicle_raptor_cannon_turnspeed);
-
- /*
- ad = ad * 0.5;
- v_forward = vf * 0.5;
- traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, raptor);
- UpdateAuxiliaryXhair(player, trace_endpos, '0 1 0', 0);
- */
-
- if(!forbidWeaponUse(player))
- if(player.BUTTON_ATCK)
- if(raptor.attack_finished_single <= time)
- if(raptor.vehicle_energy > autocvar_g_vehicle_raptor_cannon_cost)
- {
- raptor.misc_bulletcounter += 1;
- raptor.attack_finished_single = time + autocvar_g_vehicle_raptor_cannon_refire;
- if(raptor.misc_bulletcounter <= 2)
- raptor_fire_cannon(self.gun1, "fire1");
- else if(raptor.misc_bulletcounter == 3)
- raptor_fire_cannon(self.gun2, "fire1");
- else
- {
- raptor.attack_finished_single = time + autocvar_g_vehicle_raptor_cannon_refire * 2;
- raptor_fire_cannon(self.gun2, "fire1");
- raptor.misc_bulletcounter = 0;
- }
- raptor.vehicle_energy -= autocvar_g_vehicle_raptor_cannon_cost;
- self.cnt = time;
- }
-
- if(self.vehicle_flags & VHF_SHIELDREGEN)
- vehicles_regen(raptor.dmg_time, vehicle_shield, autocvar_g_vehicle_raptor_shield, autocvar_g_vehicle_raptor_shield_regen_pause, autocvar_g_vehicle_raptor_shield_regen, frametime, true);
-
- if(self.vehicle_flags & VHF_HEALTHREGEN)
- vehicles_regen(raptor.dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, frametime, false);
-
- if(self.vehicle_flags & VHF_ENERGYREGEN)
- vehicles_regen(raptor.cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, frametime, false);
-
- if(!forbidWeaponUse(player))
- if(raptor.vehicle_weapon2mode == RSM_BOMB)
- {
- if(time > raptor.lip + autocvar_g_vehicle_raptor_bombs_refire)
- if(player.BUTTON_ATCK2)
- {
- raptor_bombdrop();
- raptor.delay = time + autocvar_g_vehicle_raptor_bombs_refire;
- raptor.lip = time;
- }
- }
- else
- {
- if(time > raptor.lip + autocvar_g_vehicle_raptor_flare_refire)
- if(player.BUTTON_ATCK2)
- {
- float i;
- entity _flare;
-
- for(i = 0; i < 3; ++i)
- {
- _flare = spawn();
- setmodel(_flare, "models/runematch/rune.mdl");
- _flare.effects = EF_LOWPRECISION | EF_FLAME;
- _flare.scale = 0.5;
- setorigin(_flare, self.origin - '0 0 16');
- _flare.movetype = MOVETYPE_TOSS;
- _flare.gravity = 0.15;
- _flare.velocity = 0.25 * raptor.velocity + (v_forward + randomvec() * 0.25)* -500;
- _flare.think = raptor_flare_think;
- _flare.nextthink = time;
- _flare.owner = raptor;
- _flare.solid = SOLID_CORPSE;
- _flare.takedamage = DAMAGE_YES;
- _flare.event_damage = raptor_flare_damage;
- _flare.health = 20;
- _flare.tur_impacttime = time + autocvar_g_vehicle_raptor_flare_lifetime;
- _flare.touch = raptor_flare_touch;
- }
- raptor.delay = time + autocvar_g_vehicle_raptor_flare_refire;
- raptor.lip = time;
- }
- }
-
- raptor.bomb1.alpha = raptor.bomb2.alpha = (time - raptor.lip) / (raptor.delay - raptor.lip);
- player.vehicle_reload2 = bound(0, raptor.bomb1.alpha * 100, 100);
- player.vehicle_ammo2 = (player.vehicle_reload2 == 100) ? 100 : 0;
-
- if(self.bomb1.cnt < time)
- {
- entity _missile = findchainentity(enemy, raptor);
- float _incomming = 0;
- while(_missile)
- {
- if(_missile.flags & FL_PROJECTILE)
- if(MISSILE_IS_TRACKING(_missile))
- if(vlen(self.origin - _missile.origin) < 2 * autocvar_g_vehicle_raptor_flare_range)
- ++_incomming;
-
- _missile = _missile.chain;
- }
-
- if(_incomming)
- sound(self, CH_PAIN_SINGLE, "vehicles/missile_alarm.wav", VOL_BASE, ATTEN_NONE);
-
- self.bomb1.cnt = time + 1;
- }
-
-
- VEHICLE_UPDATE_PLAYER(player, health, raptor);
- VEHICLE_UPDATE_PLAYER(player, energy, raptor);
- if(self.vehicle_flags & VHF_HASSHIELD)
- VEHICLE_UPDATE_PLAYER(player, shield, raptor);
-
- player.BUTTON_ATCK = player.BUTTON_ATCK2 = player.BUTTON_CROUCH = 0;
-
- self = player;
- return 1;
-}
-
-float raptor_takeoff()
-{
- entity player, raptor;
-
- player = self;
- raptor = self.vehicle;
- self = raptor;
-
- self.nextthink = time;
- CSQCMODEL_AUTOUPDATE();
- self.nextthink = 0; // will this work?
-
- if(self.sound_nexttime < time)
- {
- self.sound_nexttime = time + 7.955812; //soundlength("vehicles/raptor_fly.wav");
- sound (self, CH_TRIGGER_SINGLE, "vehicles/raptor_speed.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
- }
-
- // Takeoff sequense
- if(raptor.frame < 25)
- {
- raptor.frame += 25 / (autocvar_g_vehicle_raptor_takeofftime / sys_frametime);
- raptor.velocity_z = min(raptor.velocity_z * 1.5, 256);
- self.bomb1.gun1.avelocity_y = 90 + ((raptor.frame / 25) * 25000);
- self.bomb1.gun2.avelocity_y = -self.bomb1.gun1.avelocity_y;
- player.BUTTON_ATCK = player.BUTTON_ATCK2 = player.BUTTON_CROUCH = 0;
-
- setorigin(player, raptor.origin + '0 0 32');
- }
- else
- player.PlayerPhysplug = raptor_frame;
-
- if(self.vehicle_flags & VHF_SHIELDREGEN)
- vehicles_regen(raptor.dmg_time, vehicle_shield, autocvar_g_vehicle_raptor_shield, autocvar_g_vehicle_raptor_shield_regen_pause, autocvar_g_vehicle_raptor_shield_regen, frametime, true);
-
- if(self.vehicle_flags & VHF_HEALTHREGEN)
- vehicles_regen(raptor.dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, frametime, false);
-
- if(self.vehicle_flags & VHF_ENERGYREGEN)
- vehicles_regen(raptor.cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, frametime, false);
-
-
- raptor.bomb1.alpha = raptor.bomb2.alpha = (time - raptor.lip) / (raptor.delay - raptor.lip);
- player.vehicle_reload2 = bound(0, raptor.bomb1.alpha * 100, 100);
- player.vehicle_ammo2 = (player.vehicle_reload2 == 100) ? 100 : 0;
-
- VEHICLE_UPDATE_PLAYER(player, health, raptor);
- VEHICLE_UPDATE_PLAYER(player, energy, raptor);
- if(self.vehicle_flags & VHF_HASSHIELD)
- VEHICLE_UPDATE_PLAYER(player, shield, raptor);
-
- player.BUTTON_ATCK = player.BUTTON_ATCK2 = player.BUTTON_CROUCH = 0;
- self = player;
- return 1;
-}
-
-void raptor_blowup()
-{
- self.deadflag = DEAD_DEAD;
- self.vehicle_exit(VHEF_NORMAL);
- RadiusDamage (self, self.enemy, 250, 15, 250, world, world, 250, DEATH_VH_RAPT_DEATH, world);
-
- self.alpha = -1;
- self.movetype = MOVETYPE_NONE;
- self.effects = EF_NODRAW;
- self.colormod = '0 0 0';
- self.avelocity = '0 0 0';
- self.velocity = '0 0 0';
-
- setorigin(self, self.pos1);
- self.touch = func_null;
- self.nextthink = 0;
-}
-
-void raptor_diethink()
-{
- if(time >= self.wait)
- self.think = raptor_blowup;
-
- if(random() < 0.05)
- {
- sound (self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
- Send_Effect(EFFECT_EXPLOSION_SMALL, randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
- }
- self.nextthink = time;
-
- CSQCMODEL_AUTOUPDATE();
-}
-
-// If we dont do this ever now and then, the raptors rotors
-// stop working, presumably due to angle overflow. cute.
-void raptor_rotor_anglefix()
-{
- self.gun1.angles_y = anglemods(self.gun1.angles_y);
- self.gun2.angles_y = anglemods(self.gun2.angles_y);
- self.nextthink = time + 15;
-}
-
-float raptor_impulse(float _imp)
-{
- switch(_imp)
- {
- case 1:
- case 230:
- self.vehicle.vehicle_weapon2mode = RSM_BOMB;
- CSQCVehicleSetup(self, 0);
- return true;
- case 2:
- case 231:
- self.vehicle.vehicle_weapon2mode = RSM_FLARE;
- CSQCVehicleSetup(self, 0);
- return true;
-
- case 10:
- case 15:
- case 18:
- self.vehicle.vehicle_weapon2mode += 1;
- if(self.vehicle.vehicle_weapon2mode > RSM_LAST)
- self.vehicle.vehicle_weapon2mode = RSM_FIRST;
-
- CSQCVehicleSetup(self, 0);
- return true;
- case 11:
- case 12:
- case 16:
- case 19:
- self.vehicle.vehicle_weapon2mode -= 1;
- if(self.vehicle.vehicle_weapon2mode < RSM_FIRST)
- self.vehicle.vehicle_weapon2mode = RSM_LAST;
-
- CSQCVehicleSetup(self, 0);
- return true;
-
- /*
- case 17: // toss gun, could be used to exit?
- break;
- case 20: // Manual minigun reload?
- break;
- */
- }
- return false;
-}
-
-void spawnfunc_vehicle_raptor()
-{
- if(!autocvar_g_vehicle_raptor) { remove(self); return; }
- if(!vehicle_initialize(VEH_RAPTOR, false)) { remove(self); return; }
-}
-
-float v_raptor(float req)
-{
- switch(req)
- {
- case VR_IMPACT:
- {
- if(autocvar_g_vehicle_raptor_bouncepain)
- vehicles_impact(autocvar_g_vehicle_raptor_bouncepain_x, autocvar_g_vehicle_raptor_bouncepain_y, autocvar_g_vehicle_raptor_bouncepain_z);
-
- return true;
- }
- case VR_ENTER:
- {
- self.vehicle_weapon2mode = RSM_BOMB;
- self.owner.PlayerPhysplug = raptor_takeoff;
- self.movetype = MOVETYPE_BOUNCEMISSILE;
- self.solid = SOLID_SLIDEBOX;
- self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_raptor_health) * 100;
- self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_raptor_shield) * 100;
- self.velocity_z = 1; // Nudge upwards to takeoff sequense can work.
- self.tur_head.exteriormodeltoclient = self.owner;
-
- self.delay = time + autocvar_g_vehicle_raptor_bombs_refire;
- self.lip = time;
-
- if(self.owner.flagcarried)
- setorigin(self.owner.flagcarried, '-20 0 96');
-
- CSQCVehicleSetup(self.owner, 0);
- return true;
- }
- case VR_THINK:
- {
- return true;
- }
- case VR_DEATH:
- {
- self.health = 0;
- self.event_damage = func_null;
- self.solid = SOLID_CORPSE;
- self.takedamage = DAMAGE_NO;
- self.deadflag = DEAD_DYING;
- self.movetype = MOVETYPE_BOUNCE;
- self.think = raptor_diethink;
- self.nextthink = time;
- self.wait = time + 5 + (random() * 5);
-
- Send_Effect(EFFECT_EXPLOSION_MEDIUM, findbetterlocation (self.origin, 16), '0 0 0', 1);
-
- self.velocity_z += 600;
-
- self.avelocity = '0 0.5 1' * (random() * 400);
- self.avelocity -= '0 0.5 1' * (random() * 400);
-
- self.colormod = '-0.5 -0.5 -0.5';
- self.touch = raptor_blowup;
- return true;
- }
- case VR_SPAWN:
- {
- if(!self.gun1)
- {
- entity spinner;
- vector ofs;
-
- //FIXME: Camera is in a bad place in HUD model.
- //setorigin(self.vehicle_viewport, '25 0 5');
-
- self.vehicles_impulse = raptor_impulse;
-
- self.frame = 0;
-
- self.bomb1 = spawn();
- self.bomb2 = spawn();
- self.gun1 = spawn();
- self.gun2 = spawn();
-
- setmodel(self.bomb1,"models/vehicles/clusterbomb_folded.md3");
- setmodel(self.bomb2,"models/vehicles/clusterbomb_folded.md3");
- setmodel(self.gun1, "models/vehicles/raptor_gun.dpm");
- setmodel(self.gun2, "models/vehicles/raptor_gun.dpm");
- setmodel(self.tur_head, "models/vehicles/raptor_body.dpm");
-
- setattachment(self.bomb1, self, "bombmount_left");
- setattachment(self.bomb2, self, "bombmount_right");
- setattachment(self.tur_head, self,"root");
-
- // FIXMODEL Guns mounts to angled bones
- self.bomb1.angles = self.angles;
- self.angles = '0 0 0';
- // This messes up gun-aim, so work arround it.
- //setattachment(self.gun1, self, "gunmount_left");
- ofs = gettaginfo(self, gettagindex(self, "gunmount_left"));
- ofs -= self.origin;
- setattachment(self.gun1, self, "");
- setorigin(self.gun1, ofs);
-
- //setattachment(self.gun2, self, "gunmount_right");
- ofs = gettaginfo(self, gettagindex(self, "gunmount_right"));
- ofs -= self.origin;
- setattachment(self.gun2, self, "");
- setorigin(self.gun2, ofs);
-
- self.angles = self.bomb1.angles;
- self.bomb1.angles = '0 0 0';
-
- spinner = spawn();
- spinner.owner = self;
- setmodel(spinner,"models/vehicles/spinner.dpm");
- setattachment(spinner, self, "engine_left");
- spinner.movetype = MOVETYPE_NOCLIP;
- spinner.avelocity = '0 90 0';
- self.bomb1.gun1 = spinner;
-
- spinner = spawn();
- spinner.owner = self;
- setmodel(spinner,"models/vehicles/spinner.dpm");
- setattachment(spinner, self, "engine_right");
- spinner.movetype = MOVETYPE_NOCLIP;
- spinner.avelocity = '0 -90 0';
- self.bomb1.gun2 = spinner;
-
- // Sigh.
- self.bomb1.think = raptor_rotor_anglefix;
- self.bomb1.nextthink = time;
-
- self.mass = 1 ;
- }
-
- self.frame = 0;
- self.vehicle_health = autocvar_g_vehicle_raptor_health;
- self.vehicle_shield = autocvar_g_vehicle_raptor_shield;
- self.movetype = MOVETYPE_TOSS;
- self.solid = SOLID_SLIDEBOX;
- self.vehicle_energy = 1;
-
- self.PlayerPhysplug = raptor_frame;
-
- self.bomb1.gun1.avelocity_y = 90;
- self.bomb1.gun2.avelocity_y = -90;
-
- self.delay = time;
-
- self.bouncefactor = autocvar_g_vehicle_raptor_bouncefactor;
- self.bouncestop = autocvar_g_vehicle_raptor_bouncestop;
- self.damageforcescale = 0.25;
- self.vehicle_health = autocvar_g_vehicle_raptor_health;
- self.vehicle_shield = autocvar_g_vehicle_raptor_shield;
- return true;
- }
- case VR_SETUP:
- {
- if(autocvar_g_vehicle_raptor_shield)
- self.vehicle_flags |= VHF_HASSHIELD;
-
- if(autocvar_g_vehicle_raptor_shield_regen)
- self.vehicle_flags |= VHF_SHIELDREGEN;
-
- if(autocvar_g_vehicle_raptor_health_regen)
- self.vehicle_flags |= VHF_HEALTHREGEN;
-
- if(autocvar_g_vehicle_raptor_energy_regen)
- self.vehicle_flags |= VHF_ENERGYREGEN;
-
- self.vehicle_exit = raptor_exit;
- self.respawntime = autocvar_g_vehicle_raptor_respawntime;
- self.vehicle_health = autocvar_g_vehicle_raptor_health;
- self.vehicle_shield = autocvar_g_vehicle_raptor_shield;
- self.max_health = self.vehicle_health;
-
- return true;
- }
- case VR_PRECACHE:
- {
- precache_model ("models/vehicles/raptor.dpm");
- precache_model ("models/vehicles/raptor_gun.dpm");
- precache_model ("models/vehicles/spinner.dpm");
- precache_model ("models/vehicles/raptor_cockpit.dpm");
- precache_model ("models/vehicles/clusterbomb_folded.md3");
- precache_model ("models/vehicles/raptor_body.dpm");
-
- precache_sound ("vehicles/raptor_fly.wav");
- precache_sound ("vehicles/raptor_speed.wav");
- precache_sound ("vehicles/missile_alarm.wav");
-
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-
-void RaptorCBShellfragDraw()
-{
- if(wasfreed(self))
- return;
-
- Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
- self.move_avelocity += randomvec() * 15;
- self.renderflags = 0;
-
- if(self.cnt < time)
- self.alpha = bound(0, self.nextthink - time, 1);
-
- if(self.alpha < ALPHA_MIN_VISIBLE)
- remove(self);
-}
-
-void RaptorCBShellfragToss(vector _org, vector _vel, vector _ang)
-{
- entity sfrag;
-
- sfrag = spawn();
- setmodel(sfrag, "models/vehicles/clusterbomb_fragment.md3");
- setorigin(sfrag, _org);
-
- sfrag.move_movetype = MOVETYPE_BOUNCE;
- sfrag.gravity = 0.15;
- sfrag.solid = SOLID_CORPSE;
-
- sfrag.draw = RaptorCBShellfragDraw;
-
- sfrag.move_origin = sfrag.origin = _org;
- sfrag.move_velocity = _vel;
- sfrag.move_avelocity = prandomvec() * vlen(sfrag.move_velocity);
- sfrag.angles = self.move_angles = _ang;
-
- sfrag.move_time = time;
- sfrag.damageforcescale = 4;
-
- sfrag.nextthink = time + 3;
- sfrag.cnt = time + 2;
- sfrag.alpha = 1;
- sfrag.drawmask = MASK_NORMAL;
-}
-
-float v_raptor(float req)
-{
- switch(req)
- {
- case VR_HUD:
- {
- string crosshair;
-
- switch(weapon2mode)
- {
- case RSM_FLARE: crosshair = vCROSS_RAIN; break;
- case RSM_BOMB: crosshair = vCROSS_BURST; break;
- default: crosshair = vCROSS_BURST;
- }
-
- Vehicles_drawHUD(VEH_RAPTOR.m_icon, "vehicle_raptor_weapon1", "vehicle_raptor_weapon2",
- "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
- "vehicle_icon_ammo2", autocvar_hud_progressbar_vehicles_ammo2_color,
- crosshair);
- return true;
- }
- case VR_SETUP:
- {
- AuxiliaryXhair[1].axh_image = vCROSS_LOCK;
- return true;
- }
- case VR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_VEHICLE
+++ /dev/null
-#ifndef RAPTOR_H
-#define RAPTOR_H
-
-const int RSM_FIRST = 1;
-const int RSM_BOMB = 1;
-const int RSM_FLARE = 2;
-const int RSM_LAST = 2;
-
-#endif
+++ /dev/null
-#ifndef VEHICLE_SPIDERBOT
-#define VEHICLE_SPIDERBOT
-#ifndef MENUQC
-int v_spiderbot(int);
-#endif
-REGISTER_VEHICLE_SIMPLE(
-/* VEH_##id */ SPIDERBOT,
-/* spawnflags */ VHF_DMGSHAKE,
-/* mins,maxs */ '-75 -75 10', '75 75 125',
-/* model */ "models/vehicles/spiderbot.dpm",
-/* head_model */ "models/vehicles/spiderbot_top.dpm",
-/* hud_model */ "models/vehicles/spiderbot_cockpit.dpm",
-/* tags */ "tag_head", "tag_hud", "",
-/* netname */ "spiderbot",
-/* fullname */ _("Spiderbot")
-) {
- this.m_icon = "vehicle_spider";
-#ifndef MENUQC
- this.vehicle_func = v_spiderbot;
-#endif
-}
-#endif
-
-#ifdef IMPLEMENTATION
-
-const int SBRM_FIRST = 1;
-const int SBRM_VOLLY = 1;
-const int SBRM_GUIDE = 2;
-const int SBRM_ARTILLERY = 3;
-const int SBRM_LAST = 3;
-
-#ifdef SVQC
-bool autocvar_g_vehicle_spiderbot;
-
-float autocvar_g_vehicle_spiderbot_respawntime;
-
-float autocvar_g_vehicle_spiderbot_speed_stop;
-float autocvar_g_vehicle_spiderbot_speed_strafe;
-float autocvar_g_vehicle_spiderbot_speed_walk;
-float autocvar_g_vehicle_spiderbot_speed_run = 700;
-float autocvar_g_vehicle_spiderbot_turnspeed;
-float autocvar_g_vehicle_spiderbot_turnspeed_strafe;
-float autocvar_g_vehicle_spiderbot_movement_inertia;
-
-float autocvar_g_vehicle_spiderbot_springlength;
-float autocvar_g_vehicle_spiderbot_springup;
-float autocvar_g_vehicle_spiderbot_springblend;
-float autocvar_g_vehicle_spiderbot_tiltlimit;
-
-float autocvar_g_vehicle_spiderbot_head_pitchlimit_down;
-float autocvar_g_vehicle_spiderbot_head_pitchlimit_up;
-float autocvar_g_vehicle_spiderbot_head_turnlimit;
-float autocvar_g_vehicle_spiderbot_head_turnspeed;
-
-int autocvar_g_vehicle_spiderbot_health;
-float autocvar_g_vehicle_spiderbot_health_regen;
-float autocvar_g_vehicle_spiderbot_health_regen_pause;
-
-int autocvar_g_vehicle_spiderbot_shield;
-float autocvar_g_vehicle_spiderbot_shield_regen;
-float autocvar_g_vehicle_spiderbot_shield_regen_pause;
-
-float autocvar_g_vehicle_spiderbot_minigun_damage;
-float autocvar_g_vehicle_spiderbot_minigun_refire;
-float autocvar_g_vehicle_spiderbot_minigun_spread;
-int autocvar_g_vehicle_spiderbot_minigun_ammo_cost;
-int autocvar_g_vehicle_spiderbot_minigun_ammo_max;
-int autocvar_g_vehicle_spiderbot_minigun_ammo_regen;
-float autocvar_g_vehicle_spiderbot_minigun_ammo_regen_pause;
-float autocvar_g_vehicle_spiderbot_minigun_force;
-float autocvar_g_vehicle_spiderbot_minigun_solidpenetration;
-
-float autocvar_g_vehicle_spiderbot_rocket_damage;
-float autocvar_g_vehicle_spiderbot_rocket_force;
-float autocvar_g_vehicle_spiderbot_rocket_radius;
-float autocvar_g_vehicle_spiderbot_rocket_speed;
-float autocvar_g_vehicle_spiderbot_rocket_spread;
-float autocvar_g_vehicle_spiderbot_rocket_refire;
-float autocvar_g_vehicle_spiderbot_rocket_refire2;
-float autocvar_g_vehicle_spiderbot_rocket_reload;
-float autocvar_g_vehicle_spiderbot_rocket_health;
-float autocvar_g_vehicle_spiderbot_rocket_noise;
-float autocvar_g_vehicle_spiderbot_rocket_turnrate;
-float autocvar_g_vehicle_spiderbot_rocket_lifetime;
-
-vector autocvar_g_vehicle_spiderbot_bouncepain;
-
-void spiderbot_rocket_artillery()
-{
- self.nextthink = time;
- UpdateCSQCProjectile(self);
-}
-
-void spiderbot_rocket_unguided()
-{
- vector newdir, olddir;
-
- self.nextthink = time;
-
- olddir = normalize(self.velocity);
- newdir = normalize(self.pos1 - self.origin) + randomvec() * autocvar_g_vehicle_spiderbot_rocket_noise;
- self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_spiderbot_rocket_turnrate) * autocvar_g_vehicle_spiderbot_rocket_speed;
-
- UpdateCSQCProjectile(self);
-
- if (self.owner.deadflag != DEAD_NO || self.cnt < time || vlen(self.pos1 - self.origin) < 16)
- self.use();
-}
-
-void spiderbot_rocket_guided()
-{
- vector newdir, olddir;
-
- self.nextthink = time;
-
- if(!self.realowner.vehicle)
- self.think = spiderbot_rocket_unguided;
-
- crosshair_trace(self.realowner);
- olddir = normalize(self.velocity);
- newdir = normalize(trace_endpos - self.origin) + randomvec() * autocvar_g_vehicle_spiderbot_rocket_noise;
- self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_spiderbot_rocket_turnrate) * autocvar_g_vehicle_spiderbot_rocket_speed;
-
- UpdateCSQCProjectile(self);
-
- if (self.owner.deadflag != DEAD_NO || self.cnt < time)
- self.use();
-}
-
-void spiderbot_guide_release()
-{
- entity rkt;
- rkt = findchainentity(realowner, self.owner);
- if(!rkt)
- return;
-
- crosshair_trace(self.owner);
- while(rkt)
- {
- if(rkt.think == spiderbot_rocket_guided)
- {
- rkt.pos1 = trace_endpos;
- rkt.think = spiderbot_rocket_unguided;
- }
- rkt = rkt.chain;
- }
-}
-
-float spiberbot_calcartillery_flighttime;
-vector spiberbot_calcartillery(vector org, vector tgt, float ht)
-{
- float grav, sdist, zdist, vs, vz, jumpheight;
- vector sdir;
-
- grav = autocvar_sv_gravity;
- zdist = tgt_z - org_z;
- sdist = vlen(tgt - org - zdist * '0 0 1');
- sdir = normalize(tgt - org - zdist * '0 0 1');
-
- // how high do we need to go?
- jumpheight = fabs(ht);
- if(zdist > 0)
- jumpheight = jumpheight + zdist;
-
- // push so high...
- vz = sqrt(2 * grav * jumpheight); // NOTE: sqrt(positive)!
-
- // we start with downwards velocity only if it's a downjump and the jump apex should be outside the jump!
- if(ht < 0)
- if(zdist < 0)
- vz = -vz;
-
- vector solution;
- solution = solve_quadratic(0.5 * grav, -vz, zdist); // equation "z(ti) = zdist"
- // ALWAYS solvable because jumpheight >= zdist
- if(!solution_z)
- solution_y = solution_x; // just in case it is not solvable due to roundoff errors, assume two equal solutions at their center (this is mainly for the usual case with ht == 0)
- if(zdist == 0)
- solution_x = solution_y; // solution_x is 0 in this case, so don't use it, but rather use solution_y (which will be sqrt(0.5 * jumpheight / grav), actually)
-
- if(zdist < 0)
- {
- // down-jump
- if(ht < 0)
- {
- // almost straight line type
- // jump apex is before the jump
- // we must take the larger one
- spiberbot_calcartillery_flighttime = solution_y;
- }
- else
- {
- // regular jump
- // jump apex is during the jump
- // we must take the larger one too
- spiberbot_calcartillery_flighttime = solution_y;
- }
- }
- else
- {
- // up-jump
- if(ht < 0)
- {
- // almost straight line type
- // jump apex is after the jump
- // we must take the smaller one
- spiberbot_calcartillery_flighttime = solution_x;
- }
- else
- {
- // regular jump
- // jump apex is during the jump
- // we must take the larger one
- spiberbot_calcartillery_flighttime = solution_y;
- }
- }
- vs = sdist / spiberbot_calcartillery_flighttime;
-
- // finally calculate the velocity
- return sdir * vs + '0 0 1' * vz;
-}
-
-void spiderbot_rocket_do()
-{
- vector v;
- entity rocket = world;
-
- if (self.wait != -10)
- {
- if (self.owner.BUTTON_ATCK2 && self.vehicle_weapon2mode == SBRM_GUIDE)
- {
- if (self.wait == 1)
- if (self.tur_head.frame == 9 || self.tur_head.frame == 1)
- {
- if(self.gun2.cnt < time && self.tur_head.frame == 9)
- self.tur_head.frame = 1;
-
- return;
- }
- self.wait = 1;
- }
- else
- {
- if(self.wait)
- spiderbot_guide_release();
-
- self.wait = 0;
- }
- }
-
- if(self.gun2.cnt > time)
- return;
-
- if (self.tur_head.frame >= 9)
- {
- self.tur_head.frame = 1;
- self.wait = 0;
- }
-
- if(self.wait != -10)
- if(!self.owner.BUTTON_ATCK2)
- return;
-
- if(forbidWeaponUse(self.owner))
- return;
-
- v = gettaginfo(self.tur_head,gettagindex(self.tur_head,"tag_fire"));
-
- switch(self.vehicle_weapon2mode)
- {
- case SBRM_VOLLY:
- rocket = vehicles_projectile(EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, W_Sound("rocket_fire"),
- v, normalize(randomvec() * autocvar_g_vehicle_spiderbot_rocket_spread + v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
- autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
- DEATH_VH_SPID_ROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, true, self.owner);
- crosshair_trace(self.owner);
- float _dist = (random() * autocvar_g_vehicle_spiderbot_rocket_radius) + vlen(v - trace_endpos);
- _dist -= (random() * autocvar_g_vehicle_spiderbot_rocket_radius) ;
- rocket.nextthink = time + (_dist / autocvar_g_vehicle_spiderbot_rocket_speed);
- rocket.think = vehicles_projectile_explode;
-
- if(self.owner.BUTTON_ATCK2 && self.tur_head.frame == 1)
- self.wait = -10;
- break;
- case SBRM_GUIDE:
- rocket = vehicles_projectile(EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, W_Sound("rocket_fire"),
- v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
- autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
- DEATH_VH_SPID_ROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, false, self.owner);
- crosshair_trace(self.owner);
- rocket.pos1 = trace_endpos;
- rocket.nextthink = time;
- rocket.think = spiderbot_rocket_guided;
-
-
- break;
- case SBRM_ARTILLERY:
- rocket = vehicles_projectile(EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, W_Sound("rocket_fire"),
- v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
- autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
- DEATH_VH_SPID_ROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, true, self.owner);
-
- crosshair_trace(self.owner);
-
- rocket.pos1 = trace_endpos + randomvec() * (0.75 * autocvar_g_vehicle_spiderbot_rocket_radius);
- rocket.pos1_z = trace_endpos_z;
-
- traceline(v, v + '0 0 1' * MAX_SHOT_DISTANCE, MOVE_WORLDONLY, self);
- float h1 = 0.75 * vlen(v - trace_endpos);
-
- //v = trace_endpos;
- traceline(v , rocket.pos1 + '0 0 1' * MAX_SHOT_DISTANCE, MOVE_WORLDONLY, self);
- float h2 = 0.75 * vlen(rocket.pos1 - v);
-
- rocket.velocity = spiberbot_calcartillery(v, rocket.pos1, ((h1 < h2) ? h1 : h2));
- rocket.movetype = MOVETYPE_TOSS;
- rocket.gravity = 1;
- //rocket.think = spiderbot_rocket_artillery;
- break;
- }
- rocket.classname = "spiderbot_rocket";
-
- rocket.cnt = time + autocvar_g_vehicle_spiderbot_rocket_lifetime;
-
- self.tur_head.frame += 1;
- if (self.tur_head.frame == 9)
- self.attack_finished_single = autocvar_g_vehicle_spiderbot_rocket_reload;
- else
- self.attack_finished_single = ((self.vehicle_weapon2mode == SBRM_VOLLY) ? autocvar_g_vehicle_spiderbot_rocket_refire2 : autocvar_g_vehicle_spiderbot_rocket_refire);
-
- self.gun2.cnt = time + self.attack_finished_single;
-}
-
-.float jump_delay;
-float spiderbot_frame()
-{
- vector ad, vf;
- entity player, spider;
- float ftmp;
-
- if(intermission_running)
- {
- self.vehicle.velocity = '0 0 0';
- self.vehicle.avelocity = '0 0 0';
- return 1;
- }
-
- player = self;
- spider = self.vehicle;
- self = spider;
-
- vehicles_painframe();
-
- player.BUTTON_ZOOM = 0;
- player.BUTTON_CROUCH = 0;
- player.switchweapon = 0;
- player.vehicle_weapon2mode = spider.vehicle_weapon2mode;
-
-
-#if 1 // 0 to enable per-gun impact aux crosshairs
- // Avarage gun impact point's -> aux cross
- ad = gettaginfo(spider.tur_head, gettagindex(spider.tur_head, "tag_hardpoint01"));
- vf = v_forward;
- ad += gettaginfo(spider.tur_head, gettagindex(spider.tur_head, "tag_hardpoint02"));
- vf += v_forward;
- ad = ad * 0.5;
- v_forward = vf * 0.5;
- traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, spider);
- UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload1) + ('0 1 0' * (1 - player.vehicle_reload1)), 0);
-#else
- ad = gettaginfo(spider.gun1, gettagindex(spider.gun1, "barrels"));
- traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, spider);
- UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload1) + ('0 1 0' * (1 - player.vehicle_reload1)), 0);
- vf = ad;
- ad = gettaginfo(spider.gun2, gettagindex(spider.gun2, "barrels"));
- traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, spider);
- UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload1) + ('0 1 0' * (1 - player.vehicle_reload1)), 1);
- ad = 0.5 * (ad + vf);
-#endif
-
- crosshair_trace(player);
- ad = vectoangles(normalize(trace_endpos - ad));
- ad = AnglesTransform_ToAngles(AnglesTransform_LeftDivide(AnglesTransform_FromAngles(spider.angles), AnglesTransform_FromAngles(ad))) - spider.tur_head.angles;
- ad = AnglesTransform_Normalize(ad, true);
- //UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload2) + ('0 1 0' * (1 - player.vehicle_reload2)), 2);
-
- // Rotate head
- ftmp = autocvar_g_vehicle_spiderbot_head_turnspeed * sys_frametime;
- ad_y = bound(-ftmp, ad_y, ftmp);
- spider.tur_head.angles_y = bound(autocvar_g_vehicle_spiderbot_head_turnlimit * -1, spider.tur_head.angles_y + ad_y, autocvar_g_vehicle_spiderbot_head_turnlimit);
-
- // Pitch head
- ad_x = bound(ftmp * -1, ad_x, ftmp);
- spider.tur_head.angles_x = bound(autocvar_g_vehicle_spiderbot_head_pitchlimit_down, spider.tur_head.angles_x + ad_x, autocvar_g_vehicle_spiderbot_head_pitchlimit_up);
-
-
- //fixedmakevectors(spider.angles);
- makevectors(spider.angles + '-2 0 0' * spider.angles_x);
-
- movelib_groundalign4point(autocvar_g_vehicle_spiderbot_springlength, autocvar_g_vehicle_spiderbot_springup, autocvar_g_vehicle_spiderbot_springblend, autocvar_g_vehicle_spiderbot_tiltlimit);
-
- if(spider.flags & FL_ONGROUND)
- spider.jump_delay = time; // reset now so movement can begin
-
- //if(spider.flags & FL_ONGROUND)
- {
- if(spider.flags & FL_ONGROUND)
- if(spider.frame == 4 && self.tur_head.wait != 0)
- {
- sound (self, CH_TRIGGER_SINGLE, "vehicles/spiderbot_land.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
- spider.frame = 5;
- }
-
- if(!player.BUTTON_JUMP)
- spider.BUTTON_JUMP = 0;
-
- if((spider.flags & FL_ONGROUND) && player.BUTTON_JUMP && !spider.BUTTON_JUMP && self.tur_head.wait < time)
- {
- sound (self, CH_TRIGGER_SINGLE, "vehicles/spiderbot_jump.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
- //dprint("spiderbot_jump:", ftos(soundlength("vehicles/spiderbot_jump.wav")), "\n");
- self.delay = 0;
-
- self.tur_head.wait = time + 2;
- spider.jump_delay = time + 2;
- spider.BUTTON_JUMP = 1; // set spider's jump
- //player.BUTTON_JUMP = 0;
-
- vector movefix = '0 0 0';
- if(player.movement_x > 0) movefix_x = 1;
- if(player.movement_x < 0) movefix_x = -1;
- if(player.movement_y > 0) movefix_y = 1;
- if(player.movement_y < 0) movefix_y = -1;
-
- vector rt = movefix_y * v_right;
- vector sd = movefix_x * v_forward;
- if(movefix_y == 0 && movefix_x == 0)
- sd = v_forward; // always do forward
-
- spider.flags &= ~FL_ONGROUND;
-
- spider.velocity = sd * 700 + rt * 600 + v_up * 600;
- spider.frame = 4;
- }
- else if(time >= spider.jump_delay)
- {
- if(vlen(player.movement) == 0)
- {
- if(spider.flags & FL_ONGROUND)
- {
- if(self.sound_nexttime < time || self.delay != 3)
- {
- self.delay = 3;
- self.sound_nexttime = time + 6.486500; //soundlength("vehicles/spiderbot_idle.wav");
- //dprint("spiderbot_idle:", ftos(soundlength("vehicles/spiderbot_idle.wav")), "\n");
- sound (self, CH_TRIGGER_SINGLE, "vehicles/spiderbot_idle.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
- }
- movelib_beak_simple(autocvar_g_vehicle_spiderbot_speed_stop);
- spider.frame = 5;
- }
- }
- else
- {
- // Turn Body
- if(player.movement_x == 0 && player.movement_y != 0)
- ftmp = autocvar_g_vehicle_spiderbot_turnspeed_strafe * sys_frametime;
- else
- ftmp = autocvar_g_vehicle_spiderbot_turnspeed * sys_frametime;
-
- ftmp = bound(-ftmp, spider.tur_head.angles_y, ftmp);
- spider.angles_y = anglemods(spider.angles_y + ftmp);
- spider.tur_head.angles_y -= ftmp;
-
- if(player.movement_x != 0)
- {
- if(player.movement_x > 0)
- {
- player.movement_x = 1;
- if(spider.flags & FL_ONGROUND)
- spider.frame = 0;
- }
- else if(player.movement_x < 0)
- {
- player.movement_x = -1;
- if(spider.flags & FL_ONGROUND)
- spider.frame = 1;
- }
- player.movement_y = 0;
- float oldvelz = spider.velocity_z;
- movelib_move_simple(normalize(v_forward * player.movement_x),((player.BUTTON_JUMP) ? autocvar_g_vehicle_spiderbot_speed_run : autocvar_g_vehicle_spiderbot_speed_walk),autocvar_g_vehicle_spiderbot_movement_inertia);
- spider.velocity_z = oldvelz;
- float g = ((autocvar_sv_gameplayfix_gravityunaffectedbyticrate) ? 0.5 : 1);
- if(spider.velocity_z <= 20) // not while jumping
- spider.velocity_z -= g * sys_frametime * autocvar_sv_gravity;
- if(spider.flags & FL_ONGROUND)
- if(self.sound_nexttime < time || self.delay != 1)
- {
- self.delay = 1;
- self.sound_nexttime = time + 6.486500; //soundlength("vehicles/spiderbot_walk.wav");
- sound (self, CH_TRIGGER_SINGLE, "vehicles/spiderbot_walk.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
- //dprint("spiderbot_walk:", ftos(soundlength("vehicles/spiderbot_walk.wav")), "\n");
- }
- }
- else if(player.movement_y != 0)
- {
- if(player.movement_y < 0)
- {
- player.movement_y = -1;
- if(spider.flags & FL_ONGROUND)
- spider.frame = 2;
- }
- else if(player.movement_y > 0)
- {
- player.movement_y = 1;
- if(spider.flags & FL_ONGROUND)
- spider.frame = 3;
- }
-
- float oldvelz = spider.velocity_z;
- movelib_move_simple(normalize(v_right * player.movement_y),autocvar_g_vehicle_spiderbot_speed_strafe,autocvar_g_vehicle_spiderbot_movement_inertia);
- spider.velocity_z = oldvelz;
- float g = ((autocvar_sv_gameplayfix_gravityunaffectedbyticrate) ? 0.5 : 1);
- if(spider.velocity_z <= 20) // not while jumping
- spider.velocity_z -= g * sys_frametime * autocvar_sv_gravity;
- if(spider.flags & FL_ONGROUND)
- if(self.sound_nexttime < time || self.delay != 2)
- {
- self.delay = 2;
- self.sound_nexttime = time + 6.486500; //soundlength("vehicles/spiderbot_strafe.wav");
- sound (self, CH_TRIGGER_SINGLE, "vehicles/spiderbot_strafe.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
- //dprint("spiderbot_strafe:", ftos(soundlength("vehicles/spiderbot_strafe.wav")), "\n");
- }
- }
- }
- }
- }
-
- self.angles_x = bound(-autocvar_g_vehicle_spiderbot_tiltlimit, self.angles_x, autocvar_g_vehicle_spiderbot_tiltlimit);
- self.angles_z = bound(-autocvar_g_vehicle_spiderbot_tiltlimit, self.angles_z, autocvar_g_vehicle_spiderbot_tiltlimit);
-
- if(!forbidWeaponUse(player))
- if(player.BUTTON_ATCK)
- {
- spider.cnt = time;
- if(spider.vehicle_ammo1 >= autocvar_g_vehicle_spiderbot_minigun_ammo_cost && spider.tur_head.attack_finished_single <= time)
- {
- entity gun;
- vector v;
- spider.misc_bulletcounter += 1;
-
- self = player;
-
- gun = (spider.misc_bulletcounter % 2) ? spider.gun1 : spider.gun2;
-
- v = gettaginfo(gun, gettagindex(gun, "barrels"));
- v_forward = normalize(v_forward);
- v += v_forward * 50;
-
- fireBullet(v, v_forward, autocvar_g_vehicle_spiderbot_minigun_spread, autocvar_g_vehicle_spiderbot_minigun_solidpenetration,
- autocvar_g_vehicle_spiderbot_minigun_damage, autocvar_g_vehicle_spiderbot_minigun_force, DEATH_VH_SPID_MINIGUN, 0);
-
- sound (gun, CH_WEAPON_A, W_Sound("uzi_fire"), VOL_BASE, ATTEN_NORM);
- //trailparticles(self, _particleeffectnum("spiderbot_minigun_trail"), v, trace_endpos);
- pointparticles(particleeffectnum(EFFECT_SPIDERBOT_MINIGUN_MUZZLEFLASH), v, v_forward * 2500, 1);
-
- self = spider;
-
- spider.vehicle_ammo1 -= autocvar_g_vehicle_spiderbot_minigun_ammo_cost;
- spider.tur_head.attack_finished_single = time + autocvar_g_vehicle_spiderbot_minigun_refire;
- player.vehicle_ammo1 = (spider.vehicle_ammo1 / autocvar_g_vehicle_spiderbot_minigun_ammo_max) * 100;
- spider.gun1.angles_z += 45;
- spider.gun2.angles_z -= 45;
- if(spider.gun1.angles_z >= 360)
- {
- spider.gun1.angles_z = 0;
- spider.gun2.angles_z = 0;
- }
- }
- }
- else
- vehicles_regen(spider.cnt, vehicle_ammo1, autocvar_g_vehicle_spiderbot_minigun_ammo_max,
- autocvar_g_vehicle_spiderbot_minigun_ammo_regen_pause,
- autocvar_g_vehicle_spiderbot_minigun_ammo_regen, frametime, false);
-
-
- spiderbot_rocket_do();
-
- if(self.vehicle_flags & VHF_SHIELDREGEN)
- vehicles_regen(spider.dmg_time, vehicle_shield, autocvar_g_vehicle_spiderbot_shield, autocvar_g_vehicle_spiderbot_shield_regen_pause, autocvar_g_vehicle_spiderbot_shield_regen, frametime, true);
-
- if(self.vehicle_flags & VHF_HEALTHREGEN)
- vehicles_regen(spider.dmg_time, vehicle_health, autocvar_g_vehicle_spiderbot_health, autocvar_g_vehicle_spiderbot_health_regen_pause, autocvar_g_vehicle_spiderbot_health_regen, frametime, false);
-
- player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
- //player.vehicle_ammo2 = spider.tur_head.frame;
- player.vehicle_ammo2 = (9 - spider.tur_head.frame) / 8 * 100; // Percentage, like ammo1
-
- if(spider.gun2.cnt <= time)
- player.vehicle_reload2 = 100;
- else
- player.vehicle_reload2 = 100 - ((spider.gun2.cnt - time) / spider.attack_finished_single) * 100;
-
- setorigin(player, spider.origin + '0 0 1' * spider.maxs_z);
- player.velocity = spider.velocity;
-
- VEHICLE_UPDATE_PLAYER(player, health, spiderbot);
-
- if(self.vehicle_flags & VHF_HASSHIELD)
- VEHICLE_UPDATE_PLAYER(player, shield, spiderbot);
-
- self = player;
- return 1;
-}
-
-void spiderbot_exit(float eject)
-{
- entity e;
- vector spot;
-
- e = findchain(classname,"spiderbot_rocket");
- while(e)
- {
- if(e.owner == self.owner)
- {
- e.realowner = self.owner;
- e.owner = world;
- }
- e = e.chain;
- }
-
- self.think = vehicles_think;
- self.nextthink = time;
- self.frame = 5;
- self.movetype = MOVETYPE_WALK;
-
- if(!self.owner)
- return;
-
- makevectors(self.angles);
- if(eject)
- {
- spot = self.origin + v_forward * 100 + '0 0 64';
- spot = vehicles_findgoodexit(spot);
- setorigin(self.owner , spot);
- self.owner.velocity = (v_up + v_forward * 0.25) * 750;
- self.owner.oldvelocity = self.owner.velocity;
- }
- else
- {
- if(vlen(self.velocity) > autocvar_g_vehicle_spiderbot_speed_strafe)
- {
- self.owner.velocity = normalize(self.velocity) * vlen(self.velocity);
- self.owner.velocity_z += 200;
- spot = self.origin + v_forward * 128 + '0 0 64';
- spot = vehicles_findgoodexit(spot);
- }
- else
- {
- self.owner.velocity = self.velocity * 0.5;
- self.owner.velocity_z += 10;
- spot = self.origin + v_forward * 256 + '0 0 64';
- spot = vehicles_findgoodexit(spot);
- }
- self.owner.oldvelocity = self.owner.velocity;
- setorigin(self.owner , spot);
- }
-
- antilag_clear(self.owner);
- self.owner = world;
-}
-
-void spiderbot_headfade()
-{
- self.think = spiderbot_headfade;
- self.nextthink = self.fade_time;
- self.alpha = 1 - (time - self.fade_time) * self.fade_rate;
-
- if(self.cnt < time || self.alpha < 0.1)
- {
- if(self.alpha > 0.1)
- {
- sound (self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
- Send_Effect(EFFECT_EXPLOSION_BIG, self.origin + '0 0 100', '0 0 0', 1);
- }
- remove(self);
- }
-}
-
-void spiderbot_blowup()
-{
- if(self.cnt > time)
- {
- if(random() < 0.1)
- {
- sound (self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
- Send_Effect(EFFECT_EXPLOSION_SMALL, randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
- }
- self.nextthink = time + 0.1;
- return;
- }
-
- entity h, g1, g2, b;
- b = spawn();
- h = spawn();
- g1 = spawn();
- g2 = spawn();
-
- setmodel(b, "models/vehicles/spiderbot.dpm");
- setmodel(h, "models/vehicles/spiderbot_top.dpm");
- setmodel(g1, "models/vehicles/spiderbot_barrels.dpm");
- setmodel(g2, "models/vehicles/spiderbot_barrels.dpm");
-
- setorigin(b, self.origin);
- b.frame = 11;
- b.angles = self.angles;
- setsize(b, self.mins, self.maxs);
-
- setorigin(h, gettaginfo(self, gettagindex(self, "tag_head")));
- h.movetype = MOVETYPE_BOUNCE;
- h.solid = SOLID_BBOX;
- h.velocity = v_up * (500 + random() * 500) + randomvec() * 128;
- h.modelflags = MF_ROCKET;
- h.effects = EF_FLAME | EF_LOWPRECISION;
- h.avelocity = randomvec() * 360;
-
- h.alpha = 1;
- h.cnt = time + (3.5 * random());
- h.fade_rate = 1 / min(self.respawntime, 10);
- h.fade_time = time;
- h.think = spiderbot_headfade;
- h.nextthink = time;
-
- setorigin(g1, gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_hardpoint01")));
- g1.movetype = MOVETYPE_TOSS;
- g1.solid = SOLID_CORPSE;
- g1.velocity = v_forward * 700 + (randomvec() * 32);
- g1.avelocity = randomvec() * 180;
-
- setorigin(g2, gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_hardpoint02")));
- g2.movetype = MOVETYPE_TOSS;
- g2.solid = SOLID_CORPSE;
- g2.velocity = v_forward * 700 + (randomvec() * 32);
- g2.avelocity = randomvec() * 180;
-
- h.colormod = b.colormod = g1.colormod = g2.colormod = '-2 -2 -2';
-
- SUB_SetFade(b, time + 5, min(self.respawntime, 1));
- //SUB_SetFade(h, time, min(self.respawntime, 10));
- SUB_SetFade(g1, time, min(self.respawntime, 10));
- SUB_SetFade(g2, time, min(self.respawntime, 10));
-
- RadiusDamage (self, self.enemy, 250, 15, 250, world, world, 250, DEATH_VH_SPID_DEATH, world);
-
- self.alpha = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = -1;
- self.movetype = MOVETYPE_NONE;
- self.deadflag = DEAD_DEAD;
- self.solid = SOLID_NOT;
- self.tur_head.effects &= ~EF_FLAME;
- self.vehicle_hudmodel.viewmodelforclient = self;
-}
-
-bool spiderbot_impulse(int _imp)
-{
- switch(_imp)
- {
- case 1:
- case 230:
- self.vehicle.vehicle_weapon2mode = SBRM_VOLLY;
- CSQCVehicleSetup(self, 0);
- return true;
- case 2:
- case 231:
- self.vehicle.vehicle_weapon2mode = SBRM_GUIDE;
- CSQCVehicleSetup(self, 0);
- return true;
- case 3:
- case 232:
- case 251:
- self.vehicle.vehicle_weapon2mode = SBRM_ARTILLERY;
- CSQCVehicleSetup(self, 0);
- return true;
-
- case 10:
- case 15:
- case 18:
- self.vehicle.vehicle_weapon2mode += 1;
- if(self.vehicle.vehicle_weapon2mode > SBRM_LAST)
- self.vehicle.vehicle_weapon2mode = SBRM_FIRST;
-
- //centerprint(self, strcat("Rocket mode is ", ftos(self.vehicle.vehicle_weapon2mode)));
- CSQCVehicleSetup(self, 0);
- return true;
- case 11:
- case 12:
- case 16:
- case 19:
- self.vehicle.vehicle_weapon2mode -= 1;
- if(self.vehicle.vehicle_weapon2mode < SBRM_FIRST)
- self.vehicle.vehicle_weapon2mode = SBRM_LAST;
-
- //centerprint(self, strcat("Rocket mode is ", ftos(self.vehicle.vehicle_weapon2mode)));
- CSQCVehicleSetup(self, 0);
- return true;
-
- /*
- case 17: // toss gun, could be used to exit?
- break;
- case 20: // Manual minigun reload?
- break;
- */
- }
- return false;
-}
-
-void spawnfunc_vehicle_spiderbot()
-{
- if(!autocvar_g_vehicle_spiderbot) { remove(self); return; }
- if(!vehicle_initialize(VEH_SPIDERBOT, false)) { remove(self); return; }
-}
-
-float v_spiderbot(float req)
-{
- switch(req)
- {
- case VR_IMPACT:
- {
- if(autocvar_g_vehicle_spiderbot_bouncepain)
- vehicles_impact(autocvar_g_vehicle_spiderbot_bouncepain_x, autocvar_g_vehicle_spiderbot_bouncepain_y, autocvar_g_vehicle_spiderbot_bouncepain_z);
-
- return true;
- }
- case VR_ENTER:
- {
- self.vehicle_weapon2mode = SBRM_GUIDE;
- self.movetype = MOVETYPE_WALK;
- CSQCVehicleSetup(self.owner, 0);
- self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_spiderbot_health) * 100;
- self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_spiderbot_shield) * 100;
-
- if(self.owner.flagcarried)
- {
- setattachment(self.owner.flagcarried, self.tur_head, "");
- setorigin(self.owner.flagcarried, '-20 0 120');
- }
-
- return true;
- }
- case VR_THINK:
- {
- if(self.flags & FL_ONGROUND)
- movelib_beak_simple(autocvar_g_vehicle_spiderbot_speed_stop);
-
- return true;
- }
- case VR_DEATH:
- {
- self.health = 0;
- self.event_damage = func_null;
- self.takedamage = DAMAGE_NO;
- self.touch = func_null;
- self.cnt = 3.4 + time + random() * 2;
- self.think = spiderbot_blowup;
- self.nextthink = time;
- self.deadflag = DEAD_DYING;
- self.frame = 5;
- self.tur_head.effects |= EF_FLAME;
- self.colormod = self.tur_head.colormod = '-1 -1 -1';
- self.frame = 10;
- self.movetype = MOVETYPE_TOSS;
-
- CSQCModel_UnlinkEntity(); // networking the death scene would be a nightmare
-
- return true;
- }
- case VR_SPAWN:
- {
- if(!self.gun1)
- {
- self.vehicles_impulse = spiderbot_impulse;
- self.gun1 = spawn();
- self.gun2 = spawn();
- setmodel(self.gun1, "models/vehicles/spiderbot_barrels.dpm");
- setmodel(self.gun2, "models/vehicles/spiderbot_barrels.dpm");
- setattachment(self.gun1, self.tur_head, "tag_hardpoint01");
- setattachment(self.gun2, self.tur_head, "tag_hardpoint02");
- self.gravity = 2;
- self.mass = 5000;
- }
-
- self.frame = 5;
- self.tur_head.frame = 1;
- self.movetype = MOVETYPE_WALK;
- self.solid = SOLID_SLIDEBOX;
- self.alpha = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = 1;
- self.tur_head.angles = '0 0 0';
- self.vehicle_exit = spiderbot_exit;
-
- setorigin(self, self.pos1 + '0 0 128');
- self.angles = self.pos2;
- self.damageforcescale = 0.03;
- self.vehicle_health = autocvar_g_vehicle_spiderbot_health;
- self.vehicle_shield = autocvar_g_vehicle_spiderbot_shield;
-
- self.PlayerPhysplug = spiderbot_frame;
-
- return true;
- }
- case VR_SETUP:
- {
- if(autocvar_g_vehicle_spiderbot_shield)
- self.vehicle_flags |= VHF_HASSHIELD;
-
- if(autocvar_g_vehicle_spiderbot_shield_regen)
- self.vehicle_flags |= VHF_SHIELDREGEN;
-
- if(autocvar_g_vehicle_spiderbot_health_regen)
- self.vehicle_flags |= VHF_HEALTHREGEN;
-
- self.respawntime = autocvar_g_vehicle_spiderbot_respawntime;
- self.vehicle_health = autocvar_g_vehicle_spiderbot_health;
- self.vehicle_shield = autocvar_g_vehicle_spiderbot_shield;
- self.max_health = self.vehicle_health;
- self.pushable = true; // spiderbot can use jumppads
-
- return true;
- }
- case VR_PRECACHE:
- {
- precache_model ("models/vhshield.md3");
- precache_model ("models/vehicles/spiderbot.dpm");
- precache_model ("models/vehicles/spiderbot_top.dpm");
- precache_model ("models/vehicles/spiderbot_barrels.dpm");
- precache_model ("models/vehicles/spiderbot_cockpit.dpm");
- precache_model ( "models/uziflash.md3");
-
- precache_sound (W_Sound("uzi_fire") );
- precache_sound (W_Sound("rocket_impact"));
-
- precache_sound ("vehicles/spiderbot_die.wav");
- precache_sound ("vehicles/spiderbot_idle.wav");
- precache_sound ("vehicles/spiderbot_jump.wav");
- precache_sound ("vehicles/spiderbot_strafe.wav");
- precache_sound ("vehicles/spiderbot_walk.wav");
- precache_sound ("vehicles/spiderbot_land.wav");
- return true;
- }
- }
-
- return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float autocvar_cl_vehicle_spiderbot_cross_alpha = 0.6;
-float autocvar_cl_vehicle_spiderbot_cross_size = 1;
-
-float v_spiderbot(float req)
-{
- switch(req)
- {
- case VR_HUD:
- {
- string crosshair;
-
- switch(weapon2mode)
- {
- case SBRM_VOLLY: crosshair = vCROSS_BURST; break;
- case SBRM_GUIDE: crosshair = vCROSS_GUIDE; break;
- case SBRM_ARTILLERY: crosshair = vCROSS_RAIN; break;
- default: crosshair = vCROSS_BURST;
- }
-
- Vehicles_drawHUD(VEH_SPIDERBOT.m_icon, "vehicle_spider_weapon1", "vehicle_spider_weapon2",
- "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
- "vehicle_icon_ammo2", autocvar_hud_progressbar_vehicles_ammo2_color,
- crosshair);
- return true;
- }
- case VR_SETUP:
- {
- AuxiliaryXhair[0].axh_image = vCROSS_HINT; // Minigun1
- AuxiliaryXhair[1].axh_image = vCROSS_HINT; // Minigun2
-
- return true;
- }
- case VR_PRECACHE:
- {
- return true;
- }
- }
-
- return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_VEHICLE
#ifndef VEHICLE_H
#define VEHICLE_H
-int v_null(int) { return 0; }
-
CLASS(Vehicle, Object)
ATTRIB(Vehicle, vehicleid, int, 0)
/** hud icon */
ATTRIB(Vehicle, netname, string, "")
/** human readable name */
ATTRIB(Vehicle, vehicle_name, string, "Vehicle")
- /** */
- ATTRIB(Vehicle, vehicle_func, int(int), v_null)
/** full name of model */
ATTRIB(Vehicle, model, string, "")
/** currently a copy of the model */
ATTRIB(Vehicle, mins, vector, '-0 -0 -0')
/** vehicle hitbox size */
ATTRIB(Vehicle, maxs, vector, '0 0 0')
+
+ /** (BOTH) setup vehicle data */
+ METHOD(Vehicle, vr_setup, void(Vehicle)) { }
+ /** (SERVER) logic to run every frame */
+ METHOD(Vehicle, vr_think, void(Vehicle)) { }
+ /** (SERVER) called when vehicle dies */
+ METHOD(Vehicle, vr_death, void(Vehicle)) { }
+ /** (BOTH) precaches models/sounds used by this vehicle */
+ METHOD(Vehicle, vr_precache, void(Vehicle)) { }
+ /** (SERVER) called when a player enters this vehicle */
+ METHOD(Vehicle, vr_enter, void(Vehicle)) { }
+ /** (SERVER) called when the vehicle re-spawns */
+ METHOD(Vehicle, vr_spawn, void(Vehicle)) { }
+ /** (SERVER) called when a vehicle hits something */
+ METHOD(Vehicle, vr_impact, void(Vehicle)) { }
+ /** (CLIENT) logic to run every frame */
+ METHOD(Vehicle, vr_hud, void(Vehicle)) { }
ENDCLASS(Vehicle)
+// vehicle spawn flags (need them here for common registrations)
+const int VHF_ISVEHICLE = 2; /// Indicates vehicle
+const int VHF_HASSHIELD = 4; /// Vehicle has shileding
+const int VHF_SHIELDREGEN = 8; /// Vehicles shield regenerates
+const int VHF_HEALTHREGEN = 16; /// Vehicles health regenerates
+const int VHF_ENERGYREGEN = 32; /// Vehicles energy regenerates
+const int VHF_DEATHEJECT = 64; /// Vehicle ejects pilot upon fatal damage
+const int VHF_MOVE_GROUND = 128; /// Vehicle moves on gound
+const int VHF_MOVE_HOVER = 256; /// Vehicle hover close to gound
+const int VHF_MOVE_FLY = 512; /// Vehicle is airborn
+const int VHF_DMGSHAKE = 1024; /// Add random velocity each frame if health < 50%
+const int VHF_DMGROLL = 2048; /// Add random angles each frame if health < 50%
+const int VHF_DMGHEADROLL = 4096; /// Add random head angles each frame if health < 50%
+const int VHF_MULTISLOT = 8192; /// Vehicle has multiple player slots
+const int VHF_PLAYERSLOT = 16384; /// This ent is a player slot on a multi-person vehicle
+
+// fields:
+.entity tur_head;
+
#endif
--- /dev/null
+#ifndef VEHICLE_BUMBLEBEE
+#define VEHICLE_BUMBLEBEE
+#include "bumblebee.qh"
+
+#include "bumblebee_weapons.qc"
+
+CLASS(Bumblebee, Vehicle)
+/* spawnflags */ ATTRIB(Bumblebee, spawnflags, int, VHF_DMGSHAKE);
+/* mins */ ATTRIB(Bumblebee, mins, vector, '-245 -130 -130');
+/* maxs */ ATTRIB(Bumblebee, maxs, vector, '230 130 130');
+/* model */ ATTRIB(Bumblebee, mdl, string, "models/vehicles/bumblebee_body.dpm");
+/* model */ ATTRIB(Bumblebee, model, string, "models/vehicles/bumblebee_body.dpm");
+/* head_model */ ATTRIB(Bumblebee, head_model, string, "");
+/* hud_model */ ATTRIB(Bumblebee, hud_model, string, "models/vehicles/spiderbot_cockpit.dpm");
+/* tags */ ATTRIB(Bumblebee, tag_head, string, "");
+/* tags */ ATTRIB(Bumblebee, tag_hud, string, "");
+/* tags */ ATTRIB(Bumblebee, tag_view, string, "tag_viewport");
+/* netname */ ATTRIB(Bumblebee, netname, string, "bumblebee");
+/* fullname */ ATTRIB(Bumblebee, vehicle_name, string, _("Bumblebee"));
+/* icon */ ATTRIB(Bumblebee, m_icon, string, "vehicle_bumble");
+ENDCLASS(Bumblebee)
+REGISTER_VEHICLE(BUMBLEBEE, NEW(Bumblebee));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+const float BRG_SETUP = 2;
+const float BRG_START = 4;
+const float BRG_END = 8;
+
+#include "bumblebee_weapons.qc"
+
+#ifdef SVQC
+float autocvar_g_vehicle_bumblebee_speed_forward;
+float autocvar_g_vehicle_bumblebee_speed_strafe;
+float autocvar_g_vehicle_bumblebee_speed_up;
+float autocvar_g_vehicle_bumblebee_speed_down;
+float autocvar_g_vehicle_bumblebee_turnspeed;
+float autocvar_g_vehicle_bumblebee_pitchspeed;
+float autocvar_g_vehicle_bumblebee_pitchlimit;
+float autocvar_g_vehicle_bumblebee_friction;
+
+float autocvar_g_vehicle_bumblebee_energy;
+float autocvar_g_vehicle_bumblebee_energy_regen;
+float autocvar_g_vehicle_bumblebee_energy_regen_pause;
+
+float autocvar_g_vehicle_bumblebee_health;
+float autocvar_g_vehicle_bumblebee_health_regen;
+float autocvar_g_vehicle_bumblebee_health_regen_pause;
+
+float autocvar_g_vehicle_bumblebee_shield;
+float autocvar_g_vehicle_bumblebee_shield_regen;
+float autocvar_g_vehicle_bumblebee_shield_regen_pause;
+
+float autocvar_g_vehicle_bumblebee_cannon_ammo;
+float autocvar_g_vehicle_bumblebee_cannon_ammo_regen;
+float autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause;
+
+float autocvar_g_vehicle_bumblebee_cannon_lock = 0;
+
+float autocvar_g_vehicle_bumblebee_cannon_turnspeed;
+float autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down;
+float autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up;
+float autocvar_g_vehicle_bumblebee_cannon_turnlimit_in;
+float autocvar_g_vehicle_bumblebee_cannon_turnlimit_out;
+
+
+float autocvar_g_vehicle_bumblebee_raygun_turnspeed;
+float autocvar_g_vehicle_bumblebee_raygun_pitchlimit_down;
+float autocvar_g_vehicle_bumblebee_raygun_pitchlimit_up;
+float autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides;
+
+float autocvar_g_vehicle_bumblebee_raygun_range;
+float autocvar_g_vehicle_bumblebee_raygun_dps;
+float autocvar_g_vehicle_bumblebee_raygun_aps;
+float autocvar_g_vehicle_bumblebee_raygun_fps;
+
+float autocvar_g_vehicle_bumblebee_raygun;
+float autocvar_g_vehicle_bumblebee_healgun_hps;
+float autocvar_g_vehicle_bumblebee_healgun_hmax;
+float autocvar_g_vehicle_bumblebee_healgun_aps;
+float autocvar_g_vehicle_bumblebee_healgun_amax;
+float autocvar_g_vehicle_bumblebee_healgun_sps;
+float autocvar_g_vehicle_bumblebee_healgun_locktime;
+
+float autocvar_g_vehicle_bumblebee_respawntime;
+
+float autocvar_g_vehicle_bumblebee_blowup_radius;
+float autocvar_g_vehicle_bumblebee_blowup_coredamage;
+float autocvar_g_vehicle_bumblebee_blowup_edgedamage;
+float autocvar_g_vehicle_bumblebee_blowup_forceintensity;
+vector autocvar_g_vehicle_bumblebee_bouncepain;
+
+bool autocvar_g_vehicle_bumblebee = 0;
+
+float bumblebee_gunner_frame()
+{SELFPARAM();
+ entity vehic = self.vehicle.owner;
+ entity gun = self.vehicle;
+ entity gunner = self;
+ setself(vehic);
+
+ vehic.solid = SOLID_NOT;
+ //setorigin(gunner, vehic.origin);
+ gunner.velocity = vehic.velocity;
+
+ float _in, _out;
+ vehic.angles_x *= -1;
+ makevectors(vehic.angles);
+ vehic.angles_x *= -1;
+ if(gun == vehic.gun1)
+ {
+ _in = autocvar_g_vehicle_bumblebee_cannon_turnlimit_in;
+ _out = autocvar_g_vehicle_bumblebee_cannon_turnlimit_out;
+ setorigin(gunner, vehic.origin + v_up * -16 + v_forward * -16 + v_right * 128);
+ }
+ else
+ {
+ _in = autocvar_g_vehicle_bumblebee_cannon_turnlimit_out;
+ _out = autocvar_g_vehicle_bumblebee_cannon_turnlimit_in;
+ setorigin(gunner, vehic.origin + v_up * -16 + v_forward * -16 + v_right * -128);
+ }
+
+ crosshair_trace(gunner);
+ vector _ct = trace_endpos;
+ vector ad;
+
+ if(autocvar_g_vehicle_bumblebee_cannon_lock)
+ {
+ if(gun.lock_time < time)
+ gun.enemy = world;
+
+ if(trace_ent)
+ if(trace_ent.movetype)
+ if(trace_ent.takedamage)
+ if(!trace_ent.deadflag)
+ {
+ if(DIFF_TEAM(trace_ent, gunner))
+ {
+ gun.enemy = trace_ent;
+ gun.lock_time = time + 5;
+ }
+ }
+ }
+
+ if(gun.enemy)
+ {
+ float distance, impact_time;
+
+ vector vf = real_origin(gun.enemy);
+ vector _vel = gun.enemy.velocity;
+ if(gun.enemy.movetype == MOVETYPE_WALK)
+ _vel.z *= 0.1;
+
+
+ ad = vf;
+ distance = vlen(ad - gunner.origin);
+ impact_time = distance / autocvar_g_vehicle_bumblebee_cannon_speed;
+ ad = vf + _vel * impact_time;
+ trace_endpos = ad;
+
+
+ UpdateAuxiliaryXhair(gunner, ad, '1 0 1', 1);
+ vehicle_aimturret(vehic, trace_endpos, gun, "fire",
+ autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up,
+ _out * -1, _in, autocvar_g_vehicle_bumblebee_cannon_turnspeed);
+
+ }
+ else
+ vehicle_aimturret(vehic, _ct, gun, "fire",
+ autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up,
+ _out * -1, _in, autocvar_g_vehicle_bumblebee_cannon_turnspeed);
+
+ if(!forbidWeaponUse(gunner))
+ if(gunner.BUTTON_ATCK)
+ if(time > gun.attack_finished_single)
+ if(gun.vehicle_energy >= autocvar_g_vehicle_bumblebee_cannon_cost)
+ {
+ gun.vehicle_energy -= autocvar_g_vehicle_bumblebee_cannon_cost;
+ bumblebee_fire_cannon(gun, "fire", gunner);
+ gun.delay = time;
+ gun.attack_finished_single = time + autocvar_g_vehicle_bumblebee_cannon_refire;
+ }
+
+ VEHICLE_UPDATE_PLAYER(gunner, health, bumblebee);
+
+ if(vehic.vehicle_flags & VHF_HASSHIELD)
+ VEHICLE_UPDATE_PLAYER(gunner, shield, bumblebee);
+
+ ad = gettaginfo(gun, gettagindex(gun, "fire"));
+ traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, gun);
+
+ UpdateAuxiliaryXhair(gunner, trace_endpos, ('1 0 0' * gunner.vehicle_reload1) + ('0 1 0' *(1 - gunner.vehicle_reload1)), 0);
+
+ if(vehic.owner)
+ UpdateAuxiliaryXhair(vehic.owner, trace_endpos, ('1 0 0' * gunner.vehicle_reload1) + ('0 1 0' *(1 - gunner.vehicle_reload1)), ((gunner == vehic.gunner1) ? 1 : 2));
+
+ vehic.solid = SOLID_BBOX;
+ gunner.BUTTON_ATCK = gunner.BUTTON_ATCK2 = gunner.BUTTON_CROUCH = 0;
+ gunner.vehicle_energy = (gun.vehicle_energy / autocvar_g_vehicle_bumblebee_cannon_ammo) * 100;
+
+ setself(gunner);
+ return 1;
+}
+
+vector bumblebee_gunner_findgoodexit(vector prefer_spot, entity gunner, entity player)
+{
+ //vector exitspot;
+ float mysize;
+
+ tracebox(gunner.origin + '0 0 32', PL_MIN, PL_MAX, prefer_spot, MOVE_NORMAL, player);
+ if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
+ return prefer_spot;
+
+ mysize = 1.5 * vlen(PL_MAX - PL_MIN); // can't use gunner's size, as they don't have a size
+ float i;
+ vector v, v2;
+ v2 = 0.5 * (gunner.absmin + gunner.absmax);
+ for(i = 0; i < 100; ++i)
+ {
+ v = randomvec();
+ v_z = 0;
+ v = v2 + normalize(v) * mysize;
+ tracebox(v2, PL_MIN, PL_MAX, v, MOVE_NORMAL, player);
+ if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
+ return v;
+ }
+
+ return prefer_spot; // this should be considered a fallback?!
+}
+
+void bumblebee_gunner_exit(int _exitflag)
+{SELFPARAM();
+ entity player = self;
+ entity gunner = player.vehicle;
+ entity vehic = gunner.owner;
+
+ if(IS_REAL_CLIENT(player))
+ {
+ msg_entity = player;
+ WriteByte(MSG_ONE, SVC_SETVIEWPORT);
+ WriteEntity(MSG_ONE, player);
+
+ WriteByte(MSG_ONE, SVC_SETVIEWANGLES);
+ WriteAngle(MSG_ONE, 0);
+ WriteAngle(MSG_ONE, vehic.angles.y);
+ WriteAngle(MSG_ONE, 0);
+ }
+
+ CSQCVehicleSetup(player, HUD_NORMAL);
+ setsize(player, PL_MIN, PL_MAX);
+
+ player.takedamage = DAMAGE_AIM;
+ player.solid = SOLID_SLIDEBOX;
+ player.movetype = MOVETYPE_WALK;
+ player.effects &= ~EF_NODRAW;
+ player.alpha = 1;
+ player.PlayerPhysplug = func_null;
+ player.view_ofs = PL_VIEW_OFS;
+ player.event_damage = PlayerDamage;
+ player.hud = HUD_NORMAL;
+ player.teleportable = TELEPORT_NORMAL;
+ player.switchweapon = gunner.switchweapon;
+ player.vehicle_enter_delay = time + 2;
+
+ fixedmakevectors(vehic.angles);
+
+ if(player == vehic.gunner1) { vehic.gunner1 = world; }
+ if(player == vehic.gunner2) { vehic.gunner2 = world; v_right *= -1; }
+
+ vector spot = real_origin(gunner);
+ spot = spot + v_up * 128 + v_forward * 300 + v_right * 150;
+ spot = bumblebee_gunner_findgoodexit(spot, gunner, player);
+
+ // TODO: figure a way to move player out of the gunner
+
+ player.velocity = 0.75 * vehic.velocity + normalize(spot - vehic.origin) * 200;
+ player.velocity_z += 10;
+
+ gunner.phase = time + 5;
+ gunner.vehicle_hudmodel.viewmodelforclient = gunner;
+
+ MUTATOR_CALLHOOK(VehicleExit, player, gunner);
+
+ player.vehicle = world;
+}
+
+bool bumblebee_gunner_enter()
+{SELFPARAM();
+ entity vehic = self;
+ entity player = other;
+ entity gunner = world;
+
+ if(!vehic.gunner1 && !vehic.gunner2 && ((time >= vehic.gun1.phase) + (time >= vehic.gun2.phase)) == 2)
+ {
+ // we can have some fun
+ if(vlen(real_origin(vehic.gun2) - player.origin) < vlen(real_origin(vehic.gun1) - player.origin))
+ {
+ gunner = vehic.gun2;
+ vehic.gunner2 = player;
+ }
+ else
+ {
+ gunner = vehic.gun1;
+ vehic.gunner1 = player;
+ }
+ }
+ else if(!vehic.gunner1 && time >= vehic.gun1.phase) { gunner = vehic.gun1; vehic.gunner1 = player; }
+ else if(!vehic.gunner2 && time >= vehic.gun2.phase) { gunner = vehic.gun2; vehic.gunner2 = player; }
+ else { LOG_TRACE("Vehicle is full, fail\n"); return false; }
+
+ player.vehicle = gunner;
+ player.angles = vehic.angles;
+ player.takedamage = DAMAGE_NO;
+ player.solid = SOLID_NOT;
+ player.alpha = -1;
+ player.movetype = MOVETYPE_NOCLIP;
+ player.event_damage = func_null;
+ player.view_ofs = '0 0 0';
+ player.hud = gunner.hud;
+ player.teleportable = false;
+ player.PlayerPhysplug = gunner.PlayerPhysplug;
+ player.vehicle_ammo1 = vehic.vehicle_ammo1;
+ player.vehicle_ammo2 = vehic.vehicle_ammo2;
+ player.vehicle_reload1 = vehic.vehicle_reload1;
+ player.vehicle_reload2 = vehic.vehicle_reload2;
+ player.vehicle_energy = vehic.vehicle_energy;
+ player.flags &= ~FL_ONGROUND;
+
+ RemoveGrapplingHook(player);
+
+ gunner.switchweapon = player.switchweapon;
+ gunner.vehicle_exit = bumblebee_gunner_exit;
+ gunner.vehicle_hudmodel.viewmodelforclient = player;
+
+ if(IS_REAL_CLIENT(player))
+ {
+ msg_entity = player;
+ WriteByte(MSG_ONE, SVC_SETVIEWPORT);
+ WriteEntity(MSG_ONE, gunner.vehicle_viewport);
+
+ WriteByte(MSG_ONE, SVC_SETVIEWANGLES);
+ WriteAngle(MSG_ONE, gunner.angles_x + vehic.angles_x); // tilt
+ WriteAngle(MSG_ONE, gunner.angles_y + vehic.angles_y); // yaw
+ WriteAngle(MSG_ONE, 0); // roll
+ }
+
+ CSQCVehicleSetup(player, player.hud);
+
+ MUTATOR_CALLHOOK(VehicleEnter, player, gunner);
+
+ return true;
+}
+
+bool vehicles_valid_pilot()
+{SELFPARAM();
+ if(IS_BOT_CLIENT(other) && !autocvar_g_vehicles_allow_bots)
+ return false;
+
+ if((!IS_PLAYER(other))
+ || (other.deadflag != DEAD_NO)
+ || (other.vehicle)
+ || (DIFF_TEAM(other, self))
+ ) { return false; }
+
+ return true;
+}
+
+void bumblebee_touch()
+{SELFPARAM();
+ if(autocvar_g_vehicles_enter) { return; }
+
+ if(self.gunner1 != world && self.gunner2 != world)
+ {
+ vehicles_touch();
+ return;
+ }
+
+ if(vehicles_valid_pilot())
+ {
+ float phase_time = (time >= self.gun1.phase) + (time >= self.gun2.phase);
+
+ if(time >= other.vehicle_enter_delay && phase_time)
+ if(bumblebee_gunner_enter())
+ return;
+ }
+
+ vehicles_touch();
+}
+
+void bumblebee_regen()
+{SELFPARAM();
+ if(self.gun1.delay + autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause < time)
+ self.gun1.vehicle_energy = min(autocvar_g_vehicle_bumblebee_cannon_ammo,
+ self.gun1.vehicle_energy + autocvar_g_vehicle_bumblebee_cannon_ammo_regen * frametime);
+
+ if(self.gun2.delay + autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause < time)
+ self.gun2.vehicle_energy = min(autocvar_g_vehicle_bumblebee_cannon_ammo,
+ self.gun2.vehicle_energy + autocvar_g_vehicle_bumblebee_cannon_ammo_regen * frametime);
+
+ if(self.vehicle_flags & VHF_SHIELDREGEN)
+ vehicles_regen(self.dmg_time, vehicle_shield, autocvar_g_vehicle_bumblebee_shield, autocvar_g_vehicle_bumblebee_shield_regen_pause, autocvar_g_vehicle_bumblebee_shield_regen, frametime, true);
+
+ if(self.vehicle_flags & VHF_HEALTHREGEN)
+ vehicles_regen(self.dmg_time, vehicle_health, autocvar_g_vehicle_bumblebee_health, autocvar_g_vehicle_bumblebee_health_regen_pause, autocvar_g_vehicle_bumblebee_health_regen, frametime, false);
+
+ if(self.vehicle_flags & VHF_ENERGYREGEN)
+ vehicles_regen(self.wait, vehicle_energy, autocvar_g_vehicle_bumblebee_energy, autocvar_g_vehicle_bumblebee_energy_regen_pause, autocvar_g_vehicle_bumblebee_energy_regen, frametime, false);
+
+}
+
+float bumblebee_pilot_frame()
+{SELFPARAM();
+ entity pilot, vehic;
+ vector newvel;
+
+ if(intermission_running)
+ {
+ self.vehicle.velocity = '0 0 0';
+ self.vehicle.avelocity = '0 0 0';
+ return 1;
+ }
+
+ pilot = self;
+ vehic = self.vehicle;
+ setself(vehic);
+
+ if(vehic.deadflag != DEAD_NO)
+ {
+ setself(pilot);
+ pilot.BUTTON_ATCK = pilot.BUTTON_ATCK2 = 0;
+ return 1;
+ }
+
+ bumblebee_regen();
+
+ crosshair_trace(pilot);
+
+ vector vang;
+ float ftmp;
+
+ vang = vehic.angles;
+ newvel = vectoangles(normalize(trace_endpos - self.origin + '0 0 32'));
+ vang.x *= -1;
+ newvel.x *= -1;
+ if(newvel.x > 180) newvel.x -= 360;
+ if(newvel.x < -180) newvel.x += 360;
+ if(newvel.y > 180) newvel.y -= 360;
+ if(newvel.y < -180) newvel.y += 360;
+
+ ftmp = shortangle_f(pilot.v_angle.y - vang.y, vang.y);
+ if(ftmp > 180) ftmp -= 360;
+ if(ftmp < -180) ftmp += 360;
+ vehic.avelocity_y = bound(-autocvar_g_vehicle_bumblebee_turnspeed, ftmp + vehic.avelocity.y * 0.9, autocvar_g_vehicle_bumblebee_turnspeed);
+
+ // Pitch
+ ftmp = 0;
+ if(pilot.movement.x > 0 && vang.x < autocvar_g_vehicle_bumblebee_pitchlimit)
+ ftmp = 4;
+ else if(pilot.movement.x < 0 && vang.x > -autocvar_g_vehicle_bumblebee_pitchlimit)
+ ftmp = -8;
+
+ newvel.x = bound(-autocvar_g_vehicle_bumblebee_pitchlimit, newvel.x , autocvar_g_vehicle_bumblebee_pitchlimit);
+ ftmp = vang.x - bound(-autocvar_g_vehicle_bumblebee_pitchlimit, newvel.x + ftmp, autocvar_g_vehicle_bumblebee_pitchlimit);
+ vehic.avelocity_x = bound(-autocvar_g_vehicle_bumblebee_pitchspeed, ftmp + vehic.avelocity.x * 0.9, autocvar_g_vehicle_bumblebee_pitchspeed);
+
+ vehic.angles_x = anglemods(vehic.angles.x);
+ vehic.angles_y = anglemods(vehic.angles.y);
+ vehic.angles_z = anglemods(vehic.angles.z);
+
+ makevectors('0 1 0' * vehic.angles.y);
+ newvel = vehic.velocity * -autocvar_g_vehicle_bumblebee_friction;
+
+ if(pilot.movement.x != 0)
+ {
+ if(pilot.movement.x > 0)
+ newvel += v_forward * autocvar_g_vehicle_bumblebee_speed_forward;
+ else if(pilot.movement.x < 0)
+ newvel -= v_forward * autocvar_g_vehicle_bumblebee_speed_forward;
+ }
+
+ if(pilot.movement.y != 0)
+ {
+ if(pilot.movement.y < 0)
+ newvel -= v_right * autocvar_g_vehicle_bumblebee_speed_strafe;
+ else if(pilot.movement.y > 0)
+ newvel += v_right * autocvar_g_vehicle_bumblebee_speed_strafe;
+ ftmp = newvel * v_right;
+ ftmp *= frametime * 0.1;
+ vehic.angles_z = bound(-15, vehic.angles.z + ftmp, 15);
+ }
+ else
+ {
+ vehic.angles_z *= 0.95;
+ if(vehic.angles.z >= -1 && vehic.angles.z <= -1)
+ vehic.angles_z = 0;
+ }
+
+ if(pilot.BUTTON_CROUCH)
+ newvel -= v_up * autocvar_g_vehicle_bumblebee_speed_down;
+ else if(pilot.BUTTON_JUMP)
+ newvel += v_up * autocvar_g_vehicle_bumblebee_speed_up;
+
+ vehic.velocity += newvel * frametime;
+ pilot.velocity = pilot.movement = vehic.velocity;
+
+
+ if(autocvar_g_vehicle_bumblebee_healgun_locktime)
+ {
+ if(vehic.tur_head.lock_time < time || vehic.tur_head.enemy.deadflag)
+ vehic.tur_head.enemy = world;
+
+ if(trace_ent)
+ if(trace_ent.movetype)
+ if(trace_ent.takedamage)
+ if(!trace_ent.deadflag)
+ {
+ if(teamplay)
+ {
+ if(trace_ent.team == pilot.team)
+ {
+ vehic.tur_head.enemy = trace_ent;
+ vehic.tur_head.lock_time = time + autocvar_g_vehicle_bumblebee_healgun_locktime;
+ }
+ }
+ else
+ {
+ vehic.tur_head.enemy = trace_ent;
+ vehic.tur_head.lock_time = time + autocvar_g_vehicle_bumblebee_healgun_locktime;
+ }
+ }
+
+ if(vehic.tur_head.enemy)
+ {
+ trace_endpos = real_origin(vehic.tur_head.enemy);
+ UpdateAuxiliaryXhair(pilot, trace_endpos, '0 0.75 0', 0);
+ }
+ }
+
+ vang = vehicle_aimturret(vehic, trace_endpos, self.gun3, "fire",
+ autocvar_g_vehicle_bumblebee_raygun_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_raygun_pitchlimit_up,
+ autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides * -1, autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides, autocvar_g_vehicle_bumblebee_raygun_turnspeed);
+
+ if(!forbidWeaponUse(pilot))
+ if((pilot.BUTTON_ATCK || pilot.BUTTON_ATCK2) && (vehic.vehicle_energy > autocvar_g_vehicle_bumblebee_raygun_dps * sys_frametime || autocvar_g_vehicle_bumblebee_raygun == 0))
+ {
+ vehic.gun3.enemy.realowner = pilot;
+ vehic.gun3.enemy.effects &= ~EF_NODRAW;
+
+ vehic.gun3.enemy.hook_start = gettaginfo(vehic.gun3, gettagindex(vehic.gun3, "fire"));
+ vehic.gun3.enemy.SendFlags |= BRG_START;
+
+ traceline(vehic.gun3.enemy.hook_start, vehic.gun3.enemy.hook_start + v_forward * autocvar_g_vehicle_bumblebee_raygun_range, MOVE_NORMAL, vehic);
+
+ if(trace_ent)
+ {
+ if(autocvar_g_vehicle_bumblebee_raygun)
+ {
+ Damage(trace_ent, vehic, pilot, autocvar_g_vehicle_bumblebee_raygun_dps * sys_frametime, DEATH_GENERIC, trace_endpos, v_forward * autocvar_g_vehicle_bumblebee_raygun_fps * sys_frametime);
+ vehic.vehicle_energy -= autocvar_g_vehicle_bumblebee_raygun_aps * sys_frametime;
+ }
+ else
+ {
+ if(trace_ent.deadflag == DEAD_NO)
+ if((teamplay && trace_ent.team == pilot.team) || !teamplay)
+ {
+
+ if(trace_ent.vehicle_flags & VHF_ISVEHICLE)
+ {
+ if(autocvar_g_vehicle_bumblebee_healgun_sps && trace_ent.vehicle_health <= trace_ent.max_health)
+ trace_ent.vehicle_shield = min(trace_ent.vehicle_shield + autocvar_g_vehicle_bumblebee_healgun_sps * frametime, trace_ent.tur_head.max_health);
+
+ if(autocvar_g_vehicle_bumblebee_healgun_hps)
+ trace_ent.vehicle_health = min(trace_ent.vehicle_health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, trace_ent.max_health);
+ }
+ else if(IS_CLIENT(trace_ent))
+ {
+ if(trace_ent.health <= autocvar_g_vehicle_bumblebee_healgun_hmax && autocvar_g_vehicle_bumblebee_healgun_hps)
+ trace_ent.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, autocvar_g_vehicle_bumblebee_healgun_hmax);
+
+ if(trace_ent.armorvalue <= autocvar_g_vehicle_bumblebee_healgun_amax && autocvar_g_vehicle_bumblebee_healgun_aps)
+ trace_ent.armorvalue = min(trace_ent.armorvalue + autocvar_g_vehicle_bumblebee_healgun_aps * frametime, autocvar_g_vehicle_bumblebee_healgun_amax);
+
+ trace_ent.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, autocvar_g_vehicle_bumblebee_healgun_hmax);
+ }
+ else if(IS_TURRET(trace_ent))
+ {
+ if(trace_ent.health <= trace_ent.max_health && autocvar_g_vehicle_bumblebee_healgun_hps)
+ trace_ent.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, trace_ent.max_health);
+ //else ..hmmm what? ammo?
+
+ trace_ent.SendFlags |= TNSF_STATUS;
+ }
+ }
+ }
+ }
+
+ vehic.gun3.enemy.hook_end = trace_endpos;
+ setorigin(vehic.gun3.enemy, trace_endpos);
+ vehic.gun3.enemy.SendFlags |= BRG_END;
+
+ vehic.wait = time + 1;
+ }
+ else
+ vehic.gun3.enemy.effects |= EF_NODRAW;
+ /*{
+ if(vehic.gun3.enemy)
+ remove(vehic.gun3.enemy);
+
+ vehic.gun3.enemy = world;
+ }
+ */
+
+ VEHICLE_UPDATE_PLAYER(pilot, health, bumblebee);
+ VEHICLE_UPDATE_PLAYER(pilot, energy, bumblebee);
+
+ pilot.vehicle_ammo1 = (vehic.gun1.vehicle_energy / autocvar_g_vehicle_bumblebee_cannon_ammo) * 100;
+ pilot.vehicle_ammo2 = (vehic.gun2.vehicle_energy / autocvar_g_vehicle_bumblebee_cannon_ammo) * 100;
+
+ if(vehic.vehicle_flags & VHF_HASSHIELD)
+ VEHICLE_UPDATE_PLAYER(pilot, shield, bumblebee);
+
+ vehic.angles_x *= -1;
+ makevectors(vehic.angles);
+ vehic.angles_x *= -1;
+ setorigin(pilot, vehic.origin + v_up * 48 + v_forward * 160);
+
+ pilot.BUTTON_ATCK = pilot.BUTTON_ATCK2 = pilot.BUTTON_CROUCH = 0;
+ setself(pilot);
+
+ return 1;
+}
+
+void bumblebee_land()
+{SELFPARAM();
+ float hgt;
+
+ hgt = raptor_altitude(512);
+ self.velocity = (self.velocity * 0.9) + ('0 0 -1800' * (hgt / 256) * sys_frametime);
+ self.angles_x *= 0.95;
+ self.angles_z *= 0.95;
+
+ if(hgt < 16)
+ self.think = vehicles_think;
+
+ self.nextthink = time;
+
+ CSQCMODEL_AUTOUPDATE(self);
+}
+
+void bumblebee_exit(float eject)
+{SELFPARAM();
+ if(self.owner.vehicleid == VEH_BUMBLEBEE.vehicleid)
+ {
+ bumblebee_gunner_exit(eject);
+ return;
+ }
+
+ self.touch = vehicles_touch;
+
+ if(self.deadflag == DEAD_NO)
+ {
+ self.think = bumblebee_land;
+ self.nextthink = time;
+ }
+
+ self.movetype = MOVETYPE_TOSS;
+
+ if(!self.owner)
+ return;
+
+ fixedmakevectors(self.angles);
+ vector spot;
+ if(vlen(self.velocity) > autocvar_g_vehicle_bumblebee_speed_forward * 0.5)
+ spot = self.origin + v_up * 128 + v_forward * 300;
+ else
+ spot = self.origin + v_up * 128 - v_forward * 300;
+
+ spot = vehicles_findgoodexit(spot);
+
+ // Hide beam
+ if(self.gun3.enemy || !wasfreed(self.gun3.enemy)) {
+ self.gun3.enemy.effects |= EF_NODRAW;
+ }
+
+ self.owner.velocity = 0.75 * self.vehicle.velocity + normalize(spot - self.vehicle.origin) * 200;
+ self.owner.velocity_z += 10;
+ setorigin(self.owner, spot);
+
+ antilag_clear(self.owner);
+ self.owner = world;
+}
+
+void bumblebee_blowup()
+{SELFPARAM();
+ RadiusDamage(self, self.enemy, autocvar_g_vehicle_bumblebee_blowup_coredamage,
+ autocvar_g_vehicle_bumblebee_blowup_edgedamage,
+ autocvar_g_vehicle_bumblebee_blowup_radius, self, world,
+ autocvar_g_vehicle_bumblebee_blowup_forceintensity,
+ DEATH_VH_BUMB_DEATH, world);
+
+ sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
+ Send_Effect(EFFECT_EXPLOSION_BIG, (self.origin + '0 0 100') + (randomvec() * 80), '0 0 0', 1);
+
+ if(self.owner.deadflag == DEAD_DYING)
+ self.owner.deadflag = DEAD_DEAD;
+
+ remove(self);
+}
+
+void bumblebee_diethink()
+{SELFPARAM();
+ if(time >= self.wait)
+ self.think = bumblebee_blowup;
+
+ if(random() < 0.1)
+ {
+ sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
+ Send_Effect(EFFECT_EXPLOSION_SMALL, randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
+ }
+
+ self.nextthink = time + 0.1;
+}
+
+spawnfunc(vehicle_bumblebee)
+{
+ if(!autocvar_g_vehicle_bumblebee) { remove(self); return; }
+ if(!vehicle_initialize(VEH_BUMBLEBEE, false)) { remove(self); return; }
+}
+
+ METHOD(Bumblebee, vr_impact, void(Bumblebee thisveh))
+ {
+ if(autocvar_g_vehicle_bumblebee_bouncepain)
+ vehicles_impact(autocvar_g_vehicle_bumblebee_bouncepain_x, autocvar_g_vehicle_bumblebee_bouncepain_y, autocvar_g_vehicle_bumblebee_bouncepain_z);
+ }
+ METHOD(Bumblebee, vr_enter, void(Bumblebee thisveh))
+ {
+ SELFPARAM();
+ self.touch = bumblebee_touch;
+ self.nextthink = 0;
+ self.movetype = MOVETYPE_BOUNCEMISSILE;
+ }
+ METHOD(Bumblebee, vr_think, void(Bumblebee thisveh))
+ {
+ SELFPARAM();
+ self.angles_z *= 0.8;
+ self.angles_x *= 0.8;
+
+ self.nextthink = time;
+
+ if(!self.owner)
+ {
+ entity oldself = self;
+ if(self.gunner1)
+ {
+ setself(self.gunner1);
+ oldself.gun1.vehicle_exit(VHEF_EJECT);
+ entity oldother = other;
+ other = self;
+ setself(oldself);
+ self.phase = 0;
+ self.touch();
+ other = oldother;
+ return;
+ }
+
+ if(self.gunner2)
+ {
+ setself(self.gunner2);
+ oldself.gun2.vehicle_exit(VHEF_EJECT);
+ entity oldother = other;
+ other = self;
+ setself(oldself);
+ self.phase = 0;
+ self.touch();
+ other = oldother;
+ return;
+ }
+ }
+ }
+ METHOD(Bumblebee, vr_death, void(Bumblebee thisveh))
+ {
+ SELFPARAM();
+ entity oldself = self;
+
+ CSQCModel_UnlinkEntity(self);
+
+ // Hide beam
+ if(self.gun3.enemy || !wasfreed(self.gun3.enemy))
+ self.gun3.enemy.effects |= EF_NODRAW;
+
+ if(self.gunner1)
+ {
+ setself(self.gunner1);
+ oldself.gun1.vehicle_exit(VHEF_EJECT);
+ setself(oldself);
+ }
+
+ if(self.gunner2)
+ {
+ setself(self.gunner2);
+ oldself.gun2.vehicle_exit(VHEF_EJECT);
+ setself(oldself);
+ }
+
+ self.vehicle_exit(VHEF_EJECT);
+
+ fixedmakevectors(self.angles);
+ vehicle_tossgib(self.gun1, self.velocity + v_right * 300 + v_up * 100 + randomvec() * 200, "cannon_right", rint(random()), rint(random()), 6, randomvec() * 200);
+ vehicle_tossgib(self.gun2, self.velocity + v_right * -300 + v_up * 100 + randomvec() * 200, "cannon_left", rint(random()), rint(random()), 6, randomvec() * 200);
+ vehicle_tossgib(self.gun3, self.velocity + v_forward * 300 + v_up * -100 + randomvec() * 200, "raygun", rint(random()), rint(random()), 6, randomvec() * 300);
+
+ entity _body = vehicle_tossgib(self, self.velocity + randomvec() * 200, "", rint(random()), rint(random()), 6, randomvec() * 100);
+
+ if(random() > 0.5)
+ _body.touch = bumblebee_blowup;
+ else
+ _body.touch = func_null;
+
+ _body.think = bumblebee_diethink;
+ _body.nextthink = time;
+ _body.wait = time + 2 + (random() * 8);
+ _body.owner = self;
+ _body.enemy = self.enemy;
+ _body.scale = 1.5;
+ _body.angles = self.angles;
+
+ Send_Effect(EFFECT_EXPLOSION_MEDIUM, findbetterlocation(self.origin, 16), '0 0 0', 1);
+
+ self.health = 0;
+ self.event_damage = func_null;
+ self.solid = SOLID_NOT;
+ self.takedamage = DAMAGE_NO;
+ self.deadflag = DEAD_DYING;
+ self.movetype = MOVETYPE_NONE;
+ self.effects = EF_NODRAW;
+ self.colormod = '0 0 0';
+ self.avelocity = '0 0 0';
+ self.velocity = '0 0 0';
+ self.touch = func_null;
+ self.nextthink = 0;
+
+ setorigin(self, self.pos1);
+ }
+ METHOD(Bumblebee, vr_spawn, void(Bumblebee thisveh))
+ {
+ SELFPARAM();
+ if(!self.gun1)
+ {
+ // for some reason, autosizing of the shield entity refuses to work for this one so set it up in advance.
+ self.vehicle_shieldent = spawn();
+ self.vehicle_shieldent.effects = EF_LOWPRECISION;
+ setmodel(self.vehicle_shieldent, MDL_VEH_BUMBLEBEE_SHIELD);
+ setattachment(self.vehicle_shieldent, self, "");
+ setorigin(self.vehicle_shieldent, real_origin(self) - self.origin);
+ self.vehicle_shieldent.scale = 512 / vlen(self.maxs - self.mins);
+ self.vehicle_shieldent.think = shieldhit_think;
+ self.vehicle_shieldent.alpha = -1;
+ self.vehicle_shieldent.effects = EF_LOWPRECISION | EF_NODRAW;
+
+ self.gun1 = spawn();
+ self.gun2 = spawn();
+ self.gun3 = spawn();
+
+ self.vehicle_flags |= VHF_MULTISLOT;
+
+ self.gun1.owner = self;
+ self.gun2.owner = self;
+ self.gun3.owner = self;
+
+ self.gun1.classname = self.gun2.classname = "vehicle_playerslot";
+
+ setmodel(self.gun1, MDL_VEH_BUMBLEBEE_CANNON_RIGHT);
+ setmodel(self.gun2, MDL_VEH_BUMBLEBEE_CANNON_LEFT);
+ setmodel(self.gun3, MDL_VEH_BUMBLEBEE_CANNON_CENTER);
+
+ setattachment(self.gun1, self, "cannon_right");
+ setattachment(self.gun2, self, "cannon_left");
+
+ // Angled bones are no fun, messes up gun-aim; so work arround it.
+ self.gun3.pos1 = self.angles;
+ self.angles = '0 0 0';
+ vector ofs = gettaginfo(self, gettagindex(self, "raygun"));
+ ofs -= self.origin;
+ setattachment(self.gun3, self, "");
+ setorigin(self.gun3, ofs);
+ self.angles = self.gun3.pos1;
+
+ vehicle_addplayerslot(self, self.gun1, HUD_BUMBLEBEE_GUN, "models/vehicles/wakizashi_cockpit.dpm", bumblebee_gunner_frame, bumblebee_gunner_exit, bumblebee_gunner_enter);
+ vehicle_addplayerslot(self, self.gun2, HUD_BUMBLEBEE_GUN, "models/vehicles/wakizashi_cockpit.dpm", bumblebee_gunner_frame, bumblebee_gunner_exit, bumblebee_gunner_enter);
+
+ setorigin(self.vehicle_hudmodel, '50 0 -5'); // Move cockpit forward - down.
+ setorigin(self.vehicle_viewport, '5 0 2'); // Move camera forward up
+
+ //fixme-model-bones
+ setorigin(self.gun1.vehicle_hudmodel, '90 -27 -23');
+ setorigin(self.gun1.vehicle_viewport, '-85 0 50');
+ //fixme-model-bones
+ setorigin(self.gun2.vehicle_hudmodel, '90 27 -23');
+ setorigin(self.gun2.vehicle_viewport, '-85 0 50');
+
+ self.scale = 1.5;
+
+ // Raygun beam
+ if(self.gun3.enemy == world)
+ {
+ self.gun3.enemy = spawn();
+ Net_LinkEntity(self.gun3.enemy, true, 0, bumble_raygun_send);
+ self.gun3.enemy.SendFlags = BRG_SETUP;
+ self.gun3.enemy.cnt = autocvar_g_vehicle_bumblebee_raygun;
+ self.gun3.enemy.effects = EF_NODRAW | EF_LOWPRECISION;
+ }
+ }
+
+ self.vehicle_health = autocvar_g_vehicle_bumblebee_health;
+ self.vehicle_shield = autocvar_g_vehicle_bumblebee_shield;
+ self.solid = SOLID_BBOX;
+ self.movetype = MOVETYPE_TOSS;
+ self.damageforcescale = 0.025;
+
+ self.PlayerPhysplug = bumblebee_pilot_frame;
+
+ setorigin(self, self.origin + '0 0 25');
+ }
+ METHOD(Bumblebee, vr_setup, void(Bumblebee thisveh))
+ {
+ SELFPARAM();
+ if(autocvar_g_vehicle_bumblebee_energy)
+ if(autocvar_g_vehicle_bumblebee_energy_regen)
+ self.vehicle_flags |= VHF_ENERGYREGEN;
+
+ if(autocvar_g_vehicle_bumblebee_shield)
+ self.vehicle_flags |= VHF_HASSHIELD;
+
+ if(autocvar_g_vehicle_bumblebee_shield_regen)
+ self.vehicle_flags |= VHF_SHIELDREGEN;
+
+ if(autocvar_g_vehicle_bumblebee_health_regen)
+ self.vehicle_flags |= VHF_HEALTHREGEN;
+
+ self.vehicle_exit = bumblebee_exit;
+ self.respawntime = autocvar_g_vehicle_bumblebee_respawntime;
+ self.vehicle_health = autocvar_g_vehicle_bumblebee_health;
+ self.max_health = self.vehicle_health;
+ self.vehicle_shield = autocvar_g_vehicle_bumblebee_shield;
+ }
+
+#endif // SVQC
+#ifdef CSQC
+
+void CSQC_BUMBLE_GUN_HUD()
+{
+ Vehicles_drawHUD("vehicle_gunner", "vehicle_gunner_weapon1", string_null,
+ "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
+ string_null, '0 0 0',
+ string_null);
+}
+
+ METHOD(Bumblebee, vr_hud, void(Bumblebee thisveh))
+ {
+ Vehicles_drawHUD(VEH_BUMBLEBEE.m_icon, "vehicle_bumble_weapon1", "vehicle_bumble_weapon2",
+ "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
+ "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
+ vCROSS_HEAL);
+ }
+ METHOD(Bumblebee, vr_setup, void(Bumblebee thisveh))
+ {
+ AuxiliaryXhair[0].axh_image = vCROSS_LOCK; // Raygun-locked
+ AuxiliaryXhair[1].axh_image = vCROSS_BURST; // Gunner1
+ AuxiliaryXhair[2].axh_image = vCROSS_BURST; // Gunner2
+ }
+
+#endif
+#endif
--- /dev/null
+#ifndef BUMBLEBEE_H
+#define BUMBLEBEE_H
+
+#ifdef CSQC
+void bumble_raygun_read(bool bIsNew);
+
+void CSQC_BUMBLE_GUN_HUD();
+#endif
+
+#endif
--- /dev/null
+#ifndef VEHICLE_BUMBLEBEE_WEAPONS_H
+#define VEHICLE_BUMBLEBEE_WEAPONS_H
+
+#include "../../weapons/all.qh"
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+float autocvar_g_vehicle_bumblebee_cannon_cost;
+float autocvar_g_vehicle_bumblebee_cannon_damage;
+float autocvar_g_vehicle_bumblebee_cannon_radius;
+float autocvar_g_vehicle_bumblebee_cannon_refire;
+float autocvar_g_vehicle_bumblebee_cannon_speed;
+float autocvar_g_vehicle_bumblebee_cannon_spread;
+float autocvar_g_vehicle_bumblebee_cannon_force;
+
+bool bumble_raygun_send(entity this, entity to, int sf);
+
+void bumblebee_fire_cannon(entity _gun, string _tagname, entity _owner)
+{
+ vector v = gettaginfo(_gun, gettagindex(_gun, _tagname));
+ vehicles_projectile(EFFECT_BIGPLASMA_MUZZLEFLASH.eent_eff_name, SND(VEH_BUMBLEBEE_FIRE),
+ v, normalize(v_forward + randomvec() * autocvar_g_vehicle_bumblebee_cannon_spread) * autocvar_g_vehicle_bumblebee_cannon_speed,
+ autocvar_g_vehicle_bumblebee_cannon_damage, autocvar_g_vehicle_bumblebee_cannon_radius, autocvar_g_vehicle_bumblebee_cannon_force, 0,
+ DEATH_VH_BUMB_GUN, PROJECTILE_BUMBLE_GUN, 0, true, true, _owner);
+}
+
+bool bumble_raygun_send(entity this, entity to, float sf)
+{
+ WriteByte(MSG_ENTITY, ENT_CLIENT_BUMBLE_RAYGUN);
+
+ WriteByte(MSG_ENTITY, sf);
+ if(sf & BRG_SETUP)
+ {
+ WriteByte(MSG_ENTITY, num_for_edict(self.realowner));
+ WriteByte(MSG_ENTITY, self.realowner.team);
+ WriteByte(MSG_ENTITY, self.cnt);
+ }
+
+ if(sf & BRG_START)
+ {
+ WriteCoord(MSG_ENTITY, self.hook_start_x);
+ WriteCoord(MSG_ENTITY, self.hook_start_y);
+ WriteCoord(MSG_ENTITY, self.hook_start_z);
+ }
+
+ if(sf & BRG_END)
+ {
+ WriteCoord(MSG_ENTITY, self.hook_end_x);
+ WriteCoord(MSG_ENTITY, self.hook_end_y);
+ WriteCoord(MSG_ENTITY, self.hook_end_z);
+ }
+
+ return true;
+}
+
+#endif
+
+#ifdef CSQC
+
+void bumble_raygun_draw(entity this);
+
+void bumble_raygun_read(bool bIsNew)
+{SELFPARAM();
+ int sf = ReadByte();
+
+ if(sf & BRG_SETUP)
+ {
+ self.cnt = ReadByte();
+ self.team = ReadByte();
+ self.cnt = ReadByte();
+
+ if(self.cnt)
+ self.colormod = '1 0 0';
+ else
+ self.colormod = '0 1 0';
+
+ self.traileffect = EFFECT_BUMBLEBEE_HEAL_MUZZLEFLASH.m_id;
+ self.lip = particleeffectnum(EFFECT_BUMBLEBEE_HEAL_IMPACT);
+
+ self.draw = bumble_raygun_draw;
+ }
+
+
+ if(sf & BRG_START)
+ {
+ self.origin_x = ReadCoord();
+ self.origin_y = ReadCoord();
+ self.origin_z = ReadCoord();
+ setorigin(self, self.origin);
+ }
+
+ if(sf & BRG_END)
+ {
+ self.move_origin_x = ReadCoord();
+ self.move_origin_y = ReadCoord();
+ self.move_origin_z = ReadCoord();
+ }
+}
+
+void bumble_raygun_draw(entity this)
+{
+ float _len;
+ vector _dir;
+ vector _vtmp1, _vtmp2;
+
+ _len = vlen(self.origin - self.move_origin);
+ _dir = normalize(self.move_origin - self.origin);
+
+ if(self.total_damages < time)
+ {
+ boxparticles(particleeffectnum(Effects[self.traileffect]), self, self.origin, self.origin + _dir * -64, _dir * -_len , _dir * -_len, 1, PARTICLES_USEALPHA);
+ boxparticles(self.lip, self, self.move_origin, self.move_origin + _dir * -64, _dir * -200 , _dir * -200, 1, PARTICLES_USEALPHA);
+ self.total_damages = time + 0.1;
+ }
+
+ float i, df, sz, al;
+ for(i = -0.1; i < 0.2; i += 0.1)
+ {
+ df = DRAWFLAG_NORMAL; //((random() < 0.5) ? DRAWFLAG_ADDITIVE : DRAWFLAG_SCREEN);
+ sz = 5 + random() * 5;
+ al = 0.25 + random() * 0.5;
+ _vtmp1 = self.origin + _dir * _len * (0.25 + i);
+ _vtmp1 += (randomvec() * (_len * 0.2) * (frametime * 2)); //self.raygun_l1;
+ Draw_CylindricLine(self.origin, _vtmp1, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin);
+
+ _vtmp2 = self.origin + _dir * _len * (0.5 + i);
+ _vtmp2 += (randomvec() * (_len * 0.2) * (frametime * 5)); //self.raygun_l2;
+ Draw_CylindricLine(_vtmp1, _vtmp2, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin);
+
+ _vtmp1 = self.origin + _dir * _len * (0.75 + i);
+ _vtmp1 += randomvec() * (_len * 0.2) * (frametime * 10); //self.raygun_l3;
+ Draw_CylindricLine(_vtmp2, _vtmp1, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin);
+
+ Draw_CylindricLine(_vtmp1, self.move_origin + randomvec() * 32, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin);
+ }
+}
+
+#endif
+
+#endif
--- /dev/null
+#ifndef VEHICLE_RACER
+#define VEHICLE_RACER
+
+#include "racer_weapon.qc"
+
+CLASS(Racer, Vehicle)
+/* spawnflags */ ATTRIB(Racer, spawnflags, int, VHF_DMGSHAKE | VHF_DMGROLL);
+/* mins */ ATTRIB(Racer, mins, vector, '-120 -120 -40' * 0.5);
+/* maxs */ ATTRIB(Racer, maxs, vector, '120 120 40' * 0.5);
+/* model */ ATTRIB(Racer, mdl, string, "models/vehicles/wakizashi.dpm");
+/* model */ ATTRIB(Racer, model, string, "models/vehicles/wakizashi.dpm");
+/* head_model */ ATTRIB(Racer, head_model, string, "null");
+/* hud_model */ ATTRIB(Racer, hud_model, string, "models/vehicles/wakizashi_cockpit.dpm");
+/* tags */ ATTRIB(Racer, tag_head, string, "");
+/* tags */ ATTRIB(Racer, tag_hud, string, "");
+/* tags */ ATTRIB(Racer, tag_view, string, "tag_viewport");
+/* netname */ ATTRIB(Racer, netname, string, "racer");
+/* fullname */ ATTRIB(Racer, vehicle_name, string, _("Racer"));
+/* icon */ ATTRIB(Racer, m_icon, string, "vehicle_racer");
+ENDCLASS(Racer)
+REGISTER_VEHICLE(RACER, NEW(Racer));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#include "racer_weapon.qc"
+
+#ifdef SVQC
+#include "../../effects/effects.qh"
+#include "../../triggers/trigger/impulse.qh"
+
+bool autocvar_g_vehicle_racer;
+
+float autocvar_g_vehicle_racer_speed_afterburn;
+float autocvar_g_vehicle_racer_afterburn_cost;
+
+float autocvar_g_vehicle_racer_waterburn_cost;
+float autocvar_g_vehicle_racer_waterburn_speed;
+
+float autocvar_g_vehicle_racer_water_speed_forward;
+float autocvar_g_vehicle_racer_water_speed_strafe;
+
+float autocvar_g_vehicle_racer_pitchlimit = 30;
+
+float autocvar_g_vehicle_racer_water_downforce = 0.03;
+float autocvar_g_vehicle_racer_water_upforcedamper = 15;
+
+float autocvar_g_vehicle_racer_anglestabilizer;
+float autocvar_g_vehicle_racer_downforce;
+
+float autocvar_g_vehicle_racer_speed_forward;
+float autocvar_g_vehicle_racer_speed_strafe;
+float autocvar_g_vehicle_racer_springlength;
+float autocvar_g_vehicle_racer_upforcedamper;
+float autocvar_g_vehicle_racer_friction;
+
+float autocvar_g_vehicle_racer_water_time = 5;
+
+float autocvar_g_vehicle_racer_hovertype;
+float autocvar_g_vehicle_racer_hoverpower;
+
+float autocvar_g_vehicle_racer_turnroll;
+float autocvar_g_vehicle_racer_turnspeed;
+float autocvar_g_vehicle_racer_pitchspeed;
+
+float autocvar_g_vehicle_racer_energy;
+float autocvar_g_vehicle_racer_energy_regen;
+float autocvar_g_vehicle_racer_energy_regen_pause;
+
+float autocvar_g_vehicle_racer_health;
+float autocvar_g_vehicle_racer_health_regen;
+float autocvar_g_vehicle_racer_health_regen_pause;
+
+float autocvar_g_vehicle_racer_shield;
+float autocvar_g_vehicle_racer_shield_regen;
+float autocvar_g_vehicle_racer_shield_regen_pause;
+
+float autocvar_g_vehicle_racer_rocket_locktarget;
+float autocvar_g_vehicle_racer_rocket_locking_time;
+float autocvar_g_vehicle_racer_rocket_locking_releasetime;
+float autocvar_g_vehicle_racer_rocket_locked_time;
+
+float autocvar_g_vehicle_racer_respawntime;
+
+float autocvar_g_vehicle_racer_blowup_radius;
+float autocvar_g_vehicle_racer_blowup_coredamage;
+float autocvar_g_vehicle_racer_blowup_edgedamage;
+float autocvar_g_vehicle_racer_blowup_forceintensity;
+
+float autocvar_g_vehicle_racer_bouncefactor;
+float autocvar_g_vehicle_racer_bouncestop;
+vector autocvar_g_vehicle_racer_bouncepain;
+
+.float racer_watertime;
+
+var vector racer_force_from_tag(string tag_name, float spring_length, float max_power);
+
+void racer_align4point(float _delta)
+{SELFPARAM();
+ vector push_vector;
+ float fl_push, fr_push, bl_push, br_push;
+
+ push_vector = racer_force_from_tag("tag_engine_fr", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
+ fr_push = force_fromtag_normpower;
+ //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
+
+ push_vector += racer_force_from_tag("tag_engine_fl", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
+ fl_push = force_fromtag_normpower;
+ //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
+
+ push_vector += racer_force_from_tag("tag_engine_br", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
+ br_push = force_fromtag_normpower;
+ //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
+
+ push_vector += racer_force_from_tag("tag_engine_bl", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
+ bl_push = force_fromtag_normpower;
+ //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
+
+ self.velocity += push_vector * _delta;
+
+ float uforce = autocvar_g_vehicle_racer_upforcedamper;
+
+ int cont = pointcontents(self.origin - '0 0 64');
+ if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
+ {
+ uforce = autocvar_g_vehicle_racer_water_upforcedamper;
+
+ if(self.owner.BUTTON_CROUCH && time < self.air_finished)
+ self.velocity_z += 30;
+ else
+ self.velocity_z += 200;
+ }
+
+
+ // Anti ocilation
+ if(self.velocity_z > 0)
+ self.velocity_z *= 1 - uforce * _delta;
+
+ push_vector_x = (fl_push - bl_push);
+ push_vector_x += (fr_push - br_push);
+ push_vector_x *= 360;
+
+ push_vector_z = (fr_push - fl_push);
+ push_vector_z += (br_push - bl_push);
+ push_vector_z *= 360;
+
+ // Apply angle diffrance
+ self.angles_z += push_vector_z * _delta;
+ self.angles_x += push_vector_x * _delta;
+
+ // Apply stabilizer
+ self.angles_x *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * _delta);
+ self.angles_z *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * _delta);
+}
+
+void racer_fire_rocket_aim(string tagname, entity trg)
+{
+ SELFPARAM();
+ vector v = gettaginfo(self, gettagindex(self, tagname));
+ racer_fire_rocket(v, v_forward, trg);
+}
+
+float racer_frame()
+{SELFPARAM();
+ entity player, racer;
+ vector df;
+ float ftmp;
+
+ if(intermission_running)
+ {
+ self.vehicle.velocity = '0 0 0';
+ self.vehicle.avelocity = '0 0 0';
+ return 1;
+ }
+
+ player = self;
+ racer = self.vehicle;
+ setself(racer);
+
+ vehicles_painframe();
+
+ if(pointcontents(racer.origin) != CONTENT_WATER)
+ racer.air_finished = time + autocvar_g_vehicle_racer_water_time;
+
+ if(racer.deadflag != DEAD_NO)
+ {
+ setself(player);
+ player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
+ return 1;
+ }
+
+ racer_align4point(PHYS_INPUT_TIMELENGTH);
+
+ player.BUTTON_ZOOM = player.BUTTON_CROUCH = 0;
+
+ crosshair_trace(player);
+
+ racer.angles_x *= -1;
+
+ // Yaw
+ ftmp = autocvar_g_vehicle_racer_turnspeed * PHYS_INPUT_TIMELENGTH;
+ ftmp = bound(-ftmp, shortangle_f(player.v_angle_y - racer.angles_y, racer.angles_y), ftmp);
+ racer.angles_y = anglemods(racer.angles_y + ftmp);
+
+ // Roll
+ racer.angles_z += -ftmp * autocvar_g_vehicle_racer_turnroll * PHYS_INPUT_TIMELENGTH;
+
+ // Pitch
+ ftmp = autocvar_g_vehicle_racer_pitchspeed * PHYS_INPUT_TIMELENGTH;
+ ftmp = bound(-ftmp, shortangle_f(player.v_angle_x - racer.angles_x, racer.angles_x), ftmp);
+ racer.angles_x = bound(-autocvar_g_vehicle_racer_pitchlimit, anglemods(racer.angles_x + ftmp), autocvar_g_vehicle_racer_pitchlimit);
+
+ makevectors(racer.angles);
+ racer.angles_x *= -1;
+
+ //ftmp = racer.velocity_z;
+ df = racer.velocity * -autocvar_g_vehicle_racer_friction;
+ //racer.velocity_z = ftmp;
+
+ int cont = pointcontents(racer.origin);
+ if(vlen(player.movement) != 0)
+ {
+ if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
+ {
+ if(player.movement_x) { df += v_forward * ((player.movement_x > 0) ? autocvar_g_vehicle_racer_water_speed_forward : -autocvar_g_vehicle_racer_water_speed_forward); }
+ if(player.movement_y) { df += v_right * ((player.movement_y > 0) ? autocvar_g_vehicle_racer_water_speed_strafe : -autocvar_g_vehicle_racer_water_speed_strafe); }
+ }
+ else
+ {
+ if(player.movement_x) { df += v_forward * ((player.movement_x > 0) ? autocvar_g_vehicle_racer_speed_forward : -autocvar_g_vehicle_racer_speed_forward); }
+ if(player.movement_y) { df += v_right * ((player.movement_y > 0) ? autocvar_g_vehicle_racer_speed_strafe : -autocvar_g_vehicle_racer_speed_strafe); }
+ }
+
+#ifdef SVQC
+ if(self.sound_nexttime < time || self.sounds != 1)
+ {
+ self.sounds = 1;
+ self.sound_nexttime = time + 10.922667; //soundlength("vehicles/racer_move.wav");
+ sound (self, CH_TRIGGER_SINGLE, SND_VEH_RACER_MOVE, VOL_VEHICLEENGINE, ATTEN_NORM);
+ }
+#endif
+ }
+#ifdef SVQC
+ else
+ {
+ if(self.sound_nexttime < time || self.sounds != 0)
+ {
+ self.sounds = 0;
+ self.sound_nexttime = time + 11.888604; //soundlength("vehicles/racer_idle.wav");
+ sound (self, CH_TRIGGER_SINGLE, SND_VEH_RACER_IDLE, VOL_VEHICLEENGINE, ATTEN_NORM);
+ }
+ }
+#endif
+
+ // Afterburn
+ if (PHYS_INPUT_BUTTON_JUMP(player) && racer.vehicle_energy >= (autocvar_g_vehicle_racer_afterburn_cost * PHYS_INPUT_TIMELENGTH))
+ {
+#ifdef SVQC
+ if(time - racer.wait > 0.2)
+ pointparticles(particleeffectnum(EFFECT_RACER_BOOSTER), self.origin - v_forward * 32, v_forward * vlen(self.velocity), 1);
+#endif
+
+ racer.wait = time;
+
+ if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
+ {
+ racer.vehicle_energy -= autocvar_g_vehicle_racer_waterburn_cost * PHYS_INPUT_TIMELENGTH;
+ df += (v_forward * autocvar_g_vehicle_racer_waterburn_speed);
+ }
+ else
+ {
+ racer.vehicle_energy -= autocvar_g_vehicle_racer_afterburn_cost * PHYS_INPUT_TIMELENGTH;
+ df += (v_forward * autocvar_g_vehicle_racer_speed_afterburn);
+ }
+
+#ifdef SVQC
+ if(racer.invincible_finished < time)
+ {
+ traceline(racer.origin, racer.origin - '0 0 256', MOVE_NORMAL, self);
+ if(trace_fraction != 1.0)
+ pointparticles(particleeffectnum(EFFECT_SMOKE_SMALL), trace_endpos, '0 0 0', 1);
+
+ racer.invincible_finished = time + 0.1 + (random() * 0.1);
+ }
+
+ if(racer.strength_finished < time)
+ {
+ racer.strength_finished = time + 10.922667; //soundlength("vehicles/racer_boost.wav");
+ sound (racer.tur_head, CH_TRIGGER_SINGLE, SND_VEH_RACER_BOOST, VOL_VEHICLEENGINE, ATTEN_NORM);
+ }
+#endif
+ }
+ else
+ {
+ racer.strength_finished = 0;
+ sound (racer.tur_head, CH_TRIGGER_SINGLE, SND_Null, VOL_VEHICLEENGINE, ATTEN_NORM);
+ }
+
+ if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
+ racer.racer_watertime = time;
+
+ float dforce = autocvar_g_vehicle_racer_downforce;
+ if(time - racer.racer_watertime <= 3)
+ dforce = autocvar_g_vehicle_racer_water_downforce;
+
+ df -= v_up * (vlen(racer.velocity) * dforce);
+ player.movement = racer.velocity += df * PHYS_INPUT_TIMELENGTH;
+
+#ifdef SVQC
+ Weapon wep1 = WEP_RACER;
+ if (!forbidWeaponUse(player))
+ if (player.BUTTON_ATCK)
+ if (wep1.wr_checkammo1(wep1))
+ {
+ string tagname = (racer.cnt)
+ ? (racer.cnt = 0, "tag_fire1")
+ : (racer.cnt = 1, "tag_fire2");
+ vector org = gettaginfo(self, gettagindex(self, tagname));
+ w_shotorg = org;
+ w_shotdir = v_forward;
+ // Fix z-aim (for chase mode)
+ crosshair_trace(player);
+ w_shotdir.z = normalize(trace_endpos - org).z * 0.5;
+ wep1.wr_think(wep1, self, true, false);
+ }
+
+ if(autocvar_g_vehicle_racer_rocket_locktarget)
+ {
+ vehicles_locktarget((1 / autocvar_g_vehicle_racer_rocket_locking_time) * frametime,
+ (1 / autocvar_g_vehicle_racer_rocket_locking_releasetime) * frametime,
+ autocvar_g_vehicle_racer_rocket_locked_time);
+
+ if(self.lock_target)
+ {
+ if(racer.lock_strength == 1)
+ UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '1 0 0', 0);
+ else if(self.lock_strength > 0.5)
+ UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '0 1 0', 0);
+ else if(self.lock_strength < 0.5)
+ UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '0 0 1', 0);
+ }
+ }
+
+ if(!forbidWeaponUse(player))
+ if(time > racer.delay)
+ if(player.BUTTON_ATCK2)
+ {
+ racer.misc_bulletcounter += 1;
+ racer.delay = time + 0.3;
+
+ if(racer.misc_bulletcounter == 1)
+ {
+ racer_fire_rocket_aim("tag_rocket_r", (racer.lock_strength == 1 && racer.lock_target) ? racer.lock_target : world);
+ player.vehicle_ammo2 = 50;
+ }
+ else if(racer.misc_bulletcounter == 2)
+ {
+ racer_fire_rocket_aim("tag_rocket_l", (racer.lock_strength == 1 && racer.lock_target) ? racer.lock_target : world);
+ racer.lock_strength = 0;
+ racer.lock_target = world;
+ racer.misc_bulletcounter = 0;
+ racer.delay = time + autocvar_g_vehicle_racer_rocket_refire;
+ racer.lip = time;
+ player.vehicle_ammo2 = 0;
+ }
+ }
+ else if(racer.misc_bulletcounter == 0)
+ player.vehicle_ammo2 = 100;
+
+ player.vehicle_reload2 = bound(0, 100 * ((time - racer.lip) / (racer.delay - racer.lip)), 100);
+
+ if(racer.vehicle_flags & VHF_SHIELDREGEN)
+ vehicles_regen(racer.dmg_time, vehicle_shield, autocvar_g_vehicle_racer_shield, autocvar_g_vehicle_racer_shield_regen_pause, autocvar_g_vehicle_racer_shield_regen, frametime, true);
+
+ if(racer.vehicle_flags & VHF_HEALTHREGEN)
+ vehicles_regen(racer.dmg_time, vehicle_health, autocvar_g_vehicle_racer_health, autocvar_g_vehicle_racer_health_regen_pause, autocvar_g_vehicle_racer_health_regen, frametime, false);
+
+ if(racer.vehicle_flags & VHF_ENERGYREGEN)
+ vehicles_regen(racer.wait, vehicle_energy, autocvar_g_vehicle_racer_energy, autocvar_g_vehicle_racer_energy_regen_pause, autocvar_g_vehicle_racer_energy_regen, frametime, false);
+
+
+ VEHICLE_UPDATE_PLAYER(player, health, racer);
+ VEHICLE_UPDATE_PLAYER(player, energy, racer);
+
+ if(racer.vehicle_flags & VHF_HASSHIELD)
+ VEHICLE_UPDATE_PLAYER(player, shield, racer);
+
+ player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
+#endif
+
+ setorigin(player,racer.origin + '0 0 32');
+ player.velocity = racer.velocity;
+
+ setself(player);
+ return 1;
+}
+
+void racer_think()
+{SELFPARAM();
+ self.nextthink = time;
+
+ float pushdeltatime = time - self.lastpushtime;
+ if (pushdeltatime > 0.15) pushdeltatime = 0;
+ self.lastpushtime = time;
+ if(!pushdeltatime) return;
+
+ tracebox(self.origin, self.mins, self.maxs, self.origin - ('0 0 1' * autocvar_g_vehicle_racer_springlength), MOVE_NOMONSTERS, self);
+
+ vector df = self.velocity * -autocvar_g_vehicle_racer_friction;
+ df_z += (1 - trace_fraction) * autocvar_g_vehicle_racer_hoverpower + sin(time * 2) * (autocvar_g_vehicle_racer_springlength * 2);
+
+ float forced = autocvar_g_vehicle_racer_upforcedamper;
+
+ int cont = pointcontents(self.origin - '0 0 64');
+ if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
+ {
+ forced = autocvar_g_vehicle_racer_water_upforcedamper;
+ self.velocity_z += 200;
+ }
+
+ self.velocity += df * pushdeltatime;
+ if(self.velocity_z > 0)
+ self.velocity_z *= 1 - forced * pushdeltatime;
+
+ self.angles_x *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * pushdeltatime);
+ self.angles_z *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * pushdeltatime);
+
+ CSQCMODEL_AUTOUPDATE(self);
+}
+
+void racer_exit(float eject)
+{SELFPARAM();
+ vector spot;
+
+ self.think = racer_think;
+ self.nextthink = time;
+ self.movetype = MOVETYPE_BOUNCE;
+ sound (self.tur_head, CH_TRIGGER_SINGLE, SND_Null, VOL_VEHICLEENGINE, ATTEN_NORM);
+
+ if(!self.owner)
+ return;
+
+ makevectors(self.angles);
+ if(eject)
+ {
+ spot = self.origin + v_forward * 100 + '0 0 64';
+ spot = vehicles_findgoodexit(spot);
+ setorigin(self.owner , spot);
+ self.owner.velocity = (v_up + v_forward * 0.25) * 750;
+ self.owner.oldvelocity = self.owner.velocity;
+ }
+ else
+ {
+ if(vlen(self.velocity) > 2 * autocvar_sv_maxairspeed)
+ {
+ self.owner.velocity = normalize(self.velocity) * autocvar_sv_maxairspeed * 2;
+ self.owner.velocity_z += 200;
+ spot = self.origin + v_forward * 32 + '0 0 32';
+ spot = vehicles_findgoodexit(spot);
+ }
+ else
+ {
+ self.owner.velocity = self.velocity * 0.5;
+ self.owner.velocity_z += 10;
+ spot = self.origin - v_forward * 200 + '0 0 32';
+ spot = vehicles_findgoodexit(spot);
+ }
+ self.owner.oldvelocity = self.owner.velocity;
+ setorigin(self.owner , spot);
+ }
+ antilag_clear(self.owner);
+ self.owner = world;
+}
+
+void racer_blowup()
+{SELFPARAM();
+ self.deadflag = DEAD_DEAD;
+ self.vehicle_exit(VHEF_NORMAL);
+
+ RadiusDamage (self, self.enemy, autocvar_g_vehicle_racer_blowup_coredamage,
+ autocvar_g_vehicle_racer_blowup_edgedamage,
+ autocvar_g_vehicle_racer_blowup_radius, world, world,
+ autocvar_g_vehicle_racer_blowup_forceintensity,
+ DEATH_VH_WAKI_DEATH, world);
+
+ self.nextthink = time + autocvar_g_vehicle_racer_respawntime;
+ self.think = vehicles_spawn;
+ self.movetype = MOVETYPE_NONE;
+ self.effects = EF_NODRAW;
+ self.solid = SOLID_NOT;
+
+ self.colormod = '0 0 0';
+ self.avelocity = '0 0 0';
+ self.velocity = '0 0 0';
+
+ setorigin(self, self.pos1);
+}
+
+void racer_blowup_think()
+{SELFPARAM();
+ self.nextthink = time;
+
+ if(time >= self.delay)
+ racer_blowup();
+
+ CSQCMODEL_AUTOUPDATE(self);
+}
+
+void racer_deadtouch()
+{SELFPARAM();
+ self.avelocity_x *= 0.7;
+ self.cnt -= 1;
+ if(self.cnt <= 0)
+ racer_blowup();
+}
+
+spawnfunc(vehicle_racer)
+{
+ if(!autocvar_g_vehicle_racer) { remove(self); return; }
+ if(!vehicle_initialize(VEH_RACER, false)) { remove(self); return; }
+}
+
+#endif // SVQC
+
+#ifdef CSQC
+#if 0
+void racer_draw()
+{SELFPARAM();
+ float pushdeltatime = time - self.lastpushtime;
+ if (pushdeltatime > 0.15) pushdeltatime = 0;
+ self.lastpushtime = time;
+ if(!pushdeltatime) return;
+
+ tracebox(self.move_origin, self.mins, self.maxs, self.move_origin - ('0 0 1' * getstatf(STAT_VEH_RACER_SPRINGLENGTH)), MOVE_NOMONSTERS, self);
+
+ vector df = self.move_velocity * -getstatf(STAT_VEH_RACER_FRICTION);
+ df_z += (1 - trace_fraction) * getstatf(STAT_VEH_RACER_HOVERPOWER) + sin(time * 2) * (getstatf(STAT_VEH_RACER_SPRINGLENGTH) * 2);
+
+ float forced = getstatf(STAT_VEH_RACER_UPFORCEDAMPER);
+
+ int cont = pointcontents(self.move_origin - '0 0 64');
+ if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
+ {
+ forced = getstatf(STAT_VEH_RACER_WATER_UPFORCEDAMPER);
+ self.move_velocity_z += 200;
+ }
+
+ self.move_velocity += df * pushdeltatime;
+ if(self.move_velocity_z > 0)
+ self.move_velocity_z *= 1 - forced * pushdeltatime;
+
+ self.move_angles_x *= 1 - (getstatf(STAT_VEH_RACER_ANGLESTABILIZER) * pushdeltatime);
+ self.move_angles_z *= 1 - (getstatf(STAT_VEH_RACER_ANGLESTABILIZER) * pushdeltatime);
+
+ Movetype_Physics_MatchServer(false);
+}
+#endif
+#endif
+
+ METHOD(Racer, vr_impact, void(Racer thisveh))
+ {
+ #ifdef SVQC
+ if(autocvar_g_vehicle_racer_bouncepain)
+ vehicles_impact(autocvar_g_vehicle_racer_bouncepain_x, autocvar_g_vehicle_racer_bouncepain_y, autocvar_g_vehicle_racer_bouncepain_z);
+ #endif
+ }
+
+ METHOD(Racer, vr_enter, void(Racer thisveh))
+ {
+ #ifdef SVQC
+ self.movetype = MOVETYPE_BOUNCE;
+ self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_racer_health) * 100;
+ self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_racer_shield) * 100;
+
+ if(self.owner.flagcarried)
+ setorigin(self.owner.flagcarried, '-190 0 96');
+ #elif defined(CSQC)
+
+ self.move_movetype = MOVETYPE_BOUNCE;
+ #endif
+ }
+
+ METHOD(Racer, vr_spawn, void(Racer thisveh))
+ {
+ #ifdef SVQC
+ if(self.scale != 0.5)
+ {
+ if(autocvar_g_vehicle_racer_hovertype != 0)
+ racer_force_from_tag = vehicles_force_fromtag_maglev;
+ else
+ racer_force_from_tag = vehicles_force_fromtag_hover;
+
+ // FIXME: this be hakkz, fix the models insted (scale body, add tag_viewport to the hudmodel).
+ self.scale = 0.5;
+ setattachment(self.vehicle_hudmodel, self, "");
+ setattachment(self.vehicle_viewport, self, "tag_viewport");
+
+ self.mass = 900;
+ }
+
+ self.think = racer_think;
+ self.nextthink = time;
+ self.vehicle_health = autocvar_g_vehicle_racer_health;
+ self.vehicle_shield = autocvar_g_vehicle_racer_shield;
+
+ self.movetype = MOVETYPE_TOSS;
+ self.solid = SOLID_SLIDEBOX;
+ self.delay = time;
+ self.scale = 0.5;
+
+ self.PlayerPhysplug = racer_frame;
+
+ self.bouncefactor = autocvar_g_vehicle_racer_bouncefactor;
+ self.bouncestop = autocvar_g_vehicle_racer_bouncestop;
+ self.damageforcescale = 0.5;
+ self.vehicle_health = autocvar_g_vehicle_racer_health;
+ self.vehicle_shield = autocvar_g_vehicle_racer_shield;
+ #endif
+ }
+
+ METHOD(Racer, vr_death, void(Racer thisveh))
+ {
+ #ifdef SVQC
+ self.SendEntity = func_null; // stop networking this racer (for now)
+ self.health = 0;
+ self.event_damage = func_null;
+ self.solid = SOLID_CORPSE;
+ self.takedamage = DAMAGE_NO;
+ self.deadflag = DEAD_DYING;
+ self.movetype = MOVETYPE_BOUNCE;
+ self.wait = time;
+ self.delay = 2 + time + random() * 3;
+ self.cnt = 1 + random() * 2;
+ self.touch = racer_deadtouch;
+
+ Send_Effect(EFFECT_EXPLOSION_MEDIUM, self.origin, '0 0 0', 1);
+
+ if(random() < 0.5)
+ self.avelocity_z = 32;
+ else
+ self.avelocity_z = -32;
+
+ self.avelocity_x = -vlen(self.velocity) * 0.2;
+ self.velocity += '0 0 700';
+ self.colormod = '-0.5 -0.5 -0.5';
+
+ self.think = racer_blowup_think;
+ self.nextthink = time;
+ #endif
+ }
+
+#ifdef CSQC
+ METHOD(Racer, vr_hud, void(Racer thisveh))
+ {
+ Vehicles_drawHUD(VEH_RACER.m_icon, "vehicle_racer_weapon1", "vehicle_racer_weapon2",
+ "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
+ "vehicle_icon_ammo2", autocvar_hud_progressbar_vehicles_ammo2_color,
+ vCROSS_GUIDE);
+ }
+#endif
+ METHOD(Racer, vr_setup, void(Racer thisveh))
+ {
+ #ifdef SVQC
+ self.vehicle_exit = racer_exit;
+ #endif
+
+ #ifdef SVQC
+ // we have no need to network energy
+ if(autocvar_g_vehicle_racer_energy)
+ if(autocvar_g_vehicle_racer_energy_regen)
+ self.vehicle_flags |= VHF_ENERGYREGEN;
+
+ if(autocvar_g_vehicle_racer_shield)
+ self.vehicle_flags |= VHF_HASSHIELD;
+
+ if(autocvar_g_vehicle_racer_shield_regen)
+ self.vehicle_flags |= VHF_SHIELDREGEN;
+
+ if(autocvar_g_vehicle_racer_health_regen)
+ self.vehicle_flags |= VHF_HEALTHREGEN;
+
+ self.respawntime = autocvar_g_vehicle_racer_respawntime;
+ self.vehicle_health = autocvar_g_vehicle_racer_health;
+ self.vehicle_shield = autocvar_g_vehicle_racer_shield;
+ self.max_health = self.vehicle_health;
+ #endif
+
+ #ifdef CSQC
+ AuxiliaryXhair[0].axh_image = vCROSS_LOCK; // Rocket
+ #endif
+ }
+
+#endif
--- /dev/null
+#ifndef VEHICLE_RACER_WEAPON_H
+#define VEHICLE_RACER_WEAPON_H
+
+#include "../../weapons/all.qh"
+
+CLASS(RacerAttack, PortoLaunch)
+/* flags */ ATTRIB(RacerAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse */ ATTRIB(RacerAttack, impulse, int, 3);
+/* refname */ ATTRIB(RacerAttack, netname, string, "racercannon");
+/* wepname */ ATTRIB(RacerAttack, message, string, _("Racer cannon"));
+ENDCLASS(RacerAttack)
+REGISTER_WEAPON(RACER, NEW(RacerAttack));
+
+// TODO: move into implementation
+#ifdef SVQC
+float autocvar_g_vehicle_racer_rocket_refire;
+void racer_fire_rocket(vector org, vector dir, entity trg);
+#endif
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+float autocvar_g_vehicle_racer_cannon_cost;
+float autocvar_g_vehicle_racer_cannon_damage;
+float autocvar_g_vehicle_racer_cannon_radius;
+float autocvar_g_vehicle_racer_cannon_refire;
+float autocvar_g_vehicle_racer_cannon_speed;
+float autocvar_g_vehicle_racer_cannon_spread;
+float autocvar_g_vehicle_racer_cannon_force;
+
+float autocvar_g_vehicle_racer_rocket_accel;
+float autocvar_g_vehicle_racer_rocket_damage;
+float autocvar_g_vehicle_racer_rocket_radius;
+float autocvar_g_vehicle_racer_rocket_force;
+float autocvar_g_vehicle_racer_rocket_speed;
+float autocvar_g_vehicle_racer_rocket_turnrate;
+
+float autocvar_g_vehicle_racer_rocket_climbspeed;
+float autocvar_g_vehicle_racer_rocket_locked_maxangle;
+
+void racer_fire_rocket(vector org, vector dir, entity trg);
+METHOD(RacerAttack, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
+{
+ bool isPlayer = IS_PLAYER(actor);
+ entity player = isPlayer ? actor : actor.owner;
+ entity veh = player.vehicle;
+ if (fire1)
+ if (weapon_prepareattack(thiswep, player, false, autocvar_g_vehicle_racer_cannon_refire)) {
+ if (veh) {
+ veh.vehicle_energy -= autocvar_g_vehicle_racer_cannon_cost;
+ veh.wait = time;
+ }
+ if (isPlayer) W_SetupShot_Dir(player, v_forward, false, 0, SND(Null), CH_WEAPON_B, 0);
+ vector org = w_shotorg;
+ vector dir = w_shotdir;
+ entity bolt = vehicles_projectile(EFFECT_RACER_MUZZLEFLASH.eent_eff_name, SND(LASERGUN_FIRE),
+ org, normalize(v_forward + randomvec() * autocvar_g_vehicle_racer_cannon_spread) * autocvar_g_vehicle_racer_cannon_speed,
+ autocvar_g_vehicle_racer_cannon_damage, autocvar_g_vehicle_racer_cannon_radius, autocvar_g_vehicle_racer_cannon_force, 0,
+ DEATH_VH_WAKI_GUN, PROJECTILE_WAKICANNON, 0, true, true, player);
+ bolt.velocity = normalize(dir) * autocvar_g_vehicle_racer_cannon_speed;
+ weapon_thinkf(player, WFRAME_FIRE1, 0, w_ready);
+ }
+ if (fire2)
+ if (!isPlayer || weapon_prepareattack(thiswep, actor, false, 0.2)) {
+ if (isPlayer) W_SetupShot_Dir(actor, v_forward, false, 0, SND(Null), CH_WEAPON_B, 0);
+ racer_fire_rocket(w_shotorg, w_shotdir, NULL);
+ weapon_thinkf(actor, WFRAME_FIRE2, 0, w_ready);
+ }
+}
+
+METHOD(RacerAttack, wr_checkammo1, bool(RacerAttack thiswep))
+{
+ SELFPARAM();
+ bool isPlayer = IS_PLAYER(self);
+ entity player = isPlayer ? self : self.owner;
+ entity veh = player.vehicle;
+ return isPlayer || veh.vehicle_energy >= autocvar_g_vehicle_racer_cannon_cost;
+}
+
+void racer_rocket_tracker();
+void racer_rocket_groundhugger();
+
+void racer_fire_rocket(vector org, vector dir, entity trg)
+{SELFPARAM();
+ entity rocket = vehicles_projectile(EFFECT_RACER_ROCKETLAUNCH.eent_eff_name, SND(ROCKET_FIRE),
+ org, dir * autocvar_g_vehicle_racer_rocket_speed,
+ autocvar_g_vehicle_racer_rocket_damage, autocvar_g_vehicle_racer_rocket_radius, autocvar_g_vehicle_racer_rocket_force, 3,
+ DEATH_VH_WAKI_ROCKET, PROJECTILE_WAKIROCKET, 20, false, false, self.owner);
+
+ rocket.lip = autocvar_g_vehicle_racer_rocket_accel * sys_frametime;
+ rocket.wait = autocvar_g_vehicle_racer_rocket_turnrate;
+ rocket.nextthink = time;
+ rocket.enemy = trg;
+ rocket.cnt = time + 15;
+
+ if(trg)
+ rocket.think = racer_rocket_tracker;
+ else
+ rocket.think = racer_rocket_groundhugger;
+}
+
+void racer_rocket_tracker()
+{SELFPARAM();
+ vector olddir, newdir;
+ float oldvel, newvel;
+
+ self.nextthink = time;
+
+ if (self.owner.deadflag != DEAD_NO || self.cnt < time)
+ {
+ self.use();
+ return;
+ }
+
+ if(!self.realowner.vehicle)
+ {
+ UpdateCSQCProjectile(self);
+ return;
+ }
+
+ olddir = normalize(self.velocity);
+ oldvel = vlen(self.velocity);
+ newvel = oldvel + self.lip;
+ makevectors(vectoangles(olddir));
+
+ float time_to_impact = min(vlen(self.enemy.origin - self.origin) / vlen(self.velocity), 1);
+ vector predicted_origin = self.enemy.origin + self.enemy.velocity * time_to_impact;
+
+ traceline(self.origin, self.origin + v_forward * 64 - '0 0 32', MOVE_NORMAL, self);
+ newdir = normalize(predicted_origin - self.origin);
+
+ //vector
+ float height_diff = predicted_origin_z - self.origin_z;
+
+ if(vlen(newdir - v_forward) > autocvar_g_vehicle_racer_rocket_locked_maxangle)
+ {
+ //bprint("Target lost!\n");
+ //dprint("OF:", ftos(vlen(newdir - v_forward)), "\n");
+ self.think = racer_rocket_groundhugger;
+ return;
+ }
+
+ if(trace_fraction != 1.0 && trace_ent != self.enemy)
+ newdir_z += 16 * sys_frametime;
+
+ self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_racer_rocket_turnrate) * newvel;
+ self.velocity_z -= 800 * sys_frametime;
+ self.velocity_z += max(height_diff, autocvar_g_vehicle_racer_rocket_climbspeed) * sys_frametime ;
+
+ UpdateCSQCProjectile(self);
+ return;
+}
+
+void racer_rocket_groundhugger()
+{SELFPARAM();
+ vector olddir, newdir;
+ float oldvel, newvel;
+
+ self.nextthink = time;
+
+ if(self.owner.deadflag != DEAD_NO || self.cnt < time)
+ {
+ self.use();
+ return;
+ }
+
+ if(!self.realowner.vehicle)
+ {
+ UpdateCSQCProjectile(self);
+ return;
+ }
+
+ olddir = normalize(self.velocity);
+ oldvel = vlen(self.velocity);
+ newvel = oldvel + self.lip;
+
+ tracebox(self.origin, self.mins, self.maxs, self.origin + olddir * 64, MOVE_WORLDONLY,self);
+ if(trace_fraction <= 0.5)
+ {
+ // Hitting somethign soon, just speed ahead
+ self.velocity = olddir * newvel;
+ UpdateCSQCProjectile(self);
+ return;
+ }
+
+ traceline(trace_endpos, trace_endpos - '0 0 64', MOVE_NORMAL, self);
+ if(trace_fraction != 1.0)
+ {
+ newdir = normalize(trace_endpos + '0 0 64' - self.origin) * autocvar_g_vehicle_racer_rocket_turnrate;
+ self.velocity = normalize(olddir + newdir) * newvel;
+ }
+ else
+ {
+ self.velocity = olddir * newvel;
+ self.velocity_z -= 1600 * sys_frametime; // 2x grav looks better for this one
+ }
+
+ int cont = pointcontents(self.origin - '0 0 32');
+ if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
+ self.velocity_z += 200;
+
+ UpdateCSQCProjectile(self);
+ return;
+}
+
+#endif
+
+#endif
--- /dev/null
+#ifndef VEHICLE_RAPTOR
+#define VEHICLE_RAPTOR
+#include "raptor.qh"
+
+#include "raptor_weapons.qc"
+
+CLASS(Raptor, Vehicle)
+/* spawnflags */ ATTRIB(Raptor, spawnflags, int, VHF_DMGSHAKE | VHF_DMGROLL);
+/* mins */ ATTRIB(Raptor, mins, vector, '-80 -80 0');
+/* maxs */ ATTRIB(Raptor, maxs, vector, '80 80 70');
+/* model */ ATTRIB(Raptor, mdl, string, "models/vehicles/raptor.dpm");
+/* model */ ATTRIB(Raptor, model, string, "models/vehicles/raptor.dpm");
+/* head_model */ ATTRIB(Raptor, head_model, string, "");
+/* hud_model */ ATTRIB(Raptor, hud_model, string, "models/vehicles/raptor_cockpit.dpm");
+/* tags */ ATTRIB(Raptor, tag_head, string, "");
+/* tags */ ATTRIB(Raptor, tag_hud, string, "tag_hud");
+/* tags */ ATTRIB(Raptor, tag_view, string, "tag_camera");
+/* netname */ ATTRIB(Raptor, netname, string, "raptor");
+/* fullname */ ATTRIB(Raptor, vehicle_name, string, _("Raptor"));
+/* icon */ ATTRIB(Raptor, m_icon, string, "vehicle_raptor");
+ENDCLASS(Raptor)
+REGISTER_VEHICLE(RAPTOR, NEW(Raptor));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#include "raptor_weapons.qc"
+
+#ifdef SVQC
+
+bool autocvar_g_vehicle_raptor;
+
+float autocvar_g_vehicle_raptor_respawntime;
+float autocvar_g_vehicle_raptor_takeofftime;
+
+float autocvar_g_vehicle_raptor_movestyle;
+float autocvar_g_vehicle_raptor_turnspeed;
+float autocvar_g_vehicle_raptor_pitchspeed;
+float autocvar_g_vehicle_raptor_pitchlimit;
+
+float autocvar_g_vehicle_raptor_speed_forward;
+float autocvar_g_vehicle_raptor_speed_strafe;
+float autocvar_g_vehicle_raptor_speed_up;
+float autocvar_g_vehicle_raptor_speed_down;
+float autocvar_g_vehicle_raptor_friction;
+
+float autocvar_g_vehicle_raptor_cannon_turnspeed;
+float autocvar_g_vehicle_raptor_cannon_turnlimit;
+float autocvar_g_vehicle_raptor_cannon_pitchlimit_up;
+float autocvar_g_vehicle_raptor_cannon_pitchlimit_down;
+
+float autocvar_g_vehicle_raptor_cannon_locktarget;
+float autocvar_g_vehicle_raptor_cannon_locking_time;
+float autocvar_g_vehicle_raptor_cannon_locking_releasetime;
+float autocvar_g_vehicle_raptor_cannon_locked_time;
+float autocvar_g_vehicle_raptor_cannon_predicttarget;
+
+float autocvar_g_vehicle_raptor_energy;
+float autocvar_g_vehicle_raptor_energy_regen;
+float autocvar_g_vehicle_raptor_energy_regen_pause;
+
+float autocvar_g_vehicle_raptor_health;
+float autocvar_g_vehicle_raptor_health_regen;
+float autocvar_g_vehicle_raptor_health_regen_pause;
+
+float autocvar_g_vehicle_raptor_shield;
+float autocvar_g_vehicle_raptor_shield_regen;
+float autocvar_g_vehicle_raptor_shield_regen_pause;
+
+float autocvar_g_vehicle_raptor_bouncefactor;
+float autocvar_g_vehicle_raptor_bouncestop;
+vector autocvar_g_vehicle_raptor_bouncepain;
+
+.entity bomb1;
+.entity bomb2;
+
+float raptor_altitude(float amax)
+{SELFPARAM();
+ tracebox(self.origin, self.mins, self.maxs, self.origin - ('0 0 1' * amax), MOVE_WORLDONLY, self);
+ return vlen(self.origin - trace_endpos);
+}
+
+void raptor_land()
+{SELFPARAM();
+ float hgt;
+
+ hgt = raptor_altitude(512);
+ self.velocity = (self.velocity * 0.9) + ('0 0 -1800' * (hgt / 256) * sys_frametime);
+ self.angles_x *= 0.95;
+ self.angles_z *= 0.95;
+
+ if(hgt < 128)
+ if(hgt > 0)
+ self.frame = (hgt / 128) * 25;
+
+ self.bomb1.gun1.avelocity_y = 90 + ((self.frame / 25) * 2000);
+ self.bomb1.gun2.avelocity_y = -self.bomb1.gun1.avelocity_y;
+
+ if(hgt < 16)
+ {
+ self.movetype = MOVETYPE_TOSS;
+ self.think = vehicles_think;
+ self.frame = 0;
+ }
+
+ self.nextthink = time;
+
+ CSQCMODEL_AUTOUPDATE(self);
+}
+
+void raptor_exit(float eject)
+{SELFPARAM();
+ vector spot;
+ self.tur_head.exteriormodeltoclient = world;
+
+ if(self.deadflag == DEAD_NO)
+ {
+ self.think = raptor_land;
+ self.nextthink = time;
+ }
+
+ if(!self.owner)
+ return;
+
+ makevectors(self.angles);
+ if(eject)
+ {
+ spot = self.origin + v_forward * 100 + '0 0 64';
+ spot = vehicles_findgoodexit(spot);
+ setorigin(self.owner , spot);
+ self.owner.velocity = (v_up + v_forward * 0.25) * 750;
+ self.owner.oldvelocity = self.owner.velocity;
+ }
+ else
+ {
+ if(vlen(self.velocity) > 2 * autocvar_sv_maxairspeed)
+ {
+ self.owner.velocity = normalize(self.velocity) * autocvar_sv_maxairspeed * 2;
+ self.owner.velocity_z += 200;
+ spot = self.origin + v_forward * 32 + '0 0 64';
+ spot = vehicles_findgoodexit(spot);
+ }
+ else
+ {
+ self.owner.velocity = self.velocity * 0.5;
+ self.owner.velocity_z += 10;
+ spot = self.origin - v_forward * 200 + '0 0 64';
+ spot = vehicles_findgoodexit(spot);
+ }
+ self.owner.oldvelocity = self.owner.velocity;
+ setorigin(self.owner , spot);
+ }
+
+ antilag_clear(self.owner);
+ self.owner = world;
+}
+
+float raptor_frame()
+{SELFPARAM();
+ entity player, raptor;
+ float ftmp = 0;
+ vector df;
+
+ if(intermission_running)
+ {
+ self.vehicle.velocity = '0 0 0';
+ self.vehicle.avelocity = '0 0 0';
+ return 1;
+ }
+
+ player = self;
+ raptor = self.vehicle;
+ setself(raptor);
+
+ vehicles_painframe();
+ /*
+ ftmp = vlen(self.velocity);
+ if(ftmp > autocvar_g_vehicle_raptor_speed_forward)
+ ftmp = 1;
+ else
+ ftmp = ftmp / autocvar_g_vehicle_raptor_speed_forward;
+ */
+
+ if(self.sound_nexttime < time)
+ {
+ self.sound_nexttime = time + 7.955812;
+ //sound (self.tur_head, CH_TRIGGER_SINGLE, SND_VEH_RAPTOR_FLY, 1 - ftmp, ATTEN_NORM );
+ sound (self, CH_TRIGGER_SINGLE, SND_VEH_RAPTOR_SPEED, 1, ATTEN_NORM);
+ self.wait = ftmp;
+ }
+ /*
+ else if(fabs(ftmp - self.wait) > 0.2)
+ {
+ sound (self.tur_head, CH_TRIGGER_SINGLE, SND_Null, 1 - ftmp, ATTEN_NORM );
+ sound (self, CH_TRIGGER_SINGLE, SND_Null, ftmp, ATTEN_NORM);
+ self.wait = ftmp;
+ }
+ */
+
+ if(raptor.deadflag != DEAD_NO)
+ {
+ setself(player);
+ player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
+ return 1;
+ }
+ crosshair_trace(player);
+
+ //if(time - self.lastteleporttime < 1)
+ //{
+ if(raptor.angles_z > 50 || raptor.angles_z < -50)
+ {
+ if(player.BUTTON_JUMP)
+ {
+ player.BUTTON_CROUCH = true;
+ player.BUTTON_JUMP = false;
+ }
+ }
+ //}
+
+ vector vang;
+ vang = raptor.angles;
+ df = vectoangles(normalize(trace_endpos - self.origin + '0 0 32'));
+ vang_x *= -1;
+ df_x *= -1;
+ if(df_x > 180) df_x -= 360;
+ if(df_x < -180) df_x += 360;
+ if(df_y > 180) df_y -= 360;
+ if(df_y < -180) df_y += 360;
+
+ ftmp = shortangle_f(player.v_angle_y - vang_y, vang_y);
+ if(ftmp > 180) ftmp -= 360; if(ftmp < -180) ftmp += 360;
+ raptor.avelocity_y = bound(-autocvar_g_vehicle_raptor_turnspeed, ftmp + raptor.avelocity_y * 0.9, autocvar_g_vehicle_raptor_turnspeed);
+
+ // Pitch
+ ftmp = 0;
+ if(player.movement_x > 0 && vang_x < autocvar_g_vehicle_raptor_pitchlimit) ftmp = 5;
+ else if(player.movement_x < 0 && vang_x > -autocvar_g_vehicle_raptor_pitchlimit) ftmp = -20;
+
+ df_x = bound(-autocvar_g_vehicle_raptor_pitchlimit, df_x , autocvar_g_vehicle_raptor_pitchlimit);
+ ftmp = vang_x - bound(-autocvar_g_vehicle_raptor_pitchlimit, df_x + ftmp, autocvar_g_vehicle_raptor_pitchlimit);
+ raptor.avelocity_x = bound(-autocvar_g_vehicle_raptor_pitchspeed, ftmp + raptor.avelocity_x * 0.9, autocvar_g_vehicle_raptor_pitchspeed);
+
+ raptor.angles_x = anglemods(raptor.angles_x);
+ raptor.angles_y = anglemods(raptor.angles_y);
+ raptor.angles_z = anglemods(raptor.angles_z);
+
+ if(autocvar_g_vehicle_raptor_movestyle == 1)
+ makevectors('0 1 0' * raptor.angles_y);
+ else
+ makevectors(player.v_angle);
+
+ df = raptor.velocity * -autocvar_g_vehicle_raptor_friction;
+
+ if(player.movement_x != 0)
+ {
+ if(player.movement_x > 0)
+ df += v_forward * autocvar_g_vehicle_raptor_speed_forward;
+ else if(player.movement_x < 0)
+ df -= v_forward * autocvar_g_vehicle_raptor_speed_forward;
+ }
+
+ if(player.movement_y != 0)
+ {
+ if(player.movement_y < 0)
+ df -= v_right * autocvar_g_vehicle_raptor_speed_strafe;
+ else if(player.movement_y > 0)
+ df += v_right * autocvar_g_vehicle_raptor_speed_strafe;
+
+ raptor.angles_z = bound(-30,raptor.angles_z + (player.movement_y / autocvar_g_vehicle_raptor_speed_strafe),30);
+ }
+ else
+ {
+ raptor.angles_z *= 0.95;
+ if(raptor.angles_z >= -1 && raptor.angles_z <= -1)
+ raptor.angles_z = 0;
+ }
+
+ if(player.BUTTON_CROUCH)
+ df -= v_up * autocvar_g_vehicle_raptor_speed_down;
+ else if (player.BUTTON_JUMP)
+ df += v_up * autocvar_g_vehicle_raptor_speed_up;
+
+ raptor.velocity += df * frametime;
+ player.velocity = player.movement = raptor.velocity;
+ setorigin(player, raptor.origin + '0 0 32');
+
+ player.vehicle_weapon2mode = raptor.vehicle_weapon2mode;
+
+ vector vf, ad;
+ // Target lock & predict
+ if(autocvar_g_vehicle_raptor_cannon_locktarget == 2)
+ {
+ if(raptor.gun1.lock_time < time || raptor.gun1.enemy.deadflag)
+ raptor.gun1.enemy = world;
+
+ if(trace_ent)
+ if(trace_ent.movetype)
+ if(trace_ent.takedamage)
+ if(!trace_ent.deadflag)
+ {
+ if(teamplay)
+ {
+ if(trace_ent.team != player.team)
+ {
+ raptor.gun1.enemy = trace_ent;
+ raptor.gun1.lock_time = time + 5;
+ }
+ }
+ else
+ {
+ raptor.gun1.enemy = trace_ent;
+ raptor.gun1.lock_time = time + 0.5;
+ }
+ }
+
+ if(raptor.gun1.enemy)
+ {
+ float distance, impact_time;
+
+ vf = real_origin(raptor.gun1.enemy);
+ UpdateAuxiliaryXhair(player, vf, '1 0 0', 1);
+ vector _vel = raptor.gun1.enemy.velocity;
+ if(raptor.gun1.enemy.movetype == MOVETYPE_WALK)
+ _vel_z *= 0.1;
+
+ if(autocvar_g_vehicle_raptor_cannon_predicttarget)
+ {
+ ad = vf;
+ distance = vlen(ad - player.origin);
+ impact_time = distance / autocvar_g_vehicle_raptor_cannon_speed;
+ ad = vf + _vel * impact_time;
+ trace_endpos = ad;
+ }
+ else
+ trace_endpos = vf;
+ }
+ }
+ else if(autocvar_g_vehicle_raptor_cannon_locktarget == 1)
+ {
+
+ vehicles_locktarget((1 / autocvar_g_vehicle_raptor_cannon_locking_time) * frametime,
+ (1 / autocvar_g_vehicle_raptor_cannon_locking_releasetime) * frametime,
+ autocvar_g_vehicle_raptor_cannon_locked_time);
+
+ if(self.lock_target != world)
+ if(autocvar_g_vehicle_raptor_cannon_predicttarget)
+ if(self.lock_strength == 1)
+ {
+ float i, distance, impact_time;
+
+ vf = real_origin(raptor.lock_target);
+ ad = vf;
+ for(i = 0; i < 4; ++i)
+ {
+ distance = vlen(ad - raptor.origin);
+ impact_time = distance / autocvar_g_vehicle_raptor_cannon_speed;
+ ad = vf + raptor.lock_target.velocity * impact_time;
+ }
+ trace_endpos = ad;
+ }
+
+ if(self.lock_target)
+ {
+ if(raptor.lock_strength == 1)
+ UpdateAuxiliaryXhair(player, real_origin(raptor.lock_target), '1 0 0', 1);
+ else if(self.lock_strength > 0.5)
+ UpdateAuxiliaryXhair(player, real_origin(raptor.lock_target), '0 1 0', 1);
+ else if(self.lock_strength < 0.5)
+ UpdateAuxiliaryXhair(player, real_origin(raptor.lock_target), '0 0 1', 1);
+ }
+ }
+
+
+ vehicle_aimturret(raptor, trace_endpos, raptor.gun1, "fire1",
+ autocvar_g_vehicle_raptor_cannon_pitchlimit_down * -1, autocvar_g_vehicle_raptor_cannon_pitchlimit_up,
+ autocvar_g_vehicle_raptor_cannon_turnlimit * -1, autocvar_g_vehicle_raptor_cannon_turnlimit, autocvar_g_vehicle_raptor_cannon_turnspeed);
+
+ vehicle_aimturret(raptor, trace_endpos, raptor.gun2, "fire1",
+ autocvar_g_vehicle_raptor_cannon_pitchlimit_down * -1, autocvar_g_vehicle_raptor_cannon_pitchlimit_up,
+ autocvar_g_vehicle_raptor_cannon_turnlimit * -1, autocvar_g_vehicle_raptor_cannon_turnlimit, autocvar_g_vehicle_raptor_cannon_turnspeed);
+
+ /*
+ ad = ad * 0.5;
+ v_forward = vf * 0.5;
+ traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, raptor);
+ UpdateAuxiliaryXhair(player, trace_endpos, '0 1 0', 0);
+ */
+
+ Weapon wep1 = WEP_RAPTOR;
+ if(!forbidWeaponUse(player))
+ if(player.BUTTON_ATCK)
+ if (wep1.wr_checkammo1(wep1))
+ {
+ wep1.wr_think(wep1, self, true, false);
+ }
+
+ if(self.vehicle_flags & VHF_SHIELDREGEN)
+ vehicles_regen(raptor.dmg_time, vehicle_shield, autocvar_g_vehicle_raptor_shield, autocvar_g_vehicle_raptor_shield_regen_pause, autocvar_g_vehicle_raptor_shield_regen, frametime, true);
+
+ if(self.vehicle_flags & VHF_HEALTHREGEN)
+ vehicles_regen(raptor.dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, frametime, false);
+
+ if(self.vehicle_flags & VHF_ENERGYREGEN)
+ vehicles_regen(raptor.cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, frametime, false);
+
+ Weapon wep2a = WEP_RAPTOR_BOMB;
+ if(!forbidWeaponUse(player))
+ if(raptor.vehicle_weapon2mode == RSM_BOMB)
+ {
+ if(time > raptor.lip + autocvar_g_vehicle_raptor_bombs_refire)
+ if(player.BUTTON_ATCK2)
+ {
+ wep2a.wr_think(wep2a, self, false, true);
+ raptor.delay = time + autocvar_g_vehicle_raptor_bombs_refire;
+ raptor.lip = time;
+ }
+ }
+ else
+ {
+ Weapon wep2b = WEP_RAPTOR_FLARE;
+ if(time > raptor.lip + autocvar_g_vehicle_raptor_flare_refire)
+ if(player.BUTTON_ATCK2)
+ {
+ wep2b.wr_think(wep2b, self, false, true);
+ raptor.delay = time + autocvar_g_vehicle_raptor_flare_refire;
+ raptor.lip = time;
+ }
+ }
+
+ raptor.bomb1.alpha = raptor.bomb2.alpha = (time - raptor.lip) / (raptor.delay - raptor.lip);
+ player.vehicle_reload2 = bound(0, raptor.bomb1.alpha * 100, 100);
+ player.vehicle_ammo2 = (player.vehicle_reload2 == 100) ? 100 : 0;
+
+ if(self.bomb1.cnt < time)
+ {
+ entity _missile = findchainentity(enemy, raptor);
+ float _incomming = 0;
+ while(_missile)
+ {
+ if(_missile.flags & FL_PROJECTILE)
+ if(MISSILE_IS_TRACKING(_missile))
+ if(vlen(self.origin - _missile.origin) < 2 * autocvar_g_vehicle_raptor_flare_range)
+ ++_incomming;
+
+ _missile = _missile.chain;
+ }
+
+ if(_incomming)
+ sound(self, CH_PAIN_SINGLE, SND_VEH_MISSILE_ALARM, VOL_BASE, ATTEN_NONE);
+
+ self.bomb1.cnt = time + 1;
+ }
+
+
+ VEHICLE_UPDATE_PLAYER(player, health, raptor);
+ VEHICLE_UPDATE_PLAYER(player, energy, raptor);
+ if(self.vehicle_flags & VHF_HASSHIELD)
+ VEHICLE_UPDATE_PLAYER(player, shield, raptor);
+
+ player.BUTTON_ATCK = player.BUTTON_ATCK2 = player.BUTTON_CROUCH = 0;
+
+ setself(player);
+ return 1;
+}
+
+float raptor_takeoff()
+{SELFPARAM();
+ entity player, raptor;
+
+ player = self;
+ raptor = self.vehicle;
+ setself(raptor);
+
+ self.nextthink = time;
+ CSQCMODEL_AUTOUPDATE(self);
+ self.nextthink = 0; // will this work?
+
+ if(self.sound_nexttime < time)
+ {
+ self.sound_nexttime = time + 7.955812; //soundlength("vehicles/raptor_fly.wav");
+ sound (self, CH_TRIGGER_SINGLE, SND_VEH_RAPTOR_SPEED, VOL_VEHICLEENGINE, ATTEN_NORM);
+ }
+
+ // Takeoff sequense
+ if(raptor.frame < 25)
+ {
+ raptor.frame += 25 / (autocvar_g_vehicle_raptor_takeofftime / sys_frametime);
+ raptor.velocity_z = min(raptor.velocity_z * 1.5, 256);
+ self.bomb1.gun1.avelocity_y = 90 + ((raptor.frame / 25) * 25000);
+ self.bomb1.gun2.avelocity_y = -self.bomb1.gun1.avelocity_y;
+ player.BUTTON_ATCK = player.BUTTON_ATCK2 = player.BUTTON_CROUCH = 0;
+
+ setorigin(player, raptor.origin + '0 0 32');
+ }
+ else
+ player.PlayerPhysplug = raptor_frame;
+
+ if(self.vehicle_flags & VHF_SHIELDREGEN)
+ vehicles_regen(raptor.dmg_time, vehicle_shield, autocvar_g_vehicle_raptor_shield, autocvar_g_vehicle_raptor_shield_regen_pause, autocvar_g_vehicle_raptor_shield_regen, frametime, true);
+
+ if(self.vehicle_flags & VHF_HEALTHREGEN)
+ vehicles_regen(raptor.dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, frametime, false);
+
+ if(self.vehicle_flags & VHF_ENERGYREGEN)
+ vehicles_regen(raptor.cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, frametime, false);
+
+
+ raptor.bomb1.alpha = raptor.bomb2.alpha = (time - raptor.lip) / (raptor.delay - raptor.lip);
+ player.vehicle_reload2 = bound(0, raptor.bomb1.alpha * 100, 100);
+ player.vehicle_ammo2 = (player.vehicle_reload2 == 100) ? 100 : 0;
+
+ VEHICLE_UPDATE_PLAYER(player, health, raptor);
+ VEHICLE_UPDATE_PLAYER(player, energy, raptor);
+ if(self.vehicle_flags & VHF_HASSHIELD)
+ VEHICLE_UPDATE_PLAYER(player, shield, raptor);
+
+ player.BUTTON_ATCK = player.BUTTON_ATCK2 = player.BUTTON_CROUCH = 0;
+ setself(player);
+ return 1;
+}
+
+void raptor_blowup()
+{SELFPARAM();
+ self.deadflag = DEAD_DEAD;
+ self.vehicle_exit(VHEF_NORMAL);
+ RadiusDamage (self, self.enemy, 250, 15, 250, world, world, 250, DEATH_VH_RAPT_DEATH, world);
+
+ self.alpha = -1;
+ self.movetype = MOVETYPE_NONE;
+ self.effects = EF_NODRAW;
+ self.colormod = '0 0 0';
+ self.avelocity = '0 0 0';
+ self.velocity = '0 0 0';
+
+ setorigin(self, self.pos1);
+ self.touch = func_null;
+ self.nextthink = 0;
+}
+
+void raptor_diethink()
+{SELFPARAM();
+ if(time >= self.wait)
+ self.think = raptor_blowup;
+
+ if(random() < 0.05)
+ {
+ sound (self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
+ Send_Effect(EFFECT_EXPLOSION_SMALL, randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
+ }
+ self.nextthink = time;
+
+ CSQCMODEL_AUTOUPDATE(self);
+}
+
+// If we dont do this ever now and then, the raptors rotors
+// stop working, presumably due to angle overflow. cute.
+void raptor_rotor_anglefix()
+{SELFPARAM();
+ self.gun1.angles_y = anglemods(self.gun1.angles_y);
+ self.gun2.angles_y = anglemods(self.gun2.angles_y);
+ self.nextthink = time + 15;
+}
+
+float raptor_impulse(float _imp)
+{SELFPARAM();
+ switch(_imp)
+ {
+ case 1:
+ self.vehicle.vehicle_weapon2mode = RSM_BOMB;
+ CSQCVehicleSetup(self, 0);
+ return true;
+ case 2:
+ self.vehicle.vehicle_weapon2mode = RSM_FLARE;
+ CSQCVehicleSetup(self, 0);
+ return true;
+
+ case 10:
+ case 15:
+ case 18:
+ self.vehicle.vehicle_weapon2mode += 1;
+ if(self.vehicle.vehicle_weapon2mode > RSM_LAST)
+ self.vehicle.vehicle_weapon2mode = RSM_FIRST;
+
+ CSQCVehicleSetup(self, 0);
+ return true;
+ case 11:
+ case 12:
+ case 16:
+ case 19:
+ self.vehicle.vehicle_weapon2mode -= 1;
+ if(self.vehicle.vehicle_weapon2mode < RSM_FIRST)
+ self.vehicle.vehicle_weapon2mode = RSM_LAST;
+
+ CSQCVehicleSetup(self, 0);
+ return true;
+
+ /*
+ case 17: // toss gun, could be used to exit?
+ break;
+ case 20: // Manual minigun reload?
+ break;
+ */
+ }
+ return false;
+}
+
+spawnfunc(vehicle_raptor)
+{
+ if(!autocvar_g_vehicle_raptor) { remove(self); return; }
+ if(!vehicle_initialize(VEH_RAPTOR, false)) { remove(self); return; }
+}
+
+ METHOD(Raptor, vr_impact, void(Raptor thisveh))
+ {
+ if(autocvar_g_vehicle_raptor_bouncepain)
+ vehicles_impact(autocvar_g_vehicle_raptor_bouncepain_x, autocvar_g_vehicle_raptor_bouncepain_y, autocvar_g_vehicle_raptor_bouncepain_z);
+ }
+ METHOD(Raptor, vr_enter, void(Raptor thisveh))
+ {
+ self.vehicle_weapon2mode = RSM_BOMB;
+ self.owner.PlayerPhysplug = raptor_takeoff;
+ self.movetype = MOVETYPE_BOUNCEMISSILE;
+ self.solid = SOLID_SLIDEBOX;
+ self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_raptor_health) * 100;
+ self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_raptor_shield) * 100;
+ self.velocity_z = 1; // Nudge upwards to takeoff sequense can work.
+ self.tur_head.exteriormodeltoclient = self.owner;
+
+ self.delay = time + autocvar_g_vehicle_raptor_bombs_refire;
+ self.lip = time;
+
+ if(self.owner.flagcarried)
+ setorigin(self.owner.flagcarried, '-20 0 96');
+
+ CSQCVehicleSetup(self.owner, 0);
+ }
+ METHOD(Raptor, vr_death, void(Raptor thisveh))
+ {
+ self.health = 0;
+ self.event_damage = func_null;
+ self.solid = SOLID_CORPSE;
+ self.takedamage = DAMAGE_NO;
+ self.deadflag = DEAD_DYING;
+ self.movetype = MOVETYPE_BOUNCE;
+ self.think = raptor_diethink;
+ self.nextthink = time;
+ self.wait = time + 5 + (random() * 5);
+
+ Send_Effect(EFFECT_EXPLOSION_MEDIUM, findbetterlocation (self.origin, 16), '0 0 0', 1);
+
+ self.velocity_z += 600;
+
+ self.avelocity = '0 0.5 1' * (random() * 400);
+ self.avelocity -= '0 0.5 1' * (random() * 400);
+
+ self.colormod = '-0.5 -0.5 -0.5';
+ self.touch = raptor_blowup;
+ }
+ METHOD(Raptor, vr_spawn, void(Raptor thisveh))
+ {
+ if(!self.gun1)
+ {
+ entity spinner;
+ vector ofs;
+
+ //FIXME: Camera is in a bad place in HUD model.
+ //setorigin(self.vehicle_viewport, '25 0 5');
+
+ self.vehicles_impulse = raptor_impulse;
+
+ self.frame = 0;
+
+ self.bomb1 = spawn();
+ self.bomb2 = spawn();
+ self.gun1 = spawn();
+ self.gun2 = spawn();
+
+ setmodel(self.bomb1, MDL_VEH_RAPTOR_CB_FOLDED);
+ setmodel(self.bomb2, MDL_VEH_RAPTOR_CB_FOLDED);
+ setmodel(self.gun1, MDL_VEH_RAPTOR_GUN);
+ setmodel(self.gun2, MDL_VEH_RAPTOR_GUN);
+ setmodel(self.tur_head, MDL_VEH_RAPTOR_TAIL);
+
+ setattachment(self.bomb1, self, "bombmount_left");
+ setattachment(self.bomb2, self, "bombmount_right");
+ setattachment(self.tur_head, self,"root");
+
+ // FIXMODEL Guns mounts to angled bones
+ self.bomb1.angles = self.angles;
+ self.angles = '0 0 0';
+ // This messes up gun-aim, so work arround it.
+ //setattachment(self.gun1, self, "gunmount_left");
+ ofs = gettaginfo(self, gettagindex(self, "gunmount_left"));
+ ofs -= self.origin;
+ setattachment(self.gun1, self, "");
+ setorigin(self.gun1, ofs);
+
+ //setattachment(self.gun2, self, "gunmount_right");
+ ofs = gettaginfo(self, gettagindex(self, "gunmount_right"));
+ ofs -= self.origin;
+ setattachment(self.gun2, self, "");
+ setorigin(self.gun2, ofs);
+
+ self.angles = self.bomb1.angles;
+ self.bomb1.angles = '0 0 0';
+
+ spinner = spawn();
+ spinner.owner = self;
+ setmodel(spinner, MDL_VEH_RAPTOR_PROP);
+ setattachment(spinner, self, "engine_left");
+ spinner.movetype = MOVETYPE_NOCLIP;
+ spinner.avelocity = '0 90 0';
+ self.bomb1.gun1 = spinner;
+
+ spinner = spawn();
+ spinner.owner = self;
+ setmodel(spinner, MDL_VEH_RAPTOR_PROP);
+ setattachment(spinner, self, "engine_right");
+ spinner.movetype = MOVETYPE_NOCLIP;
+ spinner.avelocity = '0 -90 0';
+ self.bomb1.gun2 = spinner;
+
+ // Sigh.
+ self.bomb1.think = raptor_rotor_anglefix;
+ self.bomb1.nextthink = time;
+
+ self.mass = 1 ;
+ }
+
+ self.frame = 0;
+ self.vehicle_health = autocvar_g_vehicle_raptor_health;
+ self.vehicle_shield = autocvar_g_vehicle_raptor_shield;
+ self.movetype = MOVETYPE_TOSS;
+ self.solid = SOLID_SLIDEBOX;
+ self.vehicle_energy = 1;
+
+ self.PlayerPhysplug = raptor_frame;
+
+ self.bomb1.gun1.avelocity_y = 90;
+ self.bomb1.gun2.avelocity_y = -90;
+
+ self.delay = time;
+
+ self.bouncefactor = autocvar_g_vehicle_raptor_bouncefactor;
+ self.bouncestop = autocvar_g_vehicle_raptor_bouncestop;
+ self.damageforcescale = 0.25;
+ self.vehicle_health = autocvar_g_vehicle_raptor_health;
+ self.vehicle_shield = autocvar_g_vehicle_raptor_shield;
+ }
+ METHOD(Raptor, vr_setup, void(Raptor thisveh))
+ {
+ if(autocvar_g_vehicle_raptor_shield)
+ self.vehicle_flags |= VHF_HASSHIELD;
+
+ if(autocvar_g_vehicle_raptor_shield_regen)
+ self.vehicle_flags |= VHF_SHIELDREGEN;
+
+ if(autocvar_g_vehicle_raptor_health_regen)
+ self.vehicle_flags |= VHF_HEALTHREGEN;
+
+ if(autocvar_g_vehicle_raptor_energy_regen)
+ self.vehicle_flags |= VHF_ENERGYREGEN;
+
+ self.vehicle_exit = raptor_exit;
+ self.respawntime = autocvar_g_vehicle_raptor_respawntime;
+ self.vehicle_health = autocvar_g_vehicle_raptor_health;
+ self.vehicle_shield = autocvar_g_vehicle_raptor_shield;
+ self.max_health = self.vehicle_health;
+ }
+
+#endif
+#ifdef CSQC
+
+ METHOD(Raptor, vr_hud, void(Raptor thisveh))
+ {
+ string crosshair;
+
+ switch(weapon2mode)
+ {
+ case RSM_FLARE: crosshair = vCROSS_RAIN; break;
+ case RSM_BOMB: crosshair = vCROSS_BURST; break;
+ default: crosshair = vCROSS_BURST;
+ }
+
+ Vehicles_drawHUD(VEH_RAPTOR.m_icon, "vehicle_raptor_weapon1", "vehicle_raptor_weapon2",
+ "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
+ "vehicle_icon_ammo2", autocvar_hud_progressbar_vehicles_ammo2_color,
+ crosshair);
+ }
+ METHOD(Raptor, vr_setup, void(Raptor thisveh))
+ {
+ AuxiliaryXhair[1].axh_image = vCROSS_LOCK;
+ }
+
+#endif
+#endif
--- /dev/null
+#ifndef RAPTOR_H
+#define RAPTOR_H
+
+const int RSM_FIRST = 1;
+const int RSM_BOMB = 1;
+const int RSM_FLARE = 2;
+const int RSM_LAST = 2;
+
+#endif
--- /dev/null
+#ifndef VEHICLE_RAPTOR_WEAPONS_H
+#define VEHICLE_RAPTOR_WEAPONS_H
+
+#include "../../weapons/all.qh"
+
+CLASS(RaptorCannon, PortoLaunch)
+/* flags */ ATTRIB(RaptorCannon, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse */ ATTRIB(RaptorCannon, impulse, int, 3);
+/* refname */ ATTRIB(RaptorCannon, netname, string, "raptorcannon");
+/* wepname */ ATTRIB(RaptorCannon, message, string, _("Raptor cannon"));
+ENDCLASS(RaptorCannon)
+REGISTER_WEAPON(RAPTOR, NEW(RaptorCannon));
+
+CLASS(RaptorBomb, PortoLaunch)
+/* flags */ ATTRIB(RaptorBomb, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse */ ATTRIB(RaptorBomb, impulse, int, 3);
+/* refname */ ATTRIB(RaptorBomb, netname, string, "raptorbomb");
+/* wepname */ ATTRIB(RaptorBomb, message, string, _("Raptor bomb"));
+ENDCLASS(RaptorBomb)
+REGISTER_WEAPON(RAPTOR_BOMB, NEW(RaptorBomb));
+
+CLASS(RaptorFlare, PortoLaunch)
+/* flags */ ATTRIB(RaptorFlare, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse */ ATTRIB(RaptorFlare, impulse, int, 3);
+/* refname */ ATTRIB(RaptorFlare, netname, string, "raptorflare");
+/* wepname */ ATTRIB(RaptorFlare, message, string, _("Raptor flare"));
+ENDCLASS(RaptorFlare)
+REGISTER_WEAPON(RAPTOR_FLARE, NEW(RaptorFlare));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+float autocvar_g_vehicle_raptor_cannon_cost;
+float autocvar_g_vehicle_raptor_cannon_damage;
+float autocvar_g_vehicle_raptor_cannon_radius;
+float autocvar_g_vehicle_raptor_cannon_refire;
+float autocvar_g_vehicle_raptor_cannon_speed;
+float autocvar_g_vehicle_raptor_cannon_spread;
+float autocvar_g_vehicle_raptor_cannon_force;
+
+float autocvar_g_vehicle_raptor_bomblets;
+float autocvar_g_vehicle_raptor_bomblet_alt;
+float autocvar_g_vehicle_raptor_bomblet_time;
+float autocvar_g_vehicle_raptor_bomblet_damage;
+float autocvar_g_vehicle_raptor_bomblet_spread;
+float autocvar_g_vehicle_raptor_bomblet_edgedamage;
+float autocvar_g_vehicle_raptor_bomblet_radius;
+float autocvar_g_vehicle_raptor_bomblet_force;
+float autocvar_g_vehicle_raptor_bomblet_explode_delay;
+
+METHOD(RaptorCannon, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2)) {
+ bool isPlayer = IS_PLAYER(actor);
+ entity player = isPlayer ? actor : actor.owner;
+ entity veh = player.vehicle;
+ // 1 [wait] 1 [wait] 2 [wait] 2 [wait] [wait]
+ float t = autocvar_g_vehicle_raptor_cannon_refire * (1 + veh.misc_bulletcounter == 4);
+ if (fire1)
+ if (weapon_prepareattack(thiswep, player, false, t)) {
+ if (isPlayer) W_SetupShot_Dir(player, v_forward, false, 0, SND(Null), CH_WEAPON_B, 0);
+ vector org = w_shotorg;
+ vector dir = w_shotdir;
+ if (veh) {
+ veh.misc_bulletcounter += 1;
+ org = (veh.misc_bulletcounter <= 2) ? gettaginfo(veh.gun1, gettagindex(veh.gun1, "fire1"))
+ : (((veh.misc_bulletcounter == 4) ? veh.misc_bulletcounter = 0 : 0), gettaginfo(veh.gun2, gettagindex(veh.gun2, "fire1")));
+ dir = v_forward;
+ veh.vehicle_energy -= autocvar_g_vehicle_raptor_cannon_cost;
+ actor.cnt = time;
+ }
+ vehicles_projectile(EFFECT_RAPTOR_MUZZLEFLASH.eent_eff_name, SND(LASERGUN_FIRE),
+ org, normalize(dir + randomvec() * autocvar_g_vehicle_raptor_cannon_spread) * autocvar_g_vehicle_raptor_cannon_speed,
+ autocvar_g_vehicle_raptor_cannon_damage, autocvar_g_vehicle_raptor_cannon_radius, autocvar_g_vehicle_raptor_cannon_force, 0,
+ DEATH_VH_RAPT_CANNON, PROJECTILE_RAPTORCANNON, 0, true, true, player);
+ weapon_thinkf(player, WFRAME_FIRE1, 0, w_ready);
+ }
+}
+METHOD(RaptorCannon, wr_checkammo1, bool(RacerAttack thiswep)) {
+ SELFPARAM();
+ bool isPlayer = IS_PLAYER(self);
+ entity player = isPlayer ? self : self.owner;
+ entity veh = player.vehicle;
+ return isPlayer || veh.vehicle_energy >= autocvar_g_vehicle_raptor_cannon_cost;
+}
+
+float autocvar_g_vehicle_raptor_bombs_refire;
+
+void raptor_bombdrop();
+METHOD(RaptorBomb, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2)) {
+ bool isPlayer = IS_PLAYER(actor);
+ entity player = isPlayer ? actor : actor.owner;
+ entity veh = player.vehicle;
+ if (fire2)
+ if (!isPlayer || weapon_prepareattack(thiswep, player, true, autocvar_g_vehicle_raptor_bombs_refire)) {
+ if (veh) setself(veh);
+ raptor_bombdrop();
+ weapon_thinkf(player, WFRAME_FIRE2, 0, w_ready);
+ }
+}
+
+float autocvar_g_vehicle_raptor_flare_refire;
+float autocvar_g_vehicle_raptor_flare_lifetime;
+float autocvar_g_vehicle_raptor_flare_chase;
+float autocvar_g_vehicle_raptor_flare_range;
+
+void raptor_flare_think();
+void raptor_flare_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force);
+void raptor_flare_touch();
+
+METHOD(RaptorFlare, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2)) {
+ bool isPlayer = IS_PLAYER(actor);
+ entity player = isPlayer ? actor : actor.owner;
+ entity veh = player.vehicle;
+ if (fire2)
+ if (!isPlayer || weapon_prepareattack(thiswep, player, true, autocvar_g_vehicle_raptor_flare_refire)) {
+ for(int i = 0; i < 3; ++i) {
+ entity _flare = spawn();
+ setmodel(_flare, MDL_VEH_RAPTOR_FLARE);
+ _flare.effects = EF_LOWPRECISION | EF_FLAME;
+ _flare.scale = 0.5;
+ setorigin(_flare, actor.origin - '0 0 16');
+ _flare.movetype = MOVETYPE_TOSS;
+ _flare.gravity = 0.15;
+ _flare.velocity = 0.25 * actor.velocity + (v_forward + randomvec() * 0.25)* -500;
+ _flare.think = raptor_flare_think;
+ _flare.nextthink = time;
+ _flare.owner = veh ? veh : player;
+ _flare.solid = SOLID_CORPSE;
+ _flare.takedamage = DAMAGE_YES;
+ _flare.event_damage = raptor_flare_damage;
+ _flare.health = 20;
+ _flare.tur_impacttime = time + autocvar_g_vehicle_raptor_flare_lifetime;
+ _flare.touch = raptor_flare_touch;
+ }
+ weapon_thinkf(player, WFRAME_FIRE2, 0, w_ready);
+ }
+}
+
+
+void raptor_bomblet_boom()
+{SELFPARAM();
+ RadiusDamage (self, self.realowner, autocvar_g_vehicle_raptor_bomblet_damage,
+ autocvar_g_vehicle_raptor_bomblet_edgedamage,
+ autocvar_g_vehicle_raptor_bomblet_radius, world, world,
+ autocvar_g_vehicle_raptor_bomblet_force, DEATH_VH_RAPT_BOMB, world);
+ remove(self);
+}
+
+void raptor_bomblet_touch()
+{SELFPARAM();
+ if(other == self.owner)
+ return;
+
+ PROJECTILE_TOUCH;
+ self.think = raptor_bomblet_boom;
+ self.nextthink = time + random() * autocvar_g_vehicle_raptor_bomblet_explode_delay;
+}
+
+void raptor_bomb_burst()
+{SELFPARAM();
+ if(self.cnt > time)
+ if(autocvar_g_vehicle_raptor_bomblet_alt)
+ {
+ self.nextthink = time;
+ traceline(self.origin, self.origin + (normalize(self.velocity) * autocvar_g_vehicle_raptor_bomblet_alt), MOVE_NORMAL, self);
+ if((trace_fraction == 1.0) || (vlen(self.origin - self.owner.origin) < autocvar_g_vehicle_raptor_bomblet_radius))
+ {
+ UpdateCSQCProjectile(self);
+ return;
+ }
+ }
+
+ entity bomblet;
+ float i;
+
+ Damage_DamageInfo(self.origin, 0, 0, 0, '0 0 0', DEATH_VH_RAPT_FRAGMENT, 0, self);
+
+ for(i = 0; i < autocvar_g_vehicle_raptor_bomblets; ++i)
+ {
+ bomblet = spawn();
+ setorigin(bomblet, self.origin);
+
+ bomblet.movetype = MOVETYPE_TOSS;
+ bomblet.touch = raptor_bomblet_touch;
+ bomblet.think = raptor_bomblet_boom;
+ bomblet.nextthink = time + 5;
+ bomblet.owner = self.owner;
+ bomblet.realowner = self.realowner;
+ bomblet.velocity = normalize(normalize(self.velocity) + (randomvec() * autocvar_g_vehicle_raptor_bomblet_spread)) * vlen(self.velocity);
+
+ PROJECTILE_MAKETRIGGER(bomblet);
+ CSQCProjectile(bomblet, true, PROJECTILE_RAPTORBOMBLET, true);
+ }
+
+ remove(self);
+}
+
+void raptor_bombdrop()
+{SELFPARAM();
+ entity bomb_1, bomb_2;
+
+ bomb_1 = spawn();
+ bomb_2 = spawn();
+
+ setorigin(bomb_1, gettaginfo(self, gettagindex(self, "bombmount_left")));
+ setorigin(bomb_2, gettaginfo(self, gettagindex(self, "bombmount_right")));
+
+ bomb_1.movetype = bomb_2.movetype = MOVETYPE_BOUNCE;
+ bomb_1.velocity = bomb_2.velocity = self.velocity;
+ bomb_1.touch = bomb_2.touch = raptor_bomb_burst;
+ bomb_1.think = bomb_2.think = raptor_bomb_burst;
+ bomb_1.cnt = bomb_2.cnt = time + 10;
+
+ if(autocvar_g_vehicle_raptor_bomblet_alt)
+ bomb_1.nextthink = bomb_2.nextthink = time;
+ else
+ bomb_1.nextthink = bomb_2.nextthink = time + autocvar_g_vehicle_raptor_bomblet_time;
+
+ bomb_1.owner = bomb_2.owner = self;
+ bomb_1.realowner = bomb_2.realowner = self.owner;
+ bomb_1.solid = bomb_2.solid = SOLID_BBOX;
+ bomb_1.gravity = bomb_2.gravity = 1;
+
+ PROJECTILE_MAKETRIGGER(bomb_1);
+ PROJECTILE_MAKETRIGGER(bomb_2);
+
+ CSQCProjectile(bomb_1, true, PROJECTILE_RAPTORBOMB, true);
+ CSQCProjectile(bomb_2, true, PROJECTILE_RAPTORBOMB, true);
+}
+
+void raptor_flare_touch()
+{SELFPARAM();
+ remove(self);
+}
+
+void raptor_flare_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
+{SELFPARAM();
+ self.health -= damage;
+ if(self.health <= 0)
+ remove(self);
+}
+
+void raptor_flare_think()
+{SELFPARAM();
+ self.nextthink = time + 0.1;
+ entity _missile = findchainentity(enemy, self.owner);
+ while(_missile)
+ {
+ if(_missile.flags & FL_PROJECTILE)
+ if(vlen(self.origin - _missile.origin) < autocvar_g_vehicle_raptor_flare_range)
+ if(random() > autocvar_g_vehicle_raptor_flare_chase)
+ _missile.enemy = self;
+ _missile = _missile.chain;
+ }
+
+ if(self.tur_impacttime < time)
+ remove(self);
+}
+
+#endif
+
+#ifdef CSQC
+
+void RaptorCBShellfragDraw(entity this)
+{
+ if(wasfreed(self))
+ return;
+
+ Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
+ self.move_avelocity += randomvec() * 15;
+ self.renderflags = 0;
+
+ if(self.cnt < time)
+ self.alpha = bound(0, self.nextthink - time, 1);
+
+ if(self.alpha < ALPHA_MIN_VISIBLE)
+ remove(self);
+}
+
+void RaptorCBShellfragToss(vector _org, vector _vel, vector _ang)
+{SELFPARAM();
+ entity sfrag;
+
+ sfrag = spawn();
+ setmodel(sfrag, MDL_VEH_RAPTOR_CB_FRAGMENT);
+ setorigin(sfrag, _org);
+
+ sfrag.move_movetype = MOVETYPE_BOUNCE;
+ sfrag.gravity = 0.15;
+ sfrag.solid = SOLID_CORPSE;
+
+ sfrag.draw = RaptorCBShellfragDraw;
+
+ sfrag.move_origin = sfrag.origin = _org;
+ sfrag.move_velocity = _vel;
+ sfrag.move_avelocity = prandomvec() * vlen(sfrag.move_velocity);
+ sfrag.angles = self.move_angles = _ang;
+
+ sfrag.move_time = time;
+ sfrag.damageforcescale = 4;
+
+ sfrag.nextthink = time + 3;
+ sfrag.cnt = time + 2;
+ sfrag.alpha = 1;
+ sfrag.drawmask = MASK_NORMAL;
+}
+
+#endif
+
+#endif
--- /dev/null
+#ifndef VEHICLE_SPIDERBOT
+#define VEHICLE_SPIDERBOT
+
+#include "spiderbot_weapons.qc"
+
+CLASS(Spiderbot, Vehicle)
+/* spawnflags */ ATTRIB(Spiderbot, spawnflags, int, VHF_DMGSHAKE);
+/* mins */ ATTRIB(Spiderbot, mins, vector, '-75 -75 10');
+/* maxs */ ATTRIB(Spiderbot, maxs, vector, '75 75 125');
+/* model */ ATTRIB(Spiderbot, mdl, string, "models/vehicles/spiderbot.dpm");
+/* model */ ATTRIB(Spiderbot, model, string, "models/vehicles/spiderbot.dpm");
+/* head_model */ ATTRIB(Spiderbot, head_model, string, "models/vehicles/spiderbot_top.dpm");
+/* hud_model */ ATTRIB(Spiderbot, hud_model, string, "models/vehicles/spiderbot_cockpit.dpm");
+/* tags */ ATTRIB(Spiderbot, tag_head, string, "tag_head");
+/* tags */ ATTRIB(Spiderbot, tag_hud, string, "tag_hud");
+/* tags */ ATTRIB(Spiderbot, tag_view, string, "");
+/* netname */ ATTRIB(Spiderbot, netname, string, "spiderbot");
+/* fullname */ ATTRIB(Spiderbot, vehicle_name, string, _("Spiderbot"));
+/* icon */ ATTRIB(Spiderbot, m_icon, string, "vehicle_spider");
+ENDCLASS(Spiderbot)
+
+REGISTER_VEHICLE(SPIDERBOT, NEW(Spiderbot));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+const int SBRM_FIRST = 1;
+const int SBRM_VOLLY = 1;
+const int SBRM_GUIDE = 2;
+const int SBRM_ARTILLERY = 3;
+const int SBRM_LAST = 3;
+
+#include "spiderbot_weapons.qc"
+
+#ifdef SVQC
+bool autocvar_g_vehicle_spiderbot;
+
+float autocvar_g_vehicle_spiderbot_respawntime;
+
+float autocvar_g_vehicle_spiderbot_speed_stop;
+float autocvar_g_vehicle_spiderbot_speed_strafe;
+float autocvar_g_vehicle_spiderbot_speed_walk;
+float autocvar_g_vehicle_spiderbot_speed_run = 700;
+float autocvar_g_vehicle_spiderbot_turnspeed;
+float autocvar_g_vehicle_spiderbot_turnspeed_strafe;
+float autocvar_g_vehicle_spiderbot_movement_inertia;
+
+float autocvar_g_vehicle_spiderbot_springlength;
+float autocvar_g_vehicle_spiderbot_springup;
+float autocvar_g_vehicle_spiderbot_springblend;
+float autocvar_g_vehicle_spiderbot_tiltlimit;
+
+float autocvar_g_vehicle_spiderbot_head_pitchlimit_down;
+float autocvar_g_vehicle_spiderbot_head_pitchlimit_up;
+float autocvar_g_vehicle_spiderbot_head_turnlimit;
+float autocvar_g_vehicle_spiderbot_head_turnspeed;
+
+int autocvar_g_vehicle_spiderbot_health;
+float autocvar_g_vehicle_spiderbot_health_regen;
+float autocvar_g_vehicle_spiderbot_health_regen_pause;
+
+int autocvar_g_vehicle_spiderbot_shield;
+float autocvar_g_vehicle_spiderbot_shield_regen;
+float autocvar_g_vehicle_spiderbot_shield_regen_pause;
+
+vector autocvar_g_vehicle_spiderbot_bouncepain;
+
+.float jump_delay;
+float spiderbot_frame()
+{SELFPARAM();
+ vector ad, vf;
+ entity player, spider;
+ float ftmp;
+
+ if(intermission_running)
+ {
+ self.vehicle.velocity = '0 0 0';
+ self.vehicle.avelocity = '0 0 0';
+ return 1;
+ }
+
+ player = self;
+ spider = self.vehicle;
+ setself(spider);
+
+ vehicles_painframe();
+
+ player.BUTTON_ZOOM = 0;
+ player.BUTTON_CROUCH = 0;
+ player.switchweapon = 0;
+ player.vehicle_weapon2mode = spider.vehicle_weapon2mode;
+
+
+#if 1 // 0 to enable per-gun impact aux crosshairs
+ // Avarage gun impact point's -> aux cross
+ ad = gettaginfo(spider.tur_head, gettagindex(spider.tur_head, "tag_hardpoint01"));
+ vf = v_forward;
+ ad += gettaginfo(spider.tur_head, gettagindex(spider.tur_head, "tag_hardpoint02"));
+ vf += v_forward;
+ ad = ad * 0.5;
+ v_forward = vf * 0.5;
+ traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, spider);
+ UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload1) + ('0 1 0' * (1 - player.vehicle_reload1)), 0);
+#else
+ ad = gettaginfo(spider.gun1, gettagindex(spider.gun1, "barrels"));
+ traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, spider);
+ UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload1) + ('0 1 0' * (1 - player.vehicle_reload1)), 0);
+ vf = ad;
+ ad = gettaginfo(spider.gun2, gettagindex(spider.gun2, "barrels"));
+ traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, spider);
+ UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload1) + ('0 1 0' * (1 - player.vehicle_reload1)), 1);
+ ad = 0.5 * (ad + vf);
+#endif
+
+ crosshair_trace(player);
+ ad = vectoangles(normalize(trace_endpos - ad));
+ ad = AnglesTransform_ToAngles(AnglesTransform_LeftDivide(AnglesTransform_FromAngles(spider.angles), AnglesTransform_FromAngles(ad))) - spider.tur_head.angles;
+ ad = AnglesTransform_Normalize(ad, true);
+ //UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload2) + ('0 1 0' * (1 - player.vehicle_reload2)), 2);
+
+ // Rotate head
+ ftmp = autocvar_g_vehicle_spiderbot_head_turnspeed * sys_frametime;
+ ad_y = bound(-ftmp, ad_y, ftmp);
+ spider.tur_head.angles_y = bound(autocvar_g_vehicle_spiderbot_head_turnlimit * -1, spider.tur_head.angles_y + ad_y, autocvar_g_vehicle_spiderbot_head_turnlimit);
+
+ // Pitch head
+ ad_x = bound(ftmp * -1, ad_x, ftmp);
+ spider.tur_head.angles_x = bound(autocvar_g_vehicle_spiderbot_head_pitchlimit_down, spider.tur_head.angles_x + ad_x, autocvar_g_vehicle_spiderbot_head_pitchlimit_up);
+
+
+ //fixedmakevectors(spider.angles);
+ makevectors(spider.angles + '-2 0 0' * spider.angles_x);
+
+ movelib_groundalign4point(autocvar_g_vehicle_spiderbot_springlength, autocvar_g_vehicle_spiderbot_springup, autocvar_g_vehicle_spiderbot_springblend, autocvar_g_vehicle_spiderbot_tiltlimit);
+
+ if(spider.flags & FL_ONGROUND)
+ spider.jump_delay = time; // reset now so movement can begin
+
+ //if(spider.flags & FL_ONGROUND)
+ {
+ if(spider.flags & FL_ONGROUND)
+ if(spider.frame == 4 && self.tur_head.wait != 0)
+ {
+ sound (self, CH_TRIGGER_SINGLE, SND_VEH_SPIDERBOT_LAND, VOL_VEHICLEENGINE, ATTEN_NORM);
+ spider.frame = 5;
+ }
+
+ if(!player.BUTTON_JUMP)
+ spider.BUTTON_JUMP = 0;
+
+ if((spider.flags & FL_ONGROUND) && player.BUTTON_JUMP && !spider.BUTTON_JUMP && self.tur_head.wait < time)
+ {
+ sound (self, CH_TRIGGER_SINGLE, SND_VEH_SPIDERBOT_JUMP, VOL_VEHICLEENGINE, ATTEN_NORM);
+ //dprint("spiderbot_jump:", ftos(soundlength("vehicles/spiderbot_jump.wav")), "\n");
+ self.delay = 0;
+
+ self.tur_head.wait = time + 2;
+ spider.jump_delay = time + 2;
+ spider.BUTTON_JUMP = 1; // set spider's jump
+ //player.BUTTON_JUMP = 0;
+
+ vector movefix = '0 0 0';
+ if(player.movement_x > 0) movefix_x = 1;
+ if(player.movement_x < 0) movefix_x = -1;
+ if(player.movement_y > 0) movefix_y = 1;
+ if(player.movement_y < 0) movefix_y = -1;
+
+ vector rt = movefix_y * v_right;
+ vector sd = movefix_x * v_forward;
+ if(movefix_y == 0 && movefix_x == 0)
+ sd = v_forward; // always do forward
+
+ spider.flags &= ~FL_ONGROUND;
+
+ spider.velocity = sd * 700 + rt * 600 + v_up * 600;
+ spider.frame = 4;
+ }
+ else if(time >= spider.jump_delay)
+ {
+ if(vlen(player.movement) == 0)
+ {
+ if(spider.flags & FL_ONGROUND)
+ {
+ if(self.sound_nexttime < time || self.delay != 3)
+ {
+ self.delay = 3;
+ self.sound_nexttime = time + 6.486500; //soundlength("vehicles/spiderbot_idle.wav");
+ //dprint("spiderbot_idle:", ftos(soundlength("vehicles/spiderbot_idle.wav")), "\n");
+ sound (self, CH_TRIGGER_SINGLE, SND_VEH_SPIDERBOT_IDLE, VOL_VEHICLEENGINE, ATTEN_NORM);
+ }
+ movelib_beak_simple(autocvar_g_vehicle_spiderbot_speed_stop);
+ spider.frame = 5;
+ }
+ }
+ else
+ {
+ // Turn Body
+ if(player.movement_x == 0 && player.movement_y != 0)
+ ftmp = autocvar_g_vehicle_spiderbot_turnspeed_strafe * sys_frametime;
+ else
+ ftmp = autocvar_g_vehicle_spiderbot_turnspeed * sys_frametime;
+
+ ftmp = bound(-ftmp, spider.tur_head.angles_y, ftmp);
+ spider.angles_y = anglemods(spider.angles_y + ftmp);
+ spider.tur_head.angles_y -= ftmp;
+
+ if(player.movement_x != 0)
+ {
+ if(player.movement_x > 0)
+ {
+ player.movement_x = 1;
+ if(spider.flags & FL_ONGROUND)
+ spider.frame = 0;
+ }
+ else if(player.movement_x < 0)
+ {
+ player.movement_x = -1;
+ if(spider.flags & FL_ONGROUND)
+ spider.frame = 1;
+ }
+ player.movement_y = 0;
+ float oldvelz = spider.velocity_z;
+ movelib_move_simple(normalize(v_forward * player.movement_x),((player.BUTTON_JUMP) ? autocvar_g_vehicle_spiderbot_speed_run : autocvar_g_vehicle_spiderbot_speed_walk),autocvar_g_vehicle_spiderbot_movement_inertia);
+ spider.velocity_z = oldvelz;
+ float g = ((autocvar_sv_gameplayfix_gravityunaffectedbyticrate) ? 0.5 : 1);
+ if(spider.velocity_z <= 20) // not while jumping
+ spider.velocity_z -= g * sys_frametime * autocvar_sv_gravity;
+ if(spider.flags & FL_ONGROUND)
+ if(self.sound_nexttime < time || self.delay != 1)
+ {
+ self.delay = 1;
+ self.sound_nexttime = time + 6.486500; //soundlength("vehicles/spiderbot_walk.wav");
+ sound (self, CH_TRIGGER_SINGLE, SND_VEH_SPIDERBOT_WALK, VOL_VEHICLEENGINE, ATTEN_NORM);
+ //dprint("spiderbot_walk:", ftos(soundlength("vehicles/spiderbot_walk.wav")), "\n");
+ }
+ }
+ else if(player.movement_y != 0)
+ {
+ if(player.movement_y < 0)
+ {
+ player.movement_y = -1;
+ if(spider.flags & FL_ONGROUND)
+ spider.frame = 2;
+ }
+ else if(player.movement_y > 0)
+ {
+ player.movement_y = 1;
+ if(spider.flags & FL_ONGROUND)
+ spider.frame = 3;
+ }
+
+ float oldvelz = spider.velocity_z;
+ movelib_move_simple(normalize(v_right * player.movement_y),autocvar_g_vehicle_spiderbot_speed_strafe,autocvar_g_vehicle_spiderbot_movement_inertia);
+ spider.velocity_z = oldvelz;
+ float g = ((autocvar_sv_gameplayfix_gravityunaffectedbyticrate) ? 0.5 : 1);
+ if(spider.velocity_z <= 20) // not while jumping
+ spider.velocity_z -= g * sys_frametime * autocvar_sv_gravity;
+ if(spider.flags & FL_ONGROUND)
+ if(self.sound_nexttime < time || self.delay != 2)
+ {
+ self.delay = 2;
+ self.sound_nexttime = time + 6.486500; //soundlength("vehicles/spiderbot_strafe.wav");
+ sound (self, CH_TRIGGER_SINGLE, SND_VEH_SPIDERBOT_STRAFE, VOL_VEHICLEENGINE, ATTEN_NORM);
+ //dprint("spiderbot_strafe:", ftos(soundlength("vehicles/spiderbot_strafe.wav")), "\n");
+ }
+ }
+ }
+ }
+ }
+
+ self.angles_x = bound(-autocvar_g_vehicle_spiderbot_tiltlimit, self.angles_x, autocvar_g_vehicle_spiderbot_tiltlimit);
+ self.angles_z = bound(-autocvar_g_vehicle_spiderbot_tiltlimit, self.angles_z, autocvar_g_vehicle_spiderbot_tiltlimit);
+
+ if(!forbidWeaponUse(player))
+ if(player.BUTTON_ATCK)
+ {
+ spider.cnt = time;
+ if(spider.vehicle_ammo1 >= autocvar_g_vehicle_spiderbot_minigun_ammo_cost && spider.tur_head.attack_finished_single <= time)
+ {
+ entity gun;
+ vector v;
+ spider.misc_bulletcounter += 1;
+
+ setself(player);
+
+ gun = (spider.misc_bulletcounter % 2) ? spider.gun1 : spider.gun2;
+
+ v = gettaginfo(gun, gettagindex(gun, "barrels"));
+ v_forward = normalize(v_forward);
+ v += v_forward * 50;
+
+ fireBullet(v, v_forward, autocvar_g_vehicle_spiderbot_minigun_spread, autocvar_g_vehicle_spiderbot_minigun_solidpenetration,
+ autocvar_g_vehicle_spiderbot_minigun_damage, autocvar_g_vehicle_spiderbot_minigun_force, DEATH_VH_SPID_MINIGUN, 0);
+
+ sound (gun, CH_WEAPON_A, SND_UZI_FIRE, VOL_BASE, ATTEN_NORM);
+ //trailparticles(self, _particleeffectnum("spiderbot_minigun_trail"), v, trace_endpos);
+ pointparticles(particleeffectnum(EFFECT_SPIDERBOT_MINIGUN_MUZZLEFLASH), v, v_forward * 2500, 1);
+
+ setself(spider);
+
+ spider.vehicle_ammo1 -= autocvar_g_vehicle_spiderbot_minigun_ammo_cost;
+ spider.tur_head.attack_finished_single = time + autocvar_g_vehicle_spiderbot_minigun_refire;
+ player.vehicle_ammo1 = (spider.vehicle_ammo1 / autocvar_g_vehicle_spiderbot_minigun_ammo_max) * 100;
+ spider.gun1.angles_z += 45;
+ spider.gun2.angles_z -= 45;
+ if(spider.gun1.angles_z >= 360)
+ {
+ spider.gun1.angles_z = 0;
+ spider.gun2.angles_z = 0;
+ }
+ }
+ }
+ else
+ vehicles_regen(spider.cnt, vehicle_ammo1, autocvar_g_vehicle_spiderbot_minigun_ammo_max,
+ autocvar_g_vehicle_spiderbot_minigun_ammo_regen_pause,
+ autocvar_g_vehicle_spiderbot_minigun_ammo_regen, frametime, false);
+
+
+ spiderbot_rocket_do();
+
+ if(self.vehicle_flags & VHF_SHIELDREGEN)
+ vehicles_regen(spider.dmg_time, vehicle_shield, autocvar_g_vehicle_spiderbot_shield, autocvar_g_vehicle_spiderbot_shield_regen_pause, autocvar_g_vehicle_spiderbot_shield_regen, frametime, true);
+
+ if(self.vehicle_flags & VHF_HEALTHREGEN)
+ vehicles_regen(spider.dmg_time, vehicle_health, autocvar_g_vehicle_spiderbot_health, autocvar_g_vehicle_spiderbot_health_regen_pause, autocvar_g_vehicle_spiderbot_health_regen, frametime, false);
+
+ player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
+ //player.vehicle_ammo2 = spider.tur_head.frame;
+ player.vehicle_ammo2 = (9 - spider.tur_head.frame) / 8 * 100; // Percentage, like ammo1
+
+ if(spider.gun2.cnt <= time)
+ player.vehicle_reload2 = 100;
+ else
+ player.vehicle_reload2 = 100 - ((spider.gun2.cnt - time) / spider.attack_finished_single) * 100;
+
+ setorigin(player, spider.origin + '0 0 1' * spider.maxs_z);
+ player.velocity = spider.velocity;
+
+ VEHICLE_UPDATE_PLAYER(player, health, spiderbot);
+
+ if(self.vehicle_flags & VHF_HASSHIELD)
+ VEHICLE_UPDATE_PLAYER(player, shield, spiderbot);
+
+ setself(player);
+ return 1;
+}
+
+void spiderbot_exit(float eject)
+{SELFPARAM();
+ entity e;
+ vector spot;
+
+ e = findchain(classname,"spiderbot_rocket");
+ while(e)
+ {
+ if(e.owner == self.owner)
+ {
+ e.realowner = self.owner;
+ e.owner = world;
+ }
+ e = e.chain;
+ }
+
+ self.think = vehicles_think;
+ self.nextthink = time;
+ self.frame = 5;
+ self.movetype = MOVETYPE_WALK;
+
+ if(!self.owner)
+ return;
+
+ makevectors(self.angles);
+ if(eject)
+ {
+ spot = self.origin + v_forward * 100 + '0 0 64';
+ spot = vehicles_findgoodexit(spot);
+ setorigin(self.owner , spot);
+ self.owner.velocity = (v_up + v_forward * 0.25) * 750;
+ self.owner.oldvelocity = self.owner.velocity;
+ }
+ else
+ {
+ if(vlen(self.velocity) > autocvar_g_vehicle_spiderbot_speed_strafe)
+ {
+ self.owner.velocity = normalize(self.velocity) * vlen(self.velocity);
+ self.owner.velocity_z += 200;
+ spot = self.origin + v_forward * 128 + '0 0 64';
+ spot = vehicles_findgoodexit(spot);
+ }
+ else
+ {
+ self.owner.velocity = self.velocity * 0.5;
+ self.owner.velocity_z += 10;
+ spot = self.origin + v_forward * 256 + '0 0 64';
+ spot = vehicles_findgoodexit(spot);
+ }
+ self.owner.oldvelocity = self.owner.velocity;
+ setorigin(self.owner , spot);
+ }
+
+ antilag_clear(self.owner);
+ self.owner = world;
+}
+
+void spiderbot_headfade()
+{SELFPARAM();
+ self.think = spiderbot_headfade;
+ self.nextthink = self.fade_time;
+ self.alpha = 1 - (time - self.fade_time) * self.fade_rate;
+
+ if(self.cnt < time || self.alpha < 0.1)
+ {
+ if(self.alpha > 0.1)
+ {
+ sound (self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
+ Send_Effect(EFFECT_EXPLOSION_BIG, self.origin + '0 0 100', '0 0 0', 1);
+ }
+ remove(self);
+ }
+}
+
+void spiderbot_blowup()
+{SELFPARAM();
+ if(self.cnt > time)
+ {
+ if(random() < 0.1)
+ {
+ sound (self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
+ Send_Effect(EFFECT_EXPLOSION_SMALL, randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
+ }
+ self.nextthink = time + 0.1;
+ return;
+ }
+
+ entity h, g1, g2, b;
+ b = spawn();
+ h = spawn();
+ g1 = spawn();
+ g2 = spawn();
+
+ setmodel(b, MDL_VEH_SPIDERBOT_BODY);
+ setmodel(h, MDL_VEH_SPIDERBOT_TOP);
+ setmodel(g1, MDL_VEH_SPIDERBOT_GUN);
+ setmodel(g2, MDL_VEH_SPIDERBOT_GUN);
+
+ setorigin(b, self.origin);
+ b.frame = 11;
+ b.angles = self.angles;
+ setsize(b, self.mins, self.maxs);
+
+ setorigin(h, gettaginfo(self, gettagindex(self, "tag_head")));
+ h.movetype = MOVETYPE_BOUNCE;
+ h.solid = SOLID_BBOX;
+ h.velocity = v_up * (500 + random() * 500) + randomvec() * 128;
+ h.modelflags = MF_ROCKET;
+ h.effects = EF_FLAME | EF_LOWPRECISION;
+ h.avelocity = randomvec() * 360;
+
+ h.alpha = 1;
+ h.cnt = time + (3.5 * random());
+ h.fade_rate = 1 / min(self.respawntime, 10);
+ h.fade_time = time;
+ h.think = spiderbot_headfade;
+ h.nextthink = time;
+
+ setorigin(g1, gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_hardpoint01")));
+ g1.movetype = MOVETYPE_TOSS;
+ g1.solid = SOLID_CORPSE;
+ g1.velocity = v_forward * 700 + (randomvec() * 32);
+ g1.avelocity = randomvec() * 180;
+
+ setorigin(g2, gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_hardpoint02")));
+ g2.movetype = MOVETYPE_TOSS;
+ g2.solid = SOLID_CORPSE;
+ g2.velocity = v_forward * 700 + (randomvec() * 32);
+ g2.avelocity = randomvec() * 180;
+
+ h.colormod = b.colormod = g1.colormod = g2.colormod = '-2 -2 -2';
+
+ SUB_SetFade(b, time + 5, min(self.respawntime, 1));
+ //SUB_SetFade(h, time, min(self.respawntime, 10));
+ SUB_SetFade(g1, time, min(self.respawntime, 10));
+ SUB_SetFade(g2, time, min(self.respawntime, 10));
+
+ RadiusDamage (self, self.enemy, 250, 15, 250, world, world, 250, DEATH_VH_SPID_DEATH, world);
+
+ self.alpha = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = -1;
+ self.movetype = MOVETYPE_NONE;
+ self.deadflag = DEAD_DEAD;
+ self.solid = SOLID_NOT;
+ self.tur_head.effects &= ~EF_FLAME;
+ self.vehicle_hudmodel.viewmodelforclient = self;
+}
+
+bool spiderbot_impulse(int _imp)
+{SELFPARAM();
+ switch(_imp)
+ {
+ case 1:
+ self.vehicle.vehicle_weapon2mode = SBRM_VOLLY;
+ CSQCVehicleSetup(self, 0);
+ return true;
+ case 2:
+ self.vehicle.vehicle_weapon2mode = SBRM_GUIDE;
+ CSQCVehicleSetup(self, 0);
+ return true;
+ case 3:
+ self.vehicle.vehicle_weapon2mode = SBRM_ARTILLERY;
+ CSQCVehicleSetup(self, 0);
+ return true;
+
+ case 10:
+ case 15:
+ case 18:
+ self.vehicle.vehicle_weapon2mode += 1;
+ if(self.vehicle.vehicle_weapon2mode > SBRM_LAST)
+ self.vehicle.vehicle_weapon2mode = SBRM_FIRST;
+
+ //centerprint(self, strcat("Rocket mode is ", ftos(self.vehicle.vehicle_weapon2mode)));
+ CSQCVehicleSetup(self, 0);
+ return true;
+ case 11:
+ case 12:
+ case 16:
+ case 19:
+ self.vehicle.vehicle_weapon2mode -= 1;
+ if(self.vehicle.vehicle_weapon2mode < SBRM_FIRST)
+ self.vehicle.vehicle_weapon2mode = SBRM_LAST;
+
+ //centerprint(self, strcat("Rocket mode is ", ftos(self.vehicle.vehicle_weapon2mode)));
+ CSQCVehicleSetup(self, 0);
+ return true;
+
+ /*
+ case 17: // toss gun, could be used to exit?
+ break;
+ case 20: // Manual minigun reload?
+ break;
+ */
+ }
+ return false;
+}
+
+spawnfunc(vehicle_spiderbot)
+{
+ if(!autocvar_g_vehicle_spiderbot) { remove(self); return; }
+ if(!vehicle_initialize(VEH_SPIDERBOT, false)) { remove(self); return; }
+}
+
+ METHOD(Spiderbot, vr_impact, void(Spiderbot thisveh))
+ {
+ if(autocvar_g_vehicle_spiderbot_bouncepain)
+ vehicles_impact(autocvar_g_vehicle_spiderbot_bouncepain_x, autocvar_g_vehicle_spiderbot_bouncepain_y, autocvar_g_vehicle_spiderbot_bouncepain_z);
+ }
+ METHOD(Spiderbot, vr_enter, void(Spiderbot thisveh))
+ {
+ self.vehicle_weapon2mode = SBRM_GUIDE;
+ self.movetype = MOVETYPE_WALK;
+ CSQCVehicleSetup(self.owner, 0);
+ self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_spiderbot_health) * 100;
+ self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_spiderbot_shield) * 100;
+
+ if(self.owner.flagcarried)
+ {
+ setattachment(self.owner.flagcarried, self.tur_head, "");
+ setorigin(self.owner.flagcarried, '-20 0 120');
+ }
+ }
+ METHOD(Spiderbot, vr_think, void(Spiderbot thisveh))
+ {
+ if(self.flags & FL_ONGROUND)
+ movelib_beak_simple(autocvar_g_vehicle_spiderbot_speed_stop);
+ }
+ METHOD(Spiderbot, vr_death, void(Spiderbot thisveh))
+ {
+ self.health = 0;
+ self.event_damage = func_null;
+ self.takedamage = DAMAGE_NO;
+ self.touch = func_null;
+ self.cnt = 3.4 + time + random() * 2;
+ self.think = spiderbot_blowup;
+ self.nextthink = time;
+ self.deadflag = DEAD_DYING;
+ self.frame = 5;
+ self.tur_head.effects |= EF_FLAME;
+ self.colormod = self.tur_head.colormod = '-1 -1 -1';
+ self.frame = 10;
+ self.movetype = MOVETYPE_TOSS;
+
+ CSQCModel_UnlinkEntity(self); // networking the death scene would be a nightmare
+ }
+ METHOD(Spiderbot, vr_spawn, void(Spiderbot thisveh))
+ {
+ if(!self.gun1)
+ {
+ self.vehicles_impulse = spiderbot_impulse;
+ self.gun1 = spawn();
+ self.gun2 = spawn();
+ setmodel(self.gun1, MDL_VEH_SPIDERBOT_GUN);
+ setmodel(self.gun2, MDL_VEH_SPIDERBOT_GUN);
+ setattachment(self.gun1, self.tur_head, "tag_hardpoint01");
+ setattachment(self.gun2, self.tur_head, "tag_hardpoint02");
+ self.gravity = 2;
+ self.mass = 5000;
+ }
+
+ self.frame = 5;
+ self.tur_head.frame = 1;
+ self.movetype = MOVETYPE_WALK;
+ self.solid = SOLID_SLIDEBOX;
+ self.alpha = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = 1;
+ self.tur_head.angles = '0 0 0';
+ self.vehicle_exit = spiderbot_exit;
+
+ setorigin(self, self.pos1 + '0 0 128');
+ self.angles = self.pos2;
+ self.damageforcescale = 0.03;
+ self.vehicle_health = autocvar_g_vehicle_spiderbot_health;
+ self.vehicle_shield = autocvar_g_vehicle_spiderbot_shield;
+
+ self.PlayerPhysplug = spiderbot_frame;
+ }
+ METHOD(Spiderbot, vr_setup, void(Spiderbot thisveh))
+ {
+ if(autocvar_g_vehicle_spiderbot_shield)
+ self.vehicle_flags |= VHF_HASSHIELD;
+
+ if(autocvar_g_vehicle_spiderbot_shield_regen)
+ self.vehicle_flags |= VHF_SHIELDREGEN;
+
+ if(autocvar_g_vehicle_spiderbot_health_regen)
+ self.vehicle_flags |= VHF_HEALTHREGEN;
+
+ self.respawntime = autocvar_g_vehicle_spiderbot_respawntime;
+ self.vehicle_health = autocvar_g_vehicle_spiderbot_health;
+ self.vehicle_shield = autocvar_g_vehicle_spiderbot_shield;
+ self.max_health = self.vehicle_health;
+ self.pushable = true; // spiderbot can use jumppads
+ }
+
+#endif // SVQC
+#ifdef CSQC
+float autocvar_cl_vehicle_spiderbot_cross_alpha = 0.6;
+float autocvar_cl_vehicle_spiderbot_cross_size = 1;
+
+ METHOD(Spiderbot, vr_hud, void(Spiderbot thisveh))
+ {
+ string crosshair;
+
+ switch(weapon2mode)
+ {
+ case SBRM_VOLLY: crosshair = vCROSS_BURST; break;
+ case SBRM_GUIDE: crosshair = vCROSS_GUIDE; break;
+ case SBRM_ARTILLERY: crosshair = vCROSS_RAIN; break;
+ default: crosshair = vCROSS_BURST;
+ }
+
+ Vehicles_drawHUD(VEH_SPIDERBOT.m_icon, "vehicle_spider_weapon1", "vehicle_spider_weapon2",
+ "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
+ "vehicle_icon_ammo2", autocvar_hud_progressbar_vehicles_ammo2_color,
+ crosshair);
+ }
+ METHOD(Spiderbot, vr_setup, void(Spiderbot thisveh))
+ {
+ AuxiliaryXhair[0].axh_image = vCROSS_HINT; // Minigun1
+ AuxiliaryXhair[1].axh_image = vCROSS_HINT; // Minigun2
+ }
+
+#endif
+#endif
--- /dev/null
+#ifndef VEHICLE_SPIDERBOT_WEAPONS_H
+#define VEHICLE_SPIDERBOT_WEAPONS_H
+
+#include "../../weapons/all.qh"
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+float autocvar_g_vehicle_spiderbot_minigun_damage;
+float autocvar_g_vehicle_spiderbot_minigun_refire;
+float autocvar_g_vehicle_spiderbot_minigun_spread;
+int autocvar_g_vehicle_spiderbot_minigun_ammo_cost;
+int autocvar_g_vehicle_spiderbot_minigun_ammo_max;
+int autocvar_g_vehicle_spiderbot_minigun_ammo_regen;
+float autocvar_g_vehicle_spiderbot_minigun_ammo_regen_pause;
+float autocvar_g_vehicle_spiderbot_minigun_force;
+float autocvar_g_vehicle_spiderbot_minigun_solidpenetration;
+
+float autocvar_g_vehicle_spiderbot_rocket_damage;
+float autocvar_g_vehicle_spiderbot_rocket_force;
+float autocvar_g_vehicle_spiderbot_rocket_radius;
+float autocvar_g_vehicle_spiderbot_rocket_speed;
+float autocvar_g_vehicle_spiderbot_rocket_spread;
+float autocvar_g_vehicle_spiderbot_rocket_refire;
+float autocvar_g_vehicle_spiderbot_rocket_refire2;
+float autocvar_g_vehicle_spiderbot_rocket_reload;
+float autocvar_g_vehicle_spiderbot_rocket_health;
+float autocvar_g_vehicle_spiderbot_rocket_noise;
+float autocvar_g_vehicle_spiderbot_rocket_turnrate;
+float autocvar_g_vehicle_spiderbot_rocket_lifetime;
+
+void spiderbot_rocket_artillery()
+{SELFPARAM();
+ self.nextthink = time;
+ UpdateCSQCProjectile(self);
+}
+
+void spiderbot_rocket_unguided()
+{SELFPARAM();
+ vector newdir, olddir;
+
+ self.nextthink = time;
+
+ olddir = normalize(self.velocity);
+ newdir = normalize(self.pos1 - self.origin) + randomvec() * autocvar_g_vehicle_spiderbot_rocket_noise;
+ self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_spiderbot_rocket_turnrate) * autocvar_g_vehicle_spiderbot_rocket_speed;
+
+ UpdateCSQCProjectile(self);
+
+ if (self.owner.deadflag != DEAD_NO || self.cnt < time || vlen(self.pos1 - self.origin) < 16)
+ self.use();
+}
+
+void spiderbot_rocket_guided()
+{SELFPARAM();
+ vector newdir, olddir;
+
+ self.nextthink = time;
+
+ if(!self.realowner.vehicle)
+ self.think = spiderbot_rocket_unguided;
+
+ crosshair_trace(self.realowner);
+ olddir = normalize(self.velocity);
+ newdir = normalize(trace_endpos - self.origin) + randomvec() * autocvar_g_vehicle_spiderbot_rocket_noise;
+ self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_spiderbot_rocket_turnrate) * autocvar_g_vehicle_spiderbot_rocket_speed;
+
+ UpdateCSQCProjectile(self);
+
+ if (self.owner.deadflag != DEAD_NO || self.cnt < time)
+ self.use();
+}
+
+void spiderbot_guide_release()
+{SELFPARAM();
+ entity rkt;
+ rkt = findchainentity(realowner, self.owner);
+ if(!rkt)
+ return;
+
+ crosshair_trace(self.owner);
+ while(rkt)
+ {
+ if(rkt.think == spiderbot_rocket_guided)
+ {
+ rkt.pos1 = trace_endpos;
+ rkt.think = spiderbot_rocket_unguided;
+ }
+ rkt = rkt.chain;
+ }
+}
+
+float spiberbot_calcartillery_flighttime;
+vector spiberbot_calcartillery(vector org, vector tgt, float ht)
+{
+ float grav, sdist, zdist, vs, vz, jumpheight;
+ vector sdir;
+
+ grav = autocvar_sv_gravity;
+ zdist = tgt_z - org_z;
+ sdist = vlen(tgt - org - zdist * '0 0 1');
+ sdir = normalize(tgt - org - zdist * '0 0 1');
+
+ // how high do we need to go?
+ jumpheight = fabs(ht);
+ if(zdist > 0)
+ jumpheight = jumpheight + zdist;
+
+ // push so high...
+ vz = sqrt(2 * grav * jumpheight); // NOTE: sqrt(positive)!
+
+ // we start with downwards velocity only if it's a downjump and the jump apex should be outside the jump!
+ if(ht < 0)
+ if(zdist < 0)
+ vz = -vz;
+
+ vector solution;
+ solution = solve_quadratic(0.5 * grav, -vz, zdist); // equation "z(ti) = zdist"
+ // ALWAYS solvable because jumpheight >= zdist
+ if(!solution_z)
+ solution_y = solution_x; // just in case it is not solvable due to roundoff errors, assume two equal solutions at their center (this is mainly for the usual case with ht == 0)
+ if(zdist == 0)
+ solution_x = solution_y; // solution_x is 0 in this case, so don't use it, but rather use solution_y (which will be sqrt(0.5 * jumpheight / grav), actually)
+
+ if(zdist < 0)
+ {
+ // down-jump
+ if(ht < 0)
+ {
+ // almost straight line type
+ // jump apex is before the jump
+ // we must take the larger one
+ spiberbot_calcartillery_flighttime = solution_y;
+ }
+ else
+ {
+ // regular jump
+ // jump apex is during the jump
+ // we must take the larger one too
+ spiberbot_calcartillery_flighttime = solution_y;
+ }
+ }
+ else
+ {
+ // up-jump
+ if(ht < 0)
+ {
+ // almost straight line type
+ // jump apex is after the jump
+ // we must take the smaller one
+ spiberbot_calcartillery_flighttime = solution_x;
+ }
+ else
+ {
+ // regular jump
+ // jump apex is during the jump
+ // we must take the larger one
+ spiberbot_calcartillery_flighttime = solution_y;
+ }
+ }
+ vs = sdist / spiberbot_calcartillery_flighttime;
+
+ // finally calculate the velocity
+ return sdir * vs + '0 0 1' * vz;
+}
+
+void spiderbot_rocket_do()
+{SELFPARAM();
+ vector v;
+ entity rocket = world;
+
+ if (self.wait != -10)
+ {
+ if (self.owner.BUTTON_ATCK2 && self.vehicle_weapon2mode == SBRM_GUIDE)
+ {
+ if (self.wait == 1)
+ if (self.tur_head.frame == 9 || self.tur_head.frame == 1)
+ {
+ if(self.gun2.cnt < time && self.tur_head.frame == 9)
+ self.tur_head.frame = 1;
+
+ return;
+ }
+ self.wait = 1;
+ }
+ else
+ {
+ if(self.wait)
+ spiderbot_guide_release();
+
+ self.wait = 0;
+ }
+ }
+
+ if(self.gun2.cnt > time)
+ return;
+
+ if (self.tur_head.frame >= 9)
+ {
+ self.tur_head.frame = 1;
+ self.wait = 0;
+ }
+
+ if(self.wait != -10)
+ if(!self.owner.BUTTON_ATCK2)
+ return;
+
+ if(forbidWeaponUse(self.owner))
+ return;
+
+ v = gettaginfo(self.tur_head,gettagindex(self.tur_head,"tag_fire"));
+
+ switch(self.vehicle_weapon2mode)
+ {
+ case SBRM_VOLLY:
+ rocket = vehicles_projectile(EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND(ROCKET_FIRE),
+ v, normalize(randomvec() * autocvar_g_vehicle_spiderbot_rocket_spread + v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
+ autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
+ DEATH_VH_SPID_ROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, true, self.owner);
+ crosshair_trace(self.owner);
+ float _dist = (random() * autocvar_g_vehicle_spiderbot_rocket_radius) + vlen(v - trace_endpos);
+ _dist -= (random() * autocvar_g_vehicle_spiderbot_rocket_radius) ;
+ rocket.nextthink = time + (_dist / autocvar_g_vehicle_spiderbot_rocket_speed);
+ rocket.think = vehicles_projectile_explode;
+
+ if(self.owner.BUTTON_ATCK2 && self.tur_head.frame == 1)
+ self.wait = -10;
+ break;
+ case SBRM_GUIDE:
+ rocket = vehicles_projectile(EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND(ROCKET_FIRE),
+ v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
+ autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
+ DEATH_VH_SPID_ROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, false, self.owner);
+ crosshair_trace(self.owner);
+ rocket.pos1 = trace_endpos;
+ rocket.nextthink = time;
+ rocket.think = spiderbot_rocket_guided;
+
+
+ break;
+ case SBRM_ARTILLERY:
+ rocket = vehicles_projectile(EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND(ROCKET_FIRE),
+ v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
+ autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
+ DEATH_VH_SPID_ROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, true, self.owner);
+
+ crosshair_trace(self.owner);
+
+ rocket.pos1 = trace_endpos + randomvec() * (0.75 * autocvar_g_vehicle_spiderbot_rocket_radius);
+ rocket.pos1_z = trace_endpos_z;
+
+ traceline(v, v + '0 0 1' * MAX_SHOT_DISTANCE, MOVE_WORLDONLY, self);
+ float h1 = 0.75 * vlen(v - trace_endpos);
+
+ //v = trace_endpos;
+ traceline(v , rocket.pos1 + '0 0 1' * MAX_SHOT_DISTANCE, MOVE_WORLDONLY, self);
+ float h2 = 0.75 * vlen(rocket.pos1 - v);
+
+ rocket.velocity = spiberbot_calcartillery(v, rocket.pos1, ((h1 < h2) ? h1 : h2));
+ rocket.movetype = MOVETYPE_TOSS;
+ rocket.gravity = 1;
+ //rocket.think = spiderbot_rocket_artillery;
+ break;
+ }
+ rocket.classname = "spiderbot_rocket";
+
+ rocket.cnt = time + autocvar_g_vehicle_spiderbot_rocket_lifetime;
+
+ self.tur_head.frame += 1;
+ if (self.tur_head.frame == 9)
+ self.attack_finished_single = autocvar_g_vehicle_spiderbot_rocket_reload;
+ else
+ self.attack_finished_single = ((self.vehicle_weapon2mode == SBRM_VOLLY) ? autocvar_g_vehicle_spiderbot_rocket_refire2 : autocvar_g_vehicle_spiderbot_rocket_refire);
+
+ self.gun2.cnt = time + self.attack_finished_single;
+}
+
+#endif
+
+#endif
// client movement
void viewloc_PlayerPhysics()
-{
+{SELFPARAM();
if(self.viewloc)
{
vector oldmovement = self.movement;
#ifdef CSQC
void viewloc_SetTags()
-{
+{SELFPARAM();
if(self.viewloc && wasfreed(self.viewloc))
self.viewloc = world;
#include "weapon/arc.qc"
#include "weapon/hmg.qc"
#include "weapon/rpc.qc"
+
+#include "../../server/mutators/gamemode_nexball_weapon.qc"
#include "../../warpzonelib/common.qh"
#include "../../warpzonelib/client.qh"
#include "../util.qh"
- #include "../buffs.qh"
+ #include "../buffs/all.qh"
#include "../../client/autocvars.qh"
#include "../deathtypes.qh"
#include "../../csqcmodellib/interpolate.qh"
#include "../stats.qh"
#include "../teams.qh"
#include "../util.qh"
- #include "../buffs.qh"
+ #include "../buffs/all.qh"
#include "../monsters/all.qh"
#include "config.qh"
#include "../../server/weapons/csqcprojectile.qh"
// WEAPON PLUGIN SYSTEM
-#if WEP_MAXCOUNT > 72
-# error Kein Weltraum links auf dem Gerät
-#endif
-
WepSet WepSet_FromWeapon(int a) {
a -= WEP_FIRST;
-#if WEP_MAXCOUNT > 24
- if(a >= 24) {
+ if (Weapons_MAX > 24)
+ if (a >= 24) {
a -= 24;
-#if WEP_MAXCOUNT > 48
- if(a >= 24) {
+ if (Weapons_MAX > 48)
+ if (a >= 24) {
a -= 24;
return '0 0 1' * power2of(a);
}
-#endif
return '0 1 0' * power2of(a);
}
-#endif
return '1 0 0' * power2of(a);
}
#ifdef SVQC
void WepSet_AddStat()
{
addstat(STAT_WEAPONS, AS_INT, weapons_x);
-#if WEP_MAXCOUNT > 24
+ if (Weapons_MAX > 24)
addstat(STAT_WEAPONS2, AS_INT, weapons_y);
-#if WEP_MAXCOUNT > 48
+ if (Weapons_MAX > 48)
addstat(STAT_WEAPONS3, AS_INT, weapons_z);
-#endif
-#endif
}
void WepSet_AddStat_InMap()
{
addstat(STAT_WEAPONSINMAP, AS_INT, weaponsinmap_x);
-#if WEP_MAXCOUNT > 24
+ if (Weapons_MAX > 24)
addstat(STAT_WEAPONSINMAP2, AS_INT, weaponsinmap_y);
-#if WEP_MAXCOUNT > 48
+ if (Weapons_MAX > 48)
addstat(STAT_WEAPONSINMAP3, AS_INT, weaponsinmap_z);
-#endif
-#endif
}
void WriteWepSet(float dst, WepSet w)
{
-#if WEP_MAXCOUNT > 48
+ if (Weapons_MAX > 48)
WriteInt72_t(dst, w);
-#elif WEP_MAXCOUNT > 24
+ else if (Weapons_MAX > 24)
WriteInt48_t(dst, w);
-#else
+ else
WriteInt24_t(dst, w.x);
-#endif
}
#endif
#ifdef CSQC
{
WepSet w = '0 0 0';
w.x = getstati(STAT_WEAPONS);
-#if WEP_MAXCOUNT > 24
+ if (Weapons_MAX > 24)
w.y = getstati(STAT_WEAPONS2);
-#if WEP_MAXCOUNT > 48
+ if (Weapons_MAX > 48)
w.z = getstati(STAT_WEAPONS3);
-#endif
-#endif
return w;
}
WepSet WepSet_GetFromStat_InMap()
{
WepSet w = '0 0 0';
w_x = getstati(STAT_WEAPONSINMAP);
-#if WEP_MAXCOUNT > 24
+ if (Weapons_MAX > 24)
w_y = getstati(STAT_WEAPONSINMAP2);
-#if WEP_MAXCOUNT > 48
+ if (Weapons_MAX > 48)
w_z = getstati(STAT_WEAPONSINMAP3);
-#endif
-#endif
return w;
}
WepSet ReadWepSet()
{
-#if WEP_MAXCOUNT > 48
+ if (Weapons_MAX > 48)
return ReadInt72_t();
-#elif WEP_MAXCOUNT > 24
+ if (Weapons_MAX > 24)
return ReadInt48_t();
-#else
return ReadInt24_t() * '1 0 0';
-#endif
}
#endif
-void register_weapons_done()
-{
- dummy_weapon_info = NEW(Weapon);
-
- weaponorder_byid = "";
- for (int i = WEP_MAXCOUNT - 1; i >= 0; --i)
- if (weapon_info[i])
- weaponorder_byid = strcat(weaponorder_byid, " ", ftos(i));
- weaponorder_byid = strzone(substring(weaponorder_byid, 1, strlen(weaponorder_byid) - 1));
-}
-entity get_weaponinfo(int id)
-{
- entity w;
- if(id < WEP_FIRST || id > WEP_LAST)
- return dummy_weapon_info;
- w = weapon_info[id - 1];
- if(w)
- return w;
- return dummy_weapon_info;
-}
string W_FixWeaponOrder(string order, float complete)
{
- return fixPriorityList(order, WEP_FIRST, WEP_LAST, 230 - WEP_FIRST, complete);
+ return fixPriorityList(order, WEP_FIRST, WEP_LAST, WEP_IMPULSE_BEGIN - WEP_FIRST, complete);
}
string W_NameWeaponOrder_MapFunc(string s)
{
if(s == "0" || stof(s))
{
wi = get_weaponinfo(stof(s));
- if(wi != dummy_weapon_info)
+ if(wi != WEP_Null)
return wi.netname;
}
return s;
return mapPriorityList(order, W_NumberWeaponOrder_MapFunc);
}
-float W_FixWeaponOrder_BuildImpulseList_buf[WEP_MAXCOUNT];
+float W_FixWeaponOrder_BuildImpulseList_buf[Weapons_MAX];
string W_FixWeaponOrder_BuildImpulseList_order;
void W_FixWeaponOrder_BuildImpulseList_swap(int i, int j, entity pass)
{
string W_Sound(string w_snd)
{
- string output = strcat("weapons/", w_snd, ".wav");
+ #define extensions(X) X(wav) X(ogg)
+ #define tryext(ext) { if (fexists(strcat("sound/", output = strcat("weapons/", w_snd, "."#ext)))) break; }
+ string output;
+ do {
+ extensions(tryext);
+ #undef tryext
+ #undef extensions
+ output = strcat("weapons/", w_snd);
+ } while (0);
+
#ifdef SVQC
MUTATOR_CALLHOOK(WeaponSound, w_snd, output);
return weapon_sound_output;
#ifndef WEAPONS_ALL_H
#define WEAPONS_ALL_H
-#ifndef MENUQC
-#include "calculations.qh"
-#endif
-
-#include "../util.qh"
-#ifdef SVQC
-#include "../../server/bot/aim.qh"
-#endif
-const int MAX_SHOT_DISTANCE = 32768;
-
-// weapon pickup ratings for bot logic
-const int BOT_PICKUP_RATING_LOW = 2500;
-const int BOT_PICKUP_RATING_MID = 5000;
-const int BOT_PICKUP_RATING_HIGH = 10000;
-
-// weapon flags
-const int WEP_TYPE_OTHER = 0x00; // not for damaging people
-const int WEP_TYPE_SPLASH = 0x01; // splash damage
-const int WEP_TYPE_HITSCAN = 0x02; // hitscan
-const int WEP_TYPEMASK = 0x0F;
-const int WEP_FLAG_CANCLIMB = 0x10; // can be used for movement
-const int WEP_FLAG_NORMAL = 0x20; // in "most weapons" set
-const int WEP_FLAG_HIDDEN = 0x40; // hides from menu
-const int WEP_FLAG_RELOADABLE = 0x80; // can has reload
-const int WEP_FLAG_SUPERWEAPON = 0x100; // powerup timer
-const int WEP_FLAG_MUTATORBLOCKED = 0x200; // hides from impulse 99 etc. (mutators are allowed to clear this flag)
-
-// weapon requests
-const int WR_SETUP = 1; // (SERVER) setup weapon data
-const int WR_THINK = 2; // (SERVER) logic to run every frame
-const int WR_CHECKAMMO1 = 3; // (SERVER) checks ammo for weapon primary
-const int WR_CHECKAMMO2 = 4; // (SERVER) checks ammo for weapon second
-const int WR_AIM = 5; // (SERVER) runs bot aiming code for this weapon
-const int WR_INIT = 6; // (BOTH) precaches models/sounds used by this weapon, also sets up weapon properties
-const int WR_SUICIDEMESSAGE = 7; // (SERVER) notification number for suicide message (may inspect w_deathtype for details)
-const int WR_KILLMESSAGE = 8; // (SERVER) notification number for kill message (may inspect w_deathtype for details)
-const int WR_RELOAD = 9; // (SERVER) handles reloading for weapon
-const int WR_RESETPLAYER = 10; // (SERVER) clears fields that the weapon may use
-const int WR_IMPACTEFFECT = 11; // (CLIENT) impact effect for weapon explosion
-const int WR_PLAYERDEATH = 12; // (SERVER) called whenever a player dies
-const int WR_GONETHINK = 13; // (SERVER) logic to run when weapon is lost
-const int WR_CONFIG = 14; // (ALL) dump weapon cvars to config in data directory (see: sv_cmd dumpweapons)
-const int WR_ZOOMRETICLE = 15; // (CLIENT) weapon specific zoom reticle
-const int WR_DROP = 16; // (SERVER) the weapon is dropped
-const int WR_PICKUP = 17; // (SERVER) a weapon is picked up
-
-// variables:
-string weaponorder_byid;
-
// weapon sets
typedef vector WepSet;
+#define WEPSET(id) WepSet_FromWeapon(WEP_##id.m_id)
WepSet WepSet_FromWeapon(int a);
#ifdef SVQC
void WepSet_AddStat();
void WepSet_AddStat_InMap();
void WriteWepSet(float dest, WepSet w);
#endif
+
#ifdef CSQC
WepSet WepSet_GetFromStat();
WepSet WepSet_GetFromStat_InMap();
WepSet ReadWepSet();
#endif
-// weapon name macros
-const int WEP_FIRST = 1;
-#define WEP_MAXCOUNT 24 // Increase as needed. Can be up to three times as much.
-int WEP_COUNT;
-#define WEP_LAST (WEP_FIRST + WEP_COUNT - 1)
-WepSet WEPSET_ALL;
-WepSet WEPSET_SUPERWEAPONS;
+#include "weapon.qh"
-// functions:
-entity get_weaponinfo(int id);
-string W_FixWeaponOrder(string order, float complete);
-string W_UndeprecateName(string s);
-string W_NameWeaponOrder(string order);
-string W_NumberWeaponOrder(string order);
-string W_FixWeaponOrder_BuildImpulseList(string o);
-string W_FixWeaponOrder_AllowIncomplete(string order);
-string W_FixWeaponOrder_ForceComplete(string order);
-void W_RandomWeapons(entity e, float n);
-
-string GetAmmoPicture(.int ammotype);
-
-#ifdef CSQC
-.int GetAmmoFieldFromNum(int i);
-int GetAmmoStat(.int ammotype);
+#ifndef MENUQC
+#include "calculations.qh"
+#include "../models/all.qh"
#endif
-string W_Sound(string w_snd);
-string W_Model(string w_mdl);
-
-// ammo types
-.int ammo_shells;
-.int ammo_nails;
-.int ammo_rockets;
-.int ammo_cells;
-.int ammo_plasma;
-.int ammo_fuel;
-.int ammo_none;
+#include "../util.qh"
-// other useful macros
-#define WEP_ACTION(wpn,wrequest) (get_weaponinfo(wpn)).weapon_func(wrequest)
-#define WEP_AMMO(wpn) (WEP_##wpn.ammo_field) // only used inside weapon files/with direct name, don't duplicate prefix
-#define WEP_NAME(wpn) ((get_weaponinfo(wpn)).message)
+#ifdef SVQC
+#include "../../server/bot/aim.qh"
+#endif
+REGISTRY(Weapons, 72) // Increase as needed. Can be up to 72.
+REGISTER_REGISTRY(RegisterWeapons)
+entity get_weaponinfo(int id);
-// ======================
-// Configuration Macros
-// ======================
+#define REGISTER_WEAPON(id, inst) \
+ /* WepSet WEPSET_##id; */ \
+ REGISTER(RegisterWeapons, WEP, Weapons, id, m_id, inst)
// create cvars for weapon settings
#define WEP_ADD_CVAR_NONE(wepname,name) [[last]] float autocvar_g_balance_##wepname##_##name;
#define WEP_SKIP_CVAR(unuseda,unusedb,unusedc,unusedd) /* skip cvars */
#define WEP_SET_PROP(wepid,wepname,type,prop,name) WEP_##wepid.prop = autocvar_g_balance_##wepname##_##name;
+const int WEP_FIRST = 1;
+#define WEP_LAST (Weapons_COUNT - 1)
+WepSet WEPSET_ALL;
+WepSet WEPSET_SUPERWEAPONS;
-// =====================
-// Weapon Registration
-// =====================
-
-bool w_null(int) { return false; }
-
-/** fields which are explicitly/manually set are marked with "M", fields set automatically are marked with "A" */
-CLASS(Weapon, Object)
- ATTRIB(Weapon, m_id, int, 0)
- /**
- * M: WEP_id : WEP_...
- * you can recognize dummies when this == 0
- */
- ATTRIB(Weapon, weapon, int, 0);
- /** A: WEPSET_id : WEPSET_... */
- ATTRIB(Weapon, weapons, WepSet, '0 0 0');
- /** M: function : w_... */
- ATTRIB(Weapon, weapon_func, bool(int), w_null);
- /** M: ammotype : main ammo field */
- ATTRIB(Weapon, ammo_field, .int, ammo_none);
- /** M: impulse : weapon impulse */
- ATTRIB(Weapon, impulse, int, -1);
- /** M: flags : WEPSPAWNFLAG_... combined */
- ATTRIB(Weapon, spawnflags, int, 0);
- /** M: rating : bot weapon priority */
- ATTRIB(Weapon, bot_pickupbasevalue, float, 0);
- /** M: color : waypointsprite color */
- ATTRIB(Weapon, wpcolor, vector, '0 0 0');
- /** A: wpn-id : wpn- sprite name */
- ATTRIB(Weapon, wpmodel, string, "");
- /** M: modelname : name of model (without g_ v_ or h_ prefixes) */
- ATTRIB(Weapon, mdl, string, "");
- /** A: modelname : full path to g_ model */
- ATTRIB(Weapon, model, string, "");
- /** M: simplemdl : simpleitems weapon model/image */
- ATTRIB(Weapon, w_simplemdl, string, "foobar");
- /** M: crosshair : per-weapon crosshair: "CrosshairImage Size" */
- ATTRIB(Weapon, w_crosshair, string, "gfx/crosshair1");
- /** A: crosshair : per-weapon crosshair size (argument two of "crosshair" field) */
- ATTRIB(Weapon, w_crosshair_size, float, 1);
- /** M: wepimg : "weaponfoobar" side view image file of weapon. WEAPONTODO: Move out of skin files, move to common files */
- ATTRIB(Weapon, model2, string, "");
- /** M: refname : reference name name */
- ATTRIB(Weapon, netname, string, "");
- /** M: wepname : human readable name */
- ATTRIB(Weapon, message, string, "AOL CD Thrower");
+REGISTER_WEAPON(Null, NEW(Weapon));
- METHOD(Weapon, display, void(entity this, void(string name, string icon) returns)) {
- returns(this.message, this.model2 ? sprintf("/gfx/hud/%s/%s", cvar_string("menu_skin"), this.model2) : string_null);
- }
+#include "all.inc"
- CONSTRUCTOR(Weapon,
- bool(int) function,
- .int ammotype,
- int i,
- int weapontype,
- float pickupbasevalue,
- vector clr,
- string modelname,
- string simplemdl,
- string crosshair,
- string wepimg,
- string refname,
- string wepname
- ) {
- CONSTRUCT(Weapon);
- this.weapon_func = function;
- this.ammo_field = ammotype;
- this.impulse = i;
- this.spawnflags = weapontype;
- this.bot_pickupbasevalue = pickupbasevalue;
- this.wpcolor = clr;
- this.mdl = modelname;
- this.model = strzone(W_Model(strcat("g_", modelname, ".md3")));
- this.w_simplemdl = strzone(simplemdl); // simpleitems weapon model/image
- this.w_crosshair = strzone(car(crosshair));
- string s = cdr(crosshair);
- this.w_crosshair_size = ((s != "") ? stof(s) : 1); // so that we can scale the crosshair from code (for compat)
- this.model2 = strzone(wepimg);
- this.netname = refname;
- this.message = wepname;
+entity get_weaponinfo(int id)
+{
+ if (id >= WEP_FIRST && id <= WEP_LAST) {
+ Weapon w = Weapons[id];
+ if (w) return w;
}
- void register_weapon(entity this, int id, WepSet bit)
- {
- this.classname = "weapon_info";
- this.weapon = id;
- this.weapons = bit;
- this.wpmodel = strzone(strcat("wpn-", ftos(id)));
+ return WEP_Null;
+}
+
+// TODO: remove after 0.8.2. Retains impulse number compatibility because 0.8.1 clients don't reload the weapons.cfg
+#define WEP_HARDCODED_IMPULSES 22
+
+// TODO: invert after 0.8.2. Will require moving 'best weapon' impulses
+#define WEP_IMPULSE_BEGIN 230
+#define WEP_IMPULSE_END bound(WEP_IMPULSE_BEGIN, WEP_IMPULSE_BEGIN + (Weapons_COUNT - 1) - 1, 253)
+
+REGISTRY_SORT(Weapons, netname, WEP_HARDCODED_IMPULSES + 1)
+
+STATIC_INIT(register_weapons_done)
+{
+ for (int i = 0; i < Weapons_COUNT; ++i) {
+ Weapon it = Weapons[i];
+ it.m_id = i;
+ WepSet set = WepSet_FromWeapon(it.m_id);
+ WEPSET_ALL |= set;
+ if ((it.spawnflags) & WEP_FLAG_SUPERWEAPON) WEPSET_SUPERWEAPONS |= set;
+ it.weapon = it.m_id;
+ it.weapons = set;
#ifdef CSQC
- this.weapon_func(WR_INIT);
+ it.wr_init(it);
#endif
+ int imp = WEP_IMPULSE_BEGIN + it.m_id - 1;
+ if (imp <= WEP_IMPULSE_END)
+ localcmd(sprintf("alias weapon_%s \"impulse %d\"\n", it.netname, imp));
+ else
+ LOG_TRACEF(_("Impulse limit exceeded, weapon will not be directly accessible: %s\n"), it.netname);
}
-ENDCLASS(Weapon)
-
-void RegisterWeapons();
-REGISTER_REGISTRY(RegisterWeapons)
-entity weapon_info[WEP_MAXCOUNT], weapon_info_first, weapon_info_last;
-entity dummy_weapon_info;
-
-#define _REGISTER_WEAPON(id, function, ammotype, impulse, flags, rating, color, modelname, simplemdl, crosshair, wepimg, refname, wepname) \
- WepSet WEPSET_##id; \
- REGISTER(RegisterWeapons, WEP, weapon_info, WEP_COUNT, id, m_id, \
- NEW(Weapon, function, ammotype, impulse, flags, rating, color, modelname, simplemdl, crosshair, wepimg, refname, wepname) \
- ) { \
- this.m_id++; \
- WEPSET_ALL |= (WEPSET_##id = WepSet_FromWeapon(this.m_id)); \
- if ((flags) & WEP_FLAG_SUPERWEAPON) WEPSET_SUPERWEAPONS |= WEPSET_##id; \
- register_weapon(this, this.m_id, WEPSET_##id); \
- }
-
-#ifndef MENUQC
- #define REGISTER_WEAPON(id, function, ammotype, impulse, flags, rating, color, modelname, simplemdl, crosshair, wepimg, refname, wepname) \
- bool function(int); \
- _REGISTER_WEAPON(id, function, ammotype, impulse, flags, rating, color, modelname, simplemdl, crosshair, wepimg, refname, wepname)
-#else
- #define REGISTER_WEAPON(id, function, ammotype, impulse, flags, rating, color, modelname, simplemdl, crosshair, wepimg, refname, wepname) \
- _REGISTER_WEAPON(id, w_null, ammotype, impulse, flags, rating, color, modelname, simplemdl, crosshair, wepimg, refname, wepname)
-#endif
-
-#include "all.inc"
+ weaponorder_byid = "";
+ for (int i = Weapons_MAX - 1; i >= 1; --i)
+ if (Weapons[i])
+ weaponorder_byid = strcat(weaponorder_byid, " ", ftos(i));
+ weaponorder_byid = strzone(substring(weaponorder_byid, 1, strlen(weaponorder_byid) - 1));
+}
-#undef WEP_ADD_CVAR_MO_PRI
-#undef WEP_ADD_CVAR_MO_SEC
-#undef WEP_ADD_CVAR_MO_BOTH
-#undef WEP_ADD_CVAR_MO_NONE
-#undef WEP_ADD_CVAR
-#undef WEP_ADD_PROP
-void register_weapons_done();
-ACCUMULATE_FUNCTION(RegisterWeapons, register_weapons_done);
#endif
{ wep_config_queue[x] = string_null; }
// step 2: build new queue
- WEP_ACTION(i, WR_CONFIG);
+ Weapon w = get_weaponinfo(i);
+ w.wr_config(w);
// step 3: sort queue
heapsort(WEP_CONFIG_COUNT, W_Config_Queue_Swap, W_Config_Queue_Compare, world);
--- /dev/null
+#ifndef WEAPON_H
+#define WEAPON_H
+
+.int ammo_shells;
+.int ammo_nails;
+.int ammo_rockets;
+.int ammo_cells;
+.int ammo_plasma;
+.int ammo_fuel;
+.int ammo_none;
+
+/** fields which are explicitly/manually set are marked with "M", fields set automatically are marked with "A" */
+CLASS(Weapon, Object)
+ ATTRIB(Weapon, m_id, int, 0)
+ /**
+ * M: WEP_id : WEP_...
+ * you can recognize dummies when this == 0
+ */
+ ATTRIB(Weapon, weapon, int, 0);
+ /** A: WEPSET_id : WEPSET_... */
+ ATTRIB(Weapon, weapons, WepSet, '0 0 0');
+ /** M: ammotype : main ammo field */
+ ATTRIB(Weapon, ammo_field, .int, ammo_none);
+ /** M: impulse : weapon impulse */
+ ATTRIB(Weapon, impulse, int, -1);
+ /** M: flags : WEPSPAWNFLAG_... combined */
+ ATTRIB(Weapon, spawnflags, int, 0);
+ /** M: rating : bot weapon priority */
+ ATTRIB(Weapon, bot_pickupbasevalue, float, 0);
+ /** M: color : waypointsprite color */
+ ATTRIB(Weapon, wpcolor, vector, '0 0 0');
+ /** M: modelname : name of model (without g_ v_ or h_ prefixes) */
+ ATTRIB(Weapon, mdl, string, "");
+ /** M: model MDL_id_ITEM */
+ ATTRIB(Weapon, m_model, entity, NULL);
+ /** M: crosshair : per-weapon crosshair: "CrosshairImage Size" */
+ ATTRIB(Weapon, w_crosshair, string, "gfx/crosshair1");
+ /** A: crosshair : per-weapon crosshair size (argument two of "crosshair" field) */
+ ATTRIB(Weapon, w_crosshair_size, float, 1);
+ /** M: wepimg : "weaponfoobar" side view image file of weapon. WEAPONTODO: Move out of skin files, move to common files */
+ ATTRIB(Weapon, model2, string, "");
+ /** M: refname : reference name name */
+ ATTRIB(Weapon, netname, string, "");
+ /** M: wepname : human readable name */
+ ATTRIB(Weapon, message, string, "AOL CD Thrower");
+
+ /** (SERVER) setup weapon data */
+ METHOD(Weapon, wr_setup, void(Weapon this)) {}
+ /** (SERVER) logic to run every frame */
+ METHOD(Weapon, wr_think, void(Weapon this, entity actor, bool fire1, bool fire2)) {}
+ /** (SERVER) checks ammo for weapon primary */
+ METHOD(Weapon, wr_checkammo1, bool(Weapon this)) {return false;}
+ /** (SERVER) checks ammo for weapon second */
+ METHOD(Weapon, wr_checkammo2, bool(Weapon this)) {return false;}
+ /** (SERVER) runs bot aiming code for this weapon */
+ METHOD(Weapon, wr_aim, void(Weapon this)) {}
+ /** (BOTH) precaches models/sounds used by this weapon, also sets up weapon properties */
+ METHOD(Weapon, wr_init, void(Weapon this)) {}
+ /** (SERVER) notification number for suicide message (may inspect w_deathtype for details) */
+ METHOD(Weapon, wr_suicidemessage, int(Weapon this)) {return 0;}
+ /** (SERVER) notification number for kill message (may inspect w_deathtype for details) */
+ METHOD(Weapon, wr_killmessage, int(Weapon this)) {return 0;}
+ /** (SERVER) handles reloading for weapon */
+ METHOD(Weapon, wr_reload, void(Weapon this)) {}
+ /** (SERVER) clears fields that the weapon may use */
+ METHOD(Weapon, wr_resetplayer, void(Weapon this)) {}
+ /** (CLIENT) impact effect for weapon explosion */
+ METHOD(Weapon, wr_impacteffect, void(Weapon this)) {}
+ /** (SERVER) called whenever a player dies */
+ METHOD(Weapon, wr_playerdeath, void(Weapon this)) {}
+ /** (SERVER) logic to run when weapon is lost */
+ METHOD(Weapon, wr_gonethink, void(Weapon this)) {}
+ /** (ALL) dump weapon cvars to config in data directory (see: sv_cmd dumpweapons) */
+ METHOD(Weapon, wr_config, void(Weapon this)) {}
+ /** (CLIENT) weapon specific zoom reticle */
+ METHOD(Weapon, wr_zoomreticle, bool(Weapon this)) {
+ // no weapon specific image for this weapon
+ return false;
+ }
+ /** (SERVER) the weapon is dropped */
+ METHOD(Weapon, wr_drop, void(Weapon this)) {}
+ /** (SERVER) a weapon is picked up */
+ METHOD(Weapon, wr_pickup, void(Weapon this)) {}
+
+ METHOD(Weapon, display, void(entity this, void(string name, string icon) returns)) {
+ returns(this.message, this.model2 ? sprintf("/gfx/hud/%s/%s", cvar_string("menu_skin"), this.model2) : string_null);
+ }
+ENDCLASS(Weapon)
+
+CLASS(OffhandWeapon, Object)
+ METHOD(OffhandWeapon, offhand_think, void(OffhandWeapon this, entity player, bool key_pressed)) {}
+ENDCLASS(OffhandWeapon)
+
+#ifdef SVQC
+.OffhandWeapon offhand;
+#endif
+
+const int MAX_SHOT_DISTANCE = 32768;
+
+// weapon pickup ratings for bot logic
+const int BOT_PICKUP_RATING_LOW = 2500;
+const int BOT_PICKUP_RATING_MID = 5000;
+const int BOT_PICKUP_RATING_HIGH = 10000;
+
+// weapon flags
+const int WEP_TYPE_OTHER = 0x00; // not for damaging people
+const int WEP_TYPE_SPLASH = 0x01; // splash damage
+const int WEP_TYPE_HITSCAN = 0x02; // hitscan
+const int WEP_TYPEMASK = 0x0F;
+const int WEP_FLAG_CANCLIMB = 0x10; // can be used for movement
+const int WEP_FLAG_NORMAL = 0x20; // in "most weapons" set
+const int WEP_FLAG_HIDDEN = 0x40; // hides from menu
+const int WEP_FLAG_RELOADABLE = 0x80; // can has reload
+const int WEP_FLAG_SUPERWEAPON = 0x100; // powerup timer
+const int WEP_FLAG_MUTATORBLOCKED = 0x200; // hides from impulse 99 etc. (mutators are allowed to clear this flag)
+
+// variables:
+string weaponorder_byid;
+
+// functions:
+string W_FixWeaponOrder(string order, float complete);
+string W_UndeprecateName(string s);
+string W_NameWeaponOrder(string order);
+string W_NumberWeaponOrder(string order);
+string W_FixWeaponOrder_BuildImpulseList(string o);
+string W_FixWeaponOrder_AllowIncomplete(string order);
+string W_FixWeaponOrder_ForceComplete(string order);
+void W_RandomWeapons(entity e, float n);
+
+string GetAmmoPicture(.int ammotype);
+
+#ifdef CSQC
+.int GetAmmoFieldFromNum(int i);
+int GetAmmoStat(.int ammotype);
+#endif
+
+string W_Sound(string w_snd);
+string W_Model(string w_mdl);
+
+
+// other useful macros
+#define WEP_AMMO(wpn) (WEP_##wpn.ammo_field) // only used inside weapon files/with direct name, don't duplicate prefix
+#define WEP_NAME(wpn) ((get_weaponinfo(wpn)).message)
+
+#endif
#ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id */ ARC,
-/* function */ W_Arc,
-/* ammotype */ ammo_cells,
-/* impulse */ 3,
-/* flags */ WEP_FLAG_NORMAL,
-/* rating */ BOT_PICKUP_RATING_HIGH,
-/* color */ '1 1 1',
-/* modelname */ "arc",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairhlac 0.7",
-/* wepimg */ "weaponarc",
-/* refname */ "arc",
-/* wepname */ _("Arc")
-);
+CLASS(Arc, Weapon)
+/* ammotype */ ATTRIB(Arc, ammo_field, .int, ammo_cells)
+/* impulse */ ATTRIB(Arc, impulse, int, 3)
+/* flags */ ATTRIB(Arc, spawnflags, int, WEP_FLAG_NORMAL);
+/* rating */ ATTRIB(Arc, bot_pickupbasevalue, float, BOT_PICKUP_RATING_HIGH);
+/* color */ ATTRIB(Arc, wpcolor, vector, '1 1 1');
+/* modelname */ ATTRIB(Arc, mdl, string, "arc");
+#ifndef MENUQC
+/* model */ ATTRIB(Arc, m_model, Model, MDL_ARC_ITEM);
+#endif
+/* crosshair */ ATTRIB(Arc, w_crosshair, string, "gfx/crosshairhlac");
+/* crosshair */ ATTRIB(Arc, w_crosshair_size, float, 0.7);
+/* wepimg */ ATTRIB(Arc, model2, string, "weaponarc");
+/* refname */ ATTRIB(Arc, netname, string, "arc");
+/* wepname */ ATTRIB(Arc, message, string, _("Arc"));
+ENDCLASS(Arc)
+REGISTER_WEAPON(ARC, NEW(Arc));
#define ARC_SETTINGS(w_cvar,w_prop) ARC_SETTINGS_LIST(w_cvar, w_prop, ARC, arc)
#define ARC_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
#ifdef SVQC
ARC_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
.entity arc_beam;
-.float arc_BUTTON_ATCK_prev; // for better animation control
+.bool arc_BUTTON_ATCK_prev; // for better animation control
.float beam_prev;
.float beam_initialized;
.float beam_bursting;
#endif
#ifdef IMPLEMENTATION
#ifdef SVQC
-void spawnfunc_weapon_arc(void) { weapon_defaultspawnfunc(WEP_ARC.m_id); }
+spawnfunc(weapon_arc) { weapon_defaultspawnfunc(WEP_ARC.m_id); }
-float W_Arc_Beam_Send(entity to, int sf)
+bool W_Arc_Beam_Send(entity this, entity to, int sf)
{
WriteByte(MSG_ENTITY, ENT_CLIENT_ARC_BEAM);
}
void W_Arc_Beam_Think(void)
-{
+{SELFPARAM();
if(self != self.owner.arc_beam)
{
remove(self);
{
Send_Effect_("arc_overheat",
self.beam_start, self.beam_wantdir, 1 );
- sound(self, CH_WEAPON_A, W_Sound("arc_stop"), VOL_BASE, ATTN_NORM);
+ sound(self, CH_WEAPON_A, SND_ARC_STOP, VOL_BASE, ATTN_NORM);
}
}
if(self == self.owner.arc_beam) { self.owner.arc_beam = world; }
- entity oldself = self;
- self = self.owner;
- if(!WEP_ACTION(WEP_ARC.m_id, WR_CHECKAMMO1) && !WEP_ACTION(WEP_ARC.m_id, WR_CHECKAMMO2))
+ setself(self.owner);
+ Weapon w = WEP_ARC;
+ if(!w.wr_checkammo1(w) && !w.wr_checkammo2(w))
if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
{
// note: this doesn't force the switch
W_SwitchToOtherWeapon(self);
}
- self = oldself;
+ setself(this);
remove(self);
return;
}
}
void W_Arc_Beam(float burst)
-{
+{SELFPARAM();
// only play fire sound if 1 sec has passed since player let go the fire button
if(time - self.beam_prev > 1)
- sound(self, CH_WEAPON_A, W_Sound("arc_fire"), VOL_BASE, ATTN_NORM);
+ sound(self, CH_WEAPON_A, SND_ARC_FIRE, VOL_BASE, ATTN_NORM);
entity beam = self.arc_beam = spawn();
beam.classname = "W_Arc_Beam";
beam.beam_bursting = burst;
Net_LinkEntity(beam, false, 0, W_Arc_Beam_Send);
- entity oldself = self;
- self = beam;
- self.think();
- self = oldself;
+ WITH(entity, self, beam, beam.think());
}
void Arc_Smoke()
-{
+{SELFPARAM();
makevectors(self.v_angle);
W_SetupShot_Range(self,true,0,"",0,0,0);
if ( !self.arc_smoke_sound )
{
self.arc_smoke_sound = 1;
- sound(self, CH_SHOTS_SINGLE, W_Sound("arc_loop_overheat"), VOL_BASE, ATTN_NORM);
+ sound(self, CH_SHOTS_SINGLE, SND_ARC_LOOP_OVERHEAT, VOL_BASE, ATTN_NORM);
}
}
}
!( self.BUTTON_ATCK || self.BUTTON_ATCK2 ) ) || self.switchweapon != WEP_ARC.m_id )
{
self.arc_smoke_sound = 0;
- sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
}
}
-bool W_Arc(int req)
-{
- switch(req)
- {
- case WR_AIM:
+ METHOD(Arc, wr_aim, void(entity thiswep))
{
+ SELFPARAM();
if(WEP_CVAR(arc, beam_botaimspeed))
{
self.BUTTON_ATCK = bot_aim(
false
);
}
- return true;
}
- case WR_THINK:
+ METHOD(Arc, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
{
- Arc_Player_SetHeat(self);
+ Arc_Player_SetHeat(actor);
Arc_Smoke();
- if ( self.arc_overheat <= time )
- if(self.BUTTON_ATCK || self.BUTTON_ATCK2 || self.arc_beam.beam_bursting )
+ if (time >= actor.arc_overheat)
+ if (fire1 || fire2 || actor.arc_beam.beam_bursting)
{
- if(self.arc_BUTTON_ATCK_prev)
+ if(actor.arc_BUTTON_ATCK_prev)
{
#if 0
- if(self.animstate_startframe == self.anim_shoot.x && self.animstate_numframes == self.anim_shoot.y)
- weapon_thinkf(WFRAME_DONTCHANGE, autocvar_g_balance_arc_primary_animtime, w_ready);
+ if(actor.animstate_startframe == actor.anim_shoot.x && actor.animstate_numframes == actor.anim_shoot.y)
+ weapon_thinkf(actor, WFRAME_DONTCHANGE, autocvar_g_balance_arc_primary_animtime, w_ready);
else
#endif
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready);
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready);
}
- if((!self.arc_beam) || wasfreed(self.arc_beam))
+ if((!actor.arc_beam) || wasfreed(actor.arc_beam))
{
- if(weapon_prepareattack(!!self.BUTTON_ATCK2, 0))
+ if(weapon_prepareattack(thiswep, actor, fire2, 0))
{
- W_Arc_Beam(!!self.BUTTON_ATCK2);
+ W_Arc_Beam(fire2);
- if(!self.arc_BUTTON_ATCK_prev)
+ if(!actor.arc_BUTTON_ATCK_prev)
{
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready);
- self.arc_BUTTON_ATCK_prev = 1;
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready);
+ actor.arc_BUTTON_ATCK_prev = true;
}
}
}
- return true;
+ return;
}
- if(self.arc_BUTTON_ATCK_prev != 0)
+ if(actor.arc_BUTTON_ATCK_prev)
{
- sound(self, CH_WEAPON_A, W_Sound("arc_stop"), VOL_BASE, ATTN_NORM);
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready);
- ATTACK_FINISHED(self) = time + WEP_CVAR(arc, beam_refire) * W_WeaponRateFactor();
+ sound(actor, CH_WEAPON_A, SND_ARC_STOP, VOL_BASE, ATTN_NORM);
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready);
+ ATTACK_FINISHED(actor) = time + WEP_CVAR(arc, beam_refire) * W_WeaponRateFactor();
}
- self.arc_BUTTON_ATCK_prev = 0;
+ actor.arc_BUTTON_ATCK_prev = false;
#if 0
- if(self.BUTTON_ATCK2)
- if(weapon_prepareattack(1, autocvar_g_balance_arc_secondary_refire))
+ if(fire2)
+ if(weapon_prepareattack(thiswep, actor, true, autocvar_g_balance_arc_secondary_refire))
{
W_Arc_Attack2();
- self.arc_count = autocvar_g_balance_arc_secondary_count;
- weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_arc_secondary_animtime, w_arc_checkattack);
- self.arc_secondarytime = time + autocvar_g_balance_arc_secondary_refire2 * W_WeaponRateFactor();
+ actor.arc_count = autocvar_g_balance_arc_secondary_count;
+ weapon_thinkf(actor, WFRAME_FIRE2, autocvar_g_balance_arc_secondary_animtime, w_arc_checkattack);
+ actor.arc_secondarytime = time + autocvar_g_balance_arc_secondary_refire2 * W_WeaponRateFactor();
}
#endif
-
- return true;
}
- case WR_INIT:
+ METHOD(Arc, wr_init, void(entity thiswep))
{
- precache_model(W_Model("g_arc.md3"));
- precache_model(W_Model("v_arc.md3"));
- precache_model(W_Model("h_arc.iqm"));
- precache_sound(W_Sound("arc_fire"));
- precache_sound(W_Sound("arc_loop"));
- precache_sound(W_Sound("arc_stop"));
- precache_sound(W_Sound("arc_loop_overheat"));
if(!arc_shotorigin[0])
{
arc_shotorigin[0] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC.m_id), false, false, 1);
arc_shotorigin[3] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC.m_id), false, false, 4);
}
ARC_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
- return true;
}
- case WR_CHECKAMMO1:
+ METHOD(Arc, wr_checkammo1, bool(entity thiswep))
{
+ SELFPARAM();
return ((!WEP_CVAR(arc, beam_ammo)) || (self.WEP_AMMO(ARC) > 0));
}
- case WR_CHECKAMMO2:
+ METHOD(Arc, wr_checkammo2, bool(entity thiswep))
{
+ SELFPARAM();
return WEP_CVAR(arc, overheat_max) > 0 &&
((!WEP_CVAR(arc, burst_ammo)) || (self.WEP_AMMO(ARC) > 0));
}
- case WR_CONFIG:
+ METHOD(Arc, wr_config, void(entity thiswep))
{
ARC_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
- return true;
}
- case WR_KILLMESSAGE:
+ METHOD(Arc, wr_killmessage, int(entity thiswep))
{
return WEAPON_ARC_MURDER;
}
- case WR_DROP:
+ METHOD(Arc, wr_drop, void(entity thiswep))
{
weapon_dropevent_item.arc_overheat = self.arc_overheat;
weapon_dropevent_item.arc_cooldown = self.arc_cooldown;
self.arc_overheat = 0;
self.arc_cooldown = 0;
- return true;
}
- case WR_PICKUP:
+ METHOD(Arc, wr_pickup, void(entity thiswep))
{
if ( !client_hasweapon(self, WEP_ARC.m_id, false, false) &&
weapon_dropevent_item.arc_overheat > time )
self.arc_overheat = weapon_dropevent_item.arc_overheat;
self.arc_cooldown = weapon_dropevent_item.arc_cooldown;
}
- return true;
}
- }
- return false;
-}
#endif
#ifdef CSQC
void Draw_ArcBeam_callback(vector start, vector hit, vector end)
}
}
-void Draw_ArcBeam(void)
+void Draw_ArcBeam(entity this)
{
float dt = time - self.move_time;
self.move_time = time;
}
void Remove_ArcBeam(void)
-{
+{SELFPARAM();
remove(self.beam_muzzleentity);
- sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
}
void Ent_ReadArcBeam(float isnew)
-{
+{SELFPARAM();
int sf = ReadByte();
entity flash;
self.draw = Draw_ArcBeam;
self.entremove = Remove_ArcBeam;
self.move_time = time;
- loopsound(self, CH_SHOTS_SINGLE, W_Sound("arc_loop"), VOL_BASE, ATTEN_NORM);
+ loopsound(self, CH_SHOTS_SINGLE, SND(ARC_LOOP), VOL_BASE, ATTEN_NORM);
flash = spawn();
flash.owner = self;
self.beam_muzzlelight[3] = 1;
if(self.beam_muzzleeffect >= 0)
{
- setmodel(flash, "models/flash.md3");
+ setmodel(flash, MDL_ARC_MUZZLEFLASH);
flash.alpha = self.beam_alpha;
flash.colormod = self.beam_color;
flash.scale = 0.5;
self.beam_image = "particles/lgbeam";
if(self.beam_muzzleeffect >= 0)
{
- setmodel(flash, "models/flash.md3");
+ setmodel(flash, MDL_ARC_MUZZLEFLASH);
flash.alpha = self.beam_alpha;
flash.colormod = self.beam_color;
flash.scale = 0.5;
self.beam_image = "particles/lgbeam";
if(self.beam_muzzleeffect >= 0)
{
- setmodel(flash, "models/flash.md3");
+ setmodel(flash, MDL_ARC_MUZZLEFLASH);
flash.alpha = self.beam_alpha;
flash.colormod = self.beam_color;
flash.scale = 0.5;
self.beam_image = "particles/lgbeam";
if(self.beam_muzzleeffect >= 0)
{
- setmodel(flash, "models/flash.md3");
+ setmodel(flash, MDL_ARC_MUZZLEFLASH);
flash.alpha = self.beam_alpha;
flash.colormod = self.beam_color;
flash.scale = 0.5;
self.beam_image = "particles/lgbeam";
if(self.beam_muzzleeffect >= 0)
{
- setmodel(flash, "models/flash.md3");
+ setmodel(flash, MDL_ARC_MUZZLEFLASH);
flash.alpha = self.beam_alpha;
flash.colormod = self.beam_color;
flash.scale = 0.5;
self.beam_image = "particles/lgbeam";
if(self.beam_muzzleeffect >= 0)
{
- setmodel(flash, "models/flash.md3");
+ setmodel(flash, MDL_ARC_MUZZLEFLASH);
flash.alpha = self.beam_alpha;
flash.colormod = self.beam_color;
flash.scale = 0.5;
self.beam_image = "particles/lgbeam";
if(self.beam_muzzleeffect >= 0)
{
- setmodel(flash, "models/flash.md3");
+ setmodel(flash, MDL_ARC_MUZZLEFLASH);
flash.alpha = self.beam_alpha;
flash.colormod = self.beam_color;
flash.scale = 0.5;
self.beam_image = "particles/lgbeam";
if(self.beam_muzzleeffect >= 0)
{
- setmodel(flash, "models/flash.md3");
+ setmodel(flash, MDL_ARC_MUZZLEFLASH);
flash.alpha = self.beam_alpha;
flash.colormod = self.beam_color;
flash.scale = 0.5;
self.beam_image = "particles/lgbeam";
if(self.beam_muzzleeffect >= 0)
{
- setmodel(flash, "models/flash.md3");
+ setmodel(flash, MDL_ARC_MUZZLEFLASH);
flash.alpha = self.beam_alpha;
flash.colormod = self.beam_color;
flash.scale = 0.5;
}
}
-bool W_Arc(int req)
-{
- switch(req)
- {
- case WR_IMPACTEFFECT:
- {
- // todo
- return true;
- }
- case WR_INIT:
- {
- precache_sound(W_Sound("arc_loop"));
- return true;
- }
- case WR_ZOOMRETICLE:
- {
- // no weapon specific image for this weapon
- return false;
- }
- }
- return false;
-}
#endif
#endif
#ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id */ BLASTER,
-/* function */ W_Blaster,
-/* ammotype */ ammo_none,
-/* impulse */ 1,
-/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH,
-/* rating */ 0,
-/* color */ '1 0.5 0.5',
-/* modelname */ "laser",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairlaser 0.5",
-/* wepimg */ "weaponlaser",
-/* refname */ "blaster",
-/* wepname */ _("Blaster")
-);
+CLASS(Blaster, Weapon)
+/* ammotype */ //ATTRIB(Blaster, ammo_field, .int, ammo_none)
+/* impulse */ ATTRIB(Blaster, impulse, int, 1)
+/* flags */ ATTRIB(Blaster, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH);
+/* rating */ ATTRIB(Blaster, bot_pickupbasevalue, float, 0);
+/* color */ ATTRIB(Blaster, wpcolor, vector, '1 0.5 0.5');
+/* modelname */ ATTRIB(Blaster, mdl, string, "laser");
+#ifndef MENUQC
+/* model */ ATTRIB(Blaster, m_model, Model, MDL_BLASTER_ITEM);
+#endif
+/* crosshair */ ATTRIB(Blaster, w_crosshair, string, "gfx/crosshairlaser");
+/* crosshair */ ATTRIB(Blaster, w_crosshair_size, float, 0.5);
+/* wepimg */ ATTRIB(Blaster, model2, string, "weaponlaser");
+/* refname */ ATTRIB(Blaster, netname, string, "blaster");
+/* wepname */ ATTRIB(Blaster, message, string, _("Blaster"));
+ENDCLASS(Blaster)
+REGISTER_WEAPON(BLASTER, NEW(Blaster));
#define BLASTER_SETTINGS(w_cvar,w_prop) BLASTER_SETTINGS_LIST(w_cvar, w_prop, BLASTER, blaster)
#define BLASTER_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
#endif
#ifdef IMPLEMENTATION
#ifdef SVQC
-void spawnfunc_weapon_blaster(void) { weapon_defaultspawnfunc(WEP_BLASTER.m_id); }
-void spawnfunc_weapon_laser(void) { spawnfunc_weapon_blaster(); }
+spawnfunc(weapon_blaster) { weapon_defaultspawnfunc(WEP_BLASTER.m_id); }
+spawnfunc(weapon_laser) { spawnfunc_weapon_blaster(this); }
void W_Blaster_Touch(void)
-{
+{SELFPARAM();
PROJECTILE_TOUCH;
self.event_damage = func_null;
}
void W_Blaster_Think(void)
-{
+{SELFPARAM();
self.movetype = MOVETYPE_FLY;
self.think = SUB_Remove;
self.nextthink = time + self.blaster_lifetime;
}
void W_Blaster_Attack(
+ entity actor,
float atk_deathtype,
float atk_shotangle,
float atk_damage,
float atk_spread,
float atk_delay,
float atk_lifetime)
-{
+{SELFPARAM();
vector s_forward = v_forward * cos(atk_shotangle * DEG2RAD) + v_up * sin(atk_shotangle * DEG2RAD);
- W_SetupShot_Dir(self, s_forward, false, 3, W_Sound("lasergun_fire"), CH_WEAPON_B, atk_damage);
+ W_SetupShot_Dir(actor, s_forward, false, 3, SND(LASERGUN_FIRE), CH_WEAPON_B, atk_damage);
Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
entity missile = spawn();
- missile.owner = missile.realowner = self;
+ missile.owner = missile.realowner = actor;
missile.classname = "blasterbolt";
missile.bot_dodge = true;
missile.bot_dodgerating = atk_damage;
missile.think = W_Blaster_Think;
missile.nextthink = time + atk_delay;
- MUTATOR_CALLHOOK(EditProjectile, self, missile);
+ MUTATOR_CALLHOOK(EditProjectile, actor, missile);
- if(time >= missile.nextthink)
+ if (time >= missile.nextthink)
{
- entity oldself;
- oldself = self;
- self = missile;
- self.think();
- self = oldself;
+ WITH(entity, self, missile, missile.think());
}
}
-bool W_Blaster(int request)
-{
- switch(request)
- {
- case WR_AIM:
+
+ METHOD(Blaster, wr_aim, void(entity thiswep))
{
if(WEP_CVAR(blaster, secondary))
{
}
else
{ self.BUTTON_ATCK = bot_aim(WEP_CVAR_PRI(blaster, speed), 0, WEP_CVAR_PRI(blaster, lifetime), false); }
-
- return true;
}
- case WR_THINK:
+ METHOD(Blaster, wr_think, void(Blaster thiswep, entity actor, bool fire1, bool fire2))
{
- if(self.BUTTON_ATCK)
+ if(fire1)
{
- if(weapon_prepareattack(0, WEP_CVAR_PRI(blaster, refire)))
+ if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(blaster, refire)))
{
W_Blaster_Attack(
+ actor,
WEP_BLASTER.m_id,
WEP_CVAR_PRI(blaster, shotangle),
WEP_CVAR_PRI(blaster, damage),
WEP_CVAR_PRI(blaster, delay),
WEP_CVAR_PRI(blaster, lifetime)
);
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(blaster, animtime), w_ready);
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(blaster, animtime), w_ready);
}
}
- else if(self.BUTTON_ATCK2)
+ else if(fire2)
{
switch(WEP_CVAR(blaster, secondary))
{
case 0: // switch to last used weapon
{
- if(self.switchweapon == WEP_BLASTER.m_id) // don't do this if already switching
+ if(actor.switchweapon == WEP_BLASTER.m_id) // don't do this if already switching
W_LastWeapon();
break;
}
case 1: // normal projectile secondary
{
- if(weapon_prepareattack(1, WEP_CVAR_SEC(blaster, refire)))
+ if(weapon_prepareattack(thiswep, actor, true, WEP_CVAR_SEC(blaster, refire)))
{
W_Blaster_Attack(
+ actor,
WEP_BLASTER.m_id | HITTYPE_SECONDARY,
WEP_CVAR_SEC(blaster, shotangle),
WEP_CVAR_SEC(blaster, damage),
WEP_CVAR_SEC(blaster, delay),
WEP_CVAR_SEC(blaster, lifetime)
);
- weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(blaster, animtime), w_ready);
+ weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR_SEC(blaster, animtime), w_ready);
}
break;
}
}
}
- return true;
}
- case WR_INIT:
+ METHOD(Blaster, wr_init, void(entity thiswep))
{
- precache_model(W_Model("g_laser.md3"));
- precache_model(W_Model("v_laser.md3"));
- precache_model(W_Model("h_laser.iqm"));
- precache_sound(W_Sound("lasergun_fire"));
BLASTER_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
- return true;
}
- case WR_SETUP:
+ METHOD(Blaster, wr_setup, void(entity thiswep))
{
self.ammo_field = ammo_none;
- return true;
}
- case WR_CHECKAMMO1:
- case WR_CHECKAMMO2:
+ METHOD(Blaster, wr_checkammo1, bool(entity thiswep))
{
- return true; // laser has infinite ammo
+ return true; // infinite ammo
}
- case WR_CONFIG:
+ METHOD(Blaster, wr_checkammo2, bool(entity thiswep))
+ {
+ return true; // blaster has infinite ammo
+ }
+
+ METHOD(Blaster, wr_config, void(entity thiswep))
{
BLASTER_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
- return true;
}
- case WR_SUICIDEMESSAGE:
+ METHOD(Blaster, wr_suicidemessage, int(entity thiswep))
{
return WEAPON_BLASTER_SUICIDE;
}
- case WR_KILLMESSAGE:
+ METHOD(Blaster, wr_killmessage, int(entity thiswep))
{
return WEAPON_BLASTER_MURDER;
}
- }
- return false;
-}
+
#endif
#ifdef CSQC
-bool W_Blaster(int request)
-{
- switch(request)
- {
- case WR_IMPACTEFFECT:
+
+ METHOD(Blaster, wr_impacteffect, void(entity thiswep))
{
vector org2;
org2 = w_org + w_backoff * 6;
pointparticles(particleeffectnum(EFFECT_BLASTER_IMPACT), org2, w_backoff * 1000, 1);
- if(!w_issilent) { sound(self, CH_SHOTS, W_Sound("laserimpact"), VOL_BASE, ATTN_NORM); }
- return true;
+ if(!w_issilent) { sound(self, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTN_NORM); }
}
- case WR_INIT:
- {
- precache_sound(W_Sound("laserimpact"));
- return true;
- }
- case WR_ZOOMRETICLE:
- {
- // no weapon specific image for this weapon
- return false;
- }
- }
- return false;
-}
#endif
#endif
#ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id */ CRYLINK,
-/* function */ W_Crylink,
-/* ammotype */ ammo_cells,
-/* impulse */ 6,
-/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH,
-/* rating */ BOT_PICKUP_RATING_MID,
-/* color */ '1 0.5 1',
-/* modelname */ "crylink",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshaircrylink 0.5",
-/* wepimg */ "weaponcrylink",
-/* refname */ "crylink",
-/* wepname */ _("Crylink")
-);
+CLASS(Crylink, Weapon)
+/* ammotype */ ATTRIB(Crylink, ammo_field, .int, ammo_cells)
+/* impulse */ ATTRIB(Crylink, impulse, int, 6)
+/* flags */ ATTRIB(Crylink, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH);
+/* rating */ ATTRIB(Crylink, bot_pickupbasevalue, float, BOT_PICKUP_RATING_MID);
+/* color */ ATTRIB(Crylink, wpcolor, vector, '1 0.5 1');
+/* modelname */ ATTRIB(Crylink, mdl, string, "crylink");
+#ifndef MENUQC
+/* model */ ATTRIB(Crylink, m_model, Model, MDL_CRYLINK_ITEM);
+#endif
+/* crosshair */ ATTRIB(Crylink, w_crosshair, string, "gfx/crosshaircrylink");
+/* crosshair */ ATTRIB(Crylink, w_crosshair_size, float, 0.5);
+/* wepimg */ ATTRIB(Crylink, model2, string, "weaponcrylink");
+/* refname */ ATTRIB(Crylink, netname, string, "crylink");
+/* wepname */ ATTRIB(Crylink, message, string, _("Crylink"));
+ENDCLASS(Crylink)
+REGISTER_WEAPON(CRYLINK, NEW(Crylink));
#define CRYLINK_SETTINGS(w_cvar,w_prop) CRYLINK_SETTINGS_LIST(w_cvar, w_prop, CRYLINK, crylink)
#define CRYLINK_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
#endif
#ifdef IMPLEMENTATION
#ifdef SVQC
-void spawnfunc_weapon_crylink(void) { weapon_defaultspawnfunc(WEP_CRYLINK.m_id); }
+spawnfunc(weapon_crylink) { weapon_defaultspawnfunc(WEP_CRYLINK.m_id); }
void W_Crylink_CheckLinks(entity e)
{
}
void W_Crylink_Reset(void)
-{
+{SELFPARAM();
W_Crylink_Dequeue(self);
remove(self);
}
}
void W_Crylink_LinkJoinEffect_Think(void)
-{
+{SELFPARAM();
// is there at least 2 projectiles very close?
entity e, p;
float n;
// NO bounce protection, as bounces are limited!
void W_Crylink_Touch(void)
-{
+{SELFPARAM();
float finalhit;
float f;
float isprimary = !(self.projectiledeathtype & HITTYPE_SECONDARY);
}
void W_Crylink_Fadethink(void)
-{
+{SELFPARAM();
W_Crylink_Dequeue(self);
remove(self);
}
-void W_Crylink_Attack(void)
-{
+void W_Crylink_Attack(Weapon thiswep)
+{SELFPARAM();
float counter, shots;
entity proj, prevproj, firstproj;
vector s;
vector forward, right, up;
float maxdmg;
- W_DecreaseAmmo(WEP_CVAR_PRI(crylink, ammo));
+ W_DecreaseAmmo(thiswep, self, WEP_CVAR_PRI(crylink, ammo));
maxdmg = WEP_CVAR_PRI(crylink, damage) * WEP_CVAR_PRI(crylink, shots);
maxdmg *= 1 + WEP_CVAR_PRI(crylink, bouncedamagefactor) * WEP_CVAR_PRI(crylink, bounces);
if(WEP_CVAR_PRI(crylink, joinexplode))
maxdmg += WEP_CVAR_PRI(crylink, joinexplode_damage);
- W_SetupShot(self, false, 2, W_Sound("crylink_fire"), CH_WEAPON_A, maxdmg);
+ W_SetupShot(self, false, 2, SND(CRYLINK_FIRE), CH_WEAPON_A, maxdmg);
forward = v_forward;
right = v_right;
up = v_up;
}
}
-void W_Crylink_Attack2(void)
-{
+void W_Crylink_Attack2(Weapon thiswep)
+{SELFPARAM();
float counter, shots;
entity proj, prevproj, firstproj;
vector s;
vector forward, right, up;
float maxdmg;
- W_DecreaseAmmo(WEP_CVAR_SEC(crylink, ammo));
+ W_DecreaseAmmo(thiswep, self, WEP_CVAR_SEC(crylink, ammo));
maxdmg = WEP_CVAR_SEC(crylink, damage) * WEP_CVAR_SEC(crylink, shots);
maxdmg *= 1 + WEP_CVAR_SEC(crylink, bouncedamagefactor) * WEP_CVAR_SEC(crylink, bounces);
if(WEP_CVAR_SEC(crylink, joinexplode))
maxdmg += WEP_CVAR_SEC(crylink, joinexplode_damage);
- W_SetupShot(self, false, 2, W_Sound("crylink_fire2"), CH_WEAPON_A, maxdmg);
+ W_SetupShot(self, false, 2, SND(CRYLINK_FIRE2), CH_WEAPON_A, maxdmg);
forward = v_forward;
right = v_right;
up = v_up;
}
}
-bool W_Crylink(int req)
-{
- float ammo_amount;
- switch(req)
- {
- case WR_AIM:
+ METHOD(Crylink, wr_aim, void(entity thiswep))
{
+ SELFPARAM();
if(random() < 0.10)
self.BUTTON_ATCK = bot_aim(WEP_CVAR_PRI(crylink, speed), 0, WEP_CVAR_PRI(crylink, middle_lifetime), false);
else
self.BUTTON_ATCK2 = bot_aim(WEP_CVAR_SEC(crylink, speed), 0, WEP_CVAR_SEC(crylink, middle_lifetime), false);
-
- return true;
}
- case WR_THINK:
+ METHOD(Crylink, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
{
- if(autocvar_g_balance_crylink_reload_ammo && self.clip_load < min(WEP_CVAR_PRI(crylink, ammo), WEP_CVAR_SEC(crylink, ammo))) // forced reload
- WEP_ACTION(self.weapon, WR_RELOAD);
+ if(autocvar_g_balance_crylink_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(crylink, ammo), WEP_CVAR_SEC(crylink, ammo))) { // forced reload
+ Weapon w = get_weaponinfo(actor.weapon);
+ w.wr_reload(w);
+ }
- if(self.BUTTON_ATCK)
+ if(fire1)
{
- if(self.crylink_waitrelease != 1)
- if(weapon_prepareattack(0, WEP_CVAR_PRI(crylink, refire)))
+ if(actor.crylink_waitrelease != 1)
+ if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(crylink, refire)))
{
- W_Crylink_Attack();
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(crylink, animtime), w_ready);
+ W_Crylink_Attack(thiswep);
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(crylink, animtime), w_ready);
}
}
- if(self.BUTTON_ATCK2 && autocvar_g_balance_crylink_secondary)
+ if(fire2 && autocvar_g_balance_crylink_secondary)
{
- if(self.crylink_waitrelease != 2)
- if(weapon_prepareattack(1, WEP_CVAR_SEC(crylink, refire)))
+ if(actor.crylink_waitrelease != 2)
+ if(weapon_prepareattack(thiswep, actor, true, WEP_CVAR_SEC(crylink, refire)))
{
- W_Crylink_Attack2();
- weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(crylink, animtime), w_ready);
+ W_Crylink_Attack2(thiswep);
+ weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR_SEC(crylink, animtime), w_ready);
}
}
- if((self.crylink_waitrelease == 1 && !self.BUTTON_ATCK) || (self.crylink_waitrelease == 2 && !self.BUTTON_ATCK2))
+ if((actor.crylink_waitrelease == 1 && !fire1) || (actor.crylink_waitrelease == 2 && !fire2))
{
- if(!self.crylink_lastgroup || time > self.crylink_lastgroup.teleport_time)
+ if(!actor.crylink_lastgroup || time > actor.crylink_lastgroup.teleport_time)
{
// fired and released now!
- if(self.crylink_lastgroup)
+ if(actor.crylink_lastgroup)
{
vector pos;
entity linkjoineffect;
- float isprimary = (self.crylink_waitrelease == 1);
+ float isprimary = (actor.crylink_waitrelease == 1);
- pos = W_Crylink_LinkJoin(self.crylink_lastgroup, WEP_CVAR_BOTH(crylink, isprimary, joinspread) * WEP_CVAR_BOTH(crylink, isprimary, speed));
+ pos = W_Crylink_LinkJoin(actor.crylink_lastgroup, WEP_CVAR_BOTH(crylink, isprimary, joinspread) * WEP_CVAR_BOTH(crylink, isprimary, speed));
linkjoineffect = spawn();
linkjoineffect.think = W_Crylink_LinkJoinEffect_Think;
linkjoineffect.classname = "linkjoineffect";
linkjoineffect.nextthink = time + w_crylink_linkjoin_time;
- linkjoineffect.owner = self;
+ linkjoineffect.owner = actor;
setorigin(linkjoineffect, pos);
}
- self.crylink_waitrelease = 0;
- if(!W_Crylink(WR_CHECKAMMO1) && !W_Crylink(WR_CHECKAMMO2))
- if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+ actor.crylink_waitrelease = 0;
+ if(!thiswep.wr_checkammo1(thiswep) && !thiswep.wr_checkammo2(thiswep))
+ if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
// ran out of ammo!
- self.cnt = WEP_CRYLINK.m_id;
- self.switchweapon = w_getbestweapon(self);
+ actor.cnt = WEP_CRYLINK.m_id;
+ actor.switchweapon = w_getbestweapon(actor);
}
}
}
-
- return true;
}
- case WR_INIT:
+ METHOD(Crylink, wr_init, void(entity thiswep))
{
- precache_model(W_Model("g_crylink.md3"));
- precache_model(W_Model("v_crylink.md3"));
- precache_model(W_Model("h_crylink.iqm"));
- precache_sound(W_Sound("crylink_fire"));
- precache_sound(W_Sound("crylink_fire2"));
- precache_sound(W_Sound("crylink_linkjoin"));
CRYLINK_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
- return true;
}
- case WR_CHECKAMMO1:
+ METHOD(Crylink, wr_checkammo1, bool(entity thiswep))
{
+ SELFPARAM();
// don't "run out of ammo" and switch weapons while waiting for release
if(self.crylink_lastgroup && self.crylink_waitrelease)
return true;
- ammo_amount = self.WEP_AMMO(CRYLINK) >= WEP_CVAR_PRI(crylink, ammo);
+ float ammo_amount = self.WEP_AMMO(CRYLINK) >= WEP_CVAR_PRI(crylink, ammo);
ammo_amount += self.(weapon_load[WEP_CRYLINK.m_id]) >= WEP_CVAR_PRI(crylink, ammo);
return ammo_amount;
}
- case WR_CHECKAMMO2:
+ METHOD(Crylink, wr_checkammo2, bool(entity thiswep))
{
+ SELFPARAM();
// don't "run out of ammo" and switch weapons while waiting for release
if(self.crylink_lastgroup && self.crylink_waitrelease)
return true;
- ammo_amount = self.WEP_AMMO(CRYLINK) >= WEP_CVAR_SEC(crylink, ammo);
+ float ammo_amount = self.WEP_AMMO(CRYLINK) >= WEP_CVAR_SEC(crylink, ammo);
ammo_amount += self.(weapon_load[WEP_CRYLINK.m_id]) >= WEP_CVAR_SEC(crylink, ammo);
return ammo_amount;
}
- case WR_CONFIG:
+ METHOD(Crylink, wr_config, void(entity thiswep))
{
CRYLINK_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
- return true;
}
- case WR_RELOAD:
+ METHOD(Crylink, wr_reload, void(entity thiswep))
{
- W_Reload(min(WEP_CVAR_PRI(crylink, ammo), WEP_CVAR_SEC(crylink, ammo)), W_Sound("reload"));
- return true;
+ W_Reload(self, min(WEP_CVAR_PRI(crylink, ammo), WEP_CVAR_SEC(crylink, ammo)), SND(RELOAD));
}
- case WR_SUICIDEMESSAGE:
+ METHOD(Crylink, wr_suicidemessage, int(entity thiswep))
{
return WEAPON_CRYLINK_SUICIDE;
}
- case WR_KILLMESSAGE:
+ METHOD(Crylink, wr_killmessage, int(entity thiswep))
{
return WEAPON_CRYLINK_MURDER;
}
- }
- return false;
-}
#endif
#ifdef CSQC
-bool W_Crylink(int req)
-{
- switch(req)
- {
- case WR_IMPACTEFFECT:
+ METHOD(Crylink, wr_impacteffect, void(entity thiswep))
{
+ SELFPARAM();
vector org2;
org2 = w_org + w_backoff * 2;
if(w_deathtype & HITTYPE_SECONDARY)
{
pointparticles(particleeffectnum(EFFECT_CRYLINK_IMPACT2), org2, '0 0 0', 1);
if(!w_issilent)
- sound(self, CH_SHOTS, W_Sound("crylink_impact2"), VOL_BASE, ATTN_NORM);
+ sound(self, CH_SHOTS, SND_CRYLINK_IMPACT2, VOL_BASE, ATTN_NORM);
}
else
{
pointparticles(particleeffectnum(EFFECT_CRYLINK_IMPACT), org2, '0 0 0', 1);
if(!w_issilent)
- sound(self, CH_SHOTS, W_Sound("crylink_impact"), VOL_BASE, ATTN_NORM);
+ sound(self, CH_SHOTS, SND_CRYLINK_IMPACT, VOL_BASE, ATTN_NORM);
}
-
- return true;
}
- case WR_INIT:
- {
- precache_sound(W_Sound("crylink_impact2"));
- precache_sound(W_Sound("crylink_impact"));
- return true;
- }
- case WR_ZOOMRETICLE:
- {
- // no weapon specific image for this weapon
- return false;
- }
- }
- return false;
-}
#endif
#endif
#ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id */ DEVASTATOR,
-/* function */ W_Devastator,
-/* ammotype */ ammo_rockets,
-/* impulse */ 9,
-/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH,
-/* rating */ BOT_PICKUP_RATING_HIGH,
-/* color */ '1 1 0',
-/* modelname */ "rl",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairrocketlauncher 0.7",
-/* wepimg */ "weaponrocketlauncher",
-/* refname */ "devastator",
-/* wepname */ _("Devastator")
-);
+CLASS(Devastator, Weapon)
+/* ammotype */ ATTRIB(Devastator, ammo_field, .int, ammo_rockets)
+/* impulse */ ATTRIB(Devastator, impulse, int, 9)
+/* flags */ ATTRIB(Devastator, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH);
+/* rating */ ATTRIB(Devastator, bot_pickupbasevalue, float, BOT_PICKUP_RATING_HIGH);
+/* color */ ATTRIB(Devastator, wpcolor, vector, '1 1 0');
+/* modelname */ ATTRIB(Devastator, mdl, string, "rl");
+#ifndef MENUQC
+/* model */ ATTRIB(Devastator, m_model, Model, MDL_DEVASTATOR_ITEM);
+#endif
+/* crosshair */ ATTRIB(Devastator, w_crosshair, string, "gfx/crosshairrocketlauncher");
+/* crosshair */ ATTRIB(Devastator, w_crosshair_size, float, 0.7);
+/* wepimg */ ATTRIB(Devastator, model2, string, "weaponrocketlauncher");
+/* refname */ ATTRIB(Devastator, netname, string, "devastator");
+/* wepname */ ATTRIB(Devastator, message, string, _("Devastator"));
+ENDCLASS(Devastator)
+REGISTER_WEAPON(DEVASTATOR, NEW(Devastator));
#define DEVASTATOR_SETTINGS(w_cvar,w_prop) DEVASTATOR_SETTINGS_LIST(w_cvar, w_prop, DEVASTATOR, devastator)
#define DEVASTATOR_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
#endif
#ifdef IMPLEMENTATION
#ifdef SVQC
-void spawnfunc_weapon_devastator(void) { weapon_defaultspawnfunc(WEP_DEVASTATOR.m_id); }
-void spawnfunc_weapon_rocketlauncher(void) { spawnfunc_weapon_devastator(); }
+spawnfunc(weapon_devastator) { weapon_defaultspawnfunc(WEP_DEVASTATOR.m_id); }
+spawnfunc(weapon_rocketlauncher) { spawnfunc_weapon_devastator(this); }
void W_Devastator_Unregister(void)
-{
+{SELFPARAM();
if(self.realowner && self.realowner.lastrocket == self)
{
self.realowner.lastrocket = world;
}
void W_Devastator_Explode(void)
-{
+{SELFPARAM();
W_Devastator_Unregister();
if(other.takedamage == DAMAGE_AIM)
}
void W_Devastator_DoRemoteExplode(void)
-{
+{SELFPARAM();
W_Devastator_Unregister();
self.event_damage = func_null;
}
void W_Devastator_RemoteExplode(void)
-{
+{SELFPARAM();
if(self.realowner.deadflag == DEAD_NO)
if(self.realowner.lastrocket)
{
// normalize(0)
void W_Devastator_Think(void)
-{
+{SELFPARAM();
vector desireddir, olddir, newdir, desiredorigin, goal;
float velspeed, f;
self.nextthink = time;
{
Send_Effect(EFFECT_ROCKET_GUIDE, self.origin, self.velocity, 1);
// TODO add a better sound here
- sound(self.realowner, CH_WEAPON_B, W_Sound("rocket_mode"), VOL_BASE, ATTN_NORM);
+ sound(self.realowner, CH_WEAPON_B, SND_ROCKET_MODE, VOL_BASE, ATTN_NORM);
self.count = 1;
}
}
}
void W_Devastator_Touch(void)
-{
+{SELFPARAM();
if(WarpZone_Projectile_Touch())
{
if(wasfreed(self))
}
void W_Devastator_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
if(self.health <= 0)
return;
W_PrepareExplosionByDamage(attacker, W_Devastator_Explode);
}
-void W_Devastator_Attack(void)
-{
+void W_Devastator_Attack(Weapon thiswep)
+{SELFPARAM();
entity missile;
entity flash;
- W_DecreaseAmmo(WEP_CVAR(devastator, ammo));
+ W_DecreaseAmmo(thiswep, self, WEP_CVAR(devastator, ammo));
- W_SetupShot_ProjectileSize(self, '-3 -3 -3', '3 3 3', false, 5, W_Sound("rocket_fire"), CH_WEAPON_A, WEP_CVAR(devastator, damage));
+ W_SetupShot_ProjectileSize(self, '-3 -3 -3', '3 3 3', false, 5, SND(ROCKET_FIRE), CH_WEAPON_A, WEP_CVAR(devastator, damage));
Send_Effect(EFFECT_ROCKET_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
missile = WarpZone_RefSys_SpawnSameRefSys(self);
// muzzle flash for 1st person view
flash = spawn();
- setmodel(flash, "models/flash.md3"); // precision set below
+ setmodel(flash, MDL_DEVASTATOR_MUZZLEFLASH); // precision set below
SUB_SetFade(flash, time, 0.1);
flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
- W_AttachToShotorg(flash, '5 0 0');
+ W_AttachToShotorg(self, flash, '5 0 0');
// common properties
MUTATOR_CALLHOOK(EditProjectile, self, missile);
}
-bool W_Devastator(int req)
-{
- entity rock;
- float rockfound;
- float ammo_amount;
- switch(req)
- {
#if 0
- case WR_AIM:
+ METHOD(Devastator, wr_aim, void(entity thiswep))
{
// aim and decide to fire if appropriate
self.BUTTON_ATCK = bot_aim(WEP_CVAR(devastator, speed), 0, WEP_CVAR(devastator, lifetime), false);
if(self.BUTTON_ATCK2) self.BUTTON_ATCK = false;
}
-
- return true;
}
#else
- case WR_AIM:
+ METHOD(Devastator, wr_aim, void(entity thiswep))
{
// aim and decide to fire if appropriate
self.BUTTON_ATCK = bot_aim(WEP_CVAR(devastator, speed), 0, WEP_CVAR(devastator, lifetime), false);
// dprint(ftos(desirabledamage),"\n");
if(self.BUTTON_ATCK2 == true) self.BUTTON_ATCK = false;
}
-
- return true;
}
#endif
- case WR_THINK:
+ METHOD(Devastator, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
{
- if(WEP_CVAR(devastator, reload_ammo) && self.clip_load < WEP_CVAR(devastator, ammo)) // forced reload
- WEP_ACTION(self.weapon, WR_RELOAD);
- else
- {
- if(self.BUTTON_ATCK)
+ if(WEP_CVAR(devastator, reload_ammo) && actor.clip_load < WEP_CVAR(devastator, ammo)) { // forced reload
+ Weapon w = get_weaponinfo(actor.weapon);
+ w.wr_reload(w);
+ } else {
+ if(fire1)
{
- if(self.rl_release || WEP_CVAR(devastator, guidestop))
- if(weapon_prepareattack(0, WEP_CVAR(devastator, refire)))
+ if(actor.rl_release || WEP_CVAR(devastator, guidestop))
+ if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR(devastator, refire)))
{
- W_Devastator_Attack();
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(devastator, animtime), w_ready);
- self.rl_release = 0;
+ W_Devastator_Attack(thiswep);
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR(devastator, animtime), w_ready);
+ actor.rl_release = 0;
}
}
else
- self.rl_release = 1;
+ actor.rl_release = 1;
- if(self.BUTTON_ATCK2)
- if(self.switchweapon == WEP_DEVASTATOR.m_id)
+ if(fire2)
+ if(actor.switchweapon == WEP_DEVASTATOR.m_id)
{
- rockfound = 0;
- for(rock = world; (rock = find(rock, classname, "rocket")); ) if(rock.realowner == self)
+ entity rock;
+ bool rockfound = false;
+ for(rock = world; (rock = find(rock, classname, "rocket")); ) if(rock.realowner == actor)
{
if(!rock.rl_detonate_later)
{
rock.rl_detonate_later = true;
- rockfound = 1;
+ rockfound = true;
}
}
if(rockfound)
- sound(self, CH_WEAPON_B, W_Sound("rocket_det"), VOL_BASE, ATTN_NORM);
+ sound(actor, CH_WEAPON_B, SND_ROCKET_DET, VOL_BASE, ATTN_NORM);
}
}
-
- return true;
}
- case WR_INIT:
+ METHOD(Devastator, wr_init, void(entity thiswep))
{
- //if(autocvar_sv_precacheweapons)
- //{
- precache_model("models/flash.md3");
- precache_model(W_Model("g_rl.md3"));
- precache_model(W_Model("v_rl.md3"));
- precache_model(W_Model("h_rl.iqm"));
- precache_sound(W_Sound("rocket_det"));
- precache_sound(W_Sound("rocket_fire"));
- precache_sound(W_Sound("rocket_mode"));
- //}
DEVASTATOR_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
- return true;
}
- case WR_SETUP:
+ METHOD(Devastator, wr_setup, void(entity thiswep))
{
self.rl_release = 1;
- return true;
}
- case WR_CHECKAMMO1:
+ METHOD(Devastator, wr_checkammo1, bool(entity thiswep))
{
#if 0
// don't switch while guiding a missile
return ammo_amount;
}
#else
- ammo_amount = self.WEP_AMMO(DEVASTATOR) >= WEP_CVAR(devastator, ammo);
+ float ammo_amount = self.WEP_AMMO(DEVASTATOR) >= WEP_CVAR(devastator, ammo);
ammo_amount += self.(weapon_load[WEP_DEVASTATOR.m_id]) >= WEP_CVAR(devastator, ammo);
return ammo_amount;
#endif
}
- case WR_CHECKAMMO2:
+ METHOD(Devastator, wr_checkammo2, bool(entity thiswep))
{
return false;
}
- case WR_CONFIG:
+ METHOD(Devastator, wr_config, void(entity thiswep))
{
DEVASTATOR_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
- return true;
}
- case WR_RESETPLAYER:
+ METHOD(Devastator, wr_resetplayer, void(entity thiswep))
{
self.rl_release = 0;
- return true;
}
- case WR_RELOAD:
+ METHOD(Devastator, wr_reload, void(entity thiswep))
{
- W_Reload(WEP_CVAR(devastator, ammo), W_Sound("reload"));
- return true;
+ W_Reload(self, WEP_CVAR(devastator, ammo), SND(RELOAD));
}
- case WR_SUICIDEMESSAGE:
+ METHOD(Devastator, wr_suicidemessage, int(entity thiswep))
{
return WEAPON_DEVASTATOR_SUICIDE;
}
- case WR_KILLMESSAGE:
+ METHOD(Devastator, wr_killmessage, int(entity thiswep))
{
if((w_deathtype & HITTYPE_BOUNCE) || (w_deathtype & HITTYPE_SPLASH))
return WEAPON_DEVASTATOR_MURDER_SPLASH;
else
return WEAPON_DEVASTATOR_MURDER_DIRECT;
}
- }
- return false;
-}
+
#endif
#ifdef CSQC
-bool W_Devastator(int req)
-{
- switch(req)
- {
- case WR_IMPACTEFFECT:
+
+ METHOD(Devastator, wr_impacteffect, void(entity thiswep))
{
vector org2;
org2 = w_org + w_backoff * 12;
pointparticles(particleeffectnum(EFFECT_ROCKET_EXPLODE), org2, '0 0 0', 1);
if(!w_issilent)
- sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTN_NORM);
-
- return true;
+ sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTN_NORM);
}
- case WR_INIT:
- {
- precache_sound(W_Sound("rocket_impact"));
- return true;
- }
- case WR_ZOOMRETICLE:
- {
- // no weapon specific image for this weapon
- return false;
- }
- }
- return false;
-}
+
#endif
#endif
#ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id */ ELECTRO,
-/* function */ W_Electro,
-/* ammotype */ ammo_cells,
-/* impulse */ 5,
-/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH,
-/* rating */ BOT_PICKUP_RATING_MID,
-/* color */ '0 0.5 1',
-/* modelname */ "electro",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairelectro 0.6",
-/* wepimg */ "weaponelectro",
-/* refname */ "electro",
-/* wepname */ _("Electro")
-);
+CLASS(Electro, Weapon)
+/* ammotype */ ATTRIB(Electro, ammo_field, .int, ammo_cells)
+/* impulse */ ATTRIB(Electro, impulse, int, 5)
+/* flags */ ATTRIB(Electro, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH);
+/* rating */ ATTRIB(Electro, bot_pickupbasevalue, float, BOT_PICKUP_RATING_MID);
+/* color */ ATTRIB(Electro, wpcolor, vector, '0 0.5 1');
+/* modelname */ ATTRIB(Electro, mdl, string, "electro");
+#ifndef MENUQC
+/* model */ ATTRIB(Electro, m_model, Model, MDL_ELECTRO_ITEM);
+#endif
+/* crosshair */ ATTRIB(Electro, w_crosshair, string, "gfx/crosshairelectro");
+/* crosshair */ ATTRIB(Electro, w_crosshair_size, float, 0.6);
+/* wepimg */ ATTRIB(Electro, model2, string, "weaponelectro");
+/* refname */ ATTRIB(Electro, netname, string, "electro");
+/* wepname */ ATTRIB(Electro, message, string, _("Electro"));
+ENDCLASS(Electro)
+REGISTER_WEAPON(ELECTRO, NEW(Electro));
#define ELECTRO_SETTINGS(w_cvar,w_prop) ELECTRO_SETTINGS_LIST(w_cvar, w_prop, ELECTRO, electro)
#define ELECTRO_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
#endif
#ifdef IMPLEMENTATION
#ifdef SVQC
-void spawnfunc_weapon_electro(void) { weapon_defaultspawnfunc(WEP_ELECTRO.m_id); }
+spawnfunc(weapon_electro) { weapon_defaultspawnfunc(WEP_ELECTRO.m_id); }
void W_Electro_TriggerCombo(vector org, float rad, entity own)
{
}
void W_Electro_ExplodeCombo(void)
-{
+{SELFPARAM();
W_Electro_TriggerCombo(self.origin, WEP_CVAR(electro, combo_comboradius), self.realowner);
self.event_damage = func_null;
}
void W_Electro_Explode(void)
-{
+{SELFPARAM();
if(other.takedamage == DAMAGE_AIM)
if(IS_PLAYER(other))
if(DIFF_TEAM(self.realowner, other))
}
void W_Electro_Bolt_Think(void)
-{
+{SELFPARAM();
if(time >= self.ltime)
{
self.use();
else { self.nextthink = self.ltime; }
}
-void W_Electro_Attack_Bolt(void)
-{
+void W_Electro_Attack_Bolt(Weapon thiswep)
+{SELFPARAM();
entity proj;
- W_DecreaseAmmo(WEP_CVAR_PRI(electro, ammo));
+ W_DecreaseAmmo(thiswep, self, WEP_CVAR_PRI(electro, ammo));
W_SetupShot_ProjectileSize(
self,
'0 0 -3',
false,
2,
- W_Sound("electro_fire"),
+ SND(ELECTRO_FIRE),
CH_WEAPON_A,
WEP_CVAR_PRI(electro, damage)
);
}
void W_Electro_Orb_Touch(void)
-{
+{SELFPARAM();
PROJECTILE_TOUCH;
if(other.takedamage == DAMAGE_AIM)
{ if(WEP_CVAR_SEC(electro, touchexplode)) { W_Electro_Explode(); } }
else
{
//UpdateCSQCProjectile(self);
- spamsound(self, CH_SHOTS, W_Sound("electro_bounce"), VOL_BASE, ATTEN_NORM);
+ spamsound(self, CH_SHOTS, SND(ELECTRO_BOUNCE), VOL_BASE, ATTEN_NORM);
self.projectiledeathtype |= HITTYPE_BOUNCE;
}
}
void W_Electro_Orb_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
if(self.health <= 0)
return;
}
}
-void W_Electro_Attack_Orb(void)
-{
- W_DecreaseAmmo(WEP_CVAR_SEC(electro, ammo));
+void W_Electro_Attack_Orb(Weapon thiswep)
+{SELFPARAM();
+ W_DecreaseAmmo(thiswep, self, WEP_CVAR_SEC(electro, ammo));
W_SetupShot_ProjectileSize(
self,
'0 0 -4',
false,
2,
- W_Sound("electro_fire2"),
+ SND(ELECTRO_FIRE2),
CH_WEAPON_A,
WEP_CVAR_SEC(electro, damage)
);
entity p2;
p2 = spawn();
copyentity(proj, p2);
- setmodel(p2, "models/ebomb.mdl");
+ setmodel(p2, MDL_PROJECTILE_ELECTRO);
setsize(p2, proj.mins, proj.maxs);
#endif
MUTATOR_CALLHOOK(EditProjectile, self, proj);
}
-void W_Electro_CheckAttack(void)
-{
+void W_Electro_CheckAttack(Weapon thiswep, entity actor, bool fire1, bool fire2)
+{SELFPARAM();
if(self.electro_count > 1)
if(self.BUTTON_ATCK2)
- if(weapon_prepareattack(1, -1))
+ if(weapon_prepareattack(thiswep, actor, true, -1))
{
- W_Electro_Attack_Orb();
+ W_Electro_Attack_Orb(WEP_ELECTRO);
self.electro_count -= 1;
- weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(electro, animtime), W_Electro_CheckAttack);
+ weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR_SEC(electro, animtime), W_Electro_CheckAttack);
return;
}
// WEAPONTODO: when the player releases the button, cut down the length of refire2?
- w_ready();
+ w_ready(thiswep, actor, fire1, fire2);
}
.float bot_secondary_electromooth;
-bool W_Electro(int req)
-{
- float ammo_amount;
- switch(req)
- {
- case WR_AIM:
+
+ METHOD(Electro, wr_aim, void(entity thiswep))
{
self.BUTTON_ATCK = self.BUTTON_ATCK2 = false;
if(vlen(self.origin-self.enemy.origin) > 1000) { self.bot_secondary_electromooth = 0; }
if(random() < 0.03) self.bot_secondary_electromooth = 0;
}
}
-
- return true;
}
- case WR_THINK:
+ METHOD(Electro, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
{
if(autocvar_g_balance_electro_reload_ammo) // forced reload // WEAPONTODO
{
- ammo_amount = 0;
- if(self.clip_load >= WEP_CVAR_PRI(electro, ammo))
+ float ammo_amount = 0;
+ if(actor.clip_load >= WEP_CVAR_PRI(electro, ammo))
ammo_amount = 1;
- if(self.clip_load >= WEP_CVAR_SEC(electro, ammo))
+ if(actor.clip_load >= WEP_CVAR_SEC(electro, ammo))
ammo_amount += 1;
if(!ammo_amount)
{
- WEP_ACTION(self.weapon, WR_RELOAD);
- return false;
+ Weapon w = get_weaponinfo(actor.weapon);
+ w.wr_reload(w);
+ return;
}
-
- return true;
}
- if(self.BUTTON_ATCK)
+ if(fire1)
{
- if(weapon_prepareattack(0, WEP_CVAR_PRI(electro, refire)))
+ if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(electro, refire)))
{
- W_Electro_Attack_Bolt();
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready);
+ W_Electro_Attack_Bolt(thiswep);
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready);
}
}
- else if(self.BUTTON_ATCK2)
+ else if(fire2)
{
- if(time >= self.electro_secondarytime)
- if(weapon_prepareattack(1, WEP_CVAR_SEC(electro, refire)))
+ if(time >= actor.electro_secondarytime)
+ if(weapon_prepareattack(thiswep, actor, true, WEP_CVAR_SEC(electro, refire)))
{
- W_Electro_Attack_Orb();
- self.electro_count = WEP_CVAR_SEC(electro, count);
- weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(electro, animtime), W_Electro_CheckAttack);
- self.electro_secondarytime = time + WEP_CVAR_SEC(electro, refire2) * W_WeaponRateFactor();
+ W_Electro_Attack_Orb(thiswep);
+ actor.electro_count = WEP_CVAR_SEC(electro, count);
+ weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR_SEC(electro, animtime), W_Electro_CheckAttack);
+ actor.electro_secondarytime = time + WEP_CVAR_SEC(electro, refire2) * W_WeaponRateFactor();
}
}
-
- return true;
}
- case WR_INIT:
+ METHOD(Electro, wr_init, void(entity thiswep))
{
- precache_model(W_Model("g_electro.md3"));
- precache_model(W_Model("v_electro.md3"));
- precache_model(W_Model("h_electro.iqm"));
- precache_sound(W_Sound("electro_bounce"));
- precache_sound(W_Sound("electro_fire"));
- precache_sound(W_Sound("electro_fire2"));
- precache_sound(W_Sound("electro_impact"));
- precache_sound(W_Sound("electro_impact_combo"));
ELECTRO_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
- return true;
}
- case WR_CHECKAMMO1:
+ METHOD(Electro, wr_checkammo1, bool(entity thiswep))
{
- ammo_amount = self.WEP_AMMO(ELECTRO) >= WEP_CVAR_PRI(electro, ammo);
+ float ammo_amount = self.WEP_AMMO(ELECTRO) >= WEP_CVAR_PRI(electro, ammo);
ammo_amount += self.(weapon_load[WEP_ELECTRO.m_id]) >= WEP_CVAR_PRI(electro, ammo);
return ammo_amount;
}
- case WR_CHECKAMMO2:
+ METHOD(Electro, wr_checkammo2, bool(entity thiswep))
{
+ float ammo_amount;
if(WEP_CVAR(electro, combo_safeammocheck)) // true if you can fire at least one secondary blob AND one primary shot after it, otherwise false.
{
ammo_amount = self.WEP_AMMO(ELECTRO) >= WEP_CVAR_SEC(electro, ammo) + WEP_CVAR_PRI(electro, ammo);
}
return ammo_amount;
}
- case WR_CONFIG:
+ METHOD(Electro, wr_config, void(entity thiswep))
{
ELECTRO_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
- return true;
}
- case WR_RESETPLAYER:
+ METHOD(Electro, wr_resetplayer, void(entity thiswep))
{
self.electro_secondarytime = time;
- return true;
}
- case WR_RELOAD:
+ METHOD(Electro, wr_reload, void(entity thiswep))
{
- W_Reload(min(WEP_CVAR_PRI(electro, ammo), WEP_CVAR_SEC(electro, ammo)), W_Sound("reload"));
- return true;
+ W_Reload(self, min(WEP_CVAR_PRI(electro, ammo), WEP_CVAR_SEC(electro, ammo)), SND(RELOAD));
}
- case WR_SUICIDEMESSAGE:
+ METHOD(Electro, wr_suicidemessage, int(entity thiswep))
{
if(w_deathtype & HITTYPE_SECONDARY)
return WEAPON_ELECTRO_SUICIDE_ORBS;
else
return WEAPON_ELECTRO_SUICIDE_BOLT;
}
- case WR_KILLMESSAGE:
+ METHOD(Electro, wr_killmessage, int(entity thiswep))
{
if(w_deathtype & HITTYPE_SECONDARY)
{
return WEAPON_ELECTRO_MURDER_BOLT;
}
}
- }
- return false;
-}
+
#endif
#ifdef CSQC
-bool W_Electro(int req)
-{
- switch(req)
- {
- case WR_IMPACTEFFECT:
+
+ METHOD(Electro, wr_impacteffect, void(entity thiswep))
{
vector org2;
org2 = w_org + w_backoff * 6;
{
pointparticles(particleeffectnum(EFFECT_ELECTRO_BALLEXPLODE), org2, '0 0 0', 1);
if(!w_issilent)
- sound(self, CH_SHOTS, W_Sound("electro_impact"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_ELECTRO_IMPACT, VOL_BASE, ATTEN_NORM);
}
else
{
// this is sent as "primary (w_deathtype & HITTYPE_BOUNCE)" to distinguish it from (w_deathtype & HITTYPE_SECONDARY) bounced balls
pointparticles(particleeffectnum(EFFECT_ELECTRO_COMBO), org2, '0 0 0', 1);
if(!w_issilent)
- sound(self, CH_SHOTS, W_Sound("electro_impact_combo"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_ELECTRO_IMPACT_COMBO, VOL_BASE, ATTEN_NORM);
}
else
{
pointparticles(particleeffectnum(EFFECT_ELECTRO_IMPACT), org2, '0 0 0', 1);
if(!w_issilent)
- sound(self, CH_SHOTS, W_Sound("electro_impact"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_ELECTRO_IMPACT, VOL_BASE, ATTEN_NORM);
}
}
-
- return true;
}
- case WR_INIT:
- {
- precache_sound(W_Sound("electro_impact"));
- precache_sound(W_Sound("electro_impact_combo"));
- return true;
- }
- case WR_ZOOMRETICLE:
- {
- // no weapon specific image for this weapon
- return false;
- }
- }
- return false;
-}
+
#endif
#endif
#ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id */ FIREBALL,
-/* function */ W_Fireball,
-/* ammotype */ ammo_none,
-/* impulse */ 9,
-/* flags */ WEP_FLAG_SUPERWEAPON | WEP_TYPE_SPLASH,
-/* rating */ BOT_PICKUP_RATING_MID,
-/* color */ '1 0.5 0',
-/* modelname */ "fireball",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairfireball",
-/* wepimg */ "weaponfireball",
-/* refname */ "fireball",
-/* wepname */ _("Fireball")
-);
+CLASS(Fireball, Weapon)
+/* ammotype */ //ATTRIB(Fireball, ammo_field, .int, ammo_none)
+/* impulse */ ATTRIB(Fireball, impulse, int, 9)
+/* flags */ ATTRIB(Fireball, spawnflags, int, WEP_FLAG_SUPERWEAPON | WEP_TYPE_SPLASH);
+/* rating */ ATTRIB(Fireball, bot_pickupbasevalue, float, BOT_PICKUP_RATING_MID);
+/* color */ ATTRIB(Fireball, wpcolor, vector, '1 0.5 0');
+/* modelname */ ATTRIB(Fireball, mdl, string, "fireball");
+#ifndef MENUQC
+/* model */ ATTRIB(Fireball, m_model, Model, MDL_FIREBALL_ITEM);
+#endif
+/* crosshair */ ATTRIB(Fireball, w_crosshair, string, "gfx/crosshairfireball");
+/* crosshair */ //ATTRIB(Fireball, w_crosshair_size, float, 0.65);
+/* wepimg */ ATTRIB(Fireball, model2, string, "weaponfireball");
+/* refname */ ATTRIB(Fireball, netname, string, "fireball");
+/* wepname */ ATTRIB(Fireball, message, string, _("Fireball"));
+ENDCLASS(Fireball)
+REGISTER_WEAPON(FIREBALL, NEW(Fireball));
#define FIREBALL_SETTINGS(w_cvar,w_prop) FIREBALL_SETTINGS_LIST(w_cvar, w_prop, FIREBALL, fireball)
#define FIREBALL_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
#endif
#ifdef IMPLEMENTATION
#ifdef SVQC
-void spawnfunc_weapon_fireball(void) { weapon_defaultspawnfunc(WEP_FIREBALL.m_id); }
+spawnfunc(weapon_fireball) { weapon_defaultspawnfunc(WEP_FIREBALL.m_id); }
void W_Fireball_Explode(void)
-{
+{SELFPARAM();
entity e;
float dist;
float points;
}
void W_Fireball_LaserPlay(float dt, float dist, float damage, float edgedamage, float burntime)
-{
+{SELFPARAM();
entity e;
float d;
vector p;
}
void W_Fireball_Think(void)
-{
+{SELFPARAM();
if(time > self.pushltime)
{
self.cnt = 1;
}
void W_Fireball_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
if(self.health <= 0)
return;
}
void W_Fireball_Attack1(void)
-{
+{SELFPARAM();
entity proj;
- W_SetupShot_ProjectileSize(self, '-16 -16 -16', '16 16 16', false, 2, W_Sound("fireball_fire2"), CH_WEAPON_A, WEP_CVAR_PRI(fireball, damage) + WEP_CVAR_PRI(fireball, bfgdamage));
+ W_SetupShot_ProjectileSize(self, '-16 -16 -16', '16 16 16', false, 2, SND(FIREBALL_FIRE2), CH_WEAPON_A, WEP_CVAR_PRI(fireball, damage) + WEP_CVAR_PRI(fireball, bfgdamage));
Send_Effect(EFFECT_FIREBALL_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
}
void W_Fireball_AttackEffect(float i, vector f_diff)
-{
+{SELFPARAM();
W_SetupShot_ProjectileSize(self, '-16 -16 -16', '16 16 16', false, 0, "", 0, 0);
w_shotorg += f_diff.x * v_up + f_diff.y * v_right;
Send_Effect(EFFECT_FIREBALL_PRE_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
}
-void W_Fireball_Attack1_Frame4(void)
+void W_Fireball_Attack1_Frame4(Weapon thiswep, entity actor, bool fire1, bool fire2)
{
W_Fireball_Attack1();
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), w_ready);
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), w_ready);
}
-void W_Fireball_Attack1_Frame3(void)
+void W_Fireball_Attack1_Frame3(Weapon thiswep, entity actor, bool fire1, bool fire2)
{
W_Fireball_AttackEffect(0, '+1.25 +3.75 0');
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame4);
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame4);
}
-void W_Fireball_Attack1_Frame2(void)
+void W_Fireball_Attack1_Frame2(Weapon thiswep, entity actor, bool fire1, bool fire2)
{
W_Fireball_AttackEffect(0, '-1.25 +3.75 0');
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame3);
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame3);
}
-void W_Fireball_Attack1_Frame1(void)
+void W_Fireball_Attack1_Frame1(Weapon thiswep, entity actor, bool fire1, bool fire2)
{
W_Fireball_AttackEffect(1, '+1.25 -3.75 0');
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame2);
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame2);
}
-void W_Fireball_Attack1_Frame0(void)
-{
+void W_Fireball_Attack1_Frame0(Weapon thiswep, entity actor, bool fire1, bool fire2)
+{SELFPARAM();
W_Fireball_AttackEffect(0, '-1.25 -3.75 0');
- sound(self, CH_WEAPON_SINGLE, W_Sound("fireball_prefire2"), VOL_BASE, ATTEN_NORM);
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame1);
+ sound(self, CH_WEAPON_SINGLE, SND_FIREBALL_PREFIRE2, VOL_BASE, ATTEN_NORM);
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame1);
}
void W_Fireball_Firemine_Think(void)
-{
+{SELFPARAM();
if(time > self.pushltime)
{
remove(self);
}
void W_Fireball_Firemine_Touch(void)
-{
+{SELFPARAM();
PROJECTILE_TOUCH;
if(other.takedamage == DAMAGE_AIM)
if(Fire_AddDamage(other, self.realowner, WEP_CVAR_SEC(fireball, damage), WEP_CVAR_SEC(fireball, damagetime), self.projectiledeathtype) >= 0)
}
void W_Fireball_Attack2(void)
-{
+{SELFPARAM();
entity proj;
vector f_diff;
float c;
f_diff = '+1.25 +3.75 0';
break;
}
- W_SetupShot_ProjectileSize(self, '-4 -4 -4', '4 4 4', false, 2, W_Sound("fireball_fire"), CH_WEAPON_A, WEP_CVAR_SEC(fireball, damage));
+ W_SetupShot_ProjectileSize(self, '-4 -4 -4', '4 4 4', false, 2, SND(FIREBALL_FIRE), CH_WEAPON_A, WEP_CVAR_SEC(fireball, damage));
traceline(w_shotorg, w_shotorg + f_diff_x * v_up + f_diff_y * v_right, MOVE_NORMAL, self);
w_shotorg = trace_endpos;
MUTATOR_CALLHOOK(EditProjectile, self, proj);
}
-bool W_Fireball(int req)
-{
- switch(req)
- {
- case WR_AIM:
+ METHOD(Fireball, wr_aim, void(entity thiswep))
{
self.BUTTON_ATCK = false;
self.BUTTON_ATCK2 = false;
if(random() < 0.01) self.bot_primary_fireballmooth = 1;
}
}
-
- return true;
}
- case WR_THINK:
+ METHOD(Fireball, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
{
- if(self.BUTTON_ATCK)
+ if(fire1)
{
- if(time >= self.fireball_primarytime)
- if(weapon_prepareattack(0, WEP_CVAR_PRI(fireball, refire)))
+ if(time >= actor.fireball_primarytime)
+ if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(fireball, refire)))
{
- W_Fireball_Attack1_Frame0();
- self.fireball_primarytime = time + WEP_CVAR_PRI(fireball, refire2) * W_WeaponRateFactor();
+ W_Fireball_Attack1_Frame0(thiswep, actor, fire1, fire2);
+ actor.fireball_primarytime = time + WEP_CVAR_PRI(fireball, refire2) * W_WeaponRateFactor();
}
}
- else if(self.BUTTON_ATCK2)
+ else if(fire2)
{
- if(weapon_prepareattack(1, WEP_CVAR_SEC(fireball, refire)))
+ if(weapon_prepareattack(thiswep, actor, true, WEP_CVAR_SEC(fireball, refire)))
{
W_Fireball_Attack2();
- weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(fireball, animtime), w_ready);
+ weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR_SEC(fireball, animtime), w_ready);
}
}
-
- return true;
}
- case WR_INIT:
+ METHOD(Fireball, wr_init, void(entity thiswep))
{
- precache_model(W_Model("g_fireball.md3"));
- precache_model(W_Model("v_fireball.md3"));
- precache_model(W_Model("h_fireball.iqm"));
- precache_model("models/sphere/sphere.md3");
- precache_sound(W_Sound("fireball_fire"));
- precache_sound(W_Sound("fireball_fire2"));
- precache_sound(W_Sound("fireball_prefire2"));
FIREBALL_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
- return true;
}
- case WR_SETUP:
+ METHOD(Fireball, wr_setup, void(entity thiswep))
{
self.ammo_field = ammo_none;
- return true;
}
- case WR_CHECKAMMO1:
- case WR_CHECKAMMO2:
+ METHOD(Fireball, wr_checkammo1, bool(entity thiswep))
+ {
+ return true; // infinite ammo
+ }
+ METHOD(Fireball, wr_checkammo2, bool(entity thiswep))
{
return true; // fireball has infinite ammo
}
- case WR_CONFIG:
+ METHOD(Fireball, wr_config, void(entity thiswep))
{
FIREBALL_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
- return true;
}
- case WR_RESETPLAYER:
+ METHOD(Fireball, wr_resetplayer, void(entity thiswep))
{
self.fireball_primarytime = time;
- return true;
}
- case WR_SUICIDEMESSAGE:
+ METHOD(Fireball, wr_suicidemessage, int(entity thiswep))
{
if(w_deathtype & HITTYPE_SECONDARY)
return WEAPON_FIREBALL_SUICIDE_FIREMINE;
else
return WEAPON_FIREBALL_SUICIDE_BLAST;
}
- case WR_KILLMESSAGE:
+ METHOD(Fireball, wr_killmessage, int(entity thiswep))
{
if(w_deathtype & HITTYPE_SECONDARY)
return WEAPON_FIREBALL_MURDER_FIREMINE;
else
return WEAPON_FIREBALL_MURDER_BLAST;
}
- }
- return false;
-}
+
#endif
#ifdef CSQC
-bool W_Fireball(int req)
-{
- switch(req)
- {
- case WR_IMPACTEFFECT:
+
+ METHOD(Fireball, wr_impacteffect, void(entity thiswep))
{
vector org2;
if(w_deathtype & HITTYPE_SECONDARY)
org2 = w_org + w_backoff * 16;
pointparticles(particleeffectnum(EFFECT_FIREBALL_EXPLODE), org2, '0 0 0', 1);
if(!w_issilent)
- sound(self, CH_SHOTS, W_Sound("fireball_impact2"), VOL_BASE, ATTEN_NORM * 0.25); // long range boom
+ sound(self, CH_SHOTS, SND_FIREBALL_IMPACT2, VOL_BASE, ATTEN_NORM * 0.25); // long range boom
}
-
- return true;
}
- case WR_INIT:
- {
- precache_sound(W_Sound("fireball_impact2"));
- return true;
- }
- case WR_ZOOMRETICLE:
- {
- // no weapon specific image for this weapon
- return false;
- }
- }
- return false;
-}
+
#endif
#endif
#ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id */ HAGAR,
-/* function */ W_Hagar,
-/* ammotype */ ammo_rockets,
-/* impulse */ 8,
-/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH,
-/* rating */ BOT_PICKUP_RATING_MID,
-/* color */ '1 1 0.5',
-/* modelname */ "hagar",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairhagar 0.8",
-/* wepimg */ "weaponhagar",
-/* refname */ "hagar",
-/* wepname */ _("Hagar")
-);
+CLASS(Hagar, Weapon)
+/* ammotype */ ATTRIB(Hagar, ammo_field, .int, ammo_rockets)
+/* impulse */ ATTRIB(Hagar, impulse, int, 8)
+/* flags */ ATTRIB(Hagar, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH);
+/* rating */ ATTRIB(Hagar, bot_pickupbasevalue, float, BOT_PICKUP_RATING_MID);
+/* color */ ATTRIB(Hagar, wpcolor, vector, '1 1 0.5');
+/* modelname */ ATTRIB(Hagar, mdl, string, "hagar");
+#ifndef MENUQC
+/* model */ ATTRIB(Hagar, m_model, Model, MDL_HAGAR_ITEM);
+#endif
+/* crosshair */ ATTRIB(Hagar, w_crosshair, string, "gfx/crosshairhagar");
+/* crosshair */ ATTRIB(Hagar, w_crosshair_size, float, 0.8);
+/* wepimg */ ATTRIB(Hagar, model2, string, "weaponhagar");
+/* refname */ ATTRIB(Hagar, netname, string, "hagar");
+/* wepname */ ATTRIB(Hagar, message, string, _("Hagar"));
+ENDCLASS(Hagar)
+REGISTER_WEAPON(HAGAR, NEW(Hagar));
#define HAGAR_SETTINGS(w_cvar,w_prop) HAGAR_SETTINGS_LIST(w_cvar, w_prop, HAGAR, hagar)
#define HAGAR_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
#endif
#ifdef IMPLEMENTATION
#ifdef SVQC
-void spawnfunc_weapon_hagar(void) { weapon_defaultspawnfunc(WEP_HAGAR.m_id); }
+spawnfunc(weapon_hagar) { weapon_defaultspawnfunc(WEP_HAGAR.m_id); }
// NO bounce protection, as bounces are limited!
void W_Hagar_Explode(void)
-{
+{SELFPARAM();
self.event_damage = func_null;
RadiusDamage(self, self.realowner, WEP_CVAR_PRI(hagar, damage), WEP_CVAR_PRI(hagar, edgedamage), WEP_CVAR_PRI(hagar, radius), world, world, WEP_CVAR_PRI(hagar, force), self.projectiledeathtype, other);
}
void W_Hagar_Explode2(void)
-{
+{SELFPARAM();
self.event_damage = func_null;
RadiusDamage(self, self.realowner, WEP_CVAR_SEC(hagar, damage), WEP_CVAR_SEC(hagar, edgedamage), WEP_CVAR_SEC(hagar, radius), world, world, WEP_CVAR_SEC(hagar, force), self.projectiledeathtype, other);
}
void W_Hagar_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
if(self.health <= 0)
return;
}
void W_Hagar_Touch(void)
-{
+{SELFPARAM();
PROJECTILE_TOUCH;
self.use();
}
void W_Hagar_Touch2(void)
-{
+{SELFPARAM();
PROJECTILE_TOUCH;
if(self.cnt > 0 || other.takedamage == DAMAGE_AIM) {
}
}
-void W_Hagar_Attack(void)
-{
+void W_Hagar_Attack(Weapon thiswep)
+{SELFPARAM();
entity missile;
- W_DecreaseAmmo(WEP_CVAR_PRI(hagar, ammo));
+ W_DecreaseAmmo(thiswep, self, WEP_CVAR_PRI(hagar, ammo));
- W_SetupShot(self, false, 2, W_Sound("hagar_fire"), CH_WEAPON_A, WEP_CVAR_PRI(hagar, damage));
+ W_SetupShot(self, false, 2, SND(HAGAR_FIRE), CH_WEAPON_A, WEP_CVAR_PRI(hagar, damage));
Send_Effect(EFFECT_HAGAR_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
MUTATOR_CALLHOOK(EditProjectile, self, missile);
}
-void W_Hagar_Attack2(void)
-{
+void W_Hagar_Attack2(Weapon thiswep)
+{SELFPARAM();
entity missile;
- W_DecreaseAmmo(WEP_CVAR_SEC(hagar, ammo));
+ W_DecreaseAmmo(thiswep, self, WEP_CVAR_SEC(hagar, ammo));
- W_SetupShot(self, false, 2, W_Sound("hagar_fire"), CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage));
+ W_SetupShot(self, false, 2, SND(HAGAR_FIRE), CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage));
Send_Effect(EFFECT_HAGAR_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
.float hagar_loadstep, hagar_loadblock, hagar_loadbeep, hagar_warning;
void W_Hagar_Attack2_Load_Release(void)
-{
+{SELFPARAM();
// time to release the rockets we've loaded
entity missile;
if(!self.hagar_load)
return;
- weapon_prepareattack_do(1, WEP_CVAR_SEC(hagar, refire));
+ weapon_prepareattack_do(self, true, WEP_CVAR_SEC(hagar, refire));
- W_SetupShot(self, false, 2, W_Sound("hagar_fire"), CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage));
+ W_SetupShot(self, false, 2, SND(HAGAR_FIRE), CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage));
Send_Effect(EFFECT_HAGAR_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
forward = v_forward;
MUTATOR_CALLHOOK(EditProjectile, self, missile);
}
- weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(hagar, load_animtime), w_ready);
+ weapon_thinkf(self, WFRAME_FIRE2, WEP_CVAR_SEC(hagar, load_animtime), w_ready);
self.hagar_loadstep = time + WEP_CVAR_SEC(hagar, refire) * W_WeaponRateFactor();
self.hagar_load = 0;
}
-void W_Hagar_Attack2_Load(void)
-{
+void W_Hagar_Attack2_Load(Weapon thiswep)
+{SELFPARAM();
// loadable hagar secondary attack, must always run each frame
if(time < game_starttime)
{
// if we pressed primary fire while loading, unload all rockets and abort
self.weaponentity.state = WS_READY;
- W_DecreaseAmmo(WEP_CVAR_SEC(hagar, ammo) * self.hagar_load * -1); // give back ammo
+ W_DecreaseAmmo(thiswep, self, WEP_CVAR_SEC(hagar, ammo) * self.hagar_load * -1); // give back ammo
self.hagar_load = 0;
- sound(self, CH_WEAPON_A, W_Sound("hagar_beep"), VOL_BASE, ATTN_NORM);
+ sound(self, CH_WEAPON_A, SND_HAGAR_BEEP, VOL_BASE, ATTN_NORM);
// pause until we can load rockets again, once we re-press the alt fire button
self.hagar_loadstep = time + WEP_CVAR_SEC(hagar, load_speed) * W_WeaponRateFactor();
{
if(!self.hagar_loadblock && self.hagar_loadstep < time)
{
- W_DecreaseAmmo(WEP_CVAR_SEC(hagar, ammo));
+ W_DecreaseAmmo(thiswep, self, WEP_CVAR_SEC(hagar, ammo));
self.weaponentity.state = WS_INUSE;
self.hagar_load += 1;
- sound(self, CH_WEAPON_B, W_Sound("hagar_load"), VOL_BASE * 0.8, ATTN_NORM); // sound is too loud according to most
+ sound(self, CH_WEAPON_B, SND_HAGAR_LOAD, VOL_BASE * 0.8, ATTN_NORM); // sound is too loud according to most
if(self.hagar_load >= WEP_CVAR_SEC(hagar, load_max))
stopped = true;
if(stopped && !self.hagar_loadbeep && self.hagar_load) // prevents the beep from playing each frame
{
// if this is the last rocket we can load, play a beep sound to notify the player
- sound(self, CH_WEAPON_A, W_Sound("hagar_beep"), VOL_BASE, ATTN_NORM);
+ sound(self, CH_WEAPON_A, SND_HAGAR_BEEP, VOL_BASE, ATTN_NORM);
self.hagar_loadbeep = true;
self.hagar_loadstep = time + WEP_CVAR_SEC(hagar, load_hold) * W_WeaponRateFactor();
}
if(!self.hagar_warning) // prevents the beep from playing each frame
{
// we're about to automatically release after holding time, play a beep sound to notify the player
- sound(self, CH_WEAPON_A, W_Sound("hagar_beep"), VOL_BASE, ATTN_NORM);
+ sound(self, CH_WEAPON_A, SND_HAGAR_BEEP, VOL_BASE, ATTN_NORM);
self.hagar_warning = true;
}
}
self.hagar_warning = false;
// we aren't checking ammo during an attack, so we must do it here
- if(!(WEP_ACTION(self.weapon, WR_CHECKAMMO1) + WEP_ACTION(self.weapon, WR_CHECKAMMO2)))
+ Weapon w = get_weaponinfo(self.weapon);
+ if(!(w.wr_checkammo1(w) + w.wr_checkammo2(w)))
if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
{
// note: this doesn't force the switch
}
}
-bool W_Hagar(int req)
-{
- float ammo_amount;
- switch(req)
- {
- case WR_AIM:
+ METHOD(Hagar, wr_aim, void(entity thiswep))
{
if(random()>0.15)
self.BUTTON_ATCK = bot_aim(WEP_CVAR_PRI(hagar, speed), 0, WEP_CVAR_PRI(hagar, lifetime), false);
else // not using secondary_speed since these are only 15% and should cause some ricochets without re-aiming
self.BUTTON_ATCK2 = bot_aim(WEP_CVAR_PRI(hagar, speed), 0, WEP_CVAR_PRI(hagar, lifetime), false);
-
- return true;
}
- case WR_THINK:
+ METHOD(Hagar, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
{
float loadable_secondary;
loadable_secondary = (WEP_CVAR_SEC(hagar, load) && WEP_CVAR(hagar, secondary));
if(loadable_secondary)
- W_Hagar_Attack2_Load(); // must always run each frame
- if(autocvar_g_balance_hagar_reload_ammo && self.clip_load < min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo))) // forced reload
- WEP_ACTION(self.weapon, WR_RELOAD);
- else if(self.BUTTON_ATCK && !self.hagar_load && !self.hagar_loadblock) // not while secondary is loaded or awaiting reset
+ W_Hagar_Attack2_Load(thiswep); // must always run each frame
+ if(autocvar_g_balance_hagar_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo))) { // forced reload
+ Weapon w = get_weaponinfo(actor.weapon);
+ w.wr_reload(w);
+ } else if(fire1 && !actor.hagar_load && !actor.hagar_loadblock) // not while secondary is loaded or awaiting reset
{
- if(weapon_prepareattack(0, WEP_CVAR_PRI(hagar, refire)))
+ if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(hagar, refire)))
{
- W_Hagar_Attack();
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(hagar, refire), w_ready);
+ W_Hagar_Attack(thiswep);
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(hagar, refire), w_ready);
}
}
- else if(self.BUTTON_ATCK2 && !loadable_secondary && WEP_CVAR(hagar, secondary))
+ else if(fire2 && !loadable_secondary && WEP_CVAR(hagar, secondary))
{
- if(weapon_prepareattack(1, WEP_CVAR_SEC(hagar, refire)))
+ if(weapon_prepareattack(thiswep, actor, true, WEP_CVAR_SEC(hagar, refire)))
{
- W_Hagar_Attack2();
- weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(hagar, refire), w_ready);
+ W_Hagar_Attack2(thiswep);
+ weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR_SEC(hagar, refire), w_ready);
}
}
- return true;
}
- case WR_GONETHINK:
+ METHOD(Hagar, wr_gonethink, void(entity thiswep))
{
// we lost the weapon and want to prepare switching away
if(self.hagar_load)
self.weaponentity.state = WS_READY;
W_Hagar_Attack2_Load_Release();
}
-
- return true;
}
- case WR_INIT:
+ METHOD(Hagar, wr_init, void(entity thiswep))
{
- precache_model(W_Model("g_hagar.md3"));
- precache_model(W_Model("v_hagar.md3"));
- precache_model(W_Model("h_hagar.iqm"));
- precache_sound(W_Sound("hagar_fire"));
- precache_sound(W_Sound("hagar_load"));
- precache_sound(W_Sound("hagar_beep"));
HAGAR_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
- return true;
}
- case WR_SETUP:
+ METHOD(Hagar, wr_setup, void(entity thiswep))
{
self.hagar_loadblock = false;
if(self.hagar_load)
{
- W_DecreaseAmmo(WEP_CVAR_SEC(hagar, ammo) * self.hagar_load * -1); // give back ammo if necessary
+ W_DecreaseAmmo(thiswep, self, WEP_CVAR_SEC(hagar, ammo) * self.hagar_load * -1); // give back ammo if necessary
self.hagar_load = 0;
}
-
- return true;
}
- case WR_CHECKAMMO1:
+ METHOD(Hagar, wr_checkammo1, bool(entity thiswep))
{
- ammo_amount = self.WEP_AMMO(HAGAR) >= WEP_CVAR_PRI(hagar, ammo);
+ float ammo_amount = self.WEP_AMMO(HAGAR) >= WEP_CVAR_PRI(hagar, ammo);
ammo_amount += self.(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_PRI(hagar, ammo);
return ammo_amount;
}
- case WR_CHECKAMMO2:
+ METHOD(Hagar, wr_checkammo2, bool(entity thiswep))
{
- ammo_amount = self.WEP_AMMO(HAGAR) >= WEP_CVAR_SEC(hagar, ammo);
+ float ammo_amount = self.WEP_AMMO(HAGAR) >= WEP_CVAR_SEC(hagar, ammo);
ammo_amount += self.(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_SEC(hagar, ammo);
return ammo_amount;
}
- case WR_CONFIG:
+ METHOD(Hagar, wr_config, void(entity thiswep))
{
HAGAR_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
- return true;
}
- case WR_RESETPLAYER:
+ METHOD(Hagar, wr_resetplayer, void(entity thiswep))
{
self.hagar_load = 0;
- return true;
}
- case WR_PLAYERDEATH:
+ METHOD(Hagar, wr_playerdeath, void(entity thiswep))
{
// if we have any rockets loaded when we die, release them
if(self.hagar_load && WEP_CVAR_SEC(hagar, load_releasedeath))
W_Hagar_Attack2_Load_Release();
-
- return true;
}
- case WR_RELOAD:
+ METHOD(Hagar, wr_reload, void(entity thiswep))
{
if(!self.hagar_load) // require releasing loaded rockets first
- W_Reload(min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo)), W_Sound("reload"));
-
- return true;
+ W_Reload(self, min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo)), SND(RELOAD));
}
- case WR_SUICIDEMESSAGE:
+ METHOD(Hagar, wr_suicidemessage, int(entity thiswep))
{
return WEAPON_HAGAR_SUICIDE;
}
- case WR_KILLMESSAGE:
+ METHOD(Hagar, wr_killmessage, int(entity thiswep))
{
if(w_deathtype & HITTYPE_SECONDARY)
return WEAPON_HAGAR_MURDER_BURST;
else
return WEAPON_HAGAR_MURDER_SPRAY;
}
- }
- return false;
-}
+
#endif
#ifdef CSQC
-bool W_Hagar(int req)
-{
- switch(req)
- {
- case WR_IMPACTEFFECT:
+
+ METHOD(Hagar, wr_impacteffect, void(entity thiswep))
{
vector org2;
org2 = w_org + w_backoff * 6;
if(!w_issilent)
{
if(w_random<0.15)
- sound(self, CH_SHOTS, W_Sound("hagexp1"), VOL_BASE, ATTN_NORM);
+ sound(self, CH_SHOTS, SND_HAGEXP1, VOL_BASE, ATTN_NORM);
else if(w_random<0.7)
- sound(self, CH_SHOTS, W_Sound("hagexp2"), VOL_BASE, ATTN_NORM);
+ sound(self, CH_SHOTS, SND_HAGEXP2, VOL_BASE, ATTN_NORM);
else
- sound(self, CH_SHOTS, W_Sound("hagexp3"), VOL_BASE, ATTN_NORM);
+ sound(self, CH_SHOTS, SND_HAGEXP3, VOL_BASE, ATTN_NORM);
}
-
- return true;
- }
- case WR_INIT:
- {
- precache_sound(W_Sound("hagexp1"));
- precache_sound(W_Sound("hagexp2"));
- precache_sound(W_Sound("hagexp3"));
- return true;
}
- case WR_ZOOMRETICLE:
- {
- // no weapon specific image for this weapon
- return false;
- }
- }
- return false;
-}
+
#endif
#endif
#ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id */ HLAC,
-/* function */ W_HLAC,
-/* ammotype */ ammo_cells,
-/* impulse */ 6,
-/* flags */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH,
-/* rating */ BOT_PICKUP_RATING_MID,
-/* color */ '0 1 0',
-/* modelname */ "hlac",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairhlac 0.6",
-/* wepimg */ "weaponhlac",
-/* refname */ "hlac",
-/* wepname */ _("Heavy Laser Assault Cannon")
-);
+CLASS(HLAC, Weapon)
+/* ammotype */ ATTRIB(HLAC, ammo_field, .int, ammo_cells)
+/* impulse */ ATTRIB(HLAC, impulse, int, 6)
+/* flags */ ATTRIB(HLAC, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH);
+/* rating */ ATTRIB(HLAC, bot_pickupbasevalue, float, BOT_PICKUP_RATING_MID);
+/* color */ ATTRIB(HLAC, wpcolor, vector, '0 1 0');
+/* modelname */ ATTRIB(HLAC, mdl, string, "hlac");
+#ifndef MENUQC
+/* model */ ATTRIB(HLAC, m_model, Model, MDL_HLAC_ITEM);
+#endif
+/* crosshair */ ATTRIB(HLAC, w_crosshair, string, "gfx/crosshairhlac");
+/* crosshair */ ATTRIB(HLAC, w_crosshair_size, float, 0.6);
+/* wepimg */ ATTRIB(HLAC, model2, string, "weaponhlac");
+/* refname */ ATTRIB(HLAC, netname, string, "hlac");
+/* wepname */ ATTRIB(HLAC, message, string, _("Heavy Laser Assault Cannon"));
+ENDCLASS(HLAC)
+REGISTER_WEAPON(HLAC, NEW(HLAC));
#define HLAC_SETTINGS(w_cvar,w_prop) HLAC_SETTINGS_LIST(w_cvar, w_prop, HLAC, hlac)
#define HLAC_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
#endif
#ifdef IMPLEMENTATION
#ifdef SVQC
-void spawnfunc_weapon_hlac(void) { weapon_defaultspawnfunc(WEP_HLAC.m_id); }
+spawnfunc(weapon_hlac) { weapon_defaultspawnfunc(WEP_HLAC.m_id); }
void W_HLAC_Touch(void)
-{
+{SELFPARAM();
float isprimary;
PROJECTILE_TOUCH;
remove(self);
}
-void W_HLAC_Attack(void)
-{
+void W_HLAC_Attack(Weapon thiswep)
+{SELFPARAM();
entity missile;
float spread;
- W_DecreaseAmmo(WEP_CVAR_PRI(hlac, ammo));
+ W_DecreaseAmmo(thiswep, self, WEP_CVAR_PRI(hlac, ammo));
spread = WEP_CVAR_PRI(hlac, spread_min) + (WEP_CVAR_PRI(hlac, spread_add) * self.misc_bulletcounter);
spread = min(spread,WEP_CVAR_PRI(hlac, spread_max));
if(self.crouch)
spread = spread * WEP_CVAR_PRI(hlac, spread_crouchmod);
- W_SetupShot(self, false, 3, W_Sound("lasergun_fire"), CH_WEAPON_A, WEP_CVAR_PRI(hlac, damage));
+ W_SetupShot(self, false, 3, SND(LASERGUN_FIRE), CH_WEAPON_A, WEP_CVAR_PRI(hlac, damage));
Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
if(!autocvar_g_norecoil)
{
}
void W_HLAC_Attack2(void)
-{
+{SELFPARAM();
entity missile;
float spread;
if(self.crouch)
spread = spread * WEP_CVAR_SEC(hlac, spread_crouchmod);
- W_SetupShot(self, false, 3, W_Sound("lasergun_fire"), CH_WEAPON_A, WEP_CVAR_SEC(hlac, damage));
+ W_SetupShot(self, false, 3, SND(LASERGUN_FIRE), CH_WEAPON_A, WEP_CVAR_SEC(hlac, damage));
Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
missile = spawn();
}
// weapon frames
-void W_HLAC_Attack_Frame(void)
+void W_HLAC_Attack_Frame(Weapon thiswep, entity actor, bool fire1, bool fire2)
{
- if(self.weapon != self.switchweapon) // abort immediately if switching
+ if(actor.weapon != actor.switchweapon) // abort immediately if switching
{
- w_ready();
+ w_ready(thiswep, actor, fire1, fire2);
return;
}
- if(self.BUTTON_ATCK)
+ if(actor.BUTTON_ATCK)
{
- if(!WEP_ACTION(self.weapon, WR_CHECKAMMO1))
- if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+ Weapon w = get_weaponinfo(actor.weapon);
+ if(!w.wr_checkammo1(w))
+ if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
- W_SwitchWeapon_Force(self, w_getbestweapon(self));
- w_ready();
+ W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+ w_ready(thiswep, actor, fire1, fire2);
return;
}
- ATTACK_FINISHED(self) = time + WEP_CVAR_PRI(hlac, refire) * W_WeaponRateFactor();
- W_HLAC_Attack();
- self.misc_bulletcounter = self.misc_bulletcounter + 1;
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(hlac, refire), W_HLAC_Attack_Frame);
+ ATTACK_FINISHED(actor) = time + WEP_CVAR_PRI(hlac, refire) * W_WeaponRateFactor();
+ W_HLAC_Attack(WEP_HLAC);
+ actor.misc_bulletcounter = actor.misc_bulletcounter + 1;
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(hlac, refire), W_HLAC_Attack_Frame);
}
else
{
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(hlac, animtime), w_ready);
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(hlac, animtime), w_ready);
}
}
-void W_HLAC_Attack2_Frame(void)
-{
+void W_HLAC_Attack2_Frame(Weapon thiswep)
+{SELFPARAM();
float i;
- W_DecreaseAmmo(WEP_CVAR_SEC(hlac, ammo));
+ W_DecreaseAmmo(thiswep, self, WEP_CVAR_SEC(hlac, ammo));
for(i=WEP_CVAR_SEC(hlac, shots);i>0;--i)
W_HLAC_Attack2();
}
}
-bool W_HLAC(int req)
-{
- float ammo_amount;
- switch(req)
- {
- case WR_AIM:
+ METHOD(HLAC, wr_aim, void(entity thiswep))
{
self.BUTTON_ATCK = bot_aim(WEP_CVAR_PRI(hlac, speed), 0, WEP_CVAR_PRI(hlac, lifetime), false);
- return true;
}
- case WR_THINK:
+ METHOD(HLAC, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
{
- if(autocvar_g_balance_hlac_reload_ammo && self.clip_load < min(WEP_CVAR_PRI(hlac, ammo), WEP_CVAR_SEC(hlac, ammo))) // forced reload
- WEP_ACTION(self.weapon, WR_RELOAD);
- else if(self.BUTTON_ATCK)
+ if(autocvar_g_balance_hlac_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(hlac, ammo), WEP_CVAR_SEC(hlac, ammo))) { // forced reload
+ Weapon w = get_weaponinfo(actor.weapon);
+ w.wr_reload(w);
+ } else if(fire1)
{
- if(weapon_prepareattack(0, WEP_CVAR_PRI(hlac, refire)))
+ if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(hlac, refire)))
{
- self.misc_bulletcounter = 0;
- W_HLAC_Attack();
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(hlac, refire), W_HLAC_Attack_Frame);
+ actor.misc_bulletcounter = 0;
+ W_HLAC_Attack(thiswep);
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(hlac, refire), W_HLAC_Attack_Frame);
}
}
- else if(self.BUTTON_ATCK2 && WEP_CVAR(hlac, secondary))
+ else if(fire2 && WEP_CVAR(hlac, secondary))
{
- if(weapon_prepareattack(1, WEP_CVAR_SEC(hlac, refire)))
+ if(weapon_prepareattack(thiswep, actor, true, WEP_CVAR_SEC(hlac, refire)))
{
- W_HLAC_Attack2_Frame();
- weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(hlac, animtime), w_ready);
+ W_HLAC_Attack2_Frame(thiswep);
+ weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR_SEC(hlac, animtime), w_ready);
}
}
-
- return true;
}
- case WR_INIT:
+ METHOD(HLAC, wr_init, void(entity thiswep))
{
- precache_model(W_Model("g_hlac.md3"));
- precache_model(W_Model("v_hlac.md3"));
- precache_model(W_Model("h_hlac.iqm"));
- precache_sound(W_Sound("lasergun_fire"));
HLAC_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
- return true;
}
- case WR_CHECKAMMO1:
+ METHOD(HLAC, wr_checkammo1, bool(entity thiswep))
{
- ammo_amount = self.WEP_AMMO(HLAC) >= WEP_CVAR_PRI(hlac, ammo);
+ float ammo_amount = self.WEP_AMMO(HLAC) >= WEP_CVAR_PRI(hlac, ammo);
ammo_amount += self.(weapon_load[WEP_HLAC.m_id]) >= WEP_CVAR_PRI(hlac, ammo);
return ammo_amount;
}
- case WR_CHECKAMMO2:
+ METHOD(HLAC, wr_checkammo2, bool(entity thiswep))
{
- ammo_amount = self.WEP_AMMO(HLAC) >= WEP_CVAR_SEC(hlac, ammo);
+ float ammo_amount = self.WEP_AMMO(HLAC) >= WEP_CVAR_SEC(hlac, ammo);
ammo_amount += self.(weapon_load[WEP_HLAC.m_id]) >= WEP_CVAR_SEC(hlac, ammo);
return ammo_amount;
}
- case WR_CONFIG:
+ METHOD(HLAC, wr_config, void(entity thiswep))
{
HLAC_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
- return true;
}
- case WR_RELOAD:
+ METHOD(HLAC, wr_reload, void(entity thiswep))
{
- W_Reload(min(WEP_CVAR_PRI(hlac, ammo), WEP_CVAR_SEC(hlac, ammo)), W_Sound("reload"));
- return true;
+ W_Reload(self, min(WEP_CVAR_PRI(hlac, ammo), WEP_CVAR_SEC(hlac, ammo)), SND(RELOAD));
}
- case WR_SUICIDEMESSAGE:
+ METHOD(HLAC, wr_suicidemessage, int(entity thiswep))
{
return WEAPON_HLAC_SUICIDE;
}
- case WR_KILLMESSAGE:
+ METHOD(HLAC, wr_killmessage, int(entity thiswep))
{
return WEAPON_HLAC_MURDER;
}
- }
- return false;
-}
+
#endif
#ifdef CSQC
-bool W_HLAC(int req)
-{
- switch(req)
- {
- case WR_IMPACTEFFECT:
+
+ METHOD(HLAC, wr_impacteffect, void(entity thiswep))
{
vector org2;
org2 = w_org + w_backoff * 6;
pointparticles(particleeffectnum(EFFECT_BLASTER_IMPACT), org2, w_backoff * 1000, 1);
if(!w_issilent)
- sound(self, CH_SHOTS, W_Sound("laserimpact"), VOL_BASE, ATTN_NORM);
-
- return true;
- }
- case WR_INIT:
- {
- precache_sound(W_Sound("laserimpact"));
- return true;
+ sound(self, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTN_NORM);
}
- case WR_ZOOMRETICLE:
- {
- // no weapon specific image for this weapon
- return false;
- }
- }
- return false;
-}
+
#endif
#endif
#ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id */ HMG,
-/* function */ W_HeavyMachineGun,
-/* ammotype */ ammo_nails,
-/* impulse */ 3,
-/* flags */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_HIDDEN | WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN | WEP_FLAG_SUPERWEAPON,
-/* rating */ BOT_PICKUP_RATING_HIGH,
-/* color */ '0.5 0.5 0',
-/* modelname */ "ok_hmg",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairuzi 0.6",
-/* wepimg */ "weaponhmg",
-/* refname */ "hmg",
-/* wepname */ _("Heavy Machine Gun")
-);
+CLASS(HeavyMachineGun, Weapon)
+/* ammotype */ ATTRIB(HeavyMachineGun, ammo_field, .int, ammo_nails)
+/* impulse */ ATTRIB(HeavyMachineGun, impulse, int, 3)
+/* flags */ ATTRIB(HeavyMachineGun, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_HIDDEN | WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN | WEP_FLAG_SUPERWEAPON);
+/* rating */ ATTRIB(HeavyMachineGun, bot_pickupbasevalue, float, BOT_PICKUP_RATING_HIGH);
+/* color */ ATTRIB(HeavyMachineGun, wpcolor, vector, '0.5 0.5 0');
+/* modelname */ ATTRIB(HeavyMachineGun, mdl, string, "ok_hmg");
+#ifndef MENUQC
+/* model */ ATTRIB(HeavyMachineGun, m_model, Model, MDL_HMG_ITEM);
+#endif
+/* crosshair */ ATTRIB(HeavyMachineGun, w_crosshair, string, "gfx/crosshairuzi");
+/* crosshair */ ATTRIB(HeavyMachineGun, w_crosshair_size, float, 0.6);
+/* wepimg */ ATTRIB(HeavyMachineGun, model2, string, "weaponhmg");
+/* refname */ ATTRIB(HeavyMachineGun, netname, string, "hmg");
+/* wepname */ ATTRIB(HeavyMachineGun, message, string, _("Heavy Machine Gun"));
+ENDCLASS(HeavyMachineGun)
+REGISTER_WEAPON(HMG, NEW(HeavyMachineGun));
#define HMG_SETTINGS(w_cvar,w_prop) HMG_SETTINGS_LIST(w_cvar, w_prop, HMG, hmg)
#define HMG_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
#ifdef IMPLEMENTATION
#ifdef SVQC
-void spawnfunc_weapon_hmg() { weapon_defaultspawnfunc(WEP_HMG.m_id); }
+spawnfunc(weapon_hmg) { weapon_defaultspawnfunc(WEP_HMG.m_id); }
-void W_HeavyMachineGun_Attack_Auto()
+void W_HeavyMachineGun_Attack_Auto(Weapon thiswep, entity actor, bool fire1, bool fire2)
{
- if (!self.BUTTON_ATCK)
+ if (!actor.BUTTON_ATCK)
{
- w_ready();
+ w_ready(thiswep, actor, fire1, fire2);
return;
}
- if(!WEP_ACTION(self.weapon, WR_CHECKAMMO1))
- if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+ Weapon w = get_weaponinfo(actor.weapon);
+ if(!w.wr_checkammo1(w))
+ if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
- W_SwitchWeapon_Force(self, w_getbestweapon(self));
- w_ready();
+ W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+ w_ready(thiswep, actor, fire1, fire2);
return;
}
- W_DecreaseAmmo(WEP_CVAR(hmg, ammo));
+ W_DecreaseAmmo(WEP_HMG, self, WEP_CVAR(hmg, ammo));
- W_SetupShot (self, true, 0, W_Sound("uzi_fire"), CH_WEAPON_A, WEP_CVAR(hmg, damage));
+ W_SetupShot (actor, true, 0, SND(UZI_FIRE), CH_WEAPON_A, WEP_CVAR(hmg, damage));
if(!autocvar_g_norecoil)
{
- self.punchangle_x = random () - 0.5;
- self.punchangle_y = random () - 0.5;
+ actor.punchangle_x = random () - 0.5;
+ actor.punchangle_y = random () - 0.5;
}
- float hmg_spread = bound(WEP_CVAR(hmg, spread_min), WEP_CVAR(hmg, spread_min) + (WEP_CVAR(hmg, spread_add) * self.misc_bulletcounter), WEP_CVAR(hmg, spread_max));
+ float hmg_spread = bound(WEP_CVAR(hmg, spread_min), WEP_CVAR(hmg, spread_min) + (WEP_CVAR(hmg, spread_add) * actor.misc_bulletcounter), WEP_CVAR(hmg, spread_max));
fireBullet(w_shotorg, w_shotdir, hmg_spread, WEP_CVAR(hmg, solidpenetration), WEP_CVAR(hmg, damage), WEP_CVAR(hmg, force), WEP_HMG.m_id, 0);
- self.misc_bulletcounter = self.misc_bulletcounter + 1;
+ actor.misc_bulletcounter = actor.misc_bulletcounter + 1;
Send_Effect(EFFECT_MACHINEGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
W_MachineGun_MuzzleFlash();
- W_AttachToShotorg(self.muzzle_flash, '5 0 0');
+ W_AttachToShotorg(actor, actor.muzzle_flash, '5 0 0');
if (autocvar_g_casings >= 2) // casing code
- SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self);
+ SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, actor);
- ATTACK_FINISHED(self) = time + WEP_CVAR(hmg, refire) * W_WeaponRateFactor();
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(hmg, refire), W_HeavyMachineGun_Attack_Auto);
+ ATTACK_FINISHED(actor) = time + WEP_CVAR(hmg, refire) * W_WeaponRateFactor();
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR(hmg, refire), W_HeavyMachineGun_Attack_Auto);
}
-bool W_HeavyMachineGun(int req)
-{
- float ammo_amount;
- switch(req)
- {
- case WR_AIM:
+ METHOD(HeavyMachineGun, wr_aim, void(entity thiswep))
{
if(vlen(self.origin-self.enemy.origin) < 3000 - bound(0, skill, 10) * 200)
self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, false);
else
self.BUTTON_ATCK2 = bot_aim(1000000, 0, 0.001, false);
-
- return true;
}
- case WR_THINK:
+ METHOD(HeavyMachineGun, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
{
- if(WEP_CVAR(hmg, reload_ammo) && self.clip_load < WEP_CVAR(hmg, ammo)) // forced reload
- WEP_ACTION(self.weapon, WR_RELOAD);
- else
+ if(WEP_CVAR(hmg, reload_ammo) && actor.clip_load < WEP_CVAR(hmg, ammo)) { // forced reload
+ Weapon w = get_weaponinfo(actor.weapon);
+ w.wr_reload(w);
+ } else
{
- if (self.BUTTON_ATCK)
- if (weapon_prepareattack(0, 0))
+ if (fire1)
+ if (weapon_prepareattack(thiswep, actor, false, 0))
{
- self.misc_bulletcounter = 0;
- W_HeavyMachineGun_Attack_Auto();
+ actor.misc_bulletcounter = 0;
+ W_HeavyMachineGun_Attack_Auto(thiswep, actor, fire1, fire2);
}
}
-
- return true;
}
- case WR_INIT:
+ METHOD(HeavyMachineGun, wr_init, void(entity thiswep))
{
- precache_model ("models/uziflash.md3");
- precache_model(W_Model("g_ok_hmg.md3"));
- precache_model(W_Model("v_ok_hmg.md3"));
- precache_model(W_Model("h_ok_hmg.iqm"));
- precache_sound (W_Sound("uzi_fire"));
HMG_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
- return true;
}
- case WR_CHECKAMMO1:
+ METHOD(HeavyMachineGun, wr_checkammo1, bool(entity thiswep))
{
- ammo_amount = self.ammo_nails >= WEP_CVAR(hmg, ammo);
+ float ammo_amount = self.ammo_nails >= WEP_CVAR(hmg, ammo);
if(autocvar_g_balance_hmg_reload_ammo)
ammo_amount += self.(weapon_load[WEP_HMG.m_id]) >= WEP_CVAR(hmg, ammo);
return ammo_amount;
}
- case WR_CHECKAMMO2:
+ METHOD(HeavyMachineGun, wr_checkammo2, bool(entity thiswep))
{
- ammo_amount = self.ammo_nails >= WEP_CVAR(hmg, ammo);
+ float ammo_amount = self.ammo_nails >= WEP_CVAR(hmg, ammo);
if(autocvar_g_balance_hmg_reload_ammo)
ammo_amount += self.(weapon_load[WEP_HMG.m_id]) >= WEP_CVAR(hmg, ammo);
return ammo_amount;
}
- case WR_CONFIG:
+ METHOD(HeavyMachineGun, wr_config, void(entity thiswep))
{
HMG_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
- return true;
}
- case WR_RELOAD:
+ METHOD(HeavyMachineGun, wr_reload, void(entity thiswep))
{
- W_Reload(WEP_CVAR(hmg, ammo), W_Sound("reload"));
- return true;
+ W_Reload(self, WEP_CVAR(hmg, ammo), SND(RELOAD));
}
- case WR_SUICIDEMESSAGE:
+ METHOD(HeavyMachineGun, wr_suicidemessage, int(entity thiswep))
{
return WEAPON_THINKING_WITH_PORTALS;
}
- case WR_KILLMESSAGE:
+ METHOD(HeavyMachineGun, wr_killmessage, int(entity thiswep))
{
if(w_deathtype & HITTYPE_SECONDARY)
return WEAPON_HMG_MURDER_SNIPE;
else
return WEAPON_HMG_MURDER_SPRAY;
}
- }
- return false;
-}
+
#endif
#ifdef CSQC
-bool W_HeavyMachineGun(int req)
-{
- switch(req)
- {
- case WR_IMPACTEFFECT:
+
+ METHOD(HeavyMachineGun, wr_impacteffect, void(entity thiswep))
{
vector org2;
org2 = w_org + w_backoff * 2;
pointparticles(particleeffectnum(EFFECT_MACHINEGUN_IMPACT), org2, w_backoff * 1000, 1);
if(!w_issilent)
if(w_random < 0.05)
- sound(self, CH_SHOTS, W_Sound("ric1"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_RIC1, VOL_BASE, ATTEN_NORM);
else if(w_random < 0.1)
- sound(self, CH_SHOTS, W_Sound("ric2"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_RIC2, VOL_BASE, ATTEN_NORM);
else if(w_random < 0.2)
- sound(self, CH_SHOTS, W_Sound("ric3"), VOL_BASE, ATTEN_NORM);
-
- return true;
- }
- case WR_INIT:
- {
- precache_sound(W_Sound("ric1"));
- precache_sound(W_Sound("ric2"));
- precache_sound(W_Sound("ric3"));
- return true;
+ sound(self, CH_SHOTS, SND_RIC3, VOL_BASE, ATTEN_NORM);
}
- case WR_ZOOMRETICLE:
- {
- // no weapon specific image for this weapon
- return false;
- }
- }
- return false;
-}
+
#endif
#endif
#ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id */ HOOK,
-/* function */ W_Hook,
-/* ammotype */ ammo_fuel,
-/* impulse */ 0,
-/* flags */ WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH,
-/* rating */ 0,
-/* color */ '0 0.5 0',
-/* modelname */ "hookgun",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairhook 0.5",
-/* wepimg */ "weaponhook",
-/* refname */ "hook",
-/* wepname */ _("Grappling Hook")
-);
+CLASS(Hook, Weapon)
+/* ammotype */ ATTRIB(Hook, ammo_field, .int, ammo_fuel)
+/* impulse */ ATTRIB(Hook, impulse, int, 0)
+/* flags */ ATTRIB(Hook, spawnflags, int, WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH);
+/* rating */ ATTRIB(Hook, bot_pickupbasevalue, float, 0);
+/* color */ ATTRIB(Hook, wpcolor, vector, '0 0.5 0');
+/* modelname */ ATTRIB(Hook, mdl, string, "hookgun");
+#ifndef MENUQC
+/* model */ ATTRIB(Hook, m_model, Model, MDL_HOOK_ITEM);
+#endif
+/* crosshair */ ATTRIB(Hook, w_crosshair, string, "gfx/crosshairhook");
+/* crosshair */ ATTRIB(Hook, w_crosshair_size, float, 0.5);
+/* wepimg */ ATTRIB(Hook, model2, string, "weaponhook");
+/* refname */ ATTRIB(Hook, netname, string, "hook");
+/* wepname */ ATTRIB(Hook, message, string, _("Grappling Hook"));
+ ATTRIB(Hook, ammo_factor, float, 1)
+ENDCLASS(Hook)
+REGISTER_WEAPON(HOOK, NEW(Hook));
+
+CLASS(OffhandHook, OffhandWeapon)
+ METHOD(OffhandHook, offhand_think, void(OffhandHook this, entity actor, bool key_pressed))
+ {
+ Weapon wep = WEP_HOOK;
+ wep.wr_think(wep, actor, key_pressed, false);
+ }
+ENDCLASS(OffhandHook)
+OffhandHook OFFHAND_HOOK; STATIC_INIT(OFFHAND_HOOK) { OFFHAND_HOOK = NEW(OffhandHook); }
#define HOOK_SETTINGS(w_cvar,w_prop) HOOK_SETTINGS_LIST(w_cvar, w_prop, HOOK, hook)
#define HOOK_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
#ifdef IMPLEMENTATION
#ifdef SVQC
-void spawnfunc_weapon_hook(void)
-{
- if(g_grappling_hook) // offhand hook
- {
- startitem_failed = true;
- remove(self);
- return;
- }
- weapon_defaultspawnfunc(WEP_HOOK.m_id);
-}
+spawnfunc(weapon_hook) { weapon_defaultspawnfunc(WEP_HOOK.m_id); }
void W_Hook_ExplodeThink(void)
-{
+{SELFPARAM();
float dt, dmg_remaining_next, f;
dt = time - self.teleport_time;
}
void W_Hook_Explode2(void)
-{
+{SELFPARAM();
self.event_damage = func_null;
self.touch = func_null;
self.effects |= EF_NODRAW;
}
void W_Hook_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
if(self.health <= 0)
return;
}
void W_Hook_Touch2(void)
-{
+{SELFPARAM();
PROJECTILE_TOUCH;
self.use();
}
-void W_Hook_Attack2(void)
+void W_Hook_Attack2(Weapon thiswep, entity actor)
{
- entity gren;
+ //W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hook, ammo)); // WEAPONTODO: Figure out how to handle ammo with hook secondary (gravitybomb)
+ W_SetupShot(actor, false, 4, SND(HOOKBOMB_FIRE), CH_WEAPON_A, WEP_CVAR_SEC(hook, damage));
- //W_DecreaseAmmo(WEP_CVAR_SEC(hook, ammo)); // WEAPONTODO: Figure out how to handle ammo with hook secondary (gravitybomb)
- W_SetupShot(self, false, 4, W_Sound("hookbomb_fire"), CH_WEAPON_A, WEP_CVAR_SEC(hook, damage));
-
- gren = spawn();
- gren.owner = gren.realowner = self;
- gren.classname = "hookbomb";
+ entity gren = new(hookbomb);
+ gren.owner = gren.realowner = actor;
gren.bot_dodge = true;
gren.bot_dodgerating = WEP_CVAR_SEC(hook, damage);
gren.movetype = MOVETYPE_TOSS;
gren.missile_flags = MIF_SPLASH | MIF_ARC;
gren.velocity = '0 0 1' * WEP_CVAR_SEC(hook, speed);
- if(autocvar_g_projectiles_newton_style)
- gren.velocity = gren.velocity + self.velocity;
+ if (autocvar_g_projectiles_newton_style)
+ gren.velocity = gren.velocity + actor.velocity;
gren.gravity = WEP_CVAR_SEC(hook, gravity);
//W_SetupProjVelocity_Basic(gren); // just falling down!
CSQCProjectile(gren, true, PROJECTILE_HOOKBOMB, true);
- MUTATOR_CALLHOOK(EditProjectile, self, gren);
+ MUTATOR_CALLHOOK(EditProjectile, actor, gren);
}
-bool W_Hook(int req)
-{
- float hooked_time_max, hooked_fuel;
-
- switch(req)
- {
- case WR_AIM:
- {
- // no bot AI for hook (yet?)
- return true;
- }
- case WR_THINK:
+ METHOD(Hook, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
{
- if(self.BUTTON_ATCK || self.BUTTON_HOOK)
- {
- if(!self.hook)
- if(!(self.hook_state & HOOK_WAITING_FOR_RELEASE))
- if(!(self.hook_state & HOOK_FIRING))
- if(time > self.hook_refire)
- if(weapon_prepareattack(0, -1))
+ if (fire1) {
+ if(!actor.hook)
+ if(!(actor.hook_state & HOOK_WAITING_FOR_RELEASE))
+ if(time > actor.hook_refire)
+ if(weapon_prepareattack(thiswep, actor, false, -1))
{
- W_DecreaseAmmo(WEP_CVAR_PRI(hook, ammo));
- self.hook_state |= HOOK_FIRING;
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(hook, animtime), w_ready);
+ W_DecreaseAmmo(thiswep, actor, thiswep.ammo_factor * WEP_CVAR_PRI(hook, ammo));
+ actor.hook_state |= HOOK_FIRING;
+ actor.hook_state |= HOOK_WAITING_FOR_RELEASE;
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(hook, animtime), w_ready);
}
+ } else {
+ actor.hook_state |= HOOK_REMOVING;
+ actor.hook_state &= ~HOOK_WAITING_FOR_RELEASE;
}
- if(self.BUTTON_ATCK2)
+ if(fire2)
{
- if(weapon_prepareattack(1, WEP_CVAR_SEC(hook, refire)))
+ if(weapon_prepareattack(thiswep, actor, true, WEP_CVAR_SEC(hook, refire)))
{
- W_Hook_Attack2();
- weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(hook, animtime), w_ready);
+ W_Hook_Attack2(thiswep, actor);
+ weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR_SEC(hook, animtime), w_ready);
}
}
- if(self.hook)
+ if(actor.hook)
{
// if hooked, no bombs, and increase the timer
- self.hook_refire = max(self.hook_refire, time + WEP_CVAR_PRI(hook, refire) * W_WeaponRateFactor());
+ actor.hook_refire = max(actor.hook_refire, time + WEP_CVAR_PRI(hook, refire) * W_WeaponRateFactor());
// hook also inhibits health regeneration, but only for 1 second
- if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
- self.pauseregen_finished = max(self.pauseregen_finished, time + autocvar_g_balance_pause_fuel_regen);
+ if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+ actor.pauseregen_finished = max(actor.pauseregen_finished, time + autocvar_g_balance_pause_fuel_regen);
}
- if(self.hook && self.hook.state == 1)
+ if(actor.hook && actor.hook.state == 1)
{
- hooked_time_max = WEP_CVAR_PRI(hook, hooked_time_max);
+ float hooked_time_max = WEP_CVAR_PRI(hook, hooked_time_max);
if(hooked_time_max > 0)
{
- if( time > self.hook_time_hooked + hooked_time_max )
- self.hook_state |= HOOK_REMOVING;
+ if( time > actor.hook_time_hooked + hooked_time_max )
+ actor.hook_state |= HOOK_REMOVING;
}
- hooked_fuel = WEP_CVAR_PRI(hook, hooked_ammo);
+ float hooked_fuel = thiswep.ammo_factor * WEP_CVAR_PRI(hook, hooked_ammo);
if(hooked_fuel > 0)
{
- if( time > self.hook_time_fueldecrease )
+ if( time > actor.hook_time_fueldecrease )
{
- if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+ if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
- if( self.ammo_fuel >= (time - self.hook_time_fueldecrease) * hooked_fuel )
+ if( actor.ammo_fuel >= (time - actor.hook_time_fueldecrease) * hooked_fuel )
{
- W_DecreaseAmmo((time - self.hook_time_fueldecrease) * hooked_fuel);
- self.hook_time_fueldecrease = time;
+ W_DecreaseAmmo(thiswep, actor, (time - actor.hook_time_fueldecrease) * hooked_fuel);
+ actor.hook_time_fueldecrease = time;
// decrease next frame again
}
else
{
- self.ammo_fuel = 0;
- self.hook_state |= HOOK_REMOVING;
- W_SwitchWeapon_Force(self, w_getbestweapon(self));
+ actor.ammo_fuel = 0;
+ actor.hook_state |= HOOK_REMOVING;
+ W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
}
}
}
}
else
{
- self.hook_time_hooked = time;
- self.hook_time_fueldecrease = time + WEP_CVAR_PRI(hook, hooked_time_free);
+ actor.hook_time_hooked = time;
+ actor.hook_time_fueldecrease = time + WEP_CVAR_PRI(hook, hooked_time_free);
}
- if(self.BUTTON_CROUCH)
+ actor.hook_state = BITSET(actor.hook_state, HOOK_PULLING, (!actor.BUTTON_CROUCH || !autocvar_g_balance_grapplehook_crouchslide));
+
+ if (actor.hook_state & HOOK_FIRING)
{
- self.hook_state &= ~HOOK_PULLING;
- if(self.BUTTON_ATCK || self.BUTTON_HOOK)
- self.hook_state &= ~HOOK_RELEASING;
- else
- self.hook_state |= HOOK_RELEASING;
+ if (actor.hook)
+ RemoveGrapplingHook(actor);
+ WITH(entity, self, actor, FireGrapplingHook());
+ actor.hook_state &= ~HOOK_FIRING;
+ actor.hook_refire = max(actor.hook_refire, time + autocvar_g_balance_grapplehook_refire * W_WeaponRateFactor());
}
- else
+ else if (actor.hook_state & HOOK_REMOVING)
{
- self.hook_state |= HOOK_PULLING;
- self.hook_state &= ~HOOK_RELEASING;
-
- if(self.BUTTON_ATCK || self.BUTTON_HOOK)
- {
- // already fired
- if(self.hook)
- self.hook_state |= HOOK_WAITING_FOR_RELEASE;
- }
- else
- {
- self.hook_state |= HOOK_REMOVING;
- self.hook_state &= ~HOOK_WAITING_FOR_RELEASE;
- }
+ if (actor.hook)
+ RemoveGrapplingHook(actor);
+ actor.hook_state &= ~HOOK_REMOVING;
}
-
- return true;
}
- case WR_INIT:
+ METHOD(Hook, wr_init, void(entity thiswep))
{
- precache_model(W_Model("g_hookgun.md3"));
- precache_model(W_Model("v_hookgun.md3"));
- precache_model(W_Model("h_hookgun.iqm"));
- precache_sound(W_Sound("hook_impact")); // done by g_hook.qc
- precache_sound(W_Sound("hook_fire"));
- precache_sound(W_Sound("hookbomb_fire"));
HOOK_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
- return true;
}
- case WR_SETUP:
+ METHOD(Hook, wr_setup, void(entity thiswep))
{
self.hook_state &= ~HOOK_WAITING_FOR_RELEASE;
- return true;
}
- case WR_CHECKAMMO1:
+ METHOD(Hook, wr_checkammo1, bool(Hook thiswep))
{
+ if (!thiswep.ammo_factor) return true;
if(self.hook)
return self.ammo_fuel > 0;
else
return self.ammo_fuel >= WEP_CVAR_PRI(hook, ammo);
}
- case WR_CHECKAMMO2:
+ METHOD(Hook, wr_checkammo2, bool(Hook thiswep))
{
// infinite ammo for now
return true; // self.ammo_cells >= WEP_CVAR_SEC(hook, ammo); // WEAPONTODO: see above
}
- case WR_CONFIG:
+ METHOD(Hook, wr_config, void(entity thiswep))
{
HOOK_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
- return true;
}
- case WR_RESETPLAYER:
+ METHOD(Hook, wr_resetplayer, void(entity thiswep))
{
self.hook_refire = time;
- return true;
}
- case WR_SUICIDEMESSAGE:
+ METHOD(Hook, wr_suicidemessage, int(entity thiswep))
{
return false;
}
- case WR_KILLMESSAGE:
+ METHOD(Hook, wr_killmessage, int(entity thiswep))
{
return WEAPON_HOOK_MURDER;
}
- }
- return false;
-}
+
#endif
#ifdef CSQC
-bool W_Hook(int req)
-{
- switch(req)
- {
- case WR_IMPACTEFFECT:
+
+ METHOD(Hook, wr_impacteffect, void(entity thiswep))
{
vector org2;
org2 = w_org + w_backoff * 2;
pointparticles(particleeffectnum(EFFECT_HOOK_EXPLODE), org2, '0 0 0', 1);
if(!w_issilent)
- sound(self, CH_SHOTS, W_Sound("hookbomb_impact"), VOL_BASE, ATTN_NORM);
-
- return true;
+ sound(self, CH_SHOTS, SND_HOOKBOMB_IMPACT, VOL_BASE, ATTN_NORM);
}
- case WR_INIT:
- {
- precache_sound(W_Sound("hookbomb_impact"));
- return true;
- }
- case WR_ZOOMRETICLE:
- {
- // no weapon specific image for this weapon
- return false;
- }
- }
- return false;
-}
+
#endif
#endif
#ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id */ MACHINEGUN,
-/* function */ W_MachineGun,
-/* ammotype */ ammo_nails,
-/* impulse */ 3,
-/* flags */ WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN,
-/* rating */ BOT_PICKUP_RATING_MID,
-/* color */ '1 1 0',
-/* modelname */ "uzi",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairuzi 0.6",
-/* wepimg */ "weaponuzi",
-/* refname */ "machinegun",
-/* wepname */ _("Machine Gun")
-);
+CLASS(MachineGun, Weapon)
+/* ammotype */ ATTRIB(MachineGun, ammo_field, .int, ammo_nails)
+/* impulse */ ATTRIB(MachineGun, impulse, int, 3)
+/* flags */ ATTRIB(MachineGun, spawnflags, int, WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN);
+/* rating */ ATTRIB(MachineGun, bot_pickupbasevalue, float, BOT_PICKUP_RATING_MID);
+/* color */ ATTRIB(MachineGun, wpcolor, vector, '1 1 0');
+/* modelname */ ATTRIB(MachineGun, mdl, string, "uzi");
+#ifndef MENUQC
+/* model */ ATTRIB(MachineGun, m_model, Model, MDL_MACHINEGUN_ITEM);
+#endif
+/* crosshair */ ATTRIB(MachineGun, w_crosshair, string, "gfx/crosshairuzi");
+/* crosshair */ ATTRIB(MachineGun, w_crosshair_size, float, 0.6);
+/* wepimg */ ATTRIB(MachineGun, model2, string, "weaponuzi");
+/* refname */ ATTRIB(MachineGun, netname, string, "machinegun");
+/* wepname */ ATTRIB(MachineGun, message, string, _("MachineGun"));
+ENDCLASS(MachineGun)
+REGISTER_WEAPON(MACHINEGUN, NEW(MachineGun));
#define MACHINEGUN_SETTINGS(w_cvar,w_prop) MACHINEGUN_SETTINGS_LIST(w_cvar, w_prop, MACHINEGUN, machinegun)
#define MACHINEGUN_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
#ifdef IMPLEMENTATION
#ifdef SVQC
-void spawnfunc_weapon_machinegun(void)
+spawnfunc(weapon_machinegun)
{
if(autocvar_sv_q3acompat_machineshotgunswap)
if(self.classname != "droppedweapon")
}
weapon_defaultspawnfunc(WEP_MACHINEGUN.m_id);
}
-void spawnfunc_weapon_uzi(void) { spawnfunc_weapon_machinegun(); }
+spawnfunc(weapon_uzi) { spawnfunc_weapon_machinegun(this); }
void W_MachineGun_MuzzleFlash_Think(void)
-{
+{SELFPARAM();
self.frame = self.frame + 2;
self.scale = self.scale * 0.5;
self.alpha = self.alpha - 0.25;
}
void W_MachineGun_MuzzleFlash(void)
-{
+{SELFPARAM();
if(self.muzzle_flash == world)
self.muzzle_flash = spawn();
// muzzle flash for 1st person view
- setmodel(self.muzzle_flash, "models/uziflash.md3"); // precision set below
+ setmodel(self.muzzle_flash, MDL_MACHINEGUN_MUZZLEFLASH); // precision set below
self.muzzle_flash.scale = 0.75;
self.muzzle_flash.think = W_MachineGun_MuzzleFlash_Think;
self.muzzle_flash.owner = self.muzzle_flash.realowner = self;
}
-void W_MachineGun_Attack(int deathtype)
-{
- W_SetupShot(self, true, 0, W_Sound("uzi_fire"), CH_WEAPON_A, ((self.misc_bulletcounter == 1) ? WEP_CVAR(machinegun, first_damage) : WEP_CVAR(machinegun, sustained_damage)));
+void W_MachineGun_Attack(Weapon thiswep, int deathtype)
+{SELFPARAM();
+ W_SetupShot(self, true, 0, SND(UZI_FIRE), CH_WEAPON_A, ((self.misc_bulletcounter == 1) ? WEP_CVAR(machinegun, first_damage) : WEP_CVAR(machinegun, sustained_damage)));
if(!autocvar_g_norecoil)
{
self.punchangle_x = random() - 0.5;
Send_Effect(EFFECT_MACHINEGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
W_MachineGun_MuzzleFlash();
- W_AttachToShotorg(self.muzzle_flash, '5 0 0');
+ W_AttachToShotorg(self, self.muzzle_flash, '5 0 0');
// casing code
if(autocvar_g_casings >= 2)
SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self);
if(self.misc_bulletcounter == 1)
- W_DecreaseAmmo(WEP_CVAR(machinegun, first_ammo));
+ W_DecreaseAmmo(thiswep, self, WEP_CVAR(machinegun, first_ammo));
else
- W_DecreaseAmmo(WEP_CVAR(machinegun, sustained_ammo));
+ W_DecreaseAmmo(thiswep, self, WEP_CVAR(machinegun, sustained_ammo));
}
// weapon frames
-void W_MachineGun_Attack_Frame(void)
+void W_MachineGun_Attack_Frame(Weapon thiswep, entity actor, bool fire1, bool fire2)
{
- if(self.weapon != self.switchweapon) // abort immediately if switching
+ if(actor.weapon != actor.switchweapon) // abort immediately if switching
{
- w_ready();
+ w_ready(thiswep, actor, fire1, fire2);
return;
}
- if(self.BUTTON_ATCK)
+ if(actor.BUTTON_ATCK)
{
- if(!WEP_ACTION(self.weapon, WR_CHECKAMMO2))
- if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+ Weapon w = get_weaponinfo(actor.weapon);
+ if(!w.wr_checkammo2(w))
+ if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
- W_SwitchWeapon_Force(self, w_getbestweapon(self));
- w_ready();
+ W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+ w_ready(thiswep, actor, fire1, fire2);
return;
}
- self.misc_bulletcounter = self.misc_bulletcounter + 1;
- W_MachineGun_Attack(WEP_MACHINEGUN.m_id);
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), W_MachineGun_Attack_Frame);
+ actor.misc_bulletcounter = actor.misc_bulletcounter + 1;
+ W_MachineGun_Attack(WEP_MACHINEGUN, WEP_MACHINEGUN.m_id);
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), W_MachineGun_Attack_Frame);
}
else
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), w_ready);
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), w_ready);
}
-void W_MachineGun_Attack_Auto(void)
+void W_MachineGun_Attack_Auto(Weapon thiswep, entity actor, bool fire1, bool fire2)
{
float machinegun_spread;
- if(!self.BUTTON_ATCK)
+ if(!fire1)
{
- w_ready();
+ w_ready(thiswep, actor, fire1, fire2);
return;
}
- if(!WEP_ACTION(self.weapon, WR_CHECKAMMO1))
- if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+ Weapon w = get_weaponinfo(actor.weapon);
+ if(!w.wr_checkammo1(w))
+ if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
- W_SwitchWeapon_Force(self, w_getbestweapon(self));
- w_ready();
+ W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+ w_ready(thiswep, actor, fire1, fire2);
return;
}
- W_DecreaseAmmo(WEP_CVAR(machinegun, sustained_ammo));
+ W_DecreaseAmmo(WEP_MACHINEGUN, actor, WEP_CVAR(machinegun, sustained_ammo));
- W_SetupShot(self, true, 0, W_Sound("uzi_fire"), CH_WEAPON_A, WEP_CVAR(machinegun, sustained_damage));
+ W_SetupShot(actor, true, 0, SND(UZI_FIRE), CH_WEAPON_A, WEP_CVAR(machinegun, sustained_damage));
if(!autocvar_g_norecoil)
{
- self.punchangle_x = random() - 0.5;
- self.punchangle_y = random() - 0.5;
+ actor.punchangle_x = random() - 0.5;
+ actor.punchangle_y = random() - 0.5;
}
- machinegun_spread = bound(WEP_CVAR(machinegun, spread_min), WEP_CVAR(machinegun, spread_min) + (WEP_CVAR(machinegun, spread_add) * self.misc_bulletcounter), WEP_CVAR(machinegun, spread_max));
+ machinegun_spread = bound(WEP_CVAR(machinegun, spread_min), WEP_CVAR(machinegun, spread_min) + (WEP_CVAR(machinegun, spread_add) * actor.misc_bulletcounter), WEP_CVAR(machinegun, spread_max));
fireBullet(w_shotorg, w_shotdir, machinegun_spread, WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), WEP_MACHINEGUN.m_id, 0);
- self.misc_bulletcounter = self.misc_bulletcounter + 1;
+ actor.misc_bulletcounter = actor.misc_bulletcounter + 1;
Send_Effect(EFFECT_MACHINEGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
W_MachineGun_MuzzleFlash();
- W_AttachToShotorg(self.muzzle_flash, '5 0 0');
+ W_AttachToShotorg(actor, actor.muzzle_flash, '5 0 0');
if(autocvar_g_casings >= 2) // casing code
- SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self);
+ SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, actor);
- ATTACK_FINISHED(self) = time + WEP_CVAR(machinegun, first_refire) * W_WeaponRateFactor();
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), W_MachineGun_Attack_Auto);
+ ATTACK_FINISHED(actor) = time + WEP_CVAR(machinegun, first_refire) * W_WeaponRateFactor();
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), W_MachineGun_Attack_Auto);
}
-void W_MachineGun_Attack_Burst(void)
+void W_MachineGun_Attack_Burst(Weapon thiswep, entity actor, bool fire1, bool fire2)
{
- W_SetupShot(self, true, 0, W_Sound("uzi_fire"), CH_WEAPON_A, WEP_CVAR(machinegun, sustained_damage));
+ W_SetupShot(actor, true, 0, SND(UZI_FIRE), CH_WEAPON_A, WEP_CVAR(machinegun, sustained_damage));
if(!autocvar_g_norecoil)
{
- self.punchangle_x = random() - 0.5;
- self.punchangle_y = random() - 0.5;
+ actor.punchangle_x = random() - 0.5;
+ actor.punchangle_y = random() - 0.5;
}
fireBullet(w_shotorg, w_shotdir, WEP_CVAR(machinegun, burst_speed), WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), WEP_MACHINEGUN.m_id, 0);
Send_Effect(EFFECT_MACHINEGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
W_MachineGun_MuzzleFlash();
- W_AttachToShotorg(self.muzzle_flash, '5 0 0');
+ W_AttachToShotorg(actor, actor.muzzle_flash, '5 0 0');
if(autocvar_g_casings >= 2) // casing code
- SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self);
+ SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, actor);
- self.misc_bulletcounter = self.misc_bulletcounter + 1;
- if(self.misc_bulletcounter == 0)
+ actor.misc_bulletcounter = actor.misc_bulletcounter + 1;
+ if(actor.misc_bulletcounter == 0)
{
- ATTACK_FINISHED(self) = time + WEP_CVAR(machinegun, burst_refire2) * W_WeaponRateFactor();
- weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(machinegun, burst_animtime), w_ready);
+ ATTACK_FINISHED(actor) = time + WEP_CVAR(machinegun, burst_refire2) * W_WeaponRateFactor();
+ weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR(machinegun, burst_animtime), w_ready);
}
else
{
- weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(machinegun, burst_refire), W_MachineGun_Attack_Burst);
+ weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR(machinegun, burst_refire), W_MachineGun_Attack_Burst);
}
}
-bool W_MachineGun(int req)
-{
- float ammo_amount;
- switch(req)
- {
- case WR_AIM:
+ METHOD(MachineGun, wr_aim, void(entity thiswep))
{
if(vlen(self.origin-self.enemy.origin) < 3000 - bound(0, skill, 10) * 200)
self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, false);
else
self.BUTTON_ATCK2 = bot_aim(1000000, 0, 0.001, false);
-
- return true;
}
- case WR_THINK:
+ METHOD(MachineGun, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
{
- if(WEP_CVAR(machinegun, reload_ammo) && self.clip_load < min(max(WEP_CVAR(machinegun, sustained_ammo), WEP_CVAR(machinegun, first_ammo)), WEP_CVAR(machinegun, burst_ammo))) // forced reload
- WEP_ACTION(self.weapon, WR_RELOAD);
- else if(WEP_CVAR(machinegun, mode) == 1)
+ if(WEP_CVAR(machinegun, reload_ammo) && actor.clip_load < min(max(WEP_CVAR(machinegun, sustained_ammo), WEP_CVAR(machinegun, first_ammo)), WEP_CVAR(machinegun, burst_ammo))) { // forced reload
+ Weapon w = get_weaponinfo(actor.weapon);
+ w.wr_reload(w);
+ } else
+ if(WEP_CVAR(machinegun, mode) == 1)
{
- if(self.BUTTON_ATCK)
- if(weapon_prepareattack(0, 0))
+ if(fire1)
+ if(weapon_prepareattack(thiswep, actor, false, 0))
{
- self.misc_bulletcounter = 0;
- W_MachineGun_Attack_Auto();
+ actor.misc_bulletcounter = 0;
+ W_MachineGun_Attack_Auto(thiswep, actor, fire1, fire2);
}
- if(self.BUTTON_ATCK2)
- if(weapon_prepareattack(1, 0))
+ if(fire2)
+ if(weapon_prepareattack(thiswep, actor, true, 0))
{
- if(!WEP_ACTION(self.weapon, WR_CHECKAMMO2))
- if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+ Weapon w = get_weaponinfo(actor.weapon);
+ if(!w.wr_checkammo2(w))
+ if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
- W_SwitchWeapon_Force(self, w_getbestweapon(self));
- w_ready();
- return false;
+ W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+ w_ready(thiswep, actor, fire1, fire2);
+ return;
}
- W_DecreaseAmmo(WEP_CVAR(machinegun, burst_ammo));
+ W_DecreaseAmmo(thiswep, actor, WEP_CVAR(machinegun, burst_ammo));
- self.misc_bulletcounter = WEP_CVAR(machinegun, burst) * -1;
- W_MachineGun_Attack_Burst();
+ actor.misc_bulletcounter = WEP_CVAR(machinegun, burst) * -1;
+ W_MachineGun_Attack_Burst(thiswep, actor, fire1, fire2);
}
}
else
{
- if(self.BUTTON_ATCK)
- if(weapon_prepareattack(0, 0))
+ if(fire1)
+ if(weapon_prepareattack(thiswep, actor, false, 0))
{
- self.misc_bulletcounter = 1;
- W_MachineGun_Attack(WEP_MACHINEGUN.m_id); // sets attack_finished
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), W_MachineGun_Attack_Frame);
+ actor.misc_bulletcounter = 1;
+ W_MachineGun_Attack(WEP_MACHINEGUN, WEP_MACHINEGUN.m_id); // sets attack_finished
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), W_MachineGun_Attack_Frame);
}
- if(self.BUTTON_ATCK2 && WEP_CVAR(machinegun, first))
- if(weapon_prepareattack(1, 0))
+ if(fire2 && WEP_CVAR(machinegun, first))
+ if(weapon_prepareattack(thiswep, actor, true, 0))
{
- self.misc_bulletcounter = 1;
- W_MachineGun_Attack(WEP_MACHINEGUN.m_id | HITTYPE_SECONDARY); // sets attack_finished
- weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(machinegun, first_refire), w_ready);
+ actor.misc_bulletcounter = 1;
+ W_MachineGun_Attack(WEP_MACHINEGUN, WEP_MACHINEGUN.m_id | HITTYPE_SECONDARY); // sets attack_finished
+ weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR(machinegun, first_refire), w_ready);
}
}
-
- return true;
}
- case WR_INIT:
+ METHOD(MachineGun, wr_init, void(entity thiswep))
{
- precache_model("models/uziflash.md3");
- precache_model(W_Model("g_uzi.md3"));
- precache_model(W_Model("v_uzi.md3"));
- precache_model(W_Model("h_uzi.iqm"));
- precache_sound(W_Sound("uzi_fire"));
MACHINEGUN_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
- return true;
}
- case WR_CHECKAMMO1:
+ METHOD(MachineGun, wr_checkammo1, bool(entity thiswep))
{
+ float ammo_amount;
if(WEP_CVAR(machinegun, mode) == 1)
ammo_amount = self.WEP_AMMO(MACHINEGUN) >= WEP_CVAR(machinegun, sustained_ammo);
else
}
return ammo_amount;
}
- case WR_CHECKAMMO2:
+ METHOD(MachineGun, wr_checkammo2, bool(entity thiswep))
{
+ float ammo_amount;
if(WEP_CVAR(machinegun, mode) == 1)
ammo_amount = self.WEP_AMMO(MACHINEGUN) >= WEP_CVAR(machinegun, burst_ammo);
else
}
return ammo_amount;
}
- case WR_CONFIG:
+ METHOD(MachineGun, wr_config, void(entity thiswep))
{
MACHINEGUN_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
- return true;
}
- case WR_RELOAD:
+ METHOD(MachineGun, wr_reload, void(entity thiswep))
{
- W_Reload(min(max(WEP_CVAR(machinegun, sustained_ammo), WEP_CVAR(machinegun, first_ammo)), WEP_CVAR(machinegun, burst_ammo)), W_Sound("reload"));
- return true;
+ W_Reload(self, min(max(WEP_CVAR(machinegun, sustained_ammo), WEP_CVAR(machinegun, first_ammo)), WEP_CVAR(machinegun, burst_ammo)), SND(RELOAD));
}
- case WR_SUICIDEMESSAGE:
+ METHOD(MachineGun, wr_suicidemessage, int(entity thiswep))
{
return WEAPON_THINKING_WITH_PORTALS;
}
- case WR_KILLMESSAGE:
+ METHOD(MachineGun, wr_killmessage, int(entity thiswep))
{
if(w_deathtype & HITTYPE_SECONDARY)
return WEAPON_MACHINEGUN_MURDER_SNIPE;
else
return WEAPON_MACHINEGUN_MURDER_SPRAY;
}
- }
- return false;
-}
+
#endif
#ifdef CSQC
-bool W_MachineGun(int req)
-{
- switch(req)
- {
- case WR_IMPACTEFFECT:
+
+ METHOD(MachineGun, wr_impacteffect, void(entity thiswep))
{
vector org2;
org2 = w_org + w_backoff * 2;
pointparticles(particleeffectnum(EFFECT_MACHINEGUN_IMPACT), org2, w_backoff * 1000, 1);
if(!w_issilent)
if(w_random < 0.05)
- sound(self, CH_SHOTS, W_Sound("ric1"), VOL_BASE, ATTN_NORM);
+ sound(self, CH_SHOTS, SND_RIC1, VOL_BASE, ATTN_NORM);
else if(w_random < 0.1)
- sound(self, CH_SHOTS, W_Sound("ric2"), VOL_BASE, ATTN_NORM);
+ sound(self, CH_SHOTS, SND_RIC2, VOL_BASE, ATTN_NORM);
else if(w_random < 0.2)
- sound(self, CH_SHOTS, W_Sound("ric3"), VOL_BASE, ATTN_NORM);
-
- return true;
+ sound(self, CH_SHOTS, SND_RIC3, VOL_BASE, ATTN_NORM);
}
- case WR_INIT:
- {
- precache_sound(W_Sound("ric1"));
- precache_sound(W_Sound("ric2"));
- precache_sound(W_Sound("ric3"));
- return true;
- }
- case WR_ZOOMRETICLE:
- {
- // no weapon specific image for this weapon
- return false;
- }
- }
- return false;
-}
+
#endif
#endif
#ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id */ MINE_LAYER,
-/* function */ W_MineLayer,
-/* ammotype */ ammo_rockets,
-/* impulse */ 4,
-/* flags */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH,
-/* rating */ BOT_PICKUP_RATING_HIGH,
-/* color */ '0.75 1 0',
-/* modelname */ "minelayer",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairminelayer 0.9",
-/* wepimg */ "weaponminelayer",
-/* refname */ "minelayer",
-/* wepname */ _("Mine Layer")
-);
+CLASS(MineLayer, Weapon)
+/* ammotype */ ATTRIB(MineLayer, ammo_field, .int, ammo_rockets)
+/* impulse */ ATTRIB(MineLayer, impulse, int, 4)
+/* flags */ ATTRIB(MineLayer, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH);
+/* rating */ ATTRIB(MineLayer, bot_pickupbasevalue, float, BOT_PICKUP_RATING_HIGH);
+/* color */ ATTRIB(MineLayer, wpcolor, vector, '0.75 1 0');
+/* modelname */ ATTRIB(MineLayer, mdl, string, "minelayer");
+#ifndef MENUQC
+/* model */ ATTRIB(MineLayer, m_model, Model, MDL_MINELAYER_ITEM);
+#endif
+/* crosshair */ ATTRIB(MineLayer, w_crosshair, string, "gfx/crosshairminelayer");
+/* crosshair */ ATTRIB(MineLayer, w_crosshair_size, float, 0.9);
+/* wepimg */ ATTRIB(MineLayer, model2, string, "weaponminelayer");
+/* refname */ ATTRIB(MineLayer, netname, string, "minelayer");
+/* wepname */ ATTRIB(MineLayer, message, string, _("Mine Layer"));
+ENDCLASS(MineLayer)
+REGISTER_WEAPON(MINE_LAYER, NEW(MineLayer));
#define MINELAYER_SETTINGS(w_cvar,w_prop) MINELAYER_SETTINGS_LIST(w_cvar, w_prop, MINE_LAYER, minelayer)
#define MINELAYER_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
#endif
#ifdef IMPLEMENTATION
#ifdef SVQC
-void spawnfunc_weapon_minelayer(void) { weapon_defaultspawnfunc(WEP_MINE_LAYER.m_id); }
+spawnfunc(weapon_minelayer) { weapon_defaultspawnfunc(WEP_MINE_LAYER.m_id); }
void W_MineLayer_Stick(entity to)
-{
- spamsound(self, CH_SHOTS, W_Sound("mine_stick"), VOL_BASE, ATTN_NORM);
+{SELFPARAM();
+ spamsound(self, CH_SHOTS, SND(MINE_STICK), VOL_BASE, ATTN_NORM);
// in order for mines to face properly when sticking to the ground, they must be a server side entity rather than a csqc projectile
newmine.realowner = self.realowner;
setsize(newmine, '-4 -4 -4', '4 4 4');
setorigin(newmine, self.origin);
- setmodel(newmine, "models/mine.md3");
+ setmodel(newmine, MDL_MINELAYER_MINE);
newmine.angles = vectoangles(-trace_plane_normal); // face against the surface
newmine.mine_orientation = -trace_plane_normal;
newmine.flags = self.flags;
remove(self);
- self = newmine;
+ setself(newmine);
if(to)
SetMovetypeFollow(self, to);
}
void W_MineLayer_Explode(void)
-{
+{SELFPARAM();
if(other.takedamage == DAMAGE_AIM)
if(IS_PLAYER(other))
if(DIFF_TEAM(self.realowner, other))
if(self.realowner.weapon == WEP_MINE_LAYER.m_id)
{
- entity oldself;
- oldself = self;
- self = self.realowner;
- if(!WEP_ACTION(WEP_MINE_LAYER.m_id, WR_CHECKAMMO1))
+ setself(self.realowner);
+ Weapon w = WEP_MINE_LAYER;
+ if(!w.wr_checkammo1(w))
{
self.cnt = WEP_MINE_LAYER.m_id;
ATTACK_FINISHED(self) = time;
self.switchweapon = w_getbestweapon(self);
}
- self = oldself;
+ setself(this);
}
self.realowner.minelayer_mines -= 1;
remove(self);
}
void W_MineLayer_DoRemoteExplode(void)
-{
+{SELFPARAM();
self.event_damage = func_null;
self.takedamage = DAMAGE_NO;
if(self.realowner.weapon == WEP_MINE_LAYER.m_id)
{
- entity oldself;
- oldself = self;
- self = self.realowner;
- if(!WEP_ACTION(WEP_MINE_LAYER.m_id, WR_CHECKAMMO1))
+ setself(self.realowner);
+ Weapon w = WEP_MINE_LAYER;
+ if(!w.wr_checkammo1(w))
{
self.cnt = WEP_MINE_LAYER.m_id;
ATTACK_FINISHED(self) = time;
self.switchweapon = w_getbestweapon(self);
}
- self = oldself;
+ setself(this);
}
self.realowner.minelayer_mines -= 1;
remove(self);
}
void W_MineLayer_RemoteExplode(void)
-{
+{SELFPARAM();
if(self.realowner.deadflag == DEAD_NO)
if((self.spawnshieldtime >= 0)
? (time >= self.spawnshieldtime) // timer
}
void W_MineLayer_ProximityExplode(void)
-{
+{SELFPARAM();
// make sure no friend is in the mine's radius. If there is any, explosion is delayed until he's at a safe distance
if(WEP_CVAR(minelayer, protection) && self.mine_explodeanyway == 0)
{
}
void W_MineLayer_Think(void)
-{
+{SELFPARAM();
entity head;
self.nextthink = time;
if((time > self.cnt) && (!self.mine_time) && (self.cnt > 0))
{
if(WEP_CVAR(minelayer, lifetime_countdown) > 0)
- spamsound(self, CH_SHOTS, W_Sound("mine_trigger"), VOL_BASE, ATTN_NORM);
+ spamsound(self, CH_SHOTS, SND(MINE_TRIGGER), VOL_BASE, ATTN_NORM);
self.mine_time = time + WEP_CVAR(minelayer, lifetime_countdown);
self.mine_explodeanyway = 1; // make the mine super aggressive -- Samual: Rather, make it not care if a team mate is near.
}
if(head != self.realowner && DIFF_TEAM(head, self.realowner)) // don't trigger for team mates
if(!self.mine_time)
{
- spamsound(self, CH_SHOTS, W_Sound("mine_trigger"), VOL_BASE, ATTN_NORM);
+ spamsound(self, CH_SHOTS, SND(MINE_TRIGGER), VOL_BASE, ATTN_NORM);
self.mine_time = time + WEP_CVAR(minelayer, time);
}
head = head.chain;
}
void W_MineLayer_Touch(void)
-{
+{SELFPARAM();
if(self.movetype == MOVETYPE_NONE || self.movetype == MOVETYPE_FOLLOW)
return; // we're already a stuck mine, why do we get called? TODO does this even happen?
}
void W_MineLayer_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
if(self.health <= 0)
return;
W_PrepareExplosionByDamage(attacker, W_MineLayer_Explode);
}
-void W_MineLayer_Attack(void)
-{
+void W_MineLayer_Attack(Weapon thiswep)
+{SELFPARAM();
entity mine;
entity flash;
{
// the refire delay keeps this message from being spammed
Send_Notification(NOTIF_ONE, self, MSG_MULTI, WEAPON_MINELAYER_LIMIT, WEP_CVAR(minelayer, limit));
- play2(self, W_Sound("unavailable"));
+ play2(self, SND(UNAVAILABLE));
return;
}
}
- W_DecreaseAmmo(WEP_CVAR(minelayer, ammo));
+ W_DecreaseAmmo(thiswep, self, WEP_CVAR(minelayer, ammo));
- W_SetupShot_ProjectileSize(self, '-4 -4 -4', '4 4 4', false, 5, W_Sound("mine_fire"), CH_WEAPON_A, WEP_CVAR(minelayer, damage));
+ W_SetupShot_ProjectileSize(self, '-4 -4 -4', '4 4 4', false, 5, SND(MINE_FIRE), CH_WEAPON_A, WEP_CVAR(minelayer, damage));
Send_Effect(EFFECT_ROCKET_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
mine = WarpZone_RefSys_SpawnSameRefSys(self);
// muzzle flash for 1st person view
flash = spawn();
- setmodel(flash, "models/flash.md3"); // precision set below
+ setmodel(flash, MDL_MINELAYER_MUZZLEFLASH); // precision set below
SUB_SetFade(flash, time, 0.1);
flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
- W_AttachToShotorg(flash, '5 0 0');
+ W_AttachToShotorg(self, flash, '5 0 0');
// common properties
}
float W_MineLayer_PlacedMines(float detonate)
-{
+{SELFPARAM();
entity mine;
float minfound = 0;
return minfound;
}
-bool W_MineLayer(int req)
-{
- entity mine;
- float ammo_amount;
- switch(req)
- {
- case WR_AIM:
+ METHOD(MineLayer, wr_aim, void(entity thiswep))
{
// aim and decide to fire if appropriate
if(self.minelayer_mines >= WEP_CVAR(minelayer, limit))
teamdamage = 0;
enemydamage = 0;
targetlist = findchainfloat(bot_attack, true);
- mine = find(world, classname, "mine");
+ entity mine = find(world, classname, "mine");
while(mine)
{
if(mine.realowner != self)
// dprint(ftos(desirabledamage),"\n");
if(self.BUTTON_ATCK2 == true) self.BUTTON_ATCK = false;
}
-
- return true;
}
- case WR_THINK:
+ METHOD(MineLayer, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
{
- if(autocvar_g_balance_minelayer_reload_ammo && self.clip_load < WEP_CVAR(minelayer, ammo)) // forced reload
+ if(autocvar_g_balance_minelayer_reload_ammo && actor.clip_load < WEP_CVAR(minelayer, ammo)) // forced reload
{
// not if we're holding the minelayer without enough ammo, but can detonate existing mines
- if(!(W_MineLayer_PlacedMines(false) && self.WEP_AMMO(MINE_LAYER) < WEP_CVAR(minelayer, ammo)))
- WEP_ACTION(self.weapon, WR_RELOAD);
+ if(!(W_MineLayer_PlacedMines(false) && actor.WEP_AMMO(MINE_LAYER) < WEP_CVAR(minelayer, ammo))) {
+ Weapon w = get_weaponinfo(actor.weapon);
+ w.wr_reload(w);
+ }
}
- else if(self.BUTTON_ATCK)
+ else if(fire1)
{
- if(weapon_prepareattack(0, WEP_CVAR(minelayer, refire)))
+ if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR(minelayer, refire)))
{
- W_MineLayer_Attack();
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(minelayer, animtime), w_ready);
+ W_MineLayer_Attack(thiswep);
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR(minelayer, animtime), w_ready);
}
}
- if(self.BUTTON_ATCK2)
+ if(fire2)
{
if(W_MineLayer_PlacedMines(true))
- sound(self, CH_WEAPON_B, W_Sound("mine_det"), VOL_BASE, ATTN_NORM);
+ sound(actor, CH_WEAPON_B, SND_MINE_DET, VOL_BASE, ATTN_NORM);
}
-
- return true;
}
- case WR_INIT:
+ METHOD(MineLayer, wr_init, void(entity thiswep))
{
- precache_model("models/flash.md3");
- precache_model("models/mine.md3");
- precache_model(W_Model("g_minelayer.md3"));
- precache_model(W_Model("v_minelayer.md3"));
- precache_model(W_Model("h_minelayer.iqm"));
- precache_sound(W_Sound("mine_det"));
- precache_sound(W_Sound("mine_fire"));
- precache_sound(W_Sound("mine_stick"));
- precache_sound(W_Sound("mine_trigger"));
MINELAYER_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
- return true;
}
- case WR_CHECKAMMO1:
+ METHOD(MineLayer, wr_checkammo1, bool(entity thiswep))
{
// don't switch while placing a mine
if(ATTACK_FINISHED(self) <= time || self.weapon != WEP_MINE_LAYER.m_id)
{
- ammo_amount = self.WEP_AMMO(MINE_LAYER) >= WEP_CVAR(minelayer, ammo);
+ float ammo_amount = self.WEP_AMMO(MINE_LAYER) >= WEP_CVAR(minelayer, ammo);
ammo_amount += self.(weapon_load[WEP_MINE_LAYER.m_id]) >= WEP_CVAR(minelayer, ammo);
return ammo_amount;
}
return true;
}
- case WR_CHECKAMMO2:
+ METHOD(MineLayer, wr_checkammo2, bool(entity thiswep))
{
if(W_MineLayer_PlacedMines(false))
return true;
else
return false;
}
- case WR_CONFIG:
+ METHOD(MineLayer, wr_config, void(entity thiswep))
{
MINELAYER_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
- return true;
}
- case WR_RESETPLAYER:
+ METHOD(MineLayer, wr_resetplayers, void(entity thiswep))
{
self.minelayer_mines = 0;
- return true;
}
- case WR_RELOAD:
+ METHOD(MineLayer, wr_reload, void(entity thiswep))
{
- W_Reload(WEP_CVAR(minelayer, ammo), W_Sound("reload"));
- return true;
+ W_Reload(self, WEP_CVAR(minelayer, ammo), SND(RELOAD));
}
- case WR_SUICIDEMESSAGE:
+ METHOD(MineLayer, wr_suicidemessage, int(entity thiswep))
{
return WEAPON_MINELAYER_SUICIDE;
}
- case WR_KILLMESSAGE:
+ METHOD(MineLayer, wr_killmessage, int(entity thiswep))
{
return WEAPON_MINELAYER_MURDER;
}
- }
- return false;
-}
+
#endif
#ifdef CSQC
-bool W_MineLayer(int req)
-{
- switch(req)
- {
- case WR_IMPACTEFFECT:
+
+ METHOD(MineLayer, wr_impacteffect, void(entity thiswep))
{
vector org2;
org2 = w_org + w_backoff * 12;
pointparticles(particleeffectnum(EFFECT_ROCKET_EXPLODE), org2, '0 0 0', 1);
if(!w_issilent)
- sound(self, CH_SHOTS, W_Sound("mine_exp"), VOL_BASE, ATTN_NORM);
-
- return true;
- }
- case WR_INIT:
- {
- precache_sound(W_Sound("mine_exp"));
- return true;
+ sound(self, CH_SHOTS, SND_MINE_EXP, VOL_BASE, ATTN_NORM);
}
- case WR_ZOOMRETICLE:
- {
- // no weapon specific image for this weapon
- return false;
- }
- }
- return false;
-}
+
#endif
#endif
#ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id */ MORTAR,
-/* function */ W_Mortar,
-/* ammotype */ ammo_rockets,
-/* impulse */ 4,
-/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH,
-/* rating */ BOT_PICKUP_RATING_MID,
-/* color */ '1 0 0',
-/* modelname */ "gl",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairgrenadelauncher 0.7",
-/* wepimg */ "weapongrenadelauncher",
-/* refname */ "mortar",
-/* wepname */ _("Mortar")
-);
+CLASS(Mortar, Weapon)
+/* ammotype */ ATTRIB(Mortar, ammo_field, .int, ammo_rockets)
+/* impulse */ ATTRIB(Mortar, impulse, int, 4)
+/* flags */ ATTRIB(Mortar, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH);
+/* rating */ ATTRIB(Mortar, bot_pickupbasevalue, float, BOT_PICKUP_RATING_MID);
+/* color */ ATTRIB(Mortar, wpcolor, vector, '1 0 0');
+/* modelname */ ATTRIB(Mortar, mdl, string, "gl");
+#ifndef MENUQC
+/* model */ ATTRIB(Mortar, m_model, Model, MDL_MORTAR_ITEM);
+#endif
+/* crosshair */ ATTRIB(Mortar, w_crosshair, string, "gfx/crosshairgrenadelauncher");
+/* crosshair */ ATTRIB(Mortar, w_crosshair_size, float, 0.7);
+/* wepimg */ ATTRIB(Mortar, model2, string, "weapongrenadelauncher");
+/* refname */ ATTRIB(Mortar, netname, string, "mortar");
+/* wepname */ ATTRIB(Mortar, message, string, _("Mortar"));
+ENDCLASS(Mortar)
+REGISTER_WEAPON(MORTAR, NEW(Mortar));
#define MORTAR_SETTINGS(w_cvar,w_prop) MORTAR_SETTINGS_LIST(w_cvar, w_prop, MORTAR, mortar)
#define MORTAR_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
#ifdef IMPLEMENTATION
#ifdef SVQC
-void spawnfunc_weapon_mortar(void) { weapon_defaultspawnfunc(WEP_MORTAR.m_id); }
-void spawnfunc_weapon_grenadelauncher(void) { spawnfunc_weapon_mortar(); }
+spawnfunc(weapon_mortar) { weapon_defaultspawnfunc(WEP_MORTAR.m_id); }
+spawnfunc(weapon_grenadelauncher) { spawnfunc_weapon_mortar(this); }
void W_Mortar_Grenade_Explode(void)
-{
+{SELFPARAM();
if(other.takedamage == DAMAGE_AIM)
if(IS_PLAYER(other))
if(DIFF_TEAM(self.realowner, other))
}
void W_Mortar_Grenade_Explode2(void)
-{
+{SELFPARAM();
if(other.takedamage == DAMAGE_AIM)
if(IS_PLAYER(other))
if(DIFF_TEAM(self.realowner, other))
void W_Mortar_Grenade_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
if(self.health <= 0)
return;
}
void W_Mortar_Grenade_Think1(void)
-{
+{SELFPARAM();
self.nextthink = time;
if(time > self.cnt)
{
}
void W_Mortar_Grenade_Touch1(void)
-{
+{SELFPARAM();
PROJECTILE_TOUCH;
if(other.takedamage == DAMAGE_AIM || WEP_CVAR_PRI(mortar, type) == 0) // always explode when hitting a player, or if normal mortar projectile
{
}
else if(WEP_CVAR_PRI(mortar, type) == 1) // bounce
{
- float r;
- r = random() * 6;
- if(r < 1)
- spamsound(self, CH_SHOTS, W_Sound("grenade_bounce1"), VOL_BASE, ATTN_NORM);
- else if(r < 2)
- spamsound(self, CH_SHOTS, W_Sound("grenade_bounce2"), VOL_BASE, ATTN_NORM);
- else if(r < 3)
- spamsound(self, CH_SHOTS, W_Sound("grenade_bounce3"), VOL_BASE, ATTN_NORM);
- else if(r < 4)
- spamsound(self, CH_SHOTS, W_Sound("grenade_bounce4"), VOL_BASE, ATTN_NORM);
- else if(r < 5)
- spamsound(self, CH_SHOTS, W_Sound("grenade_bounce5"), VOL_BASE, ATTN_NORM);
- else
- spamsound(self, CH_SHOTS, W_Sound("grenade_bounce6"), VOL_BASE, ATTN_NORM);
+ spamsound(self, CH_SHOTS, SND(GRENADE_BOUNCE_RANDOM()), VOL_BASE, ATTN_NORM);
Send_Effect(EFFECT_HAGAR_BOUNCE, self.origin, self.velocity, 1);
self.projectiledeathtype |= HITTYPE_BOUNCE;
self.gl_bouncecnt += 1;
}
else if(WEP_CVAR_PRI(mortar, type) == 2 && (!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE))) // stick
{
- spamsound(self, CH_SHOTS, W_Sound("grenade_stick"), VOL_BASE, ATTN_NORM);
+ spamsound(self, CH_SHOTS, SND(GRENADE_STICK), VOL_BASE, ATTN_NORM);
// let it stick whereever it is
self.oldvelocity = self.velocity;
}
void W_Mortar_Grenade_Touch2(void)
-{
+{SELFPARAM();
PROJECTILE_TOUCH;
if(other.takedamage == DAMAGE_AIM || WEP_CVAR_SEC(mortar, type) == 0) // always explode when hitting a player, or if normal mortar projectile
{
}
else if(WEP_CVAR_SEC(mortar, type) == 1) // bounce
{
- float r;
- r = random() * 6;
- if(r < 1)
- spamsound(self, CH_SHOTS, W_Sound("grenade_bounce1"), VOL_BASE, ATTN_NORM);
- else if(r < 2)
- spamsound(self, CH_SHOTS, W_Sound("grenade_bounce2"), VOL_BASE, ATTN_NORM);
- else if(r < 3)
- spamsound(self, CH_SHOTS, W_Sound("grenade_bounce3"), VOL_BASE, ATTN_NORM);
- else if(r < 4)
- spamsound(self, CH_SHOTS, W_Sound("grenade_bounce4"), VOL_BASE, ATTN_NORM);
- else if(r < 5)
- spamsound(self, CH_SHOTS, W_Sound("grenade_bounce5"), VOL_BASE, ATTN_NORM);
- else
- spamsound(self, CH_SHOTS, W_Sound("grenade_bounce6"), VOL_BASE, ATTN_NORM);
+ spamsound(self, CH_SHOTS, SND(GRENADE_BOUNCE_RANDOM()), VOL_BASE, ATTN_NORM);
Send_Effect(EFFECT_HAGAR_BOUNCE, self.origin, self.velocity, 1);
self.projectiledeathtype |= HITTYPE_BOUNCE;
self.gl_bouncecnt += 1;
}
else if(WEP_CVAR_SEC(mortar, type) == 2 && (!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE))) // stick
{
- spamsound(self, CH_SHOTS, W_Sound("grenade_stick"), VOL_BASE, ATTN_NORM);
+ spamsound(self, CH_SHOTS, SND(GRENADE_STICK), VOL_BASE, ATTN_NORM);
// let it stick whereever it is
self.oldvelocity = self.velocity;
}
}
-void W_Mortar_Attack(void)
-{
+void W_Mortar_Attack(Weapon thiswep)
+{SELFPARAM();
entity gren;
- W_DecreaseAmmo(WEP_CVAR_PRI(mortar, ammo));
+ W_DecreaseAmmo(thiswep, self, WEP_CVAR_PRI(mortar, ammo));
- W_SetupShot_ProjectileSize(self, '-3 -3 -3', '3 3 3', false, 4, W_Sound("grenade_fire"), CH_WEAPON_A, WEP_CVAR_PRI(mortar, damage));
+ W_SetupShot_ProjectileSize(self, '-3 -3 -3', '3 3 3', false, 4, SND(GRENADE_FIRE), CH_WEAPON_A, WEP_CVAR_PRI(mortar, damage));
w_shotdir = v_forward; // no TrueAim for grenades please
Send_Effect(EFFECT_GRENADE_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
MUTATOR_CALLHOOK(EditProjectile, self, gren);
}
-void W_Mortar_Attack2(void)
-{
+void W_Mortar_Attack2(Weapon thiswep)
+{SELFPARAM();
entity gren;
- W_DecreaseAmmo(WEP_CVAR_SEC(mortar, ammo));
+ W_DecreaseAmmo(thiswep, self, WEP_CVAR_SEC(mortar, ammo));
- W_SetupShot_ProjectileSize(self, '-3 -3 -3', '3 3 3', false, 4, W_Sound("grenade_fire"), CH_WEAPON_A, WEP_CVAR_SEC(mortar, damage));
+ W_SetupShot_ProjectileSize(self, '-3 -3 -3', '3 3 3', false, 4, SND(GRENADE_FIRE), CH_WEAPON_A, WEP_CVAR_SEC(mortar, damage));
w_shotdir = v_forward; // no TrueAim for grenades please
Send_Effect(EFFECT_GRENADE_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
}
.float bot_secondary_grenademooth;
-bool W_Mortar(int req)
-{
- entity nade;
- float nadefound;
- float ammo_amount;
- switch(req)
- {
- case WR_AIM:
+
+ METHOD(Mortar, wr_aim, void(entity thiswep))
{
self.BUTTON_ATCK = false;
self.BUTTON_ATCK2 = false;
if(random() < 0.02) self.bot_secondary_grenademooth = 0;
}
}
-
- return true;
}
/*case WR_CALCINFO:
{
wepinfo_sec_dps = (WEP_CVAR_SEC(mortar, damage) * (1 / max3(sys_frametime, WEP_CVAR_SEC(mortar, refire), WEP_CVAR_SEC(mortar, animtime))));
wepinfo_ter_dps = 0;
*/
- case WR_THINK:
+ METHOD(Mortar, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
{
- if(autocvar_g_balance_mortar_reload_ammo && self.clip_load < min(WEP_CVAR_PRI(mortar, ammo), WEP_CVAR_SEC(mortar, ammo))) // forced reload
- WEP_ACTION(self.weapon, WR_RELOAD);
- else if(self.BUTTON_ATCK)
+ if(autocvar_g_balance_mortar_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(mortar, ammo), WEP_CVAR_SEC(mortar, ammo))) { // forced reload
+ Weapon w = get_weaponinfo(actor.weapon);
+ w.wr_reload(w);
+ } else if(fire1)
{
- if(weapon_prepareattack(0, WEP_CVAR_PRI(mortar, refire)))
+ if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(mortar, refire)))
{
- W_Mortar_Attack();
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(mortar, animtime), w_ready);
+ W_Mortar_Attack(thiswep);
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(mortar, animtime), w_ready);
}
}
- else if(self.BUTTON_ATCK2)
+ else if(fire2)
{
if(WEP_CVAR_SEC(mortar, remote_detonateprimary))
{
- nadefound = 0;
- for(nade = world; (nade = find(nade, classname, "grenade")); ) if(nade.realowner == self)
+ bool nadefound = false;
+ entity nade;
+ for(nade = world; (nade = find(nade, classname, "grenade")); ) if(nade.realowner == actor)
{
if(!nade.gl_detonate_later)
{
nade.gl_detonate_later = true;
- nadefound = 1;
+ nadefound = true;
}
}
if(nadefound)
- sound(self, CH_WEAPON_B, W_Sound("rocket_det"), VOL_BASE, ATTN_NORM);
+ sound(actor, CH_WEAPON_B, SND_ROCKET_DET, VOL_BASE, ATTN_NORM);
}
- else if(weapon_prepareattack(1, WEP_CVAR_SEC(mortar, refire)))
+ else if(weapon_prepareattack(thiswep, actor, true, WEP_CVAR_SEC(mortar, refire)))
{
- W_Mortar_Attack2();
- weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(mortar, animtime), w_ready);
+ W_Mortar_Attack2(thiswep);
+ weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR_SEC(mortar, animtime), w_ready);
}
}
-
- return true;
}
- case WR_INIT:
+ METHOD(Mortar, wr_init, void(entity thiswep))
{
- precache_model(W_Model("g_gl.md3"));
- precache_model(W_Model("v_gl.md3"));
- precache_model(W_Model("h_gl.iqm"));
- precache_sound(W_Sound("grenade_bounce1"));
- precache_sound(W_Sound("grenade_bounce2"));
- precache_sound(W_Sound("grenade_bounce3"));
- precache_sound(W_Sound("grenade_bounce4"));
- precache_sound(W_Sound("grenade_bounce5"));
- precache_sound(W_Sound("grenade_bounce6"));
- precache_sound(W_Sound("grenade_stick"));
- precache_sound(W_Sound("grenade_fire"));
MORTAR_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
- return true;
}
- case WR_CHECKAMMO1:
+ METHOD(Mortar, wr_checkammo1, bool(entity thiswep))
{
- ammo_amount = self.WEP_AMMO(MORTAR) >= WEP_CVAR_PRI(mortar, ammo);
+ float ammo_amount = self.WEP_AMMO(MORTAR) >= WEP_CVAR_PRI(mortar, ammo);
ammo_amount += self.(weapon_load[WEP_MORTAR.m_id]) >= WEP_CVAR_PRI(mortar, ammo);
return ammo_amount;
}
- case WR_CHECKAMMO2:
+ METHOD(Mortar, wr_checkammo2, bool(entity thiswep))
{
- ammo_amount = self.WEP_AMMO(MORTAR) >= WEP_CVAR_SEC(mortar, ammo);
+ float ammo_amount = self.WEP_AMMO(MORTAR) >= WEP_CVAR_SEC(mortar, ammo);
ammo_amount += self.(weapon_load[WEP_MORTAR.m_id]) >= WEP_CVAR_SEC(mortar, ammo);
return ammo_amount;
}
- case WR_CONFIG:
+ METHOD(Mortar, wr_config, void(entity thiswep))
{
MORTAR_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
- return true;
}
- case WR_RELOAD:
+ METHOD(Mortar, wr_reload, void(entity thiswep))
{
- W_Reload(min(WEP_CVAR_PRI(mortar, ammo), WEP_CVAR_SEC(mortar, ammo)), W_Sound("reload")); // WEAPONTODO
- return true;
+ W_Reload(self, min(WEP_CVAR_PRI(mortar, ammo), WEP_CVAR_SEC(mortar, ammo)), SND(RELOAD)); // WEAPONTODO
}
- case WR_SUICIDEMESSAGE:
+ METHOD(Mortar, wr_suicidemessage, int(entity thiswep))
{
if(w_deathtype & HITTYPE_SECONDARY)
return WEAPON_MORTAR_SUICIDE_BOUNCE;
else
return WEAPON_MORTAR_SUICIDE_EXPLODE;
}
- case WR_KILLMESSAGE:
+ METHOD(Mortar, wr_killmessage, int(entity thiswep))
{
if(w_deathtype & HITTYPE_SECONDARY)
return WEAPON_MORTAR_MURDER_BOUNCE;
else
return WEAPON_MORTAR_MURDER_EXPLODE;
}
- }
- return false;
-}
+
#endif
#ifdef CSQC
-bool W_Mortar(int req)
-{
- switch(req)
- {
- case WR_IMPACTEFFECT:
+
+ METHOD(Mortar, wr_impacteffect, void(entity thiswep))
{
vector org2;
org2 = w_org + w_backoff * 12;
pointparticles(particleeffectnum(EFFECT_GRENADE_EXPLODE), org2, '0 0 0', 1);
if(!w_issilent)
- sound(self, CH_SHOTS, W_Sound("grenade_impact"), VOL_BASE, ATTN_NORM);
-
- return true;
+ sound(self, CH_SHOTS, SND_GRENADE_IMPACT, VOL_BASE, ATTN_NORM);
}
- case WR_INIT:
- {
- precache_sound(W_Sound("grenade_impact"));
- return true;
- }
- case WR_ZOOMRETICLE:
- {
- // no weapon specific image for this weapon
- return false;
- }
- }
- return false;
-}
+
#endif
#endif
#ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id */ PORTO,
-/* function */ W_Porto,
-/* ammotype */ ammo_none,
-/* impulse */ 0,
-/* flags */ WEP_TYPE_OTHER | WEP_FLAG_SUPERWEAPON,
-/* rating */ 0,
-/* color */ '0.5 0.5 0.5',
-/* modelname */ "porto",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairporto 0.6",
-/* wepimg */ "weaponporto",
-/* refname */ "porto",
-/* wepname */ _("Port-O-Launch")
-);
+CLASS(PortoLaunch, Weapon)
+/* ammotype */ ATTRIB(PortoLaunch, ammo_field, .int, ammo_none)
+/* impulse */ ATTRIB(PortoLaunch, impulse, int, 0)
+/* flags */ ATTRIB(PortoLaunch, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_SUPERWEAPON);
+/* rating */ ATTRIB(PortoLaunch, bot_pickupbasevalue, float, 0);
+/* color */ ATTRIB(PortoLaunch, wpcolor, vector, '0.5 0.5 0.5');
+/* modelname */ ATTRIB(PortoLaunch, mdl, string, "porto");
+#ifndef MENUQC
+/* model */ ATTRIB(PortoLaunch, m_model, Model, MDL_PORTO_ITEM);
+#endif
+/* crosshair */ ATTRIB(PortoLaunch, w_crosshair, string, "gfx/crosshairporto");
+/* crosshair */ ATTRIB(PortoLaunch, w_crosshair_size, float, 0.6);
+/* wepimg */ ATTRIB(PortoLaunch, model2, string, "weaponporto");
+/* refname */ ATTRIB(PortoLaunch, netname, string, "porto");
+/* wepname */ ATTRIB(PortoLaunch, message, string, _("Port-O-Launch"));
+ENDCLASS(PortoLaunch)
+REGISTER_WEAPON(PORTO, NEW(PortoLaunch));
#define PORTO_SETTINGS(w_cvar,w_prop) PORTO_SETTINGS_LIST(w_cvar, w_prop, PORTO, porto)
#define PORTO_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
#endif
#ifdef IMPLEMENTATION
#ifdef SVQC
-#include "../triggers/trigger/jumppads.qh"
+#include "../../triggers/trigger/jumppads.qh"
-void spawnfunc_weapon_porto(void) { weapon_defaultspawnfunc(WEP_PORTO.m_id); }
+spawnfunc(weapon_porto) { weapon_defaultspawnfunc(WEP_PORTO.m_id); }
void W_Porto_Success(void)
-{
+{SELFPARAM();
if(self.realowner == world)
{
objerror("Cannot succeed successfully: no owner\n");
string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo);
void W_Porto_Fail(float failhard)
-{
+{SELFPARAM();
if(self.realowner == world)
{
objerror("Cannot fail successfully: no owner\n");
self.realowner.porto_current = world;
- if(self.cnt < 0 && !failhard && self.realowner.playerid == self.playerid && self.realowner.deadflag == DEAD_NO && !(self.realowner.weapons & WEPSET_PORTO))
+ if(self.cnt < 0 && !failhard && self.realowner.playerid == self.playerid && self.realowner.deadflag == DEAD_NO && !(self.realowner.weapons & WEPSET(PORTO)))
{
setsize(self, '-16 -16 0', '16 16 32');
setorigin(self, self.origin + trace_plane_normal);
}
void W_Porto_Remove(entity p)
-{
+{SELFPARAM();
if(p.porto_current.realowner == p && p.porto_current.classname == "porto")
{
- entity oldself;
- oldself = self;
- self = p.porto_current;
- W_Porto_Fail(1);
- self = oldself;
+ WITH(entity, self, p.porto_current, W_Porto_Fail(1));
}
}
void W_Porto_Think(void)
-{
+{SELFPARAM();
trace_plane_normal = '0 0 0';
if(self.realowner.playerid != self.playerid)
remove(self);
}
void W_Porto_Touch(void)
-{
+{SELFPARAM();
vector norm;
// do not use PROJECTILE_TOUCH here
if(self.realowner.playerid != self.playerid)
{
- sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_PORTO_UNSUPPORTED, VOL_BASE, ATTEN_NORM);
remove(self);
}
else if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP)
{
- spamsound(self, CH_SHOTS, "porto/bounce.wav", VOL_BASE, ATTEN_NORM);
+ spamsound(self, CH_SHOTS, SND(PORTO_BOUNCE), VOL_BASE, ATTEN_NORM);
// just reflect
self.right_vector = self.right_vector - 2 * trace_plane_normal * (self.right_vector * trace_plane_normal);
self.angles = vectoangles(self.velocity - 2 * trace_plane_normal * (self.velocity * trace_plane_normal));
}
else if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
{
- sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_PORTO_UNSUPPORTED, VOL_BASE, ATTEN_NORM);
W_Porto_Fail(0);
if(self.cnt < 0)
Portal_ClearAll_PortalsOnly(self.realowner);
// in-portal only
if(Portal_SpawnInPortalAtTrace(self.realowner, self.right_vector, self.portal_id))
{
- sound(self, CH_SHOTS, "porto/create.wav", VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_PORTO_CREATE, VOL_BASE, ATTEN_NORM);
trace_plane_normal = norm;
Send_Notification(NOTIF_ONE, self.realowner, MSG_CENTER, CENTER_PORTO_CREATED_IN);
W_Porto_Success();
}
else
{
- sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_PORTO_UNSUPPORTED, VOL_BASE, ATTEN_NORM);
trace_plane_normal = norm;
W_Porto_Fail(0);
}
// out-portal only
if(Portal_SpawnOutPortalAtTrace(self.realowner, self.right_vector, self.portal_id))
{
- sound(self, CH_SHOTS, "porto/create.wav", VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_PORTO_CREATE, VOL_BASE, ATTEN_NORM);
trace_plane_normal = norm;
Send_Notification(NOTIF_ONE, self.realowner, MSG_CENTER, CENTER_PORTO_CREATED_OUT);
W_Porto_Success();
}
else
{
- sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_PORTO_UNSUPPORTED, VOL_BASE, ATTEN_NORM);
trace_plane_normal = norm;
W_Porto_Fail(0);
}
self.effects += EF_BLUE - EF_RED;
if(Portal_SpawnInPortalAtTrace(self.realowner, self.right_vector, self.portal_id))
{
- sound(self, CH_SHOTS, "porto/create.wav", VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_PORTO_CREATE, VOL_BASE, ATTEN_NORM);
trace_plane_normal = norm;
Send_Notification(NOTIF_ONE, self.realowner, MSG_CENTER, CENTER_PORTO_CREATED_IN);
self.right_vector = self.right_vector - 2 * trace_plane_normal * (self.right_vector * norm);
}
else
{
- sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_PORTO_UNSUPPORTED, VOL_BASE, ATTEN_NORM);
trace_plane_normal = norm;
Portal_ClearAll_PortalsOnly(self.realowner);
W_Porto_Fail(0);
{
if(Portal_SpawnOutPortalAtTrace(self.realowner, self.right_vector, self.portal_id))
{
- sound(self, CH_SHOTS, "porto/create.wav", VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_PORTO_CREATE, VOL_BASE, ATTEN_NORM);
trace_plane_normal = norm;
Send_Notification(NOTIF_ONE, self.realowner, MSG_CENTER, CENTER_PORTO_CREATED_OUT);
W_Porto_Success();
}
else
{
- sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_PORTO_UNSUPPORTED, VOL_BASE, ATTEN_NORM);
Portal_ClearAll_PortalsOnly(self.realowner);
W_Porto_Fail(0);
}
}
else
{
- sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_PORTO_UNSUPPORTED, VOL_BASE, ATTEN_NORM);
Portal_ClearAll_PortalsOnly(self.realowner);
W_Porto_Fail(0);
}
}
void W_Porto_Attack(float type)
-{
+{SELFPARAM();
entity gren;
- W_SetupShot(self, false, 4, "porto/fire.wav", CH_WEAPON_A, 0);
+ W_SetupShot(self, false, 4, SND(PORTO_FIRE), CH_WEAPON_A, 0);
// always shoot from the eye
w_shotdir = v_forward;
w_shotorg = self.origin + self.view_ofs + ((w_shotorg - self.origin - self.view_ofs) * v_forward) * v_forward;
MUTATOR_CALLHOOK(EditProjectile, self, gren);
}
-bool w_nexball_weapon(int req); // WEAPONTODO
-bool W_Porto(int req)
-{
- //vector v_angle_save;
-
- if(g_nexball) { return w_nexball_weapon(req); }
-
- switch(req)
- {
- case WR_AIM:
+ METHOD(PortoLaunch, wr_aim, void(entity thiswep))
{
+ SELFPARAM();
self.BUTTON_ATCK = false;
self.BUTTON_ATCK2 = false;
if(!WEP_CVAR(porto, secondary))
if(bot_aim(WEP_CVAR_PRI(porto, speed), 0, WEP_CVAR_PRI(porto, lifetime), false))
self.BUTTON_ATCK = true;
-
- return true;
}
- case WR_CONFIG:
+ METHOD(PortoLaunch, wr_config, void(entity this))
{
PORTO_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
- return true;
}
- case WR_THINK:
+ METHOD(PortoLaunch, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
{
if(WEP_CVAR(porto, secondary))
{
- if(self.BUTTON_ATCK)
- if(!self.porto_current)
- if(!self.porto_forbidden)
- if(weapon_prepareattack(0, WEP_CVAR_PRI(porto, refire)))
+ if(fire1)
+ if(!actor.porto_current)
+ if(!actor.porto_forbidden)
+ if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(porto, refire)))
{
W_Porto_Attack(0);
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(porto, animtime), w_ready);
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(porto, animtime), w_ready);
}
- if(self.BUTTON_ATCK2)
- if(!self.porto_current)
- if(!self.porto_forbidden)
- if(weapon_prepareattack(1, WEP_CVAR_SEC(porto, refire)))
+ if(fire2)
+ if(!actor.porto_current)
+ if(!actor.porto_forbidden)
+ if(weapon_prepareattack(thiswep, actor, true, WEP_CVAR_SEC(porto, refire)))
{
W_Porto_Attack(1);
- weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(porto, animtime), w_ready);
+ weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR_SEC(porto, animtime), w_ready);
}
}
else
{
- if(self.porto_v_angle_held)
+ if(actor.porto_v_angle_held)
{
- if(!self.BUTTON_ATCK2)
+ if(!fire2)
{
- self.porto_v_angle_held = 0;
+ actor.porto_v_angle_held = 0;
- ClientData_Touch(self);
+ ClientData_Touch(actor);
}
}
else
{
- if(self.BUTTON_ATCK2)
+ if(fire2)
{
- self.porto_v_angle = self.v_angle;
- self.porto_v_angle_held = 1;
+ actor.porto_v_angle = actor.v_angle;
+ actor.porto_v_angle_held = 1;
- ClientData_Touch(self);
+ ClientData_Touch(actor);
}
}
- if(self.porto_v_angle_held)
- makevectors(self.porto_v_angle); // override the previously set angles
+ if(actor.porto_v_angle_held)
+ makevectors(actor.porto_v_angle); // override the previously set angles
- if(self.BUTTON_ATCK)
- if(!self.porto_current)
- if(!self.porto_forbidden)
- if(weapon_prepareattack(0, WEP_CVAR_PRI(porto, refire)))
+ if(fire1)
+ if(!actor.porto_current)
+ if(!actor.porto_forbidden)
+ if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(porto, refire)))
{
W_Porto_Attack(-1);
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(porto, animtime), w_ready);
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(porto, animtime), w_ready);
}
}
-
+ }
+ METHOD(PortoLaunch, wr_checkammo1, bool(entity this))
+ {
+ // always allow infinite ammo
return true;
}
- case WR_CHECKAMMO1:
- case WR_CHECKAMMO2:
+ METHOD(PortoLaunch, wr_checkammo2, bool(entity this))
{
// always allow infinite ammo
return true;
}
- case WR_INIT:
+ METHOD(PortoLaunch, wr_init, void(entity this))
{
- precache_model(W_Model("g_porto.md3"));
- precache_model(W_Model("v_porto.md3"));
- precache_model(W_Model("h_porto.iqm"));
- precache_model("models/portal.md3");
- precache_sound("porto/bounce.wav");
- precache_sound("porto/create.wav");
- precache_sound("porto/expire.wav");
- precache_sound("porto/explode.wav");
- precache_sound("porto/fire.wav");
- precache_sound("porto/unsupported.wav");
PORTO_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
- return true;
}
- case WR_SETUP:
+ METHOD(PortoLaunch, wr_setup, void(entity thiswep))
{
+ SELFPARAM();
self.ammo_field = ammo_none;
- return true;
}
- case WR_RESETPLAYER:
+ METHOD(PortoLaunch, wr_resetplayer, void(entity thiswep))
{
+ SELFPARAM();
self.porto_current = world;
- return true;
}
- }
- return false;
-}
#endif
#ifdef CSQC
-bool W_Porto(int req)
-{
- switch(req)
- {
- case WR_IMPACTEFFECT:
- {
- LOG_INFO("Since when does Porto send DamageInfo?\n");
- return true;
+ METHOD(PortoLaunch, wr_impacteffect, void(entity this)) {
+ LOG_WARNING("Since when does Porto send DamageInfo?\n");
}
- case WR_INIT:
- {
- // nothing to do
- return true;
- }
- case WR_ZOOMRETICLE:
- {
- // no weapon specific image for this weapon
- return false;
- }
- }
- return false;
-}
#endif
#endif
#ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id */ RIFLE,
-/* function */ W_Rifle,
-/* ammotype */ ammo_nails,
-/* impulse */ 7,
-/* flags */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN,
-/* rating */ BOT_PICKUP_RATING_MID,
-/* color */ '0.5 1 0',
-/* modelname */ "campingrifle",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairrifle 0.6",
-/* wepimg */ "weaponrifle",
-/* refname */ "rifle",
-/* wepname */ _("Rifle")
-);
+CLASS(Rifle, Weapon)
+/* ammotype */ ATTRIB(Rifle, ammo_field, .int, ammo_nails)
+/* impulse */ ATTRIB(Rifle, impulse, int, 7)
+/* flags */ ATTRIB(Rifle, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN);
+/* rating */ ATTRIB(Rifle, bot_pickupbasevalue, float, BOT_PICKUP_RATING_MID);
+/* color */ ATTRIB(Rifle, wpcolor, vector, '0.5 1 0');
+/* modelname */ ATTRIB(Rifle, mdl, string, "campingrifle");
+#ifndef MENUQC
+/* model */ ATTRIB(Rifle, m_model, Model, MDL_RIFLE_ITEM);
+#endif
+/* crosshair */ ATTRIB(Rifle, w_crosshair, string, "gfx/crosshairrifle");
+/* crosshair */ ATTRIB(Rifle, w_crosshair_size, float, 0.6);
+/* wepimg */ ATTRIB(Rifle, model2, string, "weaponrifle");
+/* refname */ ATTRIB(Rifle, netname, string, "rifle");
+/* wepname */ ATTRIB(Rifle, message, string, _("Rifle"));
+ENDCLASS(Rifle)
+REGISTER_WEAPON(RIFLE, NEW(Rifle));
#define RIFLE_SETTINGS(w_cvar,w_prop) RIFLE_SETTINGS_LIST(w_cvar, w_prop, RIFLE, rifle)
#define RIFLE_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
#endif
#ifdef IMPLEMENTATION
#ifdef SVQC
-void spawnfunc_weapon_rifle(void) { weapon_defaultspawnfunc(WEP_RIFLE.m_id); }
-void spawnfunc_weapon_campingrifle(void) { spawnfunc_weapon_rifle(); }
-void spawnfunc_weapon_sniperrifle(void) { spawnfunc_weapon_rifle(); }
+spawnfunc(weapon_rifle) { weapon_defaultspawnfunc(WEP_RIFLE.m_id); }
+spawnfunc(weapon_campingrifle) { spawnfunc_weapon_rifle(this); }
+spawnfunc(weapon_sniperrifle) { spawnfunc_weapon_rifle(this); }
-void W_Rifle_FireBullet(float pSpread, float pDamage, float pForce, float pSolidPenetration, float pAmmo, int deathtype, float pTracer, float pShots, string pSound)
-{
+void W_Rifle_FireBullet(Weapon thiswep, float pSpread, float pDamage, float pForce, float pSolidPenetration, float pAmmo, int deathtype, float pTracer, float pShots, string pSound)
+{SELFPARAM();
float i;
- W_DecreaseAmmo(pAmmo);
+ W_DecreaseAmmo(thiswep, self, pAmmo);
W_SetupShot(self, true, 2, pSound, CH_WEAPON_A, pDamage * pShots);
void W_Rifle_Attack(void)
{
- W_Rifle_FireBullet(WEP_CVAR_PRI(rifle, spread), WEP_CVAR_PRI(rifle, damage), WEP_CVAR_PRI(rifle, force), WEP_CVAR_PRI(rifle, solidpenetration), WEP_CVAR_PRI(rifle, ammo), WEP_RIFLE.m_id, WEP_CVAR_PRI(rifle, tracer), WEP_CVAR_PRI(rifle, shots), W_Sound("campingrifle_fire"));
+ W_Rifle_FireBullet(WEP_RIFLE, WEP_CVAR_PRI(rifle, spread), WEP_CVAR_PRI(rifle, damage), WEP_CVAR_PRI(rifle, force), WEP_CVAR_PRI(rifle, solidpenetration), WEP_CVAR_PRI(rifle, ammo), WEP_RIFLE.m_id, WEP_CVAR_PRI(rifle, tracer), WEP_CVAR_PRI(rifle, shots), SND(CAMPINGRIFLE_FIRE));
}
void W_Rifle_Attack2(void)
{
- W_Rifle_FireBullet(WEP_CVAR_SEC(rifle, spread), WEP_CVAR_SEC(rifle, damage), WEP_CVAR_SEC(rifle, force), WEP_CVAR_SEC(rifle, solidpenetration), WEP_CVAR_SEC(rifle, ammo), WEP_RIFLE.m_id | HITTYPE_SECONDARY, WEP_CVAR_SEC(rifle, tracer), WEP_CVAR_SEC(rifle, shots), W_Sound("campingrifle_fire2"));
+ W_Rifle_FireBullet(WEP_RIFLE, WEP_CVAR_SEC(rifle, spread), WEP_CVAR_SEC(rifle, damage), WEP_CVAR_SEC(rifle, force), WEP_CVAR_SEC(rifle, solidpenetration), WEP_CVAR_SEC(rifle, ammo), WEP_RIFLE.m_id | HITTYPE_SECONDARY, WEP_CVAR_SEC(rifle, tracer), WEP_CVAR_SEC(rifle, shots), SND(CAMPINGRIFLE_FIRE2));
}
.void(void) rifle_bullethail_attackfunc;
.float rifle_bullethail_frame;
.float rifle_bullethail_animtime;
.float rifle_bullethail_refire;
-void W_Rifle_BulletHail_Continue(void)
+void W_Rifle_BulletHail_Continue(Weapon thiswep, entity actor, bool fire1, bool fire2)
{
float r, sw, af;
- sw = self.switchweapon; // make it not detect weapon changes as reason to abort firing
- af = ATTACK_FINISHED(self);
- self.switchweapon = self.weapon;
- ATTACK_FINISHED(self) = time;
- LOG_INFO(ftos(self.WEP_AMMO(RIFLE)), "\n");
- r = weapon_prepareattack(self.rifle_bullethail_frame == WFRAME_FIRE2, self.rifle_bullethail_refire);
- if(self.switchweapon == self.weapon)
- self.switchweapon = sw;
+ sw = actor.switchweapon; // make it not detect weapon changes as reason to abort firing
+ af = ATTACK_FINISHED(actor);
+ actor.switchweapon = actor.weapon;
+ ATTACK_FINISHED(actor) = time;
+ LOG_INFO(ftos(actor.WEP_AMMO(RIFLE)), "\n");
+ r = weapon_prepareattack(thiswep, actor, actor.rifle_bullethail_frame == WFRAME_FIRE2, actor.rifle_bullethail_refire);
+ if(actor.switchweapon == actor.weapon)
+ actor.switchweapon = sw;
if(r)
{
- self.rifle_bullethail_attackfunc();
- weapon_thinkf(self.rifle_bullethail_frame, self.rifle_bullethail_animtime, W_Rifle_BulletHail_Continue);
+ actor.rifle_bullethail_attackfunc();
+ weapon_thinkf(actor, actor.rifle_bullethail_frame, actor.rifle_bullethail_animtime, W_Rifle_BulletHail_Continue);
LOG_INFO("thinkf set\n");
}
else
{
- ATTACK_FINISHED(self) = af; // reset attack_finished if we didn't fire, so the last shot enforces the refire time
- LOG_INFO("out of ammo... ", ftos(self.weaponentity.state), "\n");
+ ATTACK_FINISHED(actor) = af; // reset attack_finished if we didn't fire, so the last shot enforces the refire time
+ LOG_INFO("out of ammo... ", ftos(actor.weaponentity.state), "\n");
}
}
void W_Rifle_BulletHail(float mode, void(void) AttackFunc, float fr, float animtime, float refire)
-{
+{SELFPARAM();
// if we get here, we have at least one bullet to fire
AttackFunc();
if(mode)
self.rifle_bullethail_frame = fr;
self.rifle_bullethail_animtime = animtime;
self.rifle_bullethail_refire = refire;
- weapon_thinkf(fr, animtime, W_Rifle_BulletHail_Continue);
+ weapon_thinkf(self, fr, animtime, W_Rifle_BulletHail_Continue);
}
else
{
// just one shot
- weapon_thinkf(fr, animtime, w_ready);
+ weapon_thinkf(self, fr, animtime, w_ready);
}
}
.float bot_secondary_riflemooth;
-bool W_Rifle(int req)
-{
- float ammo_amount;
- switch(req)
- {
- case WR_AIM:
+ METHOD(Rifle, wr_aim, void(entity thiswep))
{
self.BUTTON_ATCK=false;
self.BUTTON_ATCK2=false;
if(random() < 0.03) self.bot_secondary_riflemooth = 0;
}
}
-
- return true;
}
- case WR_THINK:
+ METHOD(Rifle, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
{
- if(autocvar_g_balance_rifle_reload_ammo && self.clip_load < min(WEP_CVAR_PRI(rifle, ammo), WEP_CVAR_SEC(rifle, ammo))) // forced reload
- WEP_ACTION(self.weapon, WR_RELOAD);
- else
+ if(autocvar_g_balance_rifle_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(rifle, ammo), WEP_CVAR_SEC(rifle, ammo))) { // forced reload
+ Weapon w = get_weaponinfo(actor.weapon);
+ w.wr_reload(w);
+ } else
{
- self.rifle_accumulator = bound(time - WEP_CVAR(rifle, bursttime), self.rifle_accumulator, time);
- if(self.BUTTON_ATCK)
- if(weapon_prepareattack_check(0, WEP_CVAR_PRI(rifle, refire)))
- if(time >= self.rifle_accumulator + WEP_CVAR_PRI(rifle, burstcost))
+ actor.rifle_accumulator = bound(time - WEP_CVAR(rifle, bursttime), actor.rifle_accumulator, time);
+ if(fire1)
+ if(weapon_prepareattack_check(thiswep, actor, false, WEP_CVAR_PRI(rifle, refire)))
+ if(time >= actor.rifle_accumulator + WEP_CVAR_PRI(rifle, burstcost))
{
- weapon_prepareattack_do(0, WEP_CVAR_PRI(rifle, refire));
+ weapon_prepareattack_do(actor, false, WEP_CVAR_PRI(rifle, refire));
W_Rifle_BulletHail(WEP_CVAR_PRI(rifle, bullethail), W_Rifle_Attack, WFRAME_FIRE1, WEP_CVAR_PRI(rifle, animtime), WEP_CVAR_PRI(rifle, refire));
- self.rifle_accumulator += WEP_CVAR_PRI(rifle, burstcost);
+ actor.rifle_accumulator += WEP_CVAR_PRI(rifle, burstcost);
}
- if(self.BUTTON_ATCK2)
+ if(fire2)
{
if(WEP_CVAR(rifle, secondary))
{
- if(WEP_CVAR_SEC(rifle, reload))
- WEP_ACTION(self.weapon, WR_RELOAD);
- else
+ if(WEP_CVAR_SEC(rifle, reload)) {
+ Weapon w = get_weaponinfo(actor.weapon);
+ w.wr_reload(w);
+ } else
{
- if(weapon_prepareattack_check(1, WEP_CVAR_SEC(rifle, refire)))
- if(time >= self.rifle_accumulator + WEP_CVAR_SEC(rifle, burstcost))
+ if(weapon_prepareattack_check(thiswep, actor, true, WEP_CVAR_SEC(rifle, refire)))
+ if(time >= actor.rifle_accumulator + WEP_CVAR_SEC(rifle, burstcost))
{
- weapon_prepareattack_do(1, WEP_CVAR_SEC(rifle, refire));
+ weapon_prepareattack_do(actor, true, WEP_CVAR_SEC(rifle, refire));
W_Rifle_BulletHail(WEP_CVAR_SEC(rifle, bullethail), W_Rifle_Attack2, WFRAME_FIRE2, WEP_CVAR_SEC(rifle, animtime), WEP_CVAR_PRI(rifle, refire));
- self.rifle_accumulator += WEP_CVAR_SEC(rifle, burstcost);
+ actor.rifle_accumulator += WEP_CVAR_SEC(rifle, burstcost);
}
}
}
}
}
-
- return true;
}
- case WR_INIT:
+ METHOD(Rifle, wr_init, void(entity thiswep))
{
- precache_model(W_Model("g_sniperrifle.md3"));
- precache_model(W_Model("v_sniperrifle.md3"));
- precache_model(W_Model("h_sniperrifle.iqm"));
- precache_sound(W_Sound("campingrifle_fire"));
- precache_sound(W_Sound("campingrifle_fire2"));
RIFLE_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
- return true;
}
- case WR_CHECKAMMO1:
+ METHOD(Rifle, wr_checkammo1, bool(entity thiswep))
{
- ammo_amount = self.WEP_AMMO(RIFLE) >= WEP_CVAR_PRI(rifle, ammo);
+ float ammo_amount = self.WEP_AMMO(RIFLE) >= WEP_CVAR_PRI(rifle, ammo);
ammo_amount += self.(weapon_load[WEP_RIFLE.m_id]) >= WEP_CVAR_PRI(rifle, ammo);
return ammo_amount;
}
- case WR_CHECKAMMO2:
+ METHOD(Rifle, wr_checkammo2, bool(entity thiswep))
{
- ammo_amount = self.WEP_AMMO(RIFLE) >= WEP_CVAR_SEC(rifle, ammo);
+ float ammo_amount = self.WEP_AMMO(RIFLE) >= WEP_CVAR_SEC(rifle, ammo);
ammo_amount += self.(weapon_load[WEP_RIFLE.m_id]) >= WEP_CVAR_SEC(rifle, ammo);
return ammo_amount;
}
- case WR_CONFIG:
+ METHOD(Rifle, wr_config, void(entity thiswep))
{
RIFLE_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
- return true;
}
- case WR_RESETPLAYER:
+ METHOD(Rifle, wr_resetplayer, void(entity thiswep))
{
self.rifle_accumulator = time - WEP_CVAR(rifle, bursttime);
- return true;
}
- case WR_RELOAD:
+ METHOD(Rifle, wr_reload, void(entity thiswep))
{
- W_Reload(min(WEP_CVAR_PRI(rifle, ammo), WEP_CVAR_SEC(rifle, ammo)), W_Sound("reload"));
- return true;
+ W_Reload(self, min(WEP_CVAR_PRI(rifle, ammo), WEP_CVAR_SEC(rifle, ammo)), SND(RELOAD));
}
- case WR_SUICIDEMESSAGE:
+ METHOD(Rifle, wr_suicidemessage, int(entity thiswep))
{
return WEAPON_THINKING_WITH_PORTALS;
}
- case WR_KILLMESSAGE:
+ METHOD(Rifle, wr_killmessage, int(entity thiswep))
{
if(w_deathtype & HITTYPE_SECONDARY)
{
return WEAPON_RIFLE_MURDER;
}
}
- }
- return false;
-}
+
#endif
#ifdef CSQC
-bool W_Rifle(int req)
-{
- switch(req)
- {
- case WR_IMPACTEFFECT:
+
+ METHOD(Rifle, wr_impacteffect, void(entity thiswep))
{
vector org2;
org2 = w_org + w_backoff * 2;
if(!w_issilent)
{
if(w_random < 0.2)
- sound(self, CH_SHOTS, W_Sound("ric1"), VOL_BASE, ATTN_NORM);
+ sound(self, CH_SHOTS, SND_RIC1, VOL_BASE, ATTN_NORM);
else if(w_random < 0.4)
- sound(self, CH_SHOTS, W_Sound("ric2"), VOL_BASE, ATTN_NORM);
+ sound(self, CH_SHOTS, SND_RIC2, VOL_BASE, ATTN_NORM);
else if(w_random < 0.5)
- sound(self, CH_SHOTS, W_Sound("ric3"), VOL_BASE, ATTN_NORM);
+ sound(self, CH_SHOTS, SND_RIC3, VOL_BASE, ATTN_NORM);
}
-
- return true;
}
- case WR_INIT:
+ METHOD(Rifle, wr_init, void(entity thiswep))
{
- precache_sound(W_Sound("ric1"));
- precache_sound(W_Sound("ric2"));
- precache_sound(W_Sound("ric3"));
if(autocvar_cl_reticle && autocvar_cl_reticle_weapon)
{
precache_pic("gfx/reticle_nex");
}
- return true;
}
- case WR_ZOOMRETICLE:
+ METHOD(Rifle, wr_zoomreticle, bool(entity thiswep))
{
if(button_zoom || zoomscript_caught)
{
return false;
}
}
- }
- return false;
-}
+
#endif
#endif
#ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id */ RPC,
-/* function */ W_RocketPropelledChainsaw,
-/* ammotype */ ammo_rockets,
-/* impulse */ 7,
-/* flags */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_HIDDEN | WEP_FLAG_NORMAL | WEP_FLAG_CANCLIMB | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH | WEP_FLAG_SUPERWEAPON,
-/* rating */ BOT_PICKUP_RATING_HIGH,
-/* color */ '0.5 0.5 0',
-/* modelname */ "ok_rl",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairrocketlauncher 0.7",
-/* wepimg */ "weaponrpc",
-/* refname */ "rpc",
-/* wepname */ _("Rocket Propelled Chainsaw")
-);
+CLASS(RocketPropelledChainsaw, Weapon)
+/* ammotype */ ATTRIB(RocketPropelledChainsaw, ammo_field, .int, ammo_rockets)
+/* impulse */ ATTRIB(RocketPropelledChainsaw, impulse, int, 7)
+/* flags */ ATTRIB(RocketPropelledChainsaw, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_HIDDEN | WEP_FLAG_NORMAL | WEP_FLAG_CANCLIMB | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH | WEP_FLAG_SUPERWEAPON);
+/* rating */ ATTRIB(RocketPropelledChainsaw, bot_pickupbasevalue, float, BOT_PICKUP_RATING_HIGH);
+/* color */ ATTRIB(RocketPropelledChainsaw, wpcolor, vector, '0.5 0.5 0');
+/* modelname */ ATTRIB(RocketPropelledChainsaw, mdl, string, "ok_rl");
+#ifndef MENUQC
+/* model */ ATTRIB(RocketPropelledChainsaw, m_model, Model, MDL_RPC_ITEM);
+#endif
+/* crosshair */ ATTRIB(RocketPropelledChainsaw, w_crosshair, string, "gfx/crosshairrocketlauncher");
+/* crosshair */ ATTRIB(RocketPropelledChainsaw, w_crosshair_size, float, 0.6);
+/* wepimg */ ATTRIB(RocketPropelledChainsaw, model2, string, "weaponrpc");
+/* refname */ ATTRIB(RocketPropelledChainsaw, netname, string, "rpc");
+/* wepname */ ATTRIB(RocketPropelledChainsaw, message, string, _("Rocket Propelled Chainsaw"));
+ENDCLASS(RocketPropelledChainsaw)
+REGISTER_WEAPON(RPC, NEW(RocketPropelledChainsaw));
#define RPC_SETTINGS(w_cvar,w_prop) RPC_SETTINGS_LIST(w_cvar, w_prop, RPC, rpc)
#define RPC_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
#endif
#ifdef IMPLEMENTATION
#ifdef SVQC
-void spawnfunc_weapon_rpc() { weapon_defaultspawnfunc(WEP_RPC.m_id); }
+spawnfunc(weapon_rpc) { weapon_defaultspawnfunc(WEP_RPC.m_id); }
void W_RocketPropelledChainsaw_Explode()
-{
+{SELFPARAM();
self.event_damage = func_null;
self.takedamage = DAMAGE_NO;
}
void W_RocketPropelledChainsaw_Touch (void)
-{
+{SELFPARAM();
if(WarpZone_Projectile_Touch())
if(wasfreed(self))
return;
}
void W_RocketPropelledChainsaw_Damage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
if (self.health <= 0)
return;
}
void W_RocketPropelledChainsaw_Think()
-{
+{SELFPARAM();
if(self.cnt <= time)
{
remove(self);
self.nextthink = time;
}
-void W_RocketPropelledChainsaw_Attack (void)
-{
+void W_RocketPropelledChainsaw_Attack (Weapon thiswep)
+{SELFPARAM();
entity missile = spawn(); //WarpZone_RefSys_SpawnSameRefSys(self);
entity flash = spawn ();
- W_DecreaseAmmo(WEP_CVAR(rpc, ammo));
- W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', false, 5, W_Sound("rocket_fire"), CH_WEAPON_A, WEP_CVAR(rpc, damage));
+ W_DecreaseAmmo(thiswep, self, WEP_CVAR(rpc, ammo));
+ W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', false, 5, SND(ROCKET_FIRE), CH_WEAPON_A, WEP_CVAR(rpc, damage));
Send_Effect(EFFECT_ROCKET_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
PROJECTILE_MAKETRIGGER(missile);
CSQCProjectile(missile, true, PROJECTILE_RPC, false);
- setmodel(flash, "models/flash.md3"); // precision set below
+ setmodel(flash, MDL_RPC_MUZZLEFLASH); // precision set below
SUB_SetFade (flash, time, 0.1);
flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
- W_AttachToShotorg(flash, '5 0 0');
+ W_AttachToShotorg(self, flash, '5 0 0');
missile.pos1 = missile.velocity;
MUTATOR_CALLHOOK(EditProjectile, self, missile);
}
-bool W_RocketPropelledChainsaw(int req)
-{
- float ammo_amount = false;
- switch(req)
- {
- case WR_AIM:
+ METHOD(RocketPropelledChainsaw, wr_aim, void(entity thiswep))
{
self.BUTTON_ATCK = bot_aim(WEP_CVAR(rpc, speed), 0, WEP_CVAR(rpc, lifetime), false);
- return true;
}
- case WR_THINK:
+ METHOD(RocketPropelledChainsaw, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
{
- if(WEP_CVAR(rpc, reload_ammo) && self.clip_load < WEP_CVAR(rpc, ammo))
- WEP_ACTION(self.weapon, WR_RELOAD);
- else
+ if(WEP_CVAR(rpc, reload_ammo) && actor.clip_load < WEP_CVAR(rpc, ammo)) {
+ Weapon w = get_weaponinfo(actor.weapon);
+ w.wr_reload(w);
+ } else
{
- if (self.BUTTON_ATCK)
+ if (fire1)
{
- if(weapon_prepareattack(0, WEP_CVAR(rpc, refire)))
+ if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR(rpc, refire)))
{
- W_RocketPropelledChainsaw_Attack();
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(rpc, animtime), w_ready);
+ W_RocketPropelledChainsaw_Attack(thiswep);
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR(rpc, animtime), w_ready);
}
}
- if (self.BUTTON_ATCK2)
+ if (fire2)
{
// to-do
}
}
-
- return true;
}
- case WR_INIT:
+ METHOD(RocketPropelledChainsaw, wr_init, void(entity thiswep))
{
- precache_model ("models/flash.md3");
- precache_model(W_Model("g_ok_rl.md3"));
- precache_model(W_Model("v_ok_rl.md3"));
- precache_model(W_Model("h_ok_rl.iqm"));
- precache_sound (W_Sound("rocket_fire"));
RPC_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
- return true;
}
- case WR_CHECKAMMO1:
+ METHOD(RocketPropelledChainsaw, wr_checkammo1, bool(entity thiswep))
{
- ammo_amount = self.WEP_AMMO(RPC) >= WEP_CVAR(rpc, ammo);
+ float ammo_amount = self.WEP_AMMO(RPC) >= WEP_CVAR(rpc, ammo);
ammo_amount += self.(weapon_load[WEP_RPC.m_id]) >= WEP_CVAR(rpc, ammo);
return ammo_amount;
}
- case WR_CHECKAMMO2:
+ METHOD(RocketPropelledChainsaw, wr_checkammo2, bool(entity thiswep))
{
return false;
}
- case WR_CONFIG:
+ METHOD(RocketPropelledChainsaw, wr_config, void(entity thiswep))
{
RPC_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
- return true;
}
- case WR_RELOAD:
+ METHOD(RocketPropelledChainsaw, wr_reload, void(entity thiswep))
{
- W_Reload(WEP_CVAR(rpc, ammo), W_Sound("reload"));
- return true;
+ W_Reload(self, WEP_CVAR(rpc, ammo), SND(RELOAD));
}
- case WR_SUICIDEMESSAGE:
+ METHOD(RocketPropelledChainsaw, wr_suicidemessage, int(entity thiswep))
{
if((w_deathtype & HITTYPE_BOUNCE) || (w_deathtype & HITTYPE_SPLASH))
return WEAPON_RPC_SUICIDE_SPLASH;
else
return WEAPON_RPC_SUICIDE_DIRECT;
}
- case WR_KILLMESSAGE:
+ METHOD(RocketPropelledChainsaw, wr_killmessage, int(entity thiswep))
{
if(w_deathtype & HITTYPE_SECONDARY)
return WEAPON_BLASTER_MURDER;
else
return WEAPON_RPC_MURDER_DIRECT;
}
- }
- return false;
-}
#endif
#ifdef CSQC
-bool W_RocketPropelledChainsaw(int req)
-{
- switch(req)
- {
- case WR_IMPACTEFFECT:
+
+ METHOD(RocketPropelledChainsaw, wr_impacteffect, void(entity thiswep))
{
vector org2;
org2 = w_org + w_backoff * 12;
pointparticles(particleeffectnum(EFFECT_ROCKET_EXPLODE), org2, '0 0 0', 1);
if(!w_issilent)
- sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
-
- return true;
- }
- case WR_INIT:
- {
- precache_sound(W_Sound("rocket_impact"));
- return true;
- }
- case WR_ZOOMRETICLE:
- {
- // no weapon specific image for this weapon
- return false;
+ sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
}
- }
- return false;
-}
#endif
#endif
#ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id */ SEEKER,
-/* function */ W_Seeker,
-/* ammotype */ ammo_rockets,
-/* impulse */ 8,
-/* flags */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH,
-/* rating */ BOT_PICKUP_RATING_MID,
-/* color */ '0.5 1 0',
-/* modelname */ "seeker",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairseeker 0.8",
-/* wepimg */ "weaponseeker",
-/* refname */ "seeker",
-/* wepname */ _("T.A.G. Seeker")
-);
+CLASS(Seeker, Weapon)
+/* ammotype */ ATTRIB(Seeker, ammo_field, .int, ammo_rockets)
+/* impulse */ ATTRIB(Seeker, impulse, int, 8)
+/* flags */ ATTRIB(Seeker, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH);
+/* rating */ ATTRIB(Seeker, bot_pickupbasevalue, float, BOT_PICKUP_RATING_HIGH);
+/* color */ ATTRIB(Seeker, wpcolor, vector, '0.5 1 0');
+/* modelname */ ATTRIB(Seeker, mdl, string, "seeker");
+#ifndef MENUQC
+/* model */ ATTRIB(Seeker, m_model, Model, MDL_SEEKER_ITEM);
+#endif
+/* crosshair */ ATTRIB(Seeker, w_crosshair, string, "gfx/crosshairseeker");
+/* crosshair */ ATTRIB(Seeker, w_crosshair_size, float, 0.8);
+/* wepimg */ ATTRIB(Seeker, model2, string, "weaponseeker");
+/* refname */ ATTRIB(Seeker, netname, string, "seeker");
+/* wepname */ ATTRIB(Seeker, message, string, _("T.A.G. Seeker"));
+ENDCLASS(Seeker)
+REGISTER_WEAPON(SEEKER, NEW(Seeker));
#define SEEKER_SETTINGS(w_cvar,w_prop) SEEKER_SETTINGS_LIST(w_cvar, w_prop, SEEKER, seeker)
#define SEEKER_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
#endif
#ifdef IMPLEMENTATION
#ifdef SVQC
-void spawnfunc_weapon_seeker(void) { weapon_defaultspawnfunc(WEP_SEEKER.m_id); }
+spawnfunc(weapon_seeker) { weapon_defaultspawnfunc(WEP_SEEKER.m_id); }
// ============================
// Begin: Missile functions, these are general functions to be manipulated by other code
// ============================
void W_Seeker_Missile_Explode(void)
-{
+{SELFPARAM();
self.event_damage = func_null;
RadiusDamage(self, self.realowner, WEP_CVAR(seeker, missile_damage), WEP_CVAR(seeker, missile_edgedamage), WEP_CVAR(seeker, missile_radius), world, world, WEP_CVAR(seeker, missile_force), self.projectiledeathtype, other);
}
void W_Seeker_Missile_Think(void)
-{
+{SELFPARAM();
entity e;
vector desireddir, olddir, newdir, eorg;
float turnrate;
void W_Seeker_Missile_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
if(self.health <= 0)
return;
}
*/
-void W_Seeker_Fire_Missile(vector f_diff, entity m_target)
-{
+void W_Seeker_Fire_Missile(Weapon thiswep, vector f_diff, entity m_target)
+{SELFPARAM();
entity missile;
- W_DecreaseAmmo(WEP_CVAR(seeker, missile_ammo));
+ W_DecreaseAmmo(thiswep, self, WEP_CVAR(seeker, missile_ammo));
makevectors(self.v_angle);
- W_SetupShot_ProjectileSize(self, '-2 -2 -2', '2 2 2', false, 2, W_Sound("seeker_fire"), CH_WEAPON_A, 0);
+ W_SetupShot_ProjectileSize(self, '-2 -2 -2', '2 2 2', false, 2, SND(SEEKER_FIRE), CH_WEAPON_A, 0);
w_shotorg += f_diff;
Send_Effect(EFFECT_SEEKER_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
// Begin: FLAC, close range attack meant for defeating rockets which are coming at you.
// ============================
void W_Seeker_Flac_Explode(void)
-{
+{SELFPARAM();
self.event_damage = func_null;
RadiusDamage(self, self.realowner, WEP_CVAR(seeker, flac_damage), WEP_CVAR(seeker, flac_edgedamage), WEP_CVAR(seeker, flac_radius), world, world, WEP_CVAR(seeker, flac_force), self.projectiledeathtype, other);
W_Seeker_Flac_Explode();
}
-void W_Seeker_Fire_Flac(void)
-{
+void W_Seeker_Fire_Flac(Weapon thiswep)
+{SELFPARAM();
entity missile;
vector f_diff;
float c;
- W_DecreaseAmmo(WEP_CVAR(seeker, flac_ammo));
+ W_DecreaseAmmo(thiswep, self, WEP_CVAR(seeker, flac_ammo));
c = self.bulletcounter % 4;
switch(c)
f_diff = '+1.25 +3.75 0';
break;
}
- W_SetupShot_ProjectileSize(self, '-2 -2 -2', '2 2 2', false, 2, W_Sound("flac_fire"), CH_WEAPON_A, WEP_CVAR(seeker, flac_damage));
+ W_SetupShot_ProjectileSize(self, '-2 -2 -2', '2 2 2', false, 2, SND(FLAC_FIRE), CH_WEAPON_A, WEP_CVAR(seeker, flac_damage));
w_shotorg += f_diff;
Send_Effect(EFFECT_HAGAR_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
}
void W_Seeker_Attack(void)
-{
+{SELFPARAM();
entity tracker, closest_target;
closest_target = world;
if((!closest_target) || ((trace_fraction < 1) && (trace_ent != closest_target)))
closest_target = world;
- W_Seeker_Fire_Missile('0 0 0', closest_target);
+ W_Seeker_Fire_Missile(WEP_SEEKER, '0 0 0', closest_target);
}
void W_Seeker_Vollycontroller_Think(void) // TODO: Merge this with W_Seeker_Attack
-{
+{SELFPARAM();
float c;
- entity oldself,oldenemy;
+ entity oldenemy;
self.cnt = self.cnt - 1;
if((!(self.realowner.items & IT_UNLIMITED_AMMO) && self.realowner.WEP_AMMO(SEEKER) < WEP_CVAR(seeker, missile_ammo)) || (self.cnt <= -1) || (self.realowner.deadflag != DEAD_NO) || (self.realowner.switchweapon != WEP_SEEKER.m_id))
self.nextthink = time + WEP_CVAR(seeker, missile_delay) * W_WeaponRateFactor();
- oldself = self;
- self = self.realowner;
+ setself(self.realowner);
oldenemy = self.enemy;
- self.enemy = oldself.enemy;
+ self.enemy = this.enemy;
c = self.cnt % 4;
switch(c)
{
case 0:
- W_Seeker_Fire_Missile('-1.25 -3.75 0', self.enemy);
+ W_Seeker_Fire_Missile(WEP_SEEKER, '-1.25 -3.75 0', self.enemy);
break;
case 1:
- W_Seeker_Fire_Missile('+1.25 -3.75 0', self.enemy);
+ W_Seeker_Fire_Missile(WEP_SEEKER, '+1.25 -3.75 0', self.enemy);
break;
case 2:
- W_Seeker_Fire_Missile('-1.25 +3.75 0', self.enemy);
+ W_Seeker_Fire_Missile(WEP_SEEKER, '-1.25 +3.75 0', self.enemy);
break;
case 3:
default:
- W_Seeker_Fire_Missile('+1.25 +3.75 0', self.enemy);
+ W_Seeker_Fire_Missile(WEP_SEEKER, '+1.25 +3.75 0', self.enemy);
break;
}
self.enemy = oldenemy;
- self = oldself;
+ setself(this);
}
void W_Seeker_Tracker_Think(void)
-{
+{SELFPARAM();
// commit suicide if: You die OR target dies OR you switch away from the seeker OR commit suicide if lifetime is up
if((self.realowner.deadflag != DEAD_NO) || (self.tag_target.deadflag != DEAD_NO) || (self.realowner.switchweapon != WEP_SEEKER.m_id)
|| (time > self.tag_time + WEP_CVAR(seeker, tag_tracker_lifetime)))
// Begin: Tag projectile
// ============================
void W_Seeker_Tag_Explode(void)
-{
+{SELFPARAM();
//if(other==self.realowner)
// return;
Damage_DamageInfo(self.origin, 0, 0, 0, self.velocity, WEP_SEEKER.m_id | HITTYPE_BOUNCE, other.species, self);
}
void W_Seeker_Tag_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
if(self.health <= 0)
return;
self.health = self.health - damage;
}
void W_Seeker_Tag_Touch(void)
-{
+{SELFPARAM();
vector dir;
vector org2;
entity e;
return;
}
-void W_Seeker_Fire_Tag(void)
-{
+void W_Seeker_Fire_Tag(Weapon thiswep)
+{SELFPARAM();
entity missile;
- W_DecreaseAmmo(WEP_CVAR(seeker, tag_ammo));
+ W_DecreaseAmmo(thiswep, self, WEP_CVAR(seeker, tag_ammo));
- W_SetupShot_ProjectileSize(self, '-2 -2 -2', '2 2 2', false, 2, W_Sound("tag_fire"), CH_WEAPON_A, WEP_CVAR(seeker, missile_damage) * WEP_CVAR(seeker, missile_count));
+ W_SetupShot_ProjectileSize(self, '-2 -2 -2', '2 2 2', false, 2, SND(TAG_FIRE), CH_WEAPON_A, WEP_CVAR(seeker, missile_damage) * WEP_CVAR(seeker, missile_count));
missile = spawn();
missile.owner = missile.realowner = self;
// Begin: Genereal weapon functions
// ============================
-bool W_Seeker(int req)
-{
- float ammo_amount;
-
- switch(req)
- {
- case WR_AIM:
+ METHOD(Seeker, wr_aim, void(entity thiswep))
{
if(WEP_CVAR(seeker, type) == 1)
if(W_Seeker_Tagged_Info(self, self.enemy) != world)
self.BUTTON_ATCK2 = bot_aim(WEP_CVAR(seeker, tag_speed), 0, WEP_CVAR(seeker, tag_lifetime), false);
else
self.BUTTON_ATCK = bot_aim(WEP_CVAR(seeker, tag_speed), 0, WEP_CVAR(seeker, tag_lifetime), false);
- return true;
}
- case WR_THINK:
+ METHOD(Seeker, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
{
- if(autocvar_g_balance_seeker_reload_ammo && self.clip_load < min(WEP_CVAR(seeker, missile_ammo), WEP_CVAR(seeker, tag_ammo))) // forced reload
- WEP_ACTION(self.weapon, WR_RELOAD);
-
- else if(self.BUTTON_ATCK)
+ if(autocvar_g_balance_seeker_reload_ammo && actor.clip_load < min(WEP_CVAR(seeker, missile_ammo), WEP_CVAR(seeker, tag_ammo))) { // forced reload
+ Weapon w = get_weaponinfo(actor.weapon);
+ w.wr_reload(w);
+ } else if(fire1)
{
if(WEP_CVAR(seeker, type) == 1)
{
- if(weapon_prepareattack(0, WEP_CVAR(seeker, missile_refire)))
+ if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR(seeker, missile_refire)))
{
W_Seeker_Attack();
- weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(seeker, missile_animtime), w_ready);
+ weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR(seeker, missile_animtime), w_ready);
}
}
else
{
- if(weapon_prepareattack(0, WEP_CVAR(seeker, tag_refire)))
+ if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR(seeker, tag_refire)))
{
- W_Seeker_Fire_Tag();
- weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(seeker, tag_animtime), w_ready);
+ W_Seeker_Fire_Tag(thiswep);
+ weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR(seeker, tag_animtime), w_ready);
}
}
}
- else if(self.BUTTON_ATCK2)
+ else if(fire2)
{
if(WEP_CVAR(seeker, type) == 1)
{
- if(weapon_prepareattack(0, WEP_CVAR(seeker, tag_refire)))
+ if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR(seeker, tag_refire)))
{
- W_Seeker_Fire_Tag();
- weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(seeker, tag_animtime), w_ready);
+ W_Seeker_Fire_Tag(thiswep);
+ weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR(seeker, tag_animtime), w_ready);
}
}
else
{
- if(weapon_prepareattack(0, WEP_CVAR(seeker, flac_refire)))
+ if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR(seeker, flac_refire)))
{
- W_Seeker_Fire_Flac();
- weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(seeker, flac_animtime), w_ready);
+ W_Seeker_Fire_Flac(thiswep);
+ weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR(seeker, flac_animtime), w_ready);
}
}
}
-
- return true;
}
- case WR_INIT:
+ METHOD(Seeker, wr_init, void(entity thiswep))
{
- precache_model(W_Model("g_seeker.md3"));
- precache_model(W_Model("v_seeker.md3"));
- precache_model(W_Model("h_seeker.iqm"));
- precache_sound(W_Sound("tag_fire"));
- precache_sound(W_Sound("flac_fire"));
- precache_sound(W_Sound("seeker_fire"));
SEEKER_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
- return true;
}
- case WR_CHECKAMMO1:
+ METHOD(Seeker, wr_checkammo1, bool(entity thiswep))
{
+ float ammo_amount;
if(WEP_CVAR(seeker, type) == 1)
{
ammo_amount = self.WEP_AMMO(SEEKER) >= WEP_CVAR(seeker, missile_ammo);
}
return ammo_amount;
}
- case WR_CHECKAMMO2:
+ METHOD(Seeker, wr_checkammo2, bool(entity thiswep))
{
+ float ammo_amount;
if(WEP_CVAR(seeker, type) == 1)
{
ammo_amount = self.WEP_AMMO(SEEKER) >= WEP_CVAR(seeker, tag_ammo);
}
return ammo_amount;
}
- case WR_CONFIG:
+ METHOD(Seeker, wr_config, void(entity thiswep))
{
SEEKER_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
- return true;
}
- case WR_RELOAD:
+ METHOD(Seeker, wr_reload, void(entity thiswep))
{
- W_Reload(min(WEP_CVAR(seeker, missile_ammo), WEP_CVAR(seeker, tag_ammo)), W_Sound("reload"));
- return true;
+ W_Reload(self, min(WEP_CVAR(seeker, missile_ammo), WEP_CVAR(seeker, tag_ammo)), SND(RELOAD));
}
- case WR_SUICIDEMESSAGE:
+ METHOD(Seeker, wr_suicidemessage, int(entity thiswep))
{
return WEAPON_SEEKER_SUICIDE;
}
- case WR_KILLMESSAGE:
+ METHOD(Seeker, wr_killmessage, int(entity thiswep))
{
if(w_deathtype & HITTYPE_SECONDARY)
return WEAPON_SEEKER_MURDER_TAG;
else
return WEAPON_SEEKER_MURDER_SPRAY;
}
- }
- return false;
-}
+
#endif
#ifdef CSQC
-bool W_Seeker(int req)
-{
- switch(req)
- {
- case WR_IMPACTEFFECT:
+
+ METHOD(Seeker, wr_impacteffect, void(entity thiswep))
{
vector org2;
org2 = w_org + w_backoff * 6;
if(w_deathtype & HITTYPE_SECONDARY)
{
if(!w_issilent)
- sound(self, CH_SHOTS, W_Sound("tag_impact"), 1, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_TAG_IMPACT, 1, ATTEN_NORM);
}
else
{
if(!w_issilent)
{
if(w_random<0.15)
- sound(self, CH_SHOTS, W_Sound("tagexp1"), 1, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_TAGEXP1, 1, ATTEN_NORM);
else if(w_random<0.7)
- sound(self, CH_SHOTS, W_Sound("tagexp2"), 1, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_TAGEXP2, 1, ATTEN_NORM);
else
- sound(self, CH_SHOTS, W_Sound("tagexp3"), 1, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_TAGEXP3, 1, ATTEN_NORM);
}
}
}
if(!w_issilent)
{
if(w_random<0.15)
- sound(self, CH_SHOTS, W_Sound("seekerexp1"), 1, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_SEEKEREXP1, 1, ATTEN_NORM);
else if(w_random<0.7)
- sound(self, CH_SHOTS, W_Sound("seekerexp2"), 1, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_SEEKEREXP2, 1, ATTEN_NORM);
else
- sound(self, CH_SHOTS, W_Sound("seekerexp3"), 1, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_SEEKEREXP3, 1, ATTEN_NORM);
}
}
- return true;
- }
- case WR_INIT:
- {
- precache_sound(W_Sound("seekerexp1"));
- precache_sound(W_Sound("seekerexp2"));
- precache_sound(W_Sound("seekerexp3"));
- precache_sound(W_Sound("tagexp1"));
- precache_sound(W_Sound("tagexp2"));
- precache_sound(W_Sound("tagexp3"));
- precache_sound(W_Sound("tag_impact"));
- return true;
- }
- case WR_ZOOMRETICLE:
- {
- // no weapon specific image for this weapon
- return false;
}
- }
- return false;
-}
+
#endif
#endif
#ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id */ SHOCKWAVE,
-/* function */ W_Shockwave,
-/* ammotype */ ammo_none,
-/* impulse */ 2,
-/* flags */ WEP_FLAG_NORMAL | WEP_TYPE_HITSCAN | WEP_FLAG_CANCLIMB | WEP_FLAG_MUTATORBLOCKED,
-/* rating */ BOT_PICKUP_RATING_LOW,
-/* color */ '0.5 0.25 0',
-/* modelname */ "shotgun",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairshotgun 0.7",
-/* wepimg */ "weaponshotgun",
-/* refname */ "shockwave",
-/* wepname */ _("Shockwave")
-);
+CLASS(Shockwave, Weapon)
+/* ammotype */ //ATTRIB(Shockwave, ammo_field, .int, ammo_none)
+/* impulse */ ATTRIB(Shockwave, impulse, int, 2)
+/* flags */ ATTRIB(Shockwave, spawnflags, int, WEP_FLAG_NORMAL | WEP_TYPE_HITSCAN | WEP_FLAG_CANCLIMB | WEP_FLAG_MUTATORBLOCKED);
+/* rating */ ATTRIB(Shockwave, bot_pickupbasevalue, float, BOT_PICKUP_RATING_LOW);
+/* color */ ATTRIB(Shockwave, wpcolor, vector, '0.5 0.25 0');
+/* modelname */ ATTRIB(Shockwave, mdl, string, "shotgun");
+#ifndef MENUQC
+/* model */ ATTRIB(Shockwave, m_model, Model, MDL_SHOCKWAVE_ITEM);
+#endif
+/* crosshair */ ATTRIB(Shockwave, w_crosshair, string, "gfx/crosshairshotgun");
+/* crosshair */ ATTRIB(Shockwave, w_crosshair_size, float, 0.7);
+/* wepimg */ ATTRIB(Shockwave, model2, string, "weaponshotgun");
+/* refname */ ATTRIB(Shockwave, netname, string, "shockwave");
+/* wepname */ ATTRIB(Shockwave, message, string, _("Shockwave"));
+ENDCLASS(Shockwave)
+REGISTER_WEAPON(SHOCKWAVE, NEW(Shockwave));
#define SHOCKWAVE_SETTINGS(w_cvar,w_prop) SHOCKWAVE_SETTINGS_LIST(w_cvar, w_prop, SHOCKWAVE, shockwave)
#define SHOCKWAVE_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
#endif
#ifdef IMPLEMENTATION
#ifdef SVQC
-void spawnfunc_weapon_shockwave(void)
+spawnfunc(weapon_shockwave)
{
//if(autocvar_sv_q3acompat_machineshockwaveswap) // WEAPONTODO
if(autocvar_sv_q3acompat_machineshotgunswap)
// MELEE ATTACK MODE
void W_Shockwave_Melee_Think(void)
-{
+{SELFPARAM();
// declarations
float i, f, swing, swing_factor, swing_damage, meleetime, is_player;
entity target_victim;
}
}
-void W_Shockwave_Melee(void)
+void W_Shockwave_Melee(Weapon thiswep, entity actor, bool fire1, bool fire2)
{
- sound(self, CH_WEAPON_A, W_Sound("shotgun_melee"), VOL_BASE, ATTN_NORM);
- weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(shockwave, melee_animtime), w_ready);
+ sound(actor, CH_WEAPON_A, SND_SHOTGUN_MELEE, VOL_BASE, ATTN_NORM);
+ weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR(shockwave, melee_animtime), w_ready);
entity meleetemp;
meleetemp = spawn();
- meleetemp.owner = meleetemp.realowner = self;
+ meleetemp.owner = meleetemp.realowner = actor;
meleetemp.think = W_Shockwave_Melee_Think;
meleetemp.nextthink = time + WEP_CVAR(shockwave, melee_delay) * W_WeaponRateFactor();
- W_SetupShot_Range(self, true, 0, "", 0, WEP_CVAR(shockwave, melee_damage), WEP_CVAR(shockwave, melee_range));
+ W_SetupShot_Range(actor, true, 0, "", 0, WEP_CVAR(shockwave, melee_damage), WEP_CVAR(shockwave, melee_range));
}
// SHOCKWAVE ATTACK MODE
vector nearest_on_line,
vector sw_shotorg,
vector attack_endpos)
-{
+{SELFPARAM();
vector nearest_to_attacker = head.WarpZone_findradius_nearest;
vector center = (head.origin + (head.mins + head.maxs) * 0.5);
vector corner;
}
void W_Shockwave_Send(void)
-{
+{SELFPARAM();
WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
WriteByte(MSG_BROADCAST, TE_CSQC_SHOCKWAVEPARTICLE);
WriteCoord(MSG_BROADCAST, w_shotorg.x);
}
void W_Shockwave_Attack(void)
-{
+{SELFPARAM();
// declarations
float multiplier, multiplier_from_accuracy, multiplier_from_distance;
float final_damage;
float i, queue = 0;
// set up the shot direction
- W_SetupShot(self, false, 3, W_Sound("lasergun_fire"), CH_WEAPON_B, WEP_CVAR(shockwave, blast_damage));
+ W_SetupShot(self, false, 3, SND(LASERGUN_FIRE), CH_WEAPON_B, WEP_CVAR(shockwave, blast_damage));
vector attack_endpos = (w_shotorg + (w_shotdir * WEP_CVAR(shockwave, blast_distance)));
WarpZone_TraceLine(w_shotorg, attack_endpos, MOVE_NOMONSTERS, self);
vector attack_hitpos = trace_endpos;
);
// figure out the direction of force
- vel = normalize(combine_to_vector(head.velocity.x, head.velocity.y, 0));
+ vel = normalize(vec3(head.velocity.x, head.velocity.y, 0));
vel *=
(
bound(0, (vlen(vel) / autocvar_sv_maxspeed), 1)
}
}
-bool W_Shockwave(int req)
-{
- switch(req)
- {
- case WR_AIM:
+ METHOD(Shockwave, wr_aim, void(entity thiswep))
{
if(vlen(self.origin - self.enemy.origin) <= WEP_CVAR(shockwave, melee_range))
{ self.BUTTON_ATCK2 = bot_aim(1000000, 0, 0.001, false); }
else
{ self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, false); }
-
- return true;
}
- case WR_THINK:
+ METHOD(Shockwave, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
{
- if(self.BUTTON_ATCK)
+ if(fire1)
{
- if(time >= self.shockwave_blasttime) // handle refire separately so the secondary can be fired straight after a primary
+ if(time >= actor.shockwave_blasttime) // handle refire separately so the secondary can be fired straight after a primary
{
- if(weapon_prepareattack(0, WEP_CVAR(shockwave, blast_animtime)))
+ if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR(shockwave, blast_animtime)))
{
W_Shockwave_Attack();
- self.shockwave_blasttime = time + WEP_CVAR(shockwave, blast_refire) * W_WeaponRateFactor();
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(shockwave, blast_animtime), w_ready);
+ actor.shockwave_blasttime = time + WEP_CVAR(shockwave, blast_refire) * W_WeaponRateFactor();
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR(shockwave, blast_animtime), w_ready);
}
}
}
- else if(self.BUTTON_ATCK2)
+ else if(fire2)
{
- //if(self.clip_load >= 0) // we are not currently reloading
- if(!self.crouch) // no crouchmelee please
- if(weapon_prepareattack(1, WEP_CVAR(shockwave, melee_refire)))
+ //if(actor.clip_load >= 0) // we are not currently reloading
+ if(!actor.crouch) // no crouchmelee please
+ if(weapon_prepareattack(thiswep, actor, true, WEP_CVAR(shockwave, melee_refire)))
{
// attempt forcing playback of the anim by switching to another anim (that we never play) here...
- weapon_thinkf(WFRAME_FIRE1, 0, W_Shockwave_Melee);
+ weapon_thinkf(actor, WFRAME_FIRE1, 0, W_Shockwave_Melee);
}
}
-
- return true;
}
- case WR_INIT:
+ METHOD(Shockwave, wr_init, void(entity thiswep))
{
- precache_model("models/uziflash.md3");
- precache_model(W_Model("g_shotgun.md3"));
- precache_model(W_Model("v_shotgun.md3"));
- precache_model(W_Model("h_shotgun.iqm"));
- precache_sound("misc/itempickup.wav");
- precache_sound(W_Sound("lasergun_fire"));
- precache_sound(W_Sound("shotgun_melee"));
SHOCKWAVE_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
- return true;
}
- case WR_CHECKAMMO1:
- case WR_CHECKAMMO2:
+ METHOD(Shockwave, wr_checkammo1, bool(entity thiswep))
+ {
+ return true; // infinite ammo
+ }
+ METHOD(Shockwave, wr_checkammo2, bool(entity thiswep))
{
// shockwave has infinite ammo
return true;
}
- case WR_CONFIG:
+ METHOD(Shockwave, wr_config, void(entity thiswep))
{
SHOCKWAVE_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
- return true;
}
- case WR_SUICIDEMESSAGE:
+ METHOD(Shockwave, wr_suicidemessage, int(entity thiswep))
{
return WEAPON_THINKING_WITH_PORTALS;
}
- case WR_KILLMESSAGE:
+ METHOD(Shockwave, wr_killmessage, int(entity thiswep))
{
if(w_deathtype & HITTYPE_SECONDARY)
return WEAPON_SHOCKWAVE_MURDER_SLAP;
else
return WEAPON_SHOCKWAVE_MURDER;
}
- }
- return false;
-}
+
#endif
#ifdef CSQC
// WEAPONTODO: add client side settings for these
const float SW_MAXALPHA = 0.5;
const float SW_FADETIME = 0.4;
const float SW_DISTTOMIN = 200;
-void Draw_Shockwave()
+void Draw_Shockwave(entity this)
{
// fading/removal control
float a = bound(0, (SW_MAXALPHA - ((time - self.sw_time) / SW_FADETIME)), SW_MAXALPHA);
shockwave.sw_time = time;
}
-bool W_Shockwave(int req)
-{
- switch(req)
- {
- case WR_IMPACTEFFECT:
+ METHOD(Shockwave, wr_impacteffect, void(entity thiswep))
{
// handled by Net_ReadShockwaveParticle
//vector org2;
//org2 = w_org + w_backoff * 2;
//pointparticles(particleeffectnum(EFFECT_BLASTER_IMPACT), org2, w_backoff * 1000, 1);
- return false;
- }
- case WR_INIT:
- {
- //precache_sound(W_Sound("ric1"));
- //precache_sound(W_Sound("ric2"));
- //precache_sound(W_Sound("ric3"));
- return false;
- }
- case WR_ZOOMRETICLE:
- {
- // no weapon specific image for this weapon
- return false;
}
- }
- return false;
-}
+
#endif
#endif
#ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id */ SHOTGUN,
-/* function */ W_Shotgun,
-/* ammotype */ ammo_shells,
-/* impulse */ 2,
-/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN,
-/* rating */ BOT_PICKUP_RATING_LOW,
-/* color */ '0.5 0.25 0',
-/* modelname */ "shotgun",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairshotgun 0.65",
-/* wepimg */ "weaponshotgun",
-/* refname */ "shotgun",
-/* wepname */ _("Shotgun")
-);
+CLASS(Shotgun, Weapon)
+/* ammotype */ ATTRIB(Shotgun, ammo_field, .int, ammo_shells)
+/* impulse */ ATTRIB(Shotgun, impulse, int, 2)
+/* flags */ ATTRIB(Shotgun, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN);
+/* rating */ ATTRIB(Shotgun, bot_pickupbasevalue, float, BOT_PICKUP_RATING_LOW);
+/* color */ ATTRIB(Shotgun, wpcolor, vector, '0.5 0.25 0');
+/* modelname */ ATTRIB(Shotgun, mdl, string, "shotgun");
+#ifndef MENUQC
+/* model */ ATTRIB(Shotgun, m_model, Model, MDL_SHOTGUN_ITEM);
+#endif
+/* crosshair */ ATTRIB(Shotgun, w_crosshair, string, "gfx/crosshairshotgun");
+/* crosshair */ ATTRIB(Shotgun, w_crosshair_size, float, 0.65);
+/* wepimg */ ATTRIB(Shotgun, model2, string, "weaponshotgun");
+/* refname */ ATTRIB(Shotgun, netname, string, "shotgun");
+/* wepname */ ATTRIB(Shotgun, message, string, _("Shotgun"));
+ENDCLASS(Shotgun)
+REGISTER_WEAPON(SHOTGUN, NEW(Shotgun));
#define SHOTGUN_SETTINGS(w_cvar,w_prop) SHOTGUN_SETTINGS_LIST(w_cvar, w_prop, SHOTGUN, shotgun)
#define SHOTGUN_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
#endif
#ifdef IMPLEMENTATION
#ifdef SVQC
-void spawnfunc_weapon_shotgun(void) { weapon_defaultspawnfunc(WEP_SHOTGUN.m_id); }
+spawnfunc(weapon_shotgun) { weapon_defaultspawnfunc(WEP_SHOTGUN.m_id); }
-void W_Shotgun_Attack(float isprimary)
-{
+void W_Shotgun_Attack(Weapon thiswep, float isprimary)
+{SELFPARAM();
float sc;
entity flash;
- W_DecreaseAmmo(WEP_CVAR_PRI(shotgun, ammo));
+ W_DecreaseAmmo(thiswep, self, WEP_CVAR_PRI(shotgun, ammo));
- W_SetupShot(self, true, 5, W_Sound("shotgun_fire"), ((isprimary) ? CH_WEAPON_A : CH_WEAPON_SINGLE), WEP_CVAR_PRI(shotgun, damage) * WEP_CVAR_PRI(shotgun, bullets));
+ W_SetupShot(self, true, 5, SND(SHOTGUN_FIRE), ((isprimary) ? CH_WEAPON_A : CH_WEAPON_SINGLE), WEP_CVAR_PRI(shotgun, damage) * WEP_CVAR_PRI(shotgun, bullets));
for(sc = 0;sc < WEP_CVAR_PRI(shotgun, bullets);sc = sc + 1)
fireBullet(w_shotorg, w_shotdir, WEP_CVAR_PRI(shotgun, spread), WEP_CVAR_PRI(shotgun, solidpenetration), WEP_CVAR_PRI(shotgun, damage), WEP_CVAR_PRI(shotgun, force), WEP_SHOTGUN.m_id, 0);
// muzzle flash for 1st person view
flash = spawn();
- setmodel(flash, "models/uziflash.md3"); // precision set below
+ setmodel(flash, MDL_SHOTGUN_MUZZLEFLASH); // precision set below
flash.think = SUB_Remove;
flash.nextthink = time + 0.06;
flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
- W_AttachToShotorg(flash, '5 0 0');
+ W_AttachToShotorg(self, flash, '5 0 0');
}
.float swing_prev;
.entity swing_alreadyhit;
void W_Shotgun_Melee_Think(void)
-{
+{SELFPARAM();
// declarations
float i, f, swing, swing_factor, swing_damage, meleetime, is_player;
entity target_victim;
}
}
-void W_Shotgun_Attack2(void)
+void W_Shotgun_Attack2(Weapon thiswep, entity actor, bool fire1, bool fire2)
{
- sound(self, CH_WEAPON_A, W_Sound("shotgun_melee"), VOL_BASE, ATTEN_NORM);
- weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(shotgun, animtime), w_ready);
+ sound(actor, CH_WEAPON_A, SND_SHOTGUN_MELEE, VOL_BASE, ATTEN_NORM);
+ weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR_SEC(shotgun, animtime), w_ready);
entity meleetemp;
meleetemp = spawn();
- meleetemp.realowner = self;
+ meleetemp.realowner = actor;
meleetemp.think = W_Shotgun_Melee_Think;
meleetemp.nextthink = time + WEP_CVAR_SEC(shotgun, melee_delay) * W_WeaponRateFactor();
- W_SetupShot_Range(self, true, 0, "", 0, WEP_CVAR_SEC(shotgun, damage), WEP_CVAR_SEC(shotgun, melee_range));
+ W_SetupShot_Range(actor, true, 0, "", 0, WEP_CVAR_SEC(shotgun, damage), WEP_CVAR_SEC(shotgun, melee_range));
}
// alternate secondary weapon frames
-void W_Shotgun_Attack3_Frame2()
+void W_Shotgun_Attack3_Frame2(Weapon thiswep, entity actor, bool fire1, bool fire2)
{
- if (!WEP_ACTION(self.weapon, WR_CHECKAMMO2))
- if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+ Weapon w = get_weaponinfo(actor.weapon);
+ if (!w.wr_checkammo2(w))
+ if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
- W_SwitchWeapon_Force(self, w_getbestweapon(self));
- w_ready();
+ W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+ w_ready(thiswep, actor, fire1, fire2);
return;
}
- sound(self, CH_WEAPON_SINGLE, "misc/null.wav", VOL_BASE, ATTN_NORM); // kill previous sound
- W_Shotgun_Attack(true); // actually is secondary, but we trick the last shot into playing full reload sound
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), w_ready);
+ sound(actor, CH_WEAPON_SINGLE, SND_Null, VOL_BASE, ATTN_NORM); // kill previous sound
+ W_Shotgun_Attack(WEP_SHOTGUN, true); // actually is secondary, but we trick the last shot into playing full reload sound
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), w_ready);
}
-void W_Shotgun_Attack3_Frame1()
+void W_Shotgun_Attack3_Frame1(Weapon thiswep, entity actor, bool fire1, bool fire2)
{
- if (!WEP_ACTION(self.weapon, WR_CHECKAMMO2))
- if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+ Weapon w = get_weaponinfo(actor.weapon);
+ if (!w.wr_checkammo2(w))
+ if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
- W_SwitchWeapon_Force(self, w_getbestweapon(self));
- w_ready();
+ W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+ w_ready(thiswep, actor, fire1, fire2);
return;
}
- W_Shotgun_Attack(false);
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), W_Shotgun_Attack3_Frame2);
+ W_Shotgun_Attack(WEP_SHOTGUN, false);
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), W_Shotgun_Attack3_Frame2);
}
.float shotgun_primarytime;
-float W_Shotgun(float req)
-{
- float ammo_amount;
- switch(req)
- {
- case WR_AIM:
+ METHOD(Shotgun, wr_aim, void(entity thiswep))
{
if(vlen(self.origin-self.enemy.origin) <= WEP_CVAR_SEC(shotgun, melee_range))
self.BUTTON_ATCK2 = bot_aim(1000000, 0, 0.001, false);
else
self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, false);
-
- return true;
}
- case WR_THINK:
+ METHOD(Shotgun, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
{
- if(WEP_CVAR(shotgun, reload_ammo) && self.clip_load < WEP_CVAR_PRI(shotgun, ammo)) // forced reload
+ if(WEP_CVAR(shotgun, reload_ammo) && actor.clip_load < WEP_CVAR_PRI(shotgun, ammo)) // forced reload
{
// don't force reload an empty shotgun if its melee attack is active
- if(WEP_CVAR(shotgun, secondary) < 2)
- WEP_ACTION(self.weapon, WR_RELOAD);
+ if(WEP_CVAR(shotgun, secondary) < 2) {
+ Weapon w = get_weaponinfo(actor.weapon);
+ w.wr_reload(w);
+ }
}
else
{
- if(self.BUTTON_ATCK)
+ if(fire1)
{
- if(time >= self.shotgun_primarytime) // handle refire separately so the secondary can be fired straight after a primary
+ if(time >= actor.shotgun_primarytime) // handle refire separately so the secondary can be fired straight after a primary
{
- if(weapon_prepareattack(0, WEP_CVAR_PRI(shotgun, animtime)))
+ if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(shotgun, animtime)))
{
- W_Shotgun_Attack(true);
- self.shotgun_primarytime = time + WEP_CVAR_PRI(shotgun, refire) * W_WeaponRateFactor();
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(shotgun, animtime), w_ready);
+ W_Shotgun_Attack(thiswep, true);
+ actor.shotgun_primarytime = time + WEP_CVAR_PRI(shotgun, refire) * W_WeaponRateFactor();
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(shotgun, animtime), w_ready);
}
}
}
- else if(self.BUTTON_ATCK2 && WEP_CVAR(shotgun, secondary) == 2)
+ else if(fire2 && WEP_CVAR(shotgun, secondary) == 2)
{
- if(time >= self.shotgun_primarytime) // handle refire separately so the secondary can be fired straight after a primary
+ if(time >= actor.shotgun_primarytime) // handle refire separately so the secondary can be fired straight after a primary
{
- if(weapon_prepareattack(0, WEP_CVAR_SEC(shotgun, alt_animtime)))
+ if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_SEC(shotgun, alt_animtime)))
{
- W_Shotgun_Attack(false);
- self.shotgun_primarytime = time + WEP_CVAR_SEC(shotgun, alt_refire) * W_WeaponRateFactor();
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), W_Shotgun_Attack3_Frame1);
+ W_Shotgun_Attack(thiswep, false);
+ actor.shotgun_primarytime = time + WEP_CVAR_SEC(shotgun, alt_refire) * W_WeaponRateFactor();
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), W_Shotgun_Attack3_Frame1);
}
}
}
}
- if(self.clip_load >= 0) // we are not currently reloading
- if(!self.crouch) // no crouchmelee please
+ if(actor.clip_load >= 0) // we are not currently reloading
+ if(!actor.crouch) // no crouchmelee please
if(WEP_CVAR(shotgun, secondary) == 1)
- if((self.BUTTON_ATCK && self.WEP_AMMO(SHOTGUN) <= 0 && !(self.items & IT_UNLIMITED_WEAPON_AMMO)) || self.BUTTON_ATCK2)
- if(weapon_prepareattack(1, WEP_CVAR_SEC(shotgun, refire)))
+ if((fire1 && actor.WEP_AMMO(SHOTGUN) <= 0 && !(actor.items & IT_UNLIMITED_WEAPON_AMMO)) || fire2)
+ if(weapon_prepareattack(thiswep, actor, true, WEP_CVAR_SEC(shotgun, refire)))
{
// attempt forcing playback of the anim by switching to another anim (that we never play) here...
- weapon_thinkf(WFRAME_FIRE1, 0, W_Shotgun_Attack2);
+ weapon_thinkf(actor, WFRAME_FIRE1, 0, W_Shotgun_Attack2);
}
-
- return true;
}
- case WR_INIT:
+ METHOD(Shotgun, wr_init, void(entity thiswep))
{
- precache_model("models/uziflash.md3");
- precache_model(W_Model("g_shotgun.md3"));
- precache_model(W_Model("v_shotgun.md3"));
- precache_model(W_Model("h_shotgun.iqm"));
- precache_sound("misc/itempickup.wav");
- precache_sound(W_Sound("shotgun_fire"));
- precache_sound(W_Sound("shotgun_melee"));
SHOTGUN_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
- return true;
}
- case WR_SETUP:
+ METHOD(Shotgun, wr_setup, void(entity thiswep))
{
self.ammo_field = ammo_none;
- return true;
}
- case WR_CHECKAMMO1:
+ METHOD(Shotgun, wr_checkammo1, bool(entity thiswep))
{
- ammo_amount = self.WEP_AMMO(SHOTGUN) >= WEP_CVAR_PRI(shotgun, ammo);
+ float ammo_amount = self.WEP_AMMO(SHOTGUN) >= WEP_CVAR_PRI(shotgun, ammo);
ammo_amount += self.(weapon_load[WEP_SHOTGUN.m_id]) >= WEP_CVAR_PRI(shotgun, ammo);
return ammo_amount;
}
- case WR_CHECKAMMO2:
+ METHOD(Shotgun, wr_checkammo2, bool(entity thiswep))
{
if(IS_BOT_CLIENT(self))
if(vlen(self.origin-self.enemy.origin) > WEP_CVAR_SEC(shotgun, melee_range))
case 1: return true; // melee does not use ammo
case 2: // secondary triple shot
{
- ammo_amount = self.WEP_AMMO(SHOTGUN) >= WEP_CVAR_PRI(shotgun, ammo);
+ float ammo_amount = self.WEP_AMMO(SHOTGUN) >= WEP_CVAR_PRI(shotgun, ammo);
ammo_amount += self.(weapon_load[WEP_SHOTGUN.m_id]) >= WEP_CVAR_PRI(shotgun, ammo);
return ammo_amount;
}
default: return false; // secondary unavailable
}
}
- case WR_CONFIG:
+ METHOD(Shotgun, wr_config, void(entity thiswep))
{
SHOTGUN_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
- return true;
}
- case WR_RELOAD:
+ METHOD(Shotgun, wr_reload, void(entity thiswep))
{
- W_Reload(WEP_CVAR_PRI(shotgun, ammo), W_Sound("reload")); // WEAPONTODO
- return true;
+ W_Reload(self, WEP_CVAR_PRI(shotgun, ammo), SND(RELOAD)); // WEAPONTODO
}
- case WR_SUICIDEMESSAGE:
+ METHOD(Shotgun, wr_suicidemessage, int(entity thiswep))
{
return WEAPON_THINKING_WITH_PORTALS;
}
- case WR_KILLMESSAGE:
+ METHOD(Shotgun, wr_killmessage, int(entity thiswep))
{
if(w_deathtype & HITTYPE_SECONDARY)
return WEAPON_SHOTGUN_MURDER_SLAP;
else
return WEAPON_SHOTGUN_MURDER;
}
- }
- return false;
-}
+
#endif
#ifdef CSQC
.float prevric;
-float W_Shotgun(float req)
-{
- switch(req)
- {
- case WR_IMPACTEFFECT:
+
+ METHOD(Shotgun, wr_impacteffect, void(entity thiswep))
{
- vector org2;
- org2 = w_org + w_backoff * 2;
+ vector org2 = w_org + w_backoff * 2;
pointparticles(particleeffectnum(EFFECT_SHOTGUN_IMPACT), org2, w_backoff * 1000, 1);
if(!w_issilent && time - self.prevric > 0.25)
{
if(w_random < 0.0165)
- sound(self, CH_SHOTS, W_Sound("ric1"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_RIC1, VOL_BASE, ATTEN_NORM);
else if(w_random < 0.033)
- sound(self, CH_SHOTS, W_Sound("ric2"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_RIC2, VOL_BASE, ATTEN_NORM);
else if(w_random < 0.05)
- sound(self, CH_SHOTS, W_Sound("ric3"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_RIC3, VOL_BASE, ATTEN_NORM);
self.prevric = time;
}
-
- return true;
- }
- case WR_INIT:
- {
- precache_sound(W_Sound("ric1"));
- precache_sound(W_Sound("ric2"));
- precache_sound(W_Sound("ric3"));
- return true;
}
- case WR_ZOOMRETICLE:
- {
- // no weapon specific image for this weapon
- return false;
- }
- }
- return false;
-}
+
#endif
#endif
#ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id */ TUBA,
-/* function */ W_Tuba,
-/* ammotype */ ammo_none,
-/* impulse */ 1,
-/* flags */ WEP_FLAG_HIDDEN | WEP_TYPE_SPLASH,
-/* rating */ BOT_PICKUP_RATING_MID,
-/* color */ '0 1 0',
-/* modelname */ "tuba",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairtuba",
-/* wepimg */ "weapontuba",
-/* refname */ "tuba",
+CLASS(Tuba, Weapon)
+/* ammotype */ //ATTRIB(Tuba, ammo_field, .int, ammo_none)
+/* impulse */ ATTRIB(Tuba, impulse, int, 1)
+/* flags */ ATTRIB(Tuba, spawnflags, int, WEP_FLAG_HIDDEN | WEP_TYPE_SPLASH);
+/* rating */ ATTRIB(Tuba, bot_pickupbasevalue, float, BOT_PICKUP_RATING_MID);
+/* color */ ATTRIB(Tuba, wpcolor, vector, '0 1 0');
+/* modelname */ ATTRIB(Tuba, mdl, string, "tuba");
+#ifndef MENUQC
+/* model */ ATTRIB(Tuba, m_model, Model, MDL_TUBA_ITEM);
+#endif
+/* crosshair */ ATTRIB(Tuba, w_crosshair, string, "gfx/crosshairtuba");
+/* crosshair */ //ATTRIB(Tuba, w_crosshair_size, float, 0.65);
+/* wepimg */ ATTRIB(Tuba, model2, string, "weapontuba");
+/* refname */ ATTRIB(Tuba, netname, string, "tuba");
/* xgettext:no-c-format */
-/* wepname */ _("@!#%'n Tuba")
-);
+/* wepname */ ATTRIB(Tuba, message, string, _("@!#%'n Tuba"));
+ENDCLASS(Tuba)
+REGISTER_WEAPON(TUBA, NEW(Tuba));
#define TUBA_SETTINGS(w_cvar,w_prop) TUBA_SETTINGS_LIST(w_cvar, w_prop, TUBA, tuba)
#define TUBA_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
#endif
#ifdef IMPLEMENTATION
#ifdef SVQC
-void spawnfunc_weapon_tuba(void) { weapon_defaultspawnfunc(WEP_TUBA.m_id); }
+spawnfunc(weapon_tuba) { weapon_defaultspawnfunc(WEP_TUBA.m_id); }
bool W_Tuba_HasPlayed(entity pl, string melody, int instrument, bool ignorepitch, float mintempo, float maxtempo)
{
}
void W_Tuba_NoteOff(void)
-{
+{SELFPARAM();
// we have a note:
// on: self.spawnshieldtime
// off: time
return note;
}
-bool W_Tuba_NoteSendEntity(entity to, int sf)
+bool W_Tuba_NoteSendEntity(entity this, entity to, int sf)
{
int f;
}
void W_Tuba_NoteThink(void)
-{
+{SELFPARAM();
float dist_mult;
float vol0, vol1;
vector dir0, dir1;
}
void W_Tuba_NoteOn(float hittype)
-{
+{SELFPARAM();
vector o;
float n;
{
if(self.tuba_note.cnt != n || self.tuba_note.tuba_instrument != self.tuba_instrument)
{
- entity oldself = self;
- self = self.tuba_note;
- W_Tuba_NoteOff();
- self = oldself;
+ WITH(entity, self, self.tuba_note, W_Tuba_NoteOff());
}
}
}
}
-bool W_Tuba(int req)
-{
- switch(req)
- {
- case WR_AIM:
+ METHOD(Tuba, wr_aim, void(entity thiswep))
{
// bots cannot play the Tuba well yet
// I think they should start with the recorder first
else
self.BUTTON_ATCK2 = 1;
}
-
- return true;
}
- case WR_THINK:
+ METHOD(Tuba, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
{
- if(self.BUTTON_ATCK)
- if(weapon_prepareattack(0, WEP_CVAR(tuba, refire)))
+ if(fire1)
+ if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR(tuba, refire)))
{
W_Tuba_NoteOn(0);
- //weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_tuba_animtime, w_ready);
- weapon_thinkf(WFRAME_IDLE, WEP_CVAR(tuba, animtime), w_ready);
+ //weapon_thinkf(actor, WFRAME_FIRE1, autocvar_g_balance_tuba_animtime, w_ready);
+ weapon_thinkf(actor, WFRAME_IDLE, WEP_CVAR(tuba, animtime), w_ready);
}
- if(self.BUTTON_ATCK2)
- if(weapon_prepareattack(1, WEP_CVAR(tuba, refire)))
+ if(fire2)
+ if(weapon_prepareattack(thiswep, actor, true, WEP_CVAR(tuba, refire)))
{
W_Tuba_NoteOn(HITTYPE_SECONDARY);
- //weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_tuba_animtime, w_ready);
- weapon_thinkf(WFRAME_IDLE, WEP_CVAR(tuba, animtime), w_ready);
+ //weapon_thinkf(actor, WFRAME_FIRE2, autocvar_g_balance_tuba_animtime, w_ready);
+ weapon_thinkf(actor, WFRAME_IDLE, WEP_CVAR(tuba, animtime), w_ready);
}
- if(self.tuba_note)
+ if(actor.tuba_note)
{
- if(!self.BUTTON_ATCK && !self.BUTTON_ATCK2)
+ if(!fire1 && !fire2)
{
- entity oldself = self;
- self = self.tuba_note;
- W_Tuba_NoteOff();
- self = oldself;
+ WITH(entity, self, actor.tuba_note, W_Tuba_NoteOff());
}
}
-
- return true;
}
- case WR_INIT:
+ METHOD(Tuba, wr_init, void(entity thiswep))
{
- precache_model(W_Model("g_tuba.md3"));
- precache_model(W_Model("v_tuba.md3"));
- precache_model(W_Model("h_tuba.iqm"));
- precache_model(W_Model("v_akordeon.md3"));
- precache_model(W_Model("h_akordeon.iqm"));
- precache_model(W_Model("v_kleinbottle.md3"));
- precache_model(W_Model("h_kleinbottle.iqm"));
TUBA_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
- return true;
}
- case WR_SETUP:
+ METHOD(Tuba, wr_setup, void(entity thiswep))
{
self.ammo_field = ammo_none;
self.tuba_instrument = 0;
- return true;
}
- case WR_RELOAD:
+ METHOD(Tuba, wr_reload, void(entity thiswep))
{
// switch to alternate instruments :)
if(self.weaponentity.state == WS_READY)
W_SetupShot(self, false, 0, "", 0, 0);
Send_Effect(EFFECT_TELEPORT, w_shotorg, '0 0 0', 1);
self.weaponentity.state = WS_INUSE;
- weapon_thinkf(WFRAME_RELOAD, 0.5, w_ready);
+ weapon_thinkf(self, WFRAME_RELOAD, 0.5, w_ready);
}
-
- return true;
}
- case WR_CHECKAMMO1:
- case WR_CHECKAMMO2:
+ METHOD(Tuba, wr_checkammo1, bool(entity thiswep))
+ {
+ return true; // infinite ammo
+ }
+ METHOD(Tuba, wr_checkammo2, bool(entity thiswep))
{
return true; // tuba has infinite ammo
}
- case WR_CONFIG:
+ METHOD(Tuba, wr_config, void(entity thiswep))
{
TUBA_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
- return true;
}
- case WR_SUICIDEMESSAGE:
+ METHOD(Tuba, wr_suicidemessage, int(entity thiswep))
{
if(w_deathtype & HITTYPE_BOUNCE)
return WEAPON_KLEINBOTTLE_SUICIDE;
else
return WEAPON_TUBA_SUICIDE;
}
- case WR_KILLMESSAGE:
+ METHOD(Tuba, wr_killmessage, int(entity thiswep))
{
if(w_deathtype & HITTYPE_BOUNCE)
return WEAPON_KLEINBOTTLE_MURDER;
else
return WEAPON_TUBA_MURDER;
}
- }
- return false;
-}
-#endif
-#ifdef CSQC
-bool W_Tuba(int req)
-{
- // nothing to do here; particles of tuba are handled differently
- // WEAPONTODO
- switch(req)
- {
- case WR_ZOOMRETICLE:
- {
- // no weapon specific image for this weapon
- return false;
- }
- }
-
- return false;
-}
#endif
#endif
#ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id */ VAPORIZER,
-/* function */ W_Vaporizer,
-/* ammotype */ ammo_cells,
-/* impulse */ 7,
-/* flags */ WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_FLAG_SUPERWEAPON | WEP_TYPE_HITSCAN,
-/* rating */ BOT_PICKUP_RATING_HIGH,
-/* color */ '0.5 1 1',
-/* modelname */ "minstanex",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairminstanex 0.6",
-/* wepimg */ "weaponminstanex",
-/* refname */ "vaporizer",
-/* wepname */ _("Vaporizer")
-);
+CLASS(Vaporizer, Weapon)
+/* ammotype */ ATTRIB(Vaporizer, ammo_field, .int, ammo_cells)
+/* impulse */ ATTRIB(Vaporizer, impulse, int, 7)
+/* flags */ ATTRIB(Vaporizer, spawnflags, int, WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_FLAG_SUPERWEAPON | WEP_TYPE_HITSCAN);
+/* rating */ ATTRIB(Vaporizer, bot_pickupbasevalue, float, BOT_PICKUP_RATING_HIGH);
+/* color */ ATTRIB(Vaporizer, wpcolor, vector, '0.5 1 1');
+/* modelname */ ATTRIB(Vaporizer, mdl, string, "minstanex");
+#ifndef MENUQC
+/* model */ ATTRIB(Vaporizer, m_model, Model, MDL_VAPORIZER_ITEM);
+#endif
+/* crosshair */ ATTRIB(Vaporizer, w_crosshair, string, "gfx/crosshairminstanex");
+/* crosshair */ ATTRIB(Vaporizer, w_crosshair_size, float, 0.6);
+/* wepimg */ ATTRIB(Vaporizer, model2, string, "weaponminstanex");
+/* refname */ ATTRIB(Vaporizer, netname, string, "vaporizer");
+/* wepname */ ATTRIB(Vaporizer, message, string, _("Vaporizer"));
+ENDCLASS(Vaporizer)
+REGISTER_WEAPON(VAPORIZER, NEW(Vaporizer));
#define VAPORIZER_SETTINGS(w_cvar,w_prop) VAPORIZER_SETTINGS_LIST(w_cvar, w_prop, VAPORIZER, vaporizer)
#define VAPORIZER_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
#endif
#ifdef IMPLEMENTATION
#ifdef SVQC
-void spawnfunc_weapon_vaporizer(void) { weapon_defaultspawnfunc(WEP_VAPORIZER.m_id); }
-void spawnfunc_weapon_minstanex(void) { spawnfunc_weapon_vaporizer(); }
+spawnfunc(weapon_vaporizer) { weapon_defaultspawnfunc(WEP_VAPORIZER.m_id); }
+spawnfunc(weapon_minstanex) { spawnfunc_weapon_vaporizer(this); }
void W_RocketMinsta_Explosion(vector loc)
-{
+{SELFPARAM();
if(accuracy_canbegooddamage(self))
accuracy_add(self, WEP_DEVASTATOR.m_id, autocvar_g_rm_damage, 0);
entity dmgent = spawn();
remove(dmgent);
}
-void W_Vaporizer_Attack(void)
-{
+void W_Vaporizer_Attack(Weapon thiswep)
+{SELFPARAM();
bool flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last
float vaporizer_damage = ((WEP_CVAR_PRI(vaporizer, damage) > 0) ? WEP_CVAR_PRI(vaporizer, damage) : 10000);
W_SetupShot(self, true, 0, "", CH_WEAPON_A, vaporizer_damage);
// handle sound separately so we can change the volume
// added bonus: no longer plays the strength sound (strength gives no bonus to instakill anyway)
- sound (self, CH_WEAPON_A, W_Sound("minstanexfire"), VOL_BASE * 0.8, ATTEN_NORM);
+ sound (self, CH_WEAPON_A, SND_MINSTANEXFIRE, VOL_BASE * 0.8, ATTEN_NORM);
yoda = 0;
damage_goodhits = 0;
Send_Effect(EFFECT_VORTEX_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
// teamcolor / hit beam effect
- vector v;
- v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
- switch(self.team)
- {
- case NUM_TEAM_1: // Red
- if(damage_goodhits)
- Send_Effect(EFFECT_VAPORIZER_RED_HIT, w_shotorg, v, 1);
- else
- Send_Effect(EFFECT_VAPORIZER_RED, w_shotorg, v, 1);
- break;
- case NUM_TEAM_2: // Blue
- if(damage_goodhits)
- Send_Effect(EFFECT_VAPORIZER_BLUE_HIT, w_shotorg, v, 1);
- else
- Send_Effect(EFFECT_VAPORIZER_BLUE, w_shotorg, v, 1);
- break;
- case NUM_TEAM_3: // Yellow
- if(damage_goodhits)
- Send_Effect(EFFECT_VAPORIZER_YELLOW_HIT, w_shotorg, v, 1);
- else
- Send_Effect(EFFECT_VAPORIZER_YELLOW, w_shotorg, v, 1);
- break;
- case NUM_TEAM_4: // Pink
- if(damage_goodhits)
- Send_Effect(EFFECT_VAPORIZER_PINK_HIT, w_shotorg, v, 1);
- else
- Send_Effect(EFFECT_VAPORIZER_PINK, w_shotorg, v, 1);
- break;
- default:
- if(damage_goodhits)
- Send_Effect_("TE_TEI_G3_HIT", w_shotorg, v, 1);
- else
- Send_Effect_("TE_TEI_G3", w_shotorg, v, 1);
- break;
- }
+ vector v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
+ Send_Effect((damage_goodhits ? EFFECT_VAPORIZER_HIT(self.team) : EFFECT_VAPORIZER(self.team)), w_shotorg, v, 1);
if(autocvar_g_rm)
if(!(trace_dphitq3surfaceflags & (Q3SURFACEFLAG_SKY | Q3SURFACEFLAG_NOIMPACT)))
W_RocketMinsta_Explosion(trace_endpos);
- W_DecreaseAmmo(((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo)));
+ W_DecreaseAmmo(thiswep, self, ((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo)));
}
void W_RocketMinsta_Laser_Explode (void)
-{
+{SELFPARAM();
if(other.takedamage == DAMAGE_AIM)
if(IS_PLAYER(other))
if(DIFF_TEAM(self.realowner, other))
}
void W_RocketMinsta_Laser_Touch (void)
-{
+{SELFPARAM();
PROJECTILE_TOUCH;
//W_RocketMinsta_Laser_Explode ();
RadiusDamage (self, self.realowner, self.rm_damage, self.rm_edmg, autocvar_g_rm_laser_radius, world, world, self.rm_force, self.projectiledeathtype, other);
}
void W_RocketMinsta_Attack2(void)
-{
+{SELFPARAM();
makevectors(self.v_angle);
-
+
entity proj;
float counter = 0;
float total = autocvar_g_rm_laser_count;
float w = self.weapon;
self.weapon = WEP_ELECTRO.m_id;
- W_SetupShot_ProjectileSize (self, '0 0 -3', '0 0 -3', false, 2, W_Sound("crylink_fire"), CH_WEAPON_A, autocvar_g_rm_laser_damage);
+ W_SetupShot_ProjectileSize (self, '0 0 -3', '0 0 -3', false, 2, SND(CRYLINK_FIRE), CH_WEAPON_A, autocvar_g_rm_laser_damage);
self.weapon = w;
Send_Effect(EFFECT_ELECTRO_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
PROJECTILE_MAKETRIGGER(proj);
proj.projectiledeathtype = WEP_ELECTRO.m_id;
setorigin(proj, w_shotorg);
-
+
proj.rm_force = autocvar_g_rm_laser_force / total;
proj.rm_damage = autocvar_g_rm_laser_damage / total;
proj.rm_edmg = proj.rm_damage;
-
+
//W_SetupProjectileVelocity(proj, autocvar_g_rm_laser_speed, spread * (rndspread ? random() : 1) * autocvar_g_rm_laser_speed);
proj.movetype = MOVETYPE_BOUNCEMISSILE;
}
void W_RocketMinsta_Attack3 (void)
-{
+{SELFPARAM();
makevectors(self.v_angle);
-
+
entity proj;
float counter = 0;
float total = 1;
int w = self.weapon;
self.weapon = WEP_ELECTRO.m_id;
- W_SetupShot_ProjectileSize (self, '0 0 -3', '0 0 -3', false, 2, W_Sound("electro_fire2"), CH_WEAPON_A, autocvar_g_rm_laser_damage);
+ W_SetupShot_ProjectileSize (self, '0 0 -3', '0 0 -3', false, 2, SND(ELECTRO_FIRE2), CH_WEAPON_A, autocvar_g_rm_laser_damage);
self.weapon = w;
Send_Effect(EFFECT_ELECTRO_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
PROJECTILE_MAKETRIGGER(proj);
proj.projectiledeathtype = WEP_ELECTRO.m_id;
setorigin(proj, w_shotorg);
-
+
proj.rm_force = autocvar_g_rm_laser_force / total;
proj.rm_damage = autocvar_g_rm_laser_damage / total;
proj.rm_edmg = proj.rm_damage;
-
+
//W_SetupProjectileVelocity(proj, autocvar_g_rm_laser_speed, spread * (rndspread ? random() : 1) * autocvar_g_rm_laser_speed);
proj.movetype = MOVETYPE_BOUNCEMISSILE;
}
}
-float W_Vaporizer(float req)
-{
- float ammo_amount;
- float vaporizer_ammo;
- float rapid = autocvar_g_rm_laser_rapid;
-
- // now multiple WR_s use this
- vaporizer_ammo = ((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
-
- switch(req)
- {
- case WR_AIM:
+ METHOD(Vaporizer, wr_aim, void(entity thiswep))
{
if(self.WEP_AMMO(VAPORIZER) > 0)
self.BUTTON_ATCK = bot_aim(1000000, 0, 1, false);
else
self.BUTTON_ATCK2 = bot_aim(WEP_CVAR_SEC(vaporizer, speed), 0, WEP_CVAR_SEC(vaporizer, lifetime), false); // WEAPONTODO: replace with proper vaporizer cvars
-
- return true;
}
- case WR_THINK:
+ METHOD(Vaporizer, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
{
+ float vaporizer_ammo = ((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
// if the laser uses load, we also consider its ammo for reloading
- if(WEP_CVAR(vaporizer, reload_ammo) && WEP_CVAR_SEC(vaporizer, ammo) && self.clip_load < min(vaporizer_ammo, WEP_CVAR_SEC(vaporizer, ammo))) // forced reload
- WEP_ACTION(self.weapon, WR_RELOAD);
- else if(WEP_CVAR(vaporizer, reload_ammo) && self.clip_load < vaporizer_ammo) // forced reload
- WEP_ACTION(self.weapon, WR_RELOAD);
- if(self.BUTTON_ATCK && (self.ammo_cells || !autocvar_g_rm) && !forbidWeaponUse(self))
+ if(WEP_CVAR(vaporizer, reload_ammo) && WEP_CVAR_SEC(vaporizer, ammo) && actor.clip_load < min(vaporizer_ammo, WEP_CVAR_SEC(vaporizer, ammo))) { // forced reload
+ Weapon w = get_weaponinfo(actor.weapon);
+ w.wr_reload(w);
+ } else if(WEP_CVAR(vaporizer, reload_ammo) && actor.clip_load < vaporizer_ammo) { // forced reload
+ Weapon w = get_weaponinfo(actor.weapon);
+ w.wr_reload(w);
+ }
+ if(fire1 && (actor.ammo_cells || !autocvar_g_rm) && !forbidWeaponUse(actor))
{
- if(weapon_prepareattack(0, WEP_CVAR_PRI(vaporizer, refire)))
+ if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(vaporizer, refire)))
{
- W_Vaporizer_Attack();
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(vaporizer, animtime), w_ready);
+ W_Vaporizer_Attack(thiswep);
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(vaporizer, animtime), w_ready);
}
}
- if(self.BUTTON_ATCK2 || (self.BUTTON_ATCK && !self.ammo_cells && autocvar_g_rm))
+ if(fire2 || (fire1 && !actor.ammo_cells && autocvar_g_rm))
{
if((autocvar_g_rm && autocvar_g_rm_laser) || autocvar_g_rm_laser == 2)
{
- if(self.jump_interval <= time && !self.held_down)
+ bool rapid = autocvar_g_rm_laser_rapid;
+ if(actor.jump_interval <= time && !actor.held_down)
{
if(rapid)
- self.held_down = true;
- self.jump_interval = time + autocvar_g_rm_laser_refire;
- self.jump_interval2 = time + autocvar_g_rm_laser_rapid_delay;
+ actor.held_down = true;
+ actor.jump_interval = time + autocvar_g_rm_laser_refire;
+ actor.jump_interval2 = time + autocvar_g_rm_laser_rapid_delay;
damage_goodhits = 0;
W_RocketMinsta_Attack2();
}
- else if(rapid && self.jump_interval2 <= time && self.held_down)
+ else if(rapid && actor.jump_interval2 <= time && actor.held_down)
{
- self.jump_interval2 = time + autocvar_g_rm_laser_rapid_refire;
+ actor.jump_interval2 = time + autocvar_g_rm_laser_rapid_refire;
damage_goodhits = 0;
W_RocketMinsta_Attack3();
- //weapon_thinkf(WFRAME_FIRE2, autocvar_g_rm_laser_rapid_animtime, w_ready);
+ //weapon_thinkf(actor, WFRAME_FIRE2, autocvar_g_rm_laser_rapid_animtime, w_ready);
}
}
- else if (self.jump_interval <= time)
+ else if (actor.jump_interval <= time)
{
// handle refire manually, so that primary and secondary can be fired without conflictions (important for instagib)
- self.jump_interval = time + WEP_CVAR_SEC(vaporizer, refire) * W_WeaponRateFactor();
+ actor.jump_interval = time + WEP_CVAR_SEC(vaporizer, refire) * W_WeaponRateFactor();
// decrease ammo for the laser?
if(WEP_CVAR_SEC(vaporizer, ammo))
- W_DecreaseAmmo(WEP_CVAR_SEC(vaporizer, ammo));
+ W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(vaporizer, ammo));
// ugly instagib hack to reuse the fire mode of the laser
- makevectors(self.v_angle);
- int oldwep = self.weapon; // we can't avoid this hack
- self.weapon = WEP_BLASTER.m_id;
+ makevectors(actor.v_angle);
+ int oldwep = actor.weapon; // we can't avoid this hack
+ actor.weapon = WEP_BLASTER.m_id;
W_Blaster_Attack(
+ actor,
WEP_BLASTER.m_id | HITTYPE_SECONDARY,
WEP_CVAR_SEC(vaporizer, shotangle),
WEP_CVAR_SEC(vaporizer, damage),
WEP_CVAR_SEC(vaporizer, delay),
WEP_CVAR_SEC(vaporizer, lifetime)
);
- self.weapon = oldwep;
+ actor.weapon = oldwep;
// now do normal refire
- weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(vaporizer, animtime), w_ready);
+ weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR_SEC(vaporizer, animtime), w_ready);
}
}
else
- self.held_down = false;
-
- return true;
+ actor.held_down = false;
}
- case WR_INIT:
+ METHOD(Vaporizer, wr_init, void(entity thiswep))
{
- precache_model("models/nexflash.md3");
- precache_model(W_Model("g_minstanex.md3"));
- precache_model(W_Model("v_minstanex.md3"));
- precache_model(W_Model("h_minstanex.iqm"));
- precache_sound(W_Sound("minstanexfire"));
- precache_sound(W_Sound("nexwhoosh1"));
- precache_sound(W_Sound("nexwhoosh2"));
- precache_sound(W_Sound("nexwhoosh3"));
//W_Blaster(WR_INIT); // Samual: Is this really the proper thing to do? Didn't we already run this previously?
VAPORIZER_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
- return true;
}
- case WR_SETUP:
+ METHOD(Vaporizer, wr_setup, void(entity thiswep))
{
self.ammo_field = WEP_AMMO(VAPORIZER);
self.vaporizer_lasthit = 0;
- return true;
}
- case WR_CHECKAMMO1:
+ METHOD(Vaporizer, wr_checkammo1, bool(entity thiswep))
{
- ammo_amount = self.WEP_AMMO(VAPORIZER) >= vaporizer_ammo;
+ float vaporizer_ammo = ((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
+ float ammo_amount = self.WEP_AMMO(VAPORIZER) >= vaporizer_ammo;
ammo_amount += self.(weapon_load[WEP_VAPORIZER.m_id]) >= vaporizer_ammo;
return ammo_amount;
}
- case WR_CHECKAMMO2:
+ METHOD(Vaporizer, wr_checkammo2, bool(entity thiswep))
{
if(!WEP_CVAR_SEC(vaporizer, ammo))
return true;
- ammo_amount = self.WEP_AMMO(VAPORIZER) >= WEP_CVAR_SEC(vaporizer, ammo);
+ float ammo_amount = self.WEP_AMMO(VAPORIZER) >= WEP_CVAR_SEC(vaporizer, ammo);
ammo_amount += self.(weapon_load[WEP_VAPORIZER.m_id]) >= WEP_CVAR_SEC(vaporizer, ammo);
return ammo_amount;
}
- case WR_CONFIG:
+ METHOD(Vaporizer, wr_config, void(entity thiswep))
{
VAPORIZER_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
- return true;
}
- case WR_RESETPLAYER:
+ METHOD(Vaporizer, wr_resetplayer, void(entity thiswep))
{
self.vaporizer_lasthit = 0;
- return true;
}
- case WR_RELOAD:
+ METHOD(Vaporizer, wr_reload, void(entity thiswep))
{
+ float vaporizer_ammo = ((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
float used_ammo;
if(WEP_CVAR_SEC(vaporizer, ammo))
used_ammo = min(vaporizer_ammo, WEP_CVAR_SEC(vaporizer, ammo));
else
used_ammo = vaporizer_ammo;
- W_Reload(used_ammo, W_Sound("reload"));
- return true;
+ W_Reload(self, used_ammo, SND(RELOAD));
}
- case WR_SUICIDEMESSAGE:
+ METHOD(Vaporizer, wr_suicidemessage, int(entity thiswep))
{
return WEAPON_THINKING_WITH_PORTALS;
}
- case WR_KILLMESSAGE:
+ METHOD(Vaporizer, wr_killmessage, int(entity thiswep))
{
return WEAPON_VAPORIZER_MURDER;
}
- }
- return false;
-}
+
#endif
#ifdef CSQC
-float W_Vaporizer(float req)
-{
- switch(req)
- {
- case WR_IMPACTEFFECT:
+
+ METHOD(Vaporizer, wr_impacteffect, void(entity thiswep))
{
vector org2 = w_org + w_backoff * 6;
if(w_deathtype & HITTYPE_SECONDARY)
{
pointparticles(particleeffectnum(EFFECT_BLASTER_IMPACT), org2, w_backoff * 1000, 1);
- if(!w_issilent) { sound(self, CH_SHOTS, W_Sound("laserimpact"), VOL_BASE, ATTN_NORM); }
+ if(!w_issilent) { sound(self, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTN_NORM); }
}
else
{
pointparticles(particleeffectnum(EFFECT_VORTEX_IMPACT), org2, '0 0 0', 1);
- if(!w_issilent) { sound(self, CH_SHOTS, W_Sound("neximpact"), VOL_BASE, ATTN_NORM); }
+ if(!w_issilent) { sound(self, CH_SHOTS, SND_NEXIMPACT, VOL_BASE, ATTN_NORM); }
}
- return true;
}
- case WR_INIT:
+ METHOD(Vaporizer, wr_init, void(entity thiswep))
{
- precache_sound(W_Sound("laserimpact"));
- precache_sound(W_Sound("neximpact"));
if(autocvar_cl_reticle && autocvar_cl_reticle_weapon)
{
precache_pic("gfx/reticle_nex");
}
- return true;
}
- case WR_ZOOMRETICLE:
+ METHOD(Vaporizer, wr_zoomreticle, bool(entity thiswep))
{
if(button_zoom || zoomscript_caught)
{
return false;
}
}
- }
- return false;
-}
+
#endif
#endif
#ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id */ VORTEX,
-/* function */ W_Vortex,
-/* ammotype */ ammo_cells,
-/* impulse */ 7,
-/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN,
-/* rating */ BOT_PICKUP_RATING_HIGH,
-/* color */ '0.5 1 1',
-/* modelname */ "nex",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairnex 0.65",
-/* wepimg */ "weaponnex",
-/* refname */ "vortex",
-/* wepname */ _("Vortex")
-);
+CLASS(Vortex, Weapon)
+/* ammotype */ ATTRIB(Vortex, ammo_field, .int, ammo_cells)
+/* impulse */ ATTRIB(Vortex, impulse, int, 7)
+/* flags */ ATTRIB(Vortex, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN);
+/* rating */ ATTRIB(Vortex, bot_pickupbasevalue, float, BOT_PICKUP_RATING_HIGH);
+/* color */ ATTRIB(Vortex, wpcolor, vector, '0.5 1 1');
+/* modelname */ ATTRIB(Vortex, mdl, string, "nex");
+#ifndef MENUQC
+/* model */ ATTRIB(Vortex, m_model, Model, MDL_VORTEX_ITEM);
+#endif
+/* crosshair */ ATTRIB(Vortex, w_crosshair, string, "gfx/crosshairnex");
+/* crosshair */ ATTRIB(Vortex, w_crosshair_size, float, 0.65);
+/* wepimg */ ATTRIB(Vortex, model2, string, "weaponnex");
+/* refname */ ATTRIB(Vortex, netname, string, "vortex");
+/* wepname */ ATTRIB(Vortex, message, string, _("Vortex"));
+ENDCLASS(Vortex)
+REGISTER_WEAPON(VORTEX, NEW(Vortex));
#define VORTEX_SETTINGS(w_cvar,w_prop) VORTEX_SETTINGS_LIST(w_cvar, w_prop, VORTEX, vortex)
#define VORTEX_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
#endif
#ifdef IMPLEMENTATION
#ifdef SVQC
-void spawnfunc_weapon_vortex(void) { weapon_defaultspawnfunc(WEP_VORTEX.m_id); }
-void spawnfunc_weapon_nex(void) { spawnfunc_weapon_vortex(); }
+spawnfunc(weapon_vortex) { weapon_defaultspawnfunc(WEP_VORTEX.m_id); }
+spawnfunc(weapon_nex) { spawnfunc_weapon_vortex(this); }
void SendCSQCVortexBeamParticle(float charge) {
vector v;
WriteByte(MSG_BROADCAST, bound(0, 255 * charge, 255));
}
-void W_Vortex_Attack(float issecondary)
-{
+void W_Vortex_Attack(Weapon thiswep, float issecondary)
+{SELFPARAM();
float mydmg, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, myammo, charge;
mydmg = WEP_CVAR_BOTH(vortex, !issecondary, damage);
mydmg *= charge;
myforce *= charge;
- W_SetupShot(self, true, 5, W_Sound("nexfire"), CH_WEAPON_A, mydmg);
+ W_SetupShot(self, true, 5, SND(NEXFIRE), CH_WEAPON_A, mydmg);
if(charge > WEP_CVAR(vortex, charge_animlimit) && WEP_CVAR(vortex, charge_animlimit)) // if the Vortex is overcharged, we play an extra sound
{
- sound(self, CH_WEAPON_B, W_Sound("nexcharge"), VOL_BASE * (charge - 0.5 * WEP_CVAR(vortex, charge_animlimit)) / (1 - 0.5 * WEP_CVAR(vortex, charge_animlimit)), ATTN_NORM);
+ sound(self, CH_WEAPON_B, SND_NEXCHARGE, VOL_BASE * (charge - 0.5 * WEP_CVAR(vortex, charge_animlimit)) / (1 - 0.5 * WEP_CVAR(vortex, charge_animlimit)), ATTN_NORM);
}
yoda = 0;
//beam and muzzle flash done on client
SendCSQCVortexBeamParticle(charge);
- W_DecreaseAmmo(myammo);
+ W_DecreaseAmmo(thiswep, self, myammo);
}
-void spawnfunc_weapon_vortex(void); // defined in t_items.qc
-
.float vortex_chargepool_pauseregen_finished;
-bool W_Vortex(int req)
-{
- float dt;
- float ammo_amount;
- switch(req)
- {
- case WR_AIM:
+
+ METHOD(Vortex, wr_aim, void(entity thiswep))
{
if(bot_aim(1000000, 0, 1, false))
self.BUTTON_ATCK = true;
if(WEP_CVAR(vortex, charge))
self.BUTTON_ATCK2 = true;
}
- return true;
}
- case WR_THINK:
+ METHOD(Vortex, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
{
- if(WEP_CVAR(vortex, charge) && self.vortex_charge < WEP_CVAR(vortex, charge_limit))
- self.vortex_charge = min(1, self.vortex_charge + WEP_CVAR(vortex, charge_rate) * frametime / W_TICSPERFRAME);
+ if(WEP_CVAR(vortex, charge) && actor.vortex_charge < WEP_CVAR(vortex, charge_limit))
+ actor.vortex_charge = min(1, actor.vortex_charge + WEP_CVAR(vortex, charge_rate) * frametime / W_TICSPERFRAME);
if(WEP_CVAR_SEC(vortex, chargepool))
- if(self.vortex_chargepool_ammo < 1)
+ if(actor.vortex_chargepool_ammo < 1)
{
- if(self.vortex_chargepool_pauseregen_finished < time)
- self.vortex_chargepool_ammo = min(1, self.vortex_chargepool_ammo + WEP_CVAR_SEC(vortex, chargepool_regen) * frametime / W_TICSPERFRAME);
- self.pauseregen_finished = max(self.pauseregen_finished, time + WEP_CVAR_SEC(vortex, chargepool_pause_regen));
+ if(actor.vortex_chargepool_pauseregen_finished < time)
+ actor.vortex_chargepool_ammo = min(1, actor.vortex_chargepool_ammo + WEP_CVAR_SEC(vortex, chargepool_regen) * frametime / W_TICSPERFRAME);
+ actor.pauseregen_finished = max(actor.pauseregen_finished, time + WEP_CVAR_SEC(vortex, chargepool_pause_regen));
}
- if(autocvar_g_balance_vortex_reload_ammo && self.clip_load < min(WEP_CVAR_PRI(vortex, ammo), WEP_CVAR_SEC(vortex, ammo))) // forced reload
- WEP_ACTION(self.weapon, WR_RELOAD);
- else
+ if(autocvar_g_balance_vortex_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(vortex, ammo), WEP_CVAR_SEC(vortex, ammo))) { // forced reload
+ Weapon w = get_weaponinfo(actor.weapon);
+ w.wr_reload(w);
+ } else
{
- if(self.BUTTON_ATCK)
+ if(fire1)
{
- if(weapon_prepareattack(0, WEP_CVAR_PRI(vortex, refire)))
+ if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(vortex, refire)))
{
- W_Vortex_Attack(0);
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(vortex, animtime), w_ready);
+ W_Vortex_Attack(thiswep, 0);
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(vortex, animtime), w_ready);
}
}
- if((WEP_CVAR(vortex, charge) && !WEP_CVAR(vortex, secondary)) ? (self.BUTTON_ZOOM | self.BUTTON_ZOOMSCRIPT) : self.BUTTON_ATCK2)
+ if((WEP_CVAR(vortex, charge) && !WEP_CVAR(vortex, secondary)) ? (actor.BUTTON_ZOOM | actor.BUTTON_ZOOMSCRIPT) : fire2)
{
if(WEP_CVAR(vortex, charge))
{
- self.vortex_charge_rottime = time + WEP_CVAR(vortex, charge_rot_pause);
- dt = frametime / W_TICSPERFRAME;
+ actor.vortex_charge_rottime = time + WEP_CVAR(vortex, charge_rot_pause);
+ float dt = frametime / W_TICSPERFRAME;
- if(self.vortex_charge < 1)
+ if(actor.vortex_charge < 1)
{
if(WEP_CVAR_SEC(vortex, chargepool))
{
if(WEP_CVAR_SEC(vortex, ammo))
{
// always deplete if secondary is held
- self.vortex_chargepool_ammo = max(0, self.vortex_chargepool_ammo - WEP_CVAR_SEC(vortex, ammo) * dt);
+ actor.vortex_chargepool_ammo = max(0, actor.vortex_chargepool_ammo - WEP_CVAR_SEC(vortex, ammo) * dt);
- dt = min(dt, (1 - self.vortex_charge) / WEP_CVAR(vortex, charge_rate));
- self.vortex_chargepool_pauseregen_finished = time + WEP_CVAR_SEC(vortex, chargepool_pause_regen);
- dt = min(dt, self.vortex_chargepool_ammo);
+ dt = min(dt, (1 - actor.vortex_charge) / WEP_CVAR(vortex, charge_rate));
+ actor.vortex_chargepool_pauseregen_finished = time + WEP_CVAR_SEC(vortex, chargepool_pause_regen);
+ dt = min(dt, actor.vortex_chargepool_ammo);
dt = max(0, dt);
- self.vortex_charge += dt * WEP_CVAR(vortex, charge_rate);
+ actor.vortex_charge += dt * WEP_CVAR(vortex, charge_rate);
}
}
else if(WEP_CVAR_SEC(vortex, ammo))
{
- if(self.BUTTON_ATCK2) // only eat ammo when the button is pressed
+ if(fire2) // only eat ammo when the button is pressed
{
- dt = min(dt, (1 - self.vortex_charge) / WEP_CVAR(vortex, charge_rate));
- if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+ dt = min(dt, (1 - actor.vortex_charge) / WEP_CVAR(vortex, charge_rate));
+ if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
// if this weapon is reloadable, decrease its load. Else decrease the player's ammo
if(autocvar_g_balance_vortex_reload_ammo)
{
- dt = min(dt, (self.clip_load - WEP_CVAR_PRI(vortex, ammo)) / WEP_CVAR_SEC(vortex, ammo));
+ dt = min(dt, (actor.clip_load - WEP_CVAR_PRI(vortex, ammo)) / WEP_CVAR_SEC(vortex, ammo));
dt = max(0, dt);
if(dt > 0)
{
- self.clip_load = max(WEP_CVAR_SEC(vortex, ammo), self.clip_load - WEP_CVAR_SEC(vortex, ammo) * dt);
+ actor.clip_load = max(WEP_CVAR_SEC(vortex, ammo), actor.clip_load - WEP_CVAR_SEC(vortex, ammo) * dt);
}
- self.(weapon_load[WEP_VORTEX.m_id]) = self.clip_load;
+ actor.(weapon_load[WEP_VORTEX.m_id]) = actor.clip_load;
}
else
{
- dt = min(dt, (self.WEP_AMMO(VORTEX) - WEP_CVAR_PRI(vortex, ammo)) / WEP_CVAR_SEC(vortex, ammo));
+ dt = min(dt, (actor.WEP_AMMO(VORTEX) - WEP_CVAR_PRI(vortex, ammo)) / WEP_CVAR_SEC(vortex, ammo));
dt = max(0, dt);
if(dt > 0)
{
- self.WEP_AMMO(VORTEX) = max(WEP_CVAR_SEC(vortex, ammo), self.WEP_AMMO(VORTEX) - WEP_CVAR_SEC(vortex, ammo) * dt);
+ actor.WEP_AMMO(VORTEX) = max(WEP_CVAR_SEC(vortex, ammo), actor.WEP_AMMO(VORTEX) - WEP_CVAR_SEC(vortex, ammo) * dt);
}
}
}
- self.vortex_charge += dt * WEP_CVAR(vortex, charge_rate);
+ actor.vortex_charge += dt * WEP_CVAR(vortex, charge_rate);
}
}
else
{
- dt = min(dt, (1 - self.vortex_charge) / WEP_CVAR(vortex, charge_rate));
- self.vortex_charge += dt * WEP_CVAR(vortex, charge_rate);
+ dt = min(dt, (1 - actor.vortex_charge) / WEP_CVAR(vortex, charge_rate));
+ actor.vortex_charge += dt * WEP_CVAR(vortex, charge_rate);
}
}
}
else if(WEP_CVAR(vortex, secondary))
{
- if(weapon_prepareattack(0, WEP_CVAR_SEC(vortex, refire)))
+ if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_SEC(vortex, refire)))
{
- W_Vortex_Attack(1);
- weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_SEC(vortex, animtime), w_ready);
+ W_Vortex_Attack(thiswep, 1);
+ weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_SEC(vortex, animtime), w_ready);
}
}
}
}
-
- return true;
}
- case WR_INIT:
+ METHOD(Vortex, wr_init, void(entity thiswep))
{
- precache_model("models/nexflash.md3");
- precache_model(W_Model("g_nex.md3"));
- precache_model(W_Model("v_nex.md3"));
- precache_model(W_Model("h_nex.iqm"));
- precache_sound(W_Sound("nexfire"));
- precache_sound(W_Sound("nexcharge"));
- precache_sound(W_Sound("nexwhoosh1"));
- precache_sound(W_Sound("nexwhoosh2"));
- precache_sound(W_Sound("nexwhoosh3"));
VORTEX_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
- return true;
}
- case WR_SETUP:
+ METHOD(Vortex, wr_setup, void(entity thiswep))
{
self.vortex_lasthit = 0;
- return true;
}
- case WR_CHECKAMMO1:
+ METHOD(Vortex, wr_checkammo1, bool(entity thiswep))
{
- ammo_amount = self.WEP_AMMO(VORTEX) >= WEP_CVAR_PRI(vortex, ammo);
+ float ammo_amount = self.WEP_AMMO(VORTEX) >= WEP_CVAR_PRI(vortex, ammo);
ammo_amount += (autocvar_g_balance_vortex_reload_ammo && self.(weapon_load[WEP_VORTEX.m_id]) >= WEP_CVAR_PRI(vortex, ammo));
return ammo_amount;
}
- case WR_CHECKAMMO2:
+ METHOD(Vortex, wr_checkammo2, bool(entity thiswep))
{
if(WEP_CVAR(vortex, secondary))
{
// don't allow charging if we don't have enough ammo
- ammo_amount = self.WEP_AMMO(VORTEX) >= WEP_CVAR_SEC(vortex, ammo);
+ float ammo_amount = self.WEP_AMMO(VORTEX) >= WEP_CVAR_SEC(vortex, ammo);
ammo_amount += self.(weapon_load[WEP_VORTEX.m_id]) >= WEP_CVAR_SEC(vortex, ammo);
return ammo_amount;
}
return false; // zoom is not a fire mode
}
}
- case WR_CONFIG:
+ METHOD(Vortex, wr_config, void(entity thiswep))
{
VORTEX_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
- return true;
}
- case WR_RESETPLAYER:
+ METHOD(Vortex, wr_resetplayer, void(entity thiswep))
{
self.vortex_lasthit = 0;
- return true;
}
- case WR_RELOAD:
+ METHOD(Vortex, wr_reload, void(entity thiswep))
{
- W_Reload(min(WEP_CVAR_PRI(vortex, ammo), WEP_CVAR_SEC(vortex, ammo)), W_Sound("reload"));
- return true;
+ W_Reload(self, min(WEP_CVAR_PRI(vortex, ammo), WEP_CVAR_SEC(vortex, ammo)), SND(RELOAD));
}
- case WR_SUICIDEMESSAGE:
+ METHOD(Vortex, wr_suicidemessage, int(entity thiswep))
{
return WEAPON_THINKING_WITH_PORTALS;
}
- case WR_KILLMESSAGE:
+ METHOD(Vortex, wr_killmessage, int(entity thiswep))
{
return WEAPON_VORTEX_MURDER;
}
- }
- return false;
-}
+
#endif
#ifdef CSQC
float autocvar_g_balance_vortex_secondary = 0; // WEAPONTODO
-bool W_Vortex(int req)
-{
- switch(req)
- {
- case WR_IMPACTEFFECT:
+
+ METHOD(Vortex, wr_impacteffect, void(entity thiswep))
{
- vector org2;
- org2 = w_org + w_backoff * 6;
+ vector org2 = w_org + w_backoff * 6;
pointparticles(particleeffectnum(EFFECT_VORTEX_IMPACT), org2, '0 0 0', 1);
if(!w_issilent)
- sound(self, CH_SHOTS, W_Sound("neximpact"), VOL_BASE, ATTN_NORM);
-
- return true;
+ sound(self, CH_SHOTS, SND_NEXIMPACT, VOL_BASE, ATTN_NORM);
}
- case WR_INIT:
+ METHOD(Vortex, wr_init, void(entity thiswep))
{
- precache_sound(W_Sound("neximpact"));
if(autocvar_cl_reticle && autocvar_cl_reticle_weapon)
{
precache_pic("gfx/reticle_nex");
}
- return true;
}
- case WR_ZOOMRETICLE:
+ METHOD(Vortex, wr_zoomreticle, bool(entity thiswep))
{
if(button_zoom || zoomscript_caught || (!WEP_CVAR(vortex, secondary) && button_attack2))
{
return false;
}
}
- }
- return false;
-}
+
#endif
#endif
.float csqcmodel_lerpfrac2time;
void CSQCModel_InterpolateAnimation_2To4_PreNote(int sf)
-{
+{SELFPARAM();
if(sf & CSQCMODEL_PROPERTY_FRAME)
{
self.frame3 = self.frame;
}
}
void CSQCModel_InterpolateAnimation_1To2_PreNote(int sf)
-{
+{SELFPARAM();
if(sf & CSQCMODEL_PROPERTY_FRAME)
{
self.frame2 = self.frame;
}
void CSQCModel_InterpolateAnimation_2To4_Note(int sf, float set_times)
-{
+{SELFPARAM();
if(sf & CSQCMODEL_PROPERTY_FRAME)
{
if(set_times)
}
}
void CSQCModel_InterpolateAnimation_1To2_Note(int sf, float set_times)
-{
+{SELFPARAM();
if(sf & CSQCMODEL_PROPERTY_FRAME)
{
if(set_times)
}
void CSQCModel_InterpolateAnimation_2To4_Do()
-{
+{SELFPARAM();
if(autocvar_cl_nolerp || (autocvar_cl_lerpanim_maxdelta_framegroups == 0))
{
self.lerpfrac = self.csqcmodel_lerpfrac;
}
}
void CSQCModel_InterpolateAnimation_1To2_Do()
-{
+{SELFPARAM();
if(autocvar_cl_nolerp || (autocvar_cl_lerpanim_maxdelta_framegroups == 0))
{
self.lerpfrac = 0;
}
void CSQCModel_Draw()
-{
+{SELFPARAM();
// some nice flags for CSQCMODEL_IF and the hooks
bool isplayer = (self.entnum >= 1 && self.entnum <= maxclients);
noref bool islocalplayer = (self.entnum == player_localnum + 1);
}
void CSQCModel_Read(bool isnew)
-{
+{SELFPARAM();
int sf = ReadInt24_t();
// some nice flags for CSQCMODEL_IF and the hooks
}
void CSQCPlayer_Unpredict()
-{
+{SELFPARAM();
if(csqcplayer_status == CSQCPLAYERSTATUS_UNPREDICTED)
return;
if(csqcplayer_status != CSQCPLAYERSTATUS_PREDICTED)
}
void CSQCPlayer_SetMinsMaxs()
-{
+{SELFPARAM();
if(self.flags & FL_DUCKED)
{
self.mins = PL_CROUCH_MIN;
}
void CSQCPlayer_SavePrediction()
-{
+{SELFPARAM();
player_pmflags = self.flags;
csqcplayer_origin = self.origin;
csqcplayer_velocity = self.velocity;
void CSQC_ClientMovement_PlayerMove_Frame();
void PM_Movement_Move()
-{
+{SELFPARAM();
runstandardplayerphysics(self);
#ifdef CSQC
self.flags =
}
void CSQCPlayer_PredictTo(float endframe, float apply_error)
-{
+{SELFPARAM();
CSQCPlayer_Unpredict();
if(apply_error)
{
}
bool CSQCPlayer_IsLocalPlayer()
-{
+{SELFPARAM();
return (self == csqcplayer);
}
}
void CSQCPlayer_SetCamera()
-{
+{SELFPARAM();
vector v0;
v0 = pmove_vel; // TRICK: pmove_vel is set by the engine when we get here. No need to network velocity
if(csqcplayer)
{
- entity oldself;
- oldself = self;
- self = csqcplayer;
+ setself(csqcplayer);
if(servercommandframe == 0 || clientcommandframe == 0)
{
// relink
setorigin(self, self.origin);
- self = oldself;
+ setself(this);
}
- entity view;
- view = CSQCModel_server2csqc(player_localentnum);
+ entity view = CSQCModel_server2csqc(player_localentnum);
if(view && view != csqcplayer)
{
- entity oldself = self;
- self = view;
- InterpolateOrigin_Do();
- self.view_ofs = '0 0 1' * getstati(STAT_VIEWHEIGHT);
- self = oldself;
+ WITH(entity, self, view, InterpolateOrigin_Do());
+ view.view_ofs = '0 0 1' * getstati(STAT_VIEWHEIGHT);
}
if(view)
}
float CSQCPlayer_PreUpdate()
-{
+{SELFPARAM();
if(self != csqcplayer)
return 0;
if(csqcplayer_status != CSQCPLAYERSTATUS_FROMSERVER)
}
float CSQCPlayer_PostUpdate()
-{
+{SELFPARAM();
if(self.entnum != player_localnum + 1)
return 0;
csqcplayer = self;
.vector ivup1, ivup2;
.float itime1, itime2;
void InterpolateOrigin_Reset()
-{
+{SELFPARAM();
self.iflags &= ~IFLAG_INTERNALMASK;
self.itime1 = self.itime2 = 0;
}
void InterpolateOrigin_Note()
-{
+{SELFPARAM();
float dt;
int f0;
}
}
void InterpolateOrigin_Do()
-{
+{SELFPARAM();
vector forward, up;
if(self.itime1 && self.itime2 && self.itime1 != self.itime2)
{
}
}
void InterpolateOrigin_Undo()
-{
+{SELFPARAM();
if(self.iflags & IFLAG_ORIGIN)
setorigin(self, self.iorigin2);
if(self.iflags & IFLAG_ANGLES)
// generic CSQC model code
bool CSQCModel_Send(entity to, int sf)
-{
+{SELFPARAM();
// some nice flags for CSQCMODEL_IF
float isplayer = (IS_CLIENT(self));
float islocalplayer = (self == to);
#ifdef CSQCPLAYER_FORCE_UPDATES
.float csqcmodel_nextforcedupdate;
#endif
-void CSQCModel_CheckUpdate()
+void CSQCModel_CheckUpdate(entity e)
{
// some nice flags for CSQCMODEL_IF
- float isplayer = (IS_CLIENT(self));
+ float isplayer = (IS_CLIENT(e));
float islocalplayer = isplayer; // we set BOTH to 1 here as we need the sendflags
float isnolocalplayer = isplayer; // we set BOTH to 1 here as we need the sendflags
unused_float = isnolocalplayer;
#ifdef CSQCPLAYER_FORCE_UPDATES
- if(isplayer && time > self.csqcmodel_nextforcedupdate)
+ if(isplayer && time > e.csqcmodel_nextforcedupdate)
{
- self.SendFlags |= CSQCMODEL_PROPERTY_ORIGIN;
- self.csqcmodel_nextforcedupdate = time + CSQCPLAYER_FORCE_UPDATES * (0.5 + random()); // ensure about 4 origin sends per sec
+ e.SendFlags |= CSQCMODEL_PROPERTY_ORIGIN;
+ e.csqcmodel_nextforcedupdate = time + CSQCPLAYER_FORCE_UPDATES * (0.5 + random()); // ensure about 4 origin sends per sec
}
#endif
- if(self.effects & EF_RESTARTANIM_BIT)
+ if(e.effects & EF_RESTARTANIM_BIT)
{
- self.SendFlags |= CSQCMODEL_PROPERTY_FRAME | CSQCMODEL_PROPERTY_FRAME2; // full anim resend please
- self.effects &= ~EF_RESTARTANIM_BIT;
+ e.SendFlags |= CSQCMODEL_PROPERTY_FRAME | CSQCMODEL_PROPERTY_FRAME2; // full anim resend please
+ e.effects &= ~EF_RESTARTANIM_BIT;
}
- if(self.effects & EF_TELEPORT_BIT)
+ if(e.effects & EF_TELEPORT_BIT)
{
- self.SendFlags |= CSQCMODEL_PROPERTY_TELEPORTED; // no interpolation please
- self.effects &= ~EF_TELEPORT_BIT;
+ e.SendFlags |= CSQCMODEL_PROPERTY_TELEPORTED; // no interpolation please
+ e.effects &= ~EF_TELEPORT_BIT;
}
#define CSQCMODEL_IF(cond) if(cond) {
#define CSQCMODEL_ENDIF }
#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \
{ \
- t tmp = self.f; \
- if(tmp != self.csqcmodel_##f) \
+ t tmp = e.f; \
+ if(tmp != e.csqcmodel_##f) \
{ \
- self.csqcmodel_##f = tmp; \
- self.SendFlags |= flag; \
+ e.csqcmodel_##f = tmp; \
+ e.SendFlags |= flag; \
} \
}
#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) \
{ \
- t tmp = rint(bound(mi, s * self.f, ma) - mi); \
- if(tmp != self.csqcmodel_##f) \
+ t tmp = rint(bound(mi, s * e.f, ma) - mi); \
+ if(tmp != e.csqcmodel_##f) \
{ \
- self.csqcmodel_##f = tmp; \
- self.SendFlags |= flag; \
+ e.csqcmodel_##f = tmp; \
+ e.SendFlags |= flag; \
} \
}
ALLPROPERTIES
#undef CSQCMODEL_IF
}
-void CSQCModel_LinkEntity()
+void CSQCModel_LinkEntity(entity e)
{
- self.SendEntity = CSQCModel_Send;
- self.SendFlags = 0xFFFFFF;
- CSQCModel_CheckUpdate();
+ e.SendEntity = CSQCModel_Send;
+ e.SendFlags = 0xFFFFFF;
+ CSQCModel_CheckUpdate(e);
}
-void CSQCModel_UnlinkEntity()
+void CSQCModel_UnlinkEntity(entity e)
{
- self.SendEntity = func_null;
+ e.SendEntity = func_null;
}
// generic CSQC model code
-void CSQCModel_CheckUpdate();
-void CSQCModel_LinkEntity();
-void CSQCModel_UnlinkEntity();
+void CSQCModel_CheckUpdate(entity e);
+void CSQCModel_LinkEntity(entity e);
+void CSQCModel_UnlinkEntity(entity e);
#define CSQCMODEL_IF(cond)
#define CSQCMODEL_ENDIF
#define FALSE _FALSE
#define spawn _spawn
-
#define particleeffectnum _particleeffectnum
+#define setmodel _setmodel
#include "upstream/csprogsdefs.qc"
#undef FALSE
#undef spawn
-
#undef particleeffectnum
+#undef setmodel
#pragma noref 0
#define FALSE _FALSE
#define spawn _spawn
+#define setmodel _setmodel
#include "upstream/progsdefs.qc"
#undef FALSE
#undef spawn
+#undef setmodel
#pragma noref 0
+++ /dev/null
-#ifndef ACCUMULATE_H
-#define ACCUMULATE_H
-
-#ifdef QCC_SUPPORT_ACCUMULATE
-# define ACCUMULATE_FUNCTION(func, otherfunc) \
- [[accumulate]] void func() { otherfunc(); }
-# define CALL_ACCUMULATED_FUNCTION(func) \
- func()
-#else
-#ifdef HAVE_YO_DAWG_CPP
-// TODO make ascii art pic of xzibit
-// YO DAWG!
-// I HERD YO LIEK MACROS
-// SO I PUT A MACRO DEFINITION IN YO MACRO DEFINITION
-// SO YO CAN EXPAND MACROS WHILE YO EXPAND MACROS
-# define ACCUMULATE_FUNCTION(func,otherfunc) \
- #ifdef func \
- void __merge__##otherfunc() { func(); otherfunc(); } \
- #undef func \
- #define func __merge__##otherfunc \
- #else \
- #define func otherfunc \
- #endif
-# define CALL_ACCUMULATED_FUNCTION(func) \
- func()
-#else
-# define ACCUMULATE_FUNCTION(func,otherfunc) \
- .float _ACCUMULATE_##func##__##otherfunc
-void ACCUMULATE_call(string func)
-{
- float i;
- float n = numentityfields();
- string funcprefix = strcat("_ACCUMULATE_", func, "__");
- float funcprefixlen = strlen(funcprefix);
- for(i = 0; i < n; ++i)
- {
- string name = entityfieldname(i);
- if(substring(name, 0, funcprefixlen) == funcprefix)
- callfunction(substring(name, funcprefixlen, -1));
- }
-}
-# define CALL_ACCUMULATED_FUNCTION(func) \
- ACCUMULATE_call(#func)
-#endif
-#endif
-
-// used for simplifying ACCUMULATE_FUNCTIONs
-#define SET_FIRST_OR_LAST(input,first,count) if(!input) { input = (first + count); }
-#define SET_FIELD_COUNT(field,first,count) if(!field) { field = (first + count); ++count; }
-#define CHECK_MAX_COUNT(name,max,count,type) if(count > max) { error(strcat("Maximum ", type, " hit: ", #name, ": ", ftos(count), ".\n")); }
-
-#endif
+++ /dev/null
-#ifndef BOOL_H
-#define BOOL_H
-
-#ifndef QCC_SUPPORT_BOOL
- #define bool float
-
- // Boolean Constants
- const int true = 1;
- const int false = 0;
-#endif
-
-// Transitional aliases
-[[deprecated("use true")]] [[alias("true")]] const bool TRUE;
-[[deprecated("use false")]] [[alias("false")]] const bool FALSE;
-
-// get true/false value of a string with multiple different inputs
-float InterpretBoolean(string input)
-{
- switch (strtolower(input))
- {
- case "yes":
- case "true":
- case "on":
- return true;
-
- case "no":
- case "false":
- case "off":
- return false;
-
- default: return stof(input);
- }
-}
-
-float boolean(float value) { // if value is 0 return false (0), otherwise return true (1)
- return (value == 0) ? false : true;
-}
-
-#endif
+++ /dev/null
-#ifndef COUNTING_H
-#define COUNTING_H
-
-#include "I18N.qh"
-
-// ===============================================
-// Time processing and counting functions/macros
-// ===============================================
-
-#define count_years_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s years")), ftos_decimals(time, decs))
-#define count_years(time) count_fill(time, \
- ZCTX(_("CI_ZER^%d years")), /* zeroth */ \
- ZCTX(_("CI_FIR^%d year")), /* first */ \
- ZCTX(_("CI_SEC^%d years")), /* year */ \
- ZCTX(_("CI_THI^%d years")), /* third */ \
- ZCTX(_("CI_MUL^%d years"))) /* multi */
-
-#define count_weeks_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s weeks")), ftos_decimals(time, decs))
-#define count_weeks(time) count_fill(time, \
- ZCTX(_("CI_ZER^%d weeks")), /* zeroth */ \
- ZCTX(_("CI_FIR^%d week")), /* first */ \
- ZCTX(_("CI_SEC^%d weeks")), /* week */ \
- ZCTX(_("CI_THI^%d weeks")), /* third */ \
- ZCTX(_("CI_MUL^%d weeks"))) /* multi */
-
-#define count_days_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s days")), ftos_decimals(time, decs))
-#define count_days(time) count_fill(time, \
- ZCTX(_("CI_ZER^%d days")), /* zeroth */ \
- ZCTX(_("CI_FIR^%d day")), /* first */ \
- ZCTX(_("CI_SEC^%d days")), /* day */ \
- ZCTX(_("CI_THI^%d days")), /* third */ \
- ZCTX(_("CI_MUL^%d days"))) /* multi */
-
-#define count_hours_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s hours")), ftos_decimals(time, decs))
-#define count_hours(time) count_fill(time, \
- ZCTX(_("CI_ZER^%d hours")), /* zeroth */ \
- ZCTX(_("CI_FIR^%d hour")), /* first */ \
- ZCTX(_("CI_SEC^%d hours")), /* hour */ \
- ZCTX(_("CI_THI^%d hours")), /* third */ \
- ZCTX(_("CI_MUL^%d hours"))) /* multi */
-
-
-#define count_minutes_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s minutes")), ftos_decimals(time, decs))
-#define count_minutes(time) count_fill(time, \
- ZCTX(_("CI_ZER^%d minutes")), /* zeroth */ \
- ZCTX(_("CI_FIR^%d minute")), /* first */ \
- ZCTX(_("CI_SEC^%d minutes")), /* minute */ \
- ZCTX(_("CI_THI^%d minutes")), /* third */ \
- ZCTX(_("CI_MUL^%d minutes"))) /* multi */
-
-#define count_seconds_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s seconds")), ftos_decimals(time, decs))
-#define count_seconds(time) count_fill(time, \
- ZCTX(_("CI_ZER^%d seconds")), /* zeroth */ \
- ZCTX(_("CI_FIR^%d second")), /* first */ \
- ZCTX(_("CI_SEC^%d seconds")), /* second */ \
- ZCTX(_("CI_THI^%d seconds")), /* third */ \
- ZCTX(_("CI_MUL^%d seconds"))) /* multi */
-
-string count_ordinal(int interval)
-{
- // This function is designed primarily for the English language, it's impossible
- // to accomodate all languages unless we do a specific function for each one...
- // and since that's not technically feasible/practical, this is all we've got folks.
-
- // Basically, it just allows you to represent a number or count in different ways
- // depending on the number... like, with count_ordinal you can provide integers
- // and retrieve 1st, 2nd, 3rd, nth ordinal numbers in a clean and simple way.
- if(floor((interval % 100)/10) * 10 != 10) // examples: 12th, 111th, 213th will not execute this block
- {
- // otherwise, check normally for 1st,2nd,3rd insertions
- switch(interval % 10)
- {
- case 1: return sprintf(_("%dst"), interval);
- case 2: return sprintf(_("%dnd"), interval);
- case 3: return sprintf(_("%drd"), interval);
- default: return sprintf(_("%dth"), interval);
- }
- }
- else { return sprintf(_("%dth"), interval); }
-
- return "";
-}
-
-string count_fill(float interval, string zeroth, string first, string second, string third, string multi)
-{
- // This function is designed primarily for the English language, it's impossible
- // to accomodate all languages unless we do a specific function for each one...
- // and since that's not technically feasible/practical, this is all we've got folks.
-
- // Here you can insert specific strings based on the interval number, so you could do
- // i.e. count_seconds which outputs like this:
- // 0 seconds
- // 1 second
- // 2 seconds
- // 3 seconds
- // etc... minutes, hours, days, etc.
-
- switch(floor(interval))
- {
- case 0: return sprintf(zeroth, interval);
- case 1:
- {
- if(interval == 1) // EXACTLY value of 1
- return sprintf(first, interval);
- else
- return sprintf(multi, interval);
- }
- case 2: return sprintf(second, interval);
- case 3: return sprintf(third, interval);
- default: return sprintf(multi, interval);
- }
- return "";
-}
-
-string process_time(float outputtype, float seconds)
-{
- float tmp_hours = 0, tmp_minutes = 0, tmp_seconds = 0;
- float tmp_years = 0, tmp_weeks = 0, tmp_days = 0;
-
- tmp_seconds = floor(seconds);
-
- if(tmp_seconds)
- {
- tmp_minutes = floor(tmp_seconds / 60);
-
- if(tmp_minutes)
- {
- tmp_seconds -= (tmp_minutes * 60);
- tmp_hours = floor(tmp_minutes / 60);
-
- if(tmp_hours)
- {
- tmp_minutes -= (tmp_hours * 60);
- tmp_days = floor(tmp_hours / 24);
-
- if(tmp_days)
- {
- tmp_hours -= (tmp_days * 24);
- tmp_weeks = floor(tmp_days / 7);
-
- if(tmp_weeks)
- {
- tmp_days -= (tmp_weeks * 7);
- tmp_years = floor(tmp_weeks / 52);
- }
- }
- }
- }
- }
-
- switch(outputtype)
- {
- case 1: return sprintf("%02d:%02d:%02d", tmp_hours, tmp_minutes, tmp_seconds);
- case 2:
- {
- string output = "";
-
- output = count_seconds(tmp_seconds);
-
- if(tmp_minutes)
- {
- output = sprintf(
- "%s%s",
- count_minutes(tmp_minutes),
- ((output != "") ? sprintf(", %s", output) : ""));
- }
-
- if(tmp_hours)
- {
- output = sprintf(
- "%s%s",
- count_hours(tmp_hours),
- ((output != "") ? sprintf(", %s", output) : ""));
- }
-
- if(tmp_days)
- {
- output = sprintf(
- "%s%s",
- count_days(tmp_days),
- ((output != "") ? sprintf(", %s", output) : ""));
- }
-
- if(tmp_weeks)
- {
- output = sprintf(
- "%s%s",
- count_weeks(tmp_weeks),
- ((output != "") ? sprintf(", %s", output) : ""));
- }
-
- if(tmp_years)
- {
- output = sprintf(
- "%s%s",
- count_years(tmp_years),
- ((output != "") ? sprintf(", %s", output) : ""));
- }
-
- return output;
- }
- case 3:
- {
- string output = "";
-
- output = count_hours(tmp_hours);
-
- if(tmp_weeks) { tmp_days += (tmp_weeks * 7); }
- if(tmp_years) { tmp_days += (tmp_years * 365); }
- if(tmp_days)
- {
- output = sprintf(
- "%s%s",
- count_days(tmp_days),
- ((output != "") ? sprintf(", %s", output) : ""));
- }
-
- return output;
- }
- }
- return "";
-}
-#endif
+++ /dev/null
-#ifndef CVAR_H
-#define CVAR_H
-
-#include "Static.qh"
-
-void RegisterCvars(void(string name, string desc, bool archive, string file) f) { }
-
-void RegisterCvars_Set(string name, string desc, bool archive, string file)
-{
- localcmd(sprintf("\n%1$s %2$s \"$%2$s\" \"%3$s\"\n", (archive ? "seta" : "set"), name, desc));
-}
-
-STATIC_INIT_LATE(Cvars) { RegisterCvars(RegisterCvars_Set); }
-
-#define AUTOCVAR_5(file, archive, var, type, desc) \
- [[accumulate]] void RegisterCvars(void(string, string, bool, string) f) { f(#var, desc, archive, file); } \
- type autocvar_##var
-#define AUTOCVAR_6(file, archive, var, type, default, desc) \
- AUTOCVAR_5(file, archive, var, type, desc) = default
-#define _AUTOCVAR(...) OVERLOAD(AUTOCVAR, __FILE__, __VA_ARGS__)
-#define AUTOCVAR_SAVE(...) _AUTOCVAR(true, __VA_ARGS__)
-#define AUTOCVAR(...) _AUTOCVAR(false, __VA_ARGS__)
-
-#endif
+++ /dev/null
-#ifndef MENUQC
-#ifndef DEFER_H
-#define DEFER_H
-#include "OO.qh"
-
-entityclass(Defer);
-class(Defer) .entity owner;
-class(Defer) .void() think;
-class(Defer) .float nextthink;
-
-/*
-==================
-SUB_Remove
-
-Remove self
-==================
-*/
-void SUB_Remove()
-{
- remove (self);
-}
-
-void defer_think()
-{
- entity oself;
-
- oself = self;
- self = self.owner;
- oself.think = SUB_Remove;
- oself.nextthink = time;
-
- oself.use();
-}
-
-/*
- Execute func() after time + fdelay.
- self when func is executed = self when defer is called
-*/
-void defer(float fdelay, void() func)
-{
- entity e;
-
- e = spawn();
- e.owner = self;
- e.use = func;
- e.think = defer_think;
- e.nextthink = time + fdelay;
-}
-
-#endif
-#endif
+++ /dev/null
-#ifdef CSQC
-#ifndef DRAW_H
-#define DRAW_H
-
-#include "I18N.qh"
-#include "Vector.qh"
-
-#include "../client/defs.qh"
-
-void Draw_CylindricLine(vector from, vector to, float thickness, string texture, float aspect, float shift, vector rgb, float theAlpha, float drawflag, vector vieworg)
-{
- // I want to draw a quad...
- // from and to are MIDPOINTS.
-
- vector axis, thickdir, A, B, C, D;
- float length_tex;
-
- axis = normalize(to - from);
- length_tex = aspect * vlen(to - from) / thickness;
-
- // direction is perpendicular to the view normal, and perpendicular to the axis
- thickdir = normalize(cross(axis, vieworg - from));
-
- A = from - thickdir * (thickness / 2);
- B = from + thickdir * (thickness / 2);
- C = to + thickdir * (thickness / 2);
- D = to - thickdir * (thickness / 2);
-
- R_BeginPolygon(texture, drawflag);
- R_PolygonVertex(A, '0 0 0' + shift * '1 0 0', rgb, theAlpha);
- R_PolygonVertex(B, '0 1 0' + shift * '1 0 0', rgb, theAlpha);
- R_PolygonVertex(C, '0 1 0' + (shift + length_tex) * '1 0 0', rgb, theAlpha);
- R_PolygonVertex(D, '0 0 0' + (shift + length_tex) * '1 0 0', rgb, theAlpha);
- R_EndPolygon();
-}
-
-// a border picture is a texture containing nine parts:
-// 1/4 width: left part
-// 1/2 width: middle part (stretched)
-// 1/4 width: right part
-// divided into
-// 1/4 height: top part
-// 1/2 height: middle part (stretched)
-// 1/4 height: bottom part
-void draw_BorderPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha, vector theBorderSize)
-{
- if (theBorderSize.x < 0 && theBorderSize.y < 0) // draw whole image as it is
- {
- drawpic(theOrigin, pic, theSize, theColor, theAlpha, 0);
- return;
- }
- if (theBorderSize.x == 0 && theBorderSize.y == 0) // no border
- {
- // draw only the central part
- drawsubpic(theOrigin, theSize, pic, '0.25 0.25 0', '0.5 0.5 0', theColor, theAlpha, 0);
- return;
- }
-
- vector dX, dY;
- vector width, height;
- vector bW, bH;
- //pic = draw_UseSkinFor(pic);
- width = eX * theSize.x;
- height = eY * theSize.y;
- if(theSize.x <= theBorderSize.x * 2)
- {
- // not wide enough... draw just left and right then
- bW = eX * (0.25 * theSize.x / (theBorderSize.x * 2));
- if(theSize.y <= theBorderSize.y * 2)
- {
- // not high enough... draw just corners
- bH = eY * (0.25 * theSize.y / (theBorderSize.y * 2));
- drawsubpic(theOrigin, width * 0.5 + height * 0.5, pic, '0 0 0', bW + bH, theColor, theAlpha, 0);
- drawsubpic(theOrigin + width * 0.5, width * 0.5 + height * 0.5, pic, eX - bW, bW + bH, theColor, theAlpha, 0);
- drawsubpic(theOrigin + height * 0.5, width * 0.5 + height * 0.5, pic, eY - bH, bW + bH, theColor, theAlpha, 0);
- drawsubpic(theOrigin + theSize * 0.5, width * 0.5 + height * 0.5, pic, eX + eY - bW - bH, bW + bH, theColor, theAlpha, 0);
- }
- else
- {
- dY = theBorderSize.x * eY;
- drawsubpic(theOrigin, width * 0.5 + dY, pic, '0 0 0', '0 0.25 0' + bW, theColor, theAlpha, 0);
- drawsubpic(theOrigin + width * 0.5, width * 0.5 + dY, pic, '0 0 0' + eX - bW, '0 0.25 0' + bW, theColor, theAlpha, 0);
- drawsubpic(theOrigin + dY, width * 0.5 + height - 2 * dY, pic, '0 0.25 0', '0 0.5 0' + bW, theColor, theAlpha, 0);
- drawsubpic(theOrigin + width * 0.5 + dY, width * 0.5 + height - 2 * dY, pic, '0 0.25 0' + eX - bW, '0 0.5 0' + bW, theColor, theAlpha, 0);
- drawsubpic(theOrigin + height - dY, width * 0.5 + dY, pic, '0 0.75 0', '0 0.25 0' + bW, theColor, theAlpha, 0);
- drawsubpic(theOrigin + width * 0.5 + height - dY, width * 0.5 + dY, pic, '0 0.75 0' + eX - bW, '0 0.25 0' + bW, theColor, theAlpha, 0);
- }
- }
- else
- {
- if(theSize.y <= theBorderSize.y * 2)
- {
- // not high enough... draw just top and bottom then
- bH = eY * (0.25 * theSize.y / (theBorderSize.y * 2));
- dX = theBorderSize.x * eX;
- drawsubpic(theOrigin, dX + height * 0.5, pic, '0 0 0', '0.25 0 0' + bH, theColor, theAlpha, 0);
- drawsubpic(theOrigin + dX, width - 2 * dX + height * 0.5, pic, '0.25 0 0', '0.5 0 0' + bH, theColor, theAlpha, 0);
- drawsubpic(theOrigin + width - dX, dX + height * 0.5, pic, '0.75 0 0', '0.25 0 0' + bH, theColor, theAlpha, 0);
- drawsubpic(theOrigin + height * 0.5, dX + height * 0.5, pic, '0 0 0' + eY - bH, '0.25 0 0' + bH, theColor, theAlpha, 0);
- drawsubpic(theOrigin + dX + height * 0.5, width - 2 * dX + height * 0.5, pic, '0.25 0 0' + eY - bH, '0.5 0 0' + bH, theColor, theAlpha, 0);
- drawsubpic(theOrigin + width - dX + height * 0.5, dX + height * 0.5, pic, '0.75 0 0' + eY - bH, '0.25 0 0' + bH, theColor, theAlpha, 0);
- }
- else
- {
- dX = theBorderSize.x * eX;
- dY = theBorderSize.x * eY;
- drawsubpic(theOrigin, dX + dY, pic, '0 0 0', '0.25 0.25 0', theColor, theAlpha, 0);
- drawsubpic(theOrigin + dX, width - 2 * dX + dY, pic, '0.25 0 0', '0.5 0.25 0', theColor, theAlpha, 0);
- drawsubpic(theOrigin + width - dX, dX + dY, pic, '0.75 0 0', '0.25 0.25 0', theColor, theAlpha, 0);
- drawsubpic(theOrigin + dY, dX + height - 2 * dY, pic, '0 0.25 0', '0.25 0.5 0', theColor, theAlpha, 0);
- drawsubpic(theOrigin + dY + dX, width - 2 * dX + height - 2 * dY, pic, '0.25 0.25 0', '0.5 0.5 0', theColor, theAlpha, 0);
- drawsubpic(theOrigin + dY + width - dX, dX + height - 2 * dY, pic, '0.75 0.25 0', '0.25 0.5 0', theColor, theAlpha, 0);
- drawsubpic(theOrigin + height - dY, dX + dY, pic, '0 0.75 0', '0.25 0.25 0', theColor, theAlpha, 0);
- drawsubpic(theOrigin + height - dY + dX, width - 2 * dX + dY, pic, '0.25 0.75 0', '0.5 0.25 0', theColor, theAlpha, 0);
- drawsubpic(theOrigin + height - dY + width - dX, dX + dY, pic, '0.75 0.75 0', '0.25 0.25 0', theColor, theAlpha, 0);
- }
- }
-}
-
-void drawstringright(vector position, string text, vector theScale, vector rgb, float theAlpha, int flag)
-{
- position.x -= 2 / 3 * strlen(text) * theScale.x;
- drawstring(position, text, theScale, rgb, theAlpha, flag);
-}
-
-void drawstringcenter(vector position, string text, vector theScale, vector rgb, float theAlpha, int flag)
-{
- position.x = 0.5 * (vid_conwidth - 0.6025 * strlen(text) * theScale.x);
- drawstring(position, text, theScale, rgb, theAlpha, flag);
-}
-
-#endif
-#endif
+++ /dev/null
-#ifndef I18N_H
-#define I18N_H
-
-// translation helpers
-string prvm_language;
-
-string language_filename(string s)
-{
- string fn = prvm_language;
- if (fn == "" || fn == "dump")
- return s;
- fn = strcat(s, ".", fn);
- int fh = fopen(fn, FILE_READ);
- if (fh >= 0)
- {
- fclose(fh);
- return fn;
- }
- return s;
-}
-
-string CTX(string s)
-{
- int p = strstrofs(s, "^", 0);
- if (p < 0)
- return s;
- return substring(s, p + 1, -1);
-}
-
-#define ZCTX(s) strzone(CTX(s))
-
-#endif
+++ /dev/null
-#ifndef LAZY_H
-#define LAZY_H
-
-#include "OO.qh"
-
-CLASS(Lazy, Object)
- ATTRIB(Lazy, m_get, entity(), func_null);
- CONSTRUCTOR(Lazy, entity() _compute) { this.m_get = _compute; }
-ENDCLASS(Lazy)
-
-#define LAZY(id) __lazy_##id
-#define LAZY_NEW(id, compute) entity LAZY(id)() { \
- static bool done; \
- static entity it; \
- if (!done) { it = compute; done = true; } \
- return it; \
-}
-#endif
+++ /dev/null
-#ifndef LOG_H
-#define LOG_H
-
-#define _printferr(...) error(sprintf(__VA_ARGS__))
-#define _printfbt(...) backtrace(sprintf(__VA_ARGS__))
-#define printf(...) print(sprintf(__VA_ARGS__))
-#define dprintf(...) dprint(sprintf(__VA_ARGS__))
-#define _dprintf2(...) do { if (autocvar_developer > 1) dprintf(__VA_ARGS__); } while (0)
-
-#define _LOG(f, level, s) f("[::"level"] ["__FILE__":%s:%.0f] %s", __FUNC__, __LINE__, s)
-
-#define LOG_FATAL(...) _LOG_FATAL(strcat("", __VA_ARGS__))
-#define LOG_FATALF(...) _LOG_FATAL(sprintf(__VA_ARGS__))
-#define _LOG_FATAL(s) _LOG(_printferr, "FATAL", s)
-
-#define LOG_SEVERE(...) _LOG_SEVERE(strcat("", __VA_ARGS__))
-#define LOG_SEVEREF(...) _LOG_SEVERE(sprintf(__VA_ARGS__))
-#define _LOG_SEVERE(s) _LOG(_printfbt, "SEVERE", s)
-
-#define LOG_WARNING(...) _LOG_WARNING(strcat("", __VA_ARGS__))
-#define LOG_WARNINGF(...) _LOG_WARNING(sprintf(__VA_ARGS__))
-#define _LOG_WARNING(s) _LOG(printf, "WARNING", s)
-
-#define LOG_INFO(...) do { if (autocvar_developer) _LOG_INFO(strcat("", __VA_ARGS__)); else print (__VA_ARGS__); } while (0)
-#define LOG_INFOF(...) do { if (autocvar_developer) _LOG_INFO(sprintf(__VA_ARGS__)); else printf(__VA_ARGS__); } while (0)
-#define _LOG_INFO(s) _LOG(printf, "INFO", s)
-
-#define LOG_TRACE(...) _LOG_TRACE(strcat("", __VA_ARGS__))
-#define LOG_TRACEF(...) _LOG_TRACE(sprintf(__VA_ARGS__))
-#define _LOG_TRACE(s) _LOG(dprintf, "TRACE", s)
-
-#define LOG_DEBUG(...) _LOG_DEBUG(strcat("", __VA_ARGS__))
-#define LOG_DEBUGF(...) _LOG_DEBUG(sprintf(__VA_ARGS__))
-#define _LOG_DEBUG(s) _LOG(_dprintf2, "DEBUG", s)
-
-// TODO: this sucks, lets find a better way to do backtraces?
-#ifdef SVQC
-void builtin_remove(entity);
-#define _backtrace() builtin_remove(NULL)
-#else
-void remove(entity);
-#define _backtrace() remove(NULL)
-#endif
-
-noref int autocvar_developer;
-noref bool autocvar_prvm_backtraceforwarnings;
-
-#define backtrace(msg) do { \
- int dev = autocvar_developer; \
- bool war = autocvar_prvm_backtraceforwarnings; \
- cvar_set("developer", "1"); \
- cvar_set("prvm_backtraceforwarnings", "1"); \
- print("\n--- CUT HERE ---\n", msg, "\n"); \
- _backtrace(); \
- print("\n--- CUT UNTIL HERE ---\n"); \
- cvar_set("developer", ftos(dev)); \
- cvar_set("prvm_backtraceforwarnings", ftos(war)); \
-} while (0)
-
-#endif
+++ /dev/null
-#ifndef MATH_H
-#define MATH_H
-
-void mean_accumulate(entity e, .float a, .float c, float mean, float value, float weight)
-{
- if (weight == 0)
- return;
- if (mean == 0)
- e.(a) *= pow(value, weight);
- else
- e.(a) += pow(value, mean) * weight;
- e.(c) += weight;
-}
-
-float mean_evaluate(entity e, .float a, .float c, float mean)
-{
- if (e.(c) == 0)
- return 0;
- if (mean == 0)
- return pow(e.(a), 1.0 / e.(c));
- else
- return pow(e.(a) / e.(c), 1.0 / mean);
-}
-
-#define MEAN_ACCUMULATE(prefix,v,w) mean_accumulate(self,prefix##_accumulator,prefix##_count,prefix##_mean,v,w)
-#define MEAN_EVALUATE(prefix) mean_evaluate(self,prefix##_accumulator,prefix##_count,prefix##_mean)
-#define MEAN_DECLARE(prefix,m) float prefix##_mean = m; .float prefix##_count, prefix##_accumulator
-
-/*
-==================
-crandom
-
-Returns a random number between -1.0 and 1.0
-==================
-*/
-float crandom (void)
-{
- return 2 * (random () - 0.5);
-}
-
-
-/*
-==================
-Angc used for animations
-==================
-*/
-
-
-float angc (float a1, float a2)
-{
- float a;
-
- while (a1 > 180)
- a1 = a1 - 360;
- while (a1 < -179)
- a1 = a1 + 360;
-
- while (a2 > 180)
- a2 = a2 - 360;
- while (a2 < -179)
- a2 = a2 + 360;
-
- a = a1 - a2;
- while (a > 180)
- a = a - 360;
- while (a < -179)
- a = a + 360;
-
- return a;
-}
-
-float fsnap(float val,float fsize)
-{
- return rint(val / fsize) * fsize;
-}
-
-vector vsnap(vector point,float fsize)
-{
- vector vret;
-
- vret.x = rint(point.x / fsize) * fsize;
- vret.y = rint(point.y / fsize) * fsize;
- vret.z = ceil(point.z / fsize) * fsize;
-
- return vret;
-}
-
-vector lerpv(float t0, vector v0, float t1, vector v1, float t)
-{
- return v0 + (v1 - v0) * ((t - t0) / (t1 - t0));
-}
-
-#endif
+++ /dev/null
-#ifndef NIL_H
-#define NIL_H
-
-#ifdef QCC_SUPPORT_NIL
-#define func_null nil
-#define string_null nil
-#else
-// the NULL function
-var void func_null(void);
-string string_null;
-#endif
-
-#endif
+++ /dev/null
-#ifndef OO_H
-#define OO_H
-
-#include "Nil.qh"
-#include "Registry.qh"
-
-#ifdef MENUQC
- #define NULL (null_entity)
-#else
- #define NULL (world)
-#endif
-
-.string classname;
-/** Location entity was spawned from in source */
-.string sourceLocFile;
-.int sourceLocLine;
-entity _spawn();
-entity __spawn(string _classname, string _sourceFile, int _sourceLine) {
- entity this = _spawn();
- this.classname = _classname;
- this.sourceLocFile = _sourceFile;
- this.sourceLocLine = _sourceLine;
- return this;
-}
-
-
-
-#define entityclass(...) OVERLOAD(entityclass, __VA_ARGS__)
-#define entityclass_1(name) entityclass_2(name, Object)
-#ifndef QCC_SUPPORT_ENTITYCLASS
- #define entityclass_2(name, base) typedef entity name
- #define class(name)
- #define new(class) __spawn(#class, __FILE__, __LINE__)
-#else
- #define entityclass_2(name, base) entityclass name : base {}
- #define class(name) [[class(name)]]
- #define new(class) ((class) __spawn(#class, __FILE__, __LINE__))
-#endif
-
-// Classes have a `spawn##cname(entity)` constructor
-// The parameter is used across [[accumulate]] functions
-
-// Macro to hide this implementation detail
-#define NEW(cname, ...) \
- OVERLOAD(spawn##cname, new(cname), ##__VA_ARGS__)
-
-#define CONSTRUCT(cname, ...) \
- OVERLOAD(spawn##cname, this, ##__VA_ARGS__)
-
-#define CONSTRUCTOR(cname, ...) \
- cname OVERLOAD(spawn##cname, cname this, __VA_ARGS__) { return = this; } \
- [[accumulate]] cname OVERLOAD(spawn##cname, cname this, __VA_ARGS__)
-
-.string vtblname;
-.entity vtblbase;
-
-void RegisterClasses() { }
-STATIC_INIT(RegisterClasses) { RegisterClasses(); }
-
-#define VTBL(cname, base) \
- INIT_STATIC(cname); \
- entity cname##_vtbl; \
- void cname##_vtbl_init() { \
- cname e = new(vtbl); \
- spawn##cname##_static(e); \
- e.vtblname = #cname; \
- /* Top level objects refer to themselves */ \
- e.vtblbase = base##_vtbl ? base##_vtbl : e; \
- cname##_vtbl = e; \
- } \
- ACCUMULATE_FUNCTION(RegisterClasses, cname##_vtbl_init)
-
-#define INIT_STATIC(cname) [[accumulate]] void spawn##cname##_static(cname this)
-#define INIT(cname) [[accumulate]] cname spawn##cname##_1(cname this)
-
-#define CLASS(cname, base) \
- entityclass(cname, base); \
- class(cname) .bool instanceOf##cname; \
- VTBL(cname, base) \
- INIT_STATIC(cname) { \
- if (cname##_vtbl) { \
- copyentity(cname##_vtbl, this); \
- return; \
- } \
- spawn##base##_static(this); \
- this.instanceOf##cname = true; \
- } \
- INIT(cname) { \
- /* Only statically initialize the current class, it contains everything it inherits */ \
- if (cname##_vtbl.vtblname == this.classname) { \
- spawn##cname##_static(this); \
- this.classname = #cname; \
- this.vtblname = string_null; \
- this.vtblbase = cname##_vtbl; \
- } \
- spawn##base##_1(this); \
- }
-
-#define METHOD(cname, name, prototype) \
- class(cname) .prototype name; \
- prototype cname##_##name; \
- INIT_STATIC(cname) { this.name = cname##_##name; } \
- prototype cname##_##name
-
-#define ATTRIB(cname, name, type, val) \
- class(cname) .type name; \
- INIT(cname) { this.name = val; }
-
-#define ATTRIBARRAY(cname, name, type, cnt) \
- class(cname) .type name[cnt];
-
-#define ENDCLASS(cname) \
- [[last]] INIT(cname) { return this; }
-
-#define SUPER(cname) (cname##_vtbl.vtblbase)
-#define super (this.vtblbase.vtblbase)
-
-#define spawn_static(this)
-#define spawn_1(this)
-#define _vtbl NULL
-CLASS(Object, );
- METHOD(Object, describe, string(entity this)) {
- string s = _("No description");
- if (cvar("developer")) {
- for (int i = 0, n = numentityfields(); i < n; ++i) {
- string value = getentityfieldstring(i, this);
- if (value != "") s = sprintf("%s\n%s = %s", s, entityfieldname(i), value);
- }
- }
- return s;
- }
- METHOD(Object, display, void(entity this, void(string name, string icon) returns)) {
- returns(sprintf("entity %i", this), "nopreview_map");
- }
-ENDCLASS(Object)
-#undef spawn_static
-#undef spawn_1
-#undef _vtbl
-
-#endif
+++ /dev/null
-#ifdef CSQC
-#ifndef PLAYER_H
-#define PLAYER_H
-
-#include "String.qh"
-
-#include "../client/main.qh"
-#include "../common/teams.qh"
-
-int GetPlayerColorForce(int i)
-{
- if(!teamplay)
- return 0;
- else
- return stof(getplayerkeyvalue(i, "colors")) & 15;
-}
-
-int GetPlayerColor(int i)
-{
- if(!playerslots[i].gotscores) // unconnected
- return NUM_SPECTATOR;
- else if(stof(getplayerkeyvalue(i, "frags")) == FRAGS_SPECTATOR)
- return NUM_SPECTATOR;
- else
- return GetPlayerColorForce(i);
-}
-
-string GetPlayerName(int i)
-{
- return ColorTranslateRGB(getplayerkeyvalue(i, "name"));
-}
-
-#endif
-#endif
+++ /dev/null
-#ifndef PROGNAME_H
-#define PROGNAME_H
-
-#if defined(MENUQC)
- #define PROGNAME "MENUQC"
-#elif defined(SVQC)
- #define PROGNAME "SVQC"
-#elif defined(CSQC)
- #define PROGNAME "CSQC"
-#else
- #error "Unable to detect PROGNAME"
-#endif
-
-#endif
+++ /dev/null
-#ifndef REGISTRY_H
-#define REGISTRY_H
-
-#include "OO.qh"
-
-#define REGISTER_INIT(ns, id) [[accumulate]] void Register_##ns##_##id##_init(entity this)
-#define REGISTER_INIT_POST(ns, id) [[accumulate]] void Register_##ns##_##id##_init_post(entity this)
-
-#define REGISTER(initfunc, ns, array, counter, id, fld, inst) \
- entity ns##_##id; \
- REGISTER_INIT(ns, id) { } \
- REGISTER_INIT_POST(ns, id) { } \
- .entity enemy; /* internal next pointer */ \
- void Register_##ns##_##id() { \
- entity this = inst; \
- ns##_##id = this; \
- this.fld = counter; \
- array[counter++] = this; \
- if (!array##_first) array##_first = this; \
- if ( array##_last) array##_last.enemy = this; \
- array##_last = this; \
- Register_##ns##_##id##_init(this); \
- Register_##ns##_##id##_init_post(this); \
- } \
- ACCUMULATE_FUNCTION(initfunc, Register_##ns##_##id) \
- REGISTER_INIT(ns, id)
-
-#endif
+++ /dev/null
-#ifndef STATIC_H
-#define STATIC_H
-
-void __static_init_early() { }
-void __static_init() { CALL_ACCUMULATED_FUNCTION(__static_init_early); }
-#define static_init() CALL_ACCUMULATED_FUNCTION(__static_init)
-#define REGISTER_REGISTRY(func) ACCUMULATE_FUNCTION(__static_init_early, func)
-
-#define _STATIC_INIT(where, func) \
- void _static_##func(); \
- ACCUMULATE_FUNCTION(where, _static_##func) \
- void _static_##func()
-
-#define STATIC_INIT(func) _STATIC_INIT(__static_init_early, func##_early)
-#define STATIC_INIT_LATE(func) _STATIC_INIT(__static_init, func)
-
-#endif
+++ /dev/null
-#ifndef STRING_H
-#define STRING_H
-
-#ifndef SVQC
-float stringwidth_colors(string s, vector theSize)
-{
- return stringwidth(s, true, theSize);
-}
-
-float stringwidth_nocolors(string s, vector theSize)
-{
- return stringwidth(s, false, theSize);
-}
-#endif
-
-// Timer (#5)
-//
-// TODO: macro
-string seconds_tostring(float sec)
-{
- float minutes;
- minutes = floor(sec / 60);
-
- sec -= minutes * 60;
- return sprintf("%d:%02d", minutes, sec);
-}
-
-int ColorTranslateMode;
-
-string ColorTranslateRGB(string s)
-{
- if(ColorTranslateMode & 1)
- return strdecolorize(s);
- else
- return s;
-}
-
-#endif
+++ /dev/null
-#ifndef STRUCT_H
-#define STRUCT_H
-
-#ifndef QCC_SUPPORT_STRUCT
- #define _STRUCT_DECLARE(x, id, type, END) noref type x ##_## id ;
- #define STRUCT_DECLARE(id, s) s(_STRUCT_DECLARE, id)
-
- #define _STRUCT_PARAM_(x, id, type) type x ##_## id ,
- #define _STRUCT_PARAM_END(x, id, type) type x ##_## id
- #define _STRUCT_PARAM(x, id, type, isend) _STRUCT_PARAM_##isend(x, id, type)
- #define STRUCT_PARAM(id, s) s(_STRUCT_PARAM, id)
-
- #define _STRUCT_PASS_(x, id, type) x ##_## id ,
- #define _STRUCT_PASS_END(x, id, type) x ##_## id
- #define _STRUCT_PASS(x, id, type, END) _STRUCT_PASS_##END(x, id, type)
- #define STRUCT_PASS(id, s) s(_STRUCT_PASS, id)
-
- #define _STRUCT_STORE_DST(_, it) it
- #define _STRUCT_STORE_SRC(it, _) it
- #define _CONCAT3_(a, b, c) a ## b ## c
- #define _CONCAT3(a, b, c) _CONCAT3_(a, b, c)
- #define _STRUCT_STORE(x, id, type, END) _CONCAT3(_STRUCT_STORE_DST x, _, id) = _CONCAT3(_STRUCT_STORE_SRC x, _, id);
- #define STRUCT_STORE(from, to, s) s(_STRUCT_STORE, (from, to))
-
- #define STRUCT(id, ...)
-#else
- #define STRUCT_DECLARE(id, type) type id;
- #define STRUCT_PARAM(id, type) type id
- #define STRUCT_PASS(id, type) id
- #define STRUCT_STORE(from, to, s) to = from
- #define _STRUCT_MEMBER(my, id, type, END) type id;
- #define STRUCT(id, s) struct STRUCT_##id { s(_STRUCT_MEMBER, ) };
-#endif
-
-#endif
+++ /dev/null
-#ifndef VECTOR_H
-#define VECTOR_H
-
-const vector eX = '1 0 0';
-const vector eY = '0 1 0';
-const vector eZ = '0 0 1';
-
-vector randompos(vector m1, vector m2)
-{
- vector v;
- m2 = m2 - m1;
- v_x = m2_x * random() + m1_x;
- v_y = m2_y * random() + m1_y;
- v_z = m2_z * random() + m1_z;
- return v;
-}
-
-float vlen2d(vector v)
-{
- return sqrt(v.x * v.x + v.y * v.y);
-}
-
-float vlen_maxnorm2d(vector v)
-{
- return max(v.x, v.y, -v.x, -v.y);
-}
-
-float vlen_minnorm2d(vector v)
-{
- return min(max(v.x, -v.x), max(v.y, -v.y));
-}
-
-
-#endif
-#include "Bool.qh"
+#include "bool.qh"
#include "../warpzonelib/mathlib.qc"
-#include "Accumulate.qh"
-#include "Counting.qh"
-#include "Cvar.qh"
-#include "Defer.qh"
-#include "Draw.qh"
-#include "I18N.qh"
-#include "Lazy.qh"
-#include "Log.qh"
-#include "Math.qh"
-#include "Nil.qh"
+#include "accumulate.qh"
+#include "bits.qh"
+#include "counting.qh"
+#include "cvar.qh"
+#include "defer.qh"
+#include "draw.qh"
+#include "file.qh"
+#include "i18n.qh"
+#include "lazy.qh"
+#include "log.qh"
+#include "math.qh"
+#include "net.qh"
+#include "nil.qh"
#include "noise.qc"
-#include "OO.qh"
+#include "oo.qh"
#include "p2mathlib.qc"
-#include "Player.qh"
-#include "prandom.qc"
-#include "Progname.qh"
-#include "Registry.qh"
+#include "player.qh"
+#include "progname.qh"
+#include "random.qc"
+#include "registry.qh"
+#include "replicate.qh"
+#include "sort.qh"
#include "sortlist.qc"
-#include "Static.qh"
-#include "String.qh"
-#include "Struct.qh"
+#include "spawnfunc.qh"
+#include "static.qh"
+#include "string.qh"
+#include "struct.qh"
#include "test.qc"
#include "urllib.qc"
-#include "Vector.qh"
+#include "vector.qh"
--- /dev/null
+#ifndef ACCUMULATE_H
+#define ACCUMULATE_H
+
+#ifdef QCC_SUPPORT_ACCUMULATE
+# define ACCUMULATE_FUNCTION(func, otherfunc) \
+ [[accumulate]] void func() { otherfunc(); }
+# define CALL_ACCUMULATED_FUNCTION(func) \
+ func()
+#else
+#ifdef HAVE_YO_DAWG_CPP
+// TODO make ascii art pic of xzibit
+// YO DAWG!
+// I HERD YO LIEK MACROS
+// SO I PUT A MACRO DEFINITION IN YO MACRO DEFINITION
+// SO YO CAN EXPAND MACROS WHILE YO EXPAND MACROS
+# define ACCUMULATE_FUNCTION(func,otherfunc) \
+ #ifdef func \
+ void __merge__##otherfunc() { func(); otherfunc(); } \
+ #undef func \
+ #define func __merge__##otherfunc \
+ #else \
+ #define func otherfunc \
+ #endif
+# define CALL_ACCUMULATED_FUNCTION(func) \
+ func()
+#else
+# define ACCUMULATE_FUNCTION(func,otherfunc) \
+ .float _ACCUMULATE_##func##__##otherfunc;
+void ACCUMULATE_call(string func)
+{
+ float i;
+ float n = numentityfields();
+ string funcprefix = strcat("_ACCUMULATE_", func, "__");
+ float funcprefixlen = strlen(funcprefix);
+ for(i = 0; i < n; ++i)
+ {
+ string name = entityfieldname(i);
+ if(substring(name, 0, funcprefixlen) == funcprefix)
+ callfunction(substring(name, funcprefixlen, -1));
+ }
+}
+# define CALL_ACCUMULATED_FUNCTION(func) \
+ ACCUMULATE_call(#func)
+#endif
+#endif
+
+// used for simplifying ACCUMULATE_FUNCTIONs
+#define SET_FIRST_OR_LAST(input,first,count) if(!input) { input = (first + count); }
+#define SET_FIELD_COUNT(field,first,count) if(!field) { field = (first + count); ++count; }
+#define CHECK_MAX_COUNT(name,max,count,type) if(count > max) { error(strcat("Maximum ", type, " hit: ", #name, ": ", ftos(count), ".\n")); }
+
+#endif
--- /dev/null
+#ifndef BITS_H
+#define BITS_H
+
+#define BIT(n) (1 << (n))
+#define BITS(n) (BIT(n) - 1)
+#ifndef BRANCHLESS_BITSET
+ #define BITSET(var, mask, flag) (flag ? (var) | (mask) : (var) &~ (mask))
+#else
+ #define BITSET(var, mask, flag) ((var) ^ (-(flag) ^ (var)) & (mask))
+#endif
+
+int lowestbit(int f)
+{
+ f &= ~(f << 1);
+ f &= ~(f << 2);
+ f &= ~(f << 4);
+ f &= ~(f << 8);
+ f &= ~(f << 16);
+ return f;
+}
+
+#endif
--- /dev/null
+#ifndef BOOL_H
+#define BOOL_H
+
+#ifndef QCC_SUPPORT_BOOL
+ #define bool float
+
+ // Boolean Constants
+ const int true = 1;
+ const int false = 0;
+#endif
+
+// Transitional aliases
+[[deprecated("use true")]] [[alias("true")]] const bool TRUE;
+[[deprecated("use false")]] [[alias("false")]] const bool FALSE;
+
+// get true/false value of a string with multiple different inputs
+float InterpretBoolean(string input)
+{
+ switch (strtolower(input))
+ {
+ case "yes":
+ case "true":
+ case "on":
+ return true;
+
+ case "no":
+ case "false":
+ case "off":
+ return false;
+
+ default: return stof(input);
+ }
+}
+
+float boolean(float value) { // if value is 0 return false (0), otherwise return true (1)
+ return (value == 0) ? false : true;
+}
+
+#endif
--- /dev/null
+#ifndef COUNTING_H
+#define COUNTING_H
+
+#include "i18n.qh"
+
+// ===============================================
+// Time processing and counting functions/macros
+// ===============================================
+
+#define count_years_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s years")), ftos_decimals(time, decs))
+#define count_years(time) count_fill(time, \
+ ZCTX(_("CI_ZER^%d years")), /* zeroth */ \
+ ZCTX(_("CI_FIR^%d year")), /* first */ \
+ ZCTX(_("CI_SEC^%d years")), /* year */ \
+ ZCTX(_("CI_THI^%d years")), /* third */ \
+ ZCTX(_("CI_MUL^%d years"))) /* multi */
+
+#define count_weeks_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s weeks")), ftos_decimals(time, decs))
+#define count_weeks(time) count_fill(time, \
+ ZCTX(_("CI_ZER^%d weeks")), /* zeroth */ \
+ ZCTX(_("CI_FIR^%d week")), /* first */ \
+ ZCTX(_("CI_SEC^%d weeks")), /* week */ \
+ ZCTX(_("CI_THI^%d weeks")), /* third */ \
+ ZCTX(_("CI_MUL^%d weeks"))) /* multi */
+
+#define count_days_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s days")), ftos_decimals(time, decs))
+#define count_days(time) count_fill(time, \
+ ZCTX(_("CI_ZER^%d days")), /* zeroth */ \
+ ZCTX(_("CI_FIR^%d day")), /* first */ \
+ ZCTX(_("CI_SEC^%d days")), /* day */ \
+ ZCTX(_("CI_THI^%d days")), /* third */ \
+ ZCTX(_("CI_MUL^%d days"))) /* multi */
+
+#define count_hours_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s hours")), ftos_decimals(time, decs))
+#define count_hours(time) count_fill(time, \
+ ZCTX(_("CI_ZER^%d hours")), /* zeroth */ \
+ ZCTX(_("CI_FIR^%d hour")), /* first */ \
+ ZCTX(_("CI_SEC^%d hours")), /* hour */ \
+ ZCTX(_("CI_THI^%d hours")), /* third */ \
+ ZCTX(_("CI_MUL^%d hours"))) /* multi */
+
+
+#define count_minutes_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s minutes")), ftos_decimals(time, decs))
+#define count_minutes(time) count_fill(time, \
+ ZCTX(_("CI_ZER^%d minutes")), /* zeroth */ \
+ ZCTX(_("CI_FIR^%d minute")), /* first */ \
+ ZCTX(_("CI_SEC^%d minutes")), /* minute */ \
+ ZCTX(_("CI_THI^%d minutes")), /* third */ \
+ ZCTX(_("CI_MUL^%d minutes"))) /* multi */
+
+#define count_seconds_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s seconds")), ftos_decimals(time, decs))
+#define count_seconds(time) count_fill(time, \
+ ZCTX(_("CI_ZER^%d seconds")), /* zeroth */ \
+ ZCTX(_("CI_FIR^%d second")), /* first */ \
+ ZCTX(_("CI_SEC^%d seconds")), /* second */ \
+ ZCTX(_("CI_THI^%d seconds")), /* third */ \
+ ZCTX(_("CI_MUL^%d seconds"))) /* multi */
+
+string count_ordinal(int interval)
+{
+ // This function is designed primarily for the English language, it's impossible
+ // to accomodate all languages unless we do a specific function for each one...
+ // and since that's not technically feasible/practical, this is all we've got folks.
+
+ // Basically, it just allows you to represent a number or count in different ways
+ // depending on the number... like, with count_ordinal you can provide integers
+ // and retrieve 1st, 2nd, 3rd, nth ordinal numbers in a clean and simple way.
+ if(floor((interval % 100)/10) * 10 != 10) // examples: 12th, 111th, 213th will not execute this block
+ {
+ // otherwise, check normally for 1st,2nd,3rd insertions
+ switch(interval % 10)
+ {
+ case 1: return sprintf(_("%dst"), interval);
+ case 2: return sprintf(_("%dnd"), interval);
+ case 3: return sprintf(_("%drd"), interval);
+ default: return sprintf(_("%dth"), interval);
+ }
+ }
+ else { return sprintf(_("%dth"), interval); }
+
+ return "";
+}
+
+string count_fill(float interval, string zeroth, string first, string second, string third, string multi)
+{
+ // This function is designed primarily for the English language, it's impossible
+ // to accomodate all languages unless we do a specific function for each one...
+ // and since that's not technically feasible/practical, this is all we've got folks.
+
+ // Here you can insert specific strings based on the interval number, so you could do
+ // i.e. count_seconds which outputs like this:
+ // 0 seconds
+ // 1 second
+ // 2 seconds
+ // 3 seconds
+ // etc... minutes, hours, days, etc.
+
+ switch(floor(interval))
+ {
+ case 0: return sprintf(zeroth, interval);
+ case 1:
+ {
+ if(interval == 1) // EXACTLY value of 1
+ return sprintf(first, interval);
+ else
+ return sprintf(multi, interval);
+ }
+ case 2: return sprintf(second, interval);
+ case 3: return sprintf(third, interval);
+ default: return sprintf(multi, interval);
+ }
+ return "";
+}
+
+string process_time(float outputtype, float seconds)
+{
+ float tmp_hours = 0, tmp_minutes = 0, tmp_seconds = 0;
+ float tmp_years = 0, tmp_weeks = 0, tmp_days = 0;
+
+ tmp_seconds = floor(seconds);
+
+ if(tmp_seconds)
+ {
+ tmp_minutes = floor(tmp_seconds / 60);
+
+ if(tmp_minutes)
+ {
+ tmp_seconds -= (tmp_minutes * 60);
+ tmp_hours = floor(tmp_minutes / 60);
+
+ if(tmp_hours)
+ {
+ tmp_minutes -= (tmp_hours * 60);
+ tmp_days = floor(tmp_hours / 24);
+
+ if(tmp_days)
+ {
+ tmp_hours -= (tmp_days * 24);
+ tmp_weeks = floor(tmp_days / 7);
+
+ if(tmp_weeks)
+ {
+ tmp_days -= (tmp_weeks * 7);
+ tmp_years = floor(tmp_weeks / 52);
+ }
+ }
+ }
+ }
+ }
+
+ switch(outputtype)
+ {
+ case 1: return sprintf("%02d:%02d:%02d", tmp_hours, tmp_minutes, tmp_seconds);
+ case 2:
+ {
+ string output = "";
+
+ output = count_seconds(tmp_seconds);
+
+ if(tmp_minutes)
+ {
+ output = sprintf(
+ "%s%s",
+ count_minutes(tmp_minutes),
+ ((output != "") ? sprintf(", %s", output) : ""));
+ }
+
+ if(tmp_hours)
+ {
+ output = sprintf(
+ "%s%s",
+ count_hours(tmp_hours),
+ ((output != "") ? sprintf(", %s", output) : ""));
+ }
+
+ if(tmp_days)
+ {
+ output = sprintf(
+ "%s%s",
+ count_days(tmp_days),
+ ((output != "") ? sprintf(", %s", output) : ""));
+ }
+
+ if(tmp_weeks)
+ {
+ output = sprintf(
+ "%s%s",
+ count_weeks(tmp_weeks),
+ ((output != "") ? sprintf(", %s", output) : ""));
+ }
+
+ if(tmp_years)
+ {
+ output = sprintf(
+ "%s%s",
+ count_years(tmp_years),
+ ((output != "") ? sprintf(", %s", output) : ""));
+ }
+
+ return output;
+ }
+ case 3:
+ {
+ string output = "";
+
+ output = count_hours(tmp_hours);
+
+ if(tmp_weeks) { tmp_days += (tmp_weeks * 7); }
+ if(tmp_years) { tmp_days += (tmp_years * 365); }
+ if(tmp_days)
+ {
+ output = sprintf(
+ "%s%s",
+ count_days(tmp_days),
+ ((output != "") ? sprintf(", %s", output) : ""));
+ }
+
+ return output;
+ }
+ }
+ return "";
+}
+#endif
--- /dev/null
+#ifndef CVAR_H
+#define CVAR_H
+
+#include "nil.qh"
+#include "static.qh"
+
+void RegisterCvars(void(string name, string def, string desc, bool archive, string file) f) { }
+
+/** escape the string to make it safe for consoles */
+string MakeConsoleSafe(string input)
+{
+ input = strreplace("\n", "", input);
+ input = strreplace("\\", "\\\\", input);
+ input = strreplace("$", "$$", input);
+ input = strreplace("\"", "\\\"", input);
+ return input;
+}
+
+void RegisterCvars_Set(string name, string def, string desc, bool archive, string file)
+{
+ string val = string_null;
+ if (cvar_type(name) & CVAR_TYPEFLAG_EXISTS) {
+ val = cvar_string(name);
+ // Need to unset first to change the default
+ localcmd(sprintf("\nunset %s\n", name));
+ }
+ localcmd(sprintf("\n%s %s \"%s\" \"%s\"\n", (archive ? "seta" : "set"), name, MakeConsoleSafe(def), MakeConsoleSafe(desc)));
+ if (val) {
+ localcmd(sprintf("\n%s \"%s\"\n", name, MakeConsoleSafe(val)));
+ }
+}
+
+#ifndef SVQC
+STATIC_INIT_LATE(Cvars) { RegisterCvars(RegisterCvars_Set); }
+#endif
+
+const noref bool default_bool = false;
+const noref int default_int = 0;
+const noref float default_float = 0;
+const noref string default_string = "";
+const noref vector default_vector = '0 0 0';
+
+#define repr_cvar_bool(x) ((x) ? "1" : "0")
+#define repr_cvar_int(x) (ftos(x))
+#define repr_cvar_float(x) (ftos(x))
+#define repr_cvar_string(x) (x)
+#define repr_cvar_vector(x) (sprintf("%v", x))
+
+#define __AUTOCVAR(file, archive, var, type, desc, default) \
+ [[accumulate]] void RegisterCvars(void(string, string, string, bool, string) f) { f(#var, repr_cvar_##type(default), desc, archive, file); } \
+ type autocvar_##var = default
+#define AUTOCVAR_5(file, archive, var, type, desc) \
+ __AUTOCVAR(file, archive, var, type, desc, default_##type)
+#define AUTOCVAR_6(file, archive, var, type, default, desc) \
+ __AUTOCVAR(file, archive, var, type, desc, default)
+#define _AUTOCVAR(...) EVAL(OVERLOAD(AUTOCVAR, __FILE__, __VA_ARGS__))
+#define AUTOCVAR_SAVE(...) _AUTOCVAR(true, __VA_ARGS__)
+#define AUTOCVAR(...) _AUTOCVAR(false, __VA_ARGS__)
+
+#endif
--- /dev/null
+#ifndef MENUQC
+#ifndef DEFER_H
+#define DEFER_H
+#include "oo.qh"
+
+entityclass(Defer);
+class(Defer) .entity owner;
+class(Defer) .void() think;
+class(Defer) .float nextthink;
+
+/*
+==================
+SUB_Remove
+
+Remove self
+==================
+*/
+void SUB_Remove()
+{SELFPARAM();
+ remove (self);
+}
+
+void defer_think()
+{SELFPARAM();
+ self.think = SUB_Remove;
+ self.nextthink = time;
+ WITH(entity, self, self.owner, self.use());
+}
+
+/*
+ Execute func() after time + fdelay.
+ self when func is executed = self when defer is called
+*/
+void defer(float fdelay, void() func)
+{SELFPARAM();
+ entity e;
+
+ e = spawn();
+ e.owner = self;
+ e.use = func;
+ e.think = defer_think;
+ e.nextthink = time + fdelay;
+}
+
+#endif
+#endif
--- /dev/null
+#ifdef CSQC
+#ifndef DRAW_H
+#define DRAW_H
+
+#include "i18n.qh"
+#include "vector.qh"
+
+#include "../client/defs.qh"
+
+void Draw_CylindricLine(vector from, vector to, float thickness, string texture, float aspect, float shift, vector rgb, float theAlpha, float drawflag, vector vieworg)
+{
+ // I want to draw a quad...
+ // from and to are MIDPOINTS.
+
+ vector axis, thickdir, A, B, C, D;
+ float length_tex;
+
+ axis = normalize(to - from);
+ length_tex = aspect * vlen(to - from) / thickness;
+
+ // direction is perpendicular to the view normal, and perpendicular to the axis
+ thickdir = normalize(cross(axis, vieworg - from));
+
+ A = from - thickdir * (thickness / 2);
+ B = from + thickdir * (thickness / 2);
+ C = to + thickdir * (thickness / 2);
+ D = to - thickdir * (thickness / 2);
+
+ R_BeginPolygon(texture, drawflag);
+ R_PolygonVertex(A, '0 0 0' + shift * '1 0 0', rgb, theAlpha);
+ R_PolygonVertex(B, '0 1 0' + shift * '1 0 0', rgb, theAlpha);
+ R_PolygonVertex(C, '0 1 0' + (shift + length_tex) * '1 0 0', rgb, theAlpha);
+ R_PolygonVertex(D, '0 0 0' + (shift + length_tex) * '1 0 0', rgb, theAlpha);
+ R_EndPolygon();
+}
+
+// a border picture is a texture containing nine parts:
+// 1/4 width: left part
+// 1/2 width: middle part (stretched)
+// 1/4 width: right part
+// divided into
+// 1/4 height: top part
+// 1/2 height: middle part (stretched)
+// 1/4 height: bottom part
+void draw_BorderPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha, vector theBorderSize)
+{
+ if (theBorderSize.x < 0 && theBorderSize.y < 0) // draw whole image as it is
+ {
+ drawpic(theOrigin, pic, theSize, theColor, theAlpha, 0);
+ return;
+ }
+ if (theBorderSize.x == 0 && theBorderSize.y == 0) // no border
+ {
+ // draw only the central part
+ drawsubpic(theOrigin, theSize, pic, '0.25 0.25 0', '0.5 0.5 0', theColor, theAlpha, 0);
+ return;
+ }
+
+ vector dX, dY;
+ vector width, height;
+ vector bW, bH;
+ //pic = draw_UseSkinFor(pic);
+ width = eX * theSize.x;
+ height = eY * theSize.y;
+ if(theSize.x <= theBorderSize.x * 2)
+ {
+ // not wide enough... draw just left and right then
+ bW = eX * (0.25 * theSize.x / (theBorderSize.x * 2));
+ if(theSize.y <= theBorderSize.y * 2)
+ {
+ // not high enough... draw just corners
+ bH = eY * (0.25 * theSize.y / (theBorderSize.y * 2));
+ drawsubpic(theOrigin, width * 0.5 + height * 0.5, pic, '0 0 0', bW + bH, theColor, theAlpha, 0);
+ drawsubpic(theOrigin + width * 0.5, width * 0.5 + height * 0.5, pic, eX - bW, bW + bH, theColor, theAlpha, 0);
+ drawsubpic(theOrigin + height * 0.5, width * 0.5 + height * 0.5, pic, eY - bH, bW + bH, theColor, theAlpha, 0);
+ drawsubpic(theOrigin + theSize * 0.5, width * 0.5 + height * 0.5, pic, eX + eY - bW - bH, bW + bH, theColor, theAlpha, 0);
+ }
+ else
+ {
+ dY = theBorderSize.x * eY;
+ drawsubpic(theOrigin, width * 0.5 + dY, pic, '0 0 0', '0 0.25 0' + bW, theColor, theAlpha, 0);
+ drawsubpic(theOrigin + width * 0.5, width * 0.5 + dY, pic, '0 0 0' + eX - bW, '0 0.25 0' + bW, theColor, theAlpha, 0);
+ drawsubpic(theOrigin + dY, width * 0.5 + height - 2 * dY, pic, '0 0.25 0', '0 0.5 0' + bW, theColor, theAlpha, 0);
+ drawsubpic(theOrigin + width * 0.5 + dY, width * 0.5 + height - 2 * dY, pic, '0 0.25 0' + eX - bW, '0 0.5 0' + bW, theColor, theAlpha, 0);
+ drawsubpic(theOrigin + height - dY, width * 0.5 + dY, pic, '0 0.75 0', '0 0.25 0' + bW, theColor, theAlpha, 0);
+ drawsubpic(theOrigin + width * 0.5 + height - dY, width * 0.5 + dY, pic, '0 0.75 0' + eX - bW, '0 0.25 0' + bW, theColor, theAlpha, 0);
+ }
+ }
+ else
+ {
+ if(theSize.y <= theBorderSize.y * 2)
+ {
+ // not high enough... draw just top and bottom then
+ bH = eY * (0.25 * theSize.y / (theBorderSize.y * 2));
+ dX = theBorderSize.x * eX;
+ drawsubpic(theOrigin, dX + height * 0.5, pic, '0 0 0', '0.25 0 0' + bH, theColor, theAlpha, 0);
+ drawsubpic(theOrigin + dX, width - 2 * dX + height * 0.5, pic, '0.25 0 0', '0.5 0 0' + bH, theColor, theAlpha, 0);
+ drawsubpic(theOrigin + width - dX, dX + height * 0.5, pic, '0.75 0 0', '0.25 0 0' + bH, theColor, theAlpha, 0);
+ drawsubpic(theOrigin + height * 0.5, dX + height * 0.5, pic, '0 0 0' + eY - bH, '0.25 0 0' + bH, theColor, theAlpha, 0);
+ drawsubpic(theOrigin + dX + height * 0.5, width - 2 * dX + height * 0.5, pic, '0.25 0 0' + eY - bH, '0.5 0 0' + bH, theColor, theAlpha, 0);
+ drawsubpic(theOrigin + width - dX + height * 0.5, dX + height * 0.5, pic, '0.75 0 0' + eY - bH, '0.25 0 0' + bH, theColor, theAlpha, 0);
+ }
+ else
+ {
+ dX = theBorderSize.x * eX;
+ dY = theBorderSize.x * eY;
+ drawsubpic(theOrigin, dX + dY, pic, '0 0 0', '0.25 0.25 0', theColor, theAlpha, 0);
+ drawsubpic(theOrigin + dX, width - 2 * dX + dY, pic, '0.25 0 0', '0.5 0.25 0', theColor, theAlpha, 0);
+ drawsubpic(theOrigin + width - dX, dX + dY, pic, '0.75 0 0', '0.25 0.25 0', theColor, theAlpha, 0);
+ drawsubpic(theOrigin + dY, dX + height - 2 * dY, pic, '0 0.25 0', '0.25 0.5 0', theColor, theAlpha, 0);
+ drawsubpic(theOrigin + dY + dX, width - 2 * dX + height - 2 * dY, pic, '0.25 0.25 0', '0.5 0.5 0', theColor, theAlpha, 0);
+ drawsubpic(theOrigin + dY + width - dX, dX + height - 2 * dY, pic, '0.75 0.25 0', '0.25 0.5 0', theColor, theAlpha, 0);
+ drawsubpic(theOrigin + height - dY, dX + dY, pic, '0 0.75 0', '0.25 0.25 0', theColor, theAlpha, 0);
+ drawsubpic(theOrigin + height - dY + dX, width - 2 * dX + dY, pic, '0.25 0.75 0', '0.5 0.25 0', theColor, theAlpha, 0);
+ drawsubpic(theOrigin + height - dY + width - dX, dX + dY, pic, '0.75 0.75 0', '0.25 0.25 0', theColor, theAlpha, 0);
+ }
+ }
+}
+
+void drawstringright(vector position, string text, vector theScale, vector rgb, float theAlpha, int flag)
+{
+ position.x -= 2 / 3 * strlen(text) * theScale.x;
+ drawstring(position, text, theScale, rgb, theAlpha, flag);
+}
+
+void drawstringcenter(vector position, string text, vector theScale, vector rgb, float theAlpha, int flag)
+{
+ position.x = 0.5 * (vid_conwidth - 0.6025 * strlen(text) * theScale.x);
+ drawstring(position, text, theScale, rgb, theAlpha, flag);
+}
+
+#endif
+#endif
--- /dev/null
+#ifndef FILE_H
+#define FILE_H
+
+bool fexists(string f)
+{
+ int fh = fopen(f, FILE_READ);
+ if (fh < 0)
+ return false;
+ fclose(fh);
+ return true;
+}
+
+#endif
--- /dev/null
+#ifndef I18N_H
+#define I18N_H
+
+#include "log.qh"
+
+// translation helpers
+string prvm_language;
+
+string language_filename(string s)
+{
+ string fn = prvm_language;
+ if (fn == "" || fn == "dump")
+ return s;
+ fn = strcat(s, ".", fn);
+ int fh = fopen(fn, FILE_READ);
+ if (fh >= 0)
+ {
+ fclose(fh);
+ return fn;
+ }
+ return s;
+}
+
+string CTX(string s)
+{
+ int p = strstrofs(s, "^", 0);
+ if (p < 0)
+ return s;
+ return substring(s, p + 1, -1);
+}
+
+#define ZCTX(s) strzone(CTX(s))
+
+#endif
--- /dev/null
+#ifndef LAZY_H
+#define LAZY_H
+
+#include "oo.qh"
+
+CLASS(Lazy, Object)
+ ATTRIB(Lazy, m_get, entity(), func_null);
+ CONSTRUCTOR(Lazy, entity() _compute) { this.m_get = _compute; }
+ENDCLASS(Lazy)
+
+#define LAZY(id) __lazy_##id
+#define LAZY_NEW(id, compute) entity LAZY(id)() { \
+ static bool done; \
+ static entity it; \
+ if (!done) { it = compute; done = true; } \
+ return it; \
+}
+#endif
--- /dev/null
+#ifndef LOG_H
+#define LOG_H
+
+#define _printferr(...) error(sprintf(__VA_ARGS__))
+#define _printfbt(...) backtrace(sprintf(__VA_ARGS__))
+#define printf(...) print(sprintf(__VA_ARGS__))
+#define dprintf(...) dprint(sprintf(__VA_ARGS__))
+#define _dprintf2(...) do { if (autocvar_developer > 1) dprintf(__VA_ARGS__); } while (0)
+
+#define assert(expr, ...) do { if (!(expr)) LOG_WARNINGF(__VA_ARGS__); } while (0)
+
+#define _LOG(f, level, s) f("[::"level"] ["__FILE__":%s:%.0f] %s", __FUNC__, __LINE__, s)
+
+#define LOG_FATAL(...) _LOG_FATAL(strcat("", __VA_ARGS__))
+#define LOG_FATALF(...) _LOG_FATAL(sprintf(__VA_ARGS__))
+#define _LOG_FATAL(s) _LOG(_printferr, "FATAL", s)
+
+#define LOG_SEVERE(...) _LOG_SEVERE(strcat("", __VA_ARGS__))
+#define LOG_SEVEREF(...) _LOG_SEVERE(sprintf(__VA_ARGS__))
+#define _LOG_SEVERE(s) _LOG(_printfbt, "SEVERE", s)
+
+#define LOG_WARNING(...) _LOG_WARNING(strcat("", __VA_ARGS__))
+#define LOG_WARNINGF(...) _LOG_WARNING(sprintf(__VA_ARGS__))
+#define _LOG_WARNING(s) _LOG(printf, "WARNING", s)
+
+#define LOG_INFO(...) do { if (autocvar_developer) _LOG_INFO(strcat("", __VA_ARGS__)); else print (__VA_ARGS__); } while (0)
+#define LOG_INFOF(...) do { if (autocvar_developer) _LOG_INFO(sprintf(__VA_ARGS__)); else printf(__VA_ARGS__); } while (0)
+#define _LOG_INFO(s) _LOG(printf, "INFO", s)
+
+#define LOG_TRACE(...) _LOG_TRACE(strcat("", __VA_ARGS__))
+#define LOG_TRACEF(...) _LOG_TRACE(sprintf(__VA_ARGS__))
+#define _LOG_TRACE(s) _LOG(dprintf, "TRACE", s)
+
+#define LOG_DEBUG(...) _LOG_DEBUG(strcat("", __VA_ARGS__))
+#define LOG_DEBUGF(...) _LOG_DEBUG(sprintf(__VA_ARGS__))
+#define _LOG_DEBUG(s) _LOG(_dprintf2, "DEBUG", s)
+
+// TODO: this sucks, lets find a better way to do backtraces?
+#ifdef SVQC
+void builtin_remove(entity);
+#define _backtrace() builtin_remove(NULL)
+#else
+void remove(entity);
+#define _backtrace() remove(NULL)
+#endif
+
+noref int autocvar_developer;
+noref bool autocvar_prvm_backtraceforwarnings;
+
+#define backtrace(msg) do { \
+ int dev = autocvar_developer; \
+ bool war = autocvar_prvm_backtraceforwarnings; \
+ cvar_set("developer", "1"); \
+ cvar_set("prvm_backtraceforwarnings", "1"); \
+ print("\n--- CUT HERE ---\n", msg, "\n"); \
+ _backtrace(); \
+ print("\n--- CUT UNTIL HERE ---\n"); \
+ cvar_set("developer", ftos(dev)); \
+ cvar_set("prvm_backtraceforwarnings", ftos(war)); \
+} while (0)
+
+#define ASSERT(expr) do { if (!(expr)) LOG_FATAL("assertion failed: " #expr "\n"); } while (0)
+
+#endif
--- /dev/null
+#ifndef MATH_H
+#define MATH_H
+
+void mean_accumulate(entity e, .float a, .float c, float mean, float value, float weight)
+{
+ if (weight == 0)
+ return;
+ if (mean == 0)
+ e.(a) *= pow(value, weight);
+ else
+ e.(a) += pow(value, mean) * weight;
+ e.(c) += weight;
+}
+
+float mean_evaluate(entity e, .float a, .float c, float mean)
+{
+ if (e.(c) == 0)
+ return 0;
+ if (mean == 0)
+ return pow(e.(a), 1.0 / e.(c));
+ else
+ return pow(e.(a) / e.(c), 1.0 / mean);
+}
+
+#define MEAN_ACCUMULATE(prefix,v,w) mean_accumulate(self,prefix##_accumulator,prefix##_count,prefix##_mean,v,w)
+#define MEAN_EVALUATE(prefix) mean_evaluate(self,prefix##_accumulator,prefix##_count,prefix##_mean)
+#define MEAN_DECLARE(prefix,m) float prefix##_mean = m; .float prefix##_count, prefix##_accumulator
+
+/*
+==================
+crandom
+
+Returns a random number between -1.0 and 1.0
+==================
+*/
+float crandom()
+{
+ return 2 * (random() - 0.5);
+}
+
+
+/*
+==================
+Angc used for animations
+==================
+*/
+
+
+float angc(float a1, float a2)
+{
+ while (a1 > 180) a1 -= 360;
+ while (a1 < -179) a1 += 360;
+ while (a2 > 180) a2 -= 360;
+ while (a2 < -179) a2 += 360;
+ float a = a1 - a2;
+ while (a > 180) a -= 360;
+ while (a < -179) a += 360;
+ return a;
+}
+
+float fsnap(float val,float fsize)
+{
+ return rint(val / fsize) * fsize;
+}
+
+vector vsnap(vector point,float fsize)
+{
+ vector vret;
+
+ vret.x = rint(point.x / fsize) * fsize;
+ vret.y = rint(point.y / fsize) * fsize;
+ vret.z = ceil(point.z / fsize) * fsize;
+
+ return vret;
+}
+
+vector lerpv(float t0, vector v0, float t1, vector v1, float t)
+{
+ return v0 + (v1 - v0) * ((t - t0) / (t1 - t0));
+}
+
+vector bezier_quadratic_getpoint(vector a, vector b, vector c, float t)
+{
+ return
+ (c - 2 * b + a) * (t * t) +
+ (b - a) * (2 * t) +
+ a;
+}
+
+vector bezier_quadratic_getderivative(vector a, vector b, vector c, float t)
+{
+ return
+ (c - 2 * b + a) * (2 * t) +
+ (b - a) * 2;
+}
+
+float cubic_speedfunc(float startspeedfactor, float endspeedfactor, float x)
+{
+ return
+ ((( startspeedfactor + endspeedfactor - 2
+ ) * x - 2 * startspeedfactor - endspeedfactor + 3
+ ) * x + startspeedfactor
+ ) * x;
+}
+
+bool cubic_speedfunc_is_sane(float startspeedfactor, float endspeedfactor)
+{
+ if (startspeedfactor < 0 || endspeedfactor < 0)
+ return false;
+
+ /*
+ // if this is the case, the possible zeros of the first derivative are outside
+ // 0..1
+ We can calculate this condition as condition
+ if(se <= 3)
+ return true;
+ */
+
+ // better, see below:
+ if (startspeedfactor <= 3 && endspeedfactor <= 3)
+ return true;
+
+ // if this is the case, the first derivative has no zeros at all
+ float se = startspeedfactor + endspeedfactor;
+ float s_e = startspeedfactor - endspeedfactor;
+ if (3 * (se - 4) * (se - 4) + s_e * s_e <= 12) // an ellipse
+ return true;
+
+ // Now let s <= 3, s <= 3, s+e >= 3 (triangle) then we get se <= 6 (top right corner).
+ // we also get s_e <= 6 - se
+ // 3 * (se - 4)^2 + (6 - se)^2
+ // is quadratic, has value 12 at 3 and 6, and value < 12 in between.
+ // Therefore, above "better" check works!
+
+ return false;
+
+ // known good cases:
+ // (0, [0..3])
+ // (0.5, [0..3.8])
+ // (1, [0..4])
+ // (1.5, [0..3.9])
+ // (2, [0..3.7])
+ // (2.5, [0..3.4])
+ // (3, [0..3])
+ // (3.5, [0.2..2.3])
+ // (4, 1)
+
+ /*
+ On another note:
+ inflection point is always at (2s + e - 3) / (3s + 3e - 6).
+
+ s + e - 2 == 0: no inflection
+
+ s + e > 2:
+ 0 < inflection < 1 if:
+ 0 < 2s + e - 3 < 3s + 3e - 6
+ 2s + e > 3 and 2e + s > 3
+
+ s + e < 2:
+ 0 < inflection < 1 if:
+ 0 > 2s + e - 3 > 3s + 3e - 6
+ 2s + e < 3 and 2e + s < 3
+
+ Therefore: there is an inflection point iff:
+ e outside (3 - s)/2 .. 3 - s*2
+
+ in other words, if (s,e) in triangle (1,1)(0,3)(0,1.5) or in triangle (1,1)(3,0)(1.5,0)
+ */
+}
+
+/** continuous function mapping all reals into -1..1 */
+float float2range11(float f)
+{
+ return f / (fabs(f) + 1);
+}
+
+/** continuous function mapping all reals into 0..1 */
+float float2range01(float f)
+{
+ return 0.5 + 0.5 * float2range11(f);
+}
+
+float median(float a, float b, float c)
+{
+ return (a < c) ? bound(a, b, c) : bound(c, b, a);
+}
+
+float almost_equals(float a, float b)
+{
+ float eps = (max(a, -a) + max(b, -b)) * 0.001;
+ return a - b < eps && b - a < eps;
+}
+
+float almost_in_bounds(float a, float b, float c)
+{
+ float eps = (max(a, -a) + max(c, -c)) * 0.001;
+ if (a > c)
+ eps = -eps;
+ return b == median(a - eps, b, c + eps);
+}
+
+float power2of(float e)
+{
+ return pow(2, e);
+}
+
+float log2of(float x)
+{
+ // NOTE: generated code
+ if (x > 2048)
+ if (x > 131072)
+ if (x > 1048576)
+ if (x > 4194304)
+ return 23;
+ else
+ if (x > 2097152)
+ return 22;
+ else
+ return 21;
+ else
+ if (x > 524288)
+ return 20;
+ else
+ if (x > 262144)
+ return 19;
+ else
+ return 18;
+ else
+ if (x > 16384)
+ if (x > 65536)
+ return 17;
+ else
+ if (x > 32768)
+ return 16;
+ else
+ return 15;
+ else
+ if (x > 8192)
+ return 14;
+ else
+ if (x > 4096)
+ return 13;
+ else
+ return 12;
+ else
+ if (x > 32)
+ if (x > 256)
+ if (x > 1024)
+ return 11;
+ else
+ if (x > 512)
+ return 10;
+ else
+ return 9;
+ else
+ if (x > 128)
+ return 8;
+ else
+ if (x > 64)
+ return 7;
+ else
+ return 6;
+ else
+ if (x > 4)
+ if (x > 16)
+ return 5;
+ else
+ if (x > 8)
+ return 4;
+ else
+ return 3;
+ else
+ if (x > 2)
+ return 2;
+ else
+ if (x > 1)
+ return 1;
+ else
+ return 0;
+}
+
+
+#endif
--- /dev/null
+#ifndef NET_H
+#define NET_H
+
+#ifdef SVQC
+.int Version; // deprecated, use SendFlags
+.int SendFlags;
+.bool(entity to, int sendflags) SendEntity;
+.bool(entity this, entity to, int sendflags) SendEntity3;
+
+bool SendEntity_self(entity to, int sendflags) { return self.SendEntity3(self, to, sendflags); }
+
+void Net_LinkEntity(entity e, bool docull, float dt, bool(entity this, entity to, int sendflags) sendfunc)
+{
+ if (!e.classname) e.classname = "net_linked";
+
+ if (!e.model || !self.modelindex) {
+ vector mi = e.mins;
+ vector ma = e.maxs;
+ _setmodel(e, "null");
+ setsize(e, mi, ma);
+ }
+
+ e.SendEntity = SendEntity_self;
+ e.SendEntity3 = sendfunc;
+ e.SendFlags = 0xFFFFFF;
+
+ if (!docull) e.effects |= EF_NODEPTHTEST;
+
+ if (dt) {
+ e.nextthink = time + dt;
+ e.think = SUB_Remove;
+ }
+}
+
+.void() uncustomizeentityforclient;
+.float uncustomizeentityforclient_set;
+
+void SetCustomizer(entity e, float(void) customizer, void(void) uncustomizer)
+{
+ e.customizeentityforclient = customizer;
+ e.uncustomizeentityforclient = uncustomizer;
+ e.uncustomizeentityforclient_set = !!uncustomizer;
+}
+
+void UncustomizeEntitiesRun()
+{
+ for (entity e = NULL; (e = findfloat(e, uncustomizeentityforclient_set, 1)); ) {
+ WITH(entity, self, e, e.uncustomizeentityforclient());
+ }
+}
+
+#endif
+
+#include "registry.qh"
+#include "sort.qh"
+
+.string netname;
+.int m_id;
+.void(entity this, bool isNew) m_read;
+
+#ifdef CSQC
+ #define Net_Accept() do { if (!this) this = spawn(); } while (0)
+ #define Net_Reject() do { if (this) remove(this); } while (0)
+#else
+ #define WriteHeader(to, id) do { \
+ if (NET_##id##_istemp) WriteByte(to, SVC_TEMPENTITY); \
+ WriteByte(to, NET_##id.m_id); \
+ } while (0)
+#endif
+
+#ifdef CSQC
+ #define REGISTER_NET_LINKED(id, param) \
+ void Ent_Read##id(entity this, param) { this = self; } \
+ REGISTER(RegisterLinkedEntities, NET, LinkedEntities, id, m_id, spawn()) { \
+ this.netname = #id; \
+ this.m_read = Ent_Read##id; \
+ } \
+ [[accumulate]] void Ent_Read##id(entity this, param)
+#else
+ #define REGISTER_NET_LINKED(id, param) \
+ const bool NET_##id##_istemp = false; \
+ REGISTER(RegisterLinkedEntities, NET, LinkedEntities, id, m_id, spawn()) { \
+ this.netname = #id; \
+ }
+#endif
+
+REGISTRY(LinkedEntities, BIT(0))
+REGISTER_REGISTRY(RegisterLinkedEntities)
+REGISTRY_SORT(LinkedEntities, netname, 0)
+STATIC_INIT(RegisterLinkedEntities_renumber) {
+ for (int i = 0; i < LinkedEntities_COUNT; ++i) {
+ LinkedEntities[i].m_id = 100 + i;
+ }
+}
+
+#ifdef CSQC
+ #define REGISTER_NET_TEMP(id, param) \
+ void Net_Read##id(entity this, param); \
+ REGISTER(RegisterTempEntities, NET, TempEntities, id, m_id, spawn()) { \
+ this.netname = #id; \
+ this.m_read = Net_Read##id; \
+ } \
+ void Net_Read##id(entity this, param)
+#else
+ #define REGISTER_NET_TEMP(id, param) \
+ const bool NET_##id##_istemp = true; \
+ REGISTER(RegisterTempEntities, NET, TempEntities, id, m_id, spawn()) { \
+ this.netname = #id; \
+ }
+#endif
+
+REGISTRY(TempEntities, BIT(0))
+REGISTER_REGISTRY(RegisterTempEntities)
+REGISTRY_SORT(TempEntities, netname, 0)
+STATIC_INIT(RegisterTempEntities_renumber) {
+ for (int i = 0; i < TempEntities_COUNT; ++i) {
+ TempEntities[i].m_id = 115 + i;
+ }
+}
+
+#ifndef MENUQC
+#ifdef CSQC
+int ReadInt24_t()
+{
+ int v = ReadShort() << 8; // note: this is signed
+ v += ReadByte(); // note: this is unsigned
+ return v;
+}
+vector ReadInt48_t()
+{
+ vector v;
+ v.x = ReadInt24_t();
+ v.y = ReadInt24_t();
+ v.z = 0;
+ return v;
+}
+vector ReadInt72_t()
+{
+ vector v;
+ v.x = ReadInt24_t();
+ v.y = ReadInt24_t();
+ v.z = ReadInt24_t();
+ return v;
+}
+#else
+void WriteInt24_t(float dst, float val)
+{
+ float v;
+ WriteShort(dst, (v = floor(val >> 8)));
+ WriteByte(dst, val - (v << 8)); // 0..255
+}
+void WriteInt48_t(float dst, vector val)
+{
+ WriteInt24_t(dst, val.x);
+ WriteInt24_t(dst, val.y);
+}
+void WriteInt72_t(float dst, vector val)
+{
+ WriteInt24_t(dst, val.x);
+ WriteInt24_t(dst, val.y);
+ WriteInt24_t(dst, val.z);
+}
+#endif
+#endif
+
+#endif
--- /dev/null
+#ifndef NIL_H
+#define NIL_H
+
+#if QCC_SUPPORT_NIL
+#define func_null nil
+#define string_null nil
+#else
+// the NULL function
+var void func_null(void);
+string string_null;
+#endif
+
+#endif
--- /dev/null
+#ifndef OO_H
+#define OO_H
+
+#include "nil.qh"
+
+#ifdef MENUQC
+ #define NULL (null_entity)
+#else
+ #define NULL (world)
+#endif
+
+.string classname;
+/** Location entity was spawned from in source */
+.string sourceLocFile;
+.int sourceLocLine;
+entity _spawn();
+entity __spawn(string _classname, string _sourceFile, int _sourceLine) {
+ entity this = _spawn();
+ this.classname = _classname;
+ this.sourceLocFile = _sourceFile;
+ this.sourceLocLine = _sourceLine;
+ return this;
+}
+
+
+
+#define entityclass(...) EVAL(OVERLOAD(entityclass, __VA_ARGS__))
+#define entityclass_1(name) entityclass_2(name, Object)
+#ifndef QCC_SUPPORT_ENTITYCLASS
+ #define entityclass_2(name, base) typedef entity name
+ #define class(name)
+ #define new(class) __spawn(#class, __FILE__, __LINE__)
+#else
+ #define entityclass_2(name, base) entityclass name : base {}
+ #define class(name) [[class(name)]]
+ #define new(class) ((class) __spawn(#class, __FILE__, __LINE__))
+#endif
+
+// Classes have a `spawn##cname(entity)` constructor
+// The parameter is used across [[accumulate]] functions
+
+// Macros to hide this implementation detail:
+#ifdef GMQCC
+#define NEW(cname, ...) \
+ OVERLOAD(spawn##cname, new(cname), ##__VA_ARGS__)
+
+#define CONSTRUCT(cname, ...) \
+ OVERLOAD(spawn##cname, this, ##__VA_ARGS__)
+#else
+#define NEW_(cname, ...) \
+ OVERLOAD_(spawn##cname, __VA_ARGS__)
+#define NEW(cname, ...) \
+ NEW_(cname, new(cname), ##__VA_ARGS__)(new(cname), ##__VA_ARGS__)
+
+#define CONSTRUCT_(cname, ...) \
+ OVERLOAD_(spawn##cname, __VA_ARGS__)
+#define CONSTRUCT(cname, ...) \
+ CONSTRUCT_(cname, this, ##__VA_ARGS__)(this, ##__VA_ARGS__)
+#endif
+
+#define CONSTRUCTOR(cname, ...) \
+ cname OVERLOAD(spawn##cname, cname this, __VA_ARGS__) { return = this; } \
+ [[accumulate]] cname OVERLOAD(spawn##cname, cname this, __VA_ARGS__)
+
+.string vtblname;
+.entity vtblbase;
+
+void RegisterClasses() { }
+STATIC_INIT(RegisterClasses) { RegisterClasses(); }
+
+#define VTBL(cname, base) \
+ INIT_STATIC(cname); \
+ entity cname##_vtbl; \
+ void cname##_vtbl_init() { \
+ cname e = new(vtbl); \
+ spawn##cname##_static(e); \
+ e.vtblname = #cname; \
+ /* Top level objects refer to themselves */ \
+ e.vtblbase = base##_vtbl ? base##_vtbl : e; \
+ cname##_vtbl = e; \
+ } \
+ ACCUMULATE_FUNCTION(RegisterClasses, cname##_vtbl_init)
+
+#define INIT_STATIC(cname) [[accumulate]] void spawn##cname##_static(cname this)
+#define INIT(cname) [[accumulate]] cname spawn##cname##_1(cname this)
+
+#define CLASS(cname, base) \
+ entityclass(cname, base); \
+ class(cname) .bool instanceOf##cname; \
+ VTBL(cname, base) \
+ INIT_STATIC(cname) { \
+ if (cname##_vtbl) { \
+ copyentity(cname##_vtbl, this); \
+ return; \
+ } \
+ spawn##base##_static(this); \
+ this.instanceOf##cname = true; \
+ } \
+ INIT(cname) { \
+ /* Only statically initialize the current class, it contains everything it inherits */ \
+ if (cname##_vtbl.vtblname == this.classname) { \
+ spawn##cname##_static(this); \
+ this.classname = #cname; \
+ this.vtblname = string_null; \
+ this.vtblbase = cname##_vtbl; \
+ } \
+ spawn##base##_1(this); \
+ }
+
+#define METHOD(cname, name, prototype) \
+ class(cname) .prototype name; \
+ prototype cname##_##name; \
+ INIT_STATIC(cname) { this.name = cname##_##name; } \
+ prototype cname##_##name
+
+#define ATTRIB(cname, name, type, val) \
+ class(cname) .type name; \
+ INIT(cname) { this.name = val; }
+
+#define ATTRIBARRAY(cname, name, type, cnt) \
+ class(cname) .type name[cnt];
+
+#define ENDCLASS(cname) \
+ [[last]] INIT(cname) { return this; }
+
+#define SUPER(cname) (cname##_vtbl.vtblbase)
+#define super (this.vtblbase.vtblbase)
+
+#define spawn_static(this)
+#define spawn_1(this)
+#define _vtbl NULL
+CLASS(Object, );
+ METHOD(Object, describe, string(entity this)) {
+ string s = _("No description");
+ if (cvar("developer")) {
+ for (int i = 0, n = numentityfields(); i < n; ++i) {
+ string value = getentityfieldstring(i, this);
+ if (value != "") s = sprintf("%s\n%s = %s", s, entityfieldname(i), value);
+ }
+ }
+ return s;
+ }
+ METHOD(Object, display, void(entity this, void(string name, string icon) returns)) {
+ returns(sprintf("entity %i", this), "nopreview_map");
+ }
+ENDCLASS(Object)
+#undef spawn_static
+#undef spawn_1
+#undef _vtbl
+
+#endif
--- /dev/null
+#ifdef CSQC
+#ifndef PLAYER_H
+#define PLAYER_H
+
+#include "string.qh"
+
+#include "../client/main.qh"
+#include "../common/teams.qh"
+
+int GetPlayerColorForce(int i)
+{
+ if(!teamplay)
+ return 0;
+ else
+ return stof(getplayerkeyvalue(i, "colors")) & 15;
+}
+
+int GetPlayerColor(int i)
+{
+ if(!playerslots[i].gotscores) // unconnected
+ return NUM_SPECTATOR;
+ else if(stof(getplayerkeyvalue(i, "frags")) == FRAGS_SPECTATOR)
+ return NUM_SPECTATOR;
+ else
+ return GetPlayerColorForce(i);
+}
+
+string GetPlayerName(int i)
+{
+ return ColorTranslateRGB(getplayerkeyvalue(i, "name"));
+}
+
+#endif
+#endif
+++ /dev/null
-#include "prandom.qh"
-
-// prandom - PREDICTABLE random number generator (not seeded yet)
-
-#ifdef USE_PRANDOM
-float prandom_seed;
-float prandom()
-{
- float c;
- c = crc16(false, strcat(ftos(prandom_seed), ftos(prandom_seed + M_PI)));
- prandom_seed = c;
-
-#ifdef USE_PRANDOM_DEBUG
- LOG_TRACE("RANDOM -> ", ftos(c), "\n");
-#endif
-
- return c / 65536; // in [0..1[
-}
-
-vector prandomvec()
-{
- vector v;
-
- do
- {
- v.x = prandom();
- v.y = prandom();
- v.z = prandom();
- }
- while(v * v > 1);
-
- return v;
-}
-
-void psrandom(float seed)
-{
- prandom_seed = seed;
-#ifdef USE_PRANDOM_DEBUG
- LOG_TRACE("SRANDOM ", ftos(seed), "\n");
-#endif
-}
-
-#ifdef USE_PRANDOM_DEBUG
-void prandom_debug()
-{
- LOG_TRACE("Current random seed = ", ftos(prandom_seed), "\n");
-}
-#endif
-#endif
+++ /dev/null
-#ifndef PRANDOM_H
-#define PRANDOM_H
-
-// prandom - PREDICTABLE random number generator
-
-#define USE_PRANDOM
-
-#ifdef USE_PRANDOM
-float prandom();
-vector prandomvec();
-
-void psrandom(float seed);
-#ifdef USE_PRANDOM_DEBUG
-void prandom_debug();
-#else
-#define prandom_debug()
-#endif
-#else
-#define prandom random
-#define prandomvec randomvec
-#define psrandom(x)
-#define prandom_debug()
-#endif
-#endif
--- /dev/null
+#ifndef PROGNAME_H
+#define PROGNAME_H
+
+#if defined(MENUQC)
+ #define PROGNAME "MENUQC"
+#elif defined(SVQC)
+ #define PROGNAME "SVQC"
+#elif defined(CSQC)
+ #define PROGNAME "CSQC"
+#else
+ #error "Unable to detect PROGNAME"
+#endif
+
+#endif
--- /dev/null
+#include "random.qh"
+
+void RandomSelection_Init()
+{
+ RandomSelection_totalweight = 0;
+ RandomSelection_chosen_ent = NULL;
+ RandomSelection_chosen_float = 0;
+ RandomSelection_chosen_string = string_null;
+ RandomSelection_best_priority = -1;
+}
+
+void RandomSelection_Add(entity e, float f, string s, float weight, float priority)
+{
+ if (priority > RandomSelection_best_priority)
+ {
+ RandomSelection_best_priority = priority;
+ RandomSelection_chosen_ent = e;
+ RandomSelection_chosen_float = f;
+ RandomSelection_chosen_string = s;
+ RandomSelection_totalweight = weight;
+ }
+ else if (priority == RandomSelection_best_priority)
+ {
+ RandomSelection_totalweight += weight;
+ if (random() * RandomSelection_totalweight <= weight)
+ {
+ RandomSelection_chosen_ent = e;
+ RandomSelection_chosen_float = f;
+ RandomSelection_chosen_string = s;
+ }
+ }
+}
+
+
+// prandom - PREDICTABLE random number generator (not seeded yet)
+
+#ifdef USE_PRANDOM
+float prandom_seed;
+float prandom()
+{
+ float c;
+ c = crc16(false, strcat(ftos(prandom_seed), ftos(prandom_seed + M_PI)));
+ prandom_seed = c;
+
+#ifdef USE_PRANDOM_DEBUG
+ LOG_TRACE("RANDOM -> ", ftos(c), "\n");
+#endif
+
+ return c / 65536; // in [0..1[
+}
+
+vector prandomvec()
+{
+ vector v;
+
+ do
+ {
+ v.x = prandom();
+ v.y = prandom();
+ v.z = prandom();
+ }
+ while(v * v > 1);
+
+ return v;
+}
+
+void psrandom(float seed)
+{
+ prandom_seed = seed;
+#ifdef USE_PRANDOM_DEBUG
+ LOG_TRACE("SRANDOM ", ftos(seed), "\n");
+#endif
+}
+
+#ifdef USE_PRANDOM_DEBUG
+void prandom_debug()
+{
+ LOG_TRACE("Current random seed = ", ftos(prandom_seed), "\n");
+}
+#endif
+#endif
--- /dev/null
+#ifndef RANDOM_H
+#define RANDOM_H
+
+float RandomSelection_totalweight;
+float RandomSelection_best_priority;
+entity RandomSelection_chosen_ent;
+float RandomSelection_chosen_float;
+string RandomSelection_chosen_string;
+
+void RandomSelection_Init();
+void RandomSelection_Add(entity e, float f, string s, float weight, float priority);
+
+// prandom - PREDICTABLE random number generator
+
+#define USE_PRANDOM
+
+#ifdef USE_PRANDOM
+float prandom();
+vector prandomvec();
+
+void psrandom(float seed);
+#ifdef USE_PRANDOM_DEBUG
+void prandom_debug();
+#else
+#define prandom_debug()
+#endif
+#else
+#define prandom random
+#define prandomvec randomvec
+#define psrandom(x)
+#define prandom_debug()
+#endif
+#endif
--- /dev/null
+#ifndef REGISTRY_H
+#define REGISTRY_H
+
+#include "oo.qh"
+
+#define REGISTER_INIT(ns, id) [[accumulate]] void Register_##ns##_##id##_init(entity this)
+#define REGISTER_INIT_POST(ns, id) [[accumulate]] void Register_##ns##_##id##_init_post(entity this)
+
+#define REGISTRY(id, max) \
+ void Register##id() {} \
+ const int id##_MAX = max; \
+ noref entity id[id##_MAX], id##_first, id##_last; \
+ int id##_COUNT;
+
+/**
+ * Register a new entity with a global constructor.
+ * Must be followed by a semicolon or a function body with a `this` parameter.
+ * Wrapper macros may perform actions after user initialization like so:
+ * #define REGISTER_FOO(id) \
+ * REGISTER(RegisterFoos, FOO, FOOS, id, m_id, NEW(Foo)); \
+ * REGISTER_INIT_POST(FOO, id) { \
+ * print("Registering foo #", this.m_id + 1, "\n"); \
+ * } \
+ * REGISTER_INIT(FOO, id)
+ *
+ * Don't forget to forward declare `initfunc` and call `REGISTER_REGISTRY`:
+ * void RegisterFoos();
+ * REGISTER_REGISTRY(RegisterFoos)
+ *
+ * @param initfunc The global constructor to accumulate into
+ * @param ns Short for namespace, prefix for each global (ns##_##id)
+ * @param array The array to add each entity to. Also requires `array##_first` and `array##_last` to be defined
+ * @param id The identifier of the current entity being registered
+ * @param fld The field to store the current count into
+ * @param inst An expression to create a new instance, invoked for every registration
+ */
+#define REGISTER(initfunc, ns, array, id, fld, inst) \
+ entity ns##_##id; \
+ REGISTER_INIT(ns, id) { } \
+ REGISTER_INIT_POST(ns, id) { } \
+ .entity enemy; /* internal next pointer */ \
+ void Register_##ns##_##id() { \
+ if (array##_COUNT >= array##_MAX) LOG_FATALF("Registry capacity exceeded (%s)", ftos(array##_MAX)); \
+ entity this = inst; \
+ ns##_##id = this; \
+ this.fld = array##_COUNT; \
+ array[array##_COUNT++] = this; \
+ if (!array##_first) array##_first = this; \
+ if ( array##_last) array##_last.enemy = this; \
+ array##_last = this; \
+ Register_##ns##_##id##_init(this); \
+ Register_##ns##_##id##_init_post(this); \
+ } \
+ ACCUMULATE_FUNCTION(initfunc, Register_##ns##_##id) \
+ REGISTER_INIT(ns, id)
+
+#define REGISTRY_SORT(id, field, skip) \
+ void _REGISTRY_SWAP_##id(int i, int j, entity pass) { \
+ i += skip; j += skip; \
+ entity e = id[i]; \
+ id[i] = id[j]; \
+ id[j] = e; \
+ } \
+ float _REGISTRY_CMP_##id(int i, int j, entity pass) { \
+ i += skip; j += skip; \
+ string a = id[i].field; \
+ string b = id[j].field; \
+ return strcasecmp(a, b); \
+ } \
+ STATIC_INIT(Registry_sort_##id) { \
+ heapsort(id##_COUNT - (skip), _REGISTRY_SWAP_##id, _REGISTRY_CMP_##id, NULL); \
+ }
+
+#endif
--- /dev/null
+#ifndef REPLICATE_H
+#define REPLICATE_H
+#ifndef MENUQC
+
+#define REPLICATE(...) EVAL(OVERLOAD(REPLICATE, __VA_ARGS__))
+
+[[accumulate]] void ReplicateVars(entity this, string thisname, int i) { }
+
+#define REPLICATE_3(fld, type, var) REPLICATE_4(fld, type, var, )
+#define REPLICATE_4(fld, type, var, func) REPLICATE_##type(fld, var, func)
+#define REPLICATE_string(fld, var, func) REPLICATE_7(fld, string, var, , \
+ { if (field) strunzone(field); field = strzone(it); }, \
+ { if (field) strunzone(field); field = string_null; }, \
+ { \
+ /* also initialize to the default value of func when requesting cvars */ \
+ string s = func(field); \
+ if (s != field) { \
+ strunzone(field); \
+ field = strzone(s); \
+ } \
+ })
+#define REPLICATE_float(fld, var, func) REPLICATE_7(fld, float, var, func, { field = stof(it); }, , )
+#define REPLICATE_bool(fld, var, func) REPLICATE_7(fld, bool, var, func, { field = boolean(stoi(it)); }, , )
+#define REPLICATE_int(fld, var, func) REPLICATE_7(fld, int, var, func, { field = stoi(it); }, , )
+
+#if defined(SVQC)
+ #define REPLICATE_7(fld, type, var, func, create, destroy, after) \
+ void ReplicateVars(entity this, string thisname, int i) { \
+ type field = this.fld; \
+ if (i < 0) { destroy } \
+ else { \
+ string it = func(argv(i + 1)); \
+ bool current = thisname == var; \
+ if (i > 0) { \
+ if (current) { create } \
+ } else { \
+ stuffcmd(this, "cl_cmd sendcvar " var "\n"); \
+ } \
+ if (current) { after } \
+ } \
+ this.fld = field; \
+ }
+#elif defined(CSQC)
+ // TODO
+ #define REPLICATE_7(fld, type, var, func, create, destroy, after)
+#endif
+
+#endif
+#endif
--- /dev/null
+#ifndef SORT_H
+#define SORT_H
+
+/** is only ever called for i1 < i2 */
+typedef void(float i1, float i2, entity pass) swapfunc_t;
+/** <0 for <, ==0 for ==, >0 for > (like strcmp) */
+typedef float(float i1, float i2, entity pass) comparefunc_t;
+
+void heapsort(float n, swapfunc_t swap, comparefunc_t cmp, entity pass)
+{
+ int root, child;
+
+ // heapify
+ int start = floor((n - 2) / 2);
+ while (start >= 0) {
+ // siftdown(start, n - 1);
+ root = start;
+ while (root * 2 + 1 <= n - 1) {
+ child = root * 2 + 1;
+ if (child < n - 1 && cmp(child, child + 1, pass) < 0) {
+ child += 1;
+ }
+ if (cmp(root, child, pass) < 0) {
+ swap(root, child, pass);
+ root = child;
+ } else {
+ break;
+ }
+ }
+ // end of siftdown
+ --start;
+ }
+
+ // extract
+ int end = n - 1;
+ while (end > 0) {
+ swap(0, end, pass);
+ end -= 1;
+ // siftdown(0, end);
+ root = 0;
+ while (root * 2 + 1 <= end) {
+ child = root * 2 + 1;
+ if (child < end && cmp(child, child+1, pass) < 0) {
+ child += 1;
+ }
+ if (cmp(root, child, pass) < 0) {
+ swap(root, child, pass);
+ root = child;
+ } else {
+ break;
+ }
+ }
+ // end of siftdown
+ }
+}
+
+void shuffle(float n, swapfunc_t swap, entity pass)
+{
+ for (int i = 1; i < n; ++i) {
+ // swap i-th item at a random position from 0 to i
+ // proof for even distribution:
+ // n = 1: obvious
+ // n -> n+1:
+ // item n+1 gets at any position with chance 1/(n+1)
+ // all others will get their 1/n chance reduced by factor n/(n+1)
+ // to be on place n+1, their chance will be 1/(n+1)
+ // 1/n * n/(n+1) = 1/(n+1)
+ // q.e.d.
+ int j = floor(random() * (i + 1));
+ if (j != i)
+ swap(j, i, pass);
+ }
+}
+
+#endif
--- /dev/null
+#ifndef SPAWNFUNC_H
+#define SPAWNFUNC_H
+
+/** If this global exists, only functions with spawnfunc_ name prefix qualify as spawn functions */
+noref bool require_spawnfunc_prefix;
+.bool spawnfunc_checked;
+
+// Optional type checking; increases compile time too much to be enabled by default
+#if 0
+bool entityfieldassignablefromeditor(int i) {
+ switch (entityfieldtype(i)) {
+ case FIELD_STRING:
+ case FIELD_FLOAT:
+ case FIELD_VECTOR:
+ return true;
+ }
+ return false;
+}
+
+#define _spawnfunc_checktypes(fld) if (fieldname == #fld) \
+ if (!entityfieldassignablefromeditor(i)) LOG_FATALF("Entity field '%s' cannot be whitelisted\n", fieldname);
+#else
+#define _spawnfunc_checktypes(fld)
+#endif
+#define _spawnfunc_check(fld) if (fieldname == #fld) \
+ continue;
+
+#define spawnfunc_1(id, whitelist) spawnfunc_2(id, whitelist)
+#define spawnfunc_2(id, whitelist) void spawnfunc_##id(entity this) { \
+ this = self; \
+ if (!this.spawnfunc_checked) { \
+ for (int i = 0, n = numentityfields(); i < n; ++i) { \
+ string value = getentityfieldstring(i, this); \
+ string fieldname = entityfieldname(i); \
+ whitelist(_spawnfunc_checktypes) \
+ if (value == "") continue; \
+ if (fieldname == "") continue; \
+ FIELDS_COMMON(_spawnfunc_check) \
+ whitelist(_spawnfunc_check) \
+ LOG_WARNINGF(_("Entity field %s.%s (%s) is not whitelisted. If you believe this is an error, please file an issue.\n"), #id, fieldname, value); \
+ } \
+ this.spawnfunc_checked = true; \
+ } \
+} \
+[[accumulate]] void spawnfunc_##id(entity this)
+
+#define FIELD_SCALAR(fld, n) \
+ fld(n)
+#define FIELD_VEC(fld, n) \
+ fld(n) \
+ fld(n##_x) \
+ fld(n##_y) \
+ fld(n##_z)
+
+#define FIELDS_NONE(fld)
+#define FIELDS_ALL(fld) if (false)
+
+#define FIELDS_COMMON(fld) \
+ FIELD_SCALAR(fld, classname) \
+ FIELD_SCALAR(fld, spawnfunc_checked) \
+ /**/
+
+#define FIELDS_UNION(fld) \
+ FIELD_SCALAR(fld, Version) \
+ FIELD_SCALAR(fld, ammo_cells) \
+ FIELD_SCALAR(fld, ammo_nails) \
+ FIELD_SCALAR(fld, ammo_rockets) \
+ FIELD_SCALAR(fld, armorvalue) \
+ FIELD_SCALAR(fld, atten) \
+ FIELD_SCALAR(fld, bgmscriptdecay) \
+ FIELD_SCALAR(fld, bgmscriptsustain) \
+ FIELD_SCALAR(fld, bgmscript) \
+ FIELD_SCALAR(fld, button0) \
+ FIELD_SCALAR(fld, cnt) \
+ FIELD_SCALAR(fld, colormap) \
+ FIELD_SCALAR(fld, count) \
+ FIELD_SCALAR(fld, curvetarget) \
+ FIELD_SCALAR(fld, cvarfilter) \
+ FIELD_SCALAR(fld, debrisdamageforcescale) \
+ FIELD_SCALAR(fld, debrisfadetime) \
+ FIELD_SCALAR(fld, debristimejitter) \
+ FIELD_SCALAR(fld, debristime) \
+ FIELD_SCALAR(fld, debris) \
+ FIELD_SCALAR(fld, delay) \
+ FIELD_SCALAR(fld, dmgtime) \
+ FIELD_SCALAR(fld, dmg) \
+ FIELD_SCALAR(fld, dmg_edge) \
+ FIELD_SCALAR(fld, dmg_force) \
+ FIELD_SCALAR(fld, dmg_radius) \
+ FIELD_SCALAR(fld, effects) \
+ FIELD_SCALAR(fld, flags) \
+ FIELD_SCALAR(fld, fog) \
+ FIELD_SCALAR(fld, frags) \
+ FIELD_SCALAR(fld, frame) \
+ FIELD_SCALAR(fld, gametypefilter) \
+ FIELD_SCALAR(fld, geomtype) \
+ FIELD_SCALAR(fld, gravity) \
+ FIELD_SCALAR(fld, health) \
+ FIELD_SCALAR(fld, height) \
+ FIELD_SCALAR(fld, impulse) \
+ FIELD_SCALAR(fld, killtarget) \
+ FIELD_SCALAR(fld, lerpfrac) \
+ FIELD_SCALAR(fld, light_lev) \
+ FIELD_SCALAR(fld, lip) \
+ FIELD_SCALAR(fld, loddistance1) \
+ FIELD_SCALAR(fld, lodmodel1) \
+ FIELD_SCALAR(fld, ltime) \
+ FIELD_SCALAR(fld, mdl) \
+ FIELD_SCALAR(fld, message2) \
+ FIELD_SCALAR(fld, message) \
+ FIELD_SCALAR(fld, modelindex) \
+ FIELD_SCALAR(fld, modelscale) \
+ FIELD_SCALAR(fld, model) \
+ FIELD_SCALAR(fld, monster_moveflags) \
+ FIELD_SCALAR(fld, movetype) \
+ FIELD_SCALAR(fld, netname) \
+ FIELD_SCALAR(fld, nextthink) \
+ FIELD_SCALAR(fld, noalign) \
+ FIELD_SCALAR(fld, noise1) \
+ FIELD_SCALAR(fld, noise2) \
+ FIELD_SCALAR(fld, noise) \
+ FIELD_SCALAR(fld, phase) \
+ FIELD_SCALAR(fld, platmovetype) \
+ FIELD_SCALAR(fld, race_place) \
+ FIELD_SCALAR(fld, radius) \
+ FIELD_SCALAR(fld, respawntimejitter) \
+ FIELD_SCALAR(fld, respawntime) \
+ FIELD_SCALAR(fld, restriction) \
+ FIELD_SCALAR(fld, scale) \
+ FIELD_SCALAR(fld, skin) \
+ FIELD_SCALAR(fld, solid) \
+ FIELD_SCALAR(fld, sound1) \
+ FIELD_SCALAR(fld, sounds) \
+ FIELD_SCALAR(fld, spawnflags) \
+ FIELD_SCALAR(fld, speed) \
+ FIELD_SCALAR(fld, strength) \
+ FIELD_SCALAR(fld, target2) \
+ FIELD_SCALAR(fld, target3) \
+ FIELD_SCALAR(fld, target4) \
+ FIELD_SCALAR(fld, targetname) \
+ FIELD_SCALAR(fld, target) \
+ FIELD_SCALAR(fld, target_random) \
+ FIELD_SCALAR(fld, target_range) \
+ FIELD_SCALAR(fld, team) \
+ FIELD_SCALAR(fld, turret_scale_health) \
+ FIELD_SCALAR(fld, turret_scale_range) \
+ FIELD_SCALAR(fld, turret_scale_respawn) \
+ FIELD_SCALAR(fld, volume) \
+ FIELD_SCALAR(fld, wait) \
+ FIELD_SCALAR(fld, warpzone_fadeend) \
+ FIELD_SCALAR(fld, warpzone_fadestart) \
+ FIELD_SCALAR(fld, weapon) \
+ FIELD_VEC(fld, absmax) \
+ FIELD_VEC(fld, absmin) \
+ FIELD_VEC(fld, angles) \
+ FIELD_VEC(fld, avelocity) \
+ FIELD_VEC(fld, maxs) \
+ FIELD_VEC(fld, maxs) \
+ FIELD_VEC(fld, mins) \
+ FIELD_VEC(fld, modelscale_vec) \
+ FIELD_VEC(fld, origin) \
+ FIELD_VEC(fld, velocity) \
+ /**/
+
+#define spawnfunc(...) EVAL(OVERLOAD(spawnfunc, __VA_ARGS__, FIELDS_UNION))
+
+#endif
--- /dev/null
+#ifndef STATIC_H
+#define STATIC_H
+
+void __static_init_early() { }
+void __static_init() { CALL_ACCUMULATED_FUNCTION(__static_init_early); }
+#define static_init() CALL_ACCUMULATED_FUNCTION(__static_init)
+#define REGISTER_REGISTRY(func) ACCUMULATE_FUNCTION(__static_init_early, func)
+
+#define _STATIC_INIT(where, func) \
+ void _static_##func(); \
+ ACCUMULATE_FUNCTION(where, _static_##func) \
+ void _static_##func()
+
+#define STATIC_INIT(func) _STATIC_INIT(__static_init_early, func##_early)
+#define STATIC_INIT_LATE(func) _STATIC_INIT(__static_init, func)
+
+#endif
--- /dev/null
+#ifndef STRING_H
+#define STRING_H
+
+#ifndef SVQC
+float stringwidth_colors(string s, vector theSize)
+{
+ return stringwidth(s, true, theSize);
+}
+
+float stringwidth_nocolors(string s, vector theSize)
+{
+ return stringwidth(s, false, theSize);
+}
+#endif
+
+// Timer (#5)
+//
+// TODO: macro
+string seconds_tostring(float sec)
+{
+ float minutes = floor(sec / 60);
+ sec -= minutes * 60;
+ return sprintf("%d:%02d", minutes, sec);
+}
+
+int ColorTranslateMode;
+
+string ColorTranslateRGB(string s)
+{
+ return (ColorTranslateMode & 1) ? strdecolorize(s) : s;
+}
+
+// color code replace, place inside of sprintf and parse the string... defaults described as constants
+// foreground/normal colors
+string autocvar_hud_colorset_foreground_1 = "2"; // F1 - Green // primary priority (important names, etc)
+string autocvar_hud_colorset_foreground_2 = "3"; // F2 - Yellow // secondary priority (items, locations, numbers, etc)
+string autocvar_hud_colorset_foreground_3 = "4"; // F3 - Blue // tertiary priority or relatively inconsequential text
+string autocvar_hud_colorset_foreground_4 = "1"; // F4 - Red // notice/attention grabbing texting
+// "kill" colors
+string autocvar_hud_colorset_kill_1 = "1"; // K1 - Red // "bad" or "dangerous" text (death messages against you, kill notifications, etc)
+string autocvar_hud_colorset_kill_2 = "3"; // K2 - Yellow // similar to above, but less important... OR, a highlight out of above message type
+string autocvar_hud_colorset_kill_3 = "4"; // K3 - Blue // "good" or "beneficial" text (you fragging someone, etc)
+// background color
+string autocvar_hud_colorset_background = "7"; // BG - White // neutral/unimportant text
+
+/** color code replace, place inside of sprintf and parse the string */
+string CCR(string input)
+{
+ // See the autocvar declarations in util.qh for default values
+
+ // foreground/normal colors
+ input = strreplace("^F1", strcat("^", autocvar_hud_colorset_foreground_1), input);
+ input = strreplace("^F2", strcat("^", autocvar_hud_colorset_foreground_2), input);
+ input = strreplace("^F3", strcat("^", autocvar_hud_colorset_foreground_3), input);
+ input = strreplace("^F4", strcat("^", autocvar_hud_colorset_foreground_4), input);
+
+ // "kill" colors
+ input = strreplace("^K1", strcat("^", autocvar_hud_colorset_kill_1), input);
+ input = strreplace("^K2", strcat("^", autocvar_hud_colorset_kill_2), input);
+ input = strreplace("^K3", strcat("^", autocvar_hud_colorset_kill_3), input);
+
+ // background colors
+ input = strreplace("^BG", strcat("^", autocvar_hud_colorset_background), input);
+ input = strreplace("^N", "^7", input); // "none"-- reset to white...
+ return input;
+}
+
+bool startsWith(string haystack, string needle)
+{
+ return substring(haystack, 0, strlen(needle)) == needle;
+}
+
+bool startsWithNocase(string haystack, string needle)
+{
+ return strcasecmp(substring(haystack, 0, strlen(needle)), needle) == 0;
+}
+
+/** unzone the string, and return it as tempstring. Safe to be called on string_null */
+string fstrunzone(string s)
+{
+ if (!s) return s;
+ string sc = strcat(s, "");
+ strunzone(s);
+ return sc;
+}
+
+string car(string s)
+{
+ int o = strstrofs(s, " ", 0);
+ if (o < 0) return s;
+ return substring(s, 0, o);
+}
+
+string cdr(string s)
+{
+ int o = strstrofs(s, " ", 0);
+ if (o < 0) return string_null;
+ return substring(s, o + 1, strlen(s) - (o + 1));
+}
+
+string substring_range(string s, float b, float e)
+{
+ return substring(s, b, e - b);
+}
+
+string swapwords(string str, float i, float j)
+{
+ float n;
+ string s1, s2, s3, s4, s5;
+ float si, ei, sj, ej, s0, en;
+ n = tokenizebyseparator(str, " "); // must match g_maplist processing in ShuffleMaplist and "shuffle"
+ si = argv_start_index(i);
+ sj = argv_start_index(j);
+ ei = argv_end_index(i);
+ ej = argv_end_index(j);
+ s0 = argv_start_index(0);
+ en = argv_end_index(n-1);
+ s1 = substring_range(str, s0, si);
+ s2 = substring_range(str, si, ei);
+ s3 = substring_range(str, ei, sj);
+ s4 = substring_range(str, sj, ej);
+ s5 = substring_range(str, ej, en);
+ return strcat(s1, s4, s3, s2, s5);
+}
+
+string _shufflewords_str;
+void _shufflewords_swapfunc(float i, float j, entity pass)
+{
+ _shufflewords_str = swapwords(_shufflewords_str, i, j);
+}
+string shufflewords(string str)
+{
+ _shufflewords_str = str;
+ int n = tokenizebyseparator(str, " ");
+ shuffle(n, _shufflewords_swapfunc, NULL);
+ str = _shufflewords_str;
+ _shufflewords_str = string_null;
+ return str;
+}
+
+string unescape(string in)
+{
+ in = strzone(in); // but it doesn't seem to be necessary in my tests at least
+
+ int len = strlen(in);
+ string str = "";
+ for (int i = 0; i < len; ++i) {
+ string s = substring(in, i, 1);
+ if (s == "\\") {
+ s = substring(in, i + 1, 1);
+ if (s == "n")
+ str = strcat(str, "\n");
+ else if (s == "\\")
+ str = strcat(str, "\\");
+ else
+ str = strcat(str, substring(in, i, 2));
+ ++i;
+ continue;
+ }
+ str = strcat(str, s);
+ }
+ strunzone(in);
+ return str;
+}
+
+string strwords(string s, int w)
+{
+ int endpos = 0;
+ for (; w && endpos >= 0; --w) endpos = strstrofs(s, " ", endpos + 1);
+ if (endpos < 0) return s;
+ return substring(s, 0, endpos);
+}
+
+bool strhasword(string s, string w)
+{
+ return strstrofs(strcat(" ", s, " "), strcat(" ", w, " "), 0) >= 0;
+}
+
+int u8_strsize(string s)
+{
+ int l = 0;
+ for (int i = 0, c; (c = str2chr(s, i)) > 0; ++i, ++l)
+ {
+ l += (c >= 0x80);
+ l += (c >= 0x800);
+ l += (c >= 0x10000);
+ }
+ return l;
+}
+
+#endif
--- /dev/null
+#ifndef STRUCT_H
+#define STRUCT_H
+
+#ifndef QCC_SUPPORT_STRUCT
+ #define _STRUCT_DECLARE(x, id, type, END) noref type x ##_## id ;
+ #define STRUCT_DECLARE(id, s) s(_STRUCT_DECLARE, id)
+
+ #define _STRUCT_PARAM_(x, id, type) type x ##_## id ,
+ #define _STRUCT_PARAM_END(x, id, type) type x ##_## id
+ #define _STRUCT_PARAM(x, id, type, isend) _STRUCT_PARAM_##isend(x, id, type)
+ #define STRUCT_PARAM(id, s) s(_STRUCT_PARAM, id)
+
+ #define _STRUCT_PASS_(x, id, type) x ##_## id ,
+ #define _STRUCT_PASS_END(x, id, type) x ##_## id
+ #define _STRUCT_PASS(x, id, type, END) _STRUCT_PASS_##END(x, id, type)
+ #define STRUCT_PASS(id, s) s(_STRUCT_PASS, id)
+
+ #define _STRUCT_STORE_DST(_, it) it
+ #define _STRUCT_STORE_SRC(it, _) it
+ #define _CONCAT3_(a, b, c) a ## b ## c
+ #define _CONCAT3(a, b, c) _CONCAT3_(a, b, c)
+ #define _STRUCT_STORE(x, id, type, END) _CONCAT3(_STRUCT_STORE_DST x, _, id) = _CONCAT3(_STRUCT_STORE_SRC x, _, id);
+ #define STRUCT_STORE(from, to, s) s(_STRUCT_STORE, (from, to))
+
+ #define STRUCT(id, ...)
+#else
+ #define STRUCT_DECLARE(id, type) type id;
+ #define STRUCT_PARAM(id, type) type id
+ #define STRUCT_PASS(id, type) id
+ #define STRUCT_STORE(from, to, s) to = from
+ #define _STRUCT_MEMBER(my, id, type, END) type id;
+ #define STRUCT(id, s) struct STRUCT_##id { s(_STRUCT_MEMBER, ) };
+#endif
+
+#endif
--- /dev/null
+#ifndef VECTOR_H
+#define VECTOR_H
+
+const vector eX = '1 0 0';
+const vector eY = '0 1 0';
+const vector eZ = '0 0 1';
+
+vector randompos(vector m1, vector m2)
+{
+ vector v;
+ m2 = m2 - m1;
+ v_x = m2_x * random() + m1_x;
+ v_y = m2_y * random() + m1_y;
+ v_z = m2_z * random() + m1_z;
+ return v;
+}
+
+float vlen2d(vector v)
+{
+ return sqrt(v.x * v.x + v.y * v.y);
+}
+
+float vlen_maxnorm2d(vector v)
+{
+ return max(v.x, v.y, -v.x, -v.y);
+}
+
+float vlen_minnorm2d(vector v)
+{
+ return min(max(v.x, -v.x), max(v.y, -v.y));
+}
+
+float dist_point_line(vector p, vector l0, vector ldir)
+{
+ ldir = normalize(ldir);
+
+ // remove the component in line direction
+ p = p - (p * ldir) * ldir;
+
+ // vlen of the remaining vector
+ return vlen(p);
+}
+
+/** requires that m2>m1 in all coordinates, and that m4>m3 */
+float boxesoverlap(vector m1, vector m2, vector m3, vector m4) {return m2_x >= m3_x && m1_x <= m4_x && m2_y >= m3_y && m1_y <= m4_y && m2_z >= m3_z && m1_z <= m4_z;}
+
+/** requires the same as boxesoverlap, but is a stronger condition */
+float boxinsidebox(vector smins, vector smaxs, vector bmins, vector bmaxs) {return smins.x >= bmins.x && smaxs.x <= bmaxs.x && smins.y >= bmins.y && smaxs.y <= bmaxs.y && smins.z >= bmins.z && smaxs.z <= bmaxs.z;}
+
+
+vector vec2(vector v)
+{
+ v.z = 0;
+ return v;
+}
+
+vector vec3(float x, float y, float z)
+{
+ vector v; v.x = x; v.y = y; v.z = z;
+ return v;
+}
+
+#ifndef MENUQC
+vector get_corner_position(entity box, int corner)
+{
+ switch (corner) {
+ case 1: return vec3(box.absmin.x, box.absmin.y, box.absmin.z);
+ case 2: return vec3(box.absmax.x, box.absmin.y, box.absmin.z);
+ case 3: return vec3(box.absmin.x, box.absmax.y, box.absmin.z);
+ case 4: return vec3(box.absmin.x, box.absmin.y, box.absmax.z);
+ case 5: return vec3(box.absmax.x, box.absmax.y, box.absmin.z);
+ case 6: return vec3(box.absmin.x, box.absmax.y, box.absmax.z);
+ case 7: return vec3(box.absmax.x, box.absmin.y, box.absmax.z);
+ case 8: return vec3(box.absmax.x, box.absmax.y, box.absmax.z);
+ default: return '0 0 0';
+ }
+}
+
+vector NearestPointOnBox(entity box, vector org)
+{
+ vector m1 = box.mins + box.origin;
+ vector m2 = box.maxs + box.origin;
+
+ vector ret;
+ ret.x = bound(m1.x, org.x, m2.x);
+ ret.y = bound(m1.y, org.y, m2.y);
+ ret.z = bound(m1.z, org.z, m2.z);
+ return ret;
+}
+#endif
+
+#endif
void setterDummy(entity, float);
CLASS(Animation, Object)
METHOD(Animation, configureAnimation, void(entity, entity, void(entity, float), float, float, float, float));
+ METHOD(Animation, update, void(entity, float, float, float));
METHOD(Animation, setTimeStartEnd, void(entity, float, float));
METHOD(Animation, setTimeStartDuration, void(entity, float, float));
METHOD(Animation, setValueStartEnd, void(entity, float, float));
me.setValueStartEnd(me, animStartValue, animEndValue);
}
+void Animation_update(entity me, float animDuration, float animStartValue, float animEndValue)
+{
+ me.setTimeStartDuration(me, time, animDuration);
+ me.setValueStartEnd(me, animStartValue, animEndValue);
+}
+
void Animation_setTimeStartEnd(entity me, float s, float e)
{
me.startTime = s;
#ifndef GAMESETTINGS_H
#define GAMESETTINGS_H
-void RegisterSettings();
-const int MAX_SETTINGS = 24;
-Lazy SETTINGS[MAX_SETTINGS], SETTINGS_first, SETTINGS_last;
-int SETTINGS_COUNT;
+REGISTRY(Settings, BIT(3))
+REGISTER_REGISTRY(RegisterSettings)
#define REGISTER_SETTINGS(id, impl) \
LAZY_NEW(id, impl) \
- REGISTER(RegisterSettings, MENU, SETTINGS, SETTINGS_COUNT, id, m_id, NEW(Lazy, LAZY(id)))
-REGISTER_REGISTRY(RegisterSettings)
+ REGISTER(RegisterSettings, MENU, Settings, id, m_id, NEW(Lazy, LAZY(id)))
#endif
#endif
if(me.srcMulti)
me.keepspaceLeft = 0;
else
- me.keepspaceLeft = min(0.8, absSize.y / absSize.x);
+ me.keepspaceLeft = min(0.8, absSize.x == 0 ? 0 : (absSize.y / absSize.x));
SUPER(Button).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
}
void Button_configureButton(entity me, string txt, float sz, string gfx)
SUPER(Label).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
// absSize_y is height of label
- me.realFontSize_y = me.fontSize / absSize.y;
- me.realFontSize_x = me.fontSize / absSize.x;
+ me.realFontSize_y = absSize.y == 0 ? 0 : (me.fontSize / absSize.y);
+ me.realFontSize_x = absSize.x == 0 ? 0 : (me.fontSize / absSize.x);
if(me.marginLeft)
me.keepspaceLeft = me.marginLeft * me.realFontSize.x;
if(me.marginRight)
}
}
}
+AUTOCVAR(menu_scroll_averaging_time, float, 0.16, "smooth scroll averaging time");
+// scroll faster while dragging the scrollbar
+AUTOCVAR(menu_scroll_averaging_time_pressed, float, 0.06, "smooth scroll averaging time when dragging the scrollbar");
void ListBox_draw(entity me)
{
float i;
}
if(me.scrollPos != me.scrollPosTarget)
{
- float averaging_time = 0.16;
- if(me.pressed == 1)
- averaging_time = 0.06; // scroll faster while dragging the scrollbar
+ float averaging_time = (me.pressed == 1)
+ ? autocvar_menu_scroll_averaging_time_pressed
+ : autocvar_menu_scroll_averaging_time;
// this formula works with whatever framerate
- float f = exp(-frametime / averaging_time);
+ float f = averaging_time ? exp(-frametime / averaging_time) : 0;
me.scrollPos = me.scrollPos * f + me.scrollPosTarget * (1 - f);
if(fabs(me.scrollPos - me.scrollPosTarget) < 0.001)
me.scrollPos = me.scrollPosTarget;
METHOD(Slider, mouseRelease, float(entity, vector));
METHOD(Slider, valueToText, string(entity, float));
METHOD(Slider, toString, string(entity));
+ METHOD(Slider, setValue_allowAnim, void(entity, float, bool));
+ METHOD(Slider, setValue_noAnim, void(entity, float));
METHOD(Slider, setValue, void(entity, float));
METHOD(Slider, setSliderValue, void(entity, float));
METHOD(Slider, showNotify, void(entity));
ATTRIB(Slider, value, float, 0)
ATTRIB(Slider, animated, float, 1)
ATTRIB(Slider, sliderValue, float, 0)
+ ATTRIB(Slider, sliderAnim, entity, world)
ATTRIB(Slider, valueMin, float, 0)
ATTRIB(Slider, valueMax, float, 0)
ATTRIB(Slider, valueStep, float, 0)
#endif
#ifdef IMPLEMENTATION
-void Slider_setValue(entity me, float val)
+void Slider_setValue_allowAnim(entity me, float val, bool allowAnim)
{
- if (me.animated) {
- anim.removeObjAnim(anim, me);
- makeHostedEasing(me, Slider_setSliderValue, easingQuadInOut, 1, me.sliderValue, val);
+ if(allowAnim && me.animated) {
+ float t = 0.5;
+ if(!me.sliderAnim)
+ me.sliderAnim = makeHostedEasing(me, Slider_setSliderValue, easingQuadOut, t, me.sliderValue, val);
+ else
+ me.sliderAnim.update(me.sliderAnim, t, me.sliderValue, val);
} else {
me.setSliderValue(me, val);
}
me.value = val;
}
+void Slider_setValue_noAnim(entity me, float val)
+{
+ Slider_setValue_allowAnim(me, val, false);
+}
+void Slider_setValue(entity me, float val)
+{
+ Slider_setValue_allowAnim(me, val, true);
+}
void Slider_setSliderValue(entity me, float val)
{
me.sliderValue = val;
void Slider_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
{
SUPER(Slider).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
- me.controlWidth = absSize.y / absSize.x;
+ me.controlWidth = absSize.x == 0 ? 0 : (absSize.y / absSize.x);
}
string Slider_valueToText(entity me, float val)
{
float Slider_mouseDrag(entity me, vector pos)
{
float hit;
- float v, animed;
+ float v;
if(me.disabled)
return 0;
- anim.removeObjAnim(anim, me);
- animed = me.animated;
- me.animated = false;
-
if(me.pressed)
{
hit = 1;
if(pos.y >= 1 + me.tolerance.y) hit = 0;
if(hit)
{
+ // handle dragging
+ me.pressed = 2;
+
v = median(0, (pos.x - me.pressOffset - 0.5 * me.controlWidth) / (1 - me.textSpace - me.controlWidth), 1) * (me.valueMax - me.valueMin) + me.valueMin;
if(me.valueStep)
v = floor(0.5 + v / me.valueStep) * me.valueStep;
- me.setValue(me, v);
+ me.setValue_noAnim(me, v);
}
else
me.setValue(me, me.previousValue);
}
- me.animated = animed;
-
return 1;
}
float Slider_mousePress(entity me, vector pos)
else
draw_Picture(eX * controlLeft, strcat(me.src, "_n"), eX * me.controlWidth + eY, me.color, 1);
}
+
+ if(me.sliderAnim)
+ if(me.sliderAnim.isFinished(me.sliderAnim))
+ {
+ anim.removeObjAnim(anim, me);
+ me.sliderAnim = world;
+ }
+
me.setText(me, me.valueToText(me, me.value));
draw_alpha = save;
SUPER(Slider).draw(me);
CLASS(TextSlider, Slider)
METHOD(TextSlider, valueToText, string(entity, float));
METHOD(TextSlider, valueToIdentifier, string(entity, float));
+ METHOD(TextSlider, setValueFromIdentifier_allowAnim, void(entity, string, bool));
+ METHOD(TextSlider, setValueFromIdentifier_noAnim, void(entity, string));
METHOD(TextSlider, setValueFromIdentifier, void(entity, string));
METHOD(TextSlider, getIdentifier, string(entity));
METHOD(TextSlider, clearValues, void(entity));
return _("Custom");
return me.(valueStrings[val]);
}
-void TextSlider_setValueFromIdentifier(entity me, string id)
+void TextSlider_setValueFromIdentifier_allowAnim(entity me, string id, bool allowAnim)
{
int i;
for(i = 0; i < me.nValues; ++i)
if(me.valueToIdentifier(me, i) == id)
{
- SUPER(TextSlider).setValue( me, i );
+ SUPER(TextSlider).setValue_allowAnim(me, i, allowAnim);
return;
}
- SUPER(TextSlider).setValue( me, -1 );
+ SUPER(TextSlider).setValue_allowAnim(me, -1, allowAnim);
+}
+void TextSlider_setValueFromIdentifier_noAnim(entity me, string id)
+{
+ TextSlider_setValueFromIdentifier_allowAnim(me, id, false);
+}
+void TextSlider_setValueFromIdentifier(entity me, string id)
+{
+ TextSlider_setValueFromIdentifier_allowAnim(me, id, true);
}
string TextSlider_getIdentifier(entity me)
{
void TextSlider_configureTextSliderValues(entity me, string theDefault)
{
me.configureSliderValues(me, 0, 0, me.nValues - 1, 1, 1, 1);
- me.setValueFromIdentifier(me, theDefault);
+ me.setValueFromIdentifier_noAnim(me, theDefault);
}
#endif
--- /dev/null
+#include "../common/util-pre.qh"
+#include "../dpdefs/menudefs.qh"
+#include "../dpdefs/keycodes.qh"
+#include "../common/util-post.qh"
+
+#include "../lib/_all.inc"
+
+#include "oo/classes.qc"
+
+#include "draw.qc"
+#include "menu.qc"
+
+#include "command/all.qc"
+
+#include "xonotic/util.qc"
+
+#include "../common/campaign_file.qc"
+#include "../common/campaign_setup.qc"
+#include "../common/mapinfo.qc"
+#include "../common/playerstats.qc"
+#include "../common/util.qc"
+
+#include "../common/items/all.qc"
+#include "../common/monsters/all.qc"
+#include "../common/mutators/all.qc"
+#include "../common/vehicles/all.qc"
+#include "../common/weapons/all.qc"
+
+#if BUILD_MOD
+#include "../../mod/menu/progs.inc"
+#endif
../../menu.dat
-
-../common/util-pre.qh
-../dpdefs/menudefs.qh
-../dpdefs/keycodes.qh
-../common/util-post.qh
-
-../lib/_all.inc
-
-oo/classes.qc
-
-draw.qc
-menu.qc
-
-command/all.qc
-
-xonotic/util.qc
-
-../common/campaign_file.qc
-../common/campaign_setup.qc
-../common/mapinfo.qc
-../common/playerstats.qc
-../common/util.qc
-
-../common/items/all.qc
-../common/monsters/all.qc
-../common/mutators/all.qc
-../common/vehicles/all.qc
-../common/weapons/all.qc
-
-
-../../mod/menu/progs.inc
+progs.inc
* returns `DataSource_false` if out of bounds
* otherwise returns an entity or `DataSource_true`
*/
- METHOD(DataSource, getEntry, entity(int i, void(string name, string icon) returns)) { return DataSource_false; }
+ METHOD(DataSource, getEntry, entity(entity this, int i, void(string name, string icon) returns)) { return DataSource_false; }
/** return the index of the first match for `find`. optional */
- METHOD(DataSource, indexOf, int(string find)) { return -1; }
+ METHOD(DataSource, indexOf, int(entity this, string find)) { return -1; }
/** reload all entries matching `filter` returning how many matches were found */
- METHOD(DataSource, reload, int(string filter)) { return 0; }
+ METHOD(DataSource, reload, int(entity this, string filter)) { return 0; }
/** cleanup on shutdown. optional */
- METHOD(DataSource, destroy, void(entity)) { }
+ METHOD(DataSource, destroy, void(entity this)) { }
ENDCLASS(DataSource)
+
+
+CLASS(StringSource, DataSource)
+ ATTRIB(StringSource, StringSource_str, string, string_null)
+ ATTRIB(StringSource, StringSource_sep, string, string_null)
+ CONSTRUCTOR(StringSource, string str, string sep)
+ {
+ CONSTRUCT(StringSource);
+ this.StringSource_str = str;
+ this.StringSource_sep = sep;
+ }
+ METHOD(StringSource, getEntry, entity(entity this, int i, void(string name, string icon) returns))
+ {
+ int n = tokenizebyseparator(this.StringSource_str, this.StringSource_sep);
+ if (i < 0 || i >= n) return DataSource_false;
+ string s = argv(i);
+ if (returns) returns(s, string_null);
+ return DataSource_true;
+ }
+ METHOD(StringSource, reload, int(entity this, string filter))
+ {
+ return tokenizebyseparator(this.StringSource_str, this.StringSource_sep);
+ }
+ENDCLASS(StringSource)
+
+CLASS(CvarStringSource, StringSource)
+ ATTRIB(CvarStringSource, CvarStringSource_cvar, string, string_null)
+ CONSTRUCTOR(CvarStringSource, string cv, string sep)
+ {
+ CONSTRUCT(CvarStringSource);
+ this.CvarStringSource_cvar = cv;
+ this.StringSource_sep = sep;
+ }
+ METHOD(CvarStringSource, getEntry, entity(entity this, int i, void(string name, string icon) returns))
+ {
+ string s = this.CvarStringSource_cvar;
+ this.StringSource_str = s ? cvar_string(s) : string_null;
+ return super.getEntry(this, i, returns);
+ }
+ METHOD(CvarStringSource, reload, int(entity this, string filter))
+ {
+ string s = this.CvarStringSource_cvar;
+ this.StringSource_str = s ? cvar_string(s) : string_null;
+ return super.reload(this, filter);
+ }
+ENDCLASS(CvarStringSource)
#endif
me.TD(me, 1, 0.4, e = makeXonoticRadioButton(2, "menu_monsters_edit_spawn", "wyvern", _("Wyvern")));
me.TR(me);
me.TDempty(me, 0.1);
- me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Spawn"), '0 0 0', "cmd mobspawn $menu_monsters_edit_spawn $menu_monsters_edit_movetarget", 0));
- me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Remove"), '0 0 0', "cmd mobkill", 0));
+ me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Spawn"), '0 0 0', "spawnmob $menu_monsters_edit_spawn $menu_monsters_edit_movetarget", 0));
+ me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Remove"), '0 0 0', "killmob", 0));
me.TR(me);
me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Move target:"), '0 0 0', "editmob movetarget $menu_monsters_edit_movetarget", 0));
me.TD(me, 1, 0.5, e = makeXonoticRadioButton(2, "menu_monsters_edit_movetarget", "1", _("Follow")));
return weaponarenastring;
}
+AUTOCVAR(g_grappling_hook, bool, _("let players spawn with the grappling hook which allows them to pull themselves up"));
+
string XonoticMutatorsDialog_toString(entity me)
{
string s;
s = strcat(s, ", ", _("Low gravity"));
if(cvar("g_cloaked"))
s = strcat(s, ", ", _("Cloaked"));
- if(cvar("g_grappling_hook"))
+ if(autocvar_g_grappling_hook)
s = strcat(s, ", ", _("Hook"));
if(cvar("g_midair"))
s = strcat(s, ", ", _("Midair"));
#include "datasource.qc"
CLASS(SettingSource, DataSource)
- METHOD(SettingSource, getEntry, entity(int i, void(string name, string icon) returns))
+ METHOD(SettingSource, getEntry, entity(entity this, int i, void(string name, string icon) returns))
{
- Lazy l = SETTINGS[i];
+ Lazy l = Settings[i];
entity it = l.m_get();
if (returns) returns(it.title, string_null);
return it;
}
- METHOD(SettingSource, getEntryTooltip, entity(int i, void(string theTooltip) returns))
+ METHOD(SettingSource, getEntryTooltip, entity(entity this, int i, void(string theTooltip) returns))
{
- Lazy l = SETTINGS[i];
+ Lazy l = Settings[i];
entity it = l.m_get();
if (returns) returns(it.tooltip);
return it;
}
- METHOD(SettingSource, reload, int(string filter)) { return SETTINGS_COUNT; }
+ METHOD(SettingSource, reload, int(entity this, string filter)) { return Settings_COUNT; }
ENDCLASS(SettingSource)
#include "listbox.qc"
METHOD(XonoticRegisteredSettingsList, drawListBoxItem, void(entity this, int i, vector absSize, bool isSelected, bool isFocused))
{
if (!this.source) return;
- if (!this.source.getEntry(i, XonoticRegisteredSettingsList_getNameIcon_cb)) return;
+ if (!this.source.getEntry(this.source, i, XonoticRegisteredSettingsList_getNameIcon_cb)) return;
string name = XonoticRegisteredSettingsList_cb_name;
if (isSelected) {
draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
clearTooltip(this);
return;
}
- if (!this.source.getEntryTooltip(this.focusedItem, XonoticRegisteredSettingsList_getTooltip_cb))
+ if (!this.source.getEntryTooltip(this, this.focusedItem, XonoticRegisteredSettingsList_getTooltip_cb))
{
clearTooltip(this);
return;
this.nItems = 0;
return;
}
- this.nItems = this.source.reload(this.stringFilter);
+ this.nItems = this.source.reload(this.source, this.stringFilter);
}
METHOD(XonoticRegisteredSettingsList, resizeNotify, void(entity this, vector relOrigin, vector relSize, vector absOrigin, vector absSize))
{
ATTRIB(XonoticGameSettingsTab, intendedWidth, float, 0.9)
ATTRIB(XonoticGameSettingsTab, rows, float, 15.5)
ATTRIB(XonoticGameSettingsTab, columns, float, 6.5)
- ATTRIB(XonoticGameSettingsTab, topicList, entity, NEW(XonoticRegisteredSettingsList, NEW(SettingSource)))
+ ATTRIB(XonoticGameSettingsTab, source, DataSource, NEW(SettingSource))
+ ATTRIB(XonoticGameSettingsTab, topicList, entity, NEW(XonoticRegisteredSettingsList, this.source))
ATTRIB(XonoticGameSettingsTab, currentPanel, entity, NEW(XonoticTab))
ATTRIB(XonoticGameSettingsTab, currentItem, entity, NULL)
METHOD(XonoticGameSettingsTab, topicChangeNotify, void(entity, entity this))
{
entity c = this.currentPanel;
entity removing = this.currentItem;
- entity adding = this.topicList.source.getEntry(this.topicList.selectedItem, func_null);
+ DataSource data = this.topicList.source;
+ entity adding = data.getEntry(data, this.topicList.selectedItem, func_null);
if (removing == adding) return;
if (removing) {
this.currentItem = NULL;
KEYBIND_DEF("" , _("User defined"));
for(i = 1; i <= 32; ++i)
- KEYBIND_DEF(strcat("+userbind ", itos(i)), strcat("$$", _("userbind"), itos(i)));
+ KEYBIND_DEF(strcat("+userbind ", itos(i)), strcat("$userbind", itos(i)));
#undef KEYBIND_DEF
}
void XonoticRadioButton_configureXonoticRadioButton(entity me, float theGroup, string theCvar, string theValue, string theText, string theTooltip)
{
me.cvarName = (theCvar) ? theCvar : string_null;
+ me.cvarValue = theValue;
me.loadCvars(me);
setZonedTooltip(me, theTooltip, theCvar);
me.configureRadioButton(me, theText, me.fontSize, me.image, theGroup, 0);
if (!me.cvarName)
return;
- me.setValue( me, cvar(me.cvarName) );
+ me.setValue_noAnim(me, cvar(me.cvarName));
}
void XonoticSlider_saveCvars(entity me)
{
// snapping
if(v > fromDecibelOfSquare(me.valueMax - 0.5 * me.valueStep, me.valueMin))
- Slider_setValue(me, me.valueMax);
+ Slider_setValue_noAnim(me, me.valueMax);
else
- Slider_setValue(me, me.valueStep * floor(0.5 + toDecibelOfSquare(v, me.valueMin) / me.valueStep) );
+ Slider_setValue_noAnim(me, me.valueStep * floor(0.5 + toDecibelOfSquare(v, me.valueMin) / me.valueStep));
}
void XonoticDecibelsSlider_saveCvars(entity me)
{
}
void XonoticParticlesSlider_loadCvars(entity me)
{
- me.setValueFromIdentifier(me, sprintf("%s %s %s",
+ me.setValueFromIdentifier_noAnim(me, sprintf("%s %s %s",
cvar_string("cl_particles_quality"),
cvar_string("r_drawparticles_drawdistance"),
cvar_string("cl_damageeffect")
}
void XonoticResolutionSlider_loadCvars(entity me)
{
- me.setValueFromIdentifier(me, strcat(cvar_string("_menu_vid_width"), " ", cvar_string("_menu_vid_height"), " ", cvar_string("_menu_vid_pixelheight")));
+ me.setValueFromIdentifier_noAnim(me, strcat(cvar_string("_menu_vid_width"), " ", cvar_string("_menu_vid_height"), " ", cvar_string("_menu_vid_pixelheight")));
}
void XonoticResolutionSlider_saveCvars(entity me)
{
}
void XonoticScoreboardFadeTimeSlider_loadCvars(entity me)
{
- me.setValueFromIdentifier(me, sprintf("%s %s",
+ me.setValueFromIdentifier_noAnim(me, sprintf("%s %s",
cvar_string("scoreboard_fadeinspeed"),
cvar_string("scoreboard_fadeoutspeed")
));
float i;
for(i = 1; i < n; ++i)
s = strcat(s, " ", cvar_string(argv(i)));
- me.setValueFromIdentifier(me, s);
+ me.setValueFromIdentifier_noAnim(me, s);
if(me.value < 0 && n > 1)
{
// if it failed: check if all cvars have the same value
if(cvar_string(argv(i)) != cvar_string(argv(i-1)))
break;
if(i >= n)
- me.setValueFromIdentifier(me, cvar_string(argv(0)));
+ me.setValueFromIdentifier_noAnim(me, cvar_string(argv(0)));
}
}
void XonoticTextSlider_saveCvars(entity me)
GAMETYPE(MAPINFO_TYPE_ASSAULT) \
if (cvar("developer")) GAMETYPE(MAPINFO_TYPE_RACE) \
GAMETYPE(MAPINFO_TYPE_CTS) \
- //GAMETYPE(MAPINFO_TYPE_INVASION) \
- /* nothing */
+ /* GAMETYPE(MAPINFO_TYPE_INVASION) */ \
+ /**/
int GameType_GetID(int cnt)
{
void error(string e) = #10;
float test();
-void spawnfunc_worldspawn()
+spawnfunc(worldspawn)
{
float r;
LOG_TRACE("TESTCASE: START\n");
#include "../dpdefs/progsdefs.qh"
#include "../dpdefs/dpextensions.qh"
+#include "../common/models/all.qh"
+#include "../common/sounds/all.qh"
+
#endif
}
void anticheat_physics()
-{
+{SELFPARAM();
float f;
// div0_evade -> SPECTATORS
}
void anticheat_spectatecopy(entity spectatee)
-{
+{SELFPARAM();
// div0_evade -> SPECTATORS
self.angles = spectatee.anticheat_div0_evade_v_angle;
}
void anticheat_prethink()
-{
+{SELFPARAM();
// div0_evade -> SPECTATORS
self.anticheat_div0_evade_offset = 0;
}
}
void anticheat_report()
-{
+{SELFPARAM();
if(!autocvar_sv_eventlog)
return;
// TODO(divVerent): Use xonstat to acquire good thresholds.
}
float anticheat_getvalue(string id)
-{
+{SELFPARAM();
switch(id) {
case "_time": return servertime - self.anticheat_jointime;
case "speedhack": return MEAN_EVALUATE(anticheat_speedhack);
}
void anticheat_fixangle()
-{
+{SELFPARAM();
self.anticheat_fixangle_endtime = servertime + ANTILAG_LATENCY(self) + 0.2;
}
void anticheat_endframe()
-{
- entity oldself = self;
- FOR_EACH_CLIENT(self)
- if (self.fixangle)
- anticheat_fixangle();
- self = oldself;
+{SELFPARAM();
+ entity e;
+ FOR_EACH_CLIENT(e)
+ if (e.fixangle) {
+ WITH(entity, self, e, anticheat_fixangle());
+ }
anticheat_div0_evade_evasion_delta += frametime * (0.5 + random());
}
void anticheat_init()
-{
+{SELFPARAM();
self.anticheat_speedhack_offset = 0;
self.anticheat_jointime = servertime;
}
bool autocvar_g_full_getstatus_responses;
bool autocvar_g_fullbrightitems;
bool autocvar_g_fullbrightplayers;
-#define autocvar_g_grappling_hook cvar("g_grappling_hook")
-int autocvar_g_grappling_hook_tarzan;
int autocvar_g_balance_grapplehook_pull_frozen;
float autocvar_g_balance_grapplehook_nade_time;
bool autocvar_g_balance_grapplehook_gravity;
float autocvar_g_multijump_maxspeed;
float autocvar_g_multijump_dodging = 1;
string autocvar_g_mutatormsg;
-float autocvar_g_nexball_basketball_bouncefactor;
-float autocvar_g_nexball_basketball_bouncestop;
-float autocvar_g_nexball_basketball_carrier_highspeed;
-bool autocvar_g_nexball_basketball_meter;
-float autocvar_g_nexball_basketball_meter_maxpower;
-float autocvar_g_nexball_basketball_meter_minpower;
-float autocvar_g_nexball_delay_collect;
-float autocvar_g_nexball_delay_goal;
-float autocvar_g_nexball_delay_start;
-float autocvar_g_nexball_football_bouncefactor;
-float autocvar_g_nexball_football_bouncestop;
int autocvar_g_nexball_goalleadlimit;
#define autocvar_g_nexball_goallimit cvar("g_nexball_goallimit")
-bool autocvar_g_nexball_radar_showallplayers;
-bool autocvar_g_nexball_sound_bounce;
-int autocvar_g_nexball_trail_color;
//float autocvar_g_nick_flood_penalty;
int autocvar_g_nick_flood_penalty_red;
int autocvar_g_nick_flood_penalty_yellow;
float autocvar_g_monsters_damageforcescale = 0.8;
float autocvar_g_monsters_target_range;
bool autocvar_g_monsters_target_infront;
+float autocvar_g_monsters_target_infront_range = 0.3;
float autocvar_g_monsters_attack_range;
int autocvar_g_monsters_score_kill;
int autocvar_g_monsters_score_spawned;
float autocvar_g_random_gravity_negative;
float autocvar_g_random_gravity_delay;
bool autocvar_g_nades;
+bool autocvar_g_nades_override_dropweapon = true;
vector autocvar_g_nades_throw_offset;
bool autocvar_g_nades_spawn;
int autocvar_g_nades_spawn_count;
tracetossfaketarget = spawn();
tracetossfaketarget.solid = savesolid;
tracetossfaketarget.movetype = targ.movetype;
- setmodel(tracetossfaketarget, targ.model); // no low precision
+ _setmodel(tracetossfaketarget, targ.model); // no low precision
tracetossfaketarget.model = targ.model;
tracetossfaketarget.modelindex = targ.modelindex;
setsize(tracetossfaketarget, targ.mins, targ.maxs);
}
void lag_update()
-{
+{SELFPARAM();
if (self.lag1_time) if (time > self.lag1_time) {self.lag_func(self.lag1_time, self.lag1_float1, self.lag1_float2, self.lag1_entity1, self.lag1_vec1, self.lag1_vec2, self.lag1_vec3, self.lag1_vec4);self.lag1_time = 0;}
if (self.lag2_time) if (time > self.lag2_time) {self.lag_func(self.lag2_time, self.lag2_float1, self.lag2_float2, self.lag2_entity1, self.lag2_vec1, self.lag2_vec2, self.lag2_vec3, self.lag2_vec4);self.lag2_time = 0;}
if (self.lag3_time) if (time > self.lag3_time) {self.lag_func(self.lag3_time, self.lag3_float1, self.lag3_float2, self.lag3_entity1, self.lag3_vec1, self.lag3_vec2, self.lag3_vec3, self.lag3_vec4);self.lag3_time = 0;}
}
float lag_additem(float t, float f1, float f2, entity e1, vector v1, vector v2, vector v3, vector v4)
-{
+{SELFPARAM();
if (self.lag1_time == 0) {self.lag1_time = t;self.lag1_float1 = f1;self.lag1_float2 = f2;self.lag1_entity1 = e1;self.lag1_vec1 = v1;self.lag1_vec2 = v2;self.lag1_vec3 = v3;self.lag1_vec4 = v4;return true;}
if (self.lag2_time == 0) {self.lag2_time = t;self.lag2_float1 = f1;self.lag2_float2 = f2;self.lag2_entity1 = e1;self.lag2_vec1 = v1;self.lag2_vec2 = v2;self.lag2_vec3 = v3;self.lag2_vec4 = v4;return true;}
if (self.lag3_time == 0) {self.lag3_time = t;self.lag3_float1 = f1;self.lag3_float2 = f2;self.lag3_entity1 = e1;self.lag3_vec1 = v1;self.lag3_vec2 = v2;self.lag3_vec3 = v3;self.lag3_vec4 = v4;return true;}
}
float bot_shouldattack(entity e)
-{
+{SELFPARAM();
if (e.team == self.team)
{
if (e == self)
}
void bot_lagfunc(float t, float f1, float f2, entity e1, vector v1, vector v2, vector v3, vector v4)
-{
+{SELFPARAM();
if(self.flags & FL_INWATER)
{
self.bot_aimtarg = world;
}
float bot_aimdir(vector v, float maxfiredeviation)
-{
+{SELFPARAM();
float dist, delta_t, blend;
vector desiredang, diffang;
}
float bot_aim(float shotspeed, float shotspeedupward, float maxshottime, float applygravity)
-{
+{SELFPARAM();
float f, r, hf, distanceratio;
vector v;
/*
#include "../../warpzonelib/util_server.qh"
entity bot_spawn()
-{
- entity oldself, bot;
- bot = spawnclient();
+{SELFPARAM();
+ entity bot = spawnclient();
if (bot)
{
currentbots = currentbots + 1;
- oldself = self;
- self = bot;
+ setself(bot);
bot_setnameandstuff();
ClientConnect();
PutClientInServer();
- self = oldself;
+ setself(this);
}
return bot;
}
void bot_think()
-{
+{SELFPARAM();
if (self.bot_nextthink > time)
return;
}
void bot_setnameandstuff()
-{
+{SELFPARAM();
string readfile, s;
float file, tokens, prio;
entity p;
tokens = tokenizebyseparator(W_NumberWeaponOrder(autocvar_bot_ai_custom_weapon_priority_far)," ");
int c = 0;
- for(i=0; i < tokens && c < WEP_COUNT; ++i){
+ for(i=0; i < tokens && c < Weapons_COUNT; ++i){
w = stof(argv(i));
if ( w >= WEP_FIRST && w <= WEP_LAST) {
bot_weapons_far[c] = w;
++c;
}
}
- if(c < WEP_COUNT)
+ if(c < Weapons_COUNT)
bot_weapons_far[c] = -1;
// Parse mid distance weapon priorities
tokens = tokenizebyseparator(W_NumberWeaponOrder(autocvar_bot_ai_custom_weapon_priority_mid)," ");
c = 0;
- for(i=0; i < tokens && c < WEP_COUNT; ++i){
+ for(i=0; i < tokens && c < Weapons_COUNT; ++i){
w = stof(argv(i));
if ( w >= WEP_FIRST && w <= WEP_LAST) {
bot_weapons_mid[c] = w;
++c;
}
}
- if(c < WEP_COUNT)
+ if(c < Weapons_COUNT)
bot_weapons_mid[c] = -1;
// Parse close distance weapon priorities
tokens = tokenizebyseparator(W_NumberWeaponOrder(autocvar_bot_ai_custom_weapon_priority_close)," ");
c = 0;
- for(i=0; i < tokens && i < WEP_COUNT; ++i){
+ for(i=0; i < tokens && i < Weapons_COUNT; ++i){
w = stof(argv(i));
if ( w >= WEP_FIRST && w <= WEP_LAST) {
bot_weapons_close[c] = w;
++c;
}
}
- if(c < WEP_COUNT)
+ if(c < Weapons_COUNT)
bot_weapons_close[c] = -1;
bot_custom_weapon = true;
}
void bot_clientdisconnect()
-{
+{SELFPARAM();
if (!IS_BOT_CLIENT(self))
return;
bot_clearqueue(self);
}
void bot_clientconnect()
-{
+{SELFPARAM();
if (!IS_BOT_CLIENT(self))
return;
self.bot_preferredcolors = self.clientcolors;
float bot_distance_far;
float bot_distance_close;
-float bot_weapons_far[WEP_MAXCOUNT];
-float bot_weapons_mid[WEP_MAXCOUNT];
-float bot_weapons_close[WEP_MAXCOUNT];
+float bot_weapons_far[Weapons_MAX];
+float bot_weapons_mid[Weapons_MAX];
+float bot_weapons_close[Weapons_MAX];
entity bot_list;
entity player_list;
#include "../../../warpzonelib/common.qh"
void havocbot_ai()
-{
+{SELFPARAM();
if(self.draggedby)
return;
if(self.weapons)
{
- WEP_ACTION(self.weapon, WR_AIM);
+ Weapon w = get_weaponinfo(self.weapon);
+ w.wr_aim(w);
if (autocvar_bot_nofire || IS_INDEPENDENT_PLAYER(self))
{
self.BUTTON_ATCK = false;
}
void havocbot_keyboard_movement(vector destorg)
-{
+{SELFPARAM();
vector keyboard;
float blend, maxspeed;
float sk;
}
void havocbot_bunnyhop(vector dir)
-{
+{SELFPARAM();
float bunnyhopdistance;
vector deviation;
float maxspeed;
}
void havocbot_movetogoal()
-{
+{SELFPARAM();
vector destorg;
vector diff;
vector dir;
}
void havocbot_chooseenemy()
-{
+{SELFPARAM();
entity head, best, head2;
- float rating, bestrating, i, hf;
+ float rating, bestrating, hf;
vector eye, v;
if (autocvar_bot_nofire || IS_INDEPENDENT_PLAYER(self))
{
self.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
- for(i = 0; ; ++i)
+ bool scan_transparent = false;
+ bool scan_secondary_targets = false;
+ bool have_secondary_targets = false;
+ while(true)
{
- while (head)
+ scan_secondary_targets = false;
+ :scan_targets
+ for( ; head; head = head.chain)
{
+ if(!scan_secondary_targets)
+ {
+ if(head.classname == "misc_breakablemodel")
+ {
+ have_secondary_targets = true;
+ continue;
+ }
+ }
+ else
+ {
+ if(head.classname != "misc_breakablemodel")
+ continue;
+ }
+
v = (head.absmin + head.absmax) * 0.5;
rating = vlen(v - eye);
if (rating<autocvar_bot_ai_enemydetectionradius)
bestrating = rating;
}
}
- head = head.chain;
+ }
+
+ if(!best && have_secondary_targets && !scan_secondary_targets)
+ {
+ scan_secondary_targets = true;
+ // restart the loop
+ head = head2;
+ bestrating = 100000000;
+ goto scan_targets;
}
// I want to do a second scan if no enemy was found or I don't have weapons
// TODO: Perform the scan when using the rifle (requires changes on the rifle code)
if(best || self.weapons) // || self.weapon == WEP_RIFLE.m_id
break;
- if(i)
+ if(scan_transparent)
break;
// Set flags to see through transparent objects
self.dphitcontentsmask |= DPCONTENTS_OPAQUE;
head = head2;
+ scan_transparent = true;
}
// Restore hit flags
self.enemy = best;
self.havocbot_stickenemy = true;
+ if(best && best.classname == "misc_breakablemodel")
+ self.havocbot_stickenemy = false;
}
float havocbot_chooseweapon_checkreload(int new_weapon)
-{
+{SELFPARAM();
// bots under this skill cannot find unloaded weapons to reload idly when not in combat,
// so skip this for them, or they'll never get to reload their weapons at all.
// this also allows bots under this skill to be more stupid, and reload more often during combat :)
float i, other_weapon_available = false;
for(i = WEP_FIRST; i <= WEP_LAST; ++i)
{
+ Weapon w = get_weaponinfo(i);
// if we are out of ammo for all other weapons, it's an emergency to switch to anything else
- if (WEP_ACTION(i, WR_CHECKAMMO1) + WEP_ACTION(i, WR_CHECKAMMO2))
+ if (w.wr_checkammo1(w) + w.wr_checkammo2(w))
other_weapon_available = true;
}
if(other_weapon_available)
}
void havocbot_chooseweapon()
-{
+{SELFPARAM();
int i;
// ;)
- if(g_weaponarena_weapons == WEPSET_TUBA)
+ if(g_weaponarena_weapons == WEPSET(TUBA))
{
self.switchweapon = WEP_TUBA.m_id;
return;
// Choose weapons for far distance
if ( distance > bot_distance_far ) {
- for(i=0; i < WEP_COUNT && bot_weapons_far[i] != -1 ; ++i){
+ for(i=0; i < Weapons_COUNT && bot_weapons_far[i] != -1 ; ++i){
w = bot_weapons_far[i];
if ( client_hasweapon(self, w, true, false) )
{
// Choose weapons for mid distance
if ( distance > bot_distance_close) {
- for(i=0; i < WEP_COUNT && bot_weapons_mid[i] != -1 ; ++i){
+ for(i=0; i < Weapons_COUNT && bot_weapons_mid[i] != -1 ; ++i){
w = bot_weapons_mid[i];
if ( client_hasweapon(self, w, true, false) )
{
}
// Choose weapons for close distance
- for(i=0; i < WEP_COUNT && bot_weapons_close[i] != -1 ; ++i){
+ for(i=0; i < Weapons_COUNT && bot_weapons_close[i] != -1 ; ++i){
w = bot_weapons_close[i];
if ( client_hasweapon(self, w, true, false) )
{
}
void havocbot_aim()
-{
+{SELFPARAM();
vector selfvel, enemyvel;
// if(self.flags & FL_INWATER)
// return;
}
float havocbot_moveto_refresh_route()
-{
+{SELFPARAM();
// Refresh path to goal if necessary
entity wp;
wp = self.havocbot_personal_waypoint;
}
float havocbot_moveto(vector pos)
-{
+{SELFPARAM();
entity wp;
if(self.aistatus & AI_STATUS_WAYPOINT_PERSONAL_GOING)
}
void havocbot_setupbot()
-{
+{SELFPARAM();
self.bot_ai = havocbot_ai;
self.cmd_moveto = havocbot_moveto;
self.cmd_resetgoal = havocbot_resetgoal;
}
vector havocbot_dodge()
-{
+{SELFPARAM();
// LordHavoc: disabled because this is too expensive
return '0 0 0';
#if 0
void havocbot_goalrating_kh(float ratingscale_team, float ratingscale_dropped, float ratingscale_enemy)
-{
+{SELFPARAM();
entity head;
for (head = kh_worldkeylist; head; head = head.kh_worldkeynext)
{
}
void havocbot_role_kh_carrier()
-{
+{SELFPARAM();
if(self.deadflag != DEAD_NO)
return;
}
void havocbot_role_kh_defense()
-{
+{SELFPARAM();
if(self.deadflag != DEAD_NO)
return;
}
void havocbot_role_kh_offense()
-{
+{SELFPARAM();
if(self.deadflag != DEAD_NO)
return;
}
void havocbot_role_kh_freelancer()
-{
+{SELFPARAM();
if(self.deadflag != DEAD_NO)
return;
}
void havocbot_chooserole_kh()
-{
+{SELFPARAM();
float r;
if(self.deadflag != DEAD_NO)
.void() havocbot_role;
void havocbot_goalrating_items(float ratingscale, vector org, float sradius)
-{
+{SELFPARAM();
entity head;
entity player;
float rating, d, discard, distance, friend_distance, enemy_distance;
}
void havocbot_goalrating_controlpoints(float ratingscale, vector org, float sradius)
-{
+{SELFPARAM();
entity head;
head = findchain(classname, "dom_controlpoint");
while (head)
}
void havocbot_goalrating_enemyplayers(float ratingscale, vector org, float sradius)
-{
+{SELFPARAM();
entity head;
int t;
float distance;
// legacy bot role for standard gamemodes
// go to best items
void havocbot_role_generic()
-{
+{SELFPARAM();
if(self.deadflag != DEAD_NO)
return;
}
void havocbot_chooserole_generic()
-{
+{SELFPARAM();
self.havocbot_role = havocbot_role_generic;
}
void havocbot_chooserole()
-{
+{SELFPARAM();
LOG_TRACE("choosing a role...\n");
self.bot_strategytime = 0;
if (MUTATOR_CALLHOOK(HavocBot_ChooseRole, self))
// can be traveled, used for waypoint linking and havocbot
float tracewalk(entity e, vector start, vector m1, vector m2, vector end, float movemode)
-{
+{SELFPARAM();
vector org;
vector move;
vector dir;
// completely empty the goal stack, used when deciding where to go
void navigation_clearroute()
-{
+{SELFPARAM();
//print("bot ", etos(self), " clear\n");
self.navigation_hasgoals = false;
self.goalcurrent = world;
// That means, if the stack overflows, the bot will know how to do the FIRST 32
// steps to the goal, and then recalculate the path.
void navigation_pushroute(entity e)
-{
+{SELFPARAM();
//print("bot ", etos(self), " push ", etos(e), "\n");
self.goalstack31 = self.goalstack30;
self.goalstack30 = self.goalstack29;
// (in other words: remove a prerequisite for reaching the later goals)
// (used when a spawnfunc_waypoint is reached)
void navigation_poproute()
-{
+{SELFPARAM();
//print("bot ", etos(self), " pop\n");
self.goalcurrent = self.goalstack01;
self.goalstack01 = self.goalstack02;
// finds the waypoints near the bot initiating a navigation query
float navigation_markroutes_nearestwaypoints(entity waylist, float maxdist)
-{
+{SELFPARAM();
entity head;
vector v, m1, m2, diff;
float c;
// queries the entire spawnfunc_waypoint network for pathes leading away from the bot
void navigation_markroutes(entity fixed_source_waypoint)
-{
+{SELFPARAM();
entity w, wp, waylist;
float searching, cost, cost2;
vector p;
// updates the best goal according to a weighted calculation of travel cost and item value of a new proposed item
void navigation_routerating(entity e, float f, float rangebias)
-{
+{SELFPARAM();
entity nwp;
vector o;
if (!e)
// adds an item to the the goal stack with the path to a given item
float navigation_routetogoal(entity e, vector startposition)
-{
+{SELFPARAM();
self.goalentity = e;
// if there is no goal, just exit
// removes any currently touching waypoints from the goal stack
// (this is how bots detect if they reached a goal)
void navigation_poptouchedgoals()
-{
+{SELFPARAM();
vector org, m1, m2;
org = self.origin;
m1 = org + self.mins;
// begin a goal selection session (queries spawnfunc_waypoint network)
void navigation_goalrating_start()
-{
+{SELFPARAM();
if(self.aistatus & AI_STATUS_STUCK)
return;
// ends a goal selection session (updates goal stack to the best goal)
void navigation_goalrating_end()
-{
+{SELFPARAM();
if(self.aistatus & AI_STATUS_STUCK)
return;
}
void navigation_unstuck()
-{
+{SELFPARAM();
float search_radius = 1000;
if (!autocvar_bot_wander_enable)
}
void debugnode(vector node)
-{
+{SELFPARAM();
if (!IS_PLAYER(self))
return;
// Debug the goal stack visually
void debuggoalstack()
-{
+{SELFPARAM();
entity goal;
vector org, go;
.entity bot_places[MAX_BOT_PLACES];
.string bot_placenames[MAX_BOT_PLACES];
entity bot_getplace(string placename)
-{
+{SELFPARAM();
entity e;
if(substring(placename, 0, 1) == "@")
{
}
float bot_cmd_impulse()
-{
+{SELFPARAM();
self.impulse = bot_cmd.bot_cmd_parm_float;
return CMD_STATUS_FINISHED;
}
float bot_cmd_continue()
-{
+{SELFPARAM();
self.bot_exec_status &= ~BOT_EXEC_STATUS_PAUSED;
return CMD_STATUS_FINISHED;
}
.float bot_cmd_wait_time;
float bot_cmd_wait()
-{
+{SELFPARAM();
if(self.bot_exec_status & BOT_EXEC_STATUS_WAITING)
{
if(time>=self.bot_cmd_wait_time)
}
float bot_cmd_wait_until()
-{
+{SELFPARAM();
if(time < bot_cmd.bot_cmd_parm_float + bot_barriertime)
{
self.bot_exec_status |= BOT_EXEC_STATUS_WAITING;
}
float bot_cmd_barrier()
-{
+{SELFPARAM();
entity cl;
// 0 = no barrier, 1 = waiting, 2 = waiting finished
}
float bot_cmd_turn()
-{
+{SELFPARAM();
self.v_angle_y = self.v_angle.y + bot_cmd.bot_cmd_parm_float;
self.v_angle_y = self.v_angle.y - floor(self.v_angle.y / 360) * 360;
return CMD_STATUS_FINISHED;
}
float bot_cmd_select_weapon()
-{
+{SELFPARAM();
float id;
id = bot_cmd.bot_cmd_parm_float;
const int CMD_CONDITION_false_BLOCK = 8;
float bot_cmd_eval(string expr)
-{
+{SELFPARAM();
// Search for numbers
if(strstrofs("0123456789", substring(expr, 0, 1), 0) >= 0)
{
}
float bot_cmd_if()
-{
+{SELFPARAM();
string expr, val_a, val_b;
float cmpofs;
}
float bot_cmd_else()
-{
+{SELFPARAM();
self.bot_cmd_condition_status &= ~CMD_CONDITION_true_BLOCK;
self.bot_cmd_condition_status |= CMD_CONDITION_false_BLOCK;
return CMD_STATUS_FINISHED;
}
float bot_cmd_fi()
-{
+{SELFPARAM();
self.bot_cmd_condition_status = CMD_CONDITION_NONE;
return CMD_STATUS_FINISHED;
}
float bot_cmd_resetaim()
-{
+{SELFPARAM();
self.v_angle = '0 0 0';
return CMD_STATUS_FINISHED;
}
.vector bot_cmd_aim_end;
float bot_cmd_aim()
-{
+{SELFPARAM();
// Current direction
if(self.bot_cmd_aim_endtime)
{
}
float bot_cmd_aimtarget()
-{
+{SELFPARAM();
if(self.bot_cmd_aim_endtime)
{
return bot_cmd_aim();
const int BOT_CMD_KEY_CHAT = 1024;
float bot_presskeys()
-{
+{SELFPARAM();
self.movement = '0 0 0';
self.BUTTON_JUMP = false;
self.BUTTON_CROUCH = false;
float bot_cmd_keypress_handler(string key, float enabled)
-{
+{SELFPARAM();
switch(key)
{
case "all":
}
float bot_cmd_pause()
-{
+{SELFPARAM();
self.button1 = 0;
self.button8 = 0;
self.BUTTON_USE = 0;
}
float bot_cmd_moveto()
-{
+{SELFPARAM();
return self.cmd_moveto(bot_cmd.bot_cmd_parm_vector);
}
float bot_cmd_movetotarget()
-{
+{SELFPARAM();
entity e;
e = bot_getplace(bot_cmd.bot_cmd_parm_string);
if(!e)
}
float bot_cmd_resetgoal()
-{
+{SELFPARAM();
return self.cmd_resetgoal();
}
float bot_cmd_sound()
-{
+{SELFPARAM();
string f;
f = bot_cmd.bot_cmd_parm_string;
atten = stof(argv(2));
precache_sound(f);
- sound(self, chan, sample, vol, atten);
+ _sound(self, chan, sample, vol, atten);
return CMD_STATUS_FINISHED;
}
.entity tuba_note;
float bot_cmd_debug_assert_canfire()
-{
+{SELFPARAM();
float f;
f = bot_cmd.bot_cmd_parm_float;
//
void bot_command_executed(float rm)
-{
+{SELFPARAM();
entity cmd;
cmd = bot_cmd;
}
void bot_setcurrentcommand()
-{
+{SELFPARAM();
bot_cmd = world;
if(!self.bot_cmd_current)
// Here we map commands to functions and deal with complex interactions between commands and execution states
// NOTE: Of course you need to include your commands here too :)
float bot_execute_commands_once()
-{
+{SELFPARAM();
float status, ispressingkey;
// Find command
{
m1 = w.mins;
m2 = w.maxs;
- setmodel(w, "models/runematch/rune.mdl"); w.effects = EF_LOWPRECISION;
+ setmodel(w, MDL_WAYPOINT); w.effects = EF_LOWPRECISION;
setsize(w, m1, m2);
if (w.wpflags & WAYPOINTFLAG_ITEM)
w.colormod = '1 0 0';
// (precompile a list of all reachable waypoints from this spawnfunc_waypoint)
// (SLOW!)
void waypoint_think()
-{
+{SELFPARAM();
entity e;
vector sv, sm1, sm2, ev, em1, em2, dv;
vector m1, m2;
m1 = wp.mins;
m2 = wp.maxs;
- setmodel(wp, "models/runematch/rune.mdl"); wp.effects = EF_LOWPRECISION;
+ setmodel(wp, MDL_WAYPOINT); wp.effects = EF_LOWPRECISION;
setsize(wp, m1, m2);
if (wp.wpflags & WAYPOINTFLAG_ITEM)
wp.colormod = '1 0 0';
}
// spawnfunc_waypoint map entity
-void spawnfunc_waypoint()
+spawnfunc(waypoint)
{
setorigin(self, self.origin);
// schedule a relink after other waypoints have had a chance to spawn
}
entity waypoint_spawnpersonal(vector position)
-{
+{SELFPARAM();
entity w;
// drop the waypoint to a proper location:
* Functions
*/
-void spawnfunc_waypoint();
+spawnfunc(waypoint);
void waypoint_addlink(entity from, entity to);
void waypoint_think();
void waypoint_clearlinks(entity wp);
#include "../common/constants.qh"
#include "../common/deathtypes.qh"
-#include "../common/effects.qh"
+#include "../common/effects/effects.qh"
#include "../common/util.qh"
#include "../common/monsters/all.qh"
}
float CheatsAllowed(float i, float argc, float fr) // the cheat gets passed as argument for possible future ACL checking
-{
+{SELFPARAM();
// dead people cannot cheat
if(self.deadflag != DEAD_NO)
return 0;
float num_autoscreenshot;
void info_autoscreenshot_findtarget()
-{
+{SELFPARAM();
entity e;
e = find(world, targetname, self.target);
if(!e)
self.angles_y = a.y;
// we leave Rick Roll alone
}
-void spawnfunc_info_autoscreenshot()
+spawnfunc(info_autoscreenshot)
{
if(++num_autoscreenshot > autocvar_g_max_info_autoscreenshot)
{
}
float CheatImpulse(float i)
-{
+{SELFPARAM();
BEGIN_CHEAT_FUNCTION();
switch(i)
{
e = self;
Send_Effect(EFFECT_ROCKET_EXPLODE, e.origin, '0 0 0', 1);
- sound(e, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+ sound(e, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
e2 = spawn();
setorigin(e2, e.origin);
void DragBox_Think();
float drag_lastcnt;
float CheatCommand(float argc)
-{
+{SELFPARAM();
BEGIN_CHEAT_FUNCTION();
string cmd;
cmd = argv(0);
switch(cmd)
{
- entity e;
float effectnum, f;
vector start, end;
entity oldself;
}
else
{
- e = spawn();
+ entity e = spawn();
e.model = strzone(argv(1));
e.mdl = "rocket_explode";
e.health = 1000;
e.angles = fixedvectoangles2(trace_plane_normal, v_forward);
e.angles = AnglesTransform_ApplyToAngles(e.angles, '-90 0 0'); // so unrotated models work
}
- oldself = self;
- self = e;
- spawnfunc_func_breakable();
- self = oldself;
+ WITH(entity, self, e, spawnfunc_func_breakable(e));
// now, is it valid?
if(f == 0)
{
}
sprint(self, "Usage: sv_cheats 1; restart; cmd penalty 5.0 AHAHAHAHAHAHAH))\n");
break;
- case "dragbox_spawn":
+ case "dragbox_spawn": {
IS_CHEAT(0, argc, 0);
- e = spawn();
+ entity e = spawn();
e.classname = "dragbox_box";
e.think = DragBox_Think;
e.nextthink = time;
e.solid = -1; // black
- setmodel(e, "null"); // network it
+ setmodel(e, MDL_Null); // network it
if(argc == 4)
e.cnt = stof(argv(1));
else
e.aiment = spawn();
e.aiment.classname = "dragbox_corner_1";
e.aiment.owner = e;
- setmodel(e.aiment, "models/marker.md3");
+ setmodel(e.aiment, MDL_MARKER);
e.aiment.skin = 0;
setsize(e.aiment, '0 0 0', '0 0 0');
if(argc == 4)
e.enemy = spawn();
e.enemy.classname = "dragbox_corner_2";
e.enemy.owner = e;
- setmodel(e.enemy, "models/marker.md3");
+ setmodel(e.enemy, MDL_MARKER);
e.enemy.skin = 1;
setsize(e.enemy, '0 0 0', '0 0 0');
end = normalize(self.origin + self.view_ofs - e.aiment.origin);
setorigin(e.killindicator.killindicator, '0 0 8');
DID_CHEAT();
break;
- case "dragpoint_spawn":
+ }
+ case "dragpoint_spawn": {
IS_CHEAT(0, argc, 0);
- e = spawn();
+ entity e = spawn();
e.classname = "dragpoint";
e.think = DragBox_Think;
e.nextthink = time;
e.solid = 0; // nothing special
- setmodel(e, "models/marker.md3");
+ setmodel(e, MDL_MARKER);
setsize(e, PL_MIN, PL_MAX);
e.skin = 2;
if(argc == 3)
setorigin(e.killindicator.killindicator, '0 0 56');
DID_CHEAT();
break;
+ }
case "drag_remove":
IS_CHEAT(0, argc, 0);
RandomSelection_Init();
crosshair_trace(self);
- for(e = world; (e = find(e, classname, "dragbox_box")); )
+ for(entity e = world; (e = find(e, classname, "dragbox_box")); )
RandomSelection_Add(e, 0, string_null, 1, 1 / vlen(e.origin + (e.mins + e.maxs) * 0.5 - trace_endpos));
- for(e = world; (e = find(e, classname, "dragpoint")); )
+ for(entity e = world; (e = find(e, classname, "dragpoint")); )
RandomSelection_Add(e, 0, string_null, 1, 1 / vlen(e.origin + (e.mins + e.maxs) * 0.5 - trace_endpos));
if(RandomSelection_chosen_ent)
{
{
RandomSelection_Init();
crosshair_trace(self);
- for(e = world; (e = find(e, classname, "dragbox_box")); )
+ for(entity e = world; (e = find(e, classname, "dragbox_box")); )
RandomSelection_Add(e, 0, string_null, 1, 1 / vlen(e.origin + (e.mins + e.maxs) * 0.5 - trace_endpos));
- for(e = world; (e = find(e, classname, "dragpoint")); )
+ for(entity e = world; (e = find(e, classname, "dragpoint")); )
RandomSelection_Add(e, 0, string_null, 1, 1 / vlen(e.origin + (e.mins + e.maxs) * 0.5 - trace_endpos));
if(RandomSelection_chosen_ent)
{
{
f = fopen(argv(1), FILE_WRITE);
fputs(f, "cmd drag_clear\n");
- for(e = world; (e = find(e, classname, "dragbox_box")); )
+ for(entity e = world; (e = find(e, classname, "dragbox_box")); )
{
fputs(f, strcat("cmd dragbox_spawn ", ftos(e.cnt), " \"", vtos(e.aiment.origin), "\" \"", vtos(e.enemy.origin), "\"\n"));
}
- for(e = world; (e = find(e, classname, "dragpoint")); )
+ for(entity e = world; (e = find(e, classname, "dragpoint")); )
{
fputs(f, strcat("cmd dragpoint_spawn ", ftos(e.cnt), " \"", vtos(e.origin), "\"\n"));
}
if(argc == 2)
{
f = fopen(argv(1), FILE_WRITE);
- for(e = world; (e = find(e, classname, "dragbox_box")); )
+ for(entity e = world; (e = find(e, classname, "dragbox_box")); )
{
fputs(f, "{\n");
fputs(f, "\"classname\" \"trigger_race_checkpoint\"\n");
fputs(f, strcat("\"targetname\" \"checkpoint", ftos(e.cnt), "\"\n"));
fputs(f, "}\n");
}
- for(e = world; (e = find(e, classname, "dragpoint")); )
+ for(entity e = world; (e = find(e, classname, "dragpoint")); )
{
start = '0 0 0';
effectnum = 0;
break;
case "drag_clear":
IS_CHEAT(0, argc, 0);
- for(e = world; (e = find(e, classname, "dragbox_box")); )
+ for(entity e = world; (e = find(e, classname, "dragbox_box")); )
remove(e);
- for(e = world; (e = find(e, classname, "dragbox_corner_1")); )
+ for(entity e = world; (e = find(e, classname, "dragbox_corner_1")); )
remove(e);
- for(e = world; (e = find(e, classname, "dragbox_corner_2")); )
+ for(entity e = world; (e = find(e, classname, "dragbox_corner_2")); )
remove(e);
- for(e = world; (e = find(e, classname, "dragpoint")); )
+ for(entity e = world; (e = find(e, classname, "dragpoint")); )
remove(e);
- for(e = world; (e = find(e, classname, "drag_digit")); )
+ for(entity e = world; (e = find(e, classname, "drag_digit")); )
remove(e);
DID_CHEAT();
break;
break;
case "usetarget":
IS_CHEAT(0, argc, 0);
- e = self;
- self = spawn();
+ setself(spawn());
self.target = argv(1);
- activator = e;
+ activator = this;
SUB_UseTargets();
remove(self);
- self = e;
+ setself(this);
DID_CHEAT();
break;
case "killtarget":
IS_CHEAT(0, argc, 0);
- e = self;
- self = spawn();
+ setself(spawn());
self.killtarget = argv(1);
- activator = e;
+ activator = this;
SUB_UseTargets();
remove(self);
- self = e;
+ setself(this);
DID_CHEAT();
break;
case "teleporttotarget":
IS_CHEAT(0, argc, 0);
- e = self;
- self = spawn();
+ setself(spawn());
setorigin(self, self.origin);
self.classname = "cheattriggerteleport";
self.target = argv(1);
teleport_findtarget();
if(!wasfreed(self))
{
- Simple_TeleportPlayer(self, e);
+ Simple_TeleportPlayer(self, this);
remove(self);
- self = e;
DID_CHEAT();
}
- else
- self = e;
+ setself(this);
break;
}
.entity dragentity;
float CheatFrame()
-{
+{SELFPARAM();
BEGIN_CHEAT_FUNCTION();
// Dragging can be used as either a cheat, or a function for some objects. If sv_cheats is active,
.float dragmovetype;
float Drag(float force_allow_pick, float ischeat)
-{
+{SELFPARAM();
BEGIN_CHEAT_FUNCTION();
// returns true when an entity has been picked up
}
void DragBox_Think()
-{
+{SELFPARAM();
if(self.aiment && self.enemy)
{
self.origin_x = (self.aiment.origin.x + self.enemy.origin.x) * 0.5;
if(self.cnt == -1) // actually race_place -1
{
// show "10 10" for qualifying spawns
- setmodel(self.killindicator, "models/sprites/10.spr32");
- setmodel(self.killindicator.killindicator, "models/sprites/10.spr32");
+ setmodel(self.killindicator, MDL_NUM(10));
+ setmodel(self.killindicator.killindicator, MDL_NUM(10));
}
else if(self.cnt == -2) // actually race_place 0
{
// show "10 0" for loser spawns
- setmodel(self.killindicator, "models/sprites/10.spr32");
- setmodel(self.killindicator.killindicator, "models/sprites/0.spr32");
+ setmodel(self.killindicator, MDL_NUM(10));
+ setmodel(self.killindicator.killindicator, MDL_NUM(0));
}
else
{
- setmodel(self.killindicator, strcat("models/sprites/", ftos(self.cnt % 10), ".spr32"));
- setmodel(self.killindicator.killindicator, strcat("models/sprites/", ftos(floor(self.cnt / 10)), ".spr32"));
+ setmodel(self.killindicator, MDL_NUM(self.cnt % 10));
+ setmodel(self.killindicator.killindicator, MDL_NUM(floor(self.cnt / 10)));
}
self.nextthink = time;
WriteByte(MSG_BROADCAST, TE_CSQC_TEAMNAGGER);
}
-float ClientData_Send(entity to, int sf)
+bool ClientData_Send(entity this, entity to, int sf)
{
if(to != self.owner)
{
}
void ClientData_Attach()
-{
+{SELFPARAM();
Net_LinkEntity(self.clientdata = spawn(), false, 0, ClientData_Send);
self.clientdata.drawonlytoclient = self;
self.clientdata.owner = self;
}
void ClientData_Detach()
-{
+{SELFPARAM();
remove(self.clientdata);
self.clientdata = world;
}
void setplayermodel(entity e, string modelname)
{
precache_model(modelname);
- setmodel(e, modelname);
+ _setmodel(e, modelname);
player_setupanimsformodel();
UpdatePlayerSounds();
}
*/
void FixPlayermodel();
void PutObserverInServer (void)
-{
+{SELFPARAM();
entity spot;
self.hud = HUD_NORMAL;
}
self.frags = FRAGS_SPECTATOR;
+ self.bot_attack = false;
MUTATOR_CALLHOOK(MakePlayerObserver);
self.weapons = '0 0 0';
self.model = "";
FixPlayermodel();
- setmodel(self, "null");
+ setmodel(self, MDL_Null);
self.drawonlytoclient = self;
setsize (self, PL_CROUCH_MIN, PL_CROUCH_MAX); // give the spectator some space between walls for MOVETYPE_FLY_WORLDONLY
.float model_randomizer;
void FixPlayermodel()
-{
+{SELFPARAM();
string defaultmodel;
float defaultskin, chmdl, oldskin, n, i;
vector m1, m2;
{
if(teamplay)
{
- string s;
- s = Static_Team_ColorName_Lower(self.team);
- if(s != "neutral")
+ string s = Static_Team_ColorName_Lower(self.team);
+ if (s != "neutral")
{
defaultmodel = cvar_string(strcat("sv_defaultplayermodel_", s));
defaultskin = cvar(strcat("sv_defaultplayerskin_", s));
setcolor(self, stof(autocvar_sv_defaultplayercolors));
}
-/*
-=============
-PutClientInServer
-Called when a client spawns in the server
-=============
-*/
-void PutClientInServer (void)
+/** Called when a client spawns in the server */
+void PutClientInServer()
{
+ SELFPARAM();
if(IS_BOT_CLIENT(self))
self.classname = "player";
else if(IS_REAL_CLIENT(self))
if(IS_PLAYER(self))
{
- entity spot, oldself;
+ entity spot;
accuracy_resend(self);
if(g_weaponarena_random) // WEAPONTODO: more stuff that should be in a mutator. also: rename those cvars
{
if(g_weaponarena_random_with_blaster)
- self.weapons &= ~WEPSET_BLASTER;
+ self.weapons &= ~WEPSET(BLASTER);
W_RandomWeapons(self, g_weaponarena_random);
if(g_weaponarena_random_with_blaster)
- self.weapons |= WEPSET_BLASTER;
+ self.weapons |= WEPSET(BLASTER);
}
self.items = start_items;
self.killcount = 0;
}
- CL_SpawnWeaponentity();
+ CL_SpawnWeaponentity(self);
self.alpha = default_player_alpha;
self.colormod = '1 1 1' * autocvar_g_player_brightness;
self.exteriorweaponentity.alpha = default_weapon_alpha;
// reset fields the weapons may use
for (int j = WEP_FIRST; j <= WEP_LAST; ++j)
{
- WEP_ACTION(j, WR_RESETPLAYER);
+ Weapon w = get_weaponinfo(j);
+ w.wr_resetplayer(w);
// all weapons must be fully loaded when we spawn
entity e = get_weaponinfo(j);
self.(weapon_load[j]) = e.reloading_ammo;
}
- oldself = self;
- self = spot;
- activator = oldself;
- string s;
- s = self.target;
- self.target = string_null;
- SUB_UseTargets();
- self.target = s;
- activator = world;
- self = oldself;
+ string s = spot.target;
+ spot.target = string_null;
+ activator = self;
+ WITH(entity, self, spot, SUB_UseTargets());
+ activator = world;
+ spot.target = s;
Unfreeze(self);
.float ebouncefactor, ebouncestop; // electro's values
// TODO do we need all these fields, or should we stop autodetecting runtime
// changes and just have a console command to update this?
-float ClientInit_SendEntity(entity to, int sf)
+bool ClientInit_SendEntity(entity this, entity to, int sf)
{
WriteByte(MSG_ENTITY, ENT_CLIENT_INIT);
WriteByte(MSG_ENTITY, g_nexball_meter_period * 32);
}
void ClientInit_CheckUpdate()
-{
+{SELFPARAM();
self.nextthink = time;
if(self.count != autocvar_g_balance_armor_blockpercent)
{
}
void ClientInit_Spawn()
-{
- entity o;
- entity e;
- e = spawn();
+{SELFPARAM();
+ entity e = spawn();
e.classname = "clientinit";
e.think = ClientInit_CheckUpdate;
Net_LinkEntity(e, false, 0, ClientInit_SendEntity);
- o = self;
- self = e;
- ClientInit_CheckUpdate();
- self = o;
+ WITH(entity, self, e, ClientInit_CheckUpdate());
}
/*
=============
*/
void SetChangeParms (void)
-{
+{SELFPARAM();
// save parms for level change
parm1 = self.parm_idlesince - time;
}
=============
*/
void DecodeLevelParms (void)
-{
+{SELFPARAM();
// load parms
self.parm_idlesince = parm1;
if(self.parm_idlesince == -(86400 * 366))
.float clientkill_nexttime;
void ClientKill_Now_TeamChange()
-{
+{SELFPARAM();
if(self.killindicator_teamchange == -1)
{
JoinBestTeam( self, false, true );
}
void ClientKill_Now()
-{
+{SELFPARAM();
if(self.vehicle)
{
vehicles_exit(VHEF_RELEASE);
// now I am sure the player IS dead
}
void KillIndicator_Think()
-{
+{SELFPARAM();
if (gameover)
{
self.owner.killindicator = world;
if(self.cnt <= 0)
{
- self = self.owner;
- ClientKill_Now(); // no oldself needed
+ WITH(entity, self, self.owner, ClientKill_Now());
return;
}
else if(g_cts && self.health == 1) // health == 1 means that it's silent
else
{
if(self.cnt <= 10)
- setmodel(self, strcat("models/sprites/", ftos(self.cnt), ".spr32"));
+ setmodel(self, MDL_NUM(self.cnt));
if(IS_REAL_CLIENT(self.owner))
{
if(self.cnt <= 10)
float clientkilltime;
void ClientKill_TeamChange (float targetteam) // 0 = don't change, -1 = auto, -2 = spec
-{
+{SELFPARAM();
float killtime;
float starttime;
entity e;
}
void ClientKill (void)
-{
+{SELFPARAM();
if(gameover) return;
if(self.player_blocked) return;
if(self.frozen) return;
=============
*/
void ClientPreConnect (void)
-{
+{SELFPARAM();
if(autocvar_sv_eventlog)
{
GameLogEcho(sprintf(":connect:%d:%d:%s",
*/
void DecodeLevelParms (void);
void ClientConnect (void)
-{
+{SELFPARAM();
float t;
if(IS_CLIENT(self))
else
stuffcmd(self, "set _teams_available 0\n");
- attach_entcs();
+ attach_entcs(self);
bot_relinkplayerlist();
Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_MOTD, getwelcomemessage());
}
- if(autocvar_g_bugrigs || (g_weaponarena_weapons == WEPSET_TUBA))
+ if(autocvar_g_bugrigs || (g_weaponarena_weapons == WEPSET(TUBA)))
stuffcmd(self, "cl_cmd settemp chase_active 1\n");
}
CheatInitClient();
- CSQCMODEL_AUTOINIT();
+ CSQCMODEL_AUTOINIT(self);
self.model_randomizer = random();
sv_notice_join();
for (entity e = world; (e = findfloat(e, init_for_player_needed, 1)); ) {
- entity oldself = self;
- self = e;
- e.init_for_player(oldself);
- self = oldself;
+ WITH(entity, self, e, e.init_for_player(this));
}
MUTATOR_CALLHOOK(ClientConnect, self);
.entity chatbubbleentity;
void ReadyCount();
void ClientDisconnect (void)
-{
+{SELFPARAM();
if(self.vehicle)
vehicles_exit(VHEF_RELEASE);
bot_clientdisconnect();
- if(self.entcs)
- detach_entcs();
+ detach_entcs(self);
if(autocvar_sv_eventlog)
GameLogEcho(strcat(":part:", ftos(self.playerid)));
.float BUTTON_CHAT;
void ChatBubbleThink()
-{
+{SELFPARAM();
self.nextthink = time;
if ((self.owner.alpha < 0) || self.owner.chatbubbleentity != self)
{
remove(self);
return;
}
-
+
self.mdl = "";
-
+
if ( !self.owner.deadflag && IS_PLAYER(self.owner) )
{
if ( self.owner.active_minigame )
else if ( self.owner.BUTTON_CHAT )
self.mdl = "models/misc/chatbubble.spr";
}
-
+
if ( self.model != self.mdl )
- setmodel(self, self.mdl);
+ _setmodel(self, self.mdl);
}
void UpdateChatBubble()
-{
+{SELFPARAM();
if (self.alpha < 0)
return;
// spawn a chatbubble entity if needed
self.chatbubbleentity.exteriormodeltoclient = self;
self.chatbubbleentity.think = ChatBubbleThink;
self.chatbubbleentity.nextthink = time;
- setmodel(self.chatbubbleentity, "models/misc/chatbubble.spr"); // precision set below
+ setmodel(self.chatbubbleentity, MDL_CHAT); // precision set below
//setorigin(self.chatbubbleentity, self.origin + '0 0 15' + self.maxs_z * '0 0 1');
setorigin(self.chatbubbleentity, '0 0 15' + self.maxs_z * '0 0 1');
setattachment(self.chatbubbleentity, self, ""); // sticks to moving player better, also conserves bandwidth
}*/
void respawn(void)
-{
+{SELFPARAM();
if(self.alpha >= 0 && autocvar_g_respawn_ghosts)
{
self.solid = SOLID_NOT;
}
void play_countdown(float finished, string samp)
-{
+{SELFPARAM();
if(IS_REAL_CLIENT(self))
if(floor(finished - time - frametime) != floor(finished - time))
if(finished - time < 6)
- sound (self, CH_INFO, samp, VOL_BASE, ATTEN_NORM);
+ _sound (self, CH_INFO, samp, VOL_BASE, ATTEN_NORM);
}
void player_powerups (void)
-{
+{SELFPARAM();
// add a way to see what the items were BEFORE all of these checks for the mutator hook
int items_prev = self.items;
{
if (self.items & ITEM_Strength.m_itemid)
{
- play_countdown(self.strength_finished, "misc/poweroff.wav");
+ play_countdown(self.strength_finished, SND(POWEROFF));
self.effects = self.effects | (EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT);
if (time > self.strength_finished)
{
}
if (self.items & ITEM_Shield.m_itemid)
{
- play_countdown(self.invincible_finished, "misc/poweroff.wav");
+ play_countdown(self.invincible_finished, SND(POWEROFF));
self.effects = self.effects | (EF_RED | EF_ADDITIVE | EF_FULLBRIGHT);
if (time > self.invincible_finished)
{
}
else
{
- play_countdown(self.superweapons_finished, "misc/poweroff.wav");
+ play_countdown(self.superweapons_finished, SND(POWEROFF));
if (time > self.superweapons_finished)
{
self.items = self.items - (self.items & IT_SUPERWEAPON);
}
void player_regen (void)
-{
+{SELFPARAM();
float max_mod, regen_mod, rot_mod, limit_mod;
max_mod = regen_mod = rot_mod = limit_mod = 1;
regen_mod_max = max_mod;
float zoomstate_set;
void SetZoomState(float z)
-{
+{SELFPARAM();
if(z != self.zoomstate)
{
self.zoomstate = z;
zoomstate_set = 1;
}
-void GetPressedKeys(void) {
+void GetPressedKeys()
+{SELFPARAM();
MUTATOR_CALLHOOK(GetPressedKeys);
#define X(var,bit,flag) (flag ? var |= bit : var &= ~bit)
X(self.pressedkeys, KEY_FORWARD, self.movement_x > 0);
======================
*/
-void SpectateCopy(entity spectatee) {
+void SpectateCopy(entity spectatee)
+{SELFPARAM();
MUTATOR_CALLHOOK(SpectateCopy, spectatee, self);
self.armortype = spectatee.armortype;
self.armorvalue = spectatee.armorvalue;
}
bool SpectateUpdate()
-{
+{SELFPARAM();
if(!self.enemy)
return false;
}
bool SpectateSet()
-{
+{SELFPARAM();
if(!IS_PLAYER(self.enemy))
return false;
}
bool Spectate(entity pl)
-{
+{SELFPARAM();
if(g_ca && !autocvar_g_ca_spectate_enemies && self.caplayer)
if(DIFF_TEAM(pl, self))
return false;
// Returns next available player to spectate if g_ca_spectate_enemies == 0
entity CA_SpectateNext(entity start)
-{
+{SELFPARAM();
if(SAME_TEAM(start, self))
return start;
}
bool SpectateNext()
-{
+{SELFPARAM();
other = find(self.enemy, classname, "player");
if (g_ca && !autocvar_g_ca_spectate_enemies && self.caplayer)
}
bool SpectatePrev()
-{
+{SELFPARAM();
// NOTE: chain order is from the highest to the lower entnum (unlike find)
other = findchain(classname, "player");
if (!other) // no player
=============
*/
void ShowRespawnCountdown()
-{
+{SELFPARAM();
float number;
if(self.deadflag == DEAD_NO) // just respawned?
return;
}
void LeaveSpectatorMode()
-{
+{SELFPARAM();
if(self.caplayer)
return;
if(nJoinAllowed(self))
* it checks whether the number of currently playing players exceeds g_maxplayers.
* @return int number of free slots for players, 0 if none
*/
-float nJoinAllowed(entity ignore) {
+float nJoinAllowed(entity ignore)
+{SELFPARAM();
if(!ignore)
// this is called that way when checking if anyone may be able to join (to build qcstatus)
// so report 0 free slots if restricted
* Checks whether the client is an observer or spectator, if so, he will get kicked after
* g_maxplayers_spectator_blocktime seconds
*/
-void checkSpectatorBlock() {
+void checkSpectatorBlock()
+{SELFPARAM();
if(IS_SPEC(self) || IS_OBSERVER(self))
if(!self.caplayer)
if(IS_REAL_CLIENT(self))
}
void PrintWelcomeMessage()
-{
+{SELFPARAM();
if(self.motd_actived_time == 0)
{
if (autocvar_g_campaign) {
}
void ObserverThink()
-{
+{SELFPARAM();
if ( self.impulse )
{
MinigameImpulse(self.impulse);
}
void SpectatorThink()
-{
+{SELFPARAM();
if ( self.impulse )
{
if(MinigameImpulse(self.impulse))
void vehicles_enter (entity pl, entity veh);
void PlayerUseKey()
-{
+{SELFPARAM();
if (!IS_PLAYER(self))
return;
.float last_vehiclecheck;
.int items_added;
void PlayerPreThink (void)
-{
+{SELFPARAM();
WarpZone_PlayerPhysics_FixVAngle();
self.stat_game_starttime = game_starttime;
FixPlayermodel();
- GrapplingHookFrame();
-
// LordHavoc: allow firing on move frames (sub-ticrate), this gives better timing on slow servers
//if(frametime)
{
self.items &= ~self.items_added;
- W_WeaponFrame();
+ W_WeaponFrame(self);
self.items_added = 0;
if(self.items & ITEM_Jetpack.m_itemid)
{
self.teamkill_soundtime = 0;
- entity oldpusher, oldself;
-
- oldself = self; self = self.teamkill_soundsource;
- oldpusher = self.pusher; self.pusher = oldself;
+ setself(self.teamkill_soundsource);
+ entity oldpusher = self.pusher;
+ self.pusher = this;
PlayerSound(playersound_teamshoot, CH_VOICE, VOICETYPE_LASTATTACKER_ONLY);
self.pusher = oldpusher;
- self = oldself;
+ setself(this);
}
if(self.taunt_soundtime)
*/
.float idlekick_lasttimeleft;
void PlayerPostThink (void)
-{
+{SELFPARAM();
if(sv_maxidle > 0 && frametime) // WORKAROUND: only use dropclient in server frames (frametime set). Never use it in cl_movement frames (frametime zero).
if(IS_REAL_CLIENT(self))
if(IS_PLAYER(self) || sv_maxidle_spectatorsareidle)
playerdemo_write();
- CSQCMODEL_AUTOUPDATE();
+ CSQCMODEL_AUTOUPDATE(self);
}
*/
void ImpulseCommands (void)
-{
+{SELFPARAM();
int imp;
vector org;
float i;
W_PreviousWeapon(1);
break;
case 20:
- if(!forbidWeaponUse(self)) { WEP_ACTION(self.weapon, WR_RELOAD); }
+ if(!forbidWeaponUse(self)) {
+ Weapon w = get_weaponinfo(self.weapon);
+ w.wr_reload(w);
+ }
break;
}
}
else
self.impulse = imp; // retry in next frame
}
- else if(imp >= 230 && imp <= 253)
+ else if(imp >= WEP_IMPULSE_BEGIN && imp <= WEP_IMPULSE_END)
{
if(!self.vehicle)
if(self.deadflag == DEAD_NO)
- W_SwitchWeapon (imp - 230 + WEP_FIRST);
+ W_SwitchWeapon (imp - WEP_IMPULSE_BEGIN + WEP_FIRST);
else
self.impulse = imp; // retry in next frame
}
setorigin(e, org);
LOG_INFO("spawn without waypoint: ", etos(e), " ", vtos(e.origin), "\n");
e.effects |= EF_NODEPTHTEST;
- setmodel(e, self.model);
+ _setmodel(e, self.model);
e.frame = self.frame;
e.skin = self.skin;
e.colormod = '8 0.5 8';
#include "../common/animdecide.qh"
void CopyBody_Think(void)
-{
+{SELFPARAM();
if(self.CopyBody_nextthink && time > self.CopyBody_nextthink)
{
self.CopyBody_think();
self.CopyBody_think = self.think;
self.think = CopyBody_Think;
}
- CSQCMODEL_AUTOUPDATE();
+ CSQCMODEL_AUTOUPDATE(self);
self.nextthink = time;
}
void CopyBody(float keepvelocity)
-{
- entity oldself;
+{SELFPARAM();
if (self.effects & EF_NODRAW)
return;
- oldself = self;
- self = spawn();
- self.enemy = oldself;
- self.lip = oldself.lip;
- self.colormap = oldself.colormap;
- self.iscreature = oldself.iscreature;
- self.teleportable = oldself.teleportable;
- self.damagedbycontents = oldself.damagedbycontents;
- self.angles = oldself.angles;
- self.v_angle = oldself.v_angle;
- self.avelocity = oldself.avelocity;
+ setself(spawn());
+ self.enemy = this;
+ self.lip = this.lip;
+ self.colormap = this.colormap;
+ self.iscreature = this.iscreature;
+ self.teleportable = this.teleportable;
+ self.damagedbycontents = this.damagedbycontents;
+ self.angles = this.angles;
+ self.v_angle = this.v_angle;
+ self.avelocity = this.avelocity;
self.classname = "body";
- self.damageforcescale = oldself.damageforcescale;
- self.effects = oldself.effects;
- self.glowmod = oldself.glowmod;
- self.event_damage = oldself.event_damage;
- self.anim_state = oldself.anim_state;
- self.anim_time = oldself.anim_time;
- self.anim_lower_action = oldself.anim_lower_action;
- self.anim_lower_time = oldself.anim_lower_time;
- self.anim_upper_action = oldself.anim_upper_action;
- self.anim_upper_time = oldself.anim_upper_time;
- self.anim_implicit_state = oldself.anim_implicit_state;
- self.anim_implicit_time = oldself.anim_implicit_time;
- self.anim_lower_implicit_action = oldself.anim_lower_implicit_action;
- self.anim_lower_implicit_time = oldself.anim_lower_implicit_time;
- self.anim_upper_implicit_action = oldself.anim_upper_implicit_action;
- self.anim_upper_implicit_time = oldself.anim_upper_implicit_time;
- self.dphitcontentsmask = oldself.dphitcontentsmask;
- self.death_time = oldself.death_time;
- self.pain_finished = oldself.pain_finished;
- self.health = oldself.health;
- self.armorvalue = oldself.armorvalue;
- self.armortype = oldself.armortype;
- self.model = oldself.model;
- self.modelindex = oldself.modelindex;
- self.skin = oldself.skin;
- self.species = oldself.species;
- self.movetype = oldself.movetype;
- self.solid = oldself.solid;
- self.ballistics_density = oldself.ballistics_density;
- self.takedamage = oldself.takedamage;
- self.customizeentityforclient = oldself.customizeentityforclient;
- self.uncustomizeentityforclient = oldself.uncustomizeentityforclient;
- self.uncustomizeentityforclient_set = oldself.uncustomizeentityforclient_set;
+ self.damageforcescale = this.damageforcescale;
+ self.effects = this.effects;
+ self.glowmod = this.glowmod;
+ self.event_damage = this.event_damage;
+ self.anim_state = this.anim_state;
+ self.anim_time = this.anim_time;
+ self.anim_lower_action = this.anim_lower_action;
+ self.anim_lower_time = this.anim_lower_time;
+ self.anim_upper_action = this.anim_upper_action;
+ self.anim_upper_time = this.anim_upper_time;
+ self.anim_implicit_state = this.anim_implicit_state;
+ self.anim_implicit_time = this.anim_implicit_time;
+ self.anim_lower_implicit_action = this.anim_lower_implicit_action;
+ self.anim_lower_implicit_time = this.anim_lower_implicit_time;
+ self.anim_upper_implicit_action = this.anim_upper_implicit_action;
+ self.anim_upper_implicit_time = this.anim_upper_implicit_time;
+ self.dphitcontentsmask = this.dphitcontentsmask;
+ self.death_time = this.death_time;
+ self.pain_finished = this.pain_finished;
+ self.health = this.health;
+ self.armorvalue = this.armorvalue;
+ self.armortype = this.armortype;
+ self.model = this.model;
+ self.modelindex = this.modelindex;
+ self.skin = this.skin;
+ self.species = this.species;
+ self.movetype = this.movetype;
+ self.solid = this.solid;
+ self.ballistics_density = this.ballistics_density;
+ self.takedamage = this.takedamage;
+ self.customizeentityforclient = this.customizeentityforclient;
+ self.uncustomizeentityforclient = this.uncustomizeentityforclient;
+ self.uncustomizeentityforclient_set = this.uncustomizeentityforclient_set;
if (keepvelocity == 1)
- self.velocity = oldself.velocity;
+ self.velocity = this.velocity;
self.oldvelocity = self.velocity;
- self.alpha = oldself.alpha;
- self.fade_time = oldself.fade_time;
- self.fade_rate = oldself.fade_rate;
- //self.weapon = oldself.weapon;
- setorigin(self, oldself.origin);
- setsize(self, oldself.mins, oldself.maxs);
- self.prevorigin = oldself.origin;
+ self.alpha = this.alpha;
+ self.fade_time = this.fade_time;
+ self.fade_rate = this.fade_rate;
+ //self.weapon = this.weapon;
+ setorigin(self, this.origin);
+ setsize(self, this.mins, this.maxs);
+ self.prevorigin = this.origin;
self.reset = SUB_Remove;
- Drag_MoveDrag(oldself, self);
+ Drag_MoveDrag(this, self);
if(self.colormap <= maxclients && self.colormap > 0)
- self.colormap = 1024 + oldself.clientcolors;
+ self.colormap = 1024 + this.clientcolors;
- CSQCMODEL_AUTOINIT();
- self.CopyBody_nextthink = oldself.nextthink;
- self.CopyBody_think = oldself.think;
+ CSQCMODEL_AUTOINIT(self);
+ self.CopyBody_nextthink = this.nextthink;
+ self.CopyBody_think = this.think;
self.nextthink = time;
self.think = CopyBody_Think;
// "bake" the current animation frame for clones (they don't get clientside animation)
animdecide_load_if_needed(self);
animdecide_setframes(self, false, frame, frame1time, frame2, frame2time);
- self = oldself;
+ setself(this);
}
float player_getspecies()
-{
+{SELFPARAM();
float s;
get_model_parameters(self.model, self.skin);
s = get_model_parameters_species;
}
void player_setupanimsformodel()
-{
+{SELFPARAM();
// load animation info
animdecide_load_if_needed(self);
animdecide_setstate(self, 0, false);
}
void player_anim (void)
-{
+{SELFPARAM();
int deadbits = (self.anim_state & (ANIMSTATE_DEAD1 | ANIMSTATE_DEAD2));
if(self.deadflag) {
if (!deadbits) {
}
void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
float take, save;
vector v;
Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);
if(sound_allowed(MSG_BROADCAST, attacker))
{
if (save > 10)
- sound (self, CH_SHOTS, "misc/armorimpact.wav", VOL_BASE, ATTEN_NORM);
+ sound (self, CH_SHOTS, SND_ARMORIMPACT, VOL_BASE, ATTEN_NORM);
else if (take > 30)
- sound (self, CH_SHOTS, "misc/bodyimpact2.wav", VOL_BASE, ATTEN_NORM);
+ sound (self, CH_SHOTS, SND_BODYIMPACT2, VOL_BASE, ATTEN_NORM);
else if (take > 10)
- sound (self, CH_SHOTS, "misc/bodyimpact1.wav", VOL_BASE, ATTEN_NORM);
+ sound (self, CH_SHOTS, SND_BODYIMPACT1, VOL_BASE, ATTEN_NORM);
}
if (take > 50)
}
void calculate_player_respawn_time()
-{
+{SELFPARAM();
if(g_ca)
return;
}
void PlayerDamage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
float take, save, dh, da;
int j;
vector v;
if(sound_allowed(MSG_BROADCAST, attacker))
{
if (save > 10)
- sound (self, CH_SHOTS, "misc/armorimpact.wav", VOL_BASE, ATTEN_NORM);
+ sound (self, CH_SHOTS, SND_ARMORIMPACT, VOL_BASE, ATTEN_NORM);
else if (take > 30)
- sound (self, CH_SHOTS, "misc/bodyimpact2.wav", VOL_BASE, ATTEN_NORM);
+ sound (self, CH_SHOTS, SND_BODYIMPACT2, VOL_BASE, ATTEN_NORM);
else if (take > 10)
- sound (self, CH_SHOTS, "misc/bodyimpact1.wav", VOL_BASE, ATTEN_NORM); // FIXME possibly remove them?
+ sound (self, CH_SHOTS, SND_BODYIMPACT1, VOL_BASE, ATTEN_NORM); // FIXME possibly remove them?
}
if (take > 50)
MUTATOR_CALLHOOK(PlayerDies, inflictor, attacker, self, deathtype);
excess = frag_damage;
- WEP_ACTION(self.weapon, WR_PLAYERDEATH);
+ Weapon wep = get_weaponinfo(self.weapon);
+ wep.wr_playerdeath(wep);
RemoveGrapplingHook(self);
// reset fields the weapons may use just in case
for (j = WEP_FIRST; j <= WEP_LAST; ++j)
{
- WEP_ACTION(j, WR_RESETPLAYER);
+ Weapon w = get_weaponinfo(j);
+ w.wr_resetplayer(w);
ATTACK_FINISHED_FOR(self, j) = 0;
}
}
{
sprint(source, sourcemsgstr);
dedicated_print(msgstr); // send to server console too
- FOR_EACH_REALCLIENT(head)
+ FOR_EACH_REALCLIENT(head)
if(head != source)
if(head.active_minigame == source.active_minigame)
sprint(head, msgstr);
void PrecachePlayerSounds(string f)
{
- float fh;
- string s;
- fh = fopen(f, FILE_READ);
- if(fh < 0)
+ int fh = fopen(f, FILE_READ);
+ if (fh < 0)
return;
- while((s = fgets(fh)))
+ for (string s; (s = fgets(fh)); )
{
- if(tokenize_console(s) != 3)
+ int n = tokenize_console(s);
+ if (n != 3)
{
- LOG_TRACE("Invalid sound info line: ", s, "\n");
+ if (n != 0) LOG_TRACEF("Invalid sound info line: %s\n", s);
continue;
}
PrecacheGlobalSound(strcat(argv(1), " ", argv(2)));
}
void ClearPlayerSounds()
-{
+{SELFPARAM();
#define _VOICEMSG(m) if(self.playersound_##m) { strunzone(self.playersound_##m); self.playersound_##m = string_null; }
ALLPLAYERSOUNDS
ALLVOICEMSGS
}
float LoadPlayerSounds(string f, float first)
-{
+{SELFPARAM();
float fh;
string s;
var .string field;
}
void UpdatePlayerSounds()
-{
+{SELFPARAM();
if(self.modelindex == self.modelindex_for_playersound)
if(self.skin == self.skin_for_playersound)
return;
}
void FakeGlobalSound(string sample, float chan, float voicetype)
-{
+{SELFPARAM();
float n;
float tauntrand;
}
void GlobalSound(string sample, float chan, float voicetype)
-{
+{SELFPARAM();
float n;
float tauntrand;
}
break;
case VOICETYPE_PLAYERSOUND:
- sound(self, chan, sample, VOL_BASE, ATTEN_NORM);
+ _sound(self, chan, sample, VOL_BASE, ATTEN_NORM);
break;
default:
backtrace("Invalid voice type!");
}
void PlayerSound(.string samplefield, float chan, float voicetype)
-{
+{SELFPARAM();
GlobalSound(self.(samplefield), chan, voicetype);
}
void VoiceMessage(string type, string msg)
-{
- var .string sample;
+{SELFPARAM();
float voicetype, ownteam;
float flood;
- sample = GetVoiceMessageSampleField(type);
+ var .string sample = GetVoiceMessageSampleField(type);
if(GetPlayerSoundSampleField_notFound)
{
// =========================================================
float SV_ParseClientCommand_floodcheck()
-{
+{SELFPARAM();
if (!timeout_status) // not while paused
{
if(time <= (self.cmd_floodtime + autocvar_sv_clientcommand_antispam_time))
// =======================
void ClientCommand_autoswitch(float request, float argc)
-{
+{SELFPARAM();
switch(request)
{
case CMD_REQUEST_COMMAND:
}
void ClientCommand_clientversion(float request, float argc) // internal command, used only by code
-{
+{SELFPARAM();
switch(request)
{
case CMD_REQUEST_COMMAND:
}
void ClientCommand_mv_getpicture(float request, float argc) // internal command, used only by code
-{
+{SELFPARAM();
switch(request)
{
case CMD_REQUEST_COMMAND:
}
void ClientCommand_join(float request)
-{
+{SELFPARAM();
switch(request)
{
case CMD_REQUEST_COMMAND:
}
void ClientCommand_physics(float request, float argc)
-{
+{SELFPARAM();
switch(request)
{
case CMD_REQUEST_COMMAND:
}
void ClientCommand_ready(float request) // todo: anti-spam for toggling readyness
-{
+{SELFPARAM();
switch(request)
{
case CMD_REQUEST_COMMAND:
}
void ClientCommand_say(float request, float argc, string command)
-{
+{SELFPARAM();
switch(request)
{
case CMD_REQUEST_COMMAND:
}
void ClientCommand_say_team(float request, float argc, string command)
-{
+{SELFPARAM();
switch(request)
{
case CMD_REQUEST_COMMAND:
}
void ClientCommand_selectteam(float request, float argc)
-{
+{SELFPARAM();
switch(request)
{
case CMD_REQUEST_COMMAND:
}
void ClientCommand_selfstuff(float request, string command)
-{
+{SELFPARAM();
switch(request)
{
case CMD_REQUEST_COMMAND:
}
void ClientCommand_sentcvar(float request, float argc, string command)
-{
+{SELFPARAM();
switch(request)
{
case CMD_REQUEST_COMMAND:
}
void ClientCommand_spectate(float request)
-{
+{SELFPARAM();
switch(request)
{
case CMD_REQUEST_COMMAND:
}
void ClientCommand_suggestmap(float request, float argc)
-{
+{SELFPARAM();
switch(request)
{
case CMD_REQUEST_COMMAND:
}
void ClientCommand_tell(float request, float argc, string command)
-{
+{SELFPARAM();
switch(request)
{
case CMD_REQUEST_COMMAND:
}
void ClientCommand_voice(float request, float argc, string command)
-{
+{SELFPARAM();
switch(request)
{
case CMD_REQUEST_COMMAND:
/* nothing */
void ClientCommand_macro_help()
-{
+{SELFPARAM();
#define CLIENT_COMMAND(name,function,description) \
{ sprint(self, " ^2", name, "^7: ", description, "\n"); }
// If this function exists, server game code parses clientcommand before the engine code gets it.
void SV_ParseClientCommand(string command)
-{
+{SELFPARAM();
// If invalid UTF-8, don't even parse it
string command2 = "";
float len = strlen(command);
// used by CommonCommand_timeout() and CommonCommand_timein() to handle game pausing and messaging and such.
void timeout_handler_reset()
-{
+{SELFPARAM();
timeout_caller = world;
timeout_time = 0;
timeout_leadtime = 0;
}
void timeout_handler_think()
-{
+{SELFPARAM();
entity tmp_player;
switch(timeout_status)
}
void CommonCommand_editmob(int request, entity caller, int argc)
-{
+{SELFPARAM();
switch(request)
{
case CMD_REQUEST_COMMAND:
radarmapper = world;
}
void RadarMap_Think()
-{
+{SELFPARAM();
// rough map entity
// cnt: current line
// size: pixel width/height
// used by GameCommand_make_mapinfo()
void make_mapinfo_Think()
-{
+{SELFPARAM();
if(MapInfo_FilterGametype(MAPINFO_TYPE_ALL, 0, 0, 0, 1))
{
LOG_INFO("Done rebuiling mapinfos.\n");
}
void GameCommand_allspec(float request, float argc)
-{
+{SELFPARAM();
switch(request)
{
case CMD_REQUEST_COMMAND:
FOR_EACH_REALPLAYER(client)
{
- self = client;
- if(self.caplayer)
- self.caplayer = 0;
- PutObserverInServer();
+ if (client.caplayer)
+ client.caplayer = 0;
+ WITH(entity, self, client, PutObserverInServer());
++i;
}
if(i) { bprint(strcat("Successfully forced all (", ftos(i), ") players to spectate", (reason ? strcat(" for reason: '", reason, "'") : ""), ".\n")); }
}
void GameCommand_anticheat(float request, float argc)
-{
+{SELFPARAM();
switch(request)
{
case CMD_REQUEST_COMMAND:
if(accepted > 0)
{
- self = client;
- anticheat_report();
+ WITH(entity, self, client, anticheat_report());
return;
}
else
{
tmp_entity = spawn();
if(argv(1) == "w")
- setmodel(tmp_entity, (nextent(world)).weaponentity.model);
+ _setmodel(tmp_entity, (nextent(world)).weaponentity.model);
else
{
precache_model(argv(1));
- setmodel(tmp_entity, argv(1));
+ _setmodel(tmp_entity, argv(1));
}
tmp_entity.frame = stof(argv(2));
if(substring(argv(3), 0, 1) == "#")
{
tmp_entity = spawn();
if(argv(1) == "w")
- setmodel(tmp_entity, (nextent(world)).weaponentity.model);
+ _setmodel(tmp_entity, (nextent(world)).weaponentity.model);
else
{
precache_model(argv(1));
- setmodel(tmp_entity, argv(1));
+ _setmodel(tmp_entity, argv(1));
}
float f1 = stof(argv(2));
float f2 = stof(argv(3));
}
void GameCommand_moveplayer(float request, float argc)
-{
+{SELFPARAM();
switch(request)
{
case CMD_REQUEST_COMMAND:
{
if(!IS_SPEC(client) && !IS_OBSERVER(client))
{
- self = client;
- if(self.caplayer)
- self.caplayer = 0;
- PutObserverInServer();
+ if (client.caplayer)
+ client.caplayer = 0;
+ WITH(entity, self, client, PutObserverInServer());
successful = strcat(successful, (successful ? ", " : ""), client.netname);
}
}
void GameCommand_playerdemo(float request, float argc)
-{
+{SELFPARAM();
switch(request)
{
case CMD_REQUEST_COMMAND:
return;
}
- self = client;
- playerdemo_open_read(argv(next_token));
+ WITH(entity, self, client, playerdemo_open_read(argv(next_token)));
return;
}
return;
}
- self = client;
- playerdemo_open_write(argv(next_token));
+ WITH(entity, self, client, playerdemo_open_write(argv(next_token)));
return;
}
}
void GameCommand_shuffleteams(float request)
-{
+{SELFPARAM();
switch(request)
{
case CMD_REQUEST_COMMAND:
continue; // not a player, move on to next random slot
if(VerifyClientNumber(shuffleteams_players[z]))
- self = edict_num(shuffleteams_players[z]);
+ setself(edict_num(shuffleteams_players[z]));
if(self.team != team_color)
MoveToTeam(self, team_color, 6);
// =============================================
// Nagger for players to know status of voting
-float Nagger_SendEntity(entity to, float sendflags)
+bool Nagger_SendEntity(entity this, entity to, float sendflags)
{
int nags, i, f, b;
entity e;
// Resets the state of all clients, items, weapons, waypoints, ... of the map.
void reset_map(float dorespawn)
-{
- entity oldself;
- oldself = self;
+{SELFPARAM();
if(time <= game_starttime && round_handler_IsActive())
round_handler_Reset(game_starttime);
MUTATOR_CALLHOOK(reset_map_global);
- for(self = world; (self = nextent(self)); )
- if(IS_NOT_A_CLIENT(self))
+ for(entity e = world; (e = nextent(e)); )
{
- if(self.reset)
+ setself(e);
+ if(IS_NOT_A_CLIENT(self))
{
- self.reset();
- continue;
- }
+ if(self.reset)
+ {
+ self.reset();
+ continue;
+ }
- if(self.team_saved)
- self.team = self.team_saved;
+ if(self.team_saved)
+ self.team = self.team_saved;
- if(self.flags & FL_PROJECTILE) // remove any projectiles left
- remove(self);
+ if(self.flags & FL_PROJECTILE) // remove any projectiles left
+ remove(self);
+ }
}
// Waypoints and assault start come LAST
- for(self = world; (self = nextent(self)); )
- if(IS_NOT_A_CLIENT(self))
+ for(entity e = world; (e = nextent(e)); )
{
- if(self.reset2)
+ setself(e);
+ if(IS_NOT_A_CLIENT(self))
{
- self.reset2();
- continue;
+ if(self.reset2)
+ {
+ self.reset2();
+ continue;
+ }
}
}
- FOR_EACH_PLAYER(self)
- if(self.frozen)
- Unfreeze(self);
+ entity e;
+ FOR_EACH_PLAYER(e)
+ if(e.frozen)
+ {
+ WITH(entity, self, e, Unfreeze(self));
+ }
// Moving the player reset code here since the player-reset depends
// on spawnpoint entities which have to be reset first --blub
if(dorespawn)
if(!MUTATOR_CALLHOOK(reset_map_players))
- FOR_EACH_CLIENT(self) // reset all players
+ FOR_EACH_CLIENT(e) // reset all players
{
+ setself(e);
/*
only reset players if a restart countdown is active
this can either be due to cvar sv_ready_restart_after_countdown having set
if(g_keyhunt)
kh_Controller_SetThink(autocvar_g_balance_keyhunt_delay_round + (game_starttime - time), kh_StartRound);
- self = oldself;
+ setself(this);
}
// Restarts the map after the countdown is over (and cvar sv_ready_restart_after_countdown is set)
void ReadyRestart_think()
-{
+{SELFPARAM();
restart_mapalreadyrestarted = 1;
reset_map(true);
Score_ClearAll();
#include "controlpoint.qh"
-bool cpicon_send(entity to, int sf)
+bool cpicon_send(entity this, entity to, int sf)
{
WriteByte(MSG_ENTITY, ENT_CLIENT_CONTROLPOINT_ICON);
WriteByte(MSG_ENTITY, sf);
#define INDEPENDENT_ATTACK_FINISHED
-noref float require_spawnfunc_prefix; // if this float exists, only functions with spawnfunc_ name prefix qualify as spawn functions
-
#define BUTTON_ATCK button0
#define BUTTON_JUMP button2
#define BUTTON_ATCK2 button3
.float pauserothealth_finished;
.float pauserotarmor_finished;
.float pauserotfuel_finished;
+// string overrides entity
.string item_pickupsound;
+.entity item_pickupsound_ent;
// definitions for weaponsystem
// more WEAPONTODO: move these to their proper files
// WEAPONTODO
.float autoswitch;
-//float WEP_ACTION(float wpn, float wrequest);
float client_hasweapon(entity cl, float wpn, float andammo, float complain);
-void w_clear();
-void w_ready();
+void w_clear(Weapon thiswep, entity actor, bool fire1, bool fire2);
+void w_ready(Weapon thiswep, entity actor, bool fire1, bool fire2);
// VorteX: standalone think for weapons, so normal think on weaponentity can be reserved by weaponflashes (which needs update even player dies)
.float weapon_nextthink;
-.void() weapon_think;
+.void(Weapon thiswep, entity actor, bool fire1, bool fire2) weapon_think;
// weapon states (self.weaponentity.state)
float bot_waypoints_for_items;
-.float attack_finished_for[WEP_MAXCOUNT];
+.float attack_finished_for[Weapons_MAX];
.float attack_finished_single;
#ifdef INDEPENDENT_ATTACK_FINISHED
#define ATTACK_FINISHED_FOR(ent,w) ((ent).(attack_finished_for[(w) - WEP_FIRST]))
float next_pingtime;
-.float Version;
-.int SendFlags;
-.bool(entity to, int sendflags) SendEntity;
-
// player sounds, voice messages
// TODO implemented fall and falling
#define ALLPLAYERSOUNDS \
// _VOICEMSG(droppedflag) \
// _VOICEMSG(negative) \
// _VOICEMSG(seenenemy) \
+// /**/
string globalsound_fall;
string globalsound_metalfall;
float client_cefc_accumulatortime;
#endif
-.float weapon_load[WEP_MAXCOUNT];
+.float weapon_load[Weapons_MAX];
.int ammo_none; // used by the reloading system, must always be 0
.float clip_load;
.float old_clip_load;
+#include "ent_cs.qh"
#include "_all.qh"
-#include "defs.qh"
-#include "mutators/mutators_include.qh"
-
-/**
- * The point of these entities is to avoid the problems
- * with clientprediction.
- * If you add SendEntity to players, the engine will not
- * do any prediction anymore, and you'd have to write the whole
- * prediction code in CSQC, you want that? :P
- * Data can depend on gamemode. For now, it serves as GPS entities
- * in onslaught... YAY ;)
- */
-
-// Beware: do not redefine those in other files
-// and NO, you cannot use ".version", which already exists (at least
-// it did when I added this) But you have to use .Version
-// Capital V
-
-.entity entcs;
-
-void entcs_init()
-{
- LOG_INFO("Initializing ClientSide information entities\n");
-}
-
float entcs_customize()
{
- entity o;
- o = self.owner;
+ SELFPARAM();
+ entity o = self.owner;
if(o.deadflag != DEAD_NO)
return false;
if (!IS_PLAYER(o))
return true;
}
-float entcs_send(entity to, int sf)
+bool entcs_send(entity this, entity to, int sf)
{
WriteByte(MSG_ENTITY, ENT_CLIENT_ENTCS);
WriteByte(MSG_ENTITY, sf);
- if(sf & 1)
- WriteByte(MSG_ENTITY, num_for_edict(self.owner)-1);
- if(sf & 2)
+ if(sf & BIT(0))
+ WriteByte(MSG_ENTITY, num_for_edict(self.owner) - 1);
+ if(sf & BIT(1))
{
WriteShort(MSG_ENTITY, self.origin.x);
WriteShort(MSG_ENTITY, self.origin.y);
WriteShort(MSG_ENTITY, self.origin.z);
}
- if(sf & 4)
+ if(sf & BIT(2))
WriteByte(MSG_ENTITY, self.angles.y * 256.0 / 360);
- if(sf & 8)
+ if(sf & BIT(3))
WriteByte(MSG_ENTITY, self.health / 10); // FIXME use a better scale?
- if(sf & 16)
+ if(sf & BIT(4))
WriteByte(MSG_ENTITY, self.armorvalue / 10); // FIXME use a better scale?
return true;
}
void entcs_think()
{
+ SELFPARAM();
self.nextthink = time + 0.033333333333; // increase this to like 0.15 once the client can do smoothing
-
- entity o;
- o = self.owner;
-
- if(o.origin != self.origin)
+ entity o = self.owner;
+ if (o.origin != self.origin)
{
setorigin(self, o.origin);
- self.SendFlags |= 2;
+ self.SendFlags |= BIT(1);
}
- if(o.angles.y != self.angles.y)
+ if (o.angles.y != self.angles.y)
{
self.angles = o.angles;
- self.SendFlags |= 4;
+ self.SendFlags |= BIT(2);
}
- if(o.health != self.health)
+ if (o.health != self.health)
{
self.health = o.health;
- self.SendFlags |= 8;
+ self.SendFlags |= BIT(3);
}
- if(o.armorvalue != self.armorvalue)
+ if (o.armorvalue != self.armorvalue)
{
self.armorvalue = o.armorvalue;
- self.SendFlags |= 16;
+ self.SendFlags |= BIT(4);
}
}
-entity attach_entcs()
+entity attach_entcs(entity e)
{
- entity ent;
-
- ent = spawn();
- ent.classname = "entcs_sender_v2";
- ent.owner = self;
+ entity ent = e.entcs = new(entcs_sender);
+ ent.owner = e;
ent.think = entcs_think;
ent.nextthink = time;
Net_LinkEntity(ent, false, 0, entcs_send);
ent.customizeentityforclient = entcs_customize;
- self.entcs = ent;
-
return ent;
}
-void detach_entcs()
+void detach_entcs(entity e)
{
- remove(self.entcs);
- self.entcs = world;
+ if (!e.entcs) return;
+ remove(e.entcs);
+ e.entcs = NULL;
}
* in onslaught... YAY ;)
*/
-// Beware: do not redefine those in other files
-// and NO, you cannot use ".version", which already exists (at least
-// it did when I added this) But you have to use .Version
-// Capital V
-
.entity entcs;
-void entcs_init();
-
float entcs_customize();
-float entcs_send(entity to, int sf);
+bool entcs_send(entity this, entity to, int sf);
void entcs_think();
-entity attach_entcs();
+entity attach_entcs(entity e);
+
+void detach_entcs(entity e);
-void detach_entcs();
#endif
#include "weapons/accuracy.qh"
#include "weapons/csqcprojectile.qh"
#include "weapons/selection.qh"
-#include "../common/buffs.qh"
+#include "../common/buffs/all.qh"
#include "../common/constants.qh"
#include "../common/deathtypes.qh"
#include "../common/notifications.qh"
#include "../csqcmodellib/sv_model.qh"
#include "../warpzonelib/common.qh"
-float Damage_DamageInfo_SendEntity(entity to, int sf)
+bool Damage_DamageInfo_SendEntity(entity this, entity to, int sf)
{
WriteByte(MSG_ENTITY, ENT_CLIENT_DAMAGEINFO);
WriteShort(MSG_ENTITY, self.projectiledeathtype);
}
void GiveFrags (entity attacker, entity targ, float f, int deathtype)
-{
+{SELFPARAM();
// TODO route through PlayerScores instead
if(gameover) return;
}
// FIXME fix the mess this is (we have REAL points now!)
- entity oldself;
- oldself = self;
- self = attacker;
- if(MUTATOR_CALLHOOK(GiveFragsForKill, attacker, targ, f))
+ if(MUTATOR_CALLHOOK(GiveFragsForKill, self, attacker, targ, f))
{
f = frag_score;
- self = oldself;
- }
- else
- {
- self = oldself;
}
attacker.totalfrags += f;
if(death_weapon)
{
w_deathtype = deathtype;
- int death_message = WEP_ACTION(death_weapon, ((murder) ? WR_KILLMESSAGE : WR_SUICIDEMESSAGE));
+ Weapon w = get_weaponinfo(death_weapon);
+ int death_message = ((murder) ? w.wr_killmessage : w.wr_suicidemessage)(w);
w_deathtype = false;
if (death_message)
}
void Ice_Think()
-{
+{SELFPARAM();
if(!self.owner.frozen || self.owner.iceblock != self)
{
remove(self);
}
void Freeze (entity targ, float freeze_time, float frozen_type, float show_waypoint)
-{
+{SELFPARAM();
if(!IS_PLAYER(targ) && !IS_MONSTER(targ)) // only specified entities can be freezed
return;
targ.revive_progress = ((frozen_type == 3) ? 1 : 0);
targ.health = ((frozen_type == 3) ? targ_maxhealth : 1);
targ.revive_speed = freeze_time;
+ self.bot_attack = false;
entity ice, head;
ice = spawn();
ice.think = Ice_Think;
ice.nextthink = time;
ice.frame = floor(random() * 21); // ice model has 20 different looking frames
- setmodel(ice, "models/ice/ice.md3");
+ setmodel(ice, MDL_ICE);
ice.alpha = 1;
ice.colormod = Team_ColorRGB(targ.team);
ice.glowmod = ice.colormod;
targ.iceblock = ice;
targ.revival_time = 0;
- entity oldself;
- oldself = self;
- self = ice;
- Ice_Think();
- self = oldself;
+ WITH(entity, self, ice, Ice_Think());
RemoveGrapplingHook(targ);
void Unfreeze (entity targ)
{
+ if(!targ.frozen)
+ return;
+
if(targ.frozen && targ.frozen != 3) // only reset health if target was frozen
targ.health = ((IS_PLAYER(targ)) ? start_health : targ.max_health);
targ.frozen = 0;
targ.revive_progress = 0;
targ.revival_time = time;
+ self.bot_attack = true;
WaypointSprite_Kill(targ.waypointsprite_attached);
}
void Damage (entity targ, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
float mirrordamage;
float mirrorforce;
float complainteamdamage = 0;
if (gameover || targ.killcount == -666)
return;
- entity oldself;
- oldself = self;
- self = targ;
+ setself(targ);
damage_targ = targ;
damage_inflictor = inflictor;
damage_attacker = attacker;
if(IS_PLAYER(targ))
if(SAME_TEAM(targ, attacker))
{
- self = oldself;
+ setself(this);
return;
}
}
{
Send_Effect(EFFECT_TELEPORT, targ.origin, '0 0 0', 1);
- entity oldself = self;
- self = targ;
+ setself(targ);
entity spot = SelectSpawnPoint (false);
if(spot)
Send_Effect(EFFECT_TELEPORT, self.origin, '0 0 0', 1);
}
- self = oldself;
+ setself(this);
}
if(!g_instagib)
if (damage != 0 || (self.damageforcescale && vlen(force)))
if (self.event_damage)
self.event_damage (inflictor, attacker, damage, deathtype, hitloc, force);
- self = oldself;
+ setself(this);
// apply mirror damage if any
if(mirrordamage > 0 || mirrorforce > 0)
}
void fireburner_think()
-{
+{SELFPARAM();
// for players, this is done in the regular loop
if(wasfreed(self.owner))
{
.float dmg_force;
.float dmg_radius;
-float Damage_DamageInfo_SendEntity(entity to, int sf);
+bool Damage_DamageInfo_SendEntity(entity this, entity to, int sf);
void Damage_DamageInfo(vector org, float coredamage, float edgedamage, float rad, vector force, int deathtype, float bloodtype, entity dmgowner);
============================================*/
.float hook_length;
-.float hook_switchweapon;
void RemoveGrapplingHook(entity pl)
{
}
void GrapplingHookReset(void)
-{
+{SELFPARAM();
if(self.realowner.hook == self)
RemoveGrapplingHook(self.owner);
else // in any case:
void GrapplingHookThink();
void GrapplingHook_Stop()
-{
+{SELFPARAM();
Send_Effect(EFFECT_HOOK_IMPACT, self.origin, '0 0 0', 1);
- sound (self, CH_SHOTS, W_Sound("hook_impact"), VOL_BASE, ATTEN_NORM);
+ sound (self, CH_SHOTS, SND_HOOK_IMPACT, VOL_BASE, ATTEN_NORM);
self.state = 1;
self.think = GrapplingHookThink;
}
.vector hook_start, hook_end;
-float GrapplingHookSend(entity to, int sf)
+bool GrapplingHookSend(entity this, entity to, int sf)
{
WriteByte(MSG_ENTITY, ENT_CLIENT_HOOK);
sf = sf & 0x7F;
return true;
}
+int autocvar_g_grappling_hook_tarzan;
+
void GrapplingHookThink()
-{
+{SELFPARAM();
float spd, dist, minlength, pullspeed, ropestretch, ropeairfriction, rubberforce, newlength, rubberforce_overstretch;
vector dir, org, end, v0, dv, v, myorg, vs;
if(self.realowner.hook != self) // how did that happen?
}
void GrapplingHookTouch (void)
-{
+{SELFPARAM();
if(other.movetype == MOVETYPE_FOLLOW)
return;
PROJECTILE_TOUCH;
}
void GrapplingHook_Damage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
if(self.health <= 0)
return;
}
void FireGrapplingHook (void)
-{
+{SELFPARAM();
entity missile;
vector org;
vector vs;
vs = hook_shotorigin[s];
// UGLY WORKAROUND: play this on CH_WEAPON_B so it can't cut off fire sounds
- sound (self, CH_WEAPON_B, W_Sound("hook_fire"), VOL_BASE, ATTEN_NORM);
+ sound (self, CH_WEAPON_B, SND_HOOK_FIRE, VOL_BASE, ATTEN_NORM);
org = self.origin + self.view_ofs + v_forward * vs.x + v_right * -vs.y + v_up * vs.z;
tracebox(self.origin + self.view_ofs, '-3 -3 -3', '3 3 3', org, MOVE_NORMAL, self);
missile.movetype = ((autocvar_g_balance_grapplehook_gravity) ? MOVETYPE_TOSS : MOVETYPE_FLY);
PROJECTILE_MAKETRIGGER(missile);
- //setmodel (missile, "models/hook.md3"); // precision set below
+ //setmodel (missile, MDL_HOOK); // precision set below
setsize (missile, '-3 -3 -3', '3 3 3');
setorigin (missile, org);
Net_LinkEntity(missile, false, 0, GrapplingHookSend);
}
-// void GrapplingHookFrame()
-// {
-// // this function has been modified for Xonotic
-// - if (self.BUTTON_HOOK && g_grappling_hook)
-// {
-// - if (!self.hook && self.hook_time <= time && !self.button6_pressed_before)
-// - if (timeoutStatus != 2) //only allow the player to fire the grappling hook if the game is not paused (timeout)
-// - FireGrapplingHook();
-// }
-// - else
-// {
-// if (self.hook)
-// RemoveGrapplingHook(self);
-// }
-// - self.button6_pressed_before = self.BUTTON_HOOK;
-// /*
-// // if I have no hook or it's not pulling yet, make sure I'm not flying!
-// if((self.hook == world || !self.hook.state) && self.movetype == MOVETYPE_FLY)
-
-void GrapplingHookFrame()
-{
- if(g_grappling_hook && timeout_status != TIMEOUT_ACTIVE && self.weapon != WEP_HOOK.m_id && !self.vehicle)
- {
- // offhand hook controls
- if(self.BUTTON_HOOK)
- {
- if (!(self.hook || (self.hook_state & HOOK_WAITING_FOR_RELEASE)) && (time > self.hook_refire))
- {
- self.hook_state |= HOOK_FIRING;
- self.hook_state |= HOOK_WAITING_FOR_RELEASE;
- }
- }
- else
- {
- self.hook_state |= HOOK_REMOVING;
- self.hook_state &= ~HOOK_WAITING_FOR_RELEASE;
- }
-
- self.hook_state &= ~HOOK_RELEASING;
- if(self.BUTTON_CROUCH && autocvar_g_balance_grapplehook_crouchslide)
- {
- self.hook_state &= ~HOOK_PULLING;
- //self.hook_state |= HOOK_RELEASING;
- }
- else
- {
- self.hook_state |= HOOK_PULLING;
- //self.hook_state &= ~HOOK_RELEASING;
- }
- }
- else if(!g_grappling_hook && self.switchweapon != WEP_HOOK.m_id && !self.vehicle)
- {
- if(self.BUTTON_HOOK && !self.hook_switchweapon)
- W_SwitchWeapon(WEP_HOOK.m_id);
- }
- self.hook_switchweapon = self.BUTTON_HOOK;
-
- if(!g_grappling_hook && self.weapon != WEP_HOOK.m_id)
- {
- self.hook_state &= ~HOOK_FIRING;
- self.hook_state |= HOOK_REMOVING;
- }
-
- if (self.hook_state & HOOK_FIRING)
- {
- if (self.hook)
- RemoveGrapplingHook(self);
- FireGrapplingHook();
- self.hook_state &= ~HOOK_FIRING;
- self.hook_refire = max(self.hook_refire, time + autocvar_g_balance_grapplehook_refire * W_WeaponRateFactor());
- }
- else if(self.hook_state & HOOK_REMOVING)
- {
- if (self.hook)
- RemoveGrapplingHook(self);
- self.hook_state &= ~HOOK_REMOVING;
- }
-
- /*
- // if I have no hook or it's not pulling yet, make sure I'm not flying!
- if((self.hook == world || !self.hook.state) && self.movetype == MOVETYPE_FLY)
- {
- self.movetype = MOVETYPE_WALK;
- }
- if(self.impulse == GRAPHOOK_FIRE && self.hook_time <= time && g_grappling_hook)
- {
- // fire hook
- FireGrapplingHook();
- return;
- }
- else if(self.hookimpulse == GRAPHOOK_RELEASE)
- {
- // remove hook, reset movement type
- RemoveGrapplingHook(self);
- return;
- }
- */
- /*else // make sure the player's movetype is correct
- {
- //if(self.hook == world && self.movetype == MOVETYPE_FLY)
- if((self.hook == world || !self.hook.state) && self.movetype == MOVETYPE_FLY)
- {
- self.movetype = MOVETYPE_WALK;
- }
- }*/
- // note: The hook entity does the actual pulling
-}
-
void GrappleHookInit()
{
if(g_grappling_hook)
}
else
{
- WEP_ACTION(WEP_HOOK.m_id, WR_INIT);
+ Weapon w = WEP_HOOK;
+ w.wr_init(w);
hook_shotorigin[0] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK.m_id), false, false, 1);
hook_shotorigin[1] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK.m_id), false, false, 2);
hook_shotorigin[2] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK.m_id), false, false, 3);
}
void SetGrappleHookBindings()
-{
+{SELFPARAM();
// this function has been modified for Xonotic
// don't remove these lines! old server or demos coud overwrite the new aliases
stuffcmd(self, "alias +hook +button6\n");
// Wazat's grappling hook
.entity hook;
-void GrapplingHookFrame();
void RemoveGrapplingHook(entity pl);
void SetGrappleHookBindings();
// (note: you can change the hook impulse #'s to whatever you please)
else
self.light_lev = 0;
}
-void spawnfunc_dynlight()
+spawnfunc(dynlight)
{
if (!self.light_lev)
self.light_lev = 200;
.float modelscale;
void g_model_setcolormaptoactivator (void)
-{
+{SELFPARAM();
if(teamplay)
{
if(activator.team)
}
void g_clientmodel_setcolormaptoactivator (void)
-{
+{SELFPARAM();
g_model_setcolormaptoactivator();
self.SendFlags |= (8 | 1);
}
void g_clientmodel_use(void)
-{
+{SELFPARAM();
if (self.antiwall_flag == 1)
{
self.inactive = 1;
}
void g_model_dropbyspawnflags()
-{
+{SELFPARAM();
if((self.spawnflags & 3) == 1) // ALIGN_ORIGIN
{
traceline(self.origin, self.origin - '0 0 4096', MOVE_NOMONSTERS, self);
}
void g_clientmodel_dropbyspawnflags()
-{
+{SELFPARAM();
vector o0;
o0 = self.origin;
g_model_dropbyspawnflags();
self.SendFlags |= 2;
}
-float g_clientmodel_genericsendentity (entity to, int sf)
+bool g_clientmodel_genericsendentity(entity this, entity to, int sf)
{
sf = sf & 0x0F;
if(self.angles != '0 0 0')
self.default_solid = sol;
// non-solid model entities:
-void spawnfunc_misc_gamemodel() { self.angles_x = -self.angles.x; G_MODEL_INIT (SOLID_NOT) } // model entity
-void spawnfunc_misc_clientmodel() { self.angles_x = -self.angles.x; G_CLIENTMODEL_INIT(SOLID_NOT) } // model entity
-void spawnfunc_misc_models() { self.angles_x = -self.angles.x; G_MODEL_INIT (SOLID_NOT) } // DEPRECATED old compat entity with confusing name, do not use
+spawnfunc(misc_gamemodel) { self.angles_x = -self.angles.x; G_MODEL_INIT (SOLID_NOT) } // model entity
+spawnfunc(misc_clientmodel) { self.angles_x = -self.angles.x; G_CLIENTMODEL_INIT(SOLID_NOT) } // model entity
+spawnfunc(misc_models) { self.angles_x = -self.angles.x; G_MODEL_INIT (SOLID_NOT) } // DEPRECATED old compat entity with confusing name, do not use
// non-solid brush entities:
-void spawnfunc_func_illusionary() { G_MODEL_INIT (SOLID_NOT) } // Q1 name (WARNING: MISPREDICTED)
-void spawnfunc_func_clientillusionary() { G_CLIENTMODEL_INIT(SOLID_NOT) } // brush entity
-void spawnfunc_func_static() { G_MODEL_INIT (SOLID_NOT) } // DEPRECATED old alias name from some other game
+spawnfunc(func_illusionary) { G_MODEL_INIT (SOLID_NOT) } // Q1 name (WARNING: MISPREDICTED)
+spawnfunc(func_clientillusionary) { G_CLIENTMODEL_INIT(SOLID_NOT) } // brush entity
+spawnfunc(func_static) { G_MODEL_INIT (SOLID_NOT) } // DEPRECATED old alias name from some other game
// solid brush entities
-void spawnfunc_func_wall() { G_MODEL_INIT (SOLID_BSP) } // Q1 name
-void spawnfunc_func_clientwall() { G_CLIENTMODEL_INIT(SOLID_BSP) } // brush entity (WARNING: MISPREDICTED)
+spawnfunc(func_wall) { G_MODEL_INIT (SOLID_BSP) } // Q1 name
+spawnfunc(func_clientwall) { G_CLIENTMODEL_INIT(SOLID_BSP) } // brush entity (WARNING: MISPREDICTED)
#include "command/common.qh"
#include "../warpzonelib/common.qh"
-void spawnfunc_info_null (void)
+spawnfunc(info_null)
{
remove(self);
// if anything breaks, tell the mapper to fix his map! info_null is meant to remove itself immediately.
}
float LOD_customize()
-{
+{SELFPARAM();
float d;
if(autocvar_loddebug)
}
void LOD_uncustomize()
-{
+{SELFPARAM();
self.modelindex = self.lodmodelindex0;
}
void LODmodel_attach()
-{
+{SELFPARAM();
entity e;
if(!self.loddistance1)
ma = self.maxs;
precache_model(self.lodmodel1);
- setmodel(self, self.lodmodel1);
+ _setmodel(self, self.lodmodel1);
self.lodmodelindex1 = self.modelindex;
if(self.lodmodel2 != "")
{
precache_model(self.lodmodel2);
- setmodel(self, self.lodmodel2);
+ _setmodel(self, self.lodmodel2);
self.lodmodelindex2 = self.modelindex;
}
}
void ApplyMinMaxScaleAngles(entity e)
-{
+{SELFPARAM();
if(e.angles.x != 0 || e.angles.z != 0 || self.avelocity.x != 0 || self.avelocity.z != 0) // "weird" rotation
{
e.maxs = '1 1 1' * vlen(
}
void SetBrushEntityModel()
-{
+{SELFPARAM();
if(self.model != "")
{
precache_model(self.model);
{
vector mi = self.mins;
vector ma = self.maxs;
- setmodel(self, self.model); // no precision needed
+ _setmodel(self, self.model); // no precision needed
setsize(self, mi, ma);
}
else
- setmodel(self, self.model); // no precision needed
+ _setmodel(self, self.model); // no precision needed
InitializeEntity(self, LODmodel_attach, INITPRIO_FINDTARGET);
}
setorigin(self, self.origin);
}
void SetBrushEntityModelNoLOD()
-{
+{SELFPARAM();
if(self.model != "")
{
precache_model(self.model);
{
vector mi = self.mins;
vector ma = self.maxs;
- setmodel(self, self.model); // no precision needed
+ _setmodel(self, self.model); // no precision needed
setsize(self, mi, ma);
}
else
- setmodel(self, self.model); // no precision needed
+ _setmodel(self, self.model); // no precision needed
}
setorigin(self, self.origin);
ApplyMinMaxScaleAngles(self);
*/
void SetMovedir()
-{
+{SELFPARAM();
if (self.movedir != '0 0 0')
self.movedir = normalize(self.movedir);
else
}
void InitTrigger()
-{
+{SELFPARAM();
// trigger angles are used for one-way touches. An angle of 0 is assumed
// to mean no restrictions, so use a yaw of 360 instead.
SetMovedir ();
}
void InitSolidBSPTrigger()
-{
+{SELFPARAM();
// trigger angles are used for one-way touches. An angle of 0 is assumed
// to mean no restrictions, so use a yaw of 360 instead.
SetMovedir ();
}
float InitMovingBrushTrigger()
-{
+{SELFPARAM();
// trigger angles are used for one-way touches. An angle of 0 is assumed
// to mean no restrictions, so use a yaw of 360 instead.
self.solid = SOLID_BSP;
//void() SUB_UseTargets;
void() SUB_Remove;
-void spawnfunc_info_null (void);
+spawnfunc(info_null);
void setanim(entity e, vector anim, float looping, float override, float restart);
#include "g_violence.qh"
#include "_all.qh"
-float Violence_GibSplash_SendEntity(entity to, int sf)
+bool Violence_GibSplash_SendEntity(entity this, entity to, int sf)
{
WriteByte(MSG_ENTITY, ENT_CLIENT_GIBSPLASH);
WriteByte(MSG_ENTITY, self.state); // actually type
// TODO maybe convert this to a TE?
void Violence_GibSplash_At(vector org, vector dir, float type, float amount, entity gibowner, entity attacker)
-{
+{SELFPARAM();
if(g_cts) // no gibs in CTS
return;
#ifndef G_VIOLENCE_H
#define G_VIOLENCE_H
-float Violence_GibSplash_SendEntity(entity to, int sf);
+bool Violence_GibSplash_SendEntity(entity this, entity to, int sf);
// TODO maybe convert this to a TE?
void Violence_GibSplash_At(vector org, vector dir, float type, float amount, entity gibowner, entity attacker);
#include "scores.qh"
#include "teamplay.qh"
#include "weapons/weaponstats.qh"
-#include "../common/buffs.qh"
+#include "../common/buffs/all.qh"
#include "../common/constants.qh"
#include "../common/deathtypes.qh"
-#include "../common/effects.qh"
+#include "../common/effects/effects.qh"
#include "../common/mapinfo.qh"
#include "../common/monsters/all.qh"
#include "../common/monsters/sv_monsters.qh"
.float latency_time;
entity pingplreport;
void PingPLReport_Think()
-{
+{SELFPARAM();
float delta;
entity e;
}
void GotoFirstMap()
-{
+{SELFPARAM();
float n;
if(autocvar__sv_init)
{
}
entity randomseed;
-float RandomSeed_Send(entity to, int sf)
+bool RandomSeed_Send(entity this, entity to, int sf)
{
WriteByte(MSG_ENTITY, ENT_CLIENT_RANDOMSEED);
WriteShort(MSG_ENTITY, self.cnt);
return true;
}
void RandomSeed_Think()
-{
+{SELFPARAM();
self.cnt = bound(0, floor(random() * 65536), 65535);
self.nextthink = time + 5;
self.SendFlags |= 1;
}
void RandomSeed_Spawn()
-{
+{SELFPARAM();
randomseed = spawn();
randomseed.think = RandomSeed_Think;
Net_LinkEntity(randomseed, false, 0, RandomSeed_Send);
- entity oldself;
- oldself = self;
- self = randomseed;
- self.think(); // sets random seed and nextthink
- self = oldself;
+ WITH(entity, self, randomseed, randomseed.think()); // sets random seed and nextthink
}
-void spawnfunc___init_dedicated_server(void)
+spawnfunc(__init_dedicated_server)
{
// handler for _init/_init map (only for dedicated server initialization)
// needs to be done so early because of the constants they create
static_init();
- CALL_ACCUMULATED_FUNCTION(RegisterTurrets);
CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
void WeaponStats_Init();
void WeaponStats_Shutdown();
void Physics_AddStats();
-void spawnfunc_worldspawn (void)
+spawnfunc(worldspawn)
{
float fd, l, j, n;
string s;
// needs to be done so early because of the constants they create
static_init();
- CALL_ACCUMULATED_FUNCTION(RegisterTurrets);
CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
- initialize_minigames();
-
ServerProgsDB = db_load(strcat("server.db", autocvar_sessionid));
TemporaryDB = db_create();
PlayerStats_GameReport_Init(); // we need this to be initiated before InitGameplayMode
- precache_model ("null"); // we need this one before InitGameplayMode
InitGameplayMode();
readlevelcvars();
GrappleHookInit();
MUTATOR_CALLHOOK(BuildMutatorsString, s);
s = ret_string;
- // simple, probably not good in the mutator system
- if(autocvar_g_grappling_hook)
- s = strcat(s, ":grappling_hook");
-
// initialiation stuff, not good in the mutator system
if(!autocvar_g_use_ammunition)
s = strcat(s, ":no_use_ammunition");
world_initialized = 1;
}
-void spawnfunc_light (void)
+spawnfunc(light)
{
//makestatic (self); // Who the f___ did that?
remove(self);
return strcat("maps/", argv(position), ".bsp");
}
-string strwords(string s, float w)
-{
- float endpos;
- for(endpos = 0; w && endpos >= 0; --w)
- endpos = strstrofs(s, " ", endpos + 1);
- if(endpos < 0)
- return s;
- else
- return substring(s, 0, endpos);
-}
-
-float strhasword(string s, string w)
-{
- return strstrofs(strcat(" ", s, " "), strcat(" ", w, " "), 0) >= 0;
-}
-
void Map_MarkAsRecent(string m)
{
cvar_set("g_maplist_mostrecent", strwords(strcat(m, " ", autocvar_g_maplist_mostrecent), max(0, autocvar_g_maplist_mostrecent_count)));
*/
.float autoscreenshot;
void IntermissionThink()
-{
+{SELFPARAM();
FixIntermissionClient(self);
float server_screenshot = (autocvar_sv_autoscreenshot && self.cvar_cl_autoscreenshot);
============
*/
void CheckRules_Player()
-{
+{SELFPARAM();
if (gameover) // someone else quit the game already
return;
// they win. Otherwise the defending team wins once the timelimit passes.
void assault_new_round();
float WinningCondition_Assault()
-{
+{SELFPARAM();
float status;
WinningConditionHelper(); // set worldstatus
}
else
{
- entity oldself;
- oldself = self;
- self = ent;
- assault_new_round();
- self = oldself;
+ WITH(entity, self, ent, assault_new_round());
}
}
}
void EndFrame()
-{
+{SELFPARAM();
anticheat_endframe();
float altime;
- FOR_EACH_REALCLIENT(self)
+ entity e_;
+ FOR_EACH_REALCLIENT(e_)
{
- entity e = IS_SPEC(self) ? self.enemy : self;
+ entity e = IS_SPEC(e_) ? e_.enemy : e_;
if(e.typehitsound)
- self.typehit_time = time;
+ e_.typehit_time = time;
else if(e.damage_dealt)
{
- self.hit_time = time;
- self.damage_dealt_total += ceil(e.damage_dealt);
+ e_.hit_time = time;
+ e_.damage_dealt_total += ceil(e.damage_dealt);
}
}
altime = time + frametime * (1 + autocvar_g_antilag_nudge);
// add another frametime because client shows everything with
// 1 frame of lag (cl_nolerp 0). The last +1 however should not be
// needed!
- FOR_EACH_CLIENT(self)
+ FOR_EACH_CLIENT(e_)
+ {
+ e_.typehitsound = false;
+ e_.damage_dealt = 0;
+ setself(e_);
+ antilag_record(e_, altime);
+ }
+ FOR_EACH_MONSTER(e_)
{
- self.typehitsound = false;
- self.damage_dealt = 0;
- antilag_record(self, altime);
+ setself(e_);
+ antilag_record(e_, altime);
}
- FOR_EACH_MONSTER(self)
- antilag_record(self, altime);
}
float redirection_timeout;
float redirection_nextthink;
float RedirectionThink()
-{
+{SELFPARAM();
float clients_found;
if(redirection_target == "")
redirection_nextthink = time + 1;
clients_found = 0;
- FOR_EACH_REALCLIENT(self)
+ entity e;
+ FOR_EACH_REALCLIENT(e)
{
+ setself(e);
// TODO add timer
LOG_INFO("Redirecting: sending connect command to ", self.netname, "\n");
if(redirection_target == "self")
#include "generator.qh"
-bool generator_send(entity to, int sf)
+bool generator_send(entity this, entity to, int sf)
{
WriteByte(MSG_ENTITY, ENT_CLIENT_GENERATOR);
WriteByte(MSG_ENTITY, sf);
}
void generator_link(void() spawnproc)
-{
+{SELFPARAM();
Net_LinkEntity(self, true, 0, generator_send);
self.think = spawnproc;
self.nextthink = time;
const int GSF_STATUS = 4;
const int GSF_SETUP = 8;
-bool generator_send(entity to, int sf);
+bool generator_send(entity this, entity to, int sf);
#endif
}
void OnlineBanList_Think()
-{
+{SELFPARAM();
float argc;
string uri;
float i, n;
/**
* Key touch handler.
*/
-void item_key_touch(void) {
+void item_key_touch()
+{SELFPARAM();
if (!IS_PLAYER(other))
return;
/**
* Spawn a key with given model, key code and color.
*/
-void spawn_item_key() {
+void spawn_item_key()
+{SELFPARAM();
precache_model(self.model);
if (self.spawnflags & 1) // FLOATING
self.mdl = self.model;
self.effects = EF_LOWPRECISION;
- setmodel(self, self.model);
+ _setmodel(self, self.model);
//setsize(self, '-16 -16 -24', '16 16 32');
setorigin(self, self.origin + '0 0 32');
setsize(self, '-16 -16 -56', '16 16 0');
itemkeys MUST always have exactly one bit set.
*/
-void spawnfunc_item_key() {
+spawnfunc(item_key)
+{
string _netname;
vector _colormod;
self.message = strzone(strcat("You've picked up the ", self.netname, "!"));
if (self.noise == "")
- self.noise = "misc/itempickup.wav";
+ self.noise = SND(ITEMPICKUP);
// save the name for later
item_keys_names[lowestbit(self.itemkeys)] = self.netname;
---------NOTES----------
Don't use this entity on new maps! Use item_key instead.
*/
-void spawnfunc_item_key1(void) {
- self.classname = "item_key";
- self.itemkeys = ITEM_KEY_BIT(1);
- spawnfunc_item_key();
+spawnfunc(item_key1)
+{
+ this.classname = "item_key";
+ this.itemkeys = ITEM_KEY_BIT(1);
+ spawnfunc_item_key(this);
};
/*QUAKED item_key2 (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING
---------NOTES----------
Don't use this entity on new maps! Use item_key instead.
*/
-void spawnfunc_item_key2(void) {
- self.classname = "item_key";
- self.itemkeys = ITEM_KEY_BIT(0);
- spawnfunc_item_key();
+spawnfunc(item_key2)
+{
+ this.classname = "item_key";
+ this.itemkeys = ITEM_KEY_BIT(0);
+ spawnfunc_item_key(this);
};
}
string MapVote_Suggest(string m)
-{
+{SELFPARAM();
float i;
if(m == "")
return "That's not how to use this command.";
}
void MapVote_SendPicture(float id)
-{
+{SELFPARAM();
msg_entity = self;
WriteByte(MSG_ONE, SVC_TEMPENTITY);
WriteByte(MSG_ONE, TE_CSQC_PICTURE);
}
}
-float MapVote_SendEntity(entity to, int sf)
+bool MapVote_SendEntity(entity this, entity to, int sf)
{
float i;
}
string formatmessage(string msg)
-{
+{SELFPARAM();
float p, p1, p2;
float n;
vector cursor;
case "x": replacement = ((cursor_ent.netname == "" || !cursor_ent) ? "nothing" : cursor_ent.netname); break;
case "s": replacement = ftos(vlen(self.velocity - self.velocity_z * '0 0 1')); break;
case "S": replacement = ftos(vlen(self.velocity)); break;
+ case "t": replacement = seconds_tostring(ceil(max(0, autocvar_timelimit * 60 + game_starttime - time))); break;
+ case "T": replacement = seconds_tostring(floor(time - game_starttime)); break;
default:
{
MUTATOR_CALLHOOK(FormatMessage, escape, replacement, msg);
>0: receives a cvar from name=argv(f) value=argv(f+1)
*/
void GetCvars_handleString(string thisname, float f, .string field, string name)
-{
+{SELFPARAM();
if (f < 0)
{
if (self.(field))
stuffcmd(self, strcat("cl_cmd sendcvar ", name, "\n"));
}
void GetCvars_handleString_Fixup(string thisname, float f, .string field, string name, string(string) func)
-{
+{SELFPARAM();
GetCvars_handleString(thisname, f, field, name);
if (f >= 0) // also initialize to the fitting value for "" when sending cvars out
if (thisname == name)
}
}
void GetCvars_handleFloat(string thisname, float f, .float field, string name)
-{
+{SELFPARAM();
if (f < 0)
{
}
stuffcmd(self, strcat("cl_cmd sendcvar ", name, "\n"));
}
void GetCvars_handleFloatOnce(string thisname, float f, .float field, string name)
-{
+{SELFPARAM();
if (f < 0)
{
}
}
}
string W_FixWeaponOrder_ForceComplete_AndBuildImpulseList(string wo)
-{
+{SELFPARAM();
string o;
o = W_FixWeaponOrder_ForceComplete(wo);
if(self.weaponorder_byimpulse)
return o;
}
void GetCvars(float f)
-{
+{SELFPARAM();
string s = string_null;
if (f > 0)
Notification_GetCvars();
+ ReplicateVars(this, s, f);
+
GetCvars_handleFloat(s, f, autoswitch, "cl_autoswitch");
GetCvars_handleFloat(s, f, cvar_cl_autoscreenshot, "cl_autoscreenshot");
GetCvars_handleFloat(s, f, cvar_cl_jetpack_jump, "cl_jetpack_jump");
else
d = !(!weaponinfo.weaponstart);
- if(g_grappling_hook) // if possible, redirect off-hand hook to on-hand hook
- d |= (i == WEP_HOOK.m_id);
if(!g_cts && (weaponinfo.spawnflags & WEP_FLAG_MUTATORBLOCKED)) // never default mutator blocked guns
d = 0;
MUTATOR_CALLHOOK(SetStartItems);
- if ((start_items & ITEM_Jetpack.m_itemid) || (g_grappling_hook && (start_weapons & WEPSET_HOOK)))
+ if (start_items & ITEM_Jetpack.m_itemid)
{
start_items |= ITEM_JetpackRegen.m_itemid;
start_ammo_fuel = max(start_ammo_fuel, cvar("g_balance_fuel_rotstable"));
for (i = WEP_FIRST; i <= WEP_LAST; ++i)
{
e = get_weaponinfo(i);
- if(precache_weapons & WepSet_FromWeapon(i))
- WEP_ACTION(i, WR_INIT);
+ if(precache_weapons & WepSet_FromWeapon(i)) {
+ Weapon w = get_weaponinfo(i);
+ w.wr_init(w);
+ }
}
start_ammo_shells = max(0, start_ammo_shells);
return true;
}
-#undef sound
-void sound(entity e, float chan, string samp, float vol, float attenu)
-{
- if (!sound_allowed(MSG_BROADCAST, e))
- return;
- sound7(e, chan, samp, vol, attenu, 0, 0);
-}
-
void soundtoat(float _dest, entity e, vector o, float chan, string samp, float vol, float attenu)
{
float entno, idx;
if (entno >= 8192 || chan < 0 || chan > 7)
{
float idx, sflags;
- idx = precache_sound_index("misc/null.wav");
+ idx = precache_sound_index(SND(Null));
sflags = SND_LARGEENTITY;
if (idx >= 256)
sflags |= SND_LARGESOUND;
if (time > e.spamtime)
{
e.spamtime = time;
- sound(e, chan, samp, vol, _atten);
+ _sound(e, chan, samp, vol, _atten);
return true;
}
return false;
if (autocvar_bot_sound_monopoly)
return;
- sound(world, CH_INFO, samp, VOL_BASE, ATTEN_NONE);
+ _sound(world, CH_INFO, samp, VOL_BASE, ATTEN_NONE);
}
void PrecachePlayerSounds(string f);
}
void precache()
-{
+{SELFPARAM();
// gamemode related things
- precache_model ("models/misc/chatbubble.spr");
- precache_model("models/ice/ice.md3");
// Precache all player models if desired
if (autocvar_sv_precacheplayermodels)
}
// gore and miscellaneous sounds
- //precache_sound ("misc/h2ohit.wav");
- precache_model ("models/hook.md3");
- precache_sound ("misc/armorimpact.wav");
- precache_sound ("misc/bodyimpact1.wav");
- precache_sound ("misc/bodyimpact2.wav");
- precache_sound ("misc/gib.wav");
- precache_sound ("misc/gib_splat01.wav");
- precache_sound ("misc/gib_splat02.wav");
- precache_sound ("misc/gib_splat03.wav");
- precache_sound ("misc/gib_splat04.wav");
PrecacheGlobalSound((globalsound_fall = "misc/hitground 4"));
PrecacheGlobalSound((globalsound_metalfall = "misc/metalhitground 4"));
- precache_sound ("misc/null.wav");
- precache_sound ("misc/spawn.wav");
- precache_sound ("misc/talk.wav");
- precache_sound ("misc/teleport.wav");
- precache_sound ("misc/poweroff.wav");
- precache_sound ("player/lava.wav");
- precache_sound ("player/slime.wav");
-
- precache_model ("models/sprites/0.spr32");
- precache_model ("models/sprites/1.spr32");
- precache_model ("models/sprites/2.spr32");
- precache_model ("models/sprites/3.spr32");
- precache_model ("models/sprites/4.spr32");
- precache_model ("models/sprites/5.spr32");
- precache_model ("models/sprites/6.spr32");
- precache_model ("models/sprites/7.spr32");
- precache_model ("models/sprites/8.spr32");
- precache_model ("models/sprites/9.spr32");
- precache_model ("models/sprites/10.spr32");
-
- // common weapon precaches
- precache_sound (W_Sound("reload")); // until weapons have individual reload sounds, precache the reload sound here
- precache_sound (W_Sound("weapon_switch"));
- precache_sound (W_Sound("weaponpickup"));
- precache_sound (W_Sound("unavailable"));
- precache_sound (W_Sound("dryfire"));
- if (g_grappling_hook)
- {
- precache_sound (W_Sound("hook_fire")); // hook
- precache_sound (W_Sound("hook_impact")); // hook
- }
-
- precache_model("models/elaser.mdl");
- precache_model("models/laser.mdl");
- precache_model("models/ebomb.mdl");
#if 0
// Disabled this code because it simply does not work (e.g. ignores bgmvolume, overlaps with "cd loop" controlled tracks).
ambientsound ('0 0 0', self.noise, VOL_BASE, ATTEN_NONE);
}
#endif
-
-#include "precache-for-csqc.inc"
}
}
void objerror(string s)
-{
+{SELFPARAM();
make_safe_for_remove(self);
builtin_objerror(s);
}
if (!e || e.initialize_entity)
{
// make a proxy initializer entity
- entity e_old;
- e_old = e;
- e = spawn();
- e.classname = "initialize_entity";
+ entity e_old = e;
+ e = new(initialize_entity);
e.enemy = e_old;
}
}
}
void InitializeEntitiesRun()
-{
- entity startoflist;
- startoflist = initialize_entity_first;
- initialize_entity_first = world;
+{SELFPARAM();
+ entity startoflist = initialize_entity_first;
+ initialize_entity_first = NULL;
remove = remove_except_protected;
- for (self = startoflist; self; self = self.initialize_entity_next)
+ for (entity e = startoflist; e; e = e.initialize_entity_next)
{
- self.remove_except_protected_forbidden = 1;
+ e.remove_except_protected_forbidden = 1;
}
- for (self = startoflist; self; )
+ for (entity e = startoflist; e; )
{
- entity e;
- var void(void) func;
- e = self.initialize_entity_next;
- func = self.initialize_entity;
- self.initialize_entity_order = 0;
- self.initialize_entity = func_null;
- self.initialize_entity_next = world;
- self.remove_except_protected_forbidden = 0;
- if (self.classname == "initialize_entity")
+ e.remove_except_protected_forbidden = 0;
+ e.initialize_entity_order = 0;
+ entity next = e.initialize_entity_next;
+ e.initialize_entity_next = NULL;
+ var void() func = e.initialize_entity;
+ e.initialize_entity = func_null;
+ if (e.classname == "initialize_entity")
{
- entity e_old;
- e_old = self.enemy;
- builtin_remove(self);
- self = e_old;
+ entity wrappee = e.enemy;
+ builtin_remove(e);
+ e = wrappee;
+ }
+ //dprint("Delayed initialization: ", e.classname, "\n");
+ if (func)
+ {
+ WITH(entity, self, e, func());
}
- //dprint("Delayed initialization: ", self.classname, "\n");
- if(func)
- func();
else
{
- eprint(self);
- backtrace(strcat("Null function in: ", self.classname, "\n"));
+ eprint(e);
+ backtrace(strcat("Null function in: ", e.classname, "\n"));
}
- self = e;
+ e = next;
}
remove = remove_unsafely;
}
-void UncustomizeEntitiesRun()
-{
- entity oldself;
- oldself = self;
- for (self = world; (self = findfloat(self, uncustomizeentityforclient_set, 1)); )
- self.uncustomizeentityforclient();
- self = oldself;
-}
-void SetCustomizer(entity e, float(void) customizer, void(void) uncustomizer)
-{
- e.customizeentityforclient = customizer;
- e.uncustomizeentityforclient = uncustomizer;
- e.uncustomizeentityforclient_set = !!uncustomizer;
-}
-
-void Net_LinkEntity(entity e, bool docull, float dt, bool(entity, int) sendfunc)
-{
- vector mi, ma;
-
- if (e.classname == "")
- e.classname = "net_linked";
-
- if (e.model == "" || self.modelindex == 0)
- {
- mi = e.mins;
- ma = e.maxs;
- setmodel(e, "null");
- setsize(e, mi, ma);
- }
-
- e.SendEntity = sendfunc;
- e.SendFlags = 0xFFFFFF;
-
- if (!docull)
- e.effects |= EF_NODEPTHTEST;
-
- if (dt)
- {
- e.nextthink = time + dt;
- e.think = SUB_Remove;
- }
-}
-
-
.float(entity) isEliminated;
-float EliminatedPlayers_SendEntity(entity to, float sendflags)
+bool EliminatedPlayers_SendEntity(entity this, entity to, float sendflags)
{
float i, f, b;
entity e;
void adaptor_think2touch()
-{
+{SELFPARAM();
entity o;
o = other;
other = world;
}
void adaptor_think2use()
-{
+{SELFPARAM();
entity o, a;
o = other;
a = activator;
}
void adaptor_think2use_hittype_splash() // for timed projectile detonation
-{
+{SELFPARAM();
if(!(self.flags & FL_ONGROUND)) // if onground, we ARE touching something, but HITTYPE_SPLASH is to be networked if the damage causing projectile is not touching ANYTHING
self.projectiledeathtype |= HITTYPE_SPLASH;
adaptor_think2use();
// deferred dropping
void DropToFloor_Handler()
-{
+{SELFPARAM();
builtin_droptofloor();
self.dropped_origin = self.origin;
}
void droptofloor()
-{
+{SELFPARAM();
InitializeEntity(self, DropToFloor_Handler, INITPRIO_DROPTOFLOOR);
}
}
float SUB_NoImpactCheck()
-{
+{SELFPARAM();
// zero hitcontents = this is not the real impact, but either the
// mirror-impact of something hitting the projectile instead of the
// projectile hitting the something, or a touchareagrid one. Neither of
void W_Crylink_Dequeue(entity e);
float WarpZone_Projectile_Touch_ImpactFilter_Callback()
-{
+{SELFPARAM();
if(SUB_OwnerCheck())
return true;
if(SUB_NoImpactCheck())
return s;
}
-float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance)
+float MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundmax, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance)
{
float m, i;
vector start, org, delta, end, enddown, mstart;
m = e.dphitcontentsmask;
e.dphitcontentsmask = goodcontents | badcontents;
- org = world.mins;
- delta = world.maxs - world.mins;
+ org = boundmin;
+ delta = boundmax - boundmin;
start = end = org;
return false;
}
+float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance)
+{
+ return MoveToRandomLocationWithinBounds(e, world.mins, world.maxs, goodcontents, badcontents, badsurfaceflags, attempts, maxaboveground, minviewdistance);
+}
+
void write_recordmarker(entity pl, float tstart, float dt)
{
GameLogEcho(strcat(":recordset:", ftos(pl.playerid), ":", ftos(dt)));
}
vector shotorg_adjust(vector vecs, float y_is_right, float visual)
-{
+{SELFPARAM();
return shotorg_adjust_values(vecs, y_is_right, visual, self.owner.cvar_cl_gunalign);
}
.float scale2;
-float modeleffect_SendEntity(entity to, int sf)
+bool modeleffect_SendEntity(entity this, entity to, int sf)
{
float f;
WriteByte(MSG_ENTITY, ENT_CLIENT_MODELEFFECT);
float sz;
e = spawn();
e.classname = "modeleffect";
- setmodel(e, m);
+ _setmodel(e, m);
e.frame = f;
setorigin(e, o);
e.velocity = v;
#include "../common/constants.qh"
#include "../common/mapinfo.qh"
-#include "../common/turrets/turrets.qh"
+#include "../common/turrets/all.qh"
#ifdef RELEASE
#define cvar_string_normal builtin_cvar_string
#define cvar_set_normal builtin_cvar_set
.vector dropped_origin;
-.void(void) uncustomizeentityforclient;
-.float uncustomizeentityforclient_set;
.float nottargeted;
entity eliminatedPlayers;
void soundat(entity e, vector o, float chan, string samp, float vol, float _atten);
-void defer(float fdelay, void() func);
-
-void UncustomizeEntitiesRun();
void InitializeEntitiesRun();
void stopsoundto(float _dest, entity e, float chan);
string uid2name(string myuid);
+float MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundmax, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance);
+
float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance);
string NearestLocation(vector p);
sv_foginterval = cvar("sv_foginterval");
g_cloaked = cvar("g_cloaked");
g_footsteps = cvar("g_footsteps");
- g_grappling_hook = cvar("g_grappling_hook");
g_jetpack = cvar("g_jetpack");
sv_maxidle = cvar("sv_maxidle");
sv_maxidle_spectatorsareidle = cvar("sv_maxidle_spectatorsareidle");
if (!warmup_stage)
game_starttime = time + cvar("g_start_delay");
- for(int i = WEP_FIRST; i <= WEP_LAST; ++i)
- WEP_ACTION(i, WR_INIT);
+ for(int i = WEP_FIRST; i <= WEP_LAST; ++i) {
+ Weapon w = get_weaponinfo(i);
+ w.wr_init(w);
+ }
readplayerstartcvars();
}
float sound_allowed(float dest, entity e);
void InitializeEntity(entity e, void(void) func, float order);
void SetCustomizer(entity e, float(void) customizer, void(void) uncustomizer);
-void Net_LinkEntity(entity e, bool docull, float dt, bool(entity, int) sendfunc);
#endif
self.velocity = movelib_dragvec(self.velocity,0.02,0.5);
**/
vector movelib_dragvec(float drag, float exp_)
-{
+{SELFPARAM();
float lspeed,ldrag;
lspeed = vlen(self.velocity);
self.velocity = movelib_inertmove_byspeed(self.velocity,newvel,1000,0.1,0.9);
**/
vector movelib_inertmove_byspeed(vector vel_new, float vel_max,float newmin,float oldmax)
-{
+{SELFPARAM();
float influense;
influense = vlen(self.velocity) * (1 / vel_max);
}
vector movelib_inertmove(vector new_vel,float new_bias)
-{
+{SELFPARAM();
return new_vel * new_bias + self.velocity * (1-new_bias);
}
void movelib_move(vector force,float max_velocity,float drag,float theMass,float breakforce)
-{
+{SELFPARAM();
float deltatime;
float acceleration;
float mspeed;
*/
void movelib_beak_simple(float force)
-{
+{SELFPARAM();
float mspeed;
vector mdir;
float vz;
#endif
void movelib_groundalign4point(float spring_length, float spring_up, float blendrate, float _max)
-{
+{SELFPARAM();
vector a, b, c, d, e, r, push_angle, ahead, side;
push_angle.y = 0;
/** */
#define EV_PutClientInServer(i, o) \
- /** client wanting to spawn */ i(entity, self) \
+ /** client wanting to spawn */ i(entity, __self) \
/**/
MUTATOR_HOOKABLE(PutClientInServer, EV_PutClientInServer);
/** called when someone was fragged by "self", and is expected to change frag_score to adjust scoring for the kill */
#define EV_GiveFragsForKill(i, o) \
+ /**/ i(entity, __self) \
/** same as self */ i(entity, frag_attacker) \
/**/ i(entity, frag_target) \
/**/ i(float, frag_score) \
/** copies variables for spectating "other" to "self" */
#define EV_SpectateCopy(i, o) \
/**/ i(entity, other) \
- /**/ i(entity, self) \
+ /**/ i(entity, __self) \
/**/
MUTATOR_HOOKABLE(SpectateCopy, EV_SpectateCopy);
/** called every frame. customizes the waypoint for spectators */
#define EV_CustomizeWaypoint(i, o) \
- /** waypoint */ i(entity, self) \
+ /** waypoint */ i(entity, __self) \
/** player; other.enemy = spectator */ i(entity, other) \
/**/
MUTATOR_HOOKABLE(CustomizeWaypoint, EV_CustomizeWaypoint);
/** return error to request removal */
#define EV_TurretSpawn(i, o) \
- /** turret */ i(entity, self) \
+ /** turret */ i(entity, __self) \
/**/
MUTATOR_HOOKABLE(TurretSpawn, EV_TurretSpawn);
/** return error to not attack */
#define EV_TurretFire(i, o) \
- /** turret */ i(entity, self) \
+ /** turret */ i(entity, __self) \
/**/
MUTATOR_HOOKABLE(TurretFire, EV_TurretFire);
/** can edit any "just fired" projectile */
#define EV_EditProjectile(i, o) \
- /**/ i(entity, self) \
+ /**/ i(entity, __self) \
/**/ i(entity, other) \
/**/
MUTATOR_HOOKABLE(EditProjectile, EV_EditProjectile);
/**/ i(entity, other) \
/**/ o(entity, other) \
/**/
-.void() monster_loot;
+.void(entity this) monster_loot;
MUTATOR_HOOKABLE(MonsterDropItem, EV_MonsterDropItem);
/**
/** called at the end of player_powerups() in cl_client.qc, used for manipulating the values which are set by powerup items. */
#define EV_PlayerPowerups(i, o) \
- /**/ i(entity, self) \
+ /**/ i(entity, __self) \
/**/ i(int, olditems) \
/**/
int olditems;
* return 1 to make the spawnpoint unusable
*/
#define EV_Spawn_Score(i, o) \
- /** player wanting to spawn */ i(entity, self) \
+ /** player wanting to spawn */ i(entity, __self) \
/** spot to be evaluated */ i(entity, spawn_spot) \
/** _x is priority, _y is "distance" */ i(vector, spawn_score) \
/**/ o(vector, spawn_score) \
* return 1 to remove an item
*/
#define EV_Item_Spawn(i, o) \
- /** the item */ i(entity, self) \
+ /** the item */ i(entity, __self) \
/**/
MUTATOR_HOOKABLE(Item_Spawn, EV_Item_Spawn);
#define EV_SetWeaponreplace(i, o) \
- /** map entity */ i(entity, self) \
+ /** map entity */ i(entity, __self) \
/** weapon info */ i(entity, other) \
/**/ i(string, ret_string) \
/**/ o(string, ret_string) \
* allows you to strip a player of an item if they go through the teleporter to help prevent cheating
*/
#define EV_PortalTeleport(i, o) \
- /**/ i(entity, self) \
+ /**/ i(entity, __self) \
/**/
MUTATOR_HOOKABLE(PortalTeleport, EV_PortalTeleport);
* in a special manner using this hook
*/
#define EV_HelpMePing(i, o) \
- /** the player who pressed impulse 33 */ i(entity, self) \
+ /** the player who pressed impulse 33 */ i(entity, __self) \
/**/
MUTATOR_HOOKABLE(HelpMePing, EV_HelpMePing);
* return true to stop player from entering the vehicle
*/
#define EV_VehicleTouch(i, o) \
- /** vehicle */ i(entity, self) \
+ /** vehicle */ i(entity, __self) \
/** player */ i(entity, other) \
/**/
MUTATOR_HOOKABLE(VehicleTouch, EV_VehicleTouch);
/** called when a speedrun is aborted and the player is teleported back to start position */
#define EV_AbortSpeedrun(i, o) \
- /** player */ i(entity, self) \
+ /** player */ i(entity, __self) \
/**/
MUTATOR_HOOKABLE(AbortSpeedrun, EV_AbortSpeedrun);
/** called at when a item is touched. Called early, can edit item properties. */
#define EV_ItemTouch(i, o) \
- /** item */ i(entity, self) \
+ /** item */ i(entity, __self) \
/** player */ i(entity, other) \
/**/
MUTATOR_HOOKABLE(ItemTouch, EV_ItemTouch);
/** called at when a player connect */
#define EV_ClientConnect(i, o) \
- /** player */ i(entity, self) \
+ /** player */ i(entity, __self) \
/**/
MUTATOR_HOOKABLE(ClientConnect, EV_ClientConnect);
#define EV_HavocBot_ChooseRole(i, o) \
- /**/ i(entity, self) \
+ /**/ i(entity, __self) \
/**/
MUTATOR_HOOKABLE(HavocBot_ChooseRole, EV_HavocBot_ChooseRole);
/** called when a bullet has hit a target */
#define EV_FireBullet_Hit(i, o) \
- /**/ i(entity, self) \
+ /**/ i(entity, __self) \
/**/ i(entity, bullet_hit) \
/**/ i(vector, bullet_startpos) \
/**/ i(vector, bullet_endpos) \
MUTATOR_HOOKABLE(Scores_CountFragsRemaining, EV_NO_ARGS);
#define EV_GrappleHookThink(i, o) \
- /**/ i(entity, self) \
+ /**/ i(entity, __self) \
/**/ i(int, hook_tarzan) \
/**/ o(int, hook_tarzan) \
/**/ i(entity, hook_pullentity) \
MUTATOR_HOOKABLE(GrappleHookThink, EV_GrappleHookThink);
#define EV_BuffModel_Customize(i, o) \
- /**/ i(entity, self) \
+ /**/ i(entity, __self) \
/**/ i(entity, buff_player) \
/**/
entity buff_player;
/** called at when a buff is touched. Called early, can edit buff properties. */
#define EV_BuffTouch(i, o) \
- /** item */ i(entity, self) \
+ /** item */ i(entity, __self) \
/** player */ i(entity, other) \
/**/
MUTATOR_HOOKABLE(BuffTouch, EV_BuffTouch);
// random functions
void assault_objective_use()
-{
+{SELFPARAM();
// activate objective
self.health = 100;
//print("^2Activated objective ", self.targetname, "=", etos(self), "\n");
//print("Activator is ", activator.classname, "\n");
- entity oldself;
- oldself = self;
-
- for(self = world; (self = find(self, target, oldself.targetname)); )
+ for (entity e = world; (e = find(e, target, this.targetname)); )
{
- if(self.classname == "target_objective_decrease")
- target_objective_decrease_activate();
+ if (e.classname == "target_objective_decrease")
+ {
+ WITH(entity, self, e, target_objective_decrease_activate());
+ }
}
- self = oldself;
+ setself(this);
}
vector target_objective_spawn_evalfunc(entity player, entity spot, vector current)
-{
+{SELFPARAM();
if(self.health < 0 || self.health >= ASSAULT_VALUE_INACTIVE)
return '-1 0 0';
return current;
// reset this objective. Used when spawning an objective
// and when a new round starts
void assault_objective_reset()
-{
+{SELFPARAM();
self.health = ASSAULT_VALUE_INACTIVE;
}
// decrease the health of targeted objectives
void assault_objective_decrease_use()
-{
+{SELFPARAM();
if(activator.team != assault_attacker_team)
{
// wrong team triggered decrease
PlayerTeamScore_Add(activator, SP_ASSAULT_OBJECTIVES, ST_ASSAULT_OBJECTIVES, 1);
self.enemy.health = -1;
- entity oldself, oldactivator, head;
+ entity oldactivator, head;
- oldself = self;
- self = oldself.enemy;
+ setself(this.enemy);
if(self.message)
FOR_EACH_PLAYER(head)
centerprint(head, self.message);
oldactivator = activator;
- activator = oldself;
+ activator = this;
SUB_UseTargets();
activator = oldactivator;
- self = oldself;
+ setself(this);
}
}
}
void assault_setenemytoobjective()
-{
+{SELFPARAM();
entity objective;
for(objective = world; (objective = find(objective, targetname, self.target)); )
{
}
float assault_decreaser_sprite_visible(entity e)
-{
+{SELFPARAM();
entity decreaser;
decreaser = self.assault_decreaser;
}
void target_objective_decrease_activate()
-{
+{SELFPARAM();
entity ent, spr;
self.owner = world;
for(ent = world; (ent = find(ent, target, self.targetname)); )
}
void target_assault_roundend_reset()
-{
+{SELFPARAM();
//print("round end reset\n");
self.cnt = self.cnt + 1; // up round counter
self.winning = 0; // up round
}
void target_assault_roundend_use()
-{
+{SELFPARAM();
self.winning = 1; // round has been won by attackers
}
void assault_roundstart_use()
-{
+{SELFPARAM();
activator = self;
SUB_UseTargets();
- entity ent, oldself;
-
//(Re)spawn all turrets
- oldself = self;
- ent = find(world, classname, "turret_main");
- while(ent) {
+ for(entity ent = NULL; (ent = find(ent, classname, "turret_main")); ) {
// Swap turret teams
if(ent.team == NUM_TEAM_1)
ent.team = NUM_TEAM_2;
else
ent.team = NUM_TEAM_1;
- self = ent;
-
// Dubbles as teamchange
- turret_respawn();
-
- ent = find(ent, classname, "turret_main");
+ WITH(entity, self, ent, turret_respawn());
}
- self = oldself;
}
void assault_wall_think()
-{
+{SELFPARAM();
if(self.enemy.health < 0)
{
self.model = "";
void vehicles_clearreturn(entity veh);
void vehicles_spawn();
void assault_new_round()
-{
- entity oldself;
+{SELFPARAM();
//bprint("ASSAULT: new round\n");
- oldself = self;
// Eject players from vehicles
- FOR_EACH_PLAYER(self)
+ entity e;
+ FOR_EACH_PLAYER(e)
{
- if(self.vehicle)
- vehicles_exit(VHEF_RELEASE);
+ if(e.vehicle)
+ {
+ WITH(entity, self, e, vehicles_exit(VHEF_RELEASE));
+ }
}
- self = findchainflags(vehicle_flags, VHF_ISVEHICLE);
- while(self)
+ for (entity e_ = findchainflags(vehicle_flags, VHF_ISVEHICLE); e_; e_ = e_.chain)
{
+ setself(e_);
vehicles_clearreturn(self);
vehicles_spawn();
- self = self.chain;
}
- self = oldself;
+ setself(this);
// up round counter
self.winning = self.winning + 1;
}
// spawnfuncs
-void spawnfunc_info_player_attacker()
+spawnfunc(info_player_attacker)
{
if (!g_assault) { remove(self); return; }
self.team = NUM_TEAM_1; // red, gets swapped every round
- spawnfunc_info_player_deathmatch();
+ spawnfunc_info_player_deathmatch(this);
}
-void spawnfunc_info_player_defender()
+spawnfunc(info_player_defender)
{
if (!g_assault) { remove(self); return; }
self.team = NUM_TEAM_2; // blue, gets swapped every round
- spawnfunc_info_player_deathmatch();
+ spawnfunc_info_player_deathmatch(this);
}
-void spawnfunc_target_objective()
+spawnfunc(target_objective)
{
if (!g_assault) { remove(self); return; }
self.spawn_evalfunc = target_objective_spawn_evalfunc;
}
-void spawnfunc_target_objective_decrease()
+spawnfunc(target_objective_decrease)
{
if (!g_assault) { remove(self); return; }
}
// destructible walls that can be used to trigger target_objective_decrease
-void spawnfunc_func_assault_destructible()
+spawnfunc(func_assault_destructible)
{
if (!g_assault) { remove(self); return; }
else
self.team = NUM_TEAM_1;
- spawnfunc_func_breakable();
+ spawnfunc_func_breakable(this);
}
-void spawnfunc_func_assault_wall()
+spawnfunc(func_assault_wall)
{
if (!g_assault) { remove(self); return; }
self.classname = "func_assault_wall";
self.mdl = self.model;
- setmodel(self, self.mdl);
+ _setmodel(self, self.mdl);
self.solid = SOLID_BSP;
self.think = assault_wall_think;
self.nextthink = time;
InitializeEntity(self, assault_setenemytoobjective, INITPRIO_FINDTARGET);
}
-void spawnfunc_target_assault_roundend()
+spawnfunc(target_assault_roundend)
{
if (!g_assault) { remove(self); return; }
self.reset = target_assault_roundend_reset;
}
-void spawnfunc_target_assault_roundstart()
+spawnfunc(target_assault_roundstart)
{
if (!g_assault) { remove(self); return; }
// legacy bot code
void havocbot_goalrating_ast_targets(float ratingscale)
-{
+{SELFPARAM();
entity ad, best, wp, tod;
float radius, found, bestvalue;
vector p;
}
void havocbot_role_ast_offense()
-{
+{SELFPARAM();
if(self.deadflag != DEAD_NO)
{
self.havocbot_attack_time = 0;
}
void havocbot_role_ast_defense()
-{
+{SELFPARAM();
if(self.deadflag != DEAD_NO)
{
self.havocbot_attack_time = 0;
}
void havocbot_ast_reset_role(entity bot)
-{
+{SELFPARAM();
if(self.deadflag != DEAD_NO)
return;
// mutator hooks
MUTATOR_HOOKFUNCTION(assault_PlayerSpawn)
-{
+{SELFPARAM();
if(self.team == assault_attacker_team)
Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_ASSAULT_ATTACKING);
else
}
MUTATOR_HOOKFUNCTION(assault_TurretSpawn)
-{
+{SELFPARAM();
if(!self.team || self.team == MAX_SHOT_DISTANCE)
self.team = 5; // this gets reversed when match starts?
}
MUTATOR_HOOKFUNCTION(assault_VehicleSpawn)
-{
+{SELFPARAM();
self.nextthink = time + 0.5;
return false;
}
MUTATOR_HOOKFUNCTION(assault_BotRoles)
-{
+{SELFPARAM();
havocbot_ast_reset_role(self);
return true;
}
}
MUTATOR_HOOKFUNCTION(ca_PlayerSpawn)
-{
+{SELFPARAM();
self.caplayer = 1;
if(!warmup_stage)
eliminatedPlayers.SendFlags |= 1;
}
MUTATOR_HOOKFUNCTION(ca_PutClientInServer)
-{
+{SELFPARAM();
if(!allowed_to_spawn)
if(IS_PLAYER(self)) // this is true even when player is trying to join
{
}
MUTATOR_HOOKFUNCTION(ca_reset_map_players)
-{
- FOR_EACH_CLIENT(self)
+{SELFPARAM();
+ entity e;
+ FOR_EACH_CLIENT(e)
{
+ setself(e);
self.killcount = 0;
if(!self.caplayer && IS_BOT_CLIENT(self))
{
}
MUTATOR_HOOKFUNCTION(ca_ClientConnect)
-{
+{SELFPARAM();
self.classname = "observer";
return 1;
}
}
entity ca_LastPlayerForTeam()
-{
+{SELFPARAM();
entity pl, last_pl = world;
FOR_EACH_PLAYER(pl)
{
}
MUTATOR_HOOKFUNCTION(ca_PlayerDies)
-{
+{SELFPARAM();
ca_LastPlayerForTeam_Notify();
if(!allowed_to_spawn)
self.respawn_flags = RESPAWN_SILENT;
}
MUTATOR_HOOKFUNCTION(ca_ClientDisconnect)
-{
+{SELFPARAM();
if(self.caplayer == 1)
ca_LastPlayerForTeam_Notify();
return 1;
}
MUTATOR_HOOKFUNCTION(ca_MakePlayerObserver)
-{
+{SELFPARAM();
if(self.caplayer == 1)
ca_LastPlayerForTeam_Notify();
if(self.killindicator_teamchange == -2)
}
MUTATOR_HOOKFUNCTION(ca_FilterItem)
-{
+{SELFPARAM();
if(autocvar_g_powerups <= 0)
if(self.flags & FL_POWERUP)
return true;
}
bool ctf_CaptureShield_Customize()
-{
+{SELFPARAM();
if(!other.ctf_captureshielded) { return false; }
if(CTF_SAMETEAM(self, other)) { return false; }
}
void ctf_CaptureShield_Touch()
-{
+{SELFPARAM();
if(!other.ctf_captureshielded) { return; }
if(CTF_SAMETEAM(self, other)) { return; }
}
void ctf_CaptureShield_Spawn(entity flag)
-{
+{SELFPARAM();
entity shield = spawn();
shield.enemy = self;
shield.scale = 0.5;
setorigin(shield, self.origin);
- setmodel(shield, "models/ctf/shield.md3");
+ setmodel(shield, MDL_CTF_SHIELD);
setsize(shield, shield.scale * shield.mins, shield.scale * shield.maxs);
}
// messages and sounds
Send_Notification(NOTIF_ALL, world, MSG_INFO, ((flag.team) ? APP_TEAM_ENT_4(flag, INFO_CTF_LOST_) : INFO_CTF_LOST_NEUTRAL), player.netname);
- sound(flag, CH_TRIGGER, flag.snd_flag_dropped, VOL_BASE, ATTEN_NONE);
+ _sound(flag, CH_TRIGGER, flag.snd_flag_dropped, VOL_BASE, ATTEN_NONE);
ctf_EventLog("dropped", player.team, player);
// scoring
flag.ctf_status = FLAG_CARRY;
// messages and sounds
- sound(player, CH_TRIGGER, flag.snd_flag_pass, VOL_BASE, ATTEN_NORM);
+ _sound(player, CH_TRIGGER, flag.snd_flag_pass, VOL_BASE, ATTEN_NORM);
ctf_EventLog("receive", flag.team, player);
FOR_EACH_REALPLAYER(tmp_player)
flag.ctf_status = FLAG_PASSING;
// other
- sound(player, CH_TRIGGER, flag.snd_flag_touch, VOL_BASE, ATTEN_NORM);
+ _sound(player, CH_TRIGGER, flag.snd_flag_touch, VOL_BASE, ATTEN_NORM);
WarpZone_TrailParticles(world, _particleeffectnum(flag.passeffect), player.origin, targ_origin);
ctf_EventLog("pass", flag.team, player);
break;
// messages and sounds
Send_Notification(NOTIF_ONE, player, MSG_CENTER, ((enemy_flag.team) ? APP_TEAM_ENT_4(enemy_flag, CENTER_CTF_CAPTURE_) : CENTER_CTF_CAPTURE_NEUTRAL));
ctf_CaptureRecord(enemy_flag, player);
- sound(player, CH_TRIGGER, ((ctf_oneflag) ? player_team_flag.snd_flag_capture : ((DIFF_TEAM(player, flag)) ? enemy_flag.snd_flag_capture : flag.snd_flag_capture)), VOL_BASE, ATTEN_NONE);
+ _sound(player, CH_TRIGGER, ((ctf_oneflag) ? player_team_flag.snd_flag_capture : ((DIFF_TEAM(player, flag)) ? enemy_flag.snd_flag_capture : flag.snd_flag_capture)), VOL_BASE, ATTEN_NONE);
switch(capturetype)
{
Send_Notification(NOTIF_ONE, player, MSG_CENTER, APP_TEAM_ENT_4(flag, CENTER_CTF_RETURN_));
Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_4(flag, INFO_CTF_RETURN_), player.netname);
}
- sound(player, CH_TRIGGER, flag.snd_flag_returned, VOL_BASE, ATTEN_NONE);
+ _sound(player, CH_TRIGGER, flag.snd_flag_returned, VOL_BASE, ATTEN_NONE);
ctf_EventLog("return", flag.team, player);
// scoring
else
Send_Notification(NOTIF_ONE, tmp_entity, MSG_CHOICE, ((SAME_TEAM(flag, player)) ? CHOICE_CTF_PICKUP_ENEMY_TEAM : CHOICE_CTF_PICKUP_ENEMY), Team_ColorCode(player.team), player.netname);
- sound(player, CH_TRIGGER, flag.snd_flag_taken, VOL_BASE, ATTEN_NONE);
+ _sound(player, CH_TRIGGER, flag.snd_flag_taken, VOL_BASE, ATTEN_NONE);
// scoring
PlayerScore_Add(player, SP_CTF_PICKUPS, 1);
case RETURN_TIMEOUT:
{ Send_Notification(NOTIF_ALL, world, MSG_INFO, ((flag.team) ? APP_TEAM_ENT_4(flag, INFO_CTF_FLAGRETURN_TIMEOUT_) : INFO_CTF_FLAGRETURN_TIMEOUT_NEUTRAL)); break; }
}
- sound(flag, CH_TRIGGER, flag.snd_flag_respawn, VOL_BASE, ATTEN_NONE);
+ _sound(flag, CH_TRIGGER, flag.snd_flag_respawn, VOL_BASE, ATTEN_NONE);
ctf_EventLog("returned", flag.team, world);
ctf_RespawnFlag(flag);
}
}
bool ctf_Stalemate_Customize()
-{
+{SELFPARAM();
// make spectators see what the player would see
entity e, wp_owner;
e = WaypointSprite_getviewentity(other);
}
void ctf_FlagDamage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
if(ITEM_DAMAGE_NEEDKILL(deathtype))
{
if(autocvar_g_ctf_flag_return_damage_delay)
}
void ctf_FlagThink()
-{
+{SELFPARAM();
// declarations
entity tmp_entity;
self.health = 0;
ctf_CheckFlagReturn(self, RETURN_SPEEDRUN);
- tmp_entity = self;
- self = self.owner;
+ setself(self.owner);
self.impulse = CHIMPULSE_SPEEDRUN; // move the player back to the waypoint they set
ImpulseCommands();
- self = tmp_entity;
+ setself(this);
}
if(autocvar_g_ctf_stalemate)
{
}
void ctf_FlagTouch()
-{
+{SELFPARAM();
if(gameover) { return; }
if(trace_dphitcontents & (DPCONTENTS_PLAYERCLIP | DPCONTENTS_MONSTERCLIP)) { return; }
if(time > self.wait) // if we haven't in a while, play a sound/effect
{
Send_Effect_(self.toucheffect, self.origin, '0 0 0', 1);
- sound(self, CH_TRIGGER, self.snd_flag_touch, VOL_BASE, ATTEN_NORM);
+ _sound(self, CH_TRIGGER, self.snd_flag_touch, VOL_BASE, ATTEN_NORM);
self.wait = time + FLAG_TOUCHRATE;
}
return;
}
void ctf_Reset()
-{
+{SELFPARAM();
if(self.owner)
if(IS_PLAYER(self.owner))
ctf_Handle_Throw(self.owner, world, DROP_RESET);
}
void ctf_DelayedFlagSetup(void) // called after a flag is placed on a map by ctf_FlagSetup()
-{
+{SELFPARAM();
// bot waypoints
waypoint_spawnforitem_force(self, self.origin);
self.nearestwaypointtimeout = 0; // activate waypointing again
void set_flag_string(entity flag, .string field, string value, string teamname)
{
- if(flag.field == "")
- flag.field = strzone(sprintf(value,teamname));
+ if(flag.(field) == "")
+ flag.(field) = strzone(sprintf(value,teamname));
}
void ctf_FlagSetup(int teamnumber, entity flag) // called when spawning a flag entity on the map as a spawnfunc
-{
+{SELFPARAM();
// declarations
- string teamname = Static_Team_ColorName_Lower(teamnumber);
- self = flag; // for later usage with droptofloor()
+ setself(flag); // for later usage with droptofloor()
// main setup
flag.ctf_worldflagnext = ctf_worldflaglist; // link flag into ctf_worldflaglist
flag.nextthink = time + FLAG_THINKRATE;
flag.ctf_status = FLAG_BASE;
+ string teamname = Static_Team_ColorName_Lower(teamnumber);
// appearence
if(!flag.scale) { flag.scale = FLAG_SCALE; }
if(flag.skin == 0) { flag.skin = cvar(sprintf("g_ctf_flag_%s_skin", teamname)); }
set_flag_string(flag, capeffect, "%s_cap", teamname);
// sounds
- set_flag_string(flag, snd_flag_taken, "ctf/%s_taken.wav", teamname);
- set_flag_string(flag, snd_flag_returned, "ctf/%s_returned.wav", teamname);
- set_flag_string(flag, snd_flag_capture, "ctf/%s_capture.wav", teamname);
- set_flag_string(flag, snd_flag_dropped, "ctf/%s_dropped.wav", teamname);
- if(flag.snd_flag_respawn == "") { flag.snd_flag_respawn = "ctf/flag_respawn.wav"; } // if there is ever a team-based sound for this, update the code to match.
- if(flag.snd_flag_touch == "") { flag.snd_flag_touch = "ctf/touch.wav"; } // again has no team-based sound
- if(flag.snd_flag_pass == "") { flag.snd_flag_pass = "ctf/pass.wav"; } // same story here
-
- // precache
- precache_sound(flag.snd_flag_taken);
- precache_sound(flag.snd_flag_returned);
- precache_sound(flag.snd_flag_capture);
+ flag.snd_flag_taken = SND(CTF_TAKEN(teamnumber));
+ flag.snd_flag_returned = SND(CTF_RETURNED(teamnumber));
+ flag.snd_flag_capture = SND(CTF_CAPTURE(teamnumber));
+ flag.snd_flag_dropped = SND(CTF_DROPPED(teamnumber));
+ if (flag.snd_flag_respawn == "") flag.snd_flag_respawn = SND(CTF_RESPAWN); // if there is ever a team-based sound for this, update the code to match.
precache_sound(flag.snd_flag_respawn);
- precache_sound(flag.snd_flag_dropped);
+ if (flag.snd_flag_touch == "") flag.snd_flag_touch = SND(CTF_TOUCH); // again has no team-based sound
precache_sound(flag.snd_flag_touch);
+ if (flag.snd_flag_pass == "") flag.snd_flag_pass = SND(CTF_PASS); // same story here
precache_sound(flag.snd_flag_pass);
+
+ // precache
precache_model(flag.model);
- precache_model("models/ctf/shield.md3");
- precache_model("models/ctf/shockwavetransring.md3");
// appearence
- setmodel(flag, flag.model); // precision set below
+ _setmodel(flag, flag.model); // precision set below
setsize(flag, FLAG_MIN, FLAG_MAX);
setorigin(flag, (flag.origin + FLAG_SPAWN_OFFSET));
else // drop to floor, automatically find a platform and set that as spawn origin
{
flag.noalign = false;
- self = flag;
+ setself(flag);
droptofloor();
flag.movetype = MOVETYPE_TOSS;
}
}
void havocbot_goalrating_ctf_ourflag(float ratingscale)
-{
+{SELFPARAM();
entity head;
head = ctf_worldflaglist;
while (head)
}
void havocbot_goalrating_ctf_ourbase(float ratingscale)
-{
+{SELFPARAM();
entity head;
head = ctf_worldflaglist;
while (head)
}
void havocbot_goalrating_ctf_enemyflag(float ratingscale)
-{
+{SELFPARAM();
entity head;
head = ctf_worldflaglist;
while (head)
}
void havocbot_goalrating_ctf_enemybase(float ratingscale)
-{
+{SELFPARAM();
if (!bot_waypoints_for_items)
{
havocbot_goalrating_ctf_enemyflag(ratingscale);
}
void havocbot_goalrating_ctf_ourstolenflag(float ratingscale)
-{
+{SELFPARAM();
entity mf;
mf = havocbot_ctf_find_flag(self);
}
void havocbot_goalrating_ctf_carrieritems(float ratingscale, vector org, float sradius)
-{
+{SELFPARAM();
entity head;
float t;
head = findchainfloat(bot_pickup, true);
}
void havocbot_role_ctf_carrier()
-{
+{SELFPARAM();
if(self.deadflag != DEAD_NO)
{
havocbot_ctf_reset_role(self);
}
void havocbot_role_ctf_escort()
-{
+{SELFPARAM();
entity mf, ef;
if(self.deadflag != DEAD_NO)
}
void havocbot_role_ctf_offense()
-{
+{SELFPARAM();
entity mf, ef;
vector pos;
// Retriever (temporary role):
void havocbot_role_ctf_retriever()
-{
+{SELFPARAM();
entity mf;
if(self.deadflag != DEAD_NO)
}
void havocbot_role_ctf_middle()
-{
+{SELFPARAM();
entity mf;
if(self.deadflag != DEAD_NO)
}
void havocbot_role_ctf_defense()
-{
+{SELFPARAM();
entity mf;
if(self.deadflag != DEAD_NO)
// ==============
MUTATOR_HOOKFUNCTION(ctf_PlayerPreThink)
-{
+{SELFPARAM();
entity flag;
int t = 0, t2 = 0, t3 = 0;
}
MUTATOR_HOOKFUNCTION(ctf_RemovePlayer)
-{
+{SELFPARAM();
entity flag; // temporary entity for the search method
if(self.flagcarried)
}
MUTATOR_HOOKFUNCTION(ctf_PortalTeleport)
-{
+{SELFPARAM();
if(self.flagcarried)
if(!autocvar_g_ctf_portalteleport)
{ ctf_Handle_Throw(self, world, DROP_NORMAL); }
}
MUTATOR_HOOKFUNCTION(ctf_PlayerUseKey)
-{
+{SELFPARAM();
if(MUTATOR_RETURNVALUE || gameover) { return false; }
entity player = self;
}
MUTATOR_HOOKFUNCTION(ctf_HelpMePing)
-{
+{SELFPARAM();
if(self.wps_flagcarrier) // update the flagcarrier waypointsprite with "NEEDING HELP" notification
{
self.wps_helpme_time = time;
}
MUTATOR_HOOKFUNCTION(ctf_AbortSpeedrun)
-{
+{SELFPARAM();
if(self.flagcarried)
{
Send_Notification(NOTIF_ALL, world, MSG_INFO, ((self.flagcarried.team) ? APP_TEAM_ENT_4(self.flagcarried, INFO_CTF_FLAGRETURN_ABORTRUN_) : INFO_CTF_FLAGRETURN_ABORTRUN_NEUTRAL));
}
MUTATOR_HOOKFUNCTION(ctf_BotRoles)
-{
+{SELFPARAM();
havocbot_ctf_reset_role(self);
return true;
}
}
MUTATOR_HOOKFUNCTION(ctf_SpectateCopy)
-{
+{SELFPARAM();
self.ctf_flagstatus = other.ctf_flagstatus;
return false;
}
"noise3" sound played when flag is lost in the field and respawns itself...
"noise4" sound played when flag is dropped by a player...
"noise5" sound played when flag touches the ground... */
-void spawnfunc_item_flag_team1()
+spawnfunc(item_flag_team1)
{
if(!g_ctf) { remove(self); return; }
"noise3" sound played when flag is lost in the field and respawns itself...
"noise4" sound played when flag is dropped by a player...
"noise5" sound played when flag touches the ground... */
-void spawnfunc_item_flag_team2()
+spawnfunc(item_flag_team2)
{
if(!g_ctf) { remove(self); return; }
"noise3" sound played when flag is lost in the field and respawns itself...
"noise4" sound played when flag is dropped by a player...
"noise5" sound played when flag touches the ground... */
-void spawnfunc_item_flag_team3()
+spawnfunc(item_flag_team3)
{
if(!g_ctf) { remove(self); return; }
"noise3" sound played when flag is lost in the field and respawns itself...
"noise4" sound played when flag is dropped by a player...
"noise5" sound played when flag touches the ground... */
-void spawnfunc_item_flag_team4()
+spawnfunc(item_flag_team4)
{
if(!g_ctf) { remove(self); return; }
"noise3" sound played when flag is lost in the field and respawns itself...
"noise4" sound played when flag is dropped by a player...
"noise5" sound played when flag touches the ground... */
-void spawnfunc_item_flag_neutral()
+spawnfunc(item_flag_neutral)
{
if(!g_ctf) { remove(self); return; }
if(!cvar("g_ctf_oneflag")) { remove(self); return; }
Keys:
"netname" Name of the team (for example Red, Blue, Green, Yellow, Life, Death, Offense, Defense, etc)...
"cnt" Scoreboard color of the team (for example 4 is red and 13 is blue)... */
-void spawnfunc_ctf_team()
+spawnfunc(ctf_team)
{
if(!g_ctf) { remove(self); return; }
}
// compatibility for quake maps
-void spawnfunc_team_CTF_redflag() { spawnfunc_item_flag_team1(); }
-void spawnfunc_team_CTF_blueflag() { spawnfunc_item_flag_team2(); }
-void spawnfunc_team_CTF_redplayer() { spawnfunc_info_player_team1(); }
-void spawnfunc_team_CTF_blueplayer() { spawnfunc_info_player_team2(); }
-void spawnfunc_team_CTF_redspawn() { spawnfunc_info_player_team1(); }
-void spawnfunc_team_CTF_bluespawn() { spawnfunc_info_player_team2(); }
+spawnfunc(team_CTF_redflag) { spawnfunc_item_flag_team1(this); }
+spawnfunc(team_CTF_blueflag) { spawnfunc_item_flag_team2(this); }
+spawnfunc(team_CTF_redplayer) { spawnfunc_info_player_team1(this); }
+spawnfunc(team_CTF_blueplayer) { spawnfunc_info_player_team2(this); }
+spawnfunc(team_CTF_redspawn) { spawnfunc_info_player_team1(this); }
+spawnfunc(team_CTF_bluespawn) { spawnfunc_info_player_team2(this); }
-void team_CTF_neutralflag() { spawnfunc_item_flag_neutral(); }
-void team_neutralobelisk() { spawnfunc_item_flag_neutral(); }
+void team_CTF_neutralflag() { SELFPARAM(); spawnfunc_item_flag_neutral(self); }
+void team_neutralobelisk() { SELFPARAM(); spawnfunc_item_flag_neutral(self); }
// ==============
// code from here on is just to support maps that don't have flag and team entities
void ctf_SpawnTeam (string teamname, int teamcolor)
{
- entity oldself;
- oldself = self;
- self = spawn();
- self.classname = "ctf_team";
- self.netname = teamname;
- self.cnt = teamcolor;
-
- spawnfunc_ctf_team();
-
- self = oldself;
+ entity this = new(ctf_team);
+ this.netname = teamname;
+ this.cnt = teamcolor;
+ this.spawnfunc_checked = true;
+ WITH(entity, self, this, spawnfunc_ctf_team(this));
}
void ctf_DelayedInit() // Do this check with a delay so we can wait for teams to be set up.
// legacy bot roles
.float race_checkpoint;
void havocbot_role_cts()
-{
+{SELFPARAM();
if(self.deadflag != DEAD_NO)
return;
}
MUTATOR_HOOKFUNCTION(cts_PlayerPhysics)
-{
+{SELFPARAM();
// force kbd movement for fairness
float wishspeed;
vector wishvel;
}
MUTATOR_HOOKFUNCTION(cts_PlayerPreThink)
-{
+{SELFPARAM();
if(IS_SPEC(self) || IS_OBSERVER(self))
if(g_race_qualifying)
if(msg_entity.enemy.race_laptime)
}
MUTATOR_HOOKFUNCTION(cts_ClientConnect)
-{
+{SELFPARAM();
race_PreparePlayer();
self.race_checkpoint = -1;
}
MUTATOR_HOOKFUNCTION(cts_MakePlayerObserver)
-{
+{SELFPARAM();
if(PlayerScore_Add(self, SP_RACE_FASTEST, 0))
self.frags = FRAGS_LMS_LOSER;
else
}
MUTATOR_HOOKFUNCTION(cts_PlayerSpawn)
-{
+{SELFPARAM();
if(spawn_spot.target == "")
// Emergency: this wasn't a real spawnpoint. Can this ever happen?
race_PreparePlayer();
}
MUTATOR_HOOKFUNCTION(cts_PutClientInServer)
-{
+{SELFPARAM();
if(IS_PLAYER(self))
if(!gameover)
{
}
MUTATOR_HOOKFUNCTION(cts_PlayerDies)
-{
+{SELFPARAM();
self.respawn_flags |= RESPAWN_FORCE;
race_AbandonRaceCheck(self);
return false;
}
MUTATOR_HOOKFUNCTION(cts_BotRoles)
-{
+{SELFPARAM();
self.havocbot_role = havocbot_role_cts;
return true;
}
MUTATOR_HOOKFUNCTION(cts_PlayerPostThink)
-{
+{SELFPARAM();
if(self.cvar_cl_allow_uidtracking == 1 && self.cvar_cl_allow_uid2name == 1)
{
if (!self.stored_netname)
}
MUTATOR_HOOKFUNCTION(cts_FilterItem)
-{
+{SELFPARAM();
if(self.classname == "droppedweapon")
return true;
}
void dompoint_captured ()
-{
+{SELFPARAM();
entity head;
float old_delay, old_team, real_team;
if (head.noise != "")
if(self.enemy)
- sound(self.enemy, CH_TRIGGER, head.noise, VOL_BASE, ATTEN_NORM);
+ _sound(self.enemy, CH_TRIGGER, head.noise, VOL_BASE, ATTEN_NORM);
else
- sound(self, CH_TRIGGER, head.noise, VOL_BASE, ATTEN_NORM);
+ _sound(self, CH_TRIGGER, head.noise, VOL_BASE, ATTEN_NORM);
if (head.noise1 != "")
play2all(head.noise1);
}
void AnimateDomPoint()
-{
+{SELFPARAM();
if(self.pain_finished > time)
return;
self.pain_finished = time + self.t_width;
}
void dompointthink()
-{
+{SELFPARAM();
float fragamt;
self.nextthink = time + 0.1;
}
void dompointtouch()
-{
+{SELFPARAM();
entity head;
if (!IS_PLAYER(other))
return;
}
void dom_controlpoint_setup()
-{
+{SELFPARAM();
entity head;
// find the spawnfunc_dom_team representing unclaimed points
head = find(world, classname, "dom_team");
// copy important properties from spawnfunc_dom_team entity
self.goalentity = head;
- setmodel(self, head.mdl); // precision already set
+ _setmodel(self, head.mdl); // precision already set
self.skin = head.skin;
self.cnt = -1;
//go to best items, or control points you don't own
void havocbot_role_dom()
-{
+{SELFPARAM();
if(self.deadflag != DEAD_NO)
return;
}
MUTATOR_HOOKFUNCTION(dom_ResetMap)
-{
+{SELFPARAM();
total_pps = 0, pps_red = 0, pps_blue = 0, pps_yellow = 0, pps_pink = 0;
- FOR_EACH_PLAYER(self)
+ entity e;
+ FOR_EACH_PLAYER(e)
{
+ setself(e);
PutClientInServer();
self.player_blocked = 1;
if(IS_REAL_CLIENT(self))
}
MUTATOR_HOOKFUNCTION(dom_PlayerSpawn)
-{
+{SELFPARAM();
if(domination_roundbased)
if(!round_handler_IsRoundStarted())
self.player_blocked = 1;
}
MUTATOR_HOOKFUNCTION(dom_ClientConnect)
-{
+{SELFPARAM();
set_dom_state(self);
return false;
}
MUTATOR_HOOKFUNCTION(dom_BotRoles)
-{
+{SELFPARAM();
self.havocbot_role = havocbot_role_dom;
return true;
}
/*QUAKED spawnfunc_dom_controlpoint (0 .5 .8) (-16 -16 -24) (16 16 32)
Control point for Domination gameplay.
*/
-void spawnfunc_dom_controlpoint()
+spawnfunc(dom_controlpoint)
{
if(!g_domination)
{
(this is a global sound, like "Red team has captured a control point")
*/
-void spawnfunc_dom_team()
+spawnfunc(dom_team)
{
if(!g_domination || autocvar_g_domination_teams_override >= 2)
{
if (self.noise1 != "")
precache_sound(self.noise1);
self.classname = "dom_team";
- setmodel(self, self.model); // precision not needed
+ _setmodel(self, self.model); // precision not needed
self.mdl = self.model;
self.dmg = self.modelindex;
self.model = "";
// code from here on is just to support maps that don't have control point and team entities
void dom_spawnteam (string teamname, float teamcolor, string pointmodel, float pointskin, string capsound, string capnarration, string capmessage)
-{
- entity oldself;
- oldself = self;
- self = spawn();
+{SELFPARAM();
+ setself(spawn());
self.classname = "dom_team";
self.netname = teamname;
self.cnt = teamcolor;
self.message = capmessage;
// this code is identical to spawnfunc_dom_team
- setmodel(self, self.model); // precision not needed
+ _setmodel(self, self.model); // precision not needed
self.mdl = self.model;
self.dmg = self.modelindex;
self.model = "";
self.team = self.cnt + 1;
//eprint(self);
- self = oldself;
+ setself(this);
}
+void _spawnfunc_dom_controlpoint() { SELFPARAM(); spawnfunc_dom_controlpoint(self); }
void dom_spawnpoint(vector org)
-{
- entity oldself;
- oldself = self;
- self = spawn();
+{SELFPARAM();
+ setself(spawn());
self.classname = "dom_controlpoint";
- self.think = spawnfunc_dom_controlpoint;
+ self.think = _spawnfunc_dom_controlpoint;
self.nextthink = time;
setorigin(self, org);
- spawnfunc_dom_controlpoint();
- self = oldself;
+ spawnfunc_dom_controlpoint(this);
+ setself(this);
}
// spawn some default teams if the map is not set up for domination
void dom_spawnteams(float teams)
{
- dom_spawnteam("Red", NUM_TEAM_1-1, "models/domination/dom_red.md3", 0, "domination/claim.wav", "", "Red team has captured a control point");
- dom_spawnteam("Blue", NUM_TEAM_2-1, "models/domination/dom_blue.md3", 0, "domination/claim.wav", "", "Blue team has captured a control point");
+ dom_spawnteam("Red", NUM_TEAM_1-1, "models/domination/dom_red.md3", 0, SND(DOM_CLAIM), "", "Red team has captured a control point");
+ dom_spawnteam("Blue", NUM_TEAM_2-1, "models/domination/dom_blue.md3", 0, SND(DOM_CLAIM), "", "Blue team has captured a control point");
if(teams >= 3)
- dom_spawnteam("Yellow", NUM_TEAM_3-1, "models/domination/dom_yellow.md3", 0, "domination/claim.wav", "", "Yellow team has captured a control point");
+ dom_spawnteam("Yellow", NUM_TEAM_3-1, "models/domination/dom_yellow.md3", 0, SND(DOM_CLAIM), "", "Yellow team has captured a control point");
if(teams >= 4)
- dom_spawnteam("Pink", NUM_TEAM_4-1, "models/domination/dom_pink.md3", 0, "domination/claim.wav", "", "Pink team has captured a control point");
+ dom_spawnteam("Pink", NUM_TEAM_4-1, "models/domination/dom_pink.md3", 0, SND(DOM_CLAIM), "", "Pink team has captured a control point");
dom_spawnteam("", 0, "models/domination/dom_unclaimed.md3", 0, "", "", "");
}
void dom_Initialize()
{
- precache_model("models/domination/dom_red.md3");
- precache_model("models/domination/dom_blue.md3");
- precache_model("models/domination/dom_yellow.md3");
- precache_model("models/domination/dom_pink.md3");
- precache_model("models/domination/dom_unclaimed.md3");
- precache_sound("domination/claim.wav");
-
InitializeEntity(world, dom_DelayedInit, INITPRIO_GAMETYPE);
}
}
entity freezetag_LastPlayerForTeam()
-{
+{SELFPARAM();
entity pl, last_pl = world;
FOR_EACH_PLAYER(pl)
{
}
void freezetag_Add_Score(entity attacker)
-{
+{SELFPARAM();
if(attacker == self)
{
// you froze your own dumb self
}
void freezetag_Freeze(entity attacker)
-{
+{SELFPARAM();
if(self.frozen)
return;
}
void freezetag_Unfreeze(entity attacker)
-{
+{SELFPARAM();
self.freezetag_frozen_time = 0;
self.freezetag_frozen_timeout = 0;
void() havocbot_role_ft_offense;
void havocbot_goalrating_freeplayers(float ratingscale, vector org, float sradius)
-{
+{SELFPARAM();
entity head;
float distance;
}
void havocbot_role_ft_offense()
-{
+{SELFPARAM();
entity head;
float unfrozen;
}
void havocbot_role_ft_freeing()
-{
+{SELFPARAM();
if(self.deadflag != DEAD_NO)
return;
// ==============
MUTATOR_HOOKFUNCTION(freezetag_RemovePlayer)
-{
+{SELFPARAM();
self.health = 0; // neccessary to update correctly alive stats
if(!self.frozen)
freezetag_LastPlayerForTeam_Notify();
}
MUTATOR_HOOKFUNCTION(freezetag_PlayerDies)
-{
+{SELFPARAM();
if(round_handler_IsActive())
if(round_handler_CountdownRunning())
{
}
MUTATOR_HOOKFUNCTION(freezetag_PlayerSpawn)
-{
+{SELFPARAM();
if(self.freezetag_frozen_timeout == -1) // if PlayerSpawn is called by reset_map_players
return 1; // do nothing, round is starting right now
}
MUTATOR_HOOKFUNCTION(freezetag_reset_map_players)
-{
- FOR_EACH_PLAYER(self)
+{SELFPARAM();
+ entity e;
+ FOR_EACH_PLAYER(e)
{
- self.killcount = 0;
- self.freezetag_frozen_timeout = -1;
+ e.killcount = 0;
+ e.freezetag_frozen_timeout = -1;
+ setself(e);
PutClientInServer();
- self.freezetag_frozen_timeout = 0;
+ e.freezetag_frozen_timeout = 0;
}
freezetag_count_alive_players();
return 1;
}
MUTATOR_HOOKFUNCTION(freezetag_PlayerPreThink)
-{
+{SELFPARAM();
float n;
if(gameover)
}
MUTATOR_HOOKFUNCTION(freezetag_BotRoles)
-{
+{SELFPARAM();
if (!self.deadflag)
{
if (random() < 0.5)
#include "../../common/monsters/spawn.qh"
#include "../../common/monsters/sv_monsters.qh"
-void spawnfunc_invasion_spawnpoint()
+spawnfunc(invasion_spawnpoint)
{
if(!g_invasion) { remove(self); return; }
self.classname = "invasion_spawnpoint";
if(autocvar_g_invasion_zombies_only) // precache only if it hasn't been already
- if(self.monsterid)
- MON_ACTION(self.monsterid, MR_PRECACHE);
+ if(self.monsterid) {
+ Monster mon = get_monsterinfo(self.monsterid);
+ mon.mr_precache(mon);
+ }
}
float invasion_PickMonster(float supermonster_count)
}
MUTATOR_HOOKFUNCTION(invasion_MonsterDies)
-{
+{SELFPARAM();
if(!(self.spawnflags & MONSTERFLAG_RESPAWNED))
{
inv_numkilled += 1;
}
MUTATOR_HOOKFUNCTION(invasion_MonsterSpawn)
-{
+{SELFPARAM();
if(!(self.spawnflags & MONSTERFLAG_SPAWNED))
return true;
}
MUTATOR_HOOKFUNCTION(invasion_OnEntityPreSpawn)
-{
+{SELFPARAM();
if(startsWith(self.classname, "monster_"))
if(!(self.spawnflags & MONSTERFLAG_SPAWNED))
return true;
}
MUTATOR_HOOKFUNCTION(invasion_PlayerSpawn)
-{
+{SELFPARAM();
self.bot_attack = false;
return false;
}
}
MUTATOR_HOOKFUNCTION(invasion_PlayerCommand)
-{
+{SELFPARAM();
if(MUTATOR_RETURNVALUE) // command was already handled?
return false;
void invasion_Initialize()
{
- if(autocvar_g_invasion_zombies_only)
- MON_ACTION(MON_ZOMBIE.monsterid, MR_PRECACHE);
- else
+ if(autocvar_g_invasion_zombies_only) {
+ Monster mon = MON_ZOMBIE;
+ mon.mr_precache(mon);
+ } else
{
float i;
entity mon;
if((mon.spawnflags & MONSTER_TYPE_FLY) || (mon.spawnflags & MONSTER_TYPE_SWIM))
continue; // flying/swimming monsters not yet supported
- MON_ACTION(i, MR_PRECACHE);
+ mon.mr_precache(mon);
}
}
void ka_TouchEvent();
void ka_RespawnBall() // runs whenever the ball needs to be relocated
-{
+{SELFPARAM();
if(gameover) { return; }
vector oldballorigin = self.origin;
WaypointSprite_Spawn(WP_KaBall, 0, 0, self, '0 0 64', world, self.team, self, waypointsprite_attachedforcarrier, false, RADARICON_FLAGCARRIER);
WaypointSprite_Ping(self.waypointsprite_attachedforcarrier);
- sound(self, CH_TRIGGER, "keepaway/respawn.wav", VOL_BASE, ATTEN_NONE); // ATTEN_NONE (it's a sound intended to be heard anywhere)
+ sound(self, CH_TRIGGER, SND_KA_RESPAWN, VOL_BASE, ATTEN_NONE); // ATTEN_NONE (it's a sound intended to be heard anywhere)
}
void ka_TimeScoring()
-{
+{SELFPARAM();
if(self.owner.ballcarried)
{ // add points for holding the ball after a certain amount of time
if(autocvar_g_keepaway_score_timepoints)
}
void ka_TouchEvent() // runs any time that the ball comes in contact with something
-{
+{SELFPARAM();
if(gameover) { return; }
if(!self) { return; }
if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
if (!IS_PLAYER(other))
{ // The ball just touched an object, most likely the world
Send_Effect(EFFECT_BALL_SPARKS, self.origin, '0 0 0', 1);
- sound(self, CH_TRIGGER, "keepaway/touch.wav", VOL_BASE, ATTEN_NORM);
+ sound(self, CH_TRIGGER, SND_KA_TOUCH, VOL_BASE, ATTEN_NORM);
return;
}
else if(self.wait > time) { return; }
Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_KEEPAWAY_PICKUP, other.netname);
Send_Notification(NOTIF_ALL_EXCEPT, other, MSG_CENTER, CENTER_KEEPAWAY_PICKUP, other.netname);
Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_KEEPAWAY_PICKUP_SELF);
- sound(self.owner, CH_TRIGGER, "keepaway/pickedup.wav", VOL_BASE, ATTEN_NONE); // ATTEN_NONE (it's a sound intended to be heard anywhere)
+ sound(self.owner, CH_TRIGGER, SND_KA_PICKEDUP, VOL_BASE, ATTEN_NONE); // ATTEN_NONE (it's a sound intended to be heard anywhere)
// scoring
PlayerScore_Add(other, SP_KEEPAWAY_PICKUPS, 1);
ka_EventLog("dropped", plyr);
Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_KEEPAWAY_DROPPED, plyr.netname);
Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_KEEPAWAY_DROPPED, plyr.netname);
- sound(other, CH_TRIGGER, "keepaway/dropped.wav", VOL_BASE, ATTEN_NONE); // ATTEN_NONE (it's a sound intended to be heard anywhere)
+ sound(other, CH_TRIGGER, SND_KA_DROPPED, VOL_BASE, ATTEN_NONE); // ATTEN_NONE (it's a sound intended to be heard anywhere)
// scoring
// PlayerScore_Add(plyr, SP_KEEPAWAY_DROPS, 1); Not anymore, this is 100% the same as pickups and is useless.
}
void ka_Reset() // used to clear the ballcarrier whenever the match switches from warmup to normal
-{
+{SELFPARAM();
if((self.owner) && (IS_PLAYER(self.owner)))
ka_DropEvent(self.owner);
// ================
void havocbot_goalrating_ball(float ratingscale, vector org)
-{
+{SELFPARAM();
float t;
entity ball_owner;
ball_owner = ka_ball.owner;
}
void havocbot_role_ka_carrier()
-{
+{SELFPARAM();
if (self.deadflag != DEAD_NO)
return;
}
void havocbot_role_ka_collector()
-{
+{SELFPARAM();
if (self.deadflag != DEAD_NO)
return;
// ==============
MUTATOR_HOOKFUNCTION(ka_Scoring)
-{
+{SELFPARAM();
if((frag_attacker != frag_target) && (IS_PLAYER(frag_attacker)))
{
if(frag_target.ballcarried) { // add to amount of times killing carrier
}
MUTATOR_HOOKFUNCTION(ka_PlayerPreThink)
-{
+{SELFPARAM();
// clear the item used for the ball in keepaway
self.items &= ~IT_KEY1;
}
MUTATOR_HOOKFUNCTION(ka_PlayerUseKey)
-{
+{SELFPARAM();
if(MUTATOR_RETURNVALUE == 0)
if(self.ballcarried)
{
}
MUTATOR_HOOKFUNCTION(ka_RemovePlayer)
-{
+{SELFPARAM();
if(self.ballcarried) { ka_DropEvent(self); } // a player with the ball has left the match, drop it
return 0;
}
MUTATOR_HOOKFUNCTION(ka_PlayerPowerups)
-{
+{SELFPARAM();
// In the future this hook is supposed to allow me to do some extra stuff with waypointsprites and invisibility powerup
// So bare with me until I can fix a certain bug with ka_ballcarrier_waypointsprite_visible_for_player()
}
MUTATOR_HOOKFUNCTION(ka_PlayerPhysics)
-{
+{SELFPARAM();
if(self.ballcarried)
{
self.stat_sv_airspeedlimit_nonqw *= autocvar_g_keepaway_ballcarrier_highspeed;
}
MUTATOR_HOOKFUNCTION(ka_BotShouldAttack)
-{
+{SELFPARAM();
// if neither player has ball then don't attack unless the ball is on the ground
if(!checkentity.ballcarried && !self.ballcarried && ka_ball.owner)
return true;
}
MUTATOR_HOOKFUNCTION(ka_BotRoles)
-{
+{SELFPARAM();
if (self.ballcarried)
self.havocbot_role = havocbot_role_ka_carrier;
else
e = spawn();
e.model = "models/orbs/orbblue.md3";
precache_model(e.model);
- setmodel(e, e.model);
+ _setmodel(e, e.model);
setsize(e, '-16 -16 -20', '16 16 20'); // 20 20 20 was too big, player is only 16 16 24... gotta cheat with the Z (20) axis so that the particle isn't cut off
e.classname = "keepawayball";
e.damageforcescale = autocvar_g_keepawayball_damageforcescale;
if(!g_keepaway)
return;
- precache_sound("keepaway/pickedup.wav");
- precache_sound("keepaway/dropped.wav");
- precache_sound("keepaway/respawn.wav");
- precache_sound("keepaway/touch.wav");
-
ka_ScoreRules();
ka_SpawnBall();
}
.float kh_previous_owner_playerid;
.float kh_cp_duration;
-string kh_sound_capture = "kh/capture.wav";
-string kh_sound_destroy = "kh/destroy.wav";
-string kh_sound_drop = "kh/drop.wav";
-string kh_sound_collect = "kh/collect.wav";
-string kh_sound_alarm = "kh/alarm.wav"; // the new siren/alarm
-
float kh_key_dropped, kh_key_carried;
const float ST_KH_CAPS = 1;
}
float kh_KeyCarrier_waypointsprite_visible_for_player(entity e) // runs all the time
-{
+{SELFPARAM();
if(!IS_PLAYER(e) || self.team != e.team)
if(!kh_tracking_enabled)
return false;
}
float kh_Key_waypointsprite_visible_for_player(entity e) // ??
-{
+{SELFPARAM();
if(!kh_tracking_enabled)
return false;
if(!self.owner)
}
void kh_WaitForPlayers();
void kh_Controller_Think() // called a lot
-{
+{SELFPARAM();
if(intermission_running)
return;
if(self.cnt > 0)
{
if (!k.owner) continue;
entity first = WP_Null;
- FOREACH(WAYPOINTS, it.netname == k.owner.waypointsprite_attachedforcarrier.model1, LAMBDA(first = it; break));
+ FOREACH(Waypoints, it.netname == k.owner.waypointsprite_attachedforcarrier.model1, LAMBDA(first = it; break));
entity third = WP_Null;
- FOREACH(WAYPOINTS, it.netname == k.owner.waypointsprite_attachedforcarrier.model3, LAMBDA(third = it; break));
+ FOREACH(Waypoints, it.netname == k.owner.waypointsprite_attachedforcarrier.model3, LAMBDA(third = it; break));
WaypointSprite_UpdateSprites(k.owner.waypointsprite_attachedforcarrier, first, WP_KeyCarrierFinish, third);
}
}
{
if (!k.owner) continue;
entity first = WP_Null;
- FOREACH(WAYPOINTS, it.netname == k.owner.waypointsprite_attachedforcarrier.model1, LAMBDA(first = it; break));
+ FOREACH(Waypoints, it.netname == k.owner.waypointsprite_attachedforcarrier.model1, LAMBDA(first = it; break));
entity third = WP_Null;
- FOREACH(WAYPOINTS, it.netname == k.owner.waypointsprite_attachedforcarrier.model3, LAMBDA(third = it; break));
+ FOREACH(Waypoints, it.netname == k.owner.waypointsprite_attachedforcarrier.model3, LAMBDA(third = it; break));
WaypointSprite_UpdateSprites(k.owner.waypointsprite_attachedforcarrier, first, WP_KeyCarrierFriend, third);
}
}
}
void kh_Key_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
if(self.owner)
return;
if(ITEM_DAMAGE_NEEDKILL(deathtype))
void kh_Key_Collect(entity key, entity player) //a player picks up a dropped key
{
- sound(player, CH_TRIGGER, kh_sound_collect, VOL_BASE, ATTEN_NORM);
+ sound(player, CH_TRIGGER, SND_KH_COLLECT, VOL_BASE, ATTEN_NORM);
if(key.kh_dropperteam != player.team)
{
}
void kh_Key_Touch() // runs many, many times when a key has been dropped and can be picked up
-{
+{SELFPARAM();
if(intermission_running)
return;
midpoint = midpoint * (1 / kh_teams);
te_customflash(midpoint, 1000, 1, Team_ColorRGB(teem) * 0.5 + '0.5 0.5 0.5'); // make the color >=0.5 in each component
- play2all(kh_sound_capture);
+ play2all(SND(KH_CAPTURE));
kh_FinishRound();
}
Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_4(lostkey, INFO_KEYHUNT_LOST_), lostkey.kh_previous_owner.netname);
- play2all(kh_sound_destroy);
+ play2all(SND(KH_DESTROY));
te_tarexplosion(lostkey.origin);
kh_FinishRound();
}
void kh_Key_Think() // runs all the time
-{
+{SELFPARAM();
entity head;
//entity player; // needed by FOR_EACH_PLAYER
{
if(self.siren_time < time)
{
- sound(self.owner, CH_TRIGGER, kh_sound_alarm, VOL_BASE, ATTEN_NORM); // play a simple alarm
+ sound(self.owner, CH_TRIGGER, SND_KH_ALARM, VOL_BASE, ATTEN_NORM); // play a simple alarm
self.siren_time = time + 2.5; // repeat every 2.5 seconds
}
}
void key_reset()
-{
+{SELFPARAM();
kh_Key_AssignTo(self, world);
kh_Key_Remove(self);
}
key.pushltime = time + autocvar_g_balance_keyhunt_protecttime;
key.kh_dropperteam = key.team;
- sound(player, CH_TRIGGER, kh_sound_drop, VOL_BASE, ATTEN_NORM);
+ sound(player, CH_TRIGGER, SND_KH_DROP, VOL_BASE, ATTEN_NORM);
}
void kh_Key_DropAll(entity player, float suicide) // runs whenever a player dies
if(suicide)
key.kh_dropperteam = player.team;
}
- sound(player, CH_TRIGGER, kh_sound_drop, VOL_BASE, ATTEN_NORM);
+ sound(player, CH_TRIGGER, SND_KH_DROP, VOL_BASE, ATTEN_NORM);
}
}
void kh_Initialize() // sets up th KH environment
{
- precache_sound(kh_sound_capture);
- precache_sound(kh_sound_destroy);
- precache_sound(kh_sound_drop);
- precache_sound(kh_sound_collect);
- precache_sound(kh_sound_alarm); // the new siren
-
-#ifdef KH_PLAYER_USE_CARRIEDMODEL
- precache_model("models/keyhunt/key-carried.md3");
-#endif
- precache_model("models/keyhunt/key.md3");
-
// setup variables
kh_teams = autocvar_g_keyhunt_teams_override;
if(kh_teams < 2)
kh_controller.think = kh_Controller_Think;
kh_Controller_SetThink(0, kh_WaitForPlayers);
- setmodel(kh_controller, "models/keyhunt/key.md3");
+ setmodel(kh_controller, MDL_KH_KEY);
kh_key_dropped = kh_controller.modelindex;
/*
dprint(vtos(kh_controller.mins));
dprint("\n");
*/
#ifdef KH_PLAYER_USE_CARRIEDMODEL
- setmodel(kh_controller, "models/keyhunt/key-carried.md3");
+ setmodel(kh_controller, MDL_KH_KEY_CARRIED);
kh_key_carried = kh_controller.modelindex;
#else
kh_key_carried = kh_key_dropped;
// register this as a mutator
MUTATOR_HOOKFUNCTION(kh_Key_DropAll)
-{
+{SELFPARAM();
kh_Key_DropAll(self, true);
return 0;
}
MUTATOR_HOOKFUNCTION(kh_PlayerDies)
-{
+{SELFPARAM();
if(self == other)
kh_Key_DropAll(self, true);
else if(IS_PLAYER(other))
}
MUTATOR_HOOKFUNCTION(kh_SpectateCopy)
-{
+{SELFPARAM();
self.kh_state = other.kh_state;
return 0;
}
MUTATOR_HOOKFUNCTION(kh_PlayerUseKey)
-{
+{SELFPARAM();
if(MUTATOR_RETURNVALUE == 0)
{
entity k;
}
MUTATOR_HOOKFUNCTION(lms_ResetPlayers)
-{
+{SELFPARAM();
+ entity e;
if(restart_mapalreadyrestarted || (time < game_starttime))
- FOR_EACH_CLIENT(self)
- if(IS_PLAYER(self))
- PlayerScore_Add(self, SP_LMS_LIVES, LMS_NewPlayerLives());
+ FOR_EACH_CLIENT(e)
+ if(IS_PLAYER(e))
+ {
+ WITH(entity, self, e, PlayerScore_Add(e, SP_LMS_LIVES, LMS_NewPlayerLives()));
+ }
return false;
}
MUTATOR_HOOKFUNCTION(lms_PlayerPreSpawn)
-{
+{SELFPARAM();
// player is dead and becomes observer
// FIXME fix LMS scoring for new system
if(PlayerScore_Add(self, SP_LMS_RANK, 0) > 0)
}
MUTATOR_HOOKFUNCTION(lms_PlayerDies)
-{
+{SELFPARAM();
self.respawn_flags |= RESPAWN_FORCE;
return false;
}
MUTATOR_HOOKFUNCTION(lms_RemovePlayer)
-{
+{SELFPARAM();
// Only if the player cannot play at all
if(PlayerScore_Add(self, SP_LMS_RANK, 0) == 666)
self.frags = FRAGS_SPECTATOR;
}
MUTATOR_HOOKFUNCTION(lms_ClientConnect)
-{
+{SELFPARAM();
self.classname = "player";
campaign_bots_may_start = 1;
}
MUTATOR_HOOKFUNCTION(lms_PlayerThink)
-{
+{SELFPARAM();
if(self.deadflag == DEAD_DYING)
self.deadflag = DEAD_RESPAWNING;
}
MUTATOR_HOOKFUNCTION(lms_FilterItem)
-{
+{SELFPARAM();
if(autocvar_g_lms_extra_lives)
if(self.itemdef == ITEM_HealthMega)
{
}
MUTATOR_HOOKFUNCTION(lms_ItemTouch)
-{
+{SELFPARAM();
// give extra lives for mega health
if (self.items & ITEM_HealthMega.m_itemid)
{
#include "gamemode.qh"
+float autocvar_g_nexball_basketball_bouncefactor;
+float autocvar_g_nexball_basketball_bouncestop;
+float autocvar_g_nexball_basketball_carrier_highspeed;
+bool autocvar_g_nexball_basketball_meter;
+float autocvar_g_nexball_basketball_meter_maxpower;
+float autocvar_g_nexball_basketball_meter_minpower;
+float autocvar_g_nexball_delay_collect;
+float autocvar_g_nexball_delay_goal;
+float autocvar_g_nexball_delay_start;
+float autocvar_g_nexball_football_bouncefactor;
+float autocvar_g_nexball_football_bouncestop;
+bool autocvar_g_nexball_radar_showallplayers;
+bool autocvar_g_nexball_sound_bounce;
+int autocvar_g_nexball_trail_color;
+
float autocvar_g_nexball_safepass_turnrate;
float autocvar_g_nexball_safepass_maxdist;
float autocvar_g_nexball_safepass_holdtime;
}
void ball_restart(void)
-{
+{SELFPARAM();
if(self.owner)
DropBall(self, self.owner.origin, '0 0 0');
ResetBall();
}
void nexball_setstatus(void)
-{
- entity oldself;
+{SELFPARAM();
self.items &= ~IT_KEY1;
if(self.ballcarried)
{
if(self.ballcarried.teamtime && (self.ballcarried.teamtime < time))
{
bprint("The ", Team_ColoredFullName(self.team), " held the ball for too long.\n");
- oldself = self;
- self = self.ballcarried;
+ setself(self.ballcarried);
DropBall(self, self.owner.origin, '0 0 0');
ResetBall();
- self = oldself;
+ setself(this);
}
else
self.items |= IT_KEY1;
}
void relocate_nexball(void)
-{
+{SELFPARAM();
tracebox(self.origin, BALL_MINS, BALL_MAXS, self.origin, true, self);
if(trace_startsolid)
{
}
void DropOwner(void)
-{
+{SELFPARAM();
entity ownr;
ownr = self.owner;
DropBall(self, ownr.origin, ownr.velocity);
}
void GiveBall(entity plyr, entity ball)
-{
+{SELFPARAM();
entity ownr;
if((ownr = ball.owner))
ball.nextthink = time + autocvar_g_nexball_basketball_delay_hold;
}
- ownr = self;
- self = plyr;
- self.weaponentity.weapons = self.weapons;
- self.weaponentity.switchweapon = self.weapon;
- self.weapons = WEPSET_PORTO;
- WEP_ACTION(WEP_PORTO.m_id, WR_RESETPLAYER);
- self.switchweapon = WEP_PORTO.m_id;
- W_SwitchWeapon(WEP_PORTO.m_id);
- self = ownr;
+ plyr.weaponentity.weapons = plyr.weapons;
+ plyr.weaponentity.switchweapon = plyr.weapon;
+ plyr.weapons = WEPSET(NEXBALL);
+ setself(plyr);
+ Weapon w = WEP_NEXBALL;
+ w.wr_resetplayer(w);
+ plyr.switchweapon = WEP_NEXBALL.m_id;
+ W_SwitchWeapon(WEP_NEXBALL.m_id);
+ setself(this);
}
void DropBall(entity ball, vector org, vector vel)
}
void InitBall(void)
-{
+{SELFPARAM();
if(gameover) return;
self.flags &= ~FL_ONGROUND;
self.movetype = MOVETYPE_BOUNCE;
self.teamtime = 0;
self.pusher = world;
self.team = false;
- sound(self, CH_TRIGGER, self.noise1, VOL_BASE, ATTEN_NORM);
+ _sound(self, CH_TRIGGER, self.noise1, VOL_BASE, ATTEN_NORM);
WaypointSprite_Ping(self.waypointsprite_attachedforcarrier);
LogNB("init", world);
}
void ResetBall(void)
-{
+{SELFPARAM();
if(self.cnt < 2) // step 1
{
if(time == self.teamtime)
}
void football_touch(void)
-{
+{SELFPARAM();
if(other.solid == SOLID_BSP)
{
if(time > self.lastground + 0.1)
{
- sound(self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
+ _sound(self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
self.lastground = time;
}
if(vlen(self.velocity) && !self.cnt)
}
void basketball_touch(void)
-{
+{SELFPARAM();
if(other.ballcarried)
{
football_touch();
}
else if(other.solid == SOLID_BSP)
{
- sound(self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
+ _sound(self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
if(vlen(self.velocity) && !self.cnt)
self.nextthink = min(time + autocvar_g_nexball_delay_idle, self.teamtime);
}
}
void GoalTouch(void)
-{
+{SELFPARAM();
entity ball;
float isclient, pscore, otherteam;
string pname;
pscore = 1;
}
- sound(ball, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NONE);
+ _sound(ball, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NONE);
if(ball.team && pscore)
{
//=======================//
// team ents //
//=======================//
-void spawnfunc_nexball_team(void)
+spawnfunc(nexball_team)
{
if(!g_nexball)
{
//=======================//
void SpawnBall(void)
-{
+{SELFPARAM();
if(!g_nexball) { remove(self); return; }
// balls += 4; // using the remaining bits to count balls will leave more than the max edict count, so it's fine
}
precache_model(self.model);
- setmodel(self, self.model);
+ _setmodel(self, self.model);
setsize(self, BALL_MINS, BALL_MAXS);
ball_scale = self.scale;
if(!autocvar_g_nexball_sound_bounce)
self.noise = "";
else if(self.noise == "")
- self.noise = "sound/nexball/bounce.wav";
+ self.noise = SND(NB_BOUNCE);
//bounce sound placeholder (FIXME)
if(self.noise1 == "")
- self.noise1 = "sound/nexball/drop.wav";
+ self.noise1 = SND(NB_DROP);
//ball drop sound placeholder (FIXME)
if(self.noise2 == "")
- self.noise2 = "sound/nexball/steal.wav";
+ self.noise2 = SND(NB_STEAL);
//stealing sound placeholder (FIXME)
if(self.noise) precache_sound(self.noise);
precache_sound(self.noise1);
self.nextthink = game_starttime + autocvar_g_nexball_delay_start;
}
-void spawnfunc_nexball_basketball(void)
+spawnfunc(nexball_basketball)
{
nexball_mode |= NBM_BASKETBALL;
self.classname = "nexball_basketball";
SpawnBall();
}
-void spawnfunc_nexball_football(void)
+spawnfunc(nexball_football)
{
nexball_mode |= NBM_FOOTBALL;
self.classname = "nexball_football";
}
float nb_Goal_Customize()
-{
+{SELFPARAM();
entity e, wp_owner;
e = WaypointSprite_getviewentity(other);
wp_owner = self.owner;
}
void SpawnGoal(void)
-{
+{SELFPARAM();
if(!g_nexball) { remove(self); return; }
EXACTTRIGGER_INIT;
self.touch = GoalTouch;
}
-void spawnfunc_nexball_redgoal(void)
+spawnfunc(nexball_redgoal)
{
self.team = NUM_TEAM_1;
SpawnGoal();
}
-void spawnfunc_nexball_bluegoal(void)
+spawnfunc(nexball_bluegoal)
{
self.team = NUM_TEAM_2;
SpawnGoal();
}
-void spawnfunc_nexball_yellowgoal(void)
+spawnfunc(nexball_yellowgoal)
{
self.team = NUM_TEAM_3;
SpawnGoal();
}
-void spawnfunc_nexball_pinkgoal(void)
+spawnfunc(nexball_pinkgoal)
{
self.team = NUM_TEAM_4;
SpawnGoal();
}
-void spawnfunc_nexball_fault(void)
+spawnfunc(nexball_fault)
{
self.team = GOAL_FAULT;
if(self.noise == "")
- self.noise = "misc/typehit.wav";
+ self.noise = SND(TYPEHIT);
SpawnGoal();
}
-void spawnfunc_nexball_out(void)
+spawnfunc(nexball_out)
{
self.team = GOAL_OUT;
if(self.noise == "")
- self.noise = "misc/typehit.wav";
+ self.noise = SND(TYPEHIT);
SpawnGoal();
}
//Spawnfuncs preserved for compatibility
//
-void spawnfunc_ball(void)
+spawnfunc(ball)
{
- spawnfunc_nexball_football();
+ spawnfunc_nexball_football(this);
}
-void spawnfunc_ball_football(void)
+spawnfunc(ball_football)
{
- spawnfunc_nexball_football();
+ spawnfunc_nexball_football(this);
}
-void spawnfunc_ball_basketball(void)
+spawnfunc(ball_basketball)
{
- spawnfunc_nexball_basketball();
+ spawnfunc_nexball_basketball(this);
}
// The "red goal" is defended by blue team. A ball in there counts as a point for red.
-void spawnfunc_ball_redgoal(void)
+spawnfunc(ball_redgoal)
{
- spawnfunc_nexball_bluegoal(); // I blame Revenant
+ spawnfunc_nexball_bluegoal(this); // I blame Revenant
}
-void spawnfunc_ball_bluegoal(void)
+spawnfunc(ball_bluegoal)
{
- spawnfunc_nexball_redgoal(); // but he didn't mean to cause trouble :p
+ spawnfunc_nexball_redgoal(this); // but he didn't mean to cause trouble :p
}
-void spawnfunc_ball_fault(void)
+spawnfunc(ball_fault)
{
- spawnfunc_nexball_fault();
+ spawnfunc_nexball_fault(this);
}
-void spawnfunc_ball_bound(void)
+spawnfunc(ball_bound)
{
- spawnfunc_nexball_out();
+ spawnfunc_nexball_out(this);
}
//=======================//
void W_Nexball_Think()
-{
+{SELFPARAM();
//dprint("W_Nexball_Think\n");
//vector new_dir = steerlib_arrive(self.enemy.origin, 2500);
vector new_dir = normalize(self.enemy.origin + '0 0 50' - self.origin);
}
void W_Nexball_Touch(void)
-{
+{SELFPARAM();
entity ball, attacker;
attacker = self.owner;
//self.think = func_null;
if(!attacker.ballcarried)
{
LogNB("stole", attacker);
- sound(other, CH_TRIGGER, ball.noise2, VOL_BASE, ATTEN_NORM);
+ _sound(other, CH_TRIGGER, ball.noise2, VOL_BASE, ATTEN_NORM);
if(SAME_TEAM(attacker, other) && time > attacker.teamkill_complain)
{
}
void W_Nexball_Attack(float t)
-{
+{SELFPARAM();
entity ball;
float mul, mi, ma;
if(!(ball = self.ballcarried))
return;
- W_SetupShot(self, false, 4, "nexball/shoot1.wav", CH_WEAPON_A, 0);
+ W_SetupShot(self, false, 4, SND(NB_SHOOT1), CH_WEAPON_A, 0);
tracebox(w_shotorg, BALL_MINS, BALL_MAXS, w_shotorg, MOVE_WORLDONLY, world);
if(trace_startsolid)
{
}
void W_Nexball_Attack2(void)
-{
+{SELFPARAM();
if(self.ballcarried.enemy)
{
entity _ball = self.ballcarried;
- W_SetupShot(self, false, 4, "nexball/shoot1.wav", CH_WEAPON_A, 0);
+ W_SetupShot(self, false, 4, SND(NB_SHOOT1), CH_WEAPON_A, 0);
DropBall(_ball, w_shotorg, trigger_push_calculatevelocity(_ball.origin, _ball.enemy, 32));
_ball.think = W_Nexball_Think;
_ball.nextthink = time;
if(!autocvar_g_nexball_tackling)
return;
- entity missile;
- if(!(balls & BALL_BASKET))
- return;
- W_SetupShot(self, false, 2, "nexball/shoot2.wav", CH_WEAPON_A, 0);
- missile = spawn();
+ W_SetupShot(self, false, 2, SND(NB_SHOOT2), CH_WEAPON_A, 0);
+ entity missile = spawn();
missile.owner = self;
missile.classname = "ballstealer";
}
float ball_customize()
-{
+{SELFPARAM();
if(!self.owner)
{
self.effects &= ~EF_FLAME;
return true;
}
-float w_nexball_weapon(float req)
-{
- if(req == WR_THINK)
+ METHOD(BallStealer, wr_think, void(BallStealer thiswep, entity actor, bool fire1, bool fire2))
{
- if(self.BUTTON_ATCK)
- if(weapon_prepareattack(0, autocvar_g_balance_nexball_primary_refire))
+ if(fire1)
+ if(weapon_prepareattack(thiswep, actor, false, autocvar_g_balance_nexball_primary_refire))
if(autocvar_g_nexball_basketball_meter)
{
if(self.ballcarried && !self.metertime)
self.metertime = time;
else
- weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready);
+ weapon_thinkf(actor, WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready);
}
else
{
W_Nexball_Attack(-1);
- weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready);
+ weapon_thinkf(actor, WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready);
}
- if(self.BUTTON_ATCK2)
- if(weapon_prepareattack(1, autocvar_g_balance_nexball_secondary_refire))
+ if(fire2)
+ if(weapon_prepareattack(thiswep, actor, true, autocvar_g_balance_nexball_secondary_refire))
{
W_Nexball_Attack2();
- weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_nexball_secondary_animtime, w_ready);
+ weapon_thinkf(actor, WFRAME_FIRE2, autocvar_g_balance_nexball_secondary_animtime, w_ready);
}
- if(!self.BUTTON_ATCK && self.metertime && self.ballcarried)
+ if(!fire1 && self.metertime && self.ballcarried)
{
W_Nexball_Attack(time - self.metertime);
// DropBall or stealing will set metertime back to 0
- weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready);
+ weapon_thinkf(actor, WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready);
}
}
- else if(req == WR_INIT)
+ METHOD(BallStealer, wr_setup, void(BallStealer thiswep))
{
- precache_model(W_Model("g_porto.md3"));
- precache_model(W_Model("v_porto.md3"));
- precache_model(W_Model("h_porto.iqm"));
- precache_model("models/elaser.mdl");
- precache_sound("nexball/shoot1.wav");
- precache_sound("nexball/shoot2.wav");
- precache_sound("misc/typehit.wav");
+ //weapon_setup(WEP_PORTO.m_id);
}
- else if(req == WR_SETUP)
+ METHOD(BallStealer, wr_checkammo1, bool(BallStealer thiswep))
{
- //weapon_setup(WEP_PORTO.m_id);
+ return true;
+ }
+ METHOD(BallStealer, wr_checkammo2, bool(BallStealer thiswep))
+ {
+ return true;
}
- // No need to check WR_CHECKAMMO* or WR_AIM, it should always return true
- return true;
-}
MUTATOR_HOOKFUNCTION(nexball_BallDrop)
-{
+{SELFPARAM();
if(self.ballcarried && g_nexball)
DropBall(self.ballcarried, self.origin, self.velocity);
}
MUTATOR_HOOKFUNCTION(nexball_PlayerPreThink)
-{
+{SELFPARAM();
makevectors(self.v_angle);
if(nexball_mode & NBM_BASKETBALL)
{
if(self.weaponentity.weapons)
{
self.weapons = self.weaponentity.weapons;
- WEP_ACTION(WEP_PORTO.m_id, WR_RESETPLAYER);
+ Weapon w = WEP_NEXBALL;
+ w.wr_resetplayer(w);
self.switchweapon = self.weaponentity.switchweapon;
W_SwitchWeapon(self.switchweapon);
}
MUTATOR_HOOKFUNCTION(nexball_PlayerSpawn)
-{
+{SELFPARAM();
self.weaponentity.weapons = '0 0 0';
if(nexball_mode & NBM_BASKETBALL)
- self.weapons |= WEPSET_PORTO;
+ self.weapons |= WEPSET(NEXBALL);
else
self.weapons = '0 0 0';
}
MUTATOR_HOOKFUNCTION(nexball_PlayerPhysics)
-{
+{SELFPARAM();
if(self.ballcarried)
{
self.stat_sv_airspeedlimit_nonqw *= autocvar_g_nexball_basketball_carrier_highspeed;
return false;
}
-MUTATOR_HOOKFUNCTION(nexball_SetStartItems)
-{
- start_items |= IT_UNLIMITED_SUPERWEAPONS; // FIXME BAD BAD BAD BAD HACK, NEXBALL SHOULDN'T ABUSE PORTO'S WEAPON SLOT
-
- return false;
-}
-
MUTATOR_HOOKFUNCTION(nexball_ForbidThrowing)
-{
- if(self.weapon == WEP_MORTAR.m_id)
+{SELFPARAM();
+ if(self.weapon == WEP_NEXBALL.m_id)
return true;
return false;
}
MUTATOR_HOOKFUNCTION(nexball_FilterItem)
-{
+{SELFPARAM();
if(self.classname == "droppedweapon")
- if(self.weapon == WEP_MORTAR.m_id)
+ if(self.weapon == WEP_NEXBALL.m_id)
return true;
return false;
MUTATOR_HOOK(PlayerSpawn, nexball_PlayerSpawn, CBC_ORDER_ANY);
MUTATOR_HOOK(PlayerPreThink, nexball_PlayerPreThink, CBC_ORDER_ANY);
MUTATOR_HOOK(PlayerPhysics, nexball_PlayerPhysics, CBC_ORDER_ANY);
- MUTATOR_HOOK(SetStartItems, nexball_SetStartItems, CBC_ORDER_ANY);
MUTATOR_HOOK(ForbidThrowCurrentWeapon, nexball_ForbidThrowing, CBC_ORDER_ANY);
MUTATOR_HOOK(FilterItem, nexball_FilterItem, CBC_ORDER_ANY);
radar_showennemies = autocvar_g_nexball_radar_showallplayers;
InitializeEntity(world, nb_delayedinit, INITPRIO_GAMETYPE);
+ WEP_NEXBALL.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
}
MUTATOR_ONROLLBACK_OR_REMOVE
{
+ WEP_NEXBALL.spawnflags |= WEP_FLAG_MUTATORBLOCKED;
// we actually cannot roll back nb_delayedinit here
// BUT: we don't need to! If this gets called, adding always
// succeeds.
--- /dev/null
+#ifndef GAMEMODE_NEXBALL_WEAPON_H
+#define GAMEMODE_NEXBALL_WEAPON_H
+
+CLASS(BallStealer, PortoLaunch)
+/* flags */ ATTRIB(BallStealer, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse */ ATTRIB(BallStealer, impulse, int, 0);
+/* refname */ ATTRIB(BallStealer, netname, string, "ballstealer");
+/* wepname */ ATTRIB(BallStealer, message, string, _("Ball Stealer"));
+ENDCLASS(BallStealer)
+REGISTER_WEAPON(NEXBALL, NEW(BallStealer));
+
+#endif
// =======================
bool ons_CaptureShield_Customize()
-{
+{SELFPARAM();
entity e = WaypointSprite_getviewentity(other);
if(!self.enemy.isshielded && (ons_ControlPoint_Attackable(self.enemy, e.team) > 0 || self.enemy.classname != "onslaught_controlpoint")) { return false; }
}
void ons_CaptureShield_Touch()
-{
+{SELFPARAM();
if(!self.enemy.isshielded && (ons_ControlPoint_Attackable(self.enemy, other.team) > 0 || self.enemy.classname != "onslaught_controlpoint")) { return; }
if(!IS_PLAYER(other)) { return; }
if(SAME_TEAM(other, self)) { return; }
if(IS_REAL_CLIENT(other))
{
- play2(other, "onslaught/damageblockedbyshield.wav");
+ play2(other, SND(ONS_DAMAGEBLOCKEDBYSHIELD));
if(self.enemy.classname == "onslaught_generator")
Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_ONS_GENERATOR_SHIELDED);
}
void ons_CaptureShield_Reset()
-{
+{SELFPARAM();
self.colormap = self.enemy.colormap;
self.team = self.enemy.team;
}
precache_model(shield.model);
setorigin(shield, generator.origin);
- setmodel(shield, shield.model);
+ _setmodel(shield, shield.model);
setsize(shield, shield.scale * shield.mins, shield.scale * shield.maxs);
}
}
}
-void setmodel_fixsize(entity e, string m)
+void setmodel_fixsize(entity e, Model m)
{
setmodel(e, m);
FixSize(e);
// Main Link Functions
// ===================
-bool ons_Link_Send(entity to, int sendflags)
+bool ons_Link_Send(entity this, entity to, int sendflags)
{
WriteByte(MSG_ENTITY, ENT_CLIENT_RADARLINK);
WriteByte(MSG_ENTITY, sendflags);
}
void ons_Link_CheckUpdate()
-{
+{SELFPARAM();
// TODO check if the two sides have moved (currently they won't move anyway)
float cc = 0, cc1 = 0, cc2 = 0;
}
void ons_DelayedLinkSetup()
-{
+{SELFPARAM();
self.goalentity = find(world, targetname, self.target);
self.enemy = find(world, targetname, self.target2);
if(!self.goalentity) { objerror("can not find target\n"); }
}
void ons_ControlPoint_Icon_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
- entity oself;
-
+{SELFPARAM();
if(damage <= 0) { return; }
if (self.owner.isshielded)
if (time > self.pain_finished)
if (IS_PLAYER(attacker))
{
- play2(attacker, "onslaught/damageblockedbyshield.wav");
+ play2(attacker, SND(ONS_DAMAGEBLOCKEDBYSHIELD));
self.pain_finished = time + 1;
attacker.typehitsound += 1; // play both sounds (shield is way too quiet)
}
if(IS_PLAYER(attacker))
if(time - ons_notification_time[self.team] > 10)
{
- play2team(self.team, "onslaught/controlpoint_underattack.wav");
+ play2team(self.team, SND(ONS_CONTROLPOINT_UNDERATTACK));
ons_notification_time[self.team] = time;
}
pointparticles(particleeffectnum(EFFECT_SPARKS), hitloc, force*-1, 1);
//sound on every hit
if (random() < 0.5)
- sound(self, CH_TRIGGER, "onslaught/ons_hit1.wav", VOL_BASE+0.3, ATTEN_NORM);
+ sound(self, CH_TRIGGER, SND_ONS_HIT1, VOL_BASE+0.3, ATTEN_NORM);
else
- sound(self, CH_TRIGGER, "onslaught/ons_hit2.wav", VOL_BASE+0.3, ATTEN_NORM);
+ sound(self, CH_TRIGGER, SND_ONS_HIT2, VOL_BASE+0.3, ATTEN_NORM);
if (self.health < 0)
{
- sound(self, CH_TRIGGER, W_Sound("grenade_impact"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_TRIGGER, SND_GRENADE_IMPACT, VOL_BASE, ATTEN_NORM);
pointparticles(particleeffectnum(EFFECT_ROCKET_EXPLODE), self.origin, '0 0 0', 1);
Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_NUM_4(self.team, INFO_ONSLAUGHT_CPDESTROYED_), self.owner.message, attacker.netname);
onslaught_updatelinks();
// Use targets now (somebody make sure this is in the right place..)
- oself = self;
- self = self.owner;
+ setself(self.owner);
activator = self;
SUB_UseTargets ();
- self = oself;
+ setself(this);
self.owner.waslinked = self.owner.islinked;
if(self.owner.model != "models/onslaught/controlpoint_pad.md3")
- setmodel_fixsize(self.owner, "models/onslaught/controlpoint_pad.md3");
+ setmodel_fixsize(self.owner, MDL_ONS_CP_PAD1);
//setsize(self, '-32 -32 0', '32 32 8');
remove(self);
}
void ons_ControlPoint_Icon_Think()
-{
- entity oself;
+{SELFPARAM();
self.nextthink = time + ONS_CP_THINKRATE;
if(autocvar_g_onslaught_cp_proxydecap)
if(!self.owner.islinked)
self.owner.team = 0;
- oself = self;
- self = self.owner;
+ setself(self.owner);
activator = self;
SUB_UseTargets ();
- self = oself;
+ setself(this);
self.owner.team = t;
Send_Effect(EFFECT_ELECTRIC_SPARKS, self.origin + randompos('-10 -10 -20', '10 10 20'), '0 0 0', 1);
if(random() > 0.8)
- sound(self, CH_PAIN, "onslaught/ons_spark1.wav", VOL_BASE, ATTEN_NORM);
+ sound(self, CH_PAIN, SND_ONS_SPARK1, VOL_BASE, ATTEN_NORM);
else if (random() > 0.5)
- sound(self, CH_PAIN, "onslaught/ons_spark2.wav", VOL_BASE, ATTEN_NORM);
+ sound(self, CH_PAIN, SND_ONS_SPARK2, VOL_BASE, ATTEN_NORM);
}
}
void ons_ControlPoint_Icon_BuildThink()
-{
- entity oself;
+{SELFPARAM();
int a;
self.nextthink = time + ONS_CP_THINKRATE;
self.health = self.max_health;
self.count = autocvar_g_onslaught_cp_regen * ONS_CP_THINKRATE; // slow repair rate from now on
self.think = ons_ControlPoint_Icon_Think;
- sound(self, CH_TRIGGER, "onslaught/controlpoint_built.wav", VOL_BASE, ATTEN_NORM);
+ sound(self, CH_TRIGGER, SND_ONS_CONTROLPOINT_BUILT, VOL_BASE, ATTEN_NORM);
self.owner.iscaptured = true;
self.solid = SOLID_BBOX;
- Send_Effect_(sprintf("%s_cap", Static_Team_ColorName_Lower(self.owner.team)), self.owner.origin, '0 0 0', 1);
+ Send_Effect(EFFECT_CAP(self.owner.team), self.owner.origin, '0 0 0', 1);
WaypointSprite_UpdateMaxHealth(self.owner.sprite, self.max_health);
WaypointSprite_UpdateHealth(self.owner.sprite, self.health);
onslaught_updatelinks();
// Use targets now (somebody make sure this is in the right place..)
- oself = self;
- self = self.owner;
+ setself(self.owner);
activator = self;
SUB_UseTargets ();
- self = oself;
+ setself(this);
self.SendFlags |= CPSF_SETUP;
}
- if(self.owner.model != "models/onslaught/controlpoint_pad2.md3")
- setmodel_fixsize(self.owner, "models/onslaught/controlpoint_pad2.md3");
+ if(self.owner.model != MDL_ONS_CP_PAD2.model_str())
+ setmodel_fixsize(self.owner, MDL_ONS_CP_PAD2);
if(random() < 0.9 - self.health / self.max_health)
Send_Effect(EFFECT_RAGE, self.origin + 10 * randomvec(), '0 0 -1', 1);
e.colormap = 1024 + (e.team - 1) * 17;
e.count = (e.max_health - e.health) * ONS_CP_THINKRATE / autocvar_g_onslaught_cp_buildtime; // how long it takes to build
- sound(e, CH_TRIGGER, "onslaught/controlpoint_build.wav", VOL_BASE, ATTEN_NORM);
+ sound(e, CH_TRIGGER, SND_ONS_CONTROLPOINT_BUILD, VOL_BASE, ATTEN_NORM);
cp.goalentity = e;
cp.team = e.team;
cp.colormap = e.colormap;
- Send_Effect_(sprintf("%sflag_touch", Static_Team_ColorName_Lower(player.team)), e.origin, '0 0 0', 1);
+ Send_Effect(EFFECT_FLAG_TOUCH(player.team), e.origin, '0 0 0', 1);
WaypointSprite_UpdateBuildFinished(cp.sprite, time + (e.max_health - e.health) / (e.count / ONS_CP_THINKRATE));
WaypointSprite_UpdateRule(cp.sprite,cp.team,SPRITERULE_TEAMPLAY);
}
void ons_ControlPoint_Touch()
-{
+{SELFPARAM();
entity toucher = other;
int attackable;
}
void ons_ControlPoint_Think()
-{
+{SELFPARAM();
self.nextthink = time + ONS_CP_THINKRATE;
- CSQCMODEL_AUTOUPDATE();
+ CSQCMODEL_AUTOUPDATE(self);
}
void ons_ControlPoint_Reset()
-{
+{SELFPARAM();
if(self.goalentity)
remove(self.goalentity);
self.think = ons_ControlPoint_Think;
self.ons_toucher = world;
self.nextthink = time + ONS_CP_THINKRATE;
- setmodel_fixsize(self, "models/onslaught/controlpoint_pad.md3");
+ setmodel_fixsize(self, MDL_ONS_CP_PAD1);
WaypointSprite_UpdateMaxHealth(self.sprite, 0);
WaypointSprite_UpdateRule(self.sprite,self.team,SPRITERULE_TEAMPLAY);
activator = self;
SUB_UseTargets(); // to reset the structures, playerspawns etc.
- CSQCMODEL_AUTOUPDATE();
+ CSQCMODEL_AUTOUPDATE(self);
}
void ons_DelayedControlPoint_Setup(void)
-{
+{SELFPARAM();
onslaught_updatelinks();
// captureshield setup
ons_CaptureShield_Spawn(self, false);
- CSQCMODEL_AUTOINIT();
+ CSQCMODEL_AUTOINIT(self);
}
void ons_ControlPoint_Setup(entity cp)
-{
+{SELFPARAM();
// declarations
- self = cp; // for later usage with droptofloor()
+ setself(cp); // for later usage with droptofloor()
// main setup
cp.ons_worldcpnext = ons_worldcplist; // link control point into ons_worldcplist
if(cp.message == "") { cp.message = "a"; }
- // precache - TODO: clean up!
- precache_model("models/onslaught/controlpoint_pad.md3");
- precache_model("models/onslaught/controlpoint_pad2.md3");
- precache_model("models/onslaught/controlpoint_shield.md3");
- precache_model("models/onslaught/controlpoint_icon.md3");
- precache_model("models/onslaught/controlpoint_icon_dmg1.md3");
- precache_model("models/onslaught/controlpoint_icon_dmg2.md3");
- precache_model("models/onslaught/controlpoint_icon_dmg3.md3");
- precache_model("models/onslaught/controlpoint_icon_gib1.md3");
- precache_model("models/onslaught/controlpoint_icon_gib2.md3");
- precache_model("models/onslaught/controlpoint_icon_gib4.md3");
- precache_sound("onslaught/controlpoint_build.wav");
- precache_sound("onslaught/controlpoint_built.wav");
- precache_sound(W_Sound("grenade_impact"));
- precache_sound("onslaught/damageblockedbyshield.wav");
- precache_sound("onslaught/controlpoint_underattack.wav");
- precache_sound("onslaught/ons_spark1.wav");
- precache_sound("onslaught/ons_spark2.wav");
-
// appearence
- setmodel_fixsize(cp, "models/onslaught/controlpoint_pad.md3");
+ setmodel_fixsize(cp, MDL_ONS_CP_PAD1);
// control point placement
if((cp.spawnflags & 1) || cp.noalign) // don't drop to floor, just stay at fixed location
{
setorigin(cp, cp.origin + '0 0 20');
cp.noalign = false;
- self = cp;
+ setself(cp);
droptofloor();
cp.movetype = MOVETYPE_TOSS;
}
}
void ons_GeneratorDamage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
if(damage <= 0) { return; }
if(warmup_stage || gameover) { return; }
if(!round_handler_IsRoundStarted()) { return; }
if (time > self.pain_finished)
if (IS_PLAYER(attacker))
{
- play2(attacker, "onslaught/damageblockedbyshield.wav");
+ play2(attacker, SND(ONS_DAMAGEBLOCKEDBYSHIELD));
attacker.typehitsound += 1;
self.pain_finished = time + 1;
}
self.pain_finished = time + 10;
entity head;
FOR_EACH_REALPLAYER(head) if(SAME_TEAM(head, self)) { Send_Notification(NOTIF_ONE, head, MSG_CENTER, CENTER_GENERATOR_UNDERATTACK); }
- play2team(self.team, "onslaught/generator_underattack.wav");
+ play2team(self.team, SND(ONS_GENERATOR_UNDERATTACK));
}
}
self.health = self.health - damage;
// Throw some flaming gibs on damage, more damage = more chance for gib
if(random() < damage/220)
{
- sound(self, CH_TRIGGER, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_TRIGGER, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
}
else
{
//sound on every hit
if (random() < 0.5)
- sound(self, CH_TRIGGER, "onslaught/ons_hit1.wav", VOL_BASE, ATTEN_NORM);
+ sound(self, CH_TRIGGER, SND_ONS_HIT1, VOL_BASE, ATTEN_NORM);
else
- sound(self, CH_TRIGGER, "onslaught/ons_hit2.wav", VOL_BASE, ATTEN_NORM);
+ sound(self, CH_TRIGGER, SND_ONS_HIT2, VOL_BASE, ATTEN_NORM);
}
self.SendFlags |= GSF_STATUS;
}
void ons_GeneratorThink()
-{
+{SELFPARAM();
entity e;
self.nextthink = time + GEN_THINKRATE;
if (!gameover)
if(SAME_TEAM(e, self))
{
Send_Notification(NOTIF_ONE, e, MSG_CENTER, CENTER_ONS_NOTSHIELDED_TEAM);
- soundto(MSG_ONE, e, CHAN_AUTO, "kh/alarm.wav", VOL_BASE, ATTEN_NONE); // FIXME: unique sound?
+ soundto(MSG_ONE, e, CHAN_AUTO, SND(KH_ALARM), VOL_BASE, ATTEN_NONE); // FIXME: unique sound?
}
else
Send_Notification(NOTIF_ONE, e, MSG_CENTER, APP_TEAM_NUM_4(self.team, CENTER_ONS_NOTSHIELDED_));
}
void ons_GeneratorReset()
-{
+{SELFPARAM();
self.team = self.team_saved;
self.lasthealth = self.max_health = self.health = autocvar_g_onslaught_gen_health;
self.takedamage = DAMAGE_AIM;
}
void ons_DelayedGeneratorSetup()
-{
+{SELFPARAM();
// bot waypoints
waypoint_spawnforitem_force(self, self.origin);
self.nearestwaypointtimeout = 0; // activate waypointing again
void onslaught_generator_touch()
-{
+{SELFPARAM();
if ( IS_PLAYER(other) )
if ( SAME_TEAM(self,other) )
if ( self.iscaptured )
}
void ons_GeneratorSetup(entity gen) // called when spawning a generator entity on the map as a spawnfunc
-{
+{SELFPARAM();
// declarations
int teamnumber = gen.team;
- self = gen; // for later usage with droptofloor()
+ setself(gen); // for later usage with droptofloor()
// main setup
gen.ons_worldgeneratornext = ons_worldgeneratorlist; // link generator into ons_worldgeneratorlist
gen.isshielded = true;
gen.touch = onslaught_generator_touch;
- // precache - TODO: clean up!
- precache_model("models/onslaught/generator_shield.md3");
- precache_model("models/onslaught/gen_gib1.md3");
- precache_model("models/onslaught/gen_gib2.md3");
- precache_model("models/onslaught/gen_gib3.md3");
- precache_sound("onslaught/generator_decay.wav");
- precache_sound(W_Sound("grenade_impact"));
- precache_sound(W_Sound("rocket_impact"));
- precache_sound("onslaught/generator_underattack.wav");
- precache_sound("onslaught/shockwave.wav");
- precache_sound("onslaught/ons_hit1.wav");
- precache_sound("onslaught/ons_hit2.wav");
- precache_sound("onslaught/generator_underattack.wav");
-
// appearence
// model handled by CSQC
setsize(gen, GENERATOR_MIN, GENERATOR_MAX);
gen.colormap = 1024 + (teamnumber - 1) * 17;
// generator placement
- self = gen;
+ setself(gen);
droptofloor();
// waypointsprites
if (!wpforenemy_announced)
{
Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_OVERTIME_CONTROLPOINT);
- sound(world, CH_INFO, "onslaught/generator_decay.wav", VOL_BASE, ATTEN_NONE);
+ sound(world, CH_INFO, SND_ONS_GENERATOR_DECAY, VOL_BASE, ATTEN_NONE);
wpforenemy_announced = true;
}
ons_stalemate = false;
- play2all(sprintf("ctf/%s_capture.wav", Static_Team_ColorName_Lower(winner_team)));
+ play2all(SND(CTF_CAPTURE(winner_team)));
round_handler_Init(7, autocvar_g_onslaught_warmup, autocvar_g_onslaught_round_timelimit);
// NOTE: LEGACY CODE, needs to be re-written!
void havocbot_goalrating_ons_offenseitems(float ratingscale, vector org, float sradius)
-{
+{SELFPARAM();
entity head;
float t, c;
int i;
}
int havocbot_ons_teamcount(entity bot, int role)
-{
+{SELFPARAM();
int c = 0;
entity head;
}
void havocbot_goalrating_ons_controlpoints_attack(float ratingscale)
-{
+{SELFPARAM();
entity cp, cp1, cp2, best, pl, wp;
float radius, bestvalue;
int c;
}
bool havocbot_goalrating_ons_generator_attack(float ratingscale)
-{
+{SELFPARAM();
entity g, wp, bestwp;
bool found;
int best;
}
void havocbot_role_ons_offense()
-{
+{SELFPARAM();
if(self.deadflag != DEAD_NO)
{
self.havocbot_attack_time = 0;
}
void havocbot_role_ons_assistant()
-{
+{SELFPARAM();
havocbot_ons_reset_role(self);
}
void havocbot_role_ons_defense()
-{
+{SELFPARAM();
havocbot_ons_reset_role(self);
}
void havocbot_ons_reset_role(entity bot)
-{
+{SELFPARAM();
entity head;
int c = 0;
* if max_dist is positive, only control points within this range will be considered
*/
entity ons_Nearest_ControlPoint(vector pos, float max_dist)
-{
+{SELFPARAM();
entity tmp_entity, closest_target = world;
tmp_entity = findchain(classname, "onslaught_controlpoint");
while(tmp_entity)
* This function only check distances on the XY plane, disregarding Z
*/
entity ons_Nearest_ControlPoint_2D(vector pos, float max_dist)
-{
+{SELFPARAM();
entity tmp_entity, closest_target = world;
vector delta;
float smallest_distance = 0, distance;
* find the number of control points and generators in the same team as self
*/
int ons_Count_SelfControlPoints()
-{
+{SELFPARAM();
entity tmp_entity;
tmp_entity = findchain(classname, "onslaught_controlpoint");
int n = 0;
if ( tele_effects )
{
Send_Effect(EFFECT_TELEPORT, player.origin, '0 0 0', 1);
- sound (player, CH_TRIGGER, "misc/teleport.wav", VOL_BASE, ATTEN_NORM);
+ sound (player, CH_TRIGGER, SND_TELEPORT, VOL_BASE, ATTEN_NORM);
}
setorigin(player, loc);
player.angles = '0 1 0' * ( theta * RAD2DEG + 180 );
// ==============
MUTATOR_HOOKFUNCTION(ons_ResetMap)
-{
- FOR_EACH_PLAYER(self)
+{SELFPARAM();
+ entity e;
+ FOR_EACH_PLAYER(e)
{
- self.ons_roundlost = false;
- self.ons_deathloc = '0 0 0';
- PutClientInServer();
+ e.ons_roundlost = false;
+ e.ons_deathloc = '0 0 0';
+ WITH(entity, self, e, PutClientInServer());
}
return false;
}
MUTATOR_HOOKFUNCTION(ons_RemovePlayer)
-{
+{SELFPARAM();
self.ons_deathloc = '0 0 0';
return false;
}
MUTATOR_HOOKFUNCTION(ons_PlayerSpawn)
-{
+{SELFPARAM();
if(!round_handler_IsRoundStarted())
{
self.player_blocked = true;
}
MUTATOR_HOOKFUNCTION(ons_PlayerDies)
-{
+{SELFPARAM();
frag_target.ons_deathloc = frag_target.origin;
entity l;
for(l = ons_worldgeneratorlist; l; l = l.ons_worldgeneratornext)
}
MUTATOR_HOOKFUNCTION(ons_MonsterThink)
-{
+{SELFPARAM();
entity e = find(world, targetname, self.target);
if (e != world)
self.team = e.team;
}
void ons_MonsterSpawn_Delayed()
-{
+{SELFPARAM();
entity e, own = self.owner;
if(!own) { remove(self); return; }
}
MUTATOR_HOOKFUNCTION(ons_MonsterSpawn)
-{
+{SELFPARAM();
entity e = spawn();
e.owner = self;
InitializeEntity(e, ons_MonsterSpawn_Delayed, INITPRIO_FINDTARGET);
}
void ons_TurretSpawn_Delayed()
-{
+{SELFPARAM();
entity e, own = self.owner;
if(!own) { remove(self); return; }
}
MUTATOR_HOOKFUNCTION(ons_TurretSpawn)
-{
+{SELFPARAM();
entity e = spawn();
e.owner = self;
InitializeEntity(e, ons_TurretSpawn_Delayed, INITPRIO_FINDTARGET);
}
MUTATOR_HOOKFUNCTION(ons_BotRoles)
-{
+{SELFPARAM();
havocbot_ons_reset_role(self);
return true;
}
}
MUTATOR_HOOKFUNCTION(ons_SpectateCopy)
-{
+{SELFPARAM();
self.ons_roundlost = other.ons_roundlost; // make spectators see it too
return false;
}
MUTATOR_HOOKFUNCTION(ons_SV_ParseClientCommand)
-{
+{SELFPARAM();
if(MUTATOR_RETURNVALUE) // command was already handled?
return false;
}
MUTATOR_HOOKFUNCTION(ons_PlayerUseKey)
-{
+{SELFPARAM();
if(MUTATOR_RETURNVALUE || gameover) { return false; }
if((time > self.teleport_antispam) && (self.deadflag == DEAD_NO) && !self.vehicle)
"target" - first control point.
"target2" - second control point.
*/
-void spawnfunc_onslaught_link()
+spawnfunc(onslaught_link)
{
if(!g_onslaught) { remove(self); return; }
"message" - name of this control point (should reflect the location in the map, such as "center bridge", "north tower", etc)
*/
-void spawnfunc_onslaught_controlpoint()
+spawnfunc(onslaught_controlpoint)
{
if(!g_onslaught) { remove(self); return; }
"team" - team that owns this generator (5 = red, 14 = blue, etc), MUST BE SET.
"targetname" - name that spawnfunc_onslaught_link entities will use to target this.
*/
-void spawnfunc_onslaught_generator()
+spawnfunc(onslaught_generator)
{
if(!g_onslaught) { remove(self); return; }
if(!self.team) { objerror("team must be set"); }
void ons_Initialize()
{
- precache_sound("ctf/red_capture.wav");
- precache_sound("ctf/blue_capture.wav");
- precache_sound("ctf/yellow_capture.wav");
- precache_sound("ctf/pink_capture.wav");
-
ons_captureshield_force = autocvar_g_onslaught_shield_force;
addstat(STAT_ROUNDLOST, AS_INT, ons_roundlost);
// legacy bot roles
.float race_checkpoint;
void havocbot_role_race()
-{
+{SELFPARAM();
if(self.deadflag != DEAD_NO)
return;
}
MUTATOR_HOOKFUNCTION(race_PlayerPhysics)
-{
+{SELFPARAM();
// force kbd movement for fairness
float wishspeed;
vector wishvel;
}
MUTATOR_HOOKFUNCTION(race_PlayerPreThink)
-{
+{SELFPARAM();
if(IS_SPEC(self) || IS_OBSERVER(self))
if(g_race_qualifying)
if(msg_entity.enemy.race_laptime)
}
MUTATOR_HOOKFUNCTION(race_ClientConnect)
-{
+{SELFPARAM();
race_PreparePlayer();
self.race_checkpoint = -1;
}
MUTATOR_HOOKFUNCTION(race_MakePlayerObserver)
-{
+{SELFPARAM();
if(g_race_qualifying)
if(PlayerScore_Add(self, SP_RACE_FASTEST, 0))
self.frags = FRAGS_LMS_LOSER;
}
MUTATOR_HOOKFUNCTION(race_PlayerSpawn)
-{
+{SELFPARAM();
if(spawn_spot.target == "")
// Emergency: this wasn't a real spawnpoint. Can this ever happen?
race_PreparePlayer();
}
MUTATOR_HOOKFUNCTION(race_PutClientInServer)
-{
+{SELFPARAM();
if(IS_PLAYER(self))
if(!gameover)
{
}
MUTATOR_HOOKFUNCTION(race_PlayerDies)
-{
+{SELFPARAM();
self.respawn_flags |= RESPAWN_FORCE;
race_AbandonRaceCheck(self);
return false;
}
MUTATOR_HOOKFUNCTION(race_BotRoles)
-{
+{SELFPARAM();
self.havocbot_role = havocbot_role_race;
return true;
}
MUTATOR_HOOKFUNCTION(race_PlayerPostThink)
-{
+{SELFPARAM();
if(self.cvar_cl_allow_uidtracking == 1 && self.cvar_cl_allow_uid2name == 1)
{
if (!self.stored_netname)
Keys:
"netname" Name of the team (for example Red, Blue, Green, Yellow, Life, Death, Offense, Defense, etc)...
"cnt" Scoreboard color of the team (for example 4 is red and 13 is blue)... */
-void spawnfunc_tdm_team()
+spawnfunc(tdm_team)
{
if(!g_tdm || !self.cnt) { remove(self); return; }
// code from here on is just to support maps that don't have team entities
void tdm_SpawnTeam (string teamname, float teamcolor)
{
- entity oldself;
- oldself = self;
- self = spawn();
- self.classname = "tdm_team";
- self.netname = teamname;
- self.cnt = teamcolor;
-
- spawnfunc_tdm_team();
-
- self = oldself;
+ entity this = new(tdm_team);
+ this.netname = teamname;
+ this.cnt = teamcolor;
+ this.spawnfunc_checked = true;
+ WITH(entity, self, this, spawnfunc_tdm_team(this));
}
void tdm_DelayedInit()
.float bloodloss_timer;
MUTATOR_HOOKFUNCTION(bloodloss_PlayerThink)
-{
+{SELFPARAM();
if(IS_PLAYER(self))
if(self.health <= autocvar_g_bloodloss && self.deadflag == DEAD_NO)
{
}
MUTATOR_HOOKFUNCTION(bloodloss_PlayerJump)
-{
+{SELFPARAM();
if(self.health <= autocvar_g_bloodloss)
return true;
#include "mutator.qh"
-#include "../../common/buffs.qh"
+#include "../../common/buffs/all.qh"
entity buff_FirstFromFlags(int _buffs)
{
if (flags)
{
- FOREACH(BUFFS, it.m_itemid & _buffs, LAMBDA(return it));
+ FOREACH(Buffs, it.m_itemid & _buffs, LAMBDA(return it));
}
- return BUFF_NULL;
+ return BUFF_Null;
}
bool buffs_BuffModel_Customize()
-{
+{SELFPARAM();
entity player, myowner;
bool same_team;
void buffs_BuffModel_Spawn(entity player)
{
player.buff_model = spawn();
- setmodel(player.buff_model, BUFF_MODEL);
+ setmodel(player.buff_model, MDL_BUFF);
setsize(player.buff_model, '0 0 -40', '0 0 40');
setattachment(player.buff_model, player, "");
setorigin(player.buff_model, '0 0 1' * (player.buff_model.maxs.z * 1));
}
void buff_Effect(entity player, string eff)
-{
+{SELFPARAM();
if(!autocvar_g_buffs_effects) { return; }
if(time >= self.buff_effect_delay)
// buff item
float buff_Waypoint_visible_for_player(entity plr)
-{
+{SELFPARAM();
if(!self.owner.buff_active && !self.owner.buff_activetime)
return false;
void buff_Waypoint_Spawn(entity e)
{
entity buff = buff_FirstFromFlags(e.buffs);
- entity wp = WaypointSprite_Spawn(WP_Buff, 0, autocvar_g_buffs_waypoint_distance, e, '0 0 1' * e.maxs.z, world, e.team, e, buff_waypoint, true, RADARICON_POWERUP);
+ entity wp = WaypointSprite_Spawn(WP_Buff, 0, autocvar_g_buffs_waypoint_distance, e, '0 0 1' * e.maxs.z, world, e.team, e, buff_waypoint, true, RADARICON_Buff);
wp.wp_extra = buff.m_id;
- WaypointSprite_UpdateTeamRadar(e.buff_waypoint, RADARICON_POWERUP, e.glowmod);
+ WaypointSprite_UpdateTeamRadar(e.buff_waypoint, RADARICON_Buff, e.glowmod);
e.buff_waypoint.waypointsprite_visible_for_player = buff_Waypoint_visible_for_player;
}
void buff_SetCooldown(float cd)
-{
+{SELFPARAM();
cd = max(0, cd);
if(!self.buff_waypoint)
}
void buff_Respawn(entity ent)
-{
+{SELFPARAM();
if(gameover) { return; }
vector oldbufforigin = ent.origin;
WaypointSprite_Ping(ent.buff_waypoint);
- sound(ent, CH_TRIGGER, "keepaway/respawn.wav", VOL_BASE, ATTEN_NONE); // ATTEN_NONE (it's a sound intended to be heard anywhere)
+ sound(ent, CH_TRIGGER, SND_KA_RESPAWN, VOL_BASE, ATTEN_NONE); // ATTEN_NONE (it's a sound intended to be heard anywhere)
}
void buff_Touch()
-{
+{SELFPARAM();
if(gameover) { return; }
if(ITEM_TOUCH_NEEDKILL())
Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_ITEM_BUFF_LOST, other.netname, buffid);
other.buffs = 0;
- //sound(other, CH_TRIGGER, "relics/relic_effect.wav", VOL_BASE, ATTN_NORM);
+ //sound(other, CH_TRIGGER, SND_BUFF_LOST, VOL_BASE, ATTN_NORM);
}
else { return; } // do nothing
}
Send_Notification(NOTIF_ALL_EXCEPT, other, MSG_INFO, INFO_ITEM_BUFF, other.netname, buffid);
Send_Effect(EFFECT_ITEM_PICKUP, CENTER_OR_VIEWOFS(self), '0 0 0', 1);
- sound(other, CH_TRIGGER, "misc/shield_respawn.wav", VOL_BASE, ATTN_NORM);
+ sound(other, CH_TRIGGER, SND_SHIELD_RESPAWN, VOL_BASE, ATTN_NORM);
other.buffs |= (self.buffs);
}
float buff_Available(entity buff)
{
- if (buff == BUFF_NULL)
+ if (buff == BUFF_Null)
return false;
if (buff == BUFF_AMMO && ((start_items & IT_UNLIMITED_WEAPON_AMMO) || (start_items & IT_UNLIMITED_AMMO) || (cvar("g_melee_only"))))
return false;
void buff_NewType(entity ent, float cb)
{
RandomSelection_Init();
- FOREACH(BUFFS, buff_Available(it), LAMBDA(
+ FOREACH(Buffs, buff_Available(it), LAMBDA(
it.buff_seencount += 1;
// if it's already been chosen, give it a lower priority
RandomSelection_Add(world, it.m_itemid, string_null, 1, max(0.2, 1 / it.buff_seencount));
}
void buff_Think()
-{
+{SELFPARAM();
if(self.buffs != self.oldbuffs)
{
entity buff = buff_FirstFromFlags(self.buffs);
self.glowmod = buff_GlowColor(buff);
self.skin = buff.m_skin;
- setmodel(self, BUFF_MODEL);
+ setmodel(self, MDL_BUFF);
if(self.buff_waypoint)
{
if(!self.buff_activetime)
{
self.buff_active = true;
- sound(self, CH_TRIGGER, "misc/strength_respawn.wav", VOL_BASE, ATTN_NORM);
+ sound(self, CH_TRIGGER, SND_STRENGTH_RESPAWN, VOL_BASE, ATTN_NORM);
Send_Effect(EFFECT_ITEM_RESPAWN, CENTER_OR_VIEWOFS(self), '0 0 0', 1);
}
}
}
void buff_Waypoint_Reset()
-{
+{SELFPARAM();
WaypointSprite_Kill(self.buff_waypoint);
if(self.buff_activetime) { buff_Waypoint_Spawn(self); }
}
void buff_Reset()
-{
+{SELFPARAM();
if(autocvar_g_buffs_randomize)
buff_NewType(self, self.buffs);
self.owner = world;
}
float buff_Customize()
-{
+{SELFPARAM();
entity player = WaypointSprite_getviewentity(other);
if(!self.buff_active || (self.team && DIFF_TEAM(player, self)))
{
}
void buff_Init(entity ent)
-{
+{SELFPARAM();
if(!cvar("g_buffs")) { remove(ent); return; }
if(!teamplay && ent.team) { ent.team = 0; }
entity buff = buff_FirstFromFlags(self.buffs);
- entity oldself = self;
- self = ent;
+ setself(ent);
if(!self.buffs || buff_Available(buff))
buff_NewType(self, 0);
if(self.noalign)
self.movetype = MOVETYPE_NONE; // reset by random location
- setmodel(self, BUFF_MODEL);
+ setmodel(self, MDL_BUFF);
setsize(self, BUFF_MIN, BUFF_MAX);
if(cvar("g_buffs_random_location") || (self.spawnflags & 64))
buff_Respawn(self);
- self = oldself;
+ setself(this);
}
void buff_Init_Compat(entity ent, entity replacement)
}
void buff_Vengeance_DelayedDamage()
-{
+{SELFPARAM();
if(self.enemy)
Damage(self.enemy, self.owner, self.owner, self.dmg, DEATH_BUFF, self.enemy.origin, '0 0 0');
}
MUTATOR_HOOKFUNCTION(buffs_PlayerSpawn)
-{
+{SELFPARAM();
self.buffs = 0;
// reset timers here to prevent them continuing after re-spawn
self.buff_disability_time = 0;
}
MUTATOR_HOOKFUNCTION(buffs_PlayerPhysics)
-{
+{SELFPARAM();
if(self.buffs & BUFF_SPEED.m_itemid)
{
self.stat_sv_maxspeed *= autocvar_g_buffs_speed_speed;
}
MUTATOR_HOOKFUNCTION(buffs_PlayerJump)
-{
+{SELFPARAM();
if(self.buffs & BUFF_JUMP.m_itemid)
player_jumpheight = autocvar_g_buffs_jump_height;
}
MUTATOR_HOOKFUNCTION(buffs_MonsterMove)
-{
+{SELFPARAM();
if(time < self.buff_disability_time)
{
monster_speed_walk *= autocvar_g_buffs_disability_speed;
}
MUTATOR_HOOKFUNCTION(buffs_PlayerDies)
-{
+{SELFPARAM();
if(self.buffs)
{
int buffid = buff_FirstFromFlags(self.buffs).m_id;
}
MUTATOR_HOOKFUNCTION(buffs_PlayerUseKey)
-{
+{SELFPARAM();
if(MUTATOR_RETURNVALUE || gameover) { return false; }
if(self.buffs)
{
Send_Notification(NOTIF_ALL_EXCEPT, self, MSG_INFO, INFO_ITEM_BUFF_LOST, self.netname, buffid);
self.buffs = 0;
- sound(self, CH_TRIGGER, "relics/relic_effect.wav", VOL_BASE, ATTN_NORM);
+ sound(self, CH_TRIGGER, SND_BUFF_LOST, VOL_BASE, ATTN_NORM);
return true;
}
return false;
}
MUTATOR_HOOKFUNCTION(buffs_PlayerThrowKey)
-{
+{SELFPARAM();
if(MUTATOR_RETURNVALUE || gameover) { return false; }
if(self.buffs & BUFF_SWAPPER.m_itemid)
Send_Effect(EFFECT_ELECTRO_COMBO, their_org, '0 0 0', 1);
Send_Effect(EFFECT_ELECTRO_COMBO, my_org, '0 0 0', 1);
- sound(self, CH_TRIGGER, "keepaway/respawn.wav", VOL_BASE, ATTEN_NORM);
- sound(closest, CH_TRIGGER, "keepaway/respawn.wav", VOL_BASE, ATTEN_NORM);
+ sound(self, CH_TRIGGER, SND_KA_RESPAWN, VOL_BASE, ATTEN_NORM);
+ sound(closest, CH_TRIGGER, SND_KA_RESPAWN, VOL_BASE, ATTEN_NORM);
// TODO: add a counter to handle how many times one can teleport, and a delay to prevent spam
self.buffs = 0;
}
MUTATOR_HOOKFUNCTION(buffs_RemovePlayer)
-{
+{SELFPARAM();
if(self.buff_model)
{
remove(self.buff_model);
}
MUTATOR_HOOKFUNCTION(buffs_CustomizeWaypoint)
-{
+{SELFPARAM();
entity e = WaypointSprite_getviewentity(other);
// if you have the invisibility powerup, sprites ALWAYS are restricted to your team
}
MUTATOR_HOOKFUNCTION(buffs_OnEntityPreSpawn)
-{
+{SELFPARAM();
if(autocvar_g_buffs_replace_powerups)
switch(self.classname)
{
}
MUTATOR_HOOKFUNCTION(buffs_WeaponRate)
-{
+{SELFPARAM();
if(self.buffs & BUFF_SPEED.m_itemid)
weapon_rate *= autocvar_g_buffs_speed_rate;
}
MUTATOR_HOOKFUNCTION(buffs_WeaponSpeed)
-{
+{SELFPARAM();
if(self.buffs & BUFF_SPEED.m_itemid)
ret_float *= autocvar_g_buffs_speed_weaponspeed;
.float buff_time;
MUTATOR_HOOKFUNCTION(buffs_PlayerThink)
-{
+{SELFPARAM();
if(gameover || self.deadflag != DEAD_NO) { return false; }
if(time < self.buff_disability_time)
if(buff_lost >= 2)
{
Send_Notification(NOTIF_ONE, self, MSG_MULTI, ITEM_BUFF_DROP, buffid); // TODO: special timeout message?
- sound(self, CH_TRIGGER, "relics/relic_effect.wav", VOL_BASE, ATTN_NORM);
+ sound(self, CH_TRIGGER, SND_BUFF_LOST, VOL_BASE, ATTN_NORM);
}
self.buffs = 0;
}
for(other = world; (other = findflags(other, flags, FL_ITEM)); )
if(boxesoverlap(self.absmin - pickup_size, self.absmax + pickup_size, other.absmin, other.absmax))
{
- entity oldself = self;
- self = other;
- other = oldself;
+ setself(other);
+ other = this;
if(self.touch)
self.touch();
other = self;
- self = oldself;
+ setself(this);
}
}
if(self.buffs != self.oldbuffs)
{
entity buff = buff_FirstFromFlags(self.buffs);
- float bufftime = buff != BUFF_NULL ? buff.m_time(buff) : 0;
+ float bufftime = buff != BUFF_Null ? buff.m_time(buff) : 0;
self.buff_time = (bufftime) ? time + bufftime : 0;
BUFF_ONADD(BUFF_AMMO)
}
MUTATOR_HOOKFUNCTION(buffs_SpectateCopy)
-{
+{SELFPARAM();
self.buffs = other.buffs;
return false;
}
}
MUTATOR_HOOKFUNCTION(buffs_PlayerRegen)
-{
+{SELFPARAM();
if(self.buffs & BUFF_MEDIC.m_itemid)
{
regen_mod_rot = autocvar_g_buffs_medic_rot;
void buffs_Initialize()
{
- precache_model(BUFF_MODEL);
- precache_sound("misc/strength_respawn.wav");
- precache_sound("misc/shield_respawn.wav");
- precache_sound("relics/relic_effect.wav");
- precache_sound(W_Sound("rocket_impact"));
- precache_sound("keepaway/respawn.wav");
-
addstat(STAT_BUFFS, AS_INT, buffs);
addstat(STAT_BUFF_TIME, AS_FLOAT, buff_time);
.int oldbuffs; // for updating effects
.entity buff_model; // controls effects (TODO: make csqc)
-const string BUFF_MODEL = "models/relics/relic.md3";
-
const vector BUFF_MIN = ('-16 -16 -20');
const vector BUFF_MAX = ('16 16 20');
.float campcheck_traveled_distance;
MUTATOR_HOOKFUNCTION(campcheck_PlayerDies)
-{
+{SELFPARAM();
Kill_Notification(NOTIF_ONE, self, MSG_CENTER_CPID, CPID_CAMPCHECK);
return false;
}
MUTATOR_HOOKFUNCTION(campcheck_PlayerThink)
-{
+{SELFPARAM();
if(!gameover)
if(!warmup_stage) // don't consider it camping during warmup?
if(time >= game_starttime)
}
MUTATOR_HOOKFUNCTION(campcheck_PlayerSpawn)
-{
+{SELFPARAM();
self.campcheck_nextcheck = time + autocvar_g_campcheck_interval * 2;
self.campcheck_traveled_distance = 0;
#elif defined(SVQC)
void dodging_UpdateStats()
-{
+{SELFPARAM();
self.stat_dodging = PHYS_DODGING;
self.stat_dodging_delay = PHYS_DODGING_DELAY;
self.stat_dodging_horiz_speed_frozen = PHYS_DODGING_HORIZ_SPEED_FROZEN;
// returns 1 if the player is close to a wall
bool check_close_to_wall(float threshold)
-{
+{SELFPARAM();
if (PHYS_DODGING_WALL == 0) { return false; }
#define X(OFFSET) \
}
bool check_close_to_ground(float threshold)
-{
+{SELFPARAM();
return IS_ONGROUND(self) ? true : false;
}
float PM_dodging_checkpressedkeys()
-{
+{SELFPARAM();
if(!PHYS_DODGING)
return false;
}
void PM_dodging()
-{
+{SELFPARAM();
if (!PHYS_DODGING)
return;
--- /dev/null
+AUTOCVAR(g_grappling_hook, bool, false, _("let players spawn with the grappling hook which allows them to pull themselves up"));
+#ifdef SVQC
+REGISTER_MUTATOR(hook, autocvar_g_grappling_hook) {
+ MUTATOR_ONADD {
+ g_grappling_hook = true;
+ WEP_HOOK.ammo_factor = 0;
+ }
+ MUTATOR_ONROLLBACK_OR_REMOVE {
+ g_grappling_hook = false;
+ WEP_HOOK.ammo_factor = 1;
+ }
+}
+
+MUTATOR_HOOKFUNCTION(hook, BuildMutatorsString)
+{
+ ret_string = strcat(ret_string, ":grappling_hook");
+}
+
+MUTATOR_HOOKFUNCTION(hook, BuildMutatorsPrettyString)
+{
+ ret_string = strcat(ret_string, ", Hook");
+}
+
+MUTATOR_HOOKFUNCTION(hook, BuildGameplayTipsString)
+{
+ ret_string = strcat(ret_string, "\n\n^3grappling hook^8 is enabled, press 'e' to use it\n");
+}
+
+MUTATOR_HOOKFUNCTION(hook, PlayerSpawn)
+{
+ SELFPARAM();
+ self.offhand = OFFHAND_HOOK;
+}
+
+MUTATOR_HOOKFUNCTION(hook, FilterItem)
+{
+ return self.weapon == WEP_HOOK.m_id;
+}
+
+#endif
#include "mutator.qh"
#include "../cl_client.qh"
-#include "../../common/buffs.qh"
+#include "../../common/buffs/all.qh"
#include "../../common/items/all.qc"
-void spawnfunc_item_minst_cells (void)
+spawnfunc(item_minst_cells)
{
if (!g_instagib) { remove(self); return; }
- if (!self.ammo_cells)
- self.ammo_cells = autocvar_g_instagib_ammo_drop;
+ if (!self.ammo_cells) self.ammo_cells = autocvar_g_instagib_ammo_drop;
+ StartItemA(ITEM_VaporizerCells);
+}
- StartItemA (ITEM_VaporizerCells);
+void instagib_invisibility()
+{SELFPARAM();
+ self.strength_finished = autocvar_g_balance_powerup_strength_time;
+ StartItemA(ITEM_Invisibility);
}
-void instagib_health_mega()
-{
+void instagib_extralife()
+{SELFPARAM();
self.max_health = 1;
- StartItemA (ITEM_ExtraLife);
+ StartItemA(ITEM_ExtraLife);
+}
+
+void instagib_speed()
+{SELFPARAM();
+ self.invincible_finished = autocvar_g_balance_powerup_invincible_time;
+ StartItemA(ITEM_Speed);
}
.float instagib_nextthink;
e.instagib_needammo = false;
}
void instagib_ammocheck()
-{
+{SELFPARAM();
if(time < self.instagib_nextthink)
return;
if(!IS_PLAYER(self))
}
MUTATOR_HOOKFUNCTION(instagib_MonsterSpawn)
-{
+{SELFPARAM();
// always refill ammo
if(self.monsterid == MON_MAGE.monsterid)
self.skin = 1;
MUTATOR_HOOKFUNCTION(instagib_BotShouldAttack)
{
- if(checkentity.items & ITEM_Strength.m_itemid)
+ if (checkentity.items & ITEM_Invisibility.m_itemid)
return true;
return false;
}
MUTATOR_HOOKFUNCTION(instagib_MakePlayerObserver)
-{
+{SELFPARAM();
instagib_stop_countdown(self);
return false;
}
MUTATOR_HOOKFUNCTION(instagib_PlayerSpawn)
-{
+{SELFPARAM();
self.effects |= EF_FULLBRIGHT;
return false;
}
}
MUTATOR_HOOKFUNCTION(instagib_PlayerPowerups)
-{
+{SELFPARAM();
if (!(self.effects & EF_FULLBRIGHT))
self.effects |= EF_FULLBRIGHT;
- if (self.items & ITEM_Strength.m_itemid)
+ if (self.items & ITEM_Invisibility.m_itemid)
{
- play_countdown(self.strength_finished, "misc/poweroff.wav");
+ play_countdown(self.strength_finished, SND(POWEROFF));
if (time > self.strength_finished)
{
self.alpha = default_player_alpha;
self.exteriorweaponentity.alpha = default_weapon_alpha;
- self.items &= ~ITEM_Strength.m_itemid;
+ self.items &= ~ITEM_Invisibility.m_itemid;
Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_INVISIBILITY);
}
}
{
self.alpha = autocvar_g_instagib_invis_alpha;
self.exteriorweaponentity.alpha = autocvar_g_instagib_invis_alpha;
- self.items |= ITEM_Strength.m_itemid;
+ self.items |= ITEM_Invisibility.m_itemid;
Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_INVISIBILITY, self.netname);
Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_INVISIBILITY);
}
}
- if (self.items & ITEM_Shield.m_itemid)
+ if (self.items & ITEM_Speed.m_itemid)
{
- play_countdown(self.invincible_finished, "misc/poweroff.wav");
+ play_countdown(self.invincible_finished, SND(POWEROFF));
if (time > self.invincible_finished)
{
- self.items &= ~ITEM_Shield.m_itemid;
+ self.items &= ~ITEM_Speed.m_itemid;
Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_SPEED);
}
}
{
if (time < self.invincible_finished)
{
- self.items |= ITEM_Shield.m_itemid;
+ self.items |= ITEM_Speed.m_itemid;
Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_SPEED, self.netname);
Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_SPEED);
}
}
MUTATOR_HOOKFUNCTION(instagib_PlayerPhysics)
-{
- if(self.items & ITEM_Shield.m_itemid)
+{SELFPARAM();
+ if(self.items & ITEM_Speed.m_itemid)
self.stat_sv_maxspeed = self.stat_sv_maxspeed * autocvar_g_instagib_speed_highspeed;
return false;
frag_mirrordamage = 0;
}
- if((frag_target.buffs & BUFF_INVISIBLE.m_itemid) || (frag_target.items & ITEM_Strength.m_itemid))
+ if((frag_target.buffs & BUFF_INVISIBLE.m_itemid) || (frag_target.items & ITEM_Invisibility.m_itemid))
yoda = 1;
return false;
start_ammo_rockets = warmup_start_ammo_rockets = 0;
start_ammo_fuel = warmup_start_ammo_fuel = 0;
- start_weapons = warmup_start_weapons = WEPSET_VAPORIZER;
+ start_weapons = warmup_start_weapons = WEPSET(VAPORIZER);
start_items |= IT_UNLIMITED_SUPERWEAPONS;
return false;
}
MUTATOR_HOOKFUNCTION(instagib_FilterItem)
-{
+{SELFPARAM();
if(self.classname == "item_cells")
return true; // no normal cells?
if(self.weapon == WEP_DEVASTATOR.m_id || self.weapon == WEP_VORTEX.m_id)
{
- entity e = spawn(), oldself;
+ entity e = spawn();
setorigin(e, self.origin);
- oldself = self;
- self = e;
- self.noalign = oldself.noalign;
- self.cnt = oldself.cnt;
- self.team = oldself.team;
- spawnfunc_item_minst_cells();
- self = oldself;
+ e.noalign = self.noalign;
+ e.cnt = self.cnt;
+ e.team = self.team;
+ WITH(entity, self, e, spawnfunc_item_minst_cells(e));
return true;
}
}
MUTATOR_HOOKFUNCTION(instagib_CustomizeWaypoint)
-{
+{SELFPARAM();
entity e = WaypointSprite_getviewentity(other);
// if you have the invisibility powerup, sprites ALWAYS are restricted to your team
// but only apply this to real players, not to spectators
- if((self.owner.flags & FL_CLIENT) && (self.owner.items & ITEM_Strength.m_itemid) && (e == other))
+ if((self.owner.flags & FL_CLIENT) && (self.owner.items & ITEM_Invisibility.m_itemid) && (e == other))
if(DIFF_TEAM(self.owner, e))
return true;
return false;
}
-MUTATOR_HOOKFUNCTION(instagib_ItemCountdown)
-{
- switch (self.items)
- {
- case ITEM_Strength.m_itemid: item_name = "item-invis"; item_color = '0 0 1'; break;
- case ITEM_ExtraLife.m_itemid: item_name = "item-extralife"; item_color = '1 0 0'; break;
- case ITEM_Shield.m_itemid: item_name = "item-speed"; item_color = '1 0 1'; break;
- }
- return false;
-}
-
MUTATOR_HOOKFUNCTION(instagib_PlayerDies)
-{
+{
if(DEATH_ISWEAPON(frag_deathtype, WEP_VAPORIZER.m_id))
frag_damage = 1000; // always gib if it was a vaporizer death
}
MUTATOR_HOOKFUNCTION(instagib_ItemTouch)
-{
+{SELFPARAM();
if(self.ammo_cells)
{
// play some cool sounds ;)
}
MUTATOR_HOOKFUNCTION(instagib_OnEntityPreSpawn)
-{
+{SELFPARAM();
if (!autocvar_g_powerups) { return false; }
- if (!(self.classname == "item_strength" || self.classname == "item_invincible" || self.itemdef == ITEM_HealthMega))
+ // Can't use .itemdef here
+ if (!(self.classname == "item_strength" || self.classname == "item_invincible" || self.classname == "item_health_mega"))
return false;
entity e = spawn();
- if(random() < 0.3)
- e.think = spawnfunc_item_strength;
- else if(random() < 0.6)
- e.think = instagib_health_mega;
+ float r = random();
+ if (r < 0.3)
+ e.think = instagib_invisibility;
+ else if (r < 0.6)
+ e.think = instagib_extralife;
else
- e.think = spawnfunc_item_invincible;
+ e.think = instagib_speed;
e.nextthink = time + 0.1;
e.spawnflags = self.spawnflags;
MUTATOR_HOOK(ItemTouch, instagib_ItemTouch, CBC_ORDER_ANY);
MUTATOR_HOOK(FilterItem, instagib_FilterItem, CBC_ORDER_ANY);
MUTATOR_HOOK(CustomizeWaypoint, instagib_CustomizeWaypoint, CBC_ORDER_ANY);
- MUTATOR_HOOK(Item_RespawnCountdown, instagib_ItemCountdown, CBC_ORDER_ANY);
MUTATOR_HOOK(PlayerDies, instagib_PlayerDies, CBC_ORDER_ANY);
MUTATOR_HOOK(PlayerDamage_SplitHealthArmor, instagib_SplitHealthArmor, CBC_ORDER_ANY);
MUTATOR_HOOK(PlayerPowerups, instagib_PlayerPowerups, CBC_ORDER_ANY);
#include "../../common/items/item.qh"
-#define WITH(it) this.m_##it;
-#define CONFIGURE(...) MAP(WITH, __VA_ARGS__)
-
float instagib_respawntime_ammo = 45;
float instagib_respawntimejitter_ammo = 0;
GETTER(float, instagib_respawntime_ammo)
GETTER(float, instagib_respawntimejitter_ammo)
+#ifndef MENUQC
+MODEL(VaporizerCells_ITEM, Item_Model("a_cells.md3"));
+#endif
+
REGISTER_ITEM(VaporizerCells, Ammo) {
- this.m_model = "a_cells.md3";
+#ifndef MENUQC
+ this.m_model = MDL_VaporizerCells_ITEM;
+#endif
this.m_sound = "misc/itempickup.wav";
this.m_name = "Vaporizer Ammo";
this.m_icon = "ammo_supercells";
#endif
}
+#ifndef MENUQC
+MODEL(ExtraLife_ITEM, Item_Model("g_h100.md3"));
+#endif
+
REGISTER_ITEM(ExtraLife, Powerup) {
- this.m_model = "g_h100.md3";
+#ifndef MENUQC
+ this.m_model = MDL_ExtraLife_ITEM;
+#endif
this.m_sound = "misc/megahealth.wav";
- this.m_name = "Extralife";
+ this.m_name = "Extra life";
this.m_icon = "item_mega_health";
-#ifdef SVQC
+ this.m_color = '1 0 0';
+ this.m_waypoint = _("Extra life");
+ this.m_waypointblink = 2;
this.m_itemid = IT_NAILS;
- this.m_botvalue = BOT_PICKUP_RATING_HIGH;
+}
+
+#ifndef MENUQC
+MODEL(Invisibility_ITEM, Item_Model("g_strength.md3"));
+#endif
+
+REGISTER_ITEM(Invisibility, Powerup) {
+#ifndef MENUQC
+ this.m_model = MDL_Invisibility_ITEM;
#endif
+ this.m_sound = "misc/powerup.wav";
+ this.m_name = "Invisibility";
+ this.m_icon = "strength";
+ this.m_color = '0 0 1';
+ this.m_waypoint = _("Invisibility");
+ this.m_waypointblink = 2;
+ this.m_itemid = IT_STRENGTH;
}
-#undef WITH
-#undef CONFIGURE
+#ifndef MENUQC
+MODEL(Speed_ITEM, Item_Model("g_invincible.md3"));
+#endif
+
+REGISTER_ITEM(Speed, Powerup) {
+#ifndef MENUQC
+ this.m_model = MDL_Speed_ITEM;
+#endif
+ this.m_sound = "misc/powerup_shield.wav";
+ this.m_name = "Speed";
+ this.m_icon = "shield";
+ this.m_color = '1 0 1';
+ this.m_waypoint = _("Speed");
+ this.m_waypointblink = 2;
+ this.m_itemid = IT_INVINCIBLE;
+}
MUTATOR_HOOKFUNCTION(melee_SetStartItems)
{
start_ammo_shells = warmup_start_ammo_shells = 0;
- start_weapons = warmup_start_weapons = WEPSET_SHOTGUN;
+ start_weapons = warmup_start_weapons = WEPSET(SHOTGUN);
return false;
}
}
MUTATOR_HOOKFUNCTION(melee_FilterItem)
-{
+{SELFPARAM();
switch (self.items)
{
case ITEM_HealthSmall.m_itemid:
.float midair_shieldtime;
MUTATOR_HOOKFUNCTION(midair_PlayerDamage)
-{
+{SELFPARAM();
if(IS_PLAYER(frag_attacker))
if(IS_PLAYER(frag_target))
if(time < self.midair_shieldtime)
}
MUTATOR_HOOKFUNCTION(midair_PlayerPowerups)
-{
+{SELFPARAM();
if(time >= game_starttime)
if(self.flags & FL_ONGROUND)
{
}
MUTATOR_HOOKFUNCTION(midair_PlayerSpawn)
-{
+{SELFPARAM();
if(IS_BOT_CLIENT(self))
self.bot_moveskill = 0; // disable bunnyhopping
.float stat_multijump_dodging;
void multijump_UpdateStats()
-{
+{SELFPARAM();
self.stat_multijump = PHYS_MULTIJUMP;
self.stat_multijump_speed = PHYS_MULTIJUMP_SPEED;
self.stat_multijump_add = PHYS_MULTIJUMP_ADD;
#endif
void PM_multijump()
-{
+{SELFPARAM();
if(!PHYS_MULTIJUMP) { return; }
if(IS_ONGROUND(self))
}
bool PM_multijump_checkjump()
-{
+{SELFPARAM();
if(!PHYS_MULTIJUMP) { return false; }
#ifdef SVQC
#include "gamemode_keyhunt.qh"
#include "gamemode_freezetag.qh"
-#include "../../common/nades.qh"
+#include "../../common/nades/all.qh"
#include "../../common/monsters/spawn.qh"
#include "../../common/monsters/sv_monsters.qh"
-.float lifetime;
+.float nade_time_primed;
.entity nade_spawnloc;
void nade_timer_think()
-{
+{SELFPARAM();
self.skin = 8 - (self.owner.wait - time) / (autocvar_g_nades_nade_lifetime / 10);
self.nextthink = time;
if(!self.owner || wasfreed(self.owner))
void nade_burn_spawn(entity _nade)
{
- CSQCProjectile(_nade, true, NADES[_nade.nade_type].m_projectile[true], true);
+ CSQCProjectile(_nade, true, Nades[_nade.nade_type].m_projectile[true], true);
}
void nade_spawn(entity _nade)
{
entity timer = spawn();
- setmodel(timer, "models/ok_nade_counter/ok_nade_counter.md3");
+ setmodel(timer, MDL_NADE_TIMER);
setattachment(timer, _nade, "");
timer.classname = "nade_timer";
timer.colormap = _nade.colormap;
_nade.effects |= EF_LOWPRECISION;
- CSQCProjectile(_nade, true, NADES[_nade.nade_type].m_projectile[false], true);
+ CSQCProjectile(_nade, true, Nades[_nade.nade_type].m_projectile[false], true);
}
void napalm_damage(float dist, float damage, float edgedamage, float burntime)
-{
+{SELFPARAM();
entity e;
float d;
vector p;
void napalm_ball_think()
-{
+{SELFPARAM();
if(round_handler_IsActive())
if(!round_handler_IsRoundStarted())
{
void nade_napalm_ball()
-{
+{SELFPARAM();
entity proj;
vector kick;
- spamsound(self, CH_SHOTS, W_Sound("fireball_fire"), VOL_BASE, ATTEN_NORM);
+ spamsound(self, CH_SHOTS, SND(FIREBALL_FIRE), VOL_BASE, ATTEN_NORM);
proj = spawn ();
proj.owner = self.owner;
proj.movetype = MOVETYPE_BOUNCE;
proj.projectiledeathtype = DEATH_NADE_NAPALM;
PROJECTILE_MAKETRIGGER(proj);
- setmodel(proj, "null");
+ setmodel(proj, MDL_Null);
proj.scale = 1;//0.5;
setsize(proj, '-4 -4 -4', '4 4 4');
setorigin(proj, self.origin);
void napalm_fountain_think()
-{
+{SELFPARAM();
if(round_handler_IsActive())
if(!round_handler_IsRoundStarted())
}
void nade_napalm_boom()
-{
+{SELFPARAM();
entity fountain;
int c;
for (c = 0; c < autocvar_g_nades_napalm_ball_count; c++)
}
void nade_ice_think()
-{
+{SELFPARAM();
if(round_handler_IsActive())
if(!round_handler_IsRoundStarted())
{
if ( autocvar_g_nades_ice_explode )
{
- entity expef = NULL;
- switch(self.realowner.team)
- {
- case NUM_TEAM_1: expef = EFFECT_NADE_RED_EXPLODE; break;
- case NUM_TEAM_2: expef = EFFECT_NADE_BLUE_EXPLODE; break;
- case NUM_TEAM_3: expef = EFFECT_NADE_YELLOW_EXPLODE; break;
- case NUM_TEAM_4: expef = EFFECT_NADE_PINK_EXPLODE; break;
- default: expef = EFFECT_NADE_NEUTRAL_EXPLODE; break;
- }
+ entity expef = EFFECT_NADE_EXPLODE(self.realowner.team);
Send_Effect(expef, self.origin + '0 0 1', '0 0 0', 1);
- sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
RadiusDamage(self, self.realowner, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage,
autocvar_g_nades_nade_radius, self, world, autocvar_g_nades_nade_force, self.projectiledeathtype, self.enemy);
}
void nade_ice_boom()
-{
+{SELFPARAM();
entity fountain;
fountain = spawn();
fountain.owner = self.owner;
if ( autocvar_g_nades_ice_explode )
{
- setmodel(fountain, "models/grenademodel.md3");
+ setmodel(fountain, MDL_PROJECTILE_GRENADE);
entity timer = spawn();
- setmodel(timer, "models/ok_nade_counter/ok_nade_counter.md3");
+ setmodel(timer, MDL_NADE_TIMER);
setattachment(timer, fountain, "");
timer.classname = "nade_timer";
timer.colormap = self.colormap;
timer.skin = 10;
}
else
- setmodel(fountain, "null");
+ setmodel(fountain, MDL_Null);
}
void nade_translocate_boom()
-{
+{SELFPARAM();
if(self.realowner.vehicle)
return;
}
void nade_spawn_boom()
-{
+{SELFPARAM();
entity spawnloc = spawn();
setorigin(spawnloc, self.origin);
setsize(spawnloc, self.realowner.mins, self.realowner.maxs);
}
void nade_heal_think()
-{
+{SELFPARAM();
if(time >= self.ltime)
{
remove(self);
}
void nade_heal_touch()
-{
+{SELFPARAM();
float maxhealth;
float health_factor;
if(IS_PLAYER(other) || IS_MONSTER(other))
}
void nade_heal_boom()
-{
+{SELFPARAM();
entity healer;
healer = spawn();
healer.owner = self.owner;
healer.solid = SOLID_TRIGGER;
healer.touch = nade_heal_touch;
- setmodel(healer, "models/ctf/shield.md3");
+ setmodel(healer, MDL_NADE_HEAL);
healer.healer_radius = autocvar_g_nades_nade_radius;
vector size = '1 1 1' * healer.healer_radius / 2;
setsize(healer,-size,size);
}
void nade_monster_boom()
-{
+{SELFPARAM();
entity e = spawnmonster(self.pokenade_type, 0, self.realowner, self.realowner, self.origin, false, false, 1);
if(autocvar_g_nades_pokenade_monster_lifetime > 0)
}
void nade_boom()
-{
+{SELFPARAM();
entity expef = NULL;
bool nade_blast = true;
- switch ( NADES[self.nade_type] )
+ switch ( Nades[self.nade_type] )
{
case NADE_TYPE_NAPALM:
nade_blast = autocvar_g_nades_napalm_blast;
default:
case NADE_TYPE_NORMAL:
- switch(self.realowner.team)
- {
- case NUM_TEAM_1: expef = EFFECT_NADE_RED_EXPLODE; break;
- case NUM_TEAM_2: expef = EFFECT_NADE_BLUE_EXPLODE; break;
- case NUM_TEAM_3: expef = EFFECT_NADE_YELLOW_EXPLODE; break;
- case NUM_TEAM_4: expef = EFFECT_NADE_PINK_EXPLODE; break;
- default: expef = EFFECT_NADE_NEUTRAL_EXPLODE; break;
- }
+ expef = EFFECT_NADE_EXPLODE(self.realowner.team);
+ break;
}
if(expef)
Send_Effect(expef, findbetterlocation(self.origin, 8), '0 0 0', 1);
- sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTEN_NORM);
- sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
+ sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
self.event_damage = func_null; // prevent somehow calling damage in the next call
}
if(self.takedamage)
- switch ( NADES[self.nade_type] )
+ switch ( Nades[self.nade_type] )
{
case NADE_TYPE_NAPALM: nade_napalm_boom(); break;
case NADE_TYPE_ICE: nade_ice_boom(); break;
}
void nade_touch()
-{
+{SELFPARAM();
/*float is_weapclip = 0;
if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NODRAW)
if (!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NONSOLID))
//UpdateCSQCProjectile(self);
if(self.health == self.max_health)
{
- spamsound(self, CH_SHOTS, W_Sound(strcat("grenade_bounce", ftos(1 + rint(random() * 5)))), VOL_BASE, ATTEN_NORM);
+ spamsound(self, CH_SHOTS, SND(GRENADE_BOUNCE_RANDOM()), VOL_BASE, ATTEN_NORM);
return;
}
}
void nade_beep()
-{
- sound(self, CH_SHOTS_SINGLE, "overkill/grenadebip.ogg", VOL_BASE, 0.5 *(ATTEN_LARGE + ATTEN_MAX));
+{SELFPARAM();
+ sound(self, CH_SHOTS_SINGLE, SND_NADE_BEEP, VOL_BASE, 0.5 *(ATTEN_LARGE + ATTEN_MAX));
self.think = nade_boom;
self.nextthink = max(self.wait, time);
}
void nade_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
if(ITEM_DAMAGE_NEEDKILL(deathtype))
{
self.takedamage = DAMAGE_NO;
if(self.health == self.max_health)
{
- sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, 0.5 *(ATTEN_LARGE + ATTEN_MAX));
+ sound(self, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, 0.5 *(ATTEN_LARGE + ATTEN_MAX));
self.nextthink = max(time + autocvar_g_nades_nade_lifetime, time);
self.think = nade_beep;
}
}
void toss_nade(entity e, vector _velocity, float _time)
-{
+{SELFPARAM();
if(e.nade == world)
return;
offset = '0 0 0';
setorigin(_nade, w_shotorg + offset + (v_right * 25) * -1);
- //setmodel(_nade, W_Model("v_ok_grenade.md3"));
+ //setmodel(_nade, MDL_PROJECTILE_NADE);
//setattachment(_nade, world, "");
PROJECTILE_MAKETRIGGER(_nade);
setsize(_nade, '-16 -16 -16', '16 16 16');
if ( player.bonus_nade_score >= 1 )
{
Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_NADE_BONUS);
- play2(player,"kh/alarm.wav");
+ play2(player, SND(KH_ALARM));
player.bonus_nades++;
player.bonus_nade_score -= 1;
}
}
float nade_customize()
-{
+{SELFPARAM();
//if(IS_SPEC(other)) { return false; }
if(other == self.realowner || (IS_SPEC(other) && other.enemy == self.realowner))
{
{
//self.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
if(!self.traileffectnum)
- self.traileffectnum = _particleeffectnum(Nade_TrailEffect(NADES[self.nade_type].m_projectile[false], self.team));
+ self.traileffectnum = _particleeffectnum(Nade_TrailEffect(Nades[self.nade_type].m_projectile[false], self.team).eent_eff_name);
self.alpha = 1;
}
}
void nade_prime()
-{
+{SELFPARAM();
if(autocvar_g_nades_bonus_only)
if(!self.bonus_nades)
return; // only allow bonus nades
n.pokenade_type = ((autocvar_g_nades_client_select) ? self.cvar_cl_pokenade_type : autocvar_g_nades_pokenade_monster_type);
}
- n.nade_type = bound(1, n.nade_type, NADES_COUNT);
+ n.nade_type = bound(1, n.nade_type, Nades_COUNT);
- setmodel(n, W_Model("v_ok_grenade.md3"));
+ setmodel(n, MDL_PROJECTILE_NADE);
//setattachment(n, self, "bip01 l hand");
n.exteriormodeltoclient = self;
n.customizeentityforclient = nade_customize;
- n.traileffectnum = _particleeffectnum(Nade_TrailEffect(NADES[n.nade_type].m_projectile[false], self.team));
- n.colormod = NADES[n.nade_type].m_color;
+ n.traileffectnum = _particleeffectnum(Nade_TrailEffect(Nades[n.nade_type].m_projectile[false], self.team).eent_eff_name);
+ n.colormod = Nades[n.nade_type].m_color;
n.realowner = self;
n.colormap = self.colormap;
n.glowmod = self.glowmod;
n.wait = time + autocvar_g_nades_nade_lifetime;
- n.lifetime = time;
+ n.nade_time_primed = time;
n.think = nade_beep;
n.nextthink = max(n.wait - 3, time);
n.projectiledeathtype = DEATH_NADE;
- setmodel(fn, W_Model("h_ok_grenade.iqm"));
+ setmodel(fn, MDL_NADE_VIEW);
setattachment(fn, self.weaponentity, "");
fn.realowner = fn.owner = self;
- fn.colormod = NADES[n.nade_type].m_color;
+ fn.colormod = Nades[n.nade_type].m_color;
fn.colormap = self.colormap;
fn.glowmod = self.glowmod;
fn.think = SUB_Remove;
}
float CanThrowNade()
-{
+{SELFPARAM();
if(self.vehicle)
return false;
return true;
}
+.bool nade_altbutton;
+
void nades_CheckThrow()
-{
+{SELFPARAM();
if(!CanThrowNade())
return;
- if(!self.nade)
+ entity held_nade = self.nade;
+ if (!held_nade)
{
- if(self.nade_refire < time)
+ self.nade_altbutton = true;
+ if(time > self.nade_refire)
{
Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_NADE_THROW);
nade_prime();
}
else
{
- if(time - self.nade.lifetime >= 1)
- {
+ self.nade_altbutton = false;
+ if (time >= held_nade.nade_time_primed + 1) {
makevectors(self.v_angle);
- float _force = time - self.nade.lifetime;
+ float _force = time - held_nade.nade_time_primed;
_force /= autocvar_g_nades_nade_lifetime;
_force = autocvar_g_nades_nade_minforce + (_force * (autocvar_g_nades_nade_maxforce - autocvar_g_nades_nade_minforce));
toss_nade(self, (v_forward * 0.75 + v_up * 0.2 + v_right * 0.05) * _force, 0);
player.nade_timer = 0;
}
-MUTATOR_HOOKFUNCTION(nades_CheckThrow)
-{
- if(MUTATOR_RETURNVALUE) { nades_CheckThrow(); }
- return false;
-}
-
MUTATOR_HOOKFUNCTION(nades_VehicleEnter)
{
if(vh_player.nade)
return false;
}
-MUTATOR_HOOKFUNCTION(nades_PlayerPreThink)
-{
- if(!IS_PLAYER(self)) { return false; }
-
- float key_pressed = self.BUTTON_HOOK;
- float time_score;
-
- if(g_grappling_hook || client_hasweapon(self, WEP_HOOK.m_id, false, false) || (weaponsInMap & WEPSET_HOOK))
- key_pressed = self.button16; // if hook is enabled, use an alternate key
-
- if(self.nade)
- {
- self.nade_timer = bound(0, (time - self.nade.lifetime) / autocvar_g_nades_nade_lifetime, 1);
- //print(sprintf("%d %d\n", self.nade_timer, time - self.nade.lifetime));
- makevectors(self.angles);
- self.nade.velocity = self.velocity;
-
- setorigin(self.nade, self.origin + self.view_ofs + v_forward * 8 + v_right * -8 + v_up * 0);
- self.nade.angles_y = self.angles.y;
- }
-
- if(self.nade)
- if(self.nade.wait - 0.1 <= time)
- toss_nade(self, '0 0 0', time + 0.05);
-
- if(CanThrowNade())
- if(self.nade_refire < time)
- {
- if(key_pressed)
+CLASS(NadeOffhand, OffhandWeapon)
+ METHOD(NadeOffhand, offhand_think, void(NadeOffhand this, entity player, bool key_pressed))
+ {
+ entity held_nade = player.nade;
+ if (held_nade)
{
- if(!self.nade)
- nade_prime();
+ player.nade_timer = bound(0, (time - held_nade.nade_time_primed) / autocvar_g_nades_nade_lifetime, 1);
+ // LOG_TRACEF("%d %d\n", player.nade_timer, time - held_nade.nade_time_primed);
+ makevectors(player.angles);
+ held_nade.velocity = player.velocity;
+ setorigin(held_nade, player.origin + player.view_ofs + v_forward * 8 + v_right * -8 + v_up * 0);
+ held_nade.angles_y = player.angles.y;
+
+ if (time + 0.1 >= held_nade.wait)
+ toss_nade(player, '0 0 0', time + 0.05);
}
- else if(time - self.nade.lifetime >= 1)
- {
- if(self.nade)
- {
- makevectors(self.v_angle);
- float _force = time - self.nade.lifetime;
+
+ if (!CanThrowNade()) return;
+ if (!(time > player.nade_refire)) return;
+ if (key_pressed) {
+ if (!held_nade) {
+ nade_prime();
+ held_nade = player.nade;
+ }
+ } else if (time >= held_nade.nade_time_primed + 1) {
+ if (held_nade) {
+ makevectors(player.v_angle);
+ float _force = time - held_nade.nade_time_primed;
_force /= autocvar_g_nades_nade_lifetime;
_force = autocvar_g_nades_nade_minforce + (_force * (autocvar_g_nades_nade_maxforce - autocvar_g_nades_nade_minforce));
- toss_nade(self, (v_forward * 0.7 + v_up * 0.2 + v_right * 0.1) * _force, 0);
+ toss_nade(player, (v_forward * 0.7 + v_up * 0.2 + v_right * 0.1) * _force, 0);
}
}
+ }
+ENDCLASS(NadeOffhand)
+NadeOffhand OFFHAND_NADE; STATIC_INIT(OFFHAND_NADE) { OFFHAND_NADE = NEW(NadeOffhand); }
+
+MUTATOR_HOOKFUNCTION(nades_CheckThrow)
+{
+ if (self.offhand != OFFHAND_NADE || (self.weapons & WEPSET(HOOK)) || autocvar_g_nades_override_dropweapon) {
+ nades_CheckThrow();
+ return true;
}
+ return false;
+}
+
+MUTATOR_HOOKFUNCTION(nades_PlayerPreThink)
+{SELFPARAM();
+ if (!IS_PLAYER(self)) { return false; }
+
+ if (self.nade && self.offhand != OFFHAND_NADE) OFFHAND_NADE.offhand_think(OFFHAND_NADE, self, self.nade_altbutton);
if(IS_PLAYER(self))
{
float key_count = 0;
FOR_EACH_KH_KEY(key) if(key.owner == self) { ++key_count; }
+ float time_score;
if(self.flagcarried || self.ballcarried) // this player is important
time_score = autocvar_g_nades_bonus_score_time_flagcarrier;
else
self.pokenade_type = autocvar_g_nades_pokenade_monster_type;
}
- self.nade_type = bound(1, self.nade_type, NADES_COUNT);
+ self.nade_type = bound(1, self.nade_type, Nades_COUNT);
if(self.bonus_nade_score >= 0 && autocvar_g_nades_bonus_score_max)
nades_GiveBonus(self, time_score / autocvar_g_nades_bonus_score_max);
}
MUTATOR_HOOKFUNCTION(nades_PlayerSpawn)
-{
+{SELFPARAM();
if(autocvar_g_nades_spawn)
self.nade_refire = time + autocvar_g_spawnshieldtime;
else
self.nade_timer = 0;
+ if (!self.offhand) self.offhand = OFFHAND_NADE;
+
if(self.nade_spawnloc)
{
setorigin(self, self.nade_spawnloc.origin);
}
MUTATOR_HOOKFUNCTION(nades_MonsterDies)
-{
+{SELFPARAM();
if(IS_PLAYER(frag_attacker))
if(DIFF_TEAM(frag_attacker, self))
if(!(self.spawnflags & MONSTERFLAG_SPAWNED))
}
MUTATOR_HOOKFUNCTION(nades_RemovePlayer)
-{
+{SELFPARAM();
nades_Clear(self);
nades_RemoveBonus(self);
return false;
}
MUTATOR_HOOKFUNCTION(nades_SpectateCopy)
-{
+{SELFPARAM();
self.nade_timer = other.nade_timer;
self.nade_type = other.nade_type;
self.pokenade_type = other.pokenade_type;
addstat(STAT_NADE_BONUS_SCORE, AS_FLOAT, bonus_nade_score);
addstat(STAT_HEALING_ORB, AS_FLOAT, stat_healing_orb);
addstat(STAT_HEALING_ORB_ALPHA, AS_FLOAT, stat_healing_orb_alpha);
-
- precache_model("models/ok_nade_counter/ok_nade_counter.md3");
- precache_model(W_Model("h_ok_grenade.iqm"));
- precache_model(W_Model("v_ok_grenade.md3"));
- precache_model("models/ctf/shield.md3");
-
- precache_sound(W_Sound("rocket_impact"));
- precache_sound(W_Sound("grenade_bounce1"));
- precache_sound(W_Sound("grenade_bounce2"));
- precache_sound(W_Sound("grenade_bounce3"));
- precache_sound(W_Sound("grenade_bounce4"));
- precache_sound(W_Sound("grenade_bounce5"));
- precache_sound(W_Sound("grenade_bounce6"));
- precache_sound("overkill/grenadebip.ogg");
}
MUTATOR_DEFINITION(mutator_nades)
}
MUTATOR_HOOKFUNCTION(nt_SetWeaponreplace)
-{
+{SELFPARAM();
// otherwise, we do replace
if(self.new_toys)
{
}
MUTATOR_HOOKFUNCTION(nt_FilterItem)
-{
- if(nt_IsNewToy(self.weapon) && autocvar_g_new_toys_use_pickupsound)
- self.item_pickupsound = W_Sound("weaponpickup_new_toys");
+{SELFPARAM();
+ if(nt_IsNewToy(self.weapon) && autocvar_g_new_toys_use_pickupsound) {
+ self.item_pickupsound = string_null;
+ self.item_pickupsound_ent = SND_WEAPONPICKUP_NEW_TOYS;
+ }
return 0;
}
if(time > 1) // game loads at time 1
error("This cannot be added at runtime\n");
- precache_sound(W_Sound("weaponpickup_new_toys"));
-
// mark the guns as ok to use by e.g. impulse 99
float i;
for(i = WEP_FIRST; i <= WEP_LAST; ++i)
}
void NIX_GiveCurrentWeapon()
-{
+{SELFPARAM();
float dt;
if(!nix_nextweapon)
nix_nextchange = time; // start the first round now!
else
nix_nextchange = time + autocvar_g_balance_nix_roundtime;
- //WEP_ACTION(nix_weapon, WR_INIT); // forget it, too slow
+ // Weapon w = get_weaponinfo(nix_weapon);
+ // w.wr_init(w); // forget it, too slow
}
// get weapon info
else
Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_NIX_NEWWEAPON, nix_weapon);
- WEP_ACTION(nix_weapon, WR_RESETPLAYER);
+ Weapon w = get_weaponinfo(nix_weapon);
+ w.wr_resetplayer(w);
// all weapons must be fully loaded when we spawn
if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars
self.weapons = '0 0 0';
if(g_nix_with_blaster)
- self.weapons |= WEPSET_BLASTER;
+ self.weapons |= WEPSET(BLASTER);
self.weapons |= WepSet_FromWeapon(nix_weapon);
if(self.switchweapon != nix_weapon)
{
float i;
for (i = WEP_FIRST; i <= WEP_LAST; ++i)
- if (NIX_CanChooseWeapon(i))
- WEP_ACTION(i, WR_INIT);
+ if (NIX_CanChooseWeapon(i)) {
+ Weapon w = get_weaponinfo(i);
+ w.wr_init(w);
+ }
}
MUTATOR_HOOKFUNCTION(nix_ForbidThrowCurrentWeapon)
}
MUTATOR_HOOKFUNCTION(nix_FilterItem)
-{
+{SELFPARAM();
switch (self.items)
{
case ITEM_HealthSmall.m_itemid:
}
MUTATOR_HOOKFUNCTION(nix_OnEntityPreSpawn)
-{
+{SELFPARAM();
if(self.classname == "target_items") // items triggers cannot work in nix (as they change weapons/ammo)
return 1;
return 0;
}
MUTATOR_HOOKFUNCTION(nix_PlayerPreThink)
-{
+{SELFPARAM();
if(!intermission_running)
if(self.deadflag == DEAD_NO)
if(IS_PLAYER(self))
}
MUTATOR_HOOKFUNCTION(nix_PlayerSpawn)
-{
+{SELFPARAM();
self.nix_lastchange_id = -1;
NIX_GiveCurrentWeapon(); // overrides the weapons you got when spawning
self.items |= IT_UNLIMITED_SUPERWEAPONS;
}
MUTATOR_DEFINITION(mutator_nix)
-{
+{SELFPARAM();
entity e;
MUTATOR_HOOK(ForbidThrowCurrentWeapon, nix_ForbidThrowCurrentWeapon, CBC_ORDER_ANY);
#include "mutator.qh"
-void W_Blaster_Attack(float, float, float, float, float, float, float, float, float, float);
-void spawnfunc_weapon_hmg();
-void spawnfunc_weapon_rpc();
+void W_Blaster_Attack(entity, float, float, float, float, float, float, float, float, float, float);
+spawnfunc(weapon_hmg);
+spawnfunc(weapon_rpc);
void ok_DecreaseCharge(entity ent, int wep)
{
}
MUTATOR_HOOKFUNCTION(ok_PlayerDamage_SplitHealthArmor)
-{
+{SELFPARAM();
if(damage_take)
self.ok_pauseregen_finished = max(self.ok_pauseregen_finished, time + 2);
return false;
}
MUTATOR_HOOKFUNCTION(ok_PlayerDies)
-{
- entity oldself = self;
+{SELFPARAM();
entity targ = ((frag_attacker) ? frag_attacker : frag_target);
if(IS_MONSTER(self))
other = world;
}
- self = spawn();
+ setself(spawn());
self.ok_item = true;
self.noalign = true;
self.pickup_anyway = true;
- spawnfunc_item_armor_small();
+ spawnfunc_item_armor_small(this);
self.movetype = MOVETYPE_TOSS;
self.gravity = 1;
self.reset = SUB_Remove;
self.velocity = '0 0 200' + normalize(targ.origin - self.origin) * 500;
self.classname = "droppedweapon"; // hax
SUB_SetFade(self, time + 5, 1);
- self = oldself;
+ setself(this);
self.ok_lastwep = self.switchweapon;
}
MUTATOR_HOOKFUNCTION(ok_PlayerRegen)
-{
+{SELFPARAM();
// overkill's values are different, so use custom regen
if(!self.frozen)
{
}
MUTATOR_HOOKFUNCTION(ok_PlayerPreThink)
-{
+{SELFPARAM();
if(intermission_running || gameover)
return false;
int oldwep = self.weapon;
self.weapon = WEP_BLASTER.m_id;
W_Blaster_Attack(
+ self,
WEP_BLASTER.m_id | HITTYPE_SECONDARY,
WEP_CVAR_SEC(vaporizer, shotangle),
WEP_CVAR_SEC(vaporizer, damage),
{
//Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_OVERKILL_CHARGE);
self.ok_notice_time = time + 2;
- play2(self, W_Sound("dryfire"));
+ play2(self, SND(DRYFIRE));
}
+ Weapon wpn = get_weaponinfo(self.weapon);
if(self.weaponentity.state != WS_CLEAR)
- w_ready();
+ w_ready(wpn, self, self.BUTTON_ATCK, self.BUTTON_ATCK2);
self.weapon_blocked = true;
}
}
MUTATOR_HOOKFUNCTION(ok_PlayerSpawn)
-{
+{SELFPARAM();
if(autocvar_g_overkill_ammo_charge)
{
for(int i = WEP_FIRST; i <= WEP_LAST; ++i)
return false;
}
+void _spawnfunc_weapon_hmg() { SELFPARAM(); spawnfunc_weapon_hmg(this); }
+void _spawnfunc_weapon_rpc() { SELFPARAM(); spawnfunc_weapon_rpc(this); }
+
MUTATOR_HOOKFUNCTION(ok_OnEntityPreSpawn)
-{
+{SELFPARAM();
if(autocvar_g_powerups)
if(autocvar_g_overkill_powerups_replace)
{
{
entity wep = spawn();
setorigin(wep, self.origin);
- setmodel(wep, W_Model("g_ok_hmg.md3"));
+ setmodel(wep, MDL_OK_HMG);
wep.classname = "weapon_hmg";
wep.ok_item = true;
wep.noalign = self.noalign;
wep.team = self.team;
wep.respawntime = autocvar_g_overkill_superguns_respawn_time;
wep.pickup_anyway = true;
- wep.think = spawnfunc_weapon_hmg;
+ wep.think = _spawnfunc_weapon_hmg;
wep.nextthink = time + 0.1;
return true;
}
{
entity wep = spawn();
setorigin(wep, self.origin);
- setmodel(wep, W_Model("g_ok_rl.md3"));
+ setmodel(wep, MDL_OK_RPC);
wep.classname = "weapon_rpc";
wep.ok_item = true;
wep.noalign = self.noalign;
wep.team = self.team;
wep.respawntime = autocvar_g_overkill_superguns_respawn_time;
wep.pickup_anyway = true;
- wep.think = spawnfunc_weapon_rpc;
+ wep.think = _spawnfunc_weapon_rpc;
wep.nextthink = time + 0.1;
return true;
}
}
MUTATOR_HOOKFUNCTION(ok_ItemRemove)
-{
+{SELFPARAM();
if(self.ok_item)
return false;
}
MUTATOR_HOOKFUNCTION(ok_SpectateCopy)
-{
+{SELFPARAM();
self.ammo_charge[self.weapon] = other.ammo_charge[other.weapon];
self.ok_use_ammocharge = other.ok_use_ammocharge;
MUTATOR_HOOKFUNCTION(ok_StartItems)
{
- WepSet ok_start_items = (WEPSET_MACHINEGUN | WEPSET_VORTEX | WEPSET_SHOTGUN);
+ WepSet ok_start_items = (WEPSET(MACHINEGUN) | WEPSET(VORTEX) | WEPSET(SHOTGUN));
- if(WEP_RPC.weaponstart > 0) { ok_start_items |= WEPSET_RPC; }
- if(WEP_HMG.weaponstart > 0) { ok_start_items |= WEPSET_HMG; }
+ if(WEP_RPC.weaponstart > 0) { ok_start_items |= WEPSET(RPC); }
+ if(WEP_HMG.weaponstart > 0) { ok_start_items |= WEPSET(HMG); }
start_items |= IT_UNLIMITED_WEAPON_AMMO;
start_weapons = warmup_start_weapons = ok_start_items;
precache_all_playermodels("models/ok_player/*.dpm");
- precache_model(W_Model("h_ok_mg.iqm"));
- precache_model(W_Model("v_ok_mg.md3"));
- precache_model(W_Model("g_ok_mg.md3"));
-
- precache_model(W_Model("h_ok_shotgun.iqm"));
- precache_model(W_Model("v_ok_shotgun.md3"));
- precache_model(W_Model("g_ok_shotgun.md3"));
-
- precache_model(W_Model("h_ok_sniper.iqm"));
- precache_model(W_Model("v_ok_sniper.md3"));
- precache_model(W_Model("g_ok_sniper.md3"));
-
- precache_sound(W_Sound("dryfire"));
-
addstat(STAT_OK_AMMO_CHARGE, AS_FLOAT, ok_use_ammocharge);
addstat(STAT_OK_AMMO_CHARGEPOOL, AS_FLOAT, ok_ammo_charge);
.float ok_item;
.float ok_notice_time;
-.float ammo_charge[WEP_MAXCOUNT];
+.float ammo_charge[Weapons_MAX];
.float ok_use_ammocharge;
.float ok_ammo_charge;
.vector spawn_origin, spawn_angles;
void physical_item_think()
-{
+{SELFPARAM();
self.nextthink = time;
self.alpha = self.owner.alpha; // apply fading and ghosting
}
void physical_item_touch()
-{
+{SELFPARAM();
if(!self.cnt) // not for dropped items
if (ITEM_TOUCH_NEEDKILL())
{
}
void physical_item_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
if(!self.cnt) // not for dropped items
if(ITEM_DAMAGE_NEEDKILL(deathtype))
{
}
MUTATOR_HOOKFUNCTION(item_spawning)
-{
+{SELFPARAM();
if(self.owner == world && autocvar_g_physical_items <= 1)
return false;
if (self.spawnflags & 1) // floating item
// Ugly hack, but unless SOLID_TRIGGER is gotten to work with MOVETYPE_PHYSICS in the engine it can't be fixed.
entity wep;
wep = spawn();
- setmodel(wep, self.model);
+ _setmodel(wep, self.model);
setsize(wep, self.mins, self.maxs);
setorigin(wep, self.origin);
wep.angles = self.angles;
setorigin(wep, wep.origin + '0 0 1');
entity oldself;
oldself = self;
- self = wep;
- builtin_droptofloor();
- self = oldself;
+ WITH(entity, self, wep, builtin_droptofloor());
}
wep.spawn_origin = wep.origin;
#include "mutator.qh"
MUTATOR_HOOKFUNCTION(pinata_PlayerDies)
-{
+{SELFPARAM();
float j;
for(j = WEP_FIRST; j <= WEP_LAST; ++j)
if(self.weapons & WepSet_FromWeapon(j))
.float cvar_cl_spawn_near_teammate;
MUTATOR_HOOKFUNCTION(msnt_Spawn_Score)
-{
+{SELFPARAM();
if(autocvar_g_spawn_near_teammate_ignore_spawnpoint == 1 || (autocvar_g_spawn_near_teammate_ignore_spawnpoint == 2 && self.cvar_cl_spawn_near_teammate))
return 0;
}
MUTATOR_HOOKFUNCTION(msnt_PlayerSpawn)
-{
+{SELFPARAM();
// Note: when entering this, fixangle is already set.
if(autocvar_g_spawn_near_teammate_ignore_spawnpoint == 1 || (autocvar_g_spawn_near_teammate_ignore_spawnpoint == 2 && self.cvar_cl_spawn_near_teammate))
{
}
MUTATOR_HOOKFUNCTION(msnt_PlayerDies)
-{
+{SELFPARAM();
self.msnt_deathloc = self.origin;
return 0;
}
.string superspec_itemfilter; //"classname1 classname2 ..."
float _spectate(entity _player)
-{
+{SELFPARAM();
if(Spectate(_player) == 1)
self.classname = "spectator";
}
void superspec_save_client_conf()
-{
+{SELFPARAM();
string fn = "superspec-local.options";
float fh;
}
MUTATOR_HOOKFUNCTION(superspec_ItemTouch)
-{
- entity _oldself = self;
+{SELFPARAM();
entity _item = self;
- FOR_EACH_SPEC(self)
+ entity e;
+ FOR_EACH_SPEC(e)
{
+ setself(e);
if(self.superspec_flags & SSF_ITEMMSG)
if(superspec_filteritem(self, _item))
{
{
_spectate(other);
- self = _oldself;
+ setself(this);
return MUT_ITEMTOUCH_CONTINUE;
}
}
}
}
- self = _oldself;
+ setself(this);
return MUT_ITEMTOUCH_CONTINUE;
}
MUTATOR_HOOKFUNCTION(superspec_SV_ParseClientCommand)
-{
+{SELFPARAM();
#define OPTIONINFO(flag,var,test,text,long,short) \
var = strcat(var, ((flag & test) ? "^2[ON] ^7" : "^1[OFF] ^7")); \
var = strcat(var, text," ^7(^3 ", long, "^7 | ^3", short, " ^7)\n")
}
void superspec_hello()
-{
+{SELFPARAM();
if(self.enemy.crypto_idfp == "")
Send_Notification(NOTIF_ONE_ONLY, self.enemy, MSG_INFO, INFO_SUPERSPEC_MISSING_UID);
}
MUTATOR_HOOKFUNCTION(superspec_ClientConnect)
-{
+{SELFPARAM();
if(!IS_REAL_CLIENT(self))
return false;
}
MUTATOR_HOOKFUNCTION(superspec_PlayerDies)
-{
- entity _old_self = self;
-
- FOR_EACH_SPEC(self)
+{SELFPARAM();
+ entity e;
+ FOR_EACH_SPEC(e)
{
- if(self.autospec_flags & ASF_FOLLOWKILLER && IS_PLAYER(frag_attacker) && self.enemy == _old_self)
+ setself(e);
+ if(self.autospec_flags & ASF_FOLLOWKILLER && IS_PLAYER(frag_attacker) && self.enemy == this)
{
if(self.autospec_flags & ASF_SHOWWHAT)
superspec_msg("", "", self, sprintf("^7Following %s^7 due to followkiller\n", frag_attacker.netname), 2);
}
}
- self = _old_self;
+ setself(this);
return false;
}
.float touchexplode_time;
void PlayerTouchExplode(entity p1, entity p2)
-{
+{SELFPARAM();
vector org;
org = (p1.origin + p2.origin) * 0.5;
org.z += (p1.mins.z + p2.mins.z) * 0.5;
- sound(self, CH_TRIGGER, W_Sound("grenade_impact"), VOL_BASE, ATTEN_NORM);
+ sound(self, CH_TRIGGER, SND_GRENADE_IMPACT, VOL_BASE, ATTEN_NORM);
Send_Effect(EFFECT_EXPLOSION_SMALL, org, '0 0 0', 1);
entity e;
}
MUTATOR_HOOKFUNCTION(touchexplode_PlayerThink)
-{
+{SELFPARAM();
if(time > self.touchexplode_time)
if(!gameover)
if(!self.frozen)
.float last_dmg;
MUTATOR_HOOKFUNCTION(vh, GrappleHookThink)
-{
+{SELFPARAM();
entity dmgent = ((SAME_TEAM(self.owner, self.aiment) && autocvar_g_vampirehook_teamheal) ? self.owner : self.aiment);
if(IS_PLAYER(self.aiment))
#include "../../common/stats.qh"
#include "../../common/teams.qh"
#include "../../common/util.qh"
- #include "../../common/nades.qh"
- #include "../../common/buffs.qh"
+ #include "../../common/nades/all.qh"
+ #include "../../common/buffs/all.qh"
#include "../../common/command/markup.qh"
#include "../../common/command/rpn.qh"
#include "../../common/command/generic.qh"
#endif
#include "../../common/mutators/base.qh"
+
#include "gamemode_assault.qc"
#include "gamemode_ca.qc"
#include "gamemode_ctf.qc"
+#include "gamemode_cts.qc"
+#include "gamemode_deathmatch.qc"
#include "gamemode_domination.qc"
#include "gamemode_freezetag.qc"
-#include "gamemode_keyhunt.qc"
+#include "gamemode_invasion.qc"
#include "gamemode_keepaway.qc"
+#include "gamemode_keyhunt.qc"
+#include "gamemode_lms.qc"
#include "gamemode_nexball.qc"
#include "gamemode_onslaught.qc"
-#include "gamemode_lms.qc"
-#include "gamemode_invasion.qc"
#include "gamemode_race.qc"
-#include "gamemode_cts.qc"
#include "gamemode_tdm.qc"
-#include "gamemode_deathmatch.qc"
+#include "mutator_bloodloss.qc"
+#include "mutator_breakablehook.qc"
+#include "mutator_buffs.qc"
+#include "mutator_campcheck.qc"
+#include "mutator_dodging.qc"
+#include "mutator_hook.qc"
+#include "mutator_instagib.qc"
#include "mutator_invincibleproj.qc"
+#include "mutator_melee_only.qc"
+#include "mutator_midair.qc"
+#include "mutator_multijump.qc"
+#include "mutator_nades.qc"
#include "mutator_new_toys.qc"
#include "mutator_nix.qc"
-#include "mutator_dodging.qc"
-#include "mutator_rocketflying.qc"
-#include "mutator_vampire.qc"
-#include "mutator_spawn_near_teammate.qc"
-#include "mutator_physical_items.qc"
-#include "sandbox.qc"
-#include "mutator_superspec.qc"
#include "mutator_overkill.qc"
-#include "mutator_instagib.qc"
-#include "mutator_touchexplode.qc"
+#include "mutator_physical_items.qc"
#include "mutator_pinata.qc"
-#include "mutator_midair.qc"
-#include "mutator_bloodloss.qc"
#include "mutator_random_gravity.qc"
-#include "mutator_multijump.qc"
-#include "mutator_melee_only.qc"
-#include "mutator_nades.qc"
-#include "mutator_campcheck.qc"
-#include "mutator_buffs.qc"
+#include "mutator_rocketflying.qc"
#include "mutator_rocketminsta.qc"
+#include "mutator_spawn_near_teammate.qc"
+#include "mutator_superspec.qc"
+#include "mutator_touchexplode.qc"
#include "mutator_vampirehook.qc"
-#include "mutator_breakablehook.qc"
+#include "mutator_vampire.qc"
+
+#include "sandbox.qc"
#include "../../common/mutators/base.qh"
#include "mutators.qh"
+
#include "gamemode_assault.qh"
#include "gamemode_ca.qh"
#include "gamemode_ctf.qh"
+#include "gamemode_cts.qh"
#include "gamemode_domination.qh"
-#include "gamemode_keyhunt.qh"
+#include "gamemode_invasion.qh"
#include "gamemode_keepaway.qh"
-#include "gamemode_nexball.qh"
+#include "gamemode_keyhunt.qh"
#include "gamemode_lms.qh"
-#include "gamemode_invasion.qh"
-#include "gamemode_race.qh"
-#include "gamemode_cts.qh"
+#include "gamemode_nexball.qh"
#include "gamemode_onslaught.qh"
+#include "gamemode_race.qh"
+#include "mutator_buffs.qh"
#include "mutator_dodging.qh"
-#include "mutator_overkill.qh"
#include "mutator_nades.qh"
-#include "mutator_buffs.qh"
+#include "mutator_overkill.qh"
#endif
.float touch_timer;
void sandbox_ObjectFunction_Touch()
-{
+{SELFPARAM();
// apply material impact effects
if(!self.material)
intensity -= autocvar_g_sandbox_object_material_velocity_min; // start from minimum velocity, not actual velocity
intensity = bound(0, intensity * autocvar_g_sandbox_object_material_velocity_factor, 1);
- sound(self, CH_TRIGGER, strcat("object/impact_", self.material, "_", ftos(ceil(random() * 5)) , ".wav"), VOL_BASE * intensity, ATTEN_NORM);
+ _sound(self, CH_TRIGGER, strcat("object/impact_", self.material, "_", ftos(ceil(random() * 5)) , ".wav"), VOL_BASE * intensity, ATTEN_NORM);
Send_Effect_(strcat("impact_", self.material), self.origin, '0 0 0', ceil(intensity * 10)); // allow a count from 1 to 10
}
void sandbox_ObjectFunction_Think()
-{
+{SELFPARAM();
entity e;
// decide if and how this object can be grabbed
self.nextthink = time;
- CSQCMODEL_AUTOUPDATE();
+ CSQCMODEL_AUTOUPDATE(self);
}
.float old_solid, old_movetype;
entity sandbox_ObjectEdit_Get(float permissions)
-{
+{SELFPARAM();
// Returns the traced entity if the player can edit it, and world if not.
// If permissions if false, the object is returned regardless of editing rights.
// Attached objects are SOLID_NOT and do not get traced.
if(e.scale)
{
e.scale = bound(autocvar_g_sandbox_object_scale_min, e.scale, autocvar_g_sandbox_object_scale_max);
- setmodel(e, e.model); // reset mins and maxs based on mesh
+ _setmodel(e, e.model); // reset mins and maxs based on mesh
setsize(e, e.mins * e.scale, e.maxs * e.scale); // adapt bounding box size to model size
}
}
}
entity sandbox_ObjectSpawn(float database)
-{
+{SELFPARAM();
// spawn a new object with default properties
- entity e, oldself;
- e = spawn();
+ entity e = spawn();
e.classname = "object";
e.takedamage = DAMAGE_AIM;
e.damageforcescale = 1;
e.angles_y = self.v_angle.y;
}
- oldself = self;
- self = e;
- CSQCMODEL_AUTOINIT();
- self = oldself;
+ WITH(entity, self, e, CSQCMODEL_AUTOINIT(e));
object_count += 1;
return e;
parent = e; // mark parent objects as such
}
// properties stored for all objects
- setmodel(e, argv(argv_num)); ++argv_num;
+ _setmodel(e, argv(argv_num)); ++argv_num;
e.skin = stof(argv(argv_num)); ++argv_num;
e.alpha = stof(argv(argv_num)); ++argv_num;
e.colormod = stov(argv(argv_num)); ++argv_num;
}
MUTATOR_HOOKFUNCTION(sandbox_PlayerCommand)
-{
+{SELFPARAM();
if(MUTATOR_RETURNVALUE) // command was already handled?
return false;
if(cmd_name == "g_sandbox")
}
e = sandbox_ObjectSpawn(false);
- setmodel(e, argv(2));
+ _setmodel(e, argv(2));
if(autocvar_g_sandbox_info > 0)
LOG_INFO(strcat("^3SANDBOX - SERVER: ^7", self.netname, " spawned an object at origin ^3", vtos(e.origin), "\n"));
+++ /dev/null
-#include "pathlib.qh"
-#include "_all.qh"
-
-#define medium spawnshieldtime
-
-//#define DEBUGPATHING
-#ifdef DEBUGPATHING
-float edge_show(vector point,float fsize);
-void mark_error(vector where,float lifetime);
-void mark_info(vector where,float lifetime);
-entity mark_misc(vector where,float lifetime);
-
-void pathlib_showpath(entity start)
-{
- entity e;
- e = start;
- while(e.path_next)
- {
- te_lightning1(e,e.origin,e.path_next.origin);
- e = e.path_next;
- }
-}
-
-void path_dbg_think()
-{
- pathlib_showpath(self);
- self.nextthink = time + 1;
-}
-
-void __showpath2_think()
-{
- mark_info(self.origin,1);
- if(self.path_next)
- {
- self.path_next.think = __showpath2_think;
- self.path_next.nextthink = time + 0.15;
- }
- else
- {
- self.owner.think = __showpath2_think;
- self.owner.nextthink = time + 0.15;
- }
-}
-
-void pathlib_showpath2(entity path)
-{
- path.think = __showpath2_think;
- path.nextthink = time;
-}
-
-#endif
-
-void pathlib_deletepath(entity start)
-{
- entity e;
-
- e = findchainentity(owner, start);
- while(e)
- {
- e.think = SUB_Remove;
- e.nextthink = time;
- e = e.chain;
- }
-}
-
-float walknode_stepsize;
-vector walknode_stepup;
-vector walknode_maxdrop;
-vector walknode_boxup;
-vector walknode_boxmax;
-vector walknode_boxmin;
-float pathlib_movenode_goodnode;
-
-float floor_ok(vector point)
-{
- float pc;
-
- if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
- return 0;
-
- pc = pointcontents(point);
-
- switch(pc)
- {
- case CONTENT_SOLID:
- case CONTENT_SLIME:
- case CONTENT_LAVA:
- case CONTENT_SKY:
- return 0;
- case CONTENT_EMPTY:
- if(pointcontents(point - '0 0 1') != CONTENT_SOLID)
- return 0;
- break;
- case CONTENT_WATER:
- return 1;
- }
- if(pointcontents(point - '0 0 1') == CONTENT_SOLID)
- return 1;
-
- return 0;
-}
-
-#define _pcheck(p) traceline(p+z_up,p-z_down,MOVE_WORLDONLY,self); if (!floor_ok(trace_endpos)) return 1
-float edge_check(vector point,float fsize)
-{
- vector z_up,z_down;
-
- z_up = '0 0 1' * fsize;
- z_down = '0 0 1' * fsize;
-
- _pcheck(point + ('1 1 0' * fsize));
- _pcheck(point + ('1 -1 0' * fsize));
- _pcheck(point + ('1 0 0' * fsize));
-
- _pcheck(point + ('0 1 0' * fsize));
- _pcheck(point + ('0 -1 0' * fsize));
-
- _pcheck(point + ('-1 0 0' * fsize));
- _pcheck(point + ('-1 1 0' * fsize));
- _pcheck(point + ('-1 -1 0' * fsize));
-
- return 0;
-}
-
-#ifdef DEBUGPATHING
-#define _pshow(p) mark_error(p,10)
-float edge_show(vector point,float fsize)
-{
-
- _pshow(point + ('1 1 0' * fsize));
- _pshow(point + ('1 -1 0' * fsize));
- _pshow(point + ('1 0 0' * fsize));
-
- _pshow(point + ('0 1 0' * fsize));
- _pshow(point + ('0 -1 0' * fsize));
-
- _pshow(point + ('-1 0 0' * fsize));
- _pshow(point + ('-1 1 0' * fsize));
- _pshow(point + ('-1 -1 0' * fsize));
-
- return 0;
-}
-#endif
-
-var vector pathlib_movenode(vector start,vector end,float doedge);
-vector pathlib_wateroutnode(vector start,vector end,float doedge)
-{
- vector surface;
-
- pathlib_movenode_goodnode = 0;
-
- end.x = fsnap(end.x, pathlib_gridsize);
- end.y = fsnap(end.y, pathlib_gridsize);
-
- traceline(end + ('0 0 0.25' * pathlib_gridsize),end - ('0 0 1' * pathlib_gridsize),MOVE_WORLDONLY,self);
- end = trace_endpos;
-
- if(pointcontents(end - '0 0 1') != CONTENT_SOLID)
- return end;
-
- for(surface = start ; surface.z < (end.z + 32); ++surface.z)
- {
- if(pointcontents(surface) == CONTENT_EMPTY)
- break;
- }
-
- if(pointcontents(surface + '0 0 1') != CONTENT_EMPTY)
- return end;
-
- tracebox(start + '0 0 64', walknode_boxmin,walknode_boxmax, end + '0 0 64', MOVE_WORLDONLY, self);
- if(trace_fraction == 1)
- pathlib_movenode_goodnode = 1;
-
- if(fabs(surface.z - end.z) > 32)
- pathlib_movenode_goodnode = 0;
-
- return end;
-}
-
-vector pathlib_swimnode(vector start,vector end,float doedge)
-{
- pathlib_movenode_goodnode = 0;
-
- if(pointcontents(start) != CONTENT_WATER)
- return end;
-
- end.x = fsnap(end.x, pathlib_gridsize);
- end.y = fsnap(end.y, pathlib_gridsize);
-
- if(pointcontents(end) == CONTENT_EMPTY)
- return pathlib_wateroutnode( start, end, doedge);
-
- tracebox(start, walknode_boxmin,walknode_boxmax, end, MOVE_WORLDONLY, self);
- if(trace_fraction == 1)
- pathlib_movenode_goodnode = 1;
-
- return end;
-}
-
-vector pathlib_flynode(vector start,vector end)
-{
- pathlib_movenode_goodnode = 0;
-
- end.x = fsnap(end.x, pathlib_gridsize);
- end.y = fsnap(end.y, pathlib_gridsize);
-
- tracebox(start, walknode_boxmin,walknode_boxmax, end, MOVE_WORLDONLY, self);
- if(trace_fraction == 1)
- pathlib_movenode_goodnode = 1;
-
- return end;
-}
-
-vector pathlib_walknode(vector start,vector end,float doedge)
-{
- vector direction,point,last_point,s,e;
- float steps, distance, i,laststep;
-
- pathlib_movenode_goodnode = 0;
-
- s = start;
- e = end;
- e.z = 0;
- s.z = 0;
- direction = normalize(s - e);
-
- distance = vlen(start - end);
- laststep = distance / walknode_stepsize;
- steps = floor(laststep);
- laststep = laststep - steps;
-
- point = start;
- s = point + walknode_stepup;
- e = point - walknode_maxdrop;
-
- traceline(s, e,MOVE_WORLDONLY,self);
- if(trace_fraction == 1.0)
- return trace_endpos;
-
- if (floor_ok(trace_endpos) == 0)
- return trace_endpos;
-
- last_point = trace_endpos;
-
- for(i = 0; i < steps; ++i)
- {
- point = last_point + direction * walknode_stepsize;
-
- s = point + walknode_stepup;
- e = point - walknode_maxdrop;
- traceline(s, e,MOVE_WORLDONLY,self);
- if(trace_fraction == 1.0)
- return trace_endpos;
-
- point = trace_endpos;
- if (!floor_ok(trace_endpos))
- return trace_endpos;
-
- tracebox(last_point + walknode_boxup, walknode_boxmin,walknode_boxmax, point + walknode_boxup, MOVE_WORLDONLY, self);
- if(trace_fraction != 1.0)
- return trace_endpos;
-
- if(doedge)
- if(edge_check(point,pathlib_edge_check_size))
- return trace_endpos;
-
- last_point = point;
- }
-
- point = last_point + direction * walknode_stepsize * laststep;
-
- point.x = fsnap(point.x, pathlib_gridsize);
- point.y = fsnap(point.y, pathlib_gridsize);
-
- s = point + walknode_stepup;
- e = point - walknode_maxdrop;
- traceline(s, e,MOVE_WORLDONLY,self);
-
- if(trace_fraction == 1.0)
- return trace_endpos;
-
- point = trace_endpos;
-
- if (!floor_ok(trace_endpos))
- return trace_endpos;
-
- tracebox(last_point + walknode_boxup, walknode_boxmin,walknode_boxmax, point + walknode_boxup, MOVE_WORLDONLY, self);
- if(trace_fraction != 1.0)
- return trace_endpos;
-
- pathlib_movenode_goodnode = 1;
- return point;
-}
-
-var float pathlib_cost(entity parent,vector to, float static_cost);
-float pathlib_g_static(entity parent,vector to, float static_cost)
-{
- if(inwater(to))
- return parent.pathlib_node_g + static_cost * pathlib_movecost_waterfactor;
- else
- return parent.pathlib_node_g + static_cost;
-}
-
-float pathlib_g_static_water(entity parent,vector to, float static_cost)
-{
- if(inwater(to))
- return parent.pathlib_node_g + static_cost * pathlib_movecost_waterfactor;
- else
- return parent.pathlib_node_g + static_cost;
-}
-
-float pathlib_g_euclidean(entity parent,vector to, float static_cost)
-{
- return parent.pathlib_node_g + vlen(parent.origin - to);
-}
-float pathlib_g_euclidean_water(entity parent,vector to, float static_cost)
-{
- if(inwater(to))
- return parent.pathlib_node_g + vlen(parent.origin - to) * pathlib_movecost_waterfactor;
- else
- return parent.pathlib_node_g + vlen(parent.origin - to);
-}
-
-var float(vector from,vector to) pathlib_heuristic;
-
-/**
- Manhattan Menas we expect to move up,down left or right
- No diagonal moves espected. (like moving bewteen city blocks)
-**/
-float pathlib_h_manhattan(vector a,vector b)
-{
- //h(n) = D * (abs(n.x-goal.x) + abs(n.y-goal.y))
-
- float h;
- h = fabs(a.x - b.x);
- h += fabs(a.y - b.y);
- h *= pathlib_gridsize;
-
- return h;
-}
-
-/**
- This heuristic consider both stright and disagonal moves
- to have teh same cost.
-**/
-float pathlib_h_diagonal(vector a,vector b)
-{
- //h(n) = D * max(abs(n.x-goal.x), abs(n.y-goal.y))
- float h,x,y;
-
- x = fabs(a.x - b.x);
- y = fabs(a.y - b.y);
- h = pathlib_movecost * max(x,y);
-
- return h;
-}
-
-/**
- This heuristic only considers the stright line distance.
- Will usualy mean a lower H then G meaning A* Will speand more
- and run slower.
-**/
-float pathlib_h_euclidean(vector a,vector b)
-{
- return vlen(a - b);
-}
-
-/**
- This heuristic consider both stright and disagonal moves,
- But has a separate cost for diagonal moves.
-**/
-float pathlib_h_diagonal2(vector a,vector b)
-{
- float h_diag,h_str,h,x,y;
-
- /*
- h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
- h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
- h(n) = D2 * h_diagonal(n) + D * (h_straight(n) - 2*h_diagonal(n)))
- */
-
- x = fabs(a.x - b.x);
- y = fabs(a.y - b.y);
-
- h_diag = min(x,y);
- h_str = x + y;
-
- h = pathlib_movecost_diag * h_diag;
- h += pathlib_movecost * (h_str - 2 * h_diag);
-
- return h;
-}
-
-/**
- This heuristic consider both stright and disagonal moves,
- But has a separate cost for diagonal moves.
-
-
-**/
-float pathlib_h_diagonal2sdp(vector preprev,vector prev,vector point,vector end)
-{
- float h_diag,h_str,h,x,y,z;
-
- //h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
- //h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
- //h(n) = D2 * h_diagonal(n) + D * (h_straight(n) - 2*h_diagonal(n)))
-
- x = fabs(point.x - end.x);
- y = fabs(point.y - end.y);
- z = fabs(point.z - end.z);
-
- h_diag = min3(x,y,z);
- h_str = x + y + z;
-
- h = pathlib_movecost_diag * h_diag;
- h += pathlib_movecost * (h_str - 2 * h_diag);
-
- float m;
- vector d1,d2;
-
- d1 = normalize(preprev - point);
- d2 = normalize(prev - point);
- m = vlen(d1-d2);
- //bprint("pathlib_h_diagonal2sdp-M = ",ftos(m),"\n");
-
- return h * m;
-}
-
-
-float pathlib_h_diagonal3(vector a,vector b)
-{
- float h_diag,h_str,h,x,y,z;
-
- //h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
- //h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
- //h(n) = D2 * h_diagonal(n) + D * (h_straight(n) - 2*h_diagonal(n)))
-
- x = fabs(a.x - b.x);
- y = fabs(a.y - b.y);
- z = fabs(a.z - b.z);
-
- h_diag = min3(x,y,z);
- h_str = x + y + z;
-
- h = pathlib_movecost_diag * h_diag;
- h += pathlib_movecost * (h_str - 2 * h_diag);
-
- return h;
-}
-
-const float PATHLIB_NODEEXPIRE = 0.05;
-float pathlib_scraplist_cnt;
-entity newnode()
-{
- entity n;
-#ifdef PATHLIB_USE_NODESCRAP
- if(pathlib_scraplist_cnt)
- {
- n = findentity(world,owner,scraplist);
- if(n)
- {
- --pathlib_scraplist_cnt;
- ++pathlib_recycle_cnt;
- return n;
- }
- else
- pathlib_scraplist_cnt = 0;
- }
-#endif
- ++pathlib_made_cnt;
- n = spawn();
- n.think = SUB_Remove;
- n.nextthink = time + PATHLIB_NODEEXPIRE;
- return n;
-}
-
-void dumpnode(entity n)
-{
-#ifdef PATHLIB_USE_NODESCRAP
- ++pathlib_scraplist_cnt;
-
- n.path_next = world;
- n.path_prev = world;
- n.is_path_node = false;
- n.owner = scraplist;
-#else
- //n.is_path_node = false;
- n.think = SUB_Remove;
- n.nextthink = time;
-#endif
-}
-
-entity pathlib_mknode(vector where,entity parent)
-{
- entity node;
-
- node = newnode();
- node.is_path_node = true;
- node.owner = openlist;
- node.path_prev = parent;
-
- setorigin(node, where);
-
- ++pathlib_open_cnt;
-
- node.medium = pointcontents(where);
-
- return node;
-}
-
-var float pathlib_expandnode(entity node, vector start, vector goal);
-float pathlib_expandnode_star(entity node, vector start, vector goal);
-float pathlib_expandnode_box(entity node, vector start, vector goal);
-
-var float pathlib_makenode(entity parent,vector start, vector to, vector goal,float cost);
-float pathlib_makenode_adaptive(entity parent,vector start, vector to, vector goal,float cost)
-{
- entity node;
- float h,g,f,doedge;
- vector where;
-
- ++pathlib_searched_cnt;
-
- if(inwater(parent.origin))
- {
- pathlib_expandnode = pathlib_expandnode_box;
- pathlib_movenode = pathlib_swimnode;
- doedge = 0;
- }
- else
- {
- if(inwater(to))
- {
- pathlib_expandnode = pathlib_expandnode_box;
- pathlib_movenode = pathlib_swimnode;
- doedge = 0;
- }
- else
- {
-
- pathlib_expandnode = pathlib_expandnode_star;
- pathlib_movenode = pathlib_walknode;
- doedge = 1;
- }
- }
-
- where = pathlib_movenode(parent.origin,to,0);
- if (!pathlib_movenode_goodnode)
- return 0;
-
- if(doedge)
- if(edge_check(where,pathlib_edge_check_size))
- return 0;
-
- if(parent.path_prev)
- pathlib_h_diagonal2sdp(parent.path_prev.origin,parent.origin,where,goal);
-
- h = pathlib_heuristic(where,goal);
- g = pathlib_cost(parent,where,cost);
- f = g + h;
-
- node = findradius(where,pathlib_gridsize * 0.75);
- while(node)
- {
- if(node.is_path_node == true)
- {
- ++pathlib_merge_cnt;
- if(node.owner == openlist)
- {
- if(node.pathlib_node_g > g)
- {
- node.pathlib_node_h = h;
- node.pathlib_node_g = g;
- node.pathlib_node_f = f;
- node.path_prev = parent;
- }
-
- if (!best_open_node)
- best_open_node = node;
- else if(best_open_node.pathlib_node_f > node.pathlib_node_f)
- best_open_node = node;
- }
-
- return 1;
- }
- node = node.chain;
- }
-
- node = pathlib_mknode(where,parent);
- node.pathlib_node_h = h;
- node.pathlib_node_g = g;
- node.pathlib_node_f = f;
-
- if (!best_open_node)
- best_open_node = node;
- else if(best_open_node.pathlib_node_f > node.pathlib_node_f)
- best_open_node = node;
-
- return 1;
-}
-
-entity pathlib_getbestopen()
-{
- entity node;
- entity bestnode;
-
- if(best_open_node)
- {
- ++pathlib_bestcash_hits;
- pathlib_bestcash_saved += pathlib_open_cnt;
-
- return best_open_node;
- }
-
- node = findchainentity(owner,openlist);
- if(!node)
- return world;
-
- bestnode = node;
- while(node)
- {
- ++pathlib_bestopen_seached;
- if(node.pathlib_node_f < bestnode.pathlib_node_f)
- bestnode = node;
-
- node = node.chain;
- }
-
- return bestnode;
-}
-
-void pathlib_close_node(entity node,vector goal)
-{
-
- if(node.owner == closedlist)
- {
- LOG_TRACE("Pathlib: Tried to close a closed node!\n");
- return;
- }
-
- if(node == best_open_node)
- best_open_node = world;
-
- ++pathlib_closed_cnt;
- --pathlib_open_cnt;
-
- node.owner = closedlist;
-
- if(vlen(node.origin - goal) <= pathlib_gridsize)
- {
- vector goalmove;
-
- goalmove = pathlib_walknode(node.origin,goal,1);
- if(pathlib_movenode_goodnode)
- {
- goal_node = node;
- pathlib_foundgoal = true;
- }
- }
-}
-
-float pathlib_expandnode_star(entity node, vector start, vector goal)
-{
- vector point;
- vector where;
- float nodecnt = 0;
-
- where = node.origin;
-
- v_forward = '1 0 0';
- v_right = '0 1 0';
-
- // Forward
- point = where + v_forward * pathlib_gridsize;
- nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost);
-
- // Back
- point = where - v_forward * pathlib_gridsize;
- nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost);
-
- // Right
- point = where + v_right * pathlib_gridsize;
- nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost);
-
- // Left
- point = where - v_right * pathlib_gridsize;
- nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost);
-
- // Forward-right
- point = where + v_forward * pathlib_gridsize + v_right * pathlib_gridsize;
- nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
-
- // Forward-left
- point = where + v_forward * pathlib_gridsize - v_right * pathlib_gridsize;
- nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
-
- // Back-right
- point = where - v_forward * pathlib_gridsize + v_right * pathlib_gridsize;
- nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
-
- // Back-left
- point = where - v_forward * pathlib_gridsize - v_right * pathlib_gridsize;
- nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
-
- return pathlib_open_cnt;
-}
-
-float pathlib_expandnode_box(entity node, vector start, vector goal)
-{
- vector v;
-
- for(v.z = node.origin.z - pathlib_gridsize; v.z <= node.origin.z + pathlib_gridsize; v.z += pathlib_gridsize)
- for(v.y = node.origin.y - pathlib_gridsize; v.y <= node.origin.y + pathlib_gridsize; v.y += pathlib_gridsize)
- for(v.x = node.origin.x - pathlib_gridsize; v.x <= node.origin.x + pathlib_gridsize; v.x += pathlib_gridsize)
- {
- if(vlen(v - node.origin))
- pathlib_makenode(node,start,v,goal,pathlib_movecost);
- }
-
- return pathlib_open_cnt;
-}
-
-void pathlib_cleanup()
-{
- entity node;
-
- node = findfloat(world,is_path_node, true);
- while(node)
- {
- dumpnode(node);
- node = findfloat(node,is_path_node, true);
- }
-
- if(openlist)
- remove(openlist);
-
- if(closedlist)
- remove(closedlist);
-
- best_open_node = world;
- openlist = world;
- closedlist = world;
-}
-
-var float buildpath_nodefilter(vector n,vector c,vector p);
-float buildpath_nodefilter_directional(vector n,vector c,vector p)
-{
- vector d1,d2;
-
- d2 = normalize(p - c);
- d1 = normalize(c - n);
-
- if(vlen(d1-d2) < 0.25)
- return 1;
-
- return 0;
-}
-
-float buildpath_nodefilter_moveskip(vector n,vector c,vector p)
-{
- pathlib_walknode(p,n,1);
- if(pathlib_movenode_goodnode)
- return 1;
-
- return 0;
-}
-
-entity path_build(entity next, vector where, entity prev, entity start)
-{
- entity path;
-
- if(prev && next)
- if(buildpath_nodefilter)
- if(buildpath_nodefilter(next.origin,where,prev.origin))
- return next;
-
-
- path = spawn();
- path.owner = start;
- path.path_next = next;
-
- setorigin(path,where);
-
- if(!next)
- path.classname = "path_end";
- else
- {
- if(!prev)
- path.classname = "path_start";
- else
- path.classname = "path_node";
- }
-
- return path;
-}
-
-entity pathlib_astar(vector from,vector to)
-{
- entity path, start, end, open, n, ln;
- float ptime, ftime, ctime;
-
- ptime = gettime(GETTIME_REALTIME);
-
- pathlib_cleanup();
-
- // Select water<->land capable node make/link
- pathlib_makenode = pathlib_makenode_adaptive;
- // Select XYZ cost estimate
- pathlib_heuristic = pathlib_h_diagonal3;
- // Select distance + waterfactor cost
- pathlib_cost = pathlib_g_euclidean_water;
- // Select star expander
- pathlib_expandnode = pathlib_expandnode_star;
- // Select walk simulation movement test
- pathlib_movenode = pathlib_walknode;
- // Filter final nodes by direction
- buildpath_nodefilter = buildpath_nodefilter_directional;
-
- // If the start is in water we need diffrent settings
- if(inwater(from))
- {
- // Select volumetric node expaner
- pathlib_expandnode = pathlib_expandnode_box;
-
- // Water movement test
- pathlib_movenode = pathlib_swimnode;
- }
-
- if (!openlist)
- openlist = spawn();
-
- if (!closedlist)
- closedlist = spawn();
-
- if (!scraplist)
- scraplist = spawn();
-
- pathlib_closed_cnt = 0;
- pathlib_open_cnt = 0;
- pathlib_made_cnt = 0;
- pathlib_merge_cnt = 0;
- pathlib_searched_cnt = 0;
- pathlib_bestopen_seached = 0;
- pathlib_bestcash_hits = 0;
- pathlib_bestcash_saved = 0;
- pathlib_recycle_cnt = 0;
-
- pathlib_gridsize = 128;
- pathlib_movecost = pathlib_gridsize;
- pathlib_movecost_diag = vlen(('1 1 0' * pathlib_gridsize));
- pathlib_movecost_waterfactor = 1.1;
- pathlib_foundgoal = 0;
-
- walknode_boxmax = self.maxs * 1.5;
- walknode_boxmin = self.mins * 1.5;
-
- pathlib_edge_check_size = (vlen(walknode_boxmin - walknode_boxmax) * 0.5);
-
- walknode_boxup = '0 0 2' * self.maxs.z;
- walknode_stepsize = 32;
- walknode_stepup = '0 0 1' * walknode_stepsize;
- walknode_maxdrop = '0 0 3' * walknode_stepsize;
-
- from.x = fsnap(from.x,pathlib_gridsize);
- from.y = fsnap(from.y,pathlib_gridsize);
-
- to.x = fsnap(to.x,pathlib_gridsize);
- to.y = fsnap(to.y,pathlib_gridsize);
-
- LOG_TRACE("AStar init. ", ftos(pathlib_scraplist_cnt), " nodes on scrap\n");
- path = pathlib_mknode(from,world);
- pathlib_close_node(path,to);
- if(pathlib_foundgoal)
- {
- LOG_TRACE("AStar: Goal found on first node!\n");
-
- open = spawn();
- open.owner = open;
- open.classname = "path_end";
- setorigin(open,path.origin);
-
- pathlib_cleanup();
-
- return open;
- }
-
- if(pathlib_expandnode(path,from,to) <= 0)
- {
- LOG_TRACE("AStar path fail.\n");
- pathlib_cleanup();
-
- return world;
- }
-
- best_open_node = pathlib_getbestopen();
- n = best_open_node;
- pathlib_close_node(best_open_node,to);
- if(inwater(n.origin))
- pathlib_expandnode_box(n,from,to);
- else
- pathlib_expandnode_star(n,from,to);
-
- while(pathlib_open_cnt)
- {
- best_open_node = pathlib_getbestopen();
- n = best_open_node;
- pathlib_close_node(best_open_node,to);
-
- if(inwater(n.origin))
- pathlib_expandnode_box(n,from,to);
- else
- pathlib_expandnode(n,from,to);
-
- if(pathlib_foundgoal)
- {
- LOG_TRACE("Target found. Rebuilding and filtering path...\n");
- ftime = gettime(GETTIME_REALTIME);
- ptime = ftime - ptime;
-
- start = path_build(world,path.origin,world,world);
- end = path_build(world,goal_node.origin,world,start);
- ln = end;
-
- open = goal_node;
- for(open = goal_node; open.path_prev != path; open = open.path_prev)
- {
- n = path_build(ln,open.origin,open.path_prev,start);
- ln.path_prev = n;
- ln = n;
- }
- start.path_next = n;
- n.path_prev = start;
- ftime = gettime(GETTIME_REALTIME) - ftime;
-
- ctime = gettime(GETTIME_REALTIME);
- pathlib_cleanup();
- ctime = gettime(GETTIME_REALTIME) - ctime;
-
-
-#ifdef DEBUGPATHING
- pathlib_showpath2(start);
-
- LOG_TRACE("Time used - pathfinding: ", ftos(ptime),"\n");
- LOG_TRACE("Time used - rebuild & filter: ", ftos(ftime),"\n");
- LOG_TRACE("Time used - cleanup: ", ftos(ctime),"\n");
- LOG_TRACE("Time used - total: ", ftos(ptime + ftime + ctime),"\n");
- LOG_TRACE("Time used - # frames: ", ftos(ceil((ptime + ftime + ctime) / sys_frametime)),"\n\n");
- LOG_TRACE("Nodes - created: ", ftos(pathlib_made_cnt),"\n");
- LOG_TRACE("Nodes - open: ", ftos(pathlib_open_cnt),"\n");
- LOG_TRACE("Nodes - merged: ", ftos(pathlib_merge_cnt),"\n");
- LOG_TRACE("Nodes - closed: ", ftos(pathlib_closed_cnt),"\n");
- LOG_TRACE("Nodes - searched: ", ftos(pathlib_searched_cnt),"\n");
-
- if(pathlib_recycle_cnt)
- LOG_TRACE("Nodes - make/reuse: ", ftos(pathlib_made_cnt / pathlib_recycle_cnt),"\n");
- if(pathlib_recycle_cnt)
- LOG_TRACE("Nodes - reused: ", ftos(pathlib_recycle_cnt),"\n");
-
- LOG_TRACE("Nodes bestopen searched: ", ftos(pathlib_bestopen_seached),"\n");
- LOG_TRACE("Nodes bestcash - hits: ", ftos(pathlib_bestcash_hits),"\n");
- LOG_TRACE("Nodes bestcash - save: ", ftos(pathlib_bestcash_saved),"\n");
- LOG_TRACE("AStar done. ", ftos(pathlib_scraplist_cnt), " nodes on scrap\n\n");
-#endif
- return start;
- }
- }
-
- LOG_TRACE("A* Faild to find a path! Try a smaller gridsize.\n");
-
- pathlib_cleanup();
-
- return world;
-}
+++ /dev/null
-#ifndef PATHLIB_H
-#define PATHLIB_H
-
-//#define PATHLIB_RDFIELDS
-#ifdef PATHLIB_RDFIELDS
- #define path_next swampslug
- #define path_prev lasertarget
-#else
- .entity path_next;
- .entity path_prev;
-#endif
-
-entity openlist;
-entity closedlist;
-entity scraplist;
-
-.float pathlib_node_g;
-.float pathlib_node_h;
-.float pathlib_node_f;
-
-float pathlib_open_cnt;
-float pathlib_closed_cnt;
-float pathlib_made_cnt;
-float pathlib_merge_cnt;
-float pathlib_recycle_cnt;
-float pathlib_searched_cnt;
-
-float pathlib_bestopen_seached;
-float pathlib_bestcash_hits;
-float pathlib_bestcash_saved;
-
-float pathlib_gridsize;
-
-float pathlib_movecost;
-float pathlib_movecost_diag;
-float pathlib_movecost_waterfactor;
-
-float pathlib_edge_check_size;
-
-float pathlib_foundgoal;
-entity goal_node;
-
-entity best_open_node;
-.float is_path_node;
-
-#define inwater(point) (pointcontents(point) == CONTENT_WATER)
-
-#endif
-#include "../pathlib.qh"
+#include "pathlib.qh"
float pathlib_g_static(entity parent,vector to, float static_cost)
{
-#include "../pathlib.qh"
+#include "pathlib.qh"
+
+MODEL(SQUARE, "models/pathlib/square.md3");
+MODEL(SQUARE_GOOD, "models/pathlib/goodsquare.md3");
+MODEL(SQUARE_BAD, "models/pathlib/badsquare.md3");
+MODEL(EDGE, "models/pathlib/edge.md3");
#ifdef TURRET_DEBUG
void mark_error(vector where,float lifetime);
}
void path_dbg_think()
-{
+{SELFPARAM();
pathlib_showpath(self);
self.nextthink = time + 1;
}
void __showpath2_think()
-{
+{SELFPARAM();
#ifdef TURRET_DEBUG
mark_info(self.origin,1);
#endif
node.scale = pathlib_gridsize / 512.001;
node.solid = SOLID_NOT;
- setmodel(node,"models/pathlib/square.md3");
+ setmodel(node, MDL_SQUARE);
setorigin(node,node.origin);
node.colormod = ncolor;
s.scale = pathlib_gridsize / 512.001;
s.solid = SOLID_NOT;
- if(goodsquare)
- setmodel(s,"models/pathlib/goodsquare.md3");
- else
- setmodel(s,"models/pathlib/badsquare.md3");
-
-
+ setmodel(s, goodsquare ? MDL_SQUARE_GOOD : MDL_SQUARE_BAD);
traceline(where + '0 0 32',where - '0 0 128',MOVE_WORLDONLY,s);
e.scale = pathlib_gridsize / 512;
e.solid = SOLID_NOT;
setorigin(e,where);
- setmodel(e,"models/pathlib/edge.md3");
+ setmodel(e, MDL_EDGE);
//traceline(where + '0 0 32',where - '0 0 128',MOVE_WORLDONLY,e);
//e.angles = vectoangles(trace_plane_normal);
e.angles_y = rot;
}
entity pathlib_astar(vector from,vector to)
-{
+{SELFPARAM();
entity path, start, end, open, n, ln;
float ptime, ftime, ctime;
#include "utility.qh"
vector pathlib_wateroutnode(vector start,vector end, float doedge)
-{
+{SELFPARAM();
vector surface;
pathlib_movenode_goodnode = 0;
}
vector pathlib_swimnode(vector start,vector end, float doedge)
-{
+{SELFPARAM();
pathlib_movenode_goodnode = 0;
if(pointcontents(start) != CONTENT_WATER)
}
vector pathlib_flynode(vector start,vector end, float doedge)
-{
+{SELFPARAM();
pathlib_movenode_goodnode = 0;
end.x = fsnap(end.x, pathlib_gridsize);
}
void a_think()
-{
+{SELFPARAM();
te_lightning1(self,self.origin, self.pos1);
if(self.cnt < time)
remove(self);
}
vector pathlib_walknode(vector start,vector end,float doedge)
-{
+{SELFPARAM();
vector direction,point,last_point,s,e;
float steps, distance, i;
return world;
}
void plas_think()
-{
+{SELFPARAM();
pathlib_waypointpath_step();
if(pathlib_foundgoal)
return;
}
float tile_check_cross(vector where)
-{
+{SELFPARAM();
vector p,f,r;
f = PLIB_FORWARD * tile_check_size;
}
float tile_check_plus(vector where)
-{
+{SELFPARAM();
vector p,f,r;
f = PLIB_FORWARD * tile_check_size;
}
float tile_check_plus2(vector where)
-{
+{SELFPARAM();
vector p,f,r;
float i = 0, e = 0;
const float PLAYERDEMO_MODE_READING = 1;
const float PLAYERDEMO_MODE_WRITING = 2;
void playerdemo_init()
-{
+{SELFPARAM();
self.playerdemo_mode = PLAYERDEMO_MODE_OFF;
}
void playerdemo_shutdown()
-{
+{SELFPARAM();
if(self.playerdemo_mode != PLAYERDEMO_MODE_OFF)
{
LOG_INFO("playerdemo: ", self.netname, " closed\n");
self.playerdemo_mode = 0;
}
void playerdemo_open_read(string f)
-{
+{SELFPARAM();
playerdemo_shutdown();
self.playerdemo_mode = PLAYERDEMO_MODE_READING;
self.playerdemo_fh = fopen(f, FILE_READ);
LOG_INFO("playerdemo: ", self.netname, " reading from ", f, "\n");
}
void playerdemo_open_write(string f)
-{
+{SELFPARAM();
playerdemo_shutdown();
self.playerdemo_mode = PLAYERDEMO_MODE_WRITING;
self.playerdemo_fh = fopen(f, FILE_WRITE);
// end of list
void playerdemo_write_originvector(.vector f, string name)
-{
+{SELFPARAM();
fputs(self.playerdemo_fh, strcat(vtos(self.(f)), "\n"));
}
void playerdemo_write_sizevector(.vector f, string name)
-{
+{SELFPARAM();
fputs(self.playerdemo_fh, strcat(vtos(self.(f)), "\n"));
}
void playerdemo_write_vector(.vector f, string name)
-{
+{SELFPARAM();
fputs(self.playerdemo_fh, strcat(vtos(self.(f)), "\n"));
}
void playerdemo_write_string(.string f, string name)
-{
+{SELFPARAM();
fputs(self.playerdemo_fh, strcat(self.(f), "\n"));
}
void playerdemo_write_modelstring(.string f, string name)
-{
+{SELFPARAM();
fputs(self.playerdemo_fh, strcat(self.(f), "\n"));
}
void playerdemo_write_float(.float f, string name)
-{
+{SELFPARAM();
fputs(self.playerdemo_fh, strcat(ftos(self.(f)), "\n"));
}
void playerdemo_write()
-{
+{SELFPARAM();
if(self.playerdemo_mode != PLAYERDEMO_MODE_WRITING)
return;
fputs(self.playerdemo_fh, strcat(ftos(time - self.playerdemo_starttime), "\n"));
PLAYERDEMO_FIELDS(playerdemo_write_)
}
void playerdemo_read_originvector(.vector f, string name)
-{
+{SELFPARAM();
setorigin(self, stov(fgets(self.playerdemo_fh)));
}
void playerdemo_read_sizevector(.vector f, string name)
-{
+{SELFPARAM();
self.(f) = stov(fgets(self.playerdemo_fh));
setsize(self, self.mins, self.maxs);
}
void playerdemo_read_vector(.vector f, string name)
-{
+{SELFPARAM();
self.(f) = stov(fgets(self.playerdemo_fh));
}
void playerdemo_read_string(.string f, string name)
-{
+{SELFPARAM();
string s = fgets(self.playerdemo_fh);
if (s != self.(f))
{
}
}
void playerdemo_read_modelstring(.string f, string name)
-{
+{SELFPARAM();
string s = fgets(self.playerdemo_fh);
if (s != self.(f))
- setmodel(self, s);
+ _setmodel(self, s);
}
void playerdemo_read_float(.float f, string name)
-{
+{SELFPARAM();
self.(f) = stof(fgets(self.playerdemo_fh));
}
float playerdemo_read()
-{
+{SELFPARAM();
if(self.playerdemo_mode != PLAYERDEMO_MODE_READING)
return 0;
if(self.playerdemo_time < 0)
}
void Portal_Touch()
-{
+{SELFPARAM();
vector g;
#ifdef PORTALS_ARE_NOT_SOLID
if(killed)
{
fixedmakevectors(portal.mangle);
- sound(portal, CH_SHOTS, "porto/explode.wav", VOL_BASE, ATTEN_NORM);
+ sound(portal, CH_SHOTS, SND_PORTO_EXPLODE, VOL_BASE, ATTEN_NORM);
Send_Effect(EFFECT_ROCKET_EXPLODE, portal.origin + v_forward * 16, v_forward * 1024, 4);
remove(portal);
}
else
{
Portal_MakeBrokenPortal(portal);
- sound(portal, CH_SHOTS, "porto/expire.wav", VOL_BASE, ATTEN_NORM);
+ sound(portal, CH_SHOTS, SND_PORTO_EXPIRE, VOL_BASE, ATTEN_NORM);
SUB_SetFade(portal, time, 0.5);
}
}
void Portal_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
if(deathtype == DEATH_TELEFRAG)
return;
if(attacker != self.aiment)
}
void Portal_Think_TryTeleportPlayer(entity e, vector g)
-{
+{SELFPARAM();
if(!Portal_WillHitPlane(e.origin, e.mins, e.maxs, e.velocity + g, self.origin, v_forward, self.maxs.x))
return;
}
void Portal_Think()
-{
+{SELFPARAM();
entity e, o;
vector g;
}
float Portal_Customize()
-{
+{SELFPARAM();
if(IS_SPEC(other))
other = other.enemy;
if(other == self.aiment)
W_Porto_Remove(own);
}
void Portal_RemoveLater_Think()
-{
+{SELFPARAM();
Portal_Remove(self, self.cnt);
}
void Portal_RemoveLater(entity portal, float kill)
portal.event_damage = Portal_Damage;
portal.fade_time = time + autocvar_g_balance_portal_lifetime;
portal.health = autocvar_g_balance_portal_health;
- setmodel(portal, "models/portal.md3");
+ setmodel(portal, MDL_PORTAL);
portal.savemodelindex = portal.modelindex;
portal.customizeentityforclient = Portal_Customize;
--- /dev/null
+#include "../common/util-pre.qh"
+#include "sys-pre.qh"
+#include "../dpdefs/progsdefs.qh"
+#include "../dpdefs/dpextensions.qh"
+#include "sys-post.qh"
+#include "../common/util-post.qh"
+
+#include "../lib/_all.inc"
+
+#include "anticheat.qc"
+#include "antilag.qc"
+#include "campaign.qc"
+#include "cheats.qc"
+#include "cl_client.qc"
+#include "cl_impulse.qc"
+#include "cl_player.qc"
+#include "controlpoint.qc"
+#include "csqceffects.qc"
+#include "ent_cs.qc"
+#include "g_damage.qc"
+#include "g_hook.qc"
+// #include "g_lights.qc" // TODO: was never used
+#include "g_models.qc"
+#include "g_subs.qc"
+#include "g_violence.qc"
+#include "g_world.qc"
+#include "generator.qc"
+#include "ipban.qc"
+#include "item_key.qc"
+#include "mapvoting.qc"
+#include "miscfunctions.qc"
+#include "movelib.qc"
+#include "playerdemo.qc"
+#include "portals.qc"
+#include "race.qc"
+#include "round_handler.qc"
+#include "scores.qc"
+#include "scores_rules.qc"
+#include "spawnpoints.qc"
+#include "steerlib.qc"
+#include "sv_main.qc"
+#include "teamplay.qc"
+#include "t_halflife.qc"
+#include "t_items.qc"
+#include "t_quake3.qc"
+#include "t_quake.qc"
+
+#include "bot/aim.qc"
+#include "bot/bot.qc"
+#include "bot/navigation.qc"
+#include "bot/scripting.qc"
+#include "bot/waypoints.qc"
+
+#include "bot/havocbot/havocbot.qc"
+#include "bot/havocbot/role_keyhunt.qc"
+#include "bot/havocbot/roles.qc"
+
+#include "command/all.qc"
+
+#include "mutators/mutators_include.qc"
+#include "mutators/mutators.qc"
+
+#include "pathlib/costs.qc"
+#include "pathlib/expandnode.qc"
+#include "pathlib/main.qc"
+#include "pathlib/movenode.qc"
+#include "pathlib/path_waypoint.qc"
+#include "pathlib/utility.qc"
+
+#include "weapons/accuracy.qc"
+#include "weapons/common.qc"
+#include "weapons/csqcprojectile.qc" // TODO
+#include "weapons/hitplot.qc"
+#include "weapons/selection.qc"
+#include "weapons/spawning.qc"
+#include "weapons/throwing.qc"
+#include "weapons/tracing.qc"
+#include "weapons/weaponstats.qc"
+#include "weapons/weaponsystem.qc"
+
+#include "../common/animdecide.qc"
+#include "../common/campaign_file.qc"
+#include "../common/campaign_setup.qc"
+#include "../common/effects/effects.qc"
+#include "../common/effects/effectinfo.qc"
+#include "../common/mapinfo.qc"
+#include "../common/monsters/spawn.qc"
+#include "../common/monsters/sv_monsters.qc"
+#include "../common/minigames/minigames.qc"
+#include "../common/minigames/sv_minigames.qc"
+#include "../common/movetypes/include.qc"
+#include "../common/net_notice.qc"
+#include "../common/notifications.qc"
+#include "../common/physics.qc"
+#include "../common/playerstats.qc"
+#include "../common/viewloc.qc"
+#include "../common/triggers/include.qc"
+#include "../common/util.qc"
+
+#include "../common/buffs/all.qc"
+#include "../common/items/all.qc"
+#include "../common/monsters/all.qc"
+#include "../common/mutators/all.qc"
+#include "../common/nades/all.qc"
+#include "../common/turrets/all.qc"
+#include "../common/vehicles/all.qc"
+#include "../common/weapons/all.qc"
+
+#include "../common/turrets/sv_turrets.qc"
+#include "../common/turrets/config.qc"
+#include "../common/turrets/util.qc"
+#include "../common/turrets/checkpoint.qc"
+#include "../common/turrets/targettrigger.qc"
+#include "../common/weapons/config.qc"
+
+#include "../csqcmodellib/sv_model.qc"
+
+#include "../warpzonelib/anglestransform.qc"
+#include "../warpzonelib/common.qc"
+#include "../warpzonelib/server.qc"
+#include "../warpzonelib/util_server.qc"
+
+#if BUILD_MOD
+#include "../../mod/server/progs.inc"
+#endif
../../progs.dat
-
-../common/util-pre.qh
-sys-pre.qh
-../dpdefs/progsdefs.qh
-../dpdefs/dpextensions.qh
-sys-post.qh
-../common/util-post.qh
-
-../lib/_all.inc
-
-anticheat.qc
-antilag.qc
-campaign.qc
-cheats.qc
-cl_client.qc
-cl_impulse.qc
-cl_player.qc
-controlpoint.qc
-csqceffects.qc
-ent_cs.qc
-g_damage.qc
-g_hook.qc
-// g_lights.qc // TODO: was never used
-g_models.qc
-g_subs.qc
-g_violence.qc
-g_world.qc
-generator.qc
-ipban.qc
-item_key.qc
-mapvoting.qc
-miscfunctions.qc
-movelib.qc
-// pathlib.qc // TODO: was never used. Seems to duplicate `pathlib/`
-playerdemo.qc
-portals.qc
-race.qc
-round_handler.qc
-scores.qc
-scores_rules.qc
-spawnpoints.qc
-steerlib.qc
-sv_main.qc
-teamplay.qc
-t_halflife.qc
-t_items.qc
-t_quake3.qc
-t_quake.qc
-
-bot/aim.qc
-bot/bot.qc
-bot/navigation.qc
-bot/scripting.qc
-bot/waypoints.qc
-
-bot/havocbot/havocbot.qc
-bot/havocbot/role_keyhunt.qc
-bot/havocbot/roles.qc
-
-command/all.qc
-
-mutators/mutators_include.qc
-mutators/mutators.qc
-
-pathlib/costs.qc
-pathlib/expandnode.qc
-pathlib/main.qc
-pathlib/movenode.qc
-pathlib/path_waypoint.qc
-pathlib/utility.qc
-
-weapons/accuracy.qc
-weapons/common.qc
-weapons/csqcprojectile.qc // TODO
-weapons/hitplot.qc
-weapons/selection.qc
-weapons/spawning.qc
-weapons/throwing.qc
-weapons/tracing.qc
-weapons/weaponstats.qc
-weapons/weaponsystem.qc
-
-../common/animdecide.qc
-../common/buffs.qc
-../common/campaign_file.qc
-../common/campaign_setup.qc
-../common/effects.qc
-../common/mapinfo.qc
-../common/monsters/spawn.qc
-../common/monsters/sv_monsters.qc
-../common/minigames/minigames.qc
-../common/minigames/sv_minigames.qc
-../common/movetypes/include.qc
-../common/nades.qc
-../common/net_notice.qc
-../common/notifications.qc
-../common/physics.qc
-../common/playerstats.qc
-../common/viewloc.qc
-../common/triggers/include.qc
-../common/util.qc
-
-../common/items/all.qc
-../common/monsters/all.qc
-../common/mutators/all.qc
-../common/vehicles/all.qc
-../common/weapons/all.qc // TODO
-
-../common/turrets/sv_turrets.qc
-../common/turrets/config.qc
-../common/turrets/util.qc
-../common/turrets/turrets.qc
-../common/turrets/checkpoint.qc
-../common/turrets/targettrigger.qc
-../common/weapons/config.qc
-
-../csqcmodellib/sv_model.qc
-
-../warpzonelib/anglestransform.qc
-../warpzonelib/common.qc
-../warpzonelib/server.qc
-../warpzonelib/util_server.qc
-
-../../mod/server/progs.inc
+progs.inc
const float MAX_CHECKPOINTS = 255;
-void spawnfunc_target_checkpoint();
+spawnfunc(target_checkpoint);
.float race_penalty;
.float race_penalty_accumulator;
}
void checkpoint_passed()
-{
+{SELFPARAM();
string oldmsg;
entity cp;
{
// do not allow portalling through checkpoints
trace_plane_normal = normalize(-1 * other.velocity);
- self = other;
+ setself(other);
W_Porto_Fail(0);
return;
}
}
float race_waypointsprite_visible_for_player(entity e)
-{
+{SELFPARAM();
if(e.race_checkpoint == -1 || self.owner.race_checkpoint == -2)
return true;
else if(e.race_checkpoint == self.owner.race_checkpoint)
float have_verified;
void trigger_race_checkpoint_verify()
-{
- entity oldself, cp;
+{SELFPARAM();
+ entity cp;
float i, p;
float qual;
qual = g_race_qualifying;
- oldself = self;
- self = spawn();
+ setself(spawn());
self.classname = "player";
if(g_race)
}
}
remove(self);
- self = oldself;
+ setself(this);
}
vector trigger_race_checkpoint_spawn_evalfunc(entity player, entity spot, vector current)
-{
+{SELFPARAM();
if(g_race_qualifying)
{
// spawn at first
return current;
}
-void spawnfunc_trigger_race_checkpoint()
+spawnfunc(trigger_race_checkpoint)
{
vector o;
if(!g_race && !g_cts) { remove(self); return; }
InitializeEntity(self, trigger_race_checkpoint_verify, INITPRIO_FINDTARGET);
}
-void spawnfunc_target_checkpoint() // defrag entity
+spawnfunc(target_checkpoint) // defrag entity
{
vector o;
if(!g_race && !g_cts) { remove(self); return; }
InitializeEntity(self, trigger_race_checkpoint_verify, INITPRIO_FINDTARGET);
}
-void spawnfunc_target_startTimer() { spawnfunc_target_checkpoint(); }
-void spawnfunc_target_stopTimer() { spawnfunc_target_checkpoint(); }
+spawnfunc(target_startTimer) { spawnfunc_target_checkpoint(this); }
+spawnfunc(target_stopTimer) { spawnfunc_target_checkpoint(this); }
void race_AbandonRaceCheck(entity p)
{
}
void race_PreparePlayer()
-{
+{SELFPARAM();
race_ClearTime(self);
self.race_place = 0;
self.race_started = 0;
}
void race_RetractPlayer()
-{
+{SELFPARAM();
if(!g_race && !g_cts)
return;
if(self.race_respawn_checkpoint == 0 || self.race_respawn_checkpoint == race_timed_checkpoint)
self.race_checkpoint = self.race_respawn_checkpoint;
}
-void spawnfunc_info_player_race (void)
+spawnfunc(info_player_race)
{
if(!g_race && !g_cts) { remove(self); return; }
++race_spawns;
- spawnfunc_info_player_deathmatch();
+ spawnfunc_info_player_deathmatch(this);
if(self.race_place > race_highest_place_spawn)
race_highest_place_spawn = self.race_place;
}
void race_ClearRecords()
-{
+{SELFPARAM();
float i;
- entity e;
for(i = 0; i < MAX_CHECKPOINTS; ++i)
{
race_checkpoint_recordholders[i] = string_null;
}
- e = self;
- FOR_EACH_CLIENT(self)
+ entity e;
+ FOR_EACH_CLIENT(e)
{
- float p;
- p = self.race_place;
- race_PreparePlayer();
- self.race_place = p;
+ float p = e.race_place;
+ WITH(entity, self, e, race_PreparePlayer());
+ e.race_place = p;
}
- self = e;
}
void race_ImposePenaltyTime(entity pl, float penalty, string reason)
}
void penalty_touch()
-{
+{SELFPARAM();
EXACTTRIGGER_TOUCH;
if(other.race_lastpenalty != self)
{
}
void penalty_use()
-{
+{SELFPARAM();
race_ImposePenaltyTime(activator, self.race_penalty, self.race_penalty_reason);
}
-void spawnfunc_trigger_race_penalty()
+spawnfunc(trigger_race_penalty)
{
EXACTTRIGGER_INIT;
#include "../common/util.qh"
void round_handler_Think()
-{
+{SELFPARAM();
float f;
if(time < game_starttime)
* teamscore entities
*/
-float TeamScore_SendEntity(entity to, float sendflags)
+bool TeamScore_SendEntity(entity this, entity to, float sendflags)
{
float i, p, longflags;
}
}
-float ScoreInfo_SendEntity(entity to, int sf)
+bool ScoreInfo_SendEntity(entity this, entity to, int sf)
{
float i;
WriteByte(MSG_ENTITY, ENT_CLIENT_SCORES_INFO);
* per-player score entities
*/
-float PlayerScore_SendEntity(entity to, float sendflags)
+bool PlayerScore_SendEntity(entity this, entity to, float sendflags)
{
float i, p, longflags;
#include "../common/util.qh"
#include "../warpzonelib/util_server.qh"
-float SpawnPoint_Send(entity to, int sf)
+bool SpawnPoint_Send(entity this, entity to, int sf)
{
WriteByte(MSG_ENTITY, ENT_CLIENT_SPAWNPOINT);
return true;
}
-float SpawnEvent_Send(entity to, int sf)
+bool SpawnEvent_Send(entity this, entity to, int sf)
{
float send;
}
void spawnpoint_use()
-{
+{SELFPARAM();
if(teamplay)
if(have_team_spawns > 0)
{
}
void relocate_spawnpoint()
-{
+{SELFPARAM();
// nudge off the floor
setorigin(self, self.origin + '0 0 1');
{ Net_LinkEntity(self, false, 0, SpawnPoint_Send); }
}
-void spawnfunc_info_player_survivor (void)
+spawnfunc(info_player_survivor)
{
- spawnfunc_info_player_deathmatch();
+ spawnfunc_info_player_deathmatch(this);
}
-void spawnfunc_info_player_start (void)
+spawnfunc(info_player_start)
{
- spawnfunc_info_player_deathmatch();
+ spawnfunc_info_player_deathmatch(this);
}
-void spawnfunc_info_player_deathmatch (void)
+spawnfunc(info_player_deathmatch)
{
self.classname = "info_player_deathmatch";
relocate_spawnpoint();
/*QUAKED spawnfunc_info_player_team1 (1 0 0) (-16 -16 -24) (16 16 24)
Starting point for a player in team one (Red).
Keys: "angle" viewing angle when spawning. */
-void spawnfunc_info_player_team1()
+spawnfunc(info_player_team1)
{
- if(g_assault) { remove(self); return; }
+ if(g_assault) { remove(this); return; }
- self.team = NUM_TEAM_1; // red
- spawnfunc_info_player_deathmatch();
+ this.team = NUM_TEAM_1; // red
+ spawnfunc_info_player_deathmatch(this);
}
/*QUAKED spawnfunc_info_player_team2 (1 0 0) (-16 -16 -24) (16 16 24)
Starting point for a player in team two (Blue).
Keys: "angle" viewing angle when spawning. */
-void spawnfunc_info_player_team2()
+spawnfunc(info_player_team2)
{
- if(g_assault) { remove(self); return; }
+ if(g_assault) { remove(this); return; }
- self.team = NUM_TEAM_2; // blue
- spawnfunc_info_player_deathmatch();
+ this.team = NUM_TEAM_2; // blue
+ spawnfunc_info_player_deathmatch(this);
}
/*QUAKED spawnfunc_info_player_team3 (1 0 0) (-16 -16 -24) (16 16 24)
Starting point for a player in team three (Yellow).
Keys: "angle" viewing angle when spawning. */
-void spawnfunc_info_player_team3()
+spawnfunc(info_player_team3)
{
- if(g_assault) { remove(self); return; }
+ if(g_assault) { remove(this); return; }
- self.team = NUM_TEAM_3; // yellow
- spawnfunc_info_player_deathmatch();
+ this.team = NUM_TEAM_3; // yellow
+ spawnfunc_info_player_deathmatch(this);
}
/*QUAKED spawnfunc_info_player_team4 (1 0 0) (-16 -16 -24) (16 16 24)
Starting point for a player in team four (Purple).
Keys: "angle" viewing angle when spawning. */
-void spawnfunc_info_player_team4()
+spawnfunc(info_player_team4)
{
- if(g_assault) { remove(self); return; }
+ if(g_assault) { remove(this); return; }
- self.team = NUM_TEAM_4; // purple
- spawnfunc_info_player_deathmatch();
+ this.team = NUM_TEAM_4; // purple
+ spawnfunc_info_player_deathmatch(this);
}
// Returns:
// _x: prio (-1 if unusable)
// _y: weight
vector Spawn_Score(entity spot, float mindist, float teamcheck)
-{
+{SELFPARAM();
float shortest, thisdist;
float prio;
entity player;
++found;
if(ent.spawn_evalfunc)
{
- entity oldself = self;
- self = ent;
- spawn_score = ent.spawn_evalfunc(oldself, spot, spawn_score);
- self = oldself;
+ WITH(entity, self, ent, {
+ spawn_score = ent.spawn_evalfunc(this, spot, spawn_score);
+ });
if(spawn_score.x < 0)
return spawn_score;
}
=============
*/
entity SelectSpawnPoint (float anypoint)
-{
+{SELFPARAM();
float teamcheck;
entity spot, firstspot;
.vector spawnpoint_score;
float spawnpoint_nag;
-float SpawnEvent_Send(entity to, int sf);
+bool SpawnEvent_Send(entity this, entity to, int sf);
entity Spawn_FilterOutBadSpots(entity firstspot, float mindist, float teamcheck);
entity SelectSpawnPoint (float anypoint);
-void spawnfunc_info_player_deathmatch();
+spawnfunc(info_player_deathmatch);
void spawnpoint_use();
#endif
Uniform pull towards a point
**/
vector steerlib_pull(vector point)
-{
+{SELFPARAM();
return normalize(point - self.origin);
}
Pull toward a point, The further away, the stronger the pull.
**/
vector steerlib_arrive(vector point,float maximal_distance)
-{
+{SELFPARAM();
float distance;
vector direction;
Pull toward a point increasing the pull the closer we get
**/
vector steerlib_attract(vector point, float maximal_distance)
-{
+{SELFPARAM();
float distance;
vector direction;
}
vector steerlib_attract2(vector point, float min_influense,float max_distance,float max_influense)
-{
+{SELFPARAM();
float distance;
vector direction;
float influense;
Move away from a point.
**/
vector steerlib_repell(vector point,float maximal_distance)
-{
+{SELFPARAM();
float distance;
vector direction;
Try to keep at ideal_distance away from point
**/
vector steerlib_standoff(vector point,float ideal_distance)
-{
+{SELFPARAM();
float distance;
vector direction;
where range is the cicrle radius and tresh is how close we need to be to pick a new heading.
**/
vector steerlib_wander(float range,float tresh,vector oldpoint)
-{
+{SELFPARAM();
vector wander_point;
wander_point = v_forward - oldpoint;
Dodge a point. dont work to well.
**/
vector steerlib_dodge(vector point,vector dodge_dir,float min_distance)
-{
+{SELFPARAM();
float distance;
distance = max(vlen(self.origin - point),min_distance);
**/
.float flock_id;
vector steerlib_flock(float _radius, float standoff,float separation_force,float flock_force)
-{
+{SELFPARAM();
entity flock_member;
vector push = '0 0 0', pull = '0 0 0';
float ccount = 0;
xy only version (for ground movers).
**/
vector steerlib_flock2d(float _radius, float standoff,float separation_force,float flock_force)
-{
+{SELFPARAM();
entity flock_member;
vector push = '0 0 0', pull = '0 0 0';
float ccount = 0;
This results in a aligned movement (?!) much like flocking.
**/
vector steerlib_swarm(float _radius, float standoff,float separation_force,float swarm_force)
-{
+{SELFPARAM();
entity swarm_member;
vector force = '0 0 0', center = '0 0 0';
float ccount = 0;
You need to call makevectors() (or equivalent) before this function to set v_forward and v_right
**/
vector steerlib_traceavoid(float pitch,float length)
-{
+{SELFPARAM();
vector vup_left,vup_right,vdown_left,vdown_right;
float fup_left,fup_right,fdown_left,fdown_right;
vector upwish,downwish,leftwish,rightwish;
Run tracelines in a forward trident, bias each direction negative if something is found there.
**/
vector steerlib_traceavoid_flat(float pitch, float length, vector vofs)
-{
+{SELFPARAM();
vector vt_left, vt_right,vt_front;
float f_left, f_right,f_front;
vector leftwish, rightwish,frontwish, v_left;
//#define BEAMSTEER_VISUAL
float beamsweep(vector from, vector dir,float length, float step,float step_up, float step_down)
-{
+{SELFPARAM();
float i;
vector a,b,u,d;
}
vector steerlib_beamsteer(vector dir, float length, float step, float step_up, float step_down)
-{
+{SELFPARAM();
float bm_forward, bm_right, bm_left,p;
vector vr,vl;
//#define TLIBS_TETSLIBS
#ifdef TLIBS_TETSLIBS
void flocker_die()
-{
+{SELFPARAM();
Send_Effect(EFFECT_ROCKET_EXPLODE, self.origin, '0 0 0', 1);
self.owner.cnt += 1;
void flocker_think()
-{
+{SELFPARAM();
vector dodgemove,swarmmove;
vector reprellmove,wandermove,newmove;
self.nextthink = time + 0.1;
}
+MODEL(FLOCKER, "models/turrets/rocket.md3");
void spawn_flocker()
-{
+{SELFPARAM();
entity flocker;
flocker = spawn ();
setorigin(flocker, self.origin + '0 0 32');
- setmodel (flocker, "models/turrets/rocket.md3");
+ setmodel (flocker, MDL_FLOCKER);
setsize (flocker, '-3 -3 -3', '3 3 3');
flocker.flock_id = self.flock_id;
}
void flockerspawn_think()
-{
+{SELFPARAM();
if(self.cnt > 0)
}
void flocker_hunter_think()
-{
+{SELFPARAM();
vector dodgemove,attractmove,newmove;
entity e,ee;
float d,bd;
float globflockcnt;
-void spawnfunc_flockerspawn()
-{
- precache_model ( "models/turrets/rocket.md3");
- precache_model("models/turrets/c512.md3");
+spawnfunc(flockerspawn)
+{SELFPARAM();
++globflockcnt;
if(!self.cnt) self.cnt = 20;
self.enemy = spawn();
- setmodel(self.enemy, "models/turrets/rocket.md3");
+ setmodel(self.enemy, MDL_FLOCKER);
setorigin(self.enemy,self.origin + '0 0 768' + (randomvec() * 128));
self.enemy.classname = "FLock Hunter";
.float lastground;
void CreatureFrame (void)
-{
- entity oldself;
+{SELFPARAM();
float dm;
- oldself = self;
- for(self = world; (self = findfloat(self, damagedbycontents, true)); )
+ for(entity e = world; (e = findfloat(e, damagedbycontents, true)); )
{
+ setself(e);
if (self.movetype == MOVETYPE_NOCLIP) { continue; }
float vehic = IS_VEHICLE(self);
if (self.watersound_finished < time)
{
self.watersound_finished = time + 0.5;
- sound (self, CH_PLAYER_SINGLE, "player/lava.wav", VOL_BASE, ATTEN_NORM);
+ sound (self, CH_PLAYER_SINGLE, SND_LAVA, VOL_BASE, ATTEN_NORM);
}
Damage (self, world, world, autocvar_g_balance_contents_playerdamage_lava * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_LAVA, self.origin, '0 0 0');
}
if (self.watersound_finished < time)
{
self.watersound_finished = time + 0.5;
- sound (self, CH_PLAYER_SINGLE, "player/slime.wav", VOL_BASE, ATTEN_NORM);
+ sound (self, CH_PLAYER_SINGLE, SND_SLIME, VOL_BASE, ATTEN_NORM);
}
Damage (self, world, world, autocvar_g_balance_contents_playerdamage_slime * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_SLIME, self.origin, '0 0 0');
}
self.oldvelocity = self.velocity;
}
- self = oldself;
+ setself(this);
}
float RedirectionThink();
void StartFrame (void)
-{
+{SELFPARAM();
execute_next_frame();
remove = remove_unsafely; // not during spawning!
}
#endif
- entity e;
- for(e = world; (e = findfloat(e, csqcprojectile_clientanimate, 1)); )
+ for(entity e = world; (e = findfloat(e, csqcprojectile_clientanimate, 1)); )
CSQCProjectile_Check(e);
if(RedirectionThink())
bot_serverframe();
- FOR_EACH_PLAYER(self)
- self.porto_forbidden = max(0, self.porto_forbidden - 1);
+ entity e;
+ FOR_EACH_PLAYER(e)
+ e.porto_forbidden = max(0, e.porto_forbidden - 1);
anticheat_startframe();
.string cvarfilter;
float DoesQ3ARemoveThisEntity();
void SV_OnEntityPreSpawnFunction()
-{
+{SELFPARAM();
if (self)
if (self.gametypefilter != "")
if (!isGametypeInFilter(MapInfo_LoadedGametype, teamplay, have_team_spawns, self.gametypefilter))
#define objerror builtin_objerror
#define droptofloor builtin_droptofloor
-#define sound builtin_sound
#define remove builtin_remove
#define cvar_set builtin_cvar_set
#define cvar_string builtin_cvar_string
.float rendermode;
.vector rendercolor;
-void spawnfunc_weapon_crossbow() {}
-void spawnfunc_weapon_handgrenade() {}
-void spawnfunc_ammo_crossbow() {}
-void spawnfunc_ammo_9mmclip() {}
-void spawnfunc_ammo_gaussclip() {}
-void spawnfunc_weapon_rpg() {}
-void spawnfunc_weapon_357() {}
+spawnfunc(weapon_crossbow) {}
+spawnfunc(weapon_handgrenade) {}
+spawnfunc(ammo_crossbow) {}
+spawnfunc(ammo_9mmclip) {}
+spawnfunc(ammo_gaussclip) {}
+spawnfunc(weapon_rpg) {}
+spawnfunc(weapon_357) {}
void ammo_ARgrenades() {}
-void spawnfunc_item_battery() {}
-void spawnfunc_ammo_rpgclip() {}
+spawnfunc(item_battery) {}
+spawnfunc(ammo_rpgclip) {}
void weapon_9mmAR() {}
-void spawnfunc_weapon_tripmine() {}
-void spawnfunc_weapon_snark() {}
-void spawnfunc_ammo_buckshot() {}
+spawnfunc(weapon_tripmine) {}
+spawnfunc(weapon_snark) {}
+spawnfunc(ammo_buckshot) {}
void ammo_9mmAR() {}
-void spawnfunc_ammo_357() {}
-void spawnfunc_weapon_gauss() {}
-void spawnfunc_weapon_hornetgun() {}
-//void spawnfunc_weapon_shotgun() {}
-void spawnfunc_item_healthkit() {}
-void spawnfunc_item_longjump() {}
-void spawnfunc_item_antidote() {}
-void spawnfunc_func_recharge() {}
-void spawnfunc_info_node() {}
-void spawnfunc_env_sound() {}
-void spawnfunc_light_spot() {}
-void spawnfunc_func_healthcharger() {}
+spawnfunc(ammo_357) {}
+spawnfunc(weapon_gauss) {}
+spawnfunc(weapon_hornetgun) {}
+//spawnfunc(weapon_shotgun) {}
+spawnfunc(item_healthkit) {}
+spawnfunc(item_longjump) {}
+spawnfunc(item_antidote) {}
+spawnfunc(func_recharge) {}
+spawnfunc(info_node) {}
+spawnfunc(env_sound) {}
+spawnfunc(light_spot) {}
+spawnfunc(func_healthcharger) {}
#endif
#ifdef CSQC
-void ItemDraw()
+void ItemDraw(entity self)
{
if(self.gravity)
{
}
}
-void ItemDrawSimple()
+void ItemDrawSimple(entity this)
{
if(self.gravity)
{
}
void Item_PreDraw()
-{
+{SELFPARAM();
vector org;
float alph;
org = getpropertyvec(VF_ORIGIN);
}
void ItemRead(float _IsNew)
-{
+{SELFPARAM();
int sf = ReadByte();
if(sf & ISF_LOCATION)
LOG_TRACE("^1WARNING!^7 self.mdl is unset for item ", self.classname, " tell tZork aboute this!\n");
precache_model(self.mdl);
- setmodel(self, self.mdl);
+ _setmodel(self, self.mdl);
}
if(sf & ISF_COLORMAP)
#endif
#ifdef SVQC
-bool ItemSend(entity to, int sf)
+bool ItemSend(entity this, entity to, int sf)
{
if(self.gravity)
sf |= ISF_DROP;
}
float have_pickup_item(void)
-{
+{SELFPARAM();
if(self.flags & FL_POWERUP)
{
if(autocvar_g_powerups > 0)
}
void Item_Think()
-{
+{SELFPARAM();
self.nextthink = time;
if(self.origin != self.oldorigin)
{
void Item_ItemsTime_SetTimesForAllPlayers();
void Item_Respawn (void)
-{
+{SELFPARAM();
Item_Show(self, 1);
// this is ugly...
if(self.items == ITEM_Strength.m_itemid)
- sound (self, CH_TRIGGER, "misc/strength_respawn.wav", VOL_BASE, ATTEN_NORM); // play respawn sound
+ sound (self, CH_TRIGGER, SND_STRENGTH_RESPAWN, VOL_BASE, ATTEN_NORM); // play respawn sound
else if(self.items == ITEM_Shield.m_itemid)
- sound (self, CH_TRIGGER, "misc/shield_respawn.wav", VOL_BASE, ATTEN_NORM); // play respawn sound
+ sound (self, CH_TRIGGER, SND_SHIELD_RESPAWN, VOL_BASE, ATTEN_NORM); // play respawn sound
else
- sound (self, CH_TRIGGER, "misc/itemrespawn.wav", VOL_BASE, ATTEN_NORM); // play respawn sound
+ sound (self, CH_TRIGGER, SND_ITEMRESPAWN, VOL_BASE, ATTEN_NORM); // play respawn sound
setorigin (self, self.origin);
if (Item_ItemsTime_Allow(self.itemdef, self.weapons))
}
void Item_RespawnCountdown (void)
-{
+{SELFPARAM();
if(self.count >= ITEM_RESPAWN_TICKS)
{
if(self.waypointsprite_attached)
if(self.count == 1)
{
MUTATOR_CALLHOOK(Item_RespawnCountdown, string_null, '0 0 0');
- int wpextra = 0;
- entity e = self.itemdef;
- if (e) wpextra = e.m_id;
- if (self.flags & FL_WEAPON) {
- entity wi = get_weaponinfo(self.weapon);
- if (wi) wpextra = wi.m_id;
- }
- entity wp = WaypointSprite_Spawn(WP_Item, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_POWERUP);
- wp.wp_extra = wpextra;
+ do {
+ {
+ entity wi = get_weaponinfo(self.weapon);
+ if (wi.m_id) {
+ entity wp = WaypointSprite_Spawn(WP_Weapon, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_Weapon);
+ wp.wp_extra = wi.m_id;
+ break;
+ }
+ }
+ {
+ entity ii = self.itemdef;
+ if (ii.m_id) {
+ entity wp = WaypointSprite_Spawn(WP_Item, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_Item);
+ wp.wp_extra = ii.m_id;
+ break;
+ }
+ }
+ } while (0);
if(self.waypointsprite_attached)
{
GameItem def = self.itemdef;
if(self.waypointsprite_attached)
{
+ setself(self.waypointsprite_attached);
entity e;
- entity it = self;
- self = self.waypointsprite_attached;
FOR_EACH_REALCLIENT(e)
if(self.waypointsprite_visible_for_player(e))
{
msg_entity = e;
- soundto(MSG_ONE, it, CH_TRIGGER, "misc/itemrespawncountdown.wav", VOL_BASE, ATTEN_NORM); // play respawn sound
+ soundto(MSG_ONE, this, CH_TRIGGER, SND(ITEMRESPAWNCOUNTDOWN), VOL_BASE, ATTEN_NORM); // play respawn sound
}
- self = it;
+ setself(this);
WaypointSprite_Ping(self.waypointsprite_attached);
//WaypointSprite_UpdateHealth(self.waypointsprite_attached, self.count);
}
else
- sound(self, CH_TRIGGER, "misc/itemrespawncountdown.wav", VOL_BASE, ATTEN_NORM); // play respawn sound
+ sound(self, CH_TRIGGER, SND_ITEMRESPAWNCOUNTDOWN, VOL_BASE, ATTEN_NORM); // play respawn sound
}
}
void Item_RespawnThink()
-{
+{SELFPARAM();
self.nextthink = time;
if(self.origin != self.oldorigin)
{
for(i = WEP_FIRST; i <= WEP_LAST; ++i)
if(it & WepSet_FromWeapon(i))
{
- W_DropEvent(WR_PICKUP, player, i, item);
+ W_DropEvent(wr_pickup, player, i, item);
W_GiveWeapon(player, i);
}
}
}
void Item_Touch (void)
-{
+{SELFPARAM();
entity e, head;
// remove the item if it's currnetly in a NODROP brush or hits a NOIMPACT surface (such as sky)
other.last_pickup = time;
Send_Effect(EFFECT_ITEM_PICKUP, CENTER_OR_VIEWOFS(self), '0 0 0', 1);
- sound (other, CH_TRIGGER, self.item_pickupsound, VOL_BASE, ATTEN_NORM);
+ _sound (other, CH_TRIGGER, (self.item_pickupsound ? self.item_pickupsound : self.item_pickupsound_ent.sound_str()), VOL_BASE, ATTEN_NORM);
if (self.classname == "droppedweapon")
remove (self);
}
void Item_Reset()
-{
+{SELFPARAM();
Item_Show(self, !self.state);
setorigin (self, self.origin);
}
void Item_FindTeam()
-{
+{SELFPARAM();
entity head, e;
if(self.effects & EF_NODRAW)
// Savage: used for item garbage-collection
// TODO: perhaps nice special effect?
void RemoveItem(void)
-{
+{SELFPARAM();
if(wasfreed(self) || !self) { return; }
Send_Effect(EFFECT_ITEM_PICKUP, CENTER_OR_VIEWOFS(self), '0 0 0', 1);
remove(self);
}
void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, float defaultrespawntimejitter, string itemname, float itemid, float weaponid, float itemflags, float(entity player, entity item) pickupevalfunc, float pickupbasevalue)
-{
+{SELFPARAM();
startitem_failed = false;
if(self.model == "")
precache_model (self.model);
precache_sound (self.item_pickupsound);
- precache_sound ("misc/itemrespawncountdown.wav");
- if(itemid == ITEM_Strength.m_itemid)
- precache_sound ("misc/strength_respawn.wav");
- else if(itemid == ITEM_Shield.m_itemid)
- precache_sound ("misc/shield_respawn.wav");
- else
- precache_sound ("misc/itemrespawn.wav");
-
if((itemflags & (FL_POWERUP | FL_WEAPON)) || (itemid & (IT_HEALTH | IT_ARMOR | IT_KEY1 | IT_KEY2)))
self.target = "###item###"; // for finding the nearest item using find()
self.mdl = self.model;
self.netname = itemname;
self.touch = Item_Touch;
- setmodel(self, "null"); // precision set below
+ setmodel(self, MDL_Null); // precision set below
//self.effects |= EF_LOWPRECISION;
if((itemflags & FL_POWERUP) || self.health || self.armorvalue)
}
}
-string Item_Model(string item_mdl)
-{
- string output = strcat("models/items/", item_mdl);
- MUTATOR_CALLHOOK(ItemModel, item_mdl, output);
- return strzone(item_model_output);
-}
-
void StartItemA (entity a)
-{
+{SELFPARAM();
self.itemdef = a;
- StartItem(Item_Model(a.m_model), a.m_sound, a.m_respawntime(), a.m_respawntimejitter(), a.m_name, a.m_itemid, 0, a.m_itemflags, a.m_pickupevalfunc, a.m_botvalue);
+ StartItem(strzone(a.m_model.model_str()), a.m_sound, a.m_respawntime(), a.m_respawntimejitter(), a.m_name, a.m_itemid, 0, a.m_itemflags, a.m_pickupevalfunc, a.m_botvalue);
}
-void spawnfunc_item_rockets (void) {
+spawnfunc(item_rockets)
+{
if(!self.ammo_rockets)
self.ammo_rockets = g_pickup_rockets;
if(!self.pickup_anyway)
StartItemA (ITEM_Rockets);
}
-void spawnfunc_item_bullets (void) {
+spawnfunc(item_bullets)
+{
if(!weaponswapping)
if(autocvar_sv_q3acompat_machineshotgunswap)
if(self.classname != "droppedweapon")
{
weaponswapping = true;
- spawnfunc_item_shells();
+ spawnfunc_item_shells(this);
weaponswapping = false;
return;
}
StartItemA (ITEM_Bullets);
}
-void spawnfunc_item_cells (void) {
+spawnfunc(item_cells)
+{
if(!self.ammo_cells)
self.ammo_cells = g_pickup_cells;
if(!self.pickup_anyway)
StartItemA (ITEM_Cells);
}
-void spawnfunc_item_plasma()
+spawnfunc(item_plasma)
{
if(!self.ammo_plasma)
self.ammo_plasma = g_pickup_plasma;
StartItemA (ITEM_Plasma);
}
-void spawnfunc_item_shells (void) {
+spawnfunc(item_shells)
+{
if(!weaponswapping)
if(autocvar_sv_q3acompat_machineshotgunswap)
if(self.classname != "droppedweapon")
{
weaponswapping = true;
- spawnfunc_item_bullets();
+ spawnfunc_item_bullets(this);
weaponswapping = false;
return;
}
StartItemA (ITEM_Shells);
}
-void spawnfunc_item_armor_small (void) {
+spawnfunc(item_armor_small)
+{
if(!self.armorvalue)
self.armorvalue = g_pickup_armorsmall;
if(!self.max_armorvalue)
StartItemA (ITEM_ArmorSmall);
}
-void spawnfunc_item_armor_medium (void) {
+spawnfunc(item_armor_medium)
+{
if(!self.armorvalue)
self.armorvalue = g_pickup_armormedium;
if(!self.max_armorvalue)
StartItemA (ITEM_ArmorMedium);
}
-void spawnfunc_item_armor_big (void) {
+spawnfunc(item_armor_big)
+{
if(!self.armorvalue)
self.armorvalue = g_pickup_armorbig;
if(!self.max_armorvalue)
StartItemA (ITEM_ArmorLarge);
}
-void spawnfunc_item_armor_large (void) {
+spawnfunc(item_armor_large)
+{
if(!self.armorvalue)
self.armorvalue = g_pickup_armorlarge;
if(!self.max_armorvalue)
StartItemA (ITEM_ArmorMega);
}
-void spawnfunc_item_health_small (void) {
+spawnfunc(item_health_small)
+{
if(!self.max_health)
self.max_health = g_pickup_healthsmall_max;
if(!self.health)
StartItemA (ITEM_HealthSmall);
}
-void spawnfunc_item_health_medium (void) {
+spawnfunc(item_health_medium)
+{
if(!self.max_health)
self.max_health = g_pickup_healthmedium_max;
if(!self.health)
StartItemA (ITEM_HealthMedium);
}
-void spawnfunc_item_health_large (void) {
+spawnfunc(item_health_large)
+{
if(!self.max_health)
self.max_health = g_pickup_healthlarge_max;
if(!self.health)
StartItemA (ITEM_HealthLarge);
}
-void spawnfunc_item_health_mega (void) {
+spawnfunc(item_health_mega)
+{
if(!self.max_health)
self.max_health = g_pickup_healthmega_max;
if(!self.health)
}
// support old misnamed entities
-void spawnfunc_item_armor1() { spawnfunc_item_armor_small(); } // FIXME: in Quake this is green armor, in Xonotic maps it is an armor shard
-void spawnfunc_item_armor25() { spawnfunc_item_armor_large(); }
-void spawnfunc_item_health1() { spawnfunc_item_health_small(); }
-void spawnfunc_item_health25() { spawnfunc_item_health_medium(); }
-void spawnfunc_item_health100() { spawnfunc_item_health_mega(); }
-
-void spawnfunc_item_strength (void) {
- precache_sound("weapons/strength_fire.wav");
+spawnfunc(item_armor1) { spawnfunc_item_armor_small(this); } // FIXME: in Quake this is green armor, in Xonotic maps it is an armor shard
+spawnfunc(item_armor25) { spawnfunc_item_armor_large(this); }
+spawnfunc(item_health1) { spawnfunc_item_health_small(this); }
+spawnfunc(item_health25) { spawnfunc_item_health_medium(this); }
+spawnfunc(item_health100) { spawnfunc_item_health_mega(this); }
+
+spawnfunc(item_strength)
+{
if(!self.strength_finished)
self.strength_finished = autocvar_g_balance_powerup_strength_time;
StartItemA (ITEM_Strength);
}
-void spawnfunc_item_invincible (void) {
+spawnfunc(item_invincible)
+{
if(!self.invincible_finished)
self.invincible_finished = autocvar_g_balance_powerup_invincible_time;
StartItemA (ITEM_Shield);
}
// compatibility:
-void spawnfunc_item_quad (void) {self.classname = "item_strength";spawnfunc_item_strength();}
+spawnfunc(item_quad) { self.classname = "item_strength";spawnfunc_item_strength(this);}
-void target_items_use (void)
-{
+void target_items_use()
+{SELFPARAM();
if(activator.classname == "droppedweapon")
{
EXACTTRIGGER_TOUCH;
centerprint(activator, self.message);
}
-void spawnfunc_target_items (void)
+spawnfunc(target_items)
{
float n, i, j;
entity e;
if(!self.superweapons_finished)
self.superweapons_finished = autocvar_g_balance_superweapons_time;
- precache_sound("misc/itempickup.wav");
- precache_sound("misc/megahealth.wav");
- precache_sound("misc/armor25.wav");
- precache_sound("misc/powerup.wav");
- precache_sound("misc/poweroff.wav");
- precache_sound(W_Sound("weaponpickup"));
-
n = tokenize_console(self.netname);
if(argv(0) == "give")
{
if(s == e.netname)
{
self.weapons |= WepSet_FromWeapon(j);
- if(self.spawnflags == 0 || self.spawnflags == 2)
- WEP_ACTION(e.weapon, WR_INIT);
+ if(self.spawnflags == 0 || self.spawnflags == 2) {
+ Weapon w = get_weaponinfo(e.weapon);
+ w.wr_init(w);
+ }
break;
}
}
e = get_weaponinfo(j);
if(argv(i) == e.netname)
{
- WEP_ACTION(e.weapon, WR_INIT);
+ Weapon w = get_weaponinfo(e.weapon);
+ w.wr_init(w);
break;
}
}
}
}
-void spawnfunc_item_fuel(void)
+spawnfunc(item_fuel)
{
if(!self.ammo_fuel)
self.ammo_fuel = g_pickup_fuel;
StartItemA (ITEM_JetpackFuel);
}
-void spawnfunc_item_fuel_regen(void)
+spawnfunc(item_fuel_regen)
{
if(start_items & ITEM_JetpackRegen.m_itemid)
{
- spawnfunc_item_fuel();
+ spawnfunc_item_fuel(this);
return;
}
StartItemA (ITEM_JetpackRegen);
}
-void spawnfunc_item_jetpack(void)
+spawnfunc(item_jetpack)
{
if(!self.ammo_fuel)
self.ammo_fuel = g_pickup_fuel_jetpack;
if(start_items & ITEM_Jetpack.m_itemid)
{
- spawnfunc_item_fuel();
+ spawnfunc_item_fuel(this);
return;
}
StartItemA (ITEM_Jetpack);
if(v1 <= v0 - t)
{
if(snd_decr != "")
- sound (e, CH_TRIGGER, snd_decr, VOL_BASE, ATTEN_NORM);
+ _sound (e, CH_TRIGGER, snd_decr, VOL_BASE, ATTEN_NORM);
}
else if(v0 >= v0 + t)
{
if(snd_incr != "")
- sound (e, CH_TRIGGER, snd_incr, VOL_BASE, ATTEN_NORM);
+ _sound (e, CH_TRIGGER, snd_incr, VOL_BASE, ATTEN_NORM);
}
}
e.(regenfield) = max(e.(regenfield), time + regentime);
}
float GiveItems(entity e, float beginarg, float endarg)
-{
+{SELFPARAM();
float got, i, j, val, op;
float _switchweapon;
entity wi;
op = OP_SET;
}
- POSTGIVE_BIT(e, items, ITEM_JetpackRegen.m_itemid, "misc/itempickup.wav", string_null);
- POSTGIVE_BIT(e, items, IT_UNLIMITED_SUPERWEAPONS, "misc/powerup.wav", "misc/poweroff.wav");
- POSTGIVE_BIT(e, items, IT_UNLIMITED_WEAPON_AMMO, "misc/powerup.wav", "misc/poweroff.wav");
- POSTGIVE_BIT(e, items, ITEM_Jetpack.m_itemid, "misc/itempickup.wav", string_null);
+ POSTGIVE_BIT(e, items, ITEM_JetpackRegen.m_itemid, SND(ITEMPICKUP), string_null);
+ POSTGIVE_BIT(e, items, IT_UNLIMITED_SUPERWEAPONS, SND(POWERUP), SND(POWEROFF));
+ POSTGIVE_BIT(e, items, IT_UNLIMITED_WEAPON_AMMO, SND(POWERUP), SND(POWEROFF));
+ POSTGIVE_BIT(e, items, ITEM_Jetpack.m_itemid, SND(ITEMPICKUP), string_null);
for(j = WEP_FIRST; j <= WEP_LAST; ++j)
{
wi = get_weaponinfo(j);
if(wi.weapon)
{
- POSTGIVE_WEAPON(e, j, W_Sound("weaponpickup"), string_null);
+ POSTGIVE_WEAPON(e, j, SND(WEAPONPICKUP), string_null);
if (!(save_weapons & WepSet_FromWeapon(j)))
- if(e.weapons & WepSet_FromWeapon(j))
- WEP_ACTION(wi.weapon, WR_INIT);
+ if(e.weapons & WepSet_FromWeapon(j)) {
+ Weapon w = get_weaponinfo(wi.weapon);
+ w.wr_init(w);
+ }
}
}
- POSTGIVE_VALUE(e, strength_finished, 1, "misc/powerup.wav", "misc/poweroff.wav");
- POSTGIVE_VALUE(e, invincible_finished, 1, "misc/powerup_shield.wav", "misc/poweroff.wav");
- POSTGIVE_VALUE(e, ammo_nails, 0, "misc/itempickup.wav", string_null);
- POSTGIVE_VALUE(e, ammo_cells, 0, "misc/itempickup.wav", string_null);
- POSTGIVE_VALUE(e, ammo_plasma, 0, "misc/itempickup.wav", string_null);
- POSTGIVE_VALUE(e, ammo_shells, 0, "misc/itempickup.wav", string_null);
- POSTGIVE_VALUE(e, ammo_rockets, 0, "misc/itempickup.wav", string_null);
- POSTGIVE_VALUE_ROT(e, ammo_fuel, 1, pauserotfuel_finished, autocvar_g_balance_pause_fuel_rot, pauseregen_finished, autocvar_g_balance_pause_fuel_regen, "misc/itempickup.wav", string_null);
- POSTGIVE_VALUE_ROT(e, armorvalue, 1, pauserotarmor_finished, autocvar_g_balance_pause_armor_rot, pauseregen_finished, autocvar_g_balance_pause_health_regen, "misc/armor25.wav", string_null);
- POSTGIVE_VALUE_ROT(e, health, 1, pauserothealth_finished, autocvar_g_balance_pause_health_rot, pauseregen_finished, autocvar_g_balance_pause_health_regen, "misc/megahealth.wav", string_null);
+ POSTGIVE_VALUE(e, strength_finished, 1, SND(POWERUP), SND(POWEROFF));
+ POSTGIVE_VALUE(e, invincible_finished, 1, "misc/powerup_shield.wav", SND(POWEROFF));
+ POSTGIVE_VALUE(e, ammo_nails, 0, SND(ITEMPICKUP), string_null);
+ POSTGIVE_VALUE(e, ammo_cells, 0, SND(ITEMPICKUP), string_null);
+ POSTGIVE_VALUE(e, ammo_plasma, 0, SND(ITEMPICKUP), string_null);
+ POSTGIVE_VALUE(e, ammo_shells, 0, SND(ITEMPICKUP), string_null);
+ POSTGIVE_VALUE(e, ammo_rockets, 0, SND(ITEMPICKUP), string_null);
+ POSTGIVE_VALUE_ROT(e, ammo_fuel, 1, pauserotfuel_finished, autocvar_g_balance_pause_fuel_rot, pauseregen_finished, autocvar_g_balance_pause_fuel_regen, SND(ITEMPICKUP), string_null);
+ POSTGIVE_VALUE_ROT(e, armorvalue, 1, pauserotarmor_finished, autocvar_g_balance_pause_armor_rot, pauseregen_finished, autocvar_g_balance_pause_health_regen, SND(ARMOR25), string_null);
+ POSTGIVE_VALUE_ROT(e, health, 1, pauserothealth_finished, autocvar_g_balance_pause_health_rot, pauseregen_finished, autocvar_g_balance_pause_health_regen, SND(MEGAHEALTH), string_null);
if(e.superweapons_finished <= 0)
if(self.weapons & WEPSET_SUPERWEAPONS)
.float spawntime;
.float gravity;
.vector colormod;
-void ItemDraw();
-void ItemDrawSimple();
+void ItemDraw(entity this);
+void ItemDrawSimple(entity this);
void ItemRead(float _IsNew);
#endif
#ifdef SVQC
-void spawnfunc_item_strength();
-void spawnfunc_item_invincible();
-void spawnfunc_item_armor_small();
-void spawnfunc_item_shells();
-void spawnfunc_item_bullets();
-void spawnfunc_item_rockets();
+spawnfunc(item_strength);
+spawnfunc(item_invincible);
+spawnfunc(item_armor_small);
+spawnfunc(item_shells);
+spawnfunc(item_bullets);
+spawnfunc(item_rockets);
float autocvar_sv_simple_items;
-bool ItemSend(entity to, int sf);
+bool ItemSend(entity this, entity to, int sf);
float have_pickup_item(void);
// Savage: used for item garbage-collection
// TODO: perhaps nice special effect?
-bool ItemSend(entity to, int sf);
+bool ItemSend(entity this, entity to, int sf);
void ItemUpdate(entity item);
// pickup evaluation functions
#include "../common/weapons/all.qh"
-void spawnfunc_weapon_electro();
-void spawnfunc_weapon_hagar();
-void spawnfunc_weapon_machinegun();
-void spawnfunc_item_bullets();
-void spawnfunc_item_armor_large();
-void spawnfunc_item_armor_large();
-void spawnfunc_item_health_mega();
-void spawnfunc_item_health_medium();
+spawnfunc(weapon_electro);
+spawnfunc(weapon_hagar);
+spawnfunc(weapon_machinegun);
+spawnfunc(item_bullets);
+spawnfunc(item_armor_large);
+spawnfunc(item_armor_large);
+spawnfunc(item_health_mega);
+spawnfunc(item_health_medium);
//***********************
//QUAKE 1 ENTITIES - So people can play quake1 maps with the xonotic weapons
//***********************
-void spawnfunc_weapon_nailgun (void) {spawnfunc_weapon_electro();}
-void spawnfunc_weapon_supernailgun (void) {spawnfunc_weapon_hagar();}
-void spawnfunc_weapon_supershotgun (void) {spawnfunc_weapon_machinegun();}
-
-void spawnfunc_item_spikes (void) {spawnfunc_item_bullets();}
-//void spawnfunc_item_armor1 (void) {spawnfunc_item_armor_medium;} // FIXME: in Quake this is green armor, in Xonotic maps it is an armor shard
-void spawnfunc_item_armor2 (void) {spawnfunc_item_armor_large();}
-void item_armorInv (void) {spawnfunc_item_armor_large();}
-void spawnfunc_item_health (void) {if (self.spawnflags & 2) spawnfunc_item_health_mega();else spawnfunc_item_health_medium();}
+spawnfunc(weapon_nailgun) {spawnfunc_weapon_electro(this);}
+spawnfunc(weapon_supernailgun) {spawnfunc_weapon_hagar(this);}
+spawnfunc(weapon_supershotgun) {spawnfunc_weapon_machinegun(this);}
+
+spawnfunc(item_spikes) {spawnfunc_item_bullets(this);}
+//spawnfunc(item_armor1) {spawnfunc_item_armor_medium(this);} // FIXME: in Quake this is green armor, in Xonotic maps it is an armor shard
+spawnfunc(item_armor2) {spawnfunc_item_armor_large(this);}
+void item_armorInv() {SELFPARAM();spawnfunc_item_armor_large(self);}
+spawnfunc(item_health) {if (self.spawnflags & 2) spawnfunc_item_health_mega(this);else spawnfunc_item_health_medium(this);}
//spawnfunc_item_spikes
//spawnfunc_item_health
#include "_all.qh"
#include "../common/weapons/all.qh"
-#include "../common/buffs.qh"
+#include "../common/buffs/all.qh"
-void spawnfunc_weapon_crylink();
-void spawnfunc_weapon_electro();
-void spawnfunc_weapon_hagar();
-void spawnfunc_weapon_machinegun();
-void spawnfunc_weapon_vortex();
+spawnfunc(weapon_crylink);
+spawnfunc(weapon_electro);
+spawnfunc(weapon_hagar);
+spawnfunc(weapon_machinegun);
+spawnfunc(weapon_vortex);
-void spawnfunc_target_items();
+spawnfunc(target_items);
-void spawnfunc_item_bullets();
-void spawnfunc_item_cells();
-void spawnfunc_item_rockets();
-void spawnfunc_item_shells();
+spawnfunc(item_bullets);
+spawnfunc(item_cells);
+spawnfunc(item_rockets);
+spawnfunc(item_shells);
-void spawnfunc_item_jetpack();
+spawnfunc(item_jetpack);
-void spawnfunc_item_armor_big();
-void spawnfunc_item_armor_large();
-void spawnfunc_item_armor_small();
+spawnfunc(item_armor_big);
+spawnfunc(item_armor_large);
+spawnfunc(item_armor_small);
-void spawnfunc_item_health_medium();
-void spawnfunc_item_health_mega();
+spawnfunc(item_health_medium);
+spawnfunc(item_health_mega);
//***********************
//QUAKE 3 ENTITIES - So people can play quake3 maps with the xonotic weapons
// NOTE: for best experience, you need to swap MGs with SGs in the map or it won't have a MG
// SG -> SG
-void spawnfunc_ammo_shells() { spawnfunc_item_shells(); }
+spawnfunc(ammo_shells) { spawnfunc_item_shells(this); }
// MG -> MG
-void spawnfunc_ammo_bullets() { spawnfunc_item_bullets(); }
+spawnfunc(ammo_bullets) { spawnfunc_item_bullets(this); }
// GL -> Mortar
-void spawnfunc_ammo_grenades() { spawnfunc_item_rockets(); }
+spawnfunc(ammo_grenades) { spawnfunc_item_rockets(this); }
// LG -> Lightning
-void spawnfunc_weapon_lightning() { spawnfunc_weapon_electro(); }
-void spawnfunc_ammo_lightning() { spawnfunc_item_cells(); }
+spawnfunc(weapon_lightning) { spawnfunc_weapon_electro(this); }
+spawnfunc(ammo_lightning) { spawnfunc_item_cells(this); }
// Plasma -> Hagar
-void spawnfunc_weapon_plasmagun() { spawnfunc_weapon_hagar(); }
-void spawnfunc_ammo_cells() { spawnfunc_item_rockets(); }
+spawnfunc(weapon_plasmagun) { spawnfunc_weapon_hagar(this); }
+spawnfunc(ammo_cells) { spawnfunc_item_rockets(this); }
// Rail -> Vortex
-void spawnfunc_weapon_railgun() { spawnfunc_weapon_vortex(); }
-void spawnfunc_ammo_slugs() { spawnfunc_item_cells(); }
+spawnfunc(weapon_railgun) { spawnfunc_weapon_vortex(this); }
+spawnfunc(ammo_slugs) { spawnfunc_item_cells(this); }
// BFG -> Crylink
-void spawnfunc_weapon_bfg() { spawnfunc_weapon_crylink(); }
-void spawnfunc_ammo_bfg() { spawnfunc_item_cells(); }
+spawnfunc(weapon_bfg) { spawnfunc_weapon_crylink(this); }
+spawnfunc(ammo_bfg) { spawnfunc_item_cells(this); }
// RL -> RL
-void spawnfunc_ammo_rockets() { spawnfunc_item_rockets(); }
+spawnfunc(ammo_rockets) { spawnfunc_item_rockets(this); }
// Armor
-void spawnfunc_item_armor_body() { spawnfunc_item_armor_large(); }
-void spawnfunc_item_armor_combat() { spawnfunc_item_armor_big(); }
-void spawnfunc_item_armor_shard() { spawnfunc_item_armor_small(); }
-void spawnfunc_item_enviro() { spawnfunc_item_invincible(); }
+spawnfunc(item_armor_body) { spawnfunc_item_armor_large(this); }
+spawnfunc(item_armor_combat) { spawnfunc_item_armor_big(this); }
+spawnfunc(item_armor_shard) { spawnfunc_item_armor_small(this); }
+spawnfunc(item_enviro) { spawnfunc_item_invincible(this); }
// weapon remove ent from df
void target_init_verify()
}
}
-void spawnfunc_target_init()
+spawnfunc(target_init)
{
self.spawnflags = 0; // remove all weapons except the ones listed below
self.netname = "shotgun"; // keep these weapons through the remove trigger
- spawnfunc_target_items();
+ spawnfunc_target_items(this);
InitializeEntity(self, target_init_verify, INITPRIO_FINDTARGET);
}
// weapon give ent from defrag
void target_give_init()
-{
+{SELFPARAM();
entity targ;
for (targ = world; (targ = find(targ, targetname, self.target)); ) {
if (targ.classname == "weapon_rocketlauncher" || targ.classname == "weapon_devastator") {
targ.nextthink = time;
}
self.spawnflags = 2;
- spawnfunc_target_items();
+ spawnfunc_target_items(this);
InitializeEntity(self, target_init_verify, INITPRIO_FINDTARGET);
}
-void spawnfunc_target_give()
+spawnfunc(target_give)
{
InitializeEntity(self, target_give_init, INITPRIO_FINDTARGET);
}
-//void spawnfunc_item_flight() /* handled by buffs mutator or jetpack */
-//void spawnfunc_item_haste() /* handled by buffs mutator */
-//void spawnfunc_item_health() /* handled in t_quake.qc */
-//void spawnfunc_item_health_large() /* handled in t_items.qc */
-//void spawnfunc_item_health_small() /* handled in t_items.qc */
-//void spawnfunc_item_health_mega() /* handled in t_items.qc */
-//void spawnfunc_item_invis() /* handled by buffs mutator */
-//void spawnfunc_item_regen() /* handled by buffs mutator */
+//spawnfunc(item_flight) /* handled by buffs mutator or jetpack */
+//spawnfunc(item_haste) /* handled by buffs mutator */
+//spawnfunc(item_health) /* handled in t_quake.qc */
+//spawnfunc(item_health_large) /* handled in t_items.qc */
+//spawnfunc(item_health_small) /* handled in t_items.qc */
+//spawnfunc(item_health_mega) /* handled in t_items.qc */
+//spawnfunc(item_invis) /* handled by buffs mutator */
+//spawnfunc(item_regen) /* handled by buffs mutator */
// CTF spawnfuncs handled in mutators/gamemode_ctf.qc now
-void spawnfunc_item_flight()
+spawnfunc(item_flight)
{
if(!cvar("g_buffs") || !cvar("g_buffs_flight"))
- spawnfunc_item_jetpack();
+ spawnfunc_item_jetpack(this);
else
buff_Init_Compat(self, BUFF_FLIGHT);
}
.float notta;
.string gametype;
float DoesQ3ARemoveThisEntity()
-{
+{SELFPARAM();
// Q3 style filters (DO NOT USE, THIS IS COMPAT ONLY)
if(self.notq3a)
MUTATOR_ADD(gamemode_invasion);
}
- if(teamplay)
- entcs_init();
-
cache_mutatormsg = strzone("");
cache_lastmutatormsg = strzone("");
InitializeEntity(world, default_delayedinit, INITPRIO_GAMETYPE_FALLBACK);
}
-string GetClientVersionMessage() {
+string GetClientVersionMessage()
+{SELFPARAM();
string versionmsg;
if (self.version_mismatch) {
if(self.version < autocvar_gameversion) {
modifications = strcat(modifications, ", Low gravity");
if(g_cloaked && !g_cts)
modifications = strcat(modifications, ", Cloaked");
- if(g_grappling_hook)
- modifications = strcat(modifications, ", Hook");
if(g_weapon_stay && !g_cts)
modifications = strcat(modifications, ", Weapons stay");
if(g_jetpack)
if(modifications != "")
s = strcat(s, "^8\nactive modifications: ^3", modifications, "^8\n");
- if (g_grappling_hook)
- s = strcat(s, "\n\n^3grappling hook^8 is enabled, press 'e' to use it\n");
-
if (cvar("g_nades"))
s = strcat(s, "\n\n^3nades^8 are enabled, press 'g' to use them\n");
// set c1...c4 to show what teams are allowed
void CheckAllowedTeams (entity for_whom)
-{
+{SELFPARAM();
float dm;
entity head;
string teament_name;
}
float JoinBestTeam(entity pl, float only_return_best, float forcebestteam)
-{
+{SELFPARAM();
float smallest, selectedteam;
// don't join a team if we're not playing a team game
//void() ctf_playerchanged;
void SV_ChangeTeam(float _color)
-{
+{SELFPARAM();
float scolor, dcolor, steam, dteam; //, dbotcount, scount, dcount;
// in normal deathmatch we can just apply the color and we're done
void TeamchangeFrags(entity e);
-void entcs_init();
-
void LogTeamchange(float player_id, float team_number, float type);
void default_delayedinit();
return 1 + rint(n * 100.0 / d);
}
-float accuracy_send(entity to, int sf)
+bool accuracy_send(entity this, entity to, int sf)
{
int w, f;
entity a;
.float cvar_cl_accuracy_data_receive;
.entity accuracy;
-.float accuracy_frags[WEP_MAXCOUNT];
+.float accuracy_frags[Weapons_MAX];
-.float accuracy_hit[WEP_MAXCOUNT];
-.float accuracy_fired[WEP_MAXCOUNT];
-.float accuracy_cnt_hit[WEP_MAXCOUNT];
-.float accuracy_cnt_fired[WEP_MAXCOUNT];
+.float accuracy_hit[Weapons_MAX];
+.float accuracy_fired[Weapons_MAX];
+.float accuracy_cnt_hit[Weapons_MAX];
+.float accuracy_cnt_fired[Weapons_MAX];
// init/free
#include "../../common/weapons/all.qh"
void W_GiveWeapon (entity e, float wep)
-{
- entity oldself;
+{SELFPARAM();
if (!wep)
return;
e.weapons |= WepSet_FromWeapon(wep);
- oldself = self;
- self = e;
+ setself(e);
if(IS_PLAYER(other))
{ Send_Notification(NOTIF_ONE, other, MSG_MULTI, ITEM_WEAPON_GOT, wep); }
- self = oldself;
+ setself(this);
}
void W_PlayStrengthSound(entity player) // void W_PlayStrengthSound
&& ((time > player.prevstrengthsound + autocvar_sv_strengthsound_antispam_time) // prevent insane sound spam
|| (time > player.prevstrengthsoundattempt + autocvar_sv_strengthsound_antispam_refire_threshold)))
{
- sound(player, CH_TRIGGER, W_Sound("strength_fire"), VOL_BASE, ATTEN_NORM);
+ sound(player, CH_TRIGGER, SND_STRENGTH_FIRE, VOL_BASE, ATTEN_NORM);
player.prevstrengthsound = time;
}
player.prevstrengthsoundattempt = time;
}
void W_PrepareExplosionByDamage(entity attacker, void() explode)
-{
+{SELFPARAM();
self.takedamage = DAMAGE_NO;
self.event_damage = func_null;
.float csqcprojectile_type;
-bool CSQCProjectile_SendEntity(entity to, int sf)
+bool CSQCProjectile_SendEntity(entity this, entity to, int sf)
{
float ft, fr;
void UpdateCSQCProjectile(entity e)
{
- if(e.SendEntity == CSQCProjectile_SendEntity)
+ if(e.SendEntity3 == CSQCProjectile_SendEntity)
{
// send new origin data
e.SendFlags |= 0x01;
}
// FIXME HACK
- else if(e.SendEntity == ItemSend)
+ else if(e.SendEntity3 == ItemSend)
{
ItemUpdate(e);
}
void UpdateCSQCProjectileAfterTeleport(entity e)
{
- if(e.SendEntity == CSQCProjectile_SendEntity)
+ if(e.SendEntity3 == CSQCProjectile_SendEntity)
{
// send new origin data
e.SendFlags |= 0x01;
}
float client_hasweapon(entity cl, float wpn, float andammo, float complain)
-{
+{SELFPARAM();
float f;
- entity oldself;
if(time < self.hasweapon_complain_spam)
complain = 0;
- if(wpn == WEP_HOOK.m_id && !g_grappling_hook && autocvar_g_nades && !((cl.weapons | weaponsInMap) & WepSet_FromWeapon(wpn)))
- complain = 0;
+ // ignore hook button when using other offhand equipment
+ if (cl.offhand != OFFHAND_HOOK)
+ if (wpn == WEP_HOOK.m_id && !((cl.weapons | weaponsInMap) & WepSet_FromWeapon(wpn)))
+ complain = 0;
if(complain)
self.hasweapon_complain_spam = time + 0.2;
}
else
{
- oldself = self;
- self = cl;
- f = WEP_ACTION(wpn, WR_CHECKAMMO1);
- f = f + WEP_ACTION(wpn, WR_CHECKAMMO2);
+ setself(cl);
+ Weapon w = get_weaponinfo(wpn);
+ f = w.wr_checkammo1(w) + w.wr_checkammo2(w);
// always allow selecting the Mine Layer if we placed mines, so that we can detonate them
entity mine;
for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self)
f = 1;
- self = oldself;
+ setself(this);
}
if (!f)
{
if (complain)
if(IS_REAL_CLIENT(cl))
{
- play2(cl, W_Sound("unavailable"));
+ play2(cl, SND(UNAVAILABLE));
Send_WeaponComplain (cl, wpn, 0);
}
return false;
Send_WeaponComplain (cl, wpn, 2);
}
- play2(cl, W_Sound("unavailable"));
+ play2(cl, SND(UNAVAILABLE));
}
return false;
}
float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, float complain, float skipmissing)
-{
+{SELFPARAM();
// 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;
}
void W_SwitchWeapon(float imp)
-{
+{SELFPARAM();
if (self.switchweapon != imp)
{
if (client_hasweapon(self, imp, true, true))
else
self.selectweapon = imp; // update selectweapon ANYWAY
}
- else if(!forbidWeaponUse(self)) { WEP_ACTION(self.weapon, WR_RELOAD); }
+ else if(!forbidWeaponUse(self)) {
+ Weapon w = get_weaponinfo(self.weapon);
+ w.wr_reload(w);
+ }
}
void W_CycleWeapon(string weaponorder, float dir)
-{
+{SELFPARAM();
float w;
w = W_GetCycleWeapon(self, weaponorder, dir, -1, 1, true);
if(w > 0)
}
void W_NextWeaponOnImpulse(float imp)
-{
+{SELFPARAM();
float w;
w = W_GetCycleWeapon(self, self.cvar_cl_weaponpriority, +1, imp, 1, (self.cvar_cl_weaponimpulsemode == 0));
if(w > 0)
// next weapon
void W_NextWeapon(float list)
-{
+{SELFPARAM();
if(list == 0)
W_CycleWeapon(weaponorder_byid, -1);
else if(list == 1)
// prev weapon
void W_PreviousWeapon(float list)
-{
+{SELFPARAM();
if(list == 0)
W_CycleWeapon(weaponorder_byid, +1);
else if(list == 1)
// previously used if exists and has ammo, (second) best otherwise
void W_LastWeapon(void)
-{
+{SELFPARAM();
if(client_hasweapon(self, self.cnt, true, false))
W_SwitchWeapon(self.cnt);
else
}
void weapon_defaultspawnfunc(float wpn)
-{
+{SELFPARAM();
entity e;
float t;
string s;
- entity oldself;
float i, j;
int f;
if(t >= 2)
{
self.team = --internalteam;
- oldself = self;
for(i = 1; i < t; ++i)
{
s = argv(i);
e = get_weaponinfo(j);
if(e.netname == s)
{
- self = spawn();
- copyentity(oldself, self);
+ setself(spawn());
+ copyentity(this, self);
self.classname = "replacedweapon";
weapon_defaultspawnfunc(j);
break;
}
if(j > WEP_LAST)
{
- LOG_INFO("The weapon replace list for ", oldself.classname, " contains an unknown weapon ", s, ". Skipped.\n");
+ LOG_INFO("The weapon replace list for ", this.classname, " contains an unknown weapon ", s, ". Skipped.\n");
}
}
- self = oldself;
+ setself(this);
}
if(t >= 1) // always the case!
{
if(self.team)
f |= FL_NO_WEAPON_STAY;
- StartItem(e.model, "weapons/weaponpickup.wav", self.respawntime, self.respawntimejitter, e.message, 0, e.weapon, f, weapon_pickupevalfunc, e.bot_pickupbasevalue);
+ StartItem(strzone(e.m_model.model_str()), string_null, self.respawntime, self.respawntimejitter, e.message, 0, e.weapon, f, weapon_pickupevalfunc, e.bot_pickupbasevalue);
+ self.item_pickupsound_ent = SND_WEAPONPICKUP;
#if 0 // WEAPONTODO
- if (self.modelindex) // don't precache if self was removed
- WEP_ACTION(e.weapon, WR_INIT);
+ if (self.modelindex) { // don't precache if self was removed
+ Weapon w = get_weaponinfo(e.weapon);
+ w.wr_init(w);
+ }
#endif
}
#include "../../common/weapons/all.qh"
void thrown_wep_think()
-{
+{SELFPARAM();
self.nextthink = time;
if(self.oldorigin != self.origin)
{
// returns amount of ammo used as string, or -1 for failure, or 0 for no ammo count
string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo)
-{
- entity oldself, wep;
+{SELFPARAM();
float thisammo, i;
string s;
var .int ammotype = (get_weaponinfo(wpn)).ammo_field;
- wep = spawn();
+ entity wep = spawn();
setorigin(wep, org);
wep.classname = "droppedweapon";
wep.flags |= FL_TOSSED;
wep.colormap = own.colormap;
- W_DropEvent(WR_DROP,own,wpn,wep);
+ W_DropEvent(wr_drop,own,wpn,wep);
if(WepSet_FromWeapon(wpn) & WEPSET_SUPERWEAPONS)
{
}
}
- oldself = self;
- self = wep;
- weapon_defaultspawnfunc(wpn);
- self = oldself;
+ WITH(entity, self, wep, weapon_defaultspawnfunc(wpn));
if(startitem_failed)
return string_null;
wep.glowmod = own.weaponentity_glowmod;
// toss current weapon
void W_ThrowWeapon(vector velo, vector delta, float doreduce)
-{
+{SELFPARAM();
float w;
string a;
}
void SpawnThrownWeapon(vector org, float w)
-{
+{SELFPARAM();
if(self.weapons & WepSet_FromWeapon(self.weapon))
if(W_IsWeaponThrowable(self.weapon))
W_ThrowNewWeapon(self, self.weapon, false, org, randomvec() * 125 + '0 0 200');
if (snd != "")
{
- sound (ent, chan, snd, VOL_BASE, ATTN_NORM);
+ _sound (ent, chan, snd, VOL_BASE, ATTN_NORM);
W_PlayStrengthSound(ent);
}
// ====================
void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, int deathtype)
-{
+{SELFPARAM();
vector hitloc, force, endpoint, dir;
entity ent, endent;
float endq3surfaceflags;
if(f <= 0)
continue;
- snd = W_Sound(strcat("nexwhoosh", ftos(floor(random() * 3) + 1)));
+ snd = SND(NEXWHOOSH_RANDOM());
if(!pseudoprojectile)
pseudoprojectile = spawn(); // we need this so the sound uses the "entchannel4" volume
}
void fireBullet(vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, int tracereffects)
-{
+{SELFPARAM();
vector end;
dir = normalize(dir + randomvec() * spread);
}
-void(float fr, float t, void() func) weapon_thinkf;
+void weapon_thinkf(entity actor, float fr, float t, void(Weapon thiswep, entity actor, bool fire1, bool fire2) func);
float CL_Weaponentity_CustomizeEntityForClient()
-{
+{SELFPARAM();
self.viewmodelforclient = self.owner;
if(IS_SPEC(other))
if(other.enemy == self.owner)
// call again with ""
// remove the ent
void CL_WeaponEntity_SetModel(string name)
-{
+{SELFPARAM();
float v_shot_idx;
if (name != "")
{
// if there is a child entity, hide it until we're sure we use it
if (self.weaponentity)
self.weaponentity.model = "";
- setmodel(self, W_Model(strcat("v_", name, ".md3")));
+ _setmodel(self, W_Model(strcat("v_", name, ".md3")));
v_shot_idx = gettagindex(self, "shot"); // used later
if(!v_shot_idx)
v_shot_idx = gettagindex(self, "tag_shot");
- setmodel(self, W_Model(strcat("h_", name, ".iqm")));
+ _setmodel(self, W_Model(strcat("h_", name, ".iqm")));
// preset some defaults that work great for renamed zym files (which don't need an animinfo)
self.anim_fire1 = animfixfps(self, '0 1 0.01', '0 0 0');
self.anim_fire2 = animfixfps(self, '1 1 0.01', '0 0 0');
{
if (!self.weaponentity)
self.weaponentity = spawn();
- setmodel(self.weaponentity, W_Model(strcat("v_", name, ".md3")));
+ _setmodel(self.weaponentity, W_Model(strcat("v_", name, ".md3")));
setattachment(self.weaponentity, self, "weapon");
}
else if(gettagindex(self, "tag_weapon"))
{
if (!self.weaponentity)
self.weaponentity = spawn();
- setmodel(self.weaponentity, W_Model(strcat("v_", name, ".md3")));
+ _setmodel(self.weaponentity, W_Model(strcat("v_", name, ".md3")));
setattachment(self.weaponentity, self, "tag_weapon");
}
else
}
vector CL_Weapon_GetShotOrg(float wpn)
-{
- entity wi, oldself;
- vector ret;
- wi = get_weaponinfo(wpn);
- oldself = self;
- self = spawn();
+{SELFPARAM();
+ entity wi = get_weaponinfo(wpn);
+ setself(spawn());
CL_WeaponEntity_SetModel(wi.mdl);
- ret = self.movedir;
+ vector ret = self.movedir;
CL_WeaponEntity_SetModel("");
remove(self);
- self = oldself;
+ setself(this);
return ret;
}
void CL_Weaponentity_Think()
-{
+{SELFPARAM();
int tb;
self.nextthink = time;
if (intermission_running)
}
void CL_ExteriorWeaponentity_Think()
-{
+{SELFPARAM();
float tag_found;
self.nextthink = time;
if (self.owner.exteriorweaponentity != self)
self.dmg = self.owner.modelindex;
self.deadflag = self.owner.deadflag;
if (self.owner.weaponname != "")
- setmodel(self, W_Model(strcat("v_", self.owner.weaponname, ".md3")));
+ _setmodel(self, W_Model(strcat("v_", self.owner.weaponname, ".md3")));
else
self.model = "";
self.glowmod = self.owner.weaponentity_glowmod;
self.colormap = self.owner.colormap;
- CSQCMODEL_AUTOUPDATE();
+ CSQCMODEL_AUTOUPDATE(self);
}
// spawning weaponentity for client
-void CL_SpawnWeaponentity()
+void CL_SpawnWeaponentity(entity e)
{
- self.weaponentity = spawn();
- self.weaponentity.classname = "weaponentity";
- self.weaponentity.solid = SOLID_NOT;
- self.weaponentity.owner = self;
- setmodel(self.weaponentity, ""); // precision set when changed
- setorigin(self.weaponentity, '0 0 0');
- self.weaponentity.angles = '0 0 0';
- self.weaponentity.viewmodelforclient = self;
- self.weaponentity.flags = 0;
- self.weaponentity.think = CL_Weaponentity_Think;
- self.weaponentity.customizeentityforclient = CL_Weaponentity_CustomizeEntityForClient;
- self.weaponentity.nextthink = time;
-
- self.exteriorweaponentity = spawn();
- self.exteriorweaponentity.classname = "exteriorweaponentity";
- self.exteriorweaponentity.solid = SOLID_NOT;
- self.exteriorweaponentity.exteriorweaponentity = self.exteriorweaponentity;
- self.exteriorweaponentity.owner = self;
- setorigin(self.exteriorweaponentity, '0 0 0');
- self.exteriorweaponentity.angles = '0 0 0';
- self.exteriorweaponentity.think = CL_ExteriorWeaponentity_Think;
- self.exteriorweaponentity.nextthink = time;
-
- {
- entity oldself = self;
- self = self.exteriorweaponentity;
- CSQCMODEL_AUTOINIT();
- self = oldself;
- }
+ entity view = e.weaponentity = spawn();
+ view.classname = "weaponentity";
+ view.solid = SOLID_NOT;
+ view.owner = e;
+ setmodel(view, MDL_Null); // precision set when changed
+ setorigin(view, '0 0 0');
+ view.angles = '0 0 0';
+ view.viewmodelforclient = e;
+ view.flags = 0;
+ view.think = CL_Weaponentity_Think;
+ view.customizeentityforclient = CL_Weaponentity_CustomizeEntityForClient;
+ view.nextthink = time;
+
+ entity exterior = e.exteriorweaponentity = spawn();
+ exterior.classname = "exteriorweaponentity";
+ exterior.solid = SOLID_NOT;
+ exterior.exteriorweaponentity = exterior;
+ exterior.owner = e;
+ setorigin(exterior, '0 0 0');
+ exterior.angles = '0 0 0';
+ exterior.think = CL_ExteriorWeaponentity_Think;
+ exterior.nextthink = time;
+
+ CSQCMODEL_AUTOINIT(exterior);
}
// Weapon subs
-void w_clear()
+void w_clear(Weapon thiswep, entity actor, bool fire1, bool fire2)
{
- if (self.weapon != -1)
+ if (actor.weapon != -1)
{
- self.weapon = 0;
- self.switchingweapon = 0;
+ actor.weapon = 0;
+ actor.switchingweapon = 0;
}
- if (self.weaponentity)
+ if (actor.weaponentity)
{
- self.weaponentity.state = WS_CLEAR;
- self.weaponentity.effects = 0;
+ actor.weaponentity.state = WS_CLEAR;
+ actor.weaponentity.effects = 0;
}
}
-void w_ready()
+void w_ready(Weapon thiswep, entity actor, bool fire1, bool fire2)
{
- if (self.weaponentity)
- self.weaponentity.state = WS_READY;
- weapon_thinkf(WFRAME_IDLE, 1000000, w_ready);
+ if (actor.weaponentity)
+ actor.weaponentity.state = WS_READY;
+ weapon_thinkf(actor, WFRAME_IDLE, 1000000, w_ready);
}
.float prevdryfire;
.float prevwarntime;
-float weapon_prepareattack_checkammo(float secondary)
+bool weapon_prepareattack_checkammo(Weapon thiswep, entity actor, float secondary)
{
- if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
- if (!WEP_ACTION(self.weapon, WR_CHECKAMMO1 + secondary))
- {
- // always keep the Mine Layer if we placed mines, so that we can detonate them
- entity mine;
- if(self.weapon == WEP_MINE_LAYER.m_id)
- for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self)
- return false;
+ if ((actor.items & IT_UNLIMITED_WEAPON_AMMO)) return true;
+ bool ammo = false;
+ if (secondary) {
+ WITH(entity, self, actor, ammo = thiswep.wr_checkammo2(thiswep));
+ } else {
+ WITH(entity, self, actor, ammo = thiswep.wr_checkammo1(thiswep));
+ }
+ if (ammo) return true;
+ // always keep the Mine Layer if we placed mines, so that we can detonate them
+ entity mine;
+ if(actor.weapon == WEP_MINE_LAYER.m_id)
+ for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == actor)
+ return false;
- if(self.weapon == WEP_SHOTGUN.m_id)
- if(!secondary && WEP_CVAR(shotgun, secondary) == 1)
- return false; // no clicking, just allow
+ if(actor.weapon == WEP_SHOTGUN.m_id)
+ if(!secondary && WEP_CVAR(shotgun, secondary) == 1)
+ return false; // no clicking, just allow
- if(self.weapon == self.switchweapon && time - self.prevdryfire > 1) // only play once BEFORE starting to switch weapons
- {
- sound (self, CH_WEAPON_A, W_Sound("dryfire"), VOL_BASE, ATTEN_NORM);
- self.prevdryfire = time;
- }
+ if(actor.weapon == actor.switchweapon && time - actor.prevdryfire > 1) // only play once BEFORE starting to switch weapons
+ {
+ sound (actor, CH_WEAPON_A, SND_DRYFIRE, VOL_BASE, ATTEN_NORM);
+ actor.prevdryfire = time;
+ }
- if(WEP_ACTION(self.weapon, WR_CHECKAMMO2 - secondary)) // check if the other firing mode has enough ammo
- {
- if(time - self.prevwarntime > 1)
- {
- Send_Notification(
- NOTIF_ONE,
- self,
- MSG_MULTI,
- ITEM_WEAPON_PRIMORSEC,
- self.weapon,
- secondary,
- (1 - secondary)
- );
- }
- self.prevwarntime = time;
- }
- else // this weapon is totally unable to fire, switch to another one
+ // check if the other firing mode has enough ammo
+ bool ammo_other = false;
+ if (secondary) {
+ WITH(entity, self, actor, ammo = thiswep.wr_checkammo1(thiswep));
+ } else {
+ WITH(entity, self, actor, ammo = thiswep.wr_checkammo2(thiswep));
+ }
+ if (ammo_other)
+ {
+ if (time - actor.prevwarntime > 1)
{
- W_SwitchToOtherWeapon(self);
+ Send_Notification(
+ NOTIF_ONE,
+ actor,
+ MSG_MULTI,
+ ITEM_WEAPON_PRIMORSEC,
+ actor.weapon,
+ secondary,
+ (1 - secondary)
+ );
}
-
- return false;
+ actor.prevwarntime = time;
}
- return true;
+ else // this weapon is totally unable to fire, switch to another one
+ {
+ W_SwitchToOtherWeapon(actor);
+ }
+
+ return false;
}
.float race_penalty;
-float weapon_prepareattack_check(float secondary, float attacktime)
+bool weapon_prepareattack_check(Weapon thiswep, entity actor, bool secondary, float attacktime)
{
- if(!weapon_prepareattack_checkammo(secondary))
+ if(!weapon_prepareattack_checkammo(thiswep, actor, secondary))
return false;
//if sv_ready_restart_after_countdown is set, don't allow the player to shoot
//if all players readied up and the countdown is running
- if(time < game_starttime || time < self.race_penalty) {
+ if(time < game_starttime || time < actor.race_penalty) {
return false;
}
return false;
// do not even think about shooting if switching
- if(self.switchweapon != self.weapon)
+ if(actor.switchweapon != actor.weapon)
return false;
if(attacktime >= 0)
{
// don't fire if previous attack is not finished
- if (ATTACK_FINISHED(self) > time + self.weapon_frametime * 0.5)
+ if (ATTACK_FINISHED(actor) > time + actor.weapon_frametime * 0.5)
return false;
// don't fire while changing weapon
- if (self.weaponentity.state != WS_READY)
+ if (actor.weaponentity.state != WS_READY)
return false;
}
-
return true;
}
-float weapon_prepareattack_do(float secondary, float attacktime)
+void weapon_prepareattack_do(entity actor, bool secondary, float attacktime)
{
- self.weaponentity.state = WS_INUSE;
+ actor.weaponentity.state = WS_INUSE;
- self.spawnshieldtime = min(self.spawnshieldtime, time); // kill spawn shield when you fire
+ actor.spawnshieldtime = min(actor.spawnshieldtime, time); // kill spawn shield when you fire
// if the weapon hasn't been firing continuously, reset the timer
if(attacktime >= 0)
{
- if (ATTACK_FINISHED(self) < time - self.weapon_frametime * 1.5)
+ if (ATTACK_FINISHED(actor) < time - actor.weapon_frametime * 1.5)
{
- ATTACK_FINISHED(self) = time;
+ ATTACK_FINISHED(actor) = time;
//dprint("resetting attack finished to ", ftos(time), "\n");
}
- ATTACK_FINISHED(self) = ATTACK_FINISHED(self) + attacktime * W_WeaponRateFactor();
+ ATTACK_FINISHED(actor) = ATTACK_FINISHED(actor) + attacktime * W_WeaponRateFactor();
}
- self.bulletcounter += 1;
- //dprint("attack finished ", ftos(ATTACK_FINISHED(self)), "\n");
- return true;
+ actor.bulletcounter += 1;
+ //dprint("attack finished ", ftos(ATTACK_FINISHED(actor)), "\n");
}
-float weapon_prepareattack(float secondary, float attacktime)
+bool weapon_prepareattack(Weapon thiswep, entity actor, bool secondary, float attacktime)
{
- if(weapon_prepareattack_check(secondary, attacktime))
- {
- weapon_prepareattack_do(secondary, attacktime);
+ if (weapon_prepareattack_check(thiswep, actor, secondary, attacktime)) {
+ weapon_prepareattack_do(actor, secondary, attacktime);
return true;
}
- else
- return false;
+ return false;
}
-void weapon_thinkf(float fr, float t, void() func)
+void weapon_thinkf(entity actor, float fr, float t, void(Weapon thiswep, entity actor, bool fire1, bool fire2) func)
{
vector a;
vector of, or, ou;
if(fr == WFRAME_DONTCHANGE)
{
- fr = self.weaponentity.wframe;
+ fr = actor.weaponentity.wframe;
restartanim = false;
}
else if (fr == WFRAME_IDLE)
or = v_right;
ou = v_up;
- if (self.weaponentity)
+ if (actor.weaponentity)
{
- self.weaponentity.wframe = fr;
+ actor.weaponentity.wframe = fr;
a = '0 0 0';
if (fr == WFRAME_IDLE)
- a = self.weaponentity.anim_idle;
+ a = actor.weaponentity.anim_idle;
else if (fr == WFRAME_FIRE1)
- a = self.weaponentity.anim_fire1;
+ a = actor.weaponentity.anim_fire1;
else if (fr == WFRAME_FIRE2)
- a = self.weaponentity.anim_fire2;
+ a = actor.weaponentity.anim_fire2;
else // if (fr == WFRAME_RELOAD)
- a = self.weaponentity.anim_reload;
+ a = actor.weaponentity.anim_reload;
a.z *= g_weaponratefactor;
- setanim(self.weaponentity, a, restartanim == false, restartanim, restartanim);
+ setanim(actor.weaponentity, a, restartanim == false, restartanim, restartanim);
}
v_forward = of;
v_right = or;
v_up = ou;
- if(self.weapon_think == w_ready && func != w_ready && self.weaponentity.state == WS_RAISE)
+ if(actor.weapon_think == w_ready && func != w_ready && actor.weaponentity.state == WS_RAISE)
{
backtrace("Tried to override initial weapon think function - should this really happen?");
}
t *= W_WeaponRateFactor();
// VorteX: haste can be added here
- if (self.weapon_think == w_ready)
+ if (actor.weapon_think == w_ready)
{
- self.weapon_nextthink = time;
+ actor.weapon_nextthink = time;
//dprint("started firing at ", ftos(time), "\n");
}
- if (self.weapon_nextthink < time - self.weapon_frametime * 1.5 || self.weapon_nextthink > time + self.weapon_frametime * 1.5)
+ if (actor.weapon_nextthink < time - actor.weapon_frametime * 1.5 || actor.weapon_nextthink > time + actor.weapon_frametime * 1.5)
{
- self.weapon_nextthink = time;
+ actor.weapon_nextthink = time;
//dprint("reset weapon animation timer at ", ftos(time), "\n");
}
- self.weapon_nextthink = self.weapon_nextthink + t;
- self.weapon_think = func;
- //dprint("next ", ftos(self.weapon_nextthink), "\n");
+ actor.weapon_nextthink = actor.weapon_nextthink + t;
+ actor.weapon_think = func;
+ //dprint("next ", ftos(actor.weapon_nextthink), "\n");
if((fr == WFRAME_FIRE1 || fr == WFRAME_FIRE2) && t)
{
- if((self.weapon == WEP_SHOCKWAVE.m_id || self.weapon == WEP_SHOTGUN.m_id) && fr == WFRAME_FIRE2)
- animdecide_setaction(self, ANIMACTION_MELEE, restartanim);
+ if((actor.weapon == WEP_SHOCKWAVE.m_id || actor.weapon == WEP_SHOTGUN.m_id) && fr == WFRAME_FIRE2)
+ animdecide_setaction(actor, ANIMACTION_MELEE, restartanim);
else
- animdecide_setaction(self, ANIMACTION_SHOOT, restartanim);
+ animdecide_setaction(actor, ANIMACTION_SHOOT, restartanim);
}
else
{
- if(self.anim_upper_action == ANIMACTION_SHOOT || self.anim_upper_action == ANIMACTION_MELEE)
- self.anim_upper_action = 0;
+ if(actor.anim_upper_action == ANIMACTION_SHOOT || actor.anim_upper_action == ANIMACTION_MELEE)
+ actor.anim_upper_action = 0;
}
}
return 0;
}
-void W_WeaponFrame()
+.bool hook_switchweapon;
+
+void W_WeaponFrame(entity actor)
{
vector fo, ri, up;
if (frametime)
- self.weapon_frametime = frametime;
+ actor.weapon_frametime = frametime;
- if (!self.weaponentity || self.health < 1)
+ if (!actor.weaponentity || actor.health < 1)
return; // Dead player can't use weapons and injure impulse commands
- if(forbidWeaponUse(self))
- if(self.weaponentity.state != WS_CLEAR)
+ if(forbidWeaponUse(actor))
+ if(actor.weaponentity.state != WS_CLEAR)
{
- w_ready();
+ Weapon wpn = get_weaponinfo(actor.weapon);
+ w_ready(wpn, actor, actor.BUTTON_ATCK, actor.BUTTON_ATCK2);
return;
}
- if(!self.switchweapon)
+ if(!actor.switchweapon)
{
- self.weapon = 0;
- self.switchingweapon = 0;
- self.weaponentity.state = WS_CLEAR;
- self.weaponname = "";
- //self.items &= ~IT_AMMO;
+ actor.weapon = 0;
+ actor.switchingweapon = 0;
+ actor.weaponentity.state = WS_CLEAR;
+ actor.weaponname = "";
+ //actor.items &= ~IT_AMMO;
return;
}
- makevectors(self.v_angle);
+ makevectors(actor.v_angle);
fo = v_forward; // save them in case the weapon think functions change it
ri = v_right;
up = v_up;
// Change weapon
- if (self.weapon != self.switchweapon)
+ if (actor.weapon != actor.switchweapon)
{
- if (self.weaponentity.state == WS_CLEAR)
+ if (actor.weaponentity.state == WS_CLEAR)
{
// end switching!
- self.switchingweapon = self.switchweapon;
- entity newwep = get_weaponinfo(self.switchweapon);
+ actor.switchingweapon = actor.switchweapon;
+ entity newwep = get_weaponinfo(actor.switchweapon);
// the two weapon entities will notice this has changed and update their models
- self.weapon = self.switchweapon;
- self.weaponname = newwep.mdl;
- self.bulletcounter = 0;
- self.ammo_field = newwep.ammo_field;
- WEP_ACTION(self.switchweapon, WR_SETUP);
- self.weaponentity.state = WS_RAISE;
+ actor.weapon = actor.switchweapon;
+ actor.weaponname = newwep.mdl;
+ actor.bulletcounter = 0;
+ actor.ammo_field = newwep.ammo_field;
+ Weapon w = get_weaponinfo(actor.switchweapon);
+ w.wr_setup(w);
+ actor.weaponentity.state = WS_RAISE;
// set our clip load to the load of the weapon we switched to, if it's reloadable
if(newwep.spawnflags & WEP_FLAG_RELOADABLE && newwep.reloading_ammo) // prevent accessing undefined cvars
{
- self.clip_load = self.(weapon_load[self.switchweapon]);
- self.clip_size = newwep.reloading_ammo;
+ actor.clip_load = actor.(weapon_load[actor.switchweapon]);
+ actor.clip_size = newwep.reloading_ammo;
}
else
- self.clip_load = self.clip_size = 0;
+ actor.clip_load = actor.clip_size = 0;
- weapon_thinkf(WFRAME_IDLE, newwep.switchdelay_raise, w_ready);
+ weapon_thinkf(actor, WFRAME_IDLE, newwep.switchdelay_raise, w_ready);
}
- else if (self.weaponentity.state == WS_DROP)
+ else if (actor.weaponentity.state == WS_DROP)
{
// in dropping phase we can switch at any time
- self.switchingweapon = self.switchweapon;
+ actor.switchingweapon = actor.switchweapon;
}
- else if (self.weaponentity.state == WS_READY)
+ else if (actor.weaponentity.state == WS_READY)
{
// start switching!
- self.switchingweapon = self.switchweapon;
- entity oldwep = get_weaponinfo(self.weapon);
+ actor.switchingweapon = actor.switchweapon;
+ entity oldwep = get_weaponinfo(actor.weapon);
// set up weapon switch think in the future, and start drop anim
#ifndef INDEPENDENT_ATTACK_FINISHED
- if(ATTACK_FINISHED(self) <= time + self.weapon_frametime * 0.5)
+ if(ATTACK_FINISHED(actor) <= time + actor.weapon_frametime * 0.5)
{
#endif
- sound(self, CH_WEAPON_SINGLE, W_Sound("weapon_switch"), VOL_BASE, ATTN_NORM);
- self.weaponentity.state = WS_DROP;
- weapon_thinkf(WFRAME_DONTCHANGE, oldwep.switchdelay_drop, w_clear);
+ sound(actor, CH_WEAPON_SINGLE, SND_WEAPON_SWITCH, VOL_BASE, ATTN_NORM);
+ actor.weaponentity.state = WS_DROP;
+ weapon_thinkf(actor, WFRAME_DONTCHANGE, oldwep.switchdelay_drop, w_clear);
#ifndef INDEPENDENT_ATTACK_FINISHED
}
#endif
}
// LordHavoc: network timing test code
- //if (self.button0)
- // print(ftos(frametime), " ", ftos(time), " >= ", ftos(ATTACK_FINISHED(self)), " >= ", ftos(self.weapon_nextthink), "\n");
+ //if (actor.button0)
+ // print(ftos(frametime), " ", ftos(time), " >= ", ftos(ATTACK_FINISHED(actor)), " >= ", ftos(actor.weapon_nextthink), "\n");
float w;
- w = self.weapon;
+ w = actor.weapon;
// call the think code which may fire the weapon
// and do so multiple times to resolve framerate dependency issues if the
while (c < W_TICSPERFRAME)
{
c = c + 1;
- if(w && !(self.weapons & WepSet_FromWeapon(w)))
+ if(w && !(actor.weapons & WepSet_FromWeapon(w)))
{
- if(self.weapon == self.switchweapon)
- W_SwitchWeapon_Force(self, w_getbestweapon(self));
+ if(actor.weapon == actor.switchweapon)
+ W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
w = 0;
}
v_right = ri;
v_up = up;
- if(w)
- WEP_ACTION(self.weapon, WR_THINK);
- else
- WEP_ACTION(self.weapon, WR_GONETHINK);
+ bool block_weapon = false;
+ {
+ bool key_pressed = actor.BUTTON_HOOK && !actor.vehicle;
+ Weapon off = actor.offhand;
+ if (off && !(actor.weapons & WEPSET(HOOK))) {
+ if (off.offhand_think) off.offhand_think(off, actor, key_pressed);
+ } else {
+ if (key_pressed && actor.switchweapon != WEP_HOOK.m_id && !actor.hook_switchweapon) {
+ W_SwitchWeapon(WEP_HOOK.m_id);
+ }
+ actor.hook_switchweapon = key_pressed;
+ Weapon h = WEP_HOOK;
+ block_weapon = (actor.weapon == h.m_id && (actor.BUTTON_ATCK || key_pressed));
+ h.wr_think(h, actor, block_weapon, false);
+ }
+ }
+
+ if (!block_weapon)
+ if (w) {
+ Weapon e = get_weaponinfo(actor.weapon);
+ e.wr_think(e, actor, actor.BUTTON_ATCK, actor.BUTTON_ATCK2);
+ } else {
+ Weapon w = get_weaponinfo(actor.weapon);
+ w.wr_gonethink(w);
+ }
- if (time + self.weapon_frametime * 0.5 >= self.weapon_nextthink)
+ if (time + actor.weapon_frametime * 0.5 >= actor.weapon_nextthink)
{
- if(self.weapon_think)
+ if(actor.weapon_think)
{
v_forward = fo;
v_right = ri;
v_up = up;
- self.weapon_think();
+ Weapon wpn = get_weaponinfo(actor.weapon);
+ actor.weapon_think(wpn, actor, actor.BUTTON_ATCK, actor.BUTTON_ATCK2);
}
else
- bprint("\{1}^1ERROR: undefined weapon think function for ", self.netname, "\n");
+ bprint("\{1}^1ERROR: undefined weapon think function for ", actor.netname, "\n");
}
}
}
-void W_AttachToShotorg(entity flash, vector offset)
+void W_AttachToShotorg(entity actor, entity flash, vector offset)
{
entity xflash;
- flash.owner = self;
+ flash.owner = actor;
flash.angles_z = random() * 360;
- if(gettagindex(self.weaponentity, "shot"))
- setattachment(flash, self.weaponentity, "shot");
+ if(gettagindex(actor.weaponentity, "shot"))
+ setattachment(flash, actor.weaponentity, "shot");
else
- setattachment(flash, self.weaponentity, "tag_shot");
+ setattachment(flash, actor.weaponentity, "tag_shot");
setorigin(flash, offset);
xflash = spawn();
copyentity(flash, xflash);
- flash.viewmodelforclient = self;
+ flash.viewmodelforclient = actor;
- if(self.weaponentity.oldorigin.x > 0)
+ if(actor.weaponentity.oldorigin.x > 0)
{
- setattachment(xflash, self.exteriorweaponentity, "");
- setorigin(xflash, self.weaponentity.oldorigin + offset);
+ setattachment(xflash, actor.exteriorweaponentity, "");
+ setorigin(xflash, actor.weaponentity.oldorigin + offset);
}
else
{
- if(gettagindex(self.exteriorweaponentity, "shot"))
- setattachment(xflash, self.exteriorweaponentity, "shot");
+ if(gettagindex(actor.exteriorweaponentity, "shot"))
+ setattachment(xflash, actor.exteriorweaponentity, "shot");
else
- setattachment(xflash, self.exteriorweaponentity, "tag_shot");
+ setattachment(xflash, actor.exteriorweaponentity, "tag_shot");
setorigin(xflash, offset);
}
}
-void W_DecreaseAmmo(float ammo_use)
+void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use)
{
- entity wep = get_weaponinfo(self.weapon);
if(cvar("g_overkill"))
- if(self.ok_use_ammocharge)
+ if(actor.ok_use_ammocharge)
{
- ok_DecreaseCharge(self, self.weapon);
+ ok_DecreaseCharge(actor, actor.weapon);
return; // TODO
}
- if((self.items & IT_UNLIMITED_WEAPON_AMMO) && !wep.reloading_ammo)
+ if((actor.items & IT_UNLIMITED_WEAPON_AMMO) && !wep.reloading_ammo)
return;
// if this weapon is reloadable, decrease its load. Else decrease the player's ammo
if(wep.reloading_ammo)
{
- self.clip_load -= ammo_use;
- self.(weapon_load[self.weapon]) = self.clip_load;
+ actor.clip_load -= ammo_use;
+ actor.(weapon_load[actor.weapon]) = actor.clip_load;
}
else if(wep.ammo_field != ammo_none)
{
- self.(wep.ammo_field) -= ammo_use;
- if(self.(wep.ammo_field) < 0)
+ actor.(wep.ammo_field) -= ammo_use;
+ if(actor.(wep.ammo_field) < 0)
{
backtrace(sprintf(
"W_DecreaseAmmo(%.2f): '%s' subtracted too much %s from '%s', resulting with '%.2f' left... "
ammo_use,
wep.netname,
GetAmmoPicture(wep.ammo_field),
- self.netname,
- self.(wep.ammo_field)
+ actor.netname,
+ actor.(wep.ammo_field)
));
}
}
.float reload_complain;
.string reload_sound;
-void W_ReloadedAndReady()
+void W_ReloadedAndReady(Weapon thiswep, entity actor, bool fire1, bool fire2)
{
// finish the reloading process, and do the ammo transfer
- self.clip_load = self.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading
+ actor.clip_load = actor.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading
// if the gun uses no ammo, max out weapon load, else decrease ammo as we increase weapon load
- if(!self.reload_ammo_min || self.items & IT_UNLIMITED_WEAPON_AMMO || self.ammo_field == ammo_none)
- self.clip_load = self.reload_ammo_amount;
+ if(!actor.reload_ammo_min || actor.items & IT_UNLIMITED_WEAPON_AMMO || actor.ammo_field == ammo_none)
+ actor.clip_load = actor.reload_ammo_amount;
else
{
// make sure we don't add more ammo than we have
- float load = min(self.reload_ammo_amount - self.clip_load, self.(self.ammo_field));
- self.clip_load += load;
- self.(self.ammo_field) -= load;
+ float load = min(actor.reload_ammo_amount - actor.clip_load, actor.(actor.ammo_field));
+ actor.clip_load += load;
+ actor.(actor.ammo_field) -= load;
}
- self.(weapon_load[self.weapon]) = self.clip_load;
+ actor.(weapon_load[actor.weapon]) = actor.clip_load;
// do not set ATTACK_FINISHED in reload code any more. This causes annoying delays if eg: You start reloading a weapon,
// then quickly switch to another weapon and back. Reloading is canceled, but the reload delay is still there,
// so your weapon is disabled for a few seconds without reason
- //ATTACK_FINISHED(self) -= self.reload_time - 1;
+ //ATTACK_FINISHED(actor) -= actor.reload_time - 1;
- w_ready();
+ Weapon wpn = get_weaponinfo(actor.weapon);
+ w_ready(wpn, actor, actor.BUTTON_ATCK, actor.BUTTON_ATCK2);
}
-void W_Reload(float sent_ammo_min, string sent_sound)
+void W_Reload(entity actor, float sent_ammo_min, string sent_sound)
{
// set global values to work with
entity e;
- e = get_weaponinfo(self.weapon);
+ e = get_weaponinfo(actor.weapon);
if(cvar("g_overkill"))
- if(self.ok_use_ammocharge)
+ if(actor.ok_use_ammocharge)
return; // TODO
- self.reload_ammo_min = sent_ammo_min;
- self.reload_ammo_amount = e.reloading_ammo;
- self.reload_time = e.reloading_time;
- self.reload_sound = sent_sound;
+ actor.reload_ammo_min = sent_ammo_min;
+ actor.reload_ammo_amount = e.reloading_ammo;
+ actor.reload_time = e.reloading_time;
+ actor.reload_sound = sent_sound;
// don't reload weapons that don't have the RELOADABLE flag
if (!(e.spawnflags & WEP_FLAG_RELOADABLE))
}
// return if reloading is disabled for this weapon
- if(!self.reload_ammo_amount)
+ if(!actor.reload_ammo_amount)
return;
// our weapon is fully loaded, no need to reload
- if (self.clip_load >= self.reload_ammo_amount)
+ if (actor.clip_load >= actor.reload_ammo_amount)
return;
// no ammo, so nothing to load
- if(self.ammo_field != ammo_none)
- if(!self.(self.ammo_field) && self.reload_ammo_min)
- if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+ if(actor.ammo_field != ammo_none)
+ if(!actor.(actor.ammo_field) && actor.reload_ammo_min)
+ if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
- if(IS_REAL_CLIENT(self) && self.reload_complain < time)
+ if(IS_REAL_CLIENT(actor) && actor.reload_complain < time)
{
- play2(self, W_Sound("unavailable"));
- sprint(self, strcat("You don't have enough ammo to reload the ^2", WEP_NAME(self.weapon), "\n"));
- self.reload_complain = time + 1;
+ play2(actor, SND(UNAVAILABLE));
+ sprint(actor, strcat("You don't have enough ammo to reload the ^2", WEP_NAME(actor.weapon), "\n"));
+ actor.reload_complain = time + 1;
}
// switch away if the amount of ammo is not enough to keep using this weapon
- if (!(WEP_ACTION(self.weapon, WR_CHECKAMMO1) + WEP_ACTION(self.weapon, WR_CHECKAMMO2)))
+ Weapon w = get_weaponinfo(actor.weapon);
+ if (!(w.wr_checkammo1(w) + w.wr_checkammo2(w)))
{
- self.clip_load = -1; // reload later
- W_SwitchToOtherWeapon(self);
+ actor.clip_load = -1; // reload later
+ W_SwitchToOtherWeapon(actor);
}
return;
}
- if (self.weaponentity)
+ if (actor.weaponentity)
{
- if (self.weaponentity.wframe == WFRAME_RELOAD)
+ if (actor.weaponentity.wframe == WFRAME_RELOAD)
return;
// allow switching away while reloading, but this will cause a new reload!
- self.weaponentity.state = WS_READY;
+ actor.weaponentity.state = WS_READY;
}
// now begin the reloading process
- sound(self, CH_WEAPON_SINGLE, self.reload_sound, VOL_BASE, ATTEN_NORM);
+ _sound(actor, CH_WEAPON_SINGLE, actor.reload_sound, VOL_BASE, ATTEN_NORM);
// do not set ATTACK_FINISHED in reload code any more. This causes annoying delays if eg: You start reloading a weapon,
// then quickly switch to another weapon and back. Reloading is canceled, but the reload delay is still there,
// so your weapon is disabled for a few seconds without reason
- //ATTACK_FINISHED(self) = max(time, ATTACK_FINISHED(self)) + self.reload_time + 1;
+ //ATTACK_FINISHED(actor) = max(time, ATTACK_FINISHED(actor)) + actor.reload_time + 1;
- weapon_thinkf(WFRAME_RELOAD, self.reload_time, W_ReloadedAndReady);
+ weapon_thinkf(actor, WFRAME_RELOAD, actor.reload_time, W_ReloadedAndReady);
- if(self.clip_load < 0)
- self.clip_load = 0;
- self.old_clip_load = self.clip_load;
- self.clip_load = self.(weapon_load[self.weapon]) = -1;
+ if(actor.clip_load < 0)
+ actor.clip_load = 0;
+ actor.old_clip_load = actor.clip_load;
+ actor.clip_load = actor.(weapon_load[actor.weapon]) = -1;
}
-void W_DropEvent(float event, entity player, float weapon_type, entity weapon_item)
-{
- entity oldself = self;
- self = player;
+void W_DropEvent(.void(Weapon) event, entity player, float weapon_type, entity weapon_item)
+{SELFPARAM();
+ setself(player);
weapon_dropevent_item = weapon_item;
- WEP_ACTION(weapon_type, event);
- self = oldself;
+ Weapon w = get_weaponinfo(weapon_type);
+ w.event(w);
+ setself(this);
}
const float WFRAME_IDLE = 2;
const float WFRAME_RELOAD = 3;
-void CL_SpawnWeaponentity();
+void CL_SpawnWeaponentity(entity e);
vector CL_Weapon_GetShotOrg(float wpn);
float forbidWeaponUse(entity player);
-void W_AttachToShotorg(entity flash, vector offset);
+void W_AttachToShotorg(entity actor, entity flash, vector offset);
-void W_DecreaseAmmo(float ammo_use);
+void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use);
-void W_DropEvent(float event, entity player, float weapon_type, entity weapon_item);
+void W_DropEvent(.void(Weapon) event, entity player, float weapon_type, entity weapon_item);
-void W_Reload(float sent_ammo_min, string sent_sound);
+void W_Reload(entity actor, float sent_ammo_min, string sent_sound);
-void W_WeaponFrame();
+void W_WeaponFrame(entity actor);
float W_WeaponRateFactor();
float W_WeaponSpeedFactor();
-float weapon_prepareattack(float secondary, float attacktime);
+bool weapon_prepareattack(Weapon thiswep, entity actor, bool secondary, float attacktime);
-float weapon_prepareattack_check(float secondary, float attacktime);
+bool weapon_prepareattack_check(Weapon thiswep, entity actor, float secondary, float attacktime);
-float weapon_prepareattack_do(float secondary, float attacktime);
+void weapon_prepareattack_do(entity actor, float secondary, float attacktime);
-void weapon_thinkf(float fr, float t, void() func);
+void weapon_thinkf(entity actor, float fr, float t, void(Weapon thiswep, entity actor, bool fire1, bool fire2) func);
#endif
#endif
void WarpZone_Fade_PreDraw()
-{
+{SELFPARAM();
vector org;
org = getpropertyvec(VF_ORIGIN);
if(!checkpvs(org, self)) // this makes sense as long as we don't support recursive warpzones
}
void WarpZone_Read(float isnew)
-{
+{SELFPARAM();
warpzone_warpzones_exist = 1;
if (!self.enemy)
{
}
void WarpZone_Camera_Read(float isnew)
-{
+{SELFPARAM();
warpzone_cameras_exist = 1;
self.classname = "func_warpzone_camera";
void CL_RotateMoves(vector ang) = #638;
void WarpZone_Teleported_Read(float isnew)
-{
+{SELFPARAM();
vector v;
self.classname = "warpzone_teleported";
v.x = ReadCoord();
.vector(vector, vector) camera_transform;
float autocvar_cl_warpzone_usetrace = 1;
vector WarpZone_camera_transform(vector org, vector ang)
-{
+{SELFPARAM();
vector vf, vr, vu;
if(self.warpzone_fadestart)
if(vlen(org - self.origin - 0.5 * (self.mins + self.maxs)) > self.warpzone_fadeend + 400)
}
vector WarpZone_Camera_camera_transform(vector org, vector ang)
-{
+{SELFPARAM();
// a fixed camera view
if(self.warpzone_fadestart)
if(vlen(org - self.origin - 0.5 * (self.mins + self.maxs)) > self.warpzone_fadeend + 400)
return nearest;
}
-float WarpZoneLib_BadClassname(string myclassname)
+bool WarpZoneLib_BadEntity(entity e)
{
+ string myclassname = e.classname;
+ if (e.instanceOfObject) return true;
switch(myclassname)
{
- case "weapon_info":
- case "monster_info":
case "deathtype":
- case "callback":
- case "callbackchain":
case "weaponentity":
case "exteriorweaponentity":
case "csqc_score_team":
case "ent_client_scoreinfo":
case "saved_cvar_value":
case "accuracy":
- case "entcs_sender_v2":
- case "entcs_receiver_v2":
+ case "entcs_sender":
+ case "entcs_receiver":
case "clientinit":
case "sprite_waypoint":
case "waypoint":
for(e = e0; e; e = e.chain)
{
- if(WarpZoneLib_BadClassname(e.classname))
+ if(WarpZoneLib_BadEntity(e))
continue;
p = WarpZoneLib_NearestPointOnBox(e.origin + e.mins, e.origin + e.maxs, org0);
if(needlineofsight)
}
for(e = wz; e; e = e.WarpZone_findradius_next)
{
- if(WarpZoneLib_BadClassname(e.classname))
+ if(WarpZoneLib_BadEntity(e))
continue;
org0_new = WarpZone_TransformOrigin(e, org);
.entity WarpZone_refsys;
void WarpZone_RefSys_GC()
-{
+{SELFPARAM();
// garbage collect unused reference systems
self.nextthink = time + 1;
if(self.owner.WarpZone_refsys != self)
}
float WarpZoneLib_ExactTrigger_Touch()
-{
+{SELFPARAM();
return !WarpZoneLib_BoxTouchesBrush(other.absmin, other.absmax, self, other);
}
}
bool WarpZone_Teleported_Send(entity to, int sf)
-{
+{SELFPARAM();
WriteByte(MSG_ENTITY, ENT_CLIENT_WARPZONE_TELEPORTED);
WriteCoord(MSG_ENTITY, self.angles.x);
WriteCoord(MSG_ENTITY, self.angles.y);
player.fixangle = false;
entity ts = spawn();
- setmodel(ts, "null");
+ setmodel(ts, MDL_Null);
ts.SendEntity = WarpZone_Teleported_Send;
ts.SendFlags = 0xFFFFFF;
ts.drawonlytoclient = player;
}
void WarpZone_Touch (void)
-{
- entity oldself;
-
+{SELFPARAM();
if(other.classname == "trigger_warpzone")
return;
if (!self.target) self.target = save1;
if (!self.target3) self.target3 = save2;
- oldself = self;
- self = self.enemy;
+ setself(self.enemy);
save1 = self.target; self.target = string_null;
save2 = self.target2; self.target2 = string_null;
SUB_UseTargets();
if (!self.target) self.target = save1;
if (!self.target2) self.target2 = save2;
- self = oldself;
+ setself(this);
}
else
{
}
bool WarpZone_Send(entity to, int sendflags)
-{
+{SELFPARAM();
WriteByte(MSG_ENTITY, ENT_CLIENT_WARPZONE);
// we must send this flag for clientside to match properly too
}
bool WarpZone_Camera_Send(entity to, int sendflags)
-{
+{SELFPARAM();
int f = 0;
WriteByte(MSG_ENTITY, ENT_CLIENT_WARPZONE_CAMERA);
#ifdef WARPZONELIB_KEEPDEBUG
float WarpZone_CheckProjectileImpact(entity player)
-{
+{SELFPARAM();
vector o0, v0;
o0 = player.origin + player.view_ofs;
#endif
float WarpZone_Projectile_Touch()
-{
+{SELFPARAM();
if(other.classname == "trigger_warpzone")
return true;
}
void WarpZone_InitStep_FindOriginTarget()
-{
+{SELFPARAM();
if(self.killtarget != "")
{
self.aiment = find(world, targetname, self.killtarget);
}
void WarpZonePosition_InitStep_FindTarget()
-{
+{SELFPARAM();
if(self.target == "")
{
error("Warp zone position with no target");
}
void WarpZoneCamera_Think(void)
-{
+{SELFPARAM();
if(self.warpzone_save_origin != self.origin
|| self.warpzone_save_angles != self.angles
|| self.warpzone_save_eorigin != self.enemy.origin
}
void WarpZoneCamera_InitStep_FindTarget()
-{
+{SELFPARAM();
entity e;
float i;
if(self.target == "")
}
void WarpZone_InitStep_UpdateTransform()
-{
+{SELFPARAM();
vector org, ang, norm, point;
float area;
vector tri, a, b, c, n;
}
void WarpZone_InitStep_ClearTarget()
-{
+{SELFPARAM();
if(self.enemy)
self.enemy.enemy = world;
self.enemy = world;
entity warpzone_first; .entity warpzone_next;
void WarpZone_InitStep_FindTarget()
-{
+{SELFPARAM();
float i;
entity e, e2;
void WarpZone_Think();
void WarpZone_InitStep_FinalizeTransform()
-{
+{SELFPARAM();
if(!self.enemy || self.enemy.enemy != self)
{
error("Invalid warp zone detected. Killed.");
entity warpzone_position_first;
entity warpzone_camera_first;
.entity warpzone_next;
-void spawnfunc_misc_warpzone_position(void)
+spawnfunc(misc_warpzone_position)
{
// "target", "angles", "origin"
self.warpzone_next = warpzone_position_first;
warpzone_position_first = self;
}
-void spawnfunc_trigger_warpzone_position(void)
+spawnfunc(trigger_warpzone_position)
{
- spawnfunc_misc_warpzone_position();
+ spawnfunc_misc_warpzone_position(this);
}
-void spawnfunc_trigger_warpzone(void)
+spawnfunc(trigger_warpzone)
{
// warp zone entities must have:
// "killtarget" pointing to a target_position with a direction arrow
// the map, with another killtarget to designate its
// orientation
-#ifndef WARPZONE_USE_FIXANGLE
- // used when teleporting
- precache_model("null");
-#endif
-
if(!self.scale)
self.scale = self.modelscale;
if(!self.scale)
if(m != "")
{
precache_model(m);
- setmodel(self, m); // no precision needed
+ _setmodel(self, m); // no precision needed
}
setorigin(self, self.origin);
if(self.scale)
self.warpzone_next = warpzone_first;
warpzone_first = self;
}
-void spawnfunc_func_camera(void)
+spawnfunc(func_camera)
{
if(!self.scale)
self.scale = self.modelscale;
if(self.model != "")
{
precache_model(self.model);
- setmodel(self, self.model); // no precision needed
+ _setmodel(self, self.model); // no precision needed
}
setorigin(self, self.origin);
if(self.scale)
warpzone_camera_first = self;
}
void WarpZones_Reconnect()
-{
- entity e;
- e = self;
- for(self = warpzone_first; self; self = self.warpzone_next)
+{SELFPARAM();
+ for(setself(warpzone_first); self; setself(self.warpzone_next))
WarpZone_InitStep_ClearTarget();
- for(self = warpzone_first; self; self = self.warpzone_next)
+ for(setself(warpzone_first); self; setself(self.warpzone_next))
WarpZone_InitStep_FindTarget();
- for(self = warpzone_camera_first; self; self = self.warpzone_next)
+ for(setself(warpzone_camera_first); self; setself(self.warpzone_next))
WarpZoneCamera_InitStep_FindTarget();
- for(self = warpzone_first; self; self = self.warpzone_next)
+ for(setself(warpzone_first); self; setself(self.warpzone_next))
WarpZone_InitStep_FinalizeTransform();
- self = e;
+ setself(this);
}
void WarpZone_Think()
-{
+{SELFPARAM();
if(self.warpzone_save_origin != self.origin
|| self.warpzone_save_angles != self.angles
|| self.warpzone_save_eorigin != self.enemy.origin
|| self.warpzone_save_eangles != self.enemy.angles)
{
- entity oldself;
- oldself = self;
WarpZone_InitStep_UpdateTransform();
- self = self.enemy;
+ setself(self.enemy);
WarpZone_InitStep_UpdateTransform();
- self = oldself;
+ setself(this);
WarpZone_InitStep_FinalizeTransform();
- self = self.enemy;
+ setself(self.enemy);
WarpZone_InitStep_FinalizeTransform();
- self = oldself;
+ setself(this);
self.warpzone_save_origin = self.origin;
self.warpzone_save_angles = self.angles;
self.warpzone_save_eorigin = self.enemy.origin;
}
void WarpZone_StartFrame()
-{
+{SELFPARAM();
entity e;
if(warpzone_initialized == 0)
{
warpzone_initialized = 1;
- e = self;
- for(self = warpzone_first; self; self = self.warpzone_next)
+ for(setself(warpzone_first); self; setself(self.warpzone_next))
WarpZone_InitStep_FindOriginTarget();
- for(self = warpzone_position_first; self; self = self.warpzone_next)
+ for(setself(warpzone_position_first); self; setself(self.warpzone_next))
WarpZonePosition_InitStep_FindTarget();
- for(self = warpzone_first; self; self = self.warpzone_next)
+ for(setself(warpzone_first); self; setself(self.warpzone_next))
WarpZone_InitStep_UpdateTransform();
- self = e;
+ setself(this);
WarpZones_Reconnect();
WarpZone_PostInitialize_Callback();
}
- entity oldself, oldother;
- oldself = self;
+ entity oldother;
oldother = other;
for(e = world; (e = nextent(e)); )
{
// warpzones
if(warpzone_warpzones_exist) {
- self = WarpZone_Find(e.origin + e.mins, e.origin + e.maxs);
+ setself(WarpZone_Find(e.origin + e.mins, e.origin + e.maxs));
if(self)
if(!WarpZoneLib_ExactTrigger_Touch())
if(WarpZone_PlaneDist(self, e.origin + e.view_ofs) <= 0)
WarpZone_Teleport(self, e, -1, 0); } // NOT triggering targets by this!
// teleporters
- self = Teleport_Find(e.origin + e.mins, e.origin + e.maxs);
+ setself(Teleport_Find(e.origin + e.mins, e.origin + e.maxs));
if(self)
if(!WarpZoneLib_ExactTrigger_Touch())
Simple_TeleportPlayer(self, other); // NOT triggering targets by this!
break;
}
}
- self = oldself;
+ setself(this);
other = oldother;
}
return 0;
}
void trigger_warpzone_reconnect_use()
-{
+{SELFPARAM();
entity e;
e = self;
// NOTE: this matches for target, not targetname, but of course
// targetname must be set too on the other entities
- for(self = warpzone_first; self; self = self.warpzone_next)
+ for(setself(warpzone_first); self; setself(self.warpzone_next))
self.warpzone_reconnecting = ((e.target == "" || self.target == e.target) && !((e.spawnflags & 1) && (visible_to_some_client(self) || visible_to_some_client(self.enemy))));
- for(self = warpzone_camera_first; self; self = self.warpzone_next)
+ for(setself(warpzone_camera_first); self; setself(self.warpzone_next))
self.warpzone_reconnecting = ((e.target == "" || self.target == e.target) && !((e.spawnflags & 1) && visible_to_some_client(self)));
- for(self = warpzone_first; self; self = self.warpzone_next)
+ for(setself(warpzone_first); self; setself(self.warpzone_next))
if(self.warpzone_reconnecting)
WarpZone_InitStep_ClearTarget();
- for(self = warpzone_first; self; self = self.warpzone_next)
+ for(setself(warpzone_first); self; setself(self.warpzone_next))
if(self.warpzone_reconnecting)
WarpZone_InitStep_FindTarget();
- for(self = warpzone_camera_first; self; self = self.warpzone_next)
+ for(setself(warpzone_camera_first); self; setself(self.warpzone_next))
if(self.warpzone_reconnecting)
WarpZoneCamera_InitStep_FindTarget();
- for(self = warpzone_first; self; self = self.warpzone_next)
+ for(setself(warpzone_first); self; setself(self.warpzone_next))
if(self.warpzone_reconnecting || self.enemy.warpzone_reconnecting)
WarpZone_InitStep_FinalizeTransform();
- self = e;
+ setself(e);
}
-void spawnfunc_trigger_warpzone_reconnect()
+spawnfunc(trigger_warpzone_reconnect)
{
self.use = trigger_warpzone_reconnect_use;
}
-void spawnfunc_target_warpzone_reconnect()
+spawnfunc(target_warpzone_reconnect)
{
- spawnfunc_trigger_warpzone_reconnect(); // both names make sense here :(
+ spawnfunc_trigger_warpzone_reconnect(this); // both names make sense here :(
}
void WarpZone_PlayerPhysics_FixVAngle(void)
-{
+{SELFPARAM();
#ifndef WARPZONE_DONT_FIX_VANGLE
if(IS_REAL_CLIENT(self))
if(self.v_angle.z <= 360) // if not already adjusted
#include "common.qh"
void WarpZoneLib_ExactTrigger_Init()
-{
+{SELFPARAM();
vector mi, ma;
if (self.movedir == '0 0 0')
if (self.angles != '0 0 0')
mi = self.mins;
ma = self.maxs;
precache_model(self.model);
- setmodel(self, self.model);
+ _setmodel(self, self.model);
// let mapper-set mins/maxs override the model's bounds if set
if(mi != '0 0 0' || ma != '0 0 0')
{
#!/usr/bin/env bash
cd ${0%[\\/]*}
-find . -name .git -prune -o -type f -print0 | \
+find . -name .git -prune -o -type f -print0 | \
xargs -0 sed -i \
`# strip trailing spaces` \
-e 's/[[:space:]]*$//' \
+// TODO: remove after 0.8.2. Default impulse commands for 0.8.1 servers
alias weapon_blaster "impulse 230"
alias weapon_shotgun "impulse 231"
alias weapon_machinegun "impulse 232"
alias weapon_seeker "impulse 247"
alias weapon_shockwave "impulse 248"
alias weapon_arc "impulse 249"
-
-// Backwards compatibility with 0.7.0
-alias weapon_laser "weapon_blaster"
-alias weapon_uzi "weapon_machinegun"
-alias weapon_grenadelauncher "weapon_mortar"
-alias weapon_nex "weapon_vortex"
-alias weapon_rocketlauncher "weapon_devastator"
-alias weapon_minstanex "weapon_vaporizer"