mirror of
https://github.com/Shpoike/Quakespasm.git
synced 2024-11-10 07:21:58 +00:00
quakespasm-spike-r5
This commit is contained in:
parent
04673200eb
commit
97bccd3be6
32 changed files with 8496 additions and 338 deletions
2037
e1m1_effects/maps/e1m1.ent
Executable file
2037
e1m1_effects/maps/e1m1.ent
Executable file
File diff suppressed because it is too large
Load diff
BIN
e1m1_effects/particles/flare.tga
Executable file
BIN
e1m1_effects/particles/flare.tga
Executable file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
316
e1m1_effects/particles/lib_effects_0.cfg
Executable file
316
e1m1_effects/particles/lib_effects_0.cfg
Executable file
|
@ -0,0 +1,316 @@
|
||||||
|
// License:
|
||||||
|
//
|
||||||
|
// So that single player releases are not overwriting each other's particle script files by using the same names ...
|
||||||
|
// And that everyone's maps play nice with each other ...
|
||||||
|
// ... and NOT stomping each others files by people using the same name.
|
||||||
|
//
|
||||||
|
// You agree to the following
|
||||||
|
//
|
||||||
|
// 1) You will include these comments at the top of your effects file to help make sure others do the same
|
||||||
|
// 2) You agree to rename this file to the following convention if you do a single player map release ...
|
||||||
|
//
|
||||||
|
// * lib_effects_0_<your gamedir>.cfg // For a gamedir release
|
||||||
|
// Example: lib_effects_0_travail.cfg // If your intended gamedir is "travail"
|
||||||
|
// Example: lib_effects_0_travail_mymap.cfg // If you are one to contributor releasing a map to a group pack
|
||||||
|
//
|
||||||
|
// * lib_effects_0_<your mapname>.cfg // For a map release that doesn't use a gamedir
|
||||||
|
// Example: lib_effects_0_mymap.cfg // If your map name is "mymap.bsp"
|
||||||
|
//
|
||||||
|
// Have fun!!! Enjoy!
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Lib Effects 0 - October 5, 2016
|
||||||
|
//
|
||||||
|
// The file contains specific effects.
|
||||||
|
// If your map is named "mymap.bsp", you should also have a "mymap.cfg" to indicate which models call the effects in this file.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
r_part waterpour
|
||||||
|
{
|
||||||
|
texture ball
|
||||||
|
type smoke
|
||||||
|
scale 12
|
||||||
|
scalefactor 1
|
||||||
|
count 300
|
||||||
|
velwrand 24 14 8
|
||||||
|
veladd 200
|
||||||
|
alpha 1
|
||||||
|
rgb 192 192 192
|
||||||
|
rgbrand 0 0 64
|
||||||
|
die 2
|
||||||
|
gravity 200
|
||||||
|
cliptype waterpoursplash
|
||||||
|
clipbounce 100
|
||||||
|
clipcount 5
|
||||||
|
}
|
||||||
|
|
||||||
|
r_part waterpoursplash
|
||||||
|
{
|
||||||
|
texture ball
|
||||||
|
type texturedspark
|
||||||
|
randomvel 50 50
|
||||||
|
count 1
|
||||||
|
scalefactor 1
|
||||||
|
alpha 0.1
|
||||||
|
rgb 255 255 255
|
||||||
|
die 0.4
|
||||||
|
scale 50
|
||||||
|
stretchfactor -2.5
|
||||||
|
veladd 1
|
||||||
|
scale 1
|
||||||
|
gravity 800
|
||||||
|
}
|
||||||
|
|
||||||
|
r_part waterdrip
|
||||||
|
{
|
||||||
|
texture ball
|
||||||
|
type texturedspark
|
||||||
|
scale 1
|
||||||
|
stretchfactor -1.5
|
||||||
|
scalefactor 1
|
||||||
|
count 2
|
||||||
|
spawnchance 0.25
|
||||||
|
orgbias 0 0 0
|
||||||
|
veladd 0
|
||||||
|
velbias 0 0 -200
|
||||||
|
alpha 1
|
||||||
|
rgb 192 192 192
|
||||||
|
rgbrand 0 0 64
|
||||||
|
die 3
|
||||||
|
cliptype waterdripsplash
|
||||||
|
clipbounce 100
|
||||||
|
clipcount 5
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
r_part waterdripsplash
|
||||||
|
{
|
||||||
|
texture ball
|
||||||
|
type texturedspark
|
||||||
|
randomvel 50 50
|
||||||
|
count 1
|
||||||
|
scalefactor 1
|
||||||
|
alpha 0.1
|
||||||
|
rgb 255 255 255
|
||||||
|
die 0.4
|
||||||
|
scale 50
|
||||||
|
stretchfactor -2.5
|
||||||
|
veladd 1
|
||||||
|
scale 1
|
||||||
|
gravity 800
|
||||||
|
}
|
||||||
|
|
||||||
|
r_part misty
|
||||||
|
{
|
||||||
|
type normal
|
||||||
|
count 80
|
||||||
|
scale 40
|
||||||
|
scalerand 15
|
||||||
|
scalefactor 1
|
||||||
|
scaledelta -15
|
||||||
|
alpha 0
|
||||||
|
die 4
|
||||||
|
randomvel 4 12
|
||||||
|
veladd 50
|
||||||
|
rgb 255 255 255
|
||||||
|
rgbdelta 0 -11 -5
|
||||||
|
blend alpha
|
||||||
|
spawnorg 20 5
|
||||||
|
spawnmode box
|
||||||
|
spawnvel 6 0
|
||||||
|
up 15
|
||||||
|
rampmode delta
|
||||||
|
ramp 0 0 0 -0.7
|
||||||
|
ramp 0 0 0 0.4
|
||||||
|
ramp 0 0 0 0.3
|
||||||
|
cliptype misty
|
||||||
|
clipbounce -1
|
||||||
|
clipcount 0
|
||||||
|
}
|
||||||
|
|
||||||
|
r_part smokey
|
||||||
|
{
|
||||||
|
type normal
|
||||||
|
count 64
|
||||||
|
scale 40
|
||||||
|
scalerand 15
|
||||||
|
scalefactor 1
|
||||||
|
scaledelta -15
|
||||||
|
alpha 0
|
||||||
|
die 3
|
||||||
|
velwrand 0 0 0
|
||||||
|
velbias 0 0 50
|
||||||
|
gravity 0
|
||||||
|
up 15
|
||||||
|
rgb 8 8 8
|
||||||
|
rgbrand 2 2 2
|
||||||
|
blend modulate
|
||||||
|
spawnorg 10 5
|
||||||
|
spawnmode box
|
||||||
|
spawnvel 6 0
|
||||||
|
rampmode delta
|
||||||
|
ramp 0 0 0 -1
|
||||||
|
ramp 0 0 0 0.4
|
||||||
|
ramp 0 0 0 0.3
|
||||||
|
cliptype smokey
|
||||||
|
clipbounce -1
|
||||||
|
clipcount 0
|
||||||
|
}
|
||||||
|
|
||||||
|
r_part mystical
|
||||||
|
{
|
||||||
|
texture "particles/flare"
|
||||||
|
count 40
|
||||||
|
scale 40
|
||||||
|
scalerand 15
|
||||||
|
scalefactor 1
|
||||||
|
scaledelta -15
|
||||||
|
alpha 0
|
||||||
|
die 2
|
||||||
|
randomvel 8 12
|
||||||
|
veladd 5 -10
|
||||||
|
rgb 255 255 255
|
||||||
|
blend modulate
|
||||||
|
spawnorg 10 5
|
||||||
|
spawnmode box
|
||||||
|
spawnvel 6 0
|
||||||
|
up 15
|
||||||
|
rampmode delta
|
||||||
|
ramp 0 0 0 -0.7 // Changes scale
|
||||||
|
ramp 0 0 0 0.4 // Changes scale
|
||||||
|
ramp 0 0 0 2400 // Changes scale
|
||||||
|
}
|
||||||
|
|
||||||
|
r_part sparkcascadelite
|
||||||
|
{
|
||||||
|
type spark
|
||||||
|
count 25
|
||||||
|
spawnchance 0.10
|
||||||
|
scale 40
|
||||||
|
scalefactor 1
|
||||||
|
spawnmode box
|
||||||
|
spawnorg 0 0
|
||||||
|
orgbias 0 0 0
|
||||||
|
velwrand 70 70 8
|
||||||
|
gravity 400
|
||||||
|
die 1
|
||||||
|
cliptype sparkcascadelite
|
||||||
|
clipbounce -1
|
||||||
|
clipcount 10
|
||||||
|
alpha 1
|
||||||
|
blend add
|
||||||
|
rgb 255 128 76
|
||||||
|
rampmode delta
|
||||||
|
ramp 0 0 0 1
|
||||||
|
}
|
||||||
|
|
||||||
|
r_part sparkcascadeheavy
|
||||||
|
{
|
||||||
|
type spark
|
||||||
|
count 500
|
||||||
|
spawnchance 0.10
|
||||||
|
scale 40
|
||||||
|
scalefactor 1
|
||||||
|
spawnmode box
|
||||||
|
spawnorg 0 0
|
||||||
|
orgbias 0 0 0
|
||||||
|
randomvel 140 0
|
||||||
|
gravity 400
|
||||||
|
die 1
|
||||||
|
cliptype sparkcascadeheavy
|
||||||
|
clipbounce -1
|
||||||
|
clipcount 10
|
||||||
|
alpha 1
|
||||||
|
blend add
|
||||||
|
rgb 255 128 76
|
||||||
|
rampmode delta
|
||||||
|
ramp 0 0 0 1
|
||||||
|
}
|
||||||
|
|
||||||
|
r_part liquidfog
|
||||||
|
{
|
||||||
|
type normal
|
||||||
|
scale 80
|
||||||
|
scalerand 20
|
||||||
|
up -6
|
||||||
|
count 2
|
||||||
|
alpha 0
|
||||||
|
blend add
|
||||||
|
rgb 32 255 32
|
||||||
|
rgbrand 8 8 8
|
||||||
|
die 3.5
|
||||||
|
veladd 0
|
||||||
|
randomvel 11
|
||||||
|
gravity -15
|
||||||
|
rgb 32 32 32
|
||||||
|
rgbrand 2 2 2
|
||||||
|
spawnmode ball
|
||||||
|
cliptype liquidfog
|
||||||
|
clipbounce -1
|
||||||
|
clipcount 0
|
||||||
|
rampmode delta
|
||||||
|
ramp 0 0 0 -0.25
|
||||||
|
ramp 0 0 0 0.125
|
||||||
|
ramp 0 0 0 0.125
|
||||||
|
}
|
||||||
|
|
||||||
|
//snow from sky surfaces is often within a box
|
||||||
|
//this means we don't want the snow to ever settle.
|
||||||
|
//we also have no volume, so make the snow fall a little further.
|
||||||
|
r_part skysnow
|
||||||
|
{
|
||||||
|
texture ball
|
||||||
|
scalefactor 1
|
||||||
|
rainfrequency 2
|
||||||
|
count 1
|
||||||
|
alpha 1
|
||||||
|
rgb 255 255 255
|
||||||
|
die 8
|
||||||
|
veladd 0
|
||||||
|
velbias 0 0 -100
|
||||||
|
scale 5
|
||||||
|
flurry 40
|
||||||
|
gravity 400
|
||||||
|
friction 5
|
||||||
|
cliptype skysnow
|
||||||
|
clipbounce 0
|
||||||
|
}
|
||||||
|
|
||||||
|
r_part skyrain
|
||||||
|
{
|
||||||
|
texture ball
|
||||||
|
type texturedspark
|
||||||
|
scale 1
|
||||||
|
stretchfactor -40
|
||||||
|
scalefactor 1
|
||||||
|
rainfrequency 10
|
||||||
|
count 1
|
||||||
|
veladd 0
|
||||||
|
velbias -200 -200 -2000
|
||||||
|
alpha 0.1
|
||||||
|
rgb 255 255 255
|
||||||
|
die 2
|
||||||
|
cliptype skyrainsplash
|
||||||
|
clipbounce 100
|
||||||
|
clipcount 5
|
||||||
|
inwater skyrainsplash
|
||||||
|
}
|
||||||
|
|
||||||
|
r_part skyrainsplash
|
||||||
|
{
|
||||||
|
randomvel 50 50
|
||||||
|
count 1
|
||||||
|
texture ball
|
||||||
|
scalefactor 1
|
||||||
|
alpha 0.1
|
||||||
|
rgb 255 255 255
|
||||||
|
die 0.4
|
||||||
|
scale 50
|
||||||
|
stretchfactor -2.5
|
||||||
|
veladd 1
|
||||||
|
scale 1
|
||||||
|
type texturedspark
|
||||||
|
gravity 800
|
||||||
|
}
|
123
e1m1_effects/particles/railstuff.cfg
Executable file
123
e1m1_effects/particles/railstuff.cfg
Executable file
|
@ -0,0 +1,123 @@
|
||||||
|
r_part railtrail
|
||||||
|
{
|
||||||
|
//blue spiral, mimicing quake2
|
||||||
|
texture "classicparticle"
|
||||||
|
tcoords 0 0 16 16 32
|
||||||
|
scale 0.5
|
||||||
|
alpha 1
|
||||||
|
scalefactor 0.8
|
||||||
|
step 1
|
||||||
|
spawnmode spiral 64
|
||||||
|
spawnorg 3
|
||||||
|
spawnvel 6
|
||||||
|
die 1 1.2
|
||||||
|
// colorindex 116 7 //this would be quake2's palette, which we can't use, so we have to make it up
|
||||||
|
rgb 1 31 42
|
||||||
|
rgbrand 27 52 69
|
||||||
|
rgbrandsync 1
|
||||||
|
}
|
||||||
|
r_part +railtrail
|
||||||
|
{
|
||||||
|
//grey filler, mimicing quake2
|
||||||
|
texture "classicparticle"
|
||||||
|
tcoords 0 0 16 16 32
|
||||||
|
scale 0.5
|
||||||
|
alpha 1
|
||||||
|
scalefactor 0.8
|
||||||
|
step 0.75
|
||||||
|
spawnorg 3
|
||||||
|
spawnvel 3
|
||||||
|
die 0.6 0.8
|
||||||
|
colorindex 0 15
|
||||||
|
}
|
||||||
|
|
||||||
|
//circley effect when the slugs impacts something
|
||||||
|
r_part railslugimpact
|
||||||
|
{
|
||||||
|
type normal
|
||||||
|
count 120
|
||||||
|
die 1
|
||||||
|
scale 5
|
||||||
|
alpha 1
|
||||||
|
spawnmode circle
|
||||||
|
spawnvel 30 0
|
||||||
|
spawnorg 1 0
|
||||||
|
rgb 28 83 111
|
||||||
|
friction 1.5
|
||||||
|
}
|
||||||
|
|
||||||
|
//invisible particle that leaves our trail
|
||||||
|
r_part railslug
|
||||||
|
{
|
||||||
|
rainfrequency 0.2
|
||||||
|
|
||||||
|
count 5
|
||||||
|
scale 0
|
||||||
|
scalefactor 1
|
||||||
|
spawnmode box
|
||||||
|
spawnorg 0 0
|
||||||
|
orgbias 0 0 0
|
||||||
|
randomvel 300
|
||||||
|
veladd 600
|
||||||
|
// gravity 800
|
||||||
|
die 3
|
||||||
|
alpha 0
|
||||||
|
blend add
|
||||||
|
|
||||||
|
bounce 1.5
|
||||||
|
clipcount 120
|
||||||
|
cliptype railslugimpact
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//give it a trail
|
||||||
|
emit railtrail
|
||||||
|
emitinterval -1
|
||||||
|
|
||||||
|
//sound
|
||||||
|
sound "enforcer/enfire.wav" 1 1 0 0
|
||||||
|
//light
|
||||||
|
lightrgb .25 .5 4
|
||||||
|
lightradius 300
|
||||||
|
lightradiusfade 600
|
||||||
|
lighttime 0.333
|
||||||
|
// lightcorona 1 0.25
|
||||||
|
// lightshadows 0
|
||||||
|
// lightcubemap 0 //cubemaps/%i (not supported by quakespasm)
|
||||||
|
// lightscales 0 1 1 //ambient, diffuse, specular (not supported by quakespasm)
|
||||||
|
}
|
||||||
|
|
||||||
|
//small proxy effect that spawns our real effect only periodically.
|
||||||
|
//(thereby avoiding a sound every single frame)
|
||||||
|
r_part sparkcascadeheavy
|
||||||
|
{
|
||||||
|
count 2
|
||||||
|
spawnchance 0.20
|
||||||
|
scale 10
|
||||||
|
die 0
|
||||||
|
alpha 1
|
||||||
|
rgb 255 255 255
|
||||||
|
veladd 1
|
||||||
|
|
||||||
|
emit railslug
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//example if you want to spew particles from certain models, in this case grunts. unfortunately it includes corpses.
|
||||||
|
//r_part modelspew
|
||||||
|
//{
|
||||||
|
// type normal
|
||||||
|
// count 800
|
||||||
|
// scale 10
|
||||||
|
// scalefactor 1
|
||||||
|
// die 1
|
||||||
|
// alpha .5
|
||||||
|
// rgb 255 255 128
|
||||||
|
// veladd 300
|
||||||
|
// bounce 1.5
|
||||||
|
// randomvel 100 100
|
||||||
|
// gravity 800
|
||||||
|
//}
|
||||||
|
|
||||||
|
//r_effect "progs/soldier.mdl" modelspew forwards
|
||||||
|
|
915
high.cfg
Executable file
915
high.cfg
Executable file
|
@ -0,0 +1,915 @@
|
||||||
|
///////////////////////////////
|
||||||
|
//rain
|
||||||
|
r_part te_rain
|
||||||
|
{
|
||||||
|
texture ball; scalefactor 1; count 1; alpha 0.4; rgb 255 255 255; die 2; veladd 2; scale 2; type texturedspark
|
||||||
|
cliptype rainsplash
|
||||||
|
clipbounce 1
|
||||||
|
clipcount 5
|
||||||
|
}
|
||||||
|
|
||||||
|
r_part rainsplash
|
||||||
|
{
|
||||||
|
randomvel 50 50
|
||||||
|
count 1;
|
||||||
|
texture ball; scalefactor 1; alpha 0.1; rgb 255 255 255; die 0.4; scale 50;
|
||||||
|
stretchfactor 4
|
||||||
|
veladd 50; scale 1; type texturedspark
|
||||||
|
gravity 400
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
//rocket trail
|
||||||
|
|
||||||
|
// flame trail
|
||||||
|
r_part tr_rocket
|
||||||
|
{
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 97 97 191 191 256
|
||||||
|
step 1
|
||||||
|
scale 12
|
||||||
|
alpha 0.4
|
||||||
|
die 0.5
|
||||||
|
rgb 255 127 100
|
||||||
|
rgbdelta -14 -300 -300
|
||||||
|
blend add
|
||||||
|
scalefactor 1
|
||||||
|
scaledelta -15
|
||||||
|
}
|
||||||
|
|
||||||
|
// smoke puffs
|
||||||
|
r_part +tr_rocket
|
||||||
|
{
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 97 97 191 191 256
|
||||||
|
step 5
|
||||||
|
scale 30
|
||||||
|
alpha 0.2
|
||||||
|
die 0.75
|
||||||
|
//diesubrand 10.25
|
||||||
|
randomvel 0.2
|
||||||
|
rgb 5 5 5
|
||||||
|
//rgbdelta -230 -45 -9
|
||||||
|
gravity -15
|
||||||
|
scalefactor 1
|
||||||
|
scaledelta 20
|
||||||
|
spawnvel 5
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// burst sparks
|
||||||
|
r_part +tr_rocket
|
||||||
|
{
|
||||||
|
type texturedspark
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 1 65 31 95 256 8 32
|
||||||
|
count 1
|
||||||
|
scale 2
|
||||||
|
scalefactor 1
|
||||||
|
scaledelta -15
|
||||||
|
alpha 0.2
|
||||||
|
die 0.25
|
||||||
|
rgb 255 128 0
|
||||||
|
blend add
|
||||||
|
spawnmode ball
|
||||||
|
spawnorg 1
|
||||||
|
spawnvel 50
|
||||||
|
veladd 500
|
||||||
|
friction 0.01
|
||||||
|
gravity 100
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////
|
||||||
|
//alternate rocket trail, which is used by a handful of qw players.
|
||||||
|
//r_part tr_altrocket
|
||||||
|
//{
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////
|
||||||
|
//grenade trail
|
||||||
|
|
||||||
|
r_part tr_grenade
|
||||||
|
{
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 97 97 191 191 256
|
||||||
|
step 6
|
||||||
|
scale 32
|
||||||
|
scaledelta 12
|
||||||
|
alpha 0.3
|
||||||
|
die 1.25
|
||||||
|
randomvel 2
|
||||||
|
veladd 15
|
||||||
|
rgb 75 75 75
|
||||||
|
//rgb 255 50 50
|
||||||
|
//rgbdelta -255 -75 -75
|
||||||
|
gravity -25
|
||||||
|
scalefactor 1
|
||||||
|
blend modulate
|
||||||
|
}
|
||||||
|
r_part +tr_grenade
|
||||||
|
{
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 97 97 191 191 256
|
||||||
|
scale 1
|
||||||
|
scaledelta 0.25
|
||||||
|
alpha 0.2
|
||||||
|
step 4
|
||||||
|
die 0.8
|
||||||
|
randomvel 0
|
||||||
|
rgb 255 150 150
|
||||||
|
rgbdelta 0 -150 -150
|
||||||
|
type beam
|
||||||
|
blend add
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////
|
||||||
|
//shotgun impacts
|
||||||
|
r_part gunshotsmoke
|
||||||
|
{
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 1 65 31 95 256 8 32
|
||||||
|
count 3
|
||||||
|
scale 25
|
||||||
|
scalefactor 1
|
||||||
|
die 0.8
|
||||||
|
alpha 0.12
|
||||||
|
rgb 32 32 32
|
||||||
|
blend add
|
||||||
|
spawnmode ball
|
||||||
|
spawnorg 2
|
||||||
|
spawnvel 20
|
||||||
|
veladd -20
|
||||||
|
}
|
||||||
|
r_part te_gunshot
|
||||||
|
{
|
||||||
|
type texturedspark
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 1 65 31 95 256 8 32
|
||||||
|
count 3
|
||||||
|
scale 2
|
||||||
|
scalefactor 1
|
||||||
|
alpha 0.5
|
||||||
|
die 0.8
|
||||||
|
rgb 255 128 0
|
||||||
|
blend add
|
||||||
|
spawnmode ball
|
||||||
|
spawnorg 1
|
||||||
|
spawnvel 100
|
||||||
|
veladd -80
|
||||||
|
friction 0.3
|
||||||
|
gravity 400
|
||||||
|
assoc gunshotsmoke
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////
|
||||||
|
//nail impacts
|
||||||
|
|
||||||
|
r_part te_spike
|
||||||
|
{
|
||||||
|
type sparkfan
|
||||||
|
count 10
|
||||||
|
scale 1
|
||||||
|
scalefactor 1
|
||||||
|
alpha 0.5
|
||||||
|
die 0.2
|
||||||
|
rgb 255 128 0
|
||||||
|
blend add
|
||||||
|
spawnmode ball
|
||||||
|
spawnorg 12
|
||||||
|
spawnvel 300
|
||||||
|
}
|
||||||
|
r_part +te_spike
|
||||||
|
{
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 1 97 95 191 256
|
||||||
|
count 1
|
||||||
|
scale 1
|
||||||
|
scalefactor 1
|
||||||
|
scaledelta 190
|
||||||
|
die 0.1
|
||||||
|
alpha 0.6
|
||||||
|
rgb 255 128 0
|
||||||
|
blend add
|
||||||
|
assoc gunshotsmoke
|
||||||
|
}
|
||||||
|
|
||||||
|
r_part te_superspike
|
||||||
|
{
|
||||||
|
type sparkfan
|
||||||
|
count 20
|
||||||
|
scale 1
|
||||||
|
scalefactor 1
|
||||||
|
alpha 0.5
|
||||||
|
die 0.2
|
||||||
|
rgb 255 128 0
|
||||||
|
blend add
|
||||||
|
spawnmode ball
|
||||||
|
spawnorg 12
|
||||||
|
spawnvel 300
|
||||||
|
}
|
||||||
|
r_part +te_superspike
|
||||||
|
{
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 1 97 95 191 256
|
||||||
|
count 1
|
||||||
|
scale 1
|
||||||
|
scalefactor 1
|
||||||
|
scaledelta 190
|
||||||
|
die 0.1
|
||||||
|
alpha 0.6
|
||||||
|
rgb 255 128 0
|
||||||
|
blend add
|
||||||
|
assoc gunshotsmoke
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////
|
||||||
|
//explosion
|
||||||
|
|
||||||
|
//red bit
|
||||||
|
r_part te_explosion
|
||||||
|
{
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 97 97 191 191 256
|
||||||
|
count 1
|
||||||
|
scale 500
|
||||||
|
alpha 0.4
|
||||||
|
die 0.2
|
||||||
|
rgb 255 127 100
|
||||||
|
rgbdelta -14 -300 -300
|
||||||
|
blend add
|
||||||
|
scalefactor 1
|
||||||
|
scaledelta -15
|
||||||
|
randomvel 0
|
||||||
|
// lightradius 350
|
||||||
|
// lightrgb 1.4 1.2 1.05
|
||||||
|
// lighttime 0.5
|
||||||
|
// lightradiusfade 350
|
||||||
|
// lightrgbfade 2 2 2
|
||||||
|
}
|
||||||
|
//smoke
|
||||||
|
r_part +te_explosion
|
||||||
|
{
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 97 97 191 191 256
|
||||||
|
count 7
|
||||||
|
scale 300
|
||||||
|
alpha 0.2
|
||||||
|
die 0.8
|
||||||
|
//diesubrand 10.25
|
||||||
|
randomvel 100
|
||||||
|
rgb 5 5 5
|
||||||
|
//rgbdelta -230 -45 -9
|
||||||
|
gravity -15
|
||||||
|
scalefactor 1
|
||||||
|
scaledelta 40
|
||||||
|
spawnvel 5
|
||||||
|
}
|
||||||
|
// burst sparks
|
||||||
|
r_part +te_explosion
|
||||||
|
{
|
||||||
|
type texturedspark
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 1 65 31 95 256 8 32
|
||||||
|
count 100
|
||||||
|
scale 5
|
||||||
|
scalefactor 1
|
||||||
|
scaledelta -15
|
||||||
|
alpha 0.2
|
||||||
|
die 0.5
|
||||||
|
rgb 255 128 0
|
||||||
|
blend add
|
||||||
|
spawnmode ball
|
||||||
|
spawnorg 1
|
||||||
|
randomvel 1000
|
||||||
|
friction 0.01
|
||||||
|
gravity 100
|
||||||
|
stretchfactor -80
|
||||||
|
}
|
||||||
|
|
||||||
|
//hide lights in explosions.
|
||||||
|
//r_explosionlight 0
|
||||||
|
|
||||||
|
//hide the explosion sprite in qw
|
||||||
|
cl_expsprite 0
|
||||||
|
//hide it in nq - WARNING: some mods use this sprite as a flame thrower.
|
||||||
|
//r_effect "progs/s_explod.spr" hidden 1
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////
|
||||||
|
//rogue te_explosion2 effect
|
||||||
|
//note: if not otherwise defined, te_explosion2_BASE_RAND maps to this, and specifies the palette colours.
|
||||||
|
r_part te_explosion2
|
||||||
|
{
|
||||||
|
type texturedspark
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 1 65 31 95 256 8 32
|
||||||
|
count 256
|
||||||
|
scale 5
|
||||||
|
scalefactor 1
|
||||||
|
scaledelta -15
|
||||||
|
alpha 0.2
|
||||||
|
die 0.5
|
||||||
|
blend add
|
||||||
|
spawnmode ball
|
||||||
|
spawnorg 1
|
||||||
|
randomvel 1000
|
||||||
|
friction 0.01
|
||||||
|
gravity 100
|
||||||
|
stretchfactor -80
|
||||||
|
}
|
||||||
|
//dragon fireball
|
||||||
|
//r_part te_explosion2_228_5
|
||||||
|
|
||||||
|
//rogue multigrenade sub explosion
|
||||||
|
//also triggered from a shielded rogue player touching another player (and doing some damage)
|
||||||
|
//also used during the ending.
|
||||||
|
//red particles
|
||||||
|
//r_part te_explosion2_230_5
|
||||||
|
|
||||||
|
//rogue plasma explosion
|
||||||
|
//also rogue timemachine explosion
|
||||||
|
//white particles splaying outwards
|
||||||
|
//r_part te_explosion2_244_3
|
||||||
|
|
||||||
|
//////////////////////////////////////////
|
||||||
|
//for when a spawn dies.
|
||||||
|
//also used by TF for emp explosions.
|
||||||
|
r_part te_tarexplosion
|
||||||
|
{
|
||||||
|
type texturedspark
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 1 65 31 95 256 8 32
|
||||||
|
count 128
|
||||||
|
scale 5
|
||||||
|
scalefactor 1
|
||||||
|
scaledelta -15
|
||||||
|
rgb 0 0 17
|
||||||
|
alpha 0.5
|
||||||
|
die 0.5
|
||||||
|
spawnmode ball
|
||||||
|
spawnorg 1
|
||||||
|
randomvel 500
|
||||||
|
friction 0.01
|
||||||
|
gravity 100
|
||||||
|
stretchfactor -80
|
||||||
|
}
|
||||||
|
r_part +te_tarexplosion
|
||||||
|
{
|
||||||
|
type texturedspark
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 1 65 31 95 256 8 32
|
||||||
|
count 256
|
||||||
|
scale 5
|
||||||
|
scalefactor 1
|
||||||
|
scaledelta -15
|
||||||
|
rgb 83 67 115
|
||||||
|
alpha 0.3
|
||||||
|
die 0.5
|
||||||
|
blend add
|
||||||
|
spawnmode ball
|
||||||
|
spawnorg 1
|
||||||
|
randomvel 500
|
||||||
|
friction 0.01
|
||||||
|
gravity 100
|
||||||
|
stretchfactor -80
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////
|
||||||
|
//cthon falling into lava.
|
||||||
|
//often also used for TF gas grenades.
|
||||||
|
r_part te_lavasplash
|
||||||
|
{
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 129 1 191 63 256
|
||||||
|
count 654
|
||||||
|
scale 15
|
||||||
|
alpha 0.7
|
||||||
|
die 4
|
||||||
|
randomvel 64
|
||||||
|
rgb 255 128 128
|
||||||
|
gravity 50
|
||||||
|
blend add
|
||||||
|
spawnorg 192 64
|
||||||
|
up 48
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////
|
||||||
|
//FIXME: what if we don't have glsl support?
|
||||||
|
r_part te_teleport
|
||||||
|
{
|
||||||
|
scale 250
|
||||||
|
count 1
|
||||||
|
alpha 0.3
|
||||||
|
die 0.5
|
||||||
|
scalefactor 1
|
||||||
|
rotationstart 45
|
||||||
|
rotationspeed 0
|
||||||
|
|
||||||
|
shader
|
||||||
|
{
|
||||||
|
surfaceparm noshadows
|
||||||
|
surfaceparm nodlight
|
||||||
|
glslprogram
|
||||||
|
{
|
||||||
|
varying vec2 tcoord;
|
||||||
|
varying vec4 scoord;
|
||||||
|
varying float alph;
|
||||||
|
#ifdef VERTEX_SHADER
|
||||||
|
attribute vec2 v_texcoord;
|
||||||
|
attribute vec4 v_colour;
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
scoord = ftetransform();
|
||||||
|
tcoord = (v_texcoord.st - 0.5)*2.0;
|
||||||
|
alph = v_colour.a;
|
||||||
|
gl_Position = scoord;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef FRAGMENT_SHADER
|
||||||
|
uniform sampler2D s_t0;
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
vec2 nst;
|
||||||
|
float f;
|
||||||
|
nst = scoord.xy / scoord.w;
|
||||||
|
nst = (1.0 + nst)/2.0;
|
||||||
|
f = 1.0 - length(tcoord);
|
||||||
|
// f = 1.0 - tcoord*tcoord;
|
||||||
|
if (f < 0.0) discard;
|
||||||
|
f *= alph;
|
||||||
|
gl_FragColor = texture2D(s_t0, nst - tcoord*f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
{
|
||||||
|
map $currentrender
|
||||||
|
blendfunc blend
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////
|
||||||
|
//hellknight
|
||||||
|
r_part tr_knightspike
|
||||||
|
{
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 1 97 95 191 256
|
||||||
|
scale 15
|
||||||
|
step 1
|
||||||
|
alpha 0.6
|
||||||
|
die 0.2
|
||||||
|
rgb 192 96 48
|
||||||
|
veladd 0
|
||||||
|
randomvel 2
|
||||||
|
friction 4
|
||||||
|
scalefactor 0.825
|
||||||
|
blend add
|
||||||
|
spawnmode spiral
|
||||||
|
spawnvel -50
|
||||||
|
lighttime 0
|
||||||
|
lightshadows 0
|
||||||
|
lightradius 150
|
||||||
|
lightrgb 0.75 0.37 0.18
|
||||||
|
}
|
||||||
|
|
||||||
|
r_part te_knightspike
|
||||||
|
{
|
||||||
|
type sparkfan
|
||||||
|
count 200
|
||||||
|
scale 3
|
||||||
|
scalefactor 1
|
||||||
|
alpha 0.5
|
||||||
|
die 0.5
|
||||||
|
rgb 192 96 48
|
||||||
|
blend add
|
||||||
|
spawnmode ball
|
||||||
|
spawnorg 12
|
||||||
|
spawnvel 100
|
||||||
|
stretchfactor 10
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
//vore missiles
|
||||||
|
r_part tr_vorespike
|
||||||
|
{
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 1 97 95 191 256
|
||||||
|
scale 15
|
||||||
|
step 1
|
||||||
|
alpha 0.6
|
||||||
|
die 0.5
|
||||||
|
rgb 192 96 192
|
||||||
|
veladd 15
|
||||||
|
spawnmode spiral
|
||||||
|
spawnvel 50
|
||||||
|
randomvel 0
|
||||||
|
friction 0
|
||||||
|
scalefactor 1
|
||||||
|
blend add
|
||||||
|
lighttime 0
|
||||||
|
lightshadows 0
|
||||||
|
lightradius 150
|
||||||
|
lightrgb 0.75 0.37 0.75
|
||||||
|
}
|
||||||
|
//rygel's pack sucks
|
||||||
|
r_trail "progs/v_spike.mdl" tr_vorespike
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
//enforcer laser effect
|
||||||
|
r_part tr_enforcerlaser
|
||||||
|
{
|
||||||
|
type texturedspark
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 1 97 95 191 256
|
||||||
|
scale 15
|
||||||
|
step 4
|
||||||
|
alpha 0.3
|
||||||
|
die 0.5
|
||||||
|
rgb 255 69 0
|
||||||
|
veladd -32
|
||||||
|
spawnmode spiral
|
||||||
|
spawnvel 16
|
||||||
|
randomvel 32
|
||||||
|
friction 0
|
||||||
|
scalefactor 1
|
||||||
|
blend add
|
||||||
|
lighttime 0.2
|
||||||
|
lightshadows 0
|
||||||
|
lightradius 150
|
||||||
|
lightrgb 1 0.27 0
|
||||||
|
lightrgbfade 5 1 0
|
||||||
|
lightcorona 2 0.25
|
||||||
|
}
|
||||||
|
r_trail "progs/laser.mdl" tr_enforcerlaser
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
//rogue wrath enemy's projectiles
|
||||||
|
r_part tr_wrathball
|
||||||
|
{
|
||||||
|
type texturedspark
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 1 97 95 191 256
|
||||||
|
scale 15
|
||||||
|
step 4
|
||||||
|
alpha 0.3
|
||||||
|
die 0.5
|
||||||
|
rgb 255 0 0
|
||||||
|
veladd -32
|
||||||
|
spawnmode spiral
|
||||||
|
spawnvel 16
|
||||||
|
randomvel 32
|
||||||
|
friction 0
|
||||||
|
scalefactor 1
|
||||||
|
blend add
|
||||||
|
lighttime 0.2
|
||||||
|
lightshadows 0
|
||||||
|
lightradius 150
|
||||||
|
lightrgb 1 0.27 0
|
||||||
|
lightrgbfade 5 1 0
|
||||||
|
lightcorona 2 0.5
|
||||||
|
}
|
||||||
|
r_trail "progs/w_ball.mdl" tr_wrathball
|
||||||
|
|
||||||
|
//wrath death
|
||||||
|
//grey particles
|
||||||
|
//no difference from the fallback except for the blend mode. this should ensure that we are not quite so invisible.
|
||||||
|
r_part te_explosion2_0_4
|
||||||
|
{
|
||||||
|
type texturedspark
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 1 65 31 95 256 8 32
|
||||||
|
count 256
|
||||||
|
scale 5
|
||||||
|
scalefactor 1
|
||||||
|
scaledelta -15
|
||||||
|
alpha 0.2
|
||||||
|
die 0.5
|
||||||
|
spawnmode ball
|
||||||
|
spawnorg 1
|
||||||
|
randomvel 1000
|
||||||
|
friction 0.01
|
||||||
|
gravity 100
|
||||||
|
stretchfactor -80
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
//rogue lavaspikes
|
||||||
|
r_part tr_lavaspike
|
||||||
|
{
|
||||||
|
type spark
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 1 97 95 191 256
|
||||||
|
scale 15
|
||||||
|
step 4
|
||||||
|
alpha 0.3
|
||||||
|
die 0.5
|
||||||
|
rgb 255 0 0
|
||||||
|
veladd -32
|
||||||
|
spawnmode spiral
|
||||||
|
spawnvel 16
|
||||||
|
randomvel 32
|
||||||
|
friction 0
|
||||||
|
scalefactor 1
|
||||||
|
blend add
|
||||||
|
}
|
||||||
|
r_trail "progs/lspike.mdl" tr_lavaspike
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
//rogue plasma gun
|
||||||
|
r_part tr_plasma
|
||||||
|
{
|
||||||
|
type texturedspark
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 1 97 95 191 256
|
||||||
|
scale 15
|
||||||
|
step 4
|
||||||
|
alpha 0.3
|
||||||
|
die 0.25
|
||||||
|
rgb 128 128 255
|
||||||
|
veladd -32
|
||||||
|
spawnmode spiral
|
||||||
|
spawnvel 16
|
||||||
|
randomvel 32
|
||||||
|
friction 0
|
||||||
|
scalefactor 1
|
||||||
|
blend add
|
||||||
|
lighttime 0.2
|
||||||
|
lightshadows 0
|
||||||
|
lightradius 150
|
||||||
|
lightrgb 1 1 2
|
||||||
|
lightrgbfade 5 1 0.5
|
||||||
|
lightcorona 2 0.5
|
||||||
|
}
|
||||||
|
r_trail "progs/plasma.mdl" tr_plasma
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
//scrag missiles.
|
||||||
|
r_part tr_wizspike
|
||||||
|
{
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 1 97 95 191 256
|
||||||
|
scale 15
|
||||||
|
step 4
|
||||||
|
alpha 0.6
|
||||||
|
die 0.2
|
||||||
|
rgb 25 200 25
|
||||||
|
veladd 0
|
||||||
|
randomvel 2
|
||||||
|
friction 4
|
||||||
|
scalefactor 0.825
|
||||||
|
spawnmode spiral
|
||||||
|
spawnvel 25
|
||||||
|
blend add
|
||||||
|
lighttime 2
|
||||||
|
lightradiusfade 75
|
||||||
|
lightshadows 0
|
||||||
|
lightradius 150
|
||||||
|
lightrgb 0.1 0.7 0.1
|
||||||
|
}
|
||||||
|
|
||||||
|
r_part tr_wizspike2
|
||||||
|
{
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 1 97 95 191 256
|
||||||
|
scale 4
|
||||||
|
step 1
|
||||||
|
alpha 0.6
|
||||||
|
die 0.2
|
||||||
|
rgb 25 200 25
|
||||||
|
veladd 64
|
||||||
|
randomvel 64
|
||||||
|
friction 4
|
||||||
|
scalefactor 0.825
|
||||||
|
spawnmode spiral
|
||||||
|
spawnvel 25
|
||||||
|
blend add
|
||||||
|
}
|
||||||
|
//scrag impact
|
||||||
|
r_part te_wizspike
|
||||||
|
{
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 1 97 95 191 256
|
||||||
|
scale 15
|
||||||
|
alpha 0.6
|
||||||
|
rgb 25 200 25
|
||||||
|
friction 0
|
||||||
|
scalefactor 0.825
|
||||||
|
blend add
|
||||||
|
count 5
|
||||||
|
veladd -256
|
||||||
|
randomvel 256
|
||||||
|
die 1
|
||||||
|
diesubrand 0.5
|
||||||
|
gravity 800
|
||||||
|
emit tr_wizspike2
|
||||||
|
emitinterval -1
|
||||||
|
bounce 1.5
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
//shambler stuff
|
||||||
|
r_part shambercharging
|
||||||
|
{
|
||||||
|
spawnmode ball
|
||||||
|
count 200
|
||||||
|
spawnorg 128
|
||||||
|
spawnvel -256
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 1 1 63 63 256 2 64
|
||||||
|
scale 4
|
||||||
|
alpha 1
|
||||||
|
die 0.5
|
||||||
|
orgadd -64
|
||||||
|
rotationspeed 90
|
||||||
|
rotationstart 0 360
|
||||||
|
rgb 100 100 250
|
||||||
|
rgbrand 0 0 0
|
||||||
|
gravity 0
|
||||||
|
scalefactor 0.4
|
||||||
|
lighttime 0
|
||||||
|
lightshadows 0
|
||||||
|
lightradius 400
|
||||||
|
lightrgb 2 2 2
|
||||||
|
}
|
||||||
|
r_effect progs/s_light.mdl shambercharging 0
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
//blood effects
|
||||||
|
r_part te_blood
|
||||||
|
{
|
||||||
|
texture fte_bloodparticle
|
||||||
|
blend subtract
|
||||||
|
count 1
|
||||||
|
scale 32
|
||||||
|
alpha 0
|
||||||
|
die 1
|
||||||
|
randomvel 64
|
||||||
|
veladd 10
|
||||||
|
rotationspeed 90
|
||||||
|
rotationstart 0 360
|
||||||
|
rgb 32 64 64
|
||||||
|
rgbdelta -32 -64 -64
|
||||||
|
gravity 200
|
||||||
|
scalefactor 0.8
|
||||||
|
}
|
||||||
|
|
||||||
|
r_part high.pe_73
|
||||||
|
{
|
||||||
|
texture fte_bloodparticle
|
||||||
|
blend subtract
|
||||||
|
count 1
|
||||||
|
scale 32
|
||||||
|
alpha 0
|
||||||
|
die 1
|
||||||
|
randomvel 64
|
||||||
|
veladd 10
|
||||||
|
rotationspeed 90
|
||||||
|
rotationstart 0 360
|
||||||
|
rgb 32 64 64
|
||||||
|
rgbdelta -32 -64 -64
|
||||||
|
gravity 200
|
||||||
|
scalefactor 0.8
|
||||||
|
}
|
||||||
|
|
||||||
|
r_part te_lightningblood
|
||||||
|
{
|
||||||
|
texture fte_bloodparticle
|
||||||
|
blend subtract
|
||||||
|
count 1
|
||||||
|
scale 32
|
||||||
|
alpha 0
|
||||||
|
die 1
|
||||||
|
randomvel 32
|
||||||
|
veladd 5
|
||||||
|
rotationspeed 90
|
||||||
|
rotationstart 0 360
|
||||||
|
rgb 64 128 128
|
||||||
|
rgbdelta -64 -128 -128
|
||||||
|
gravity 200
|
||||||
|
scalefactor 0.8
|
||||||
|
}
|
||||||
|
r_part high.pe_225
|
||||||
|
{
|
||||||
|
texture fte_bloodparticle
|
||||||
|
blend subtract
|
||||||
|
count 0.5
|
||||||
|
scale 32
|
||||||
|
alpha 0
|
||||||
|
die 1
|
||||||
|
randomvel 32
|
||||||
|
veladd 5
|
||||||
|
rotationspeed 90
|
||||||
|
rotationstart 0 360
|
||||||
|
rgb 64 128 128
|
||||||
|
rgbdelta -64 -128 -128
|
||||||
|
gravity 200
|
||||||
|
scalefactor 0.8
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////
|
||||||
|
//zombie body-part blood trails
|
||||||
|
r_part tr_slightblood
|
||||||
|
{
|
||||||
|
texture fte_bloodparticle
|
||||||
|
blend subtract
|
||||||
|
// tcoords 1 1 63 63 256 2 64
|
||||||
|
step 16
|
||||||
|
scale 64
|
||||||
|
alpha 0
|
||||||
|
die 1
|
||||||
|
randomvel 32
|
||||||
|
veladd 10
|
||||||
|
rotationspeed 90
|
||||||
|
rotationstart 0 360
|
||||||
|
rgb 64 128 128
|
||||||
|
rgbdelta -64 -128 -128
|
||||||
|
gravity 200
|
||||||
|
scalefactor 0.8
|
||||||
|
scaledelta -10
|
||||||
|
stains -0.5
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////
|
||||||
|
//regular ol' blood trails
|
||||||
|
r_part tr_blood
|
||||||
|
{
|
||||||
|
texture fte_bloodparticle
|
||||||
|
blend subtract
|
||||||
|
step 8
|
||||||
|
scale 64
|
||||||
|
alpha 0
|
||||||
|
die 1
|
||||||
|
randomvel 32
|
||||||
|
veladd 10
|
||||||
|
rotationspeed 90
|
||||||
|
rotationstart 0 360
|
||||||
|
rgb 32 128 128
|
||||||
|
rgbdelta -32 -128 -128
|
||||||
|
gravity 200
|
||||||
|
scalefactor 0.8
|
||||||
|
scaledelta -10
|
||||||
|
stains -0.5
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////
|
||||||
|
//fallbacks
|
||||||
|
|
||||||
|
r_part pe_default
|
||||||
|
{
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 1 97 95 191 256
|
||||||
|
count 1
|
||||||
|
scale 4
|
||||||
|
veladd 15
|
||||||
|
die 0.4
|
||||||
|
alphadelta 0
|
||||||
|
diesubrand 0.4
|
||||||
|
gravity 40
|
||||||
|
spawnorg 8
|
||||||
|
}
|
||||||
|
r_part pe_defaulttrail
|
||||||
|
{
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 1 97 95 191 256
|
||||||
|
scale 15
|
||||||
|
step 1
|
||||||
|
alpha 0.6
|
||||||
|
die 0.2
|
||||||
|
rgb 192 96 48
|
||||||
|
veladd 0
|
||||||
|
randomvel 2
|
||||||
|
friction 4
|
||||||
|
scalefactor 0.825
|
||||||
|
spawnmode spiral
|
||||||
|
spawnvel 25
|
||||||
|
blend add
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////
|
||||||
|
//map debugging
|
||||||
|
r_part pe_pointfile
|
||||||
|
{
|
||||||
|
texture "particles/fteparticlefont.tga"
|
||||||
|
tcoords 1 97 95 191 256
|
||||||
|
count 1
|
||||||
|
scale 50
|
||||||
|
die 30
|
||||||
|
alphadelta 0
|
||||||
|
rgb 255 255 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
335
particles.txt
Executable file
335
particles.txt
Executable file
|
@ -0,0 +1,335 @@
|
||||||
|
Example:
|
||||||
|
r_part blah
|
||||||
|
{
|
||||||
|
texture textures/particles/myimage.tga
|
||||||
|
tcoords 0 0 64 64 64
|
||||||
|
die 2
|
||||||
|
scalefactor 1
|
||||||
|
scale 20
|
||||||
|
alpha 0.5
|
||||||
|
rgb 255 0 0
|
||||||
|
rgbdelta 0 128 128
|
||||||
|
spawnmode ball
|
||||||
|
spawnorg 32
|
||||||
|
}
|
||||||
|
|
||||||
|
will give transparent (0.5) red particles that will fade to fully white when they go fully transparent 2 seconds later.
|
||||||
|
they will spawn within a ball of 32 units radius.
|
||||||
|
|
||||||
|
|
||||||
|
Types:
|
||||||
|
Always try to include a type. The engine will guess what your particle is meant to be otherwise, based on textures and other nonsense. That stuff is generally unreliable, and probably not what you want.
|
||||||
|
|
||||||
|
Chaining:
|
||||||
|
You can add multiple particle descriptions to a single effect. The first should be 'r_part foo', and the others should be 'r_part +foo'. Particles without a + will reset the chain.
|
||||||
|
|
||||||
|
Effect naming:
|
||||||
|
Effects loaded by r_particledesc will be given an internal prefix, eg: foo.cfg.
|
||||||
|
If the gamecode explicitly states foo.bar, your foo.cfg will automatically be executed, and will automatically use the bar effect from it.
|
||||||
|
The effect can still be overriden from a custom config by explicitly naming the effect foo.bar - the effect bar in the config foo will not override this, but would override bar on its own.
|
||||||
|
|
||||||
|
Scale:
|
||||||
|
scale values are defined in 1/4th qu, for some reason.
|
||||||
|
scalefactor typically needs to be explicitly set to 1. this value affects how the particle scales with distance from view, rather than the actual size of the particle.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
texture <TEXTURENAME>
|
||||||
|
specifies to use an image named TEXTURENAME for this effect.
|
||||||
|
|
||||||
|
tcoords <s1> <t1> <s2> <t2> [tscale] [rsmax] [rsstep]
|
||||||
|
specifies to use a subsection of the image.
|
||||||
|
if tscale is set, all units are divided by this. it is the virtual size of your texture. So a value of 1 means that your texture coords must be between 0 and 1. But if it properly matches your texture's size, the coords are in pixels.
|
||||||
|
if rsmax is present, each particle will use a random image. These images must be on a single row in your particle font.
|
||||||
|
rsstep specifies the stride (gap from one to the next) in your particle font, and is only needed if rsmax is present and greater than 1.
|
||||||
|
|
||||||
|
rotationstart <min> [max]
|
||||||
|
the particle will start with a rotation rotated between min and max.
|
||||||
|
if max is missing, the particle will always start with the min value.
|
||||||
|
|
||||||
|
beamtexstep <value>
|
||||||
|
only valid if the effect is a beam.
|
||||||
|
specifies the number of quake units per beam texture repitition.
|
||||||
|
|
||||||
|
beamtexspeed <value>
|
||||||
|
only valid if the effect is a beam.
|
||||||
|
controls how fast the texture scrolls on the beam.
|
||||||
|
|
||||||
|
scale <min> [max]
|
||||||
|
particles will start with a diameter of this many quake units.
|
||||||
|
actual scale will be randomly chosen between min and max (max defaults to equal if min is missing)
|
||||||
|
|
||||||
|
scalerand <extra>
|
||||||
|
obsolete
|
||||||
|
overrides the scale max value
|
||||||
|
actual scale will be now be randomly chosen between min and min+extra
|
||||||
|
|
||||||
|
scalefactor <frac>
|
||||||
|
controls how the particle scales with distance.
|
||||||
|
1 makes the particle scale the same as anything else
|
||||||
|
0 makes the particle not change size no matter how far it is
|
||||||
|
|
||||||
|
scaledelta <value>
|
||||||
|
controls how the particle scales over time
|
||||||
|
specifies the change in the particle scale per second.
|
||||||
|
|
||||||
|
step <min> <max>
|
||||||
|
trails/beams only
|
||||||
|
specifies the distance between each particle in the trail (or beam).
|
||||||
|
|
||||||
|
count <min> <max>
|
||||||
|
point/box effects only (not trails or beams)
|
||||||
|
specifies how many particles are spawned per effect (some classic effects contain an extra scaler which is multiplied by the resulting value)
|
||||||
|
|
||||||
|
alpha <value>
|
||||||
|
specifies the initial alpha value of the effect
|
||||||
|
|
||||||
|
alphadelta <value>
|
||||||
|
specifies how much the alpha value of the effect changes per second (subtracted)
|
||||||
|
|
||||||
|
die <maximum age> <minimum age>
|
||||||
|
specifies the maximum age of the particle
|
||||||
|
|
||||||
|
diesubrand <value>
|
||||||
|
obsolete (set by die)
|
||||||
|
specifies the maximum starting age of the particle.
|
||||||
|
basically the particle will live up to this much less time. the alpha value will also be aged by the amount chosen by this value
|
||||||
|
|
||||||
|
randomvel <horiz> [vert]
|
||||||
|
controls how fast the particle moves when it spawns. This works regardless of any requested velocities.
|
||||||
|
if vert is not specified, horiz is used instead.
|
||||||
|
|
||||||
|
veladd <value>
|
||||||
|
controls how much of the effect's spawn velocity is used, can be greater than 1, or negative.
|
||||||
|
|
||||||
|
orgadd <value>
|
||||||
|
biases how much to add to the starting origin relative to the requested velocity.
|
||||||
|
|
||||||
|
friction <<xyz>|<xy> <z> | <x> <y> <z>>
|
||||||
|
Proportion of the particle's speed that should be lost from friction. Negative values are accepted.
|
||||||
|
|
||||||
|
gravity <value>
|
||||||
|
amount that the particle's velocity changes per second, in quake units.
|
||||||
|
|
||||||
|
clipbounce <value>
|
||||||
|
how much of the particle's velocity to use if the particle is clipped. See cliptype.
|
||||||
|
Defaults to 0.8
|
||||||
|
|
||||||
|
cliptype <effectname>
|
||||||
|
Specifies which new effect to spawn when the particle hits something.
|
||||||
|
The origin and velocity of the particle are used to spawn the new effect.
|
||||||
|
The clipbounce value is used as a scaler for the reflected velocity.
|
||||||
|
If the effect named is the effect itself, the particle will merely bounce, instead of spawning a new effect.
|
||||||
|
FIXME: make default to bounce if clipbounce is set without cliptype.
|
||||||
|
|
||||||
|
clipcount <count>
|
||||||
|
The scaler to use for the number of particles to spawn upon a clip event.
|
||||||
|
Only valid in conjunction with cliptype.
|
||||||
|
|
||||||
|
assoc <effectname>
|
||||||
|
Specifies another effect to spawn at the same time that this effect is spawned.
|
||||||
|
Thus allowing two sets of particles from one effect.
|
||||||
|
|
||||||
|
inwater <effectname>
|
||||||
|
obsolete
|
||||||
|
Specifies a replacement effect to use when this one is spawned underwater.
|
||||||
|
assoc used is the replacement effect. the assoc value from the replaced effect is ignored (this includes +foo chains).
|
||||||
|
|
||||||
|
overwater [content names]
|
||||||
|
Specifies that this particle should ONLY be spawned when out of water.
|
||||||
|
The particle will not spawn under water (this does not affect assoc chains).
|
||||||
|
Content names are a space-separated list of: water slime lava sky solid fluid. Default is fluid if not specified.
|
||||||
|
The r_part_contentswitch cvar must be enabled for this to function correctly.
|
||||||
|
|
||||||
|
underwater [content names]
|
||||||
|
Specifies that this particle should ONLY be spawned when underwater.
|
||||||
|
The particle will not spawn if the spawn position is non-water (this does not affect assoc chains).
|
||||||
|
|
||||||
|
colorindex <index> [rand]
|
||||||
|
Specifies a palette index to spawn the particle with.
|
||||||
|
The index used is between index and index+rand.
|
||||||
|
overrides the normal starting colours.
|
||||||
|
|
||||||
|
colorrand <rand>
|
||||||
|
obsolete.
|
||||||
|
replaces the [rand] part of the colorindex setting.
|
||||||
|
|
||||||
|
citracer
|
||||||
|
only valid if colorindex is set.
|
||||||
|
adds a palette index between 0 and 3, based on the particle index in the effect or trail.
|
||||||
|
|
||||||
|
red <value>
|
||||||
|
green <value>
|
||||||
|
blue <value>
|
||||||
|
rgb <red> <green> <blue>
|
||||||
|
rgb <value>
|
||||||
|
Specifies the initial red, green, and/or blue values for each particle.
|
||||||
|
Fully opaque is 255 or above.
|
||||||
|
Values above 255 are valid, but will remain opaque until the value drops below 255 from the colour deltas.
|
||||||
|
|
||||||
|
redrand <value>
|
||||||
|
greenrand <value>
|
||||||
|
bluerand <value>
|
||||||
|
rgbrand <red> <green> <blue>
|
||||||
|
rgbrand <value>
|
||||||
|
Specifies how much extra red, green, and/or blue there may be for particles.
|
||||||
|
The initial colour will be multiplied by this amount before addition.
|
||||||
|
Each componant is separately randomized. EG, red might add nothing, while the full green is added, and only half the blue.
|
||||||
|
Fully opaque is 255 or above.
|
||||||
|
|
||||||
|
redrandsync <value>
|
||||||
|
greenrandsync <value>
|
||||||
|
bluerandsync <value>
|
||||||
|
rgbrandsync <red> <green> <blue>
|
||||||
|
rgbrandsync <value>
|
||||||
|
Specifies how much extra red, green, and/or blue there may be for particles.
|
||||||
|
The initial colour will be multiplied by this amount before addition.
|
||||||
|
Componants are syncronised. EG, if the full amount of red is added, the full amount of green and blue will also be added.
|
||||||
|
Fully opaque is 255 or above.
|
||||||
|
|
||||||
|
reddelta <value>
|
||||||
|
greendelta <value>
|
||||||
|
bluedelta <value>
|
||||||
|
rgbdelta <red> <green> <blue>
|
||||||
|
rgbdelta <value>
|
||||||
|
Specifies how much the red, green, and/or blue values of each particle change over time.
|
||||||
|
The value 255 is the value required to go from opaque to invisible in 1 second.
|
||||||
|
|
||||||
|
rgbdeltatime <value>
|
||||||
|
Specifies for how long the particle may change colours for. After this many seconds, the particle may no longer change colours (delta becomes 0).
|
||||||
|
|
||||||
|
rampmode <mode>
|
||||||
|
mode may be one of:
|
||||||
|
none: uses rgb+rand+sync+delta+scale+scaledelta values.
|
||||||
|
absolute: the ramp overrides all colour+scale values. The effect moves from one absolute ramp index to the next.
|
||||||
|
delta: uses rgb+rand+sync+scale, but not delta values. All delta values come from the colour ramp instead.
|
||||||
|
|
||||||
|
if not none, the ramp index used is based upon the particle's age, its lifetime, and how many ramp elements there are.
|
||||||
|
|
||||||
|
rampindexlist <idx1> [<idx2> [idx3 ...]]
|
||||||
|
Scale used is the currently set scale value.
|
||||||
|
Specifies a set of palette index values to use for the effect as part of the effect's colour ramp.
|
||||||
|
|
||||||
|
rampindex <idx> <scale>
|
||||||
|
Specifies an individual palette index value and particle scale to use for the effect as part of the effect's colour ramp
|
||||||
|
|
||||||
|
ramp <red> <green> <blue> [alpha] [scale]
|
||||||
|
Specifies a ramp index in rgb terms, regardless of palette.
|
||||||
|
|
||||||
|
stains <value>
|
||||||
|
How much the effect discolours the wall upon impact.
|
||||||
|
The stained colour is based upon the colour of the particle upon impact.
|
||||||
|
|
||||||
|
blend <mode>
|
||||||
|
mode may be one of: add, subtract, blendcolour/blendcolor, blend
|
||||||
|
if the texture used is actually a shader, this is ignored.
|
||||||
|
|
||||||
|
spawnmode <mode> [arg1] [arg2]
|
||||||
|
This affects how particles are positioned when they first spawn, and their initial velocities.
|
||||||
|
for point effects, mode may be one of:
|
||||||
|
box: simple axially aligned box of particles.
|
||||||
|
circle: particles spawn within a ball with uniform distance from the center. none will appear in the middle.
|
||||||
|
arg1: percentage of the circle to cover. a value of 5 will go around the circle 5 separate times. this can be used for weird beam effects.
|
||||||
|
areaspread: the radius of the ball
|
||||||
|
areaspreadvert: the height of the ball. if 0, will be a flat circle
|
||||||
|
ball: particles spawn randomly within a ball.
|
||||||
|
areaspread: the radius of the ball
|
||||||
|
areaspreadvert: the height of the ball. if 0, will be a flat circle.
|
||||||
|
telebox: matches quake's telebox
|
||||||
|
lavasplash: like chthon's lava splash
|
||||||
|
uniformcircle: particles are spawned in a circle with uniform distance between and from the center. z=0.
|
||||||
|
syncfield: particles spawn at predictable locations based upon time within a rough sphere. Only useful for effects that are regenerated+replaced every frame.
|
||||||
|
distball:
|
||||||
|
*default*: regular box. particles are spawned inside an axially aligned box.
|
||||||
|
|
||||||
|
for trail effects, mode may be one of:
|
||||||
|
spiral: particles are given velocities perpendicular to the direction based on the distance moved.
|
||||||
|
tracer: particles spawn with alternating horizontal velocities (a wake effect).
|
||||||
|
*default*: particles spawn as a regular trail.
|
||||||
|
|
||||||
|
spawnparam1 <value>
|
||||||
|
obsolete. see spawnmode.
|
||||||
|
|
||||||
|
spawnparam2 <value>
|
||||||
|
obsolete. see spawnmode.
|
||||||
|
|
||||||
|
up <value>
|
||||||
|
the particle's starting origin is moved upwards by this amount (worldspace).
|
||||||
|
|
||||||
|
type <mode>
|
||||||
|
How the particles look.
|
||||||
|
mode may be:
|
||||||
|
beam: valid only for trails. Particles form a single textured beam acting as nodes along it.
|
||||||
|
spark: particles are lines, their length depending upon their speed.
|
||||||
|
sparkfan: particles are non-planar triangle fans, their length depending upon their speed.
|
||||||
|
texturedspark: textured particles are aligned along their direction of movement, their length depending upon their speed, width equal to their scale.
|
||||||
|
cdecal/decal: particles are spawned only upon bsp geometry. They are clipped by it.
|
||||||
|
udecal: unclipped decal. exact semantics are subject to change.
|
||||||
|
*default*: Particles are regular, rotating, 2d images.
|
||||||
|
|
||||||
|
isbeam
|
||||||
|
obsolete.
|
||||||
|
please use 'type beam' instead.
|
||||||
|
|
||||||
|
spawntime <value>
|
||||||
|
spawnchance <value>
|
||||||
|
|
||||||
|
|
||||||
|
emit <effectname>
|
||||||
|
Specifies the effect to periodically emit.
|
||||||
|
|
||||||
|
emitinterval <min>
|
||||||
|
Particles will not emit additional effects for this duration after emitting one.
|
||||||
|
|
||||||
|
emitintervalrand <extra>
|
||||||
|
FIXME: fold into emitinterval
|
||||||
|
|
||||||
|
|
||||||
|
emitstart <seconds>
|
||||||
|
Prevents the particle from emitting anything for this duration when it first spawns.
|
||||||
|
|
||||||
|
spawnorg <horiz> [vert]
|
||||||
|
spawnvel <horiz> [vert]
|
||||||
|
obsolete
|
||||||
|
|
||||||
|
viewspace [frac]
|
||||||
|
Specifies that this particle type should move relative to the camera.
|
||||||
|
Not compatible with splitscreen.
|
||||||
|
Should not normally be used in combination with clipping/bouncing.
|
||||||
|
|
||||||
|
perframe
|
||||||
|
apply inverse frametime to count (causes emits to be per frame).
|
||||||
|
|
||||||
|
averageout
|
||||||
|
average trail points from start to end, useful with t_lightning, etc
|
||||||
|
|
||||||
|
nostate
|
||||||
|
Causes the particle system to ignore all state information.
|
||||||
|
|
||||||
|
nospreadfirst
|
||||||
|
don't randomize org/vel for first generated particle
|
||||||
|
|
||||||
|
nospreadlast
|
||||||
|
don't randomize org/vel for last generated particle
|
||||||
|
|
||||||
|
sound <soundname> <vol> <attenuation> [pitch] [delay]
|
||||||
|
When the effect is first spawned, the named sound will play with the given volume and attenuation at the center point. This may not work with all spawn methods, as it will ignore any count scales.
|
||||||
|
|
||||||
|
lightradius <radius>
|
||||||
|
lightradiusfade <radiuspersecond>
|
||||||
|
lightrgb <r> <g> <b>
|
||||||
|
lightrgbfade <r/s> <g/s> <b/s>
|
||||||
|
lighttime <maxage>
|
||||||
|
Spawns a dlight when the effect is spawned.
|
||||||
|
dlight is removed when radius drops to 0 or the age is exceeded.
|
||||||
|
at this time it is not possible to override the corona/specular levels.
|
||||||
|
|
||||||
|
lightcubemap <cubemapnum>
|
||||||
|
value 0 means no cubemap.
|
||||||
|
otherwise with eg cubemap 5, uses image files cubemaps/5ft.tga, cubemaps/5bk.tga, etc.
|
||||||
|
fixme: at the current time, the cubemap is world-aligned and cannot rotate.
|
||||||
|
|
||||||
|
model <name> <firstframe> <endframe> <framerate> <alpha>
|
||||||
|
spawns sprites or models that fly away with random angles and run through some frame sequence. handy for simple gib effects.
|
||||||
|
|
||||||
|
spawnstain <radius> <r> <g> <b>
|
233
qs-spike.txt
Executable file
233
qs-spike.txt
Executable file
|
@ -0,0 +1,233 @@
|
||||||
|
this is an attempt to fix some of the deficiencies (as I see them) in quakespasm, while trying not to change how it feels to the user.
|
||||||
|
|
||||||
|
changes:
|
||||||
|
extra builtins -
|
||||||
|
added lots of misc builtins, including:
|
||||||
|
string manipulation+buffers,
|
||||||
|
file access,
|
||||||
|
bsp introspection,
|
||||||
|
maths,
|
||||||
|
tracebox,
|
||||||
|
botclient stuff,
|
||||||
|
clientcommands,
|
||||||
|
etc.
|
||||||
|
Setting pr_checkextensions 0 will a) prevent extensions from being advertised to the mod. b) display a warning when any extended builtin is used (assuming it would otherwise crash anyway).
|
||||||
|
stub builtins -
|
||||||
|
also added stubs for builtins that either don't make sense in quakespasm or would need protocol extensions.
|
||||||
|
these are merely present to avoid crashes and will display a warning the first time they're called.
|
||||||
|
multicast -
|
||||||
|
supports pvs culling. still does not support phs.
|
||||||
|
precache builtins -
|
||||||
|
these can now be used mid-map. be warned that this will result in other clients disconnecting (will still display warnings on the server).
|
||||||
|
misc stuff -
|
||||||
|
MOVETYPE_FOLLOW and SOLID_CORPSE now work, .movement is supported.
|
||||||
|
cvar changes -
|
||||||
|
for mods, autocvars now work. the set+seta command also now works.
|
||||||
|
I bumped the cbuf size, because not only were well-documented mods were being punished for it, but also stuffcmded aliases were overflowing it.
|
||||||
|
clc_stringcmd -
|
||||||
|
rewrote client->server string commands a little.
|
||||||
|
this security fix blocks clients from being able to execute server-side aliases/cvars with names similar to 'allowed' console commands.
|
||||||
|
SV_TouchLinks -
|
||||||
|
rewrote this to avoid potential crashes within recursive touch events (yes, this can happen in rare cases, even in the prior quakespasm version).
|
||||||
|
may have minor behaviour differences, pr_checkextensions 0 disables this, restoring prior behaviour including instability-from-recursion.
|
||||||
|
single server socket -
|
||||||
|
the server now only uses a single socket per protocol family.
|
||||||
|
this makes NATs/firewalls much easier to deal with as servers no longer need to be DMZoned, only a single port needs to be forwarded..
|
||||||
|
ipv6 -
|
||||||
|
this build can natively use ipv6, but will still assume ipv4 first.
|
||||||
|
uses non-hybrid sockets so this should work on winxp too.
|
||||||
|
use -noudp4 or -noudp6 to disable one and not the other. by default it'll try to use both.
|
||||||
|
reduced mtu size to avoid connectivity issues. still higher than vanilla though, which may also cause other issues.
|
||||||
|
master servers -
|
||||||
|
it is now possible to automatically list your server globally. hurrah...
|
||||||
|
unfortunately the server list is still lame and provides no ping info, so have fun with that. :)
|
||||||
|
thanks to ipv6, servers might get listed twice.
|
||||||
|
you can turn this on with sv_public, or via the 'new game' menu.
|
||||||
|
proquake angles -
|
||||||
|
now uses 16bit angles when connecting to proquake servers, or really most protocol15 servers including qrack+dp+etc.
|
||||||
|
also advertises protocols, allowing fte servers to serve protocol 666+999 as needed.
|
||||||
|
bug fixes -
|
||||||
|
spritegroups will now animate properly - this was a vanilla glquake bug.
|
||||||
|
model loader -
|
||||||
|
alpha-tested models now supported
|
||||||
|
spr32 sprites now supported (still using alpha testing rather than changing all sprites to use blending, so the alpha channel might as well still be 1bit)
|
||||||
|
many limit-exceeding models will now safely fail to load rather than crashing the engine.
|
||||||
|
note that some limits were not properly enforced before, and this might mean that a couple of models will newly fail to load (but won't crash the engine any more).
|
||||||
|
known-but-unsupported model formats will display a more helpful message, without crashing. unknown formats will similarly no longer crash.
|
||||||
|
bspx coloured lighting is now supported (somewhat common in the qw community). use -bspxlit argument with tyrutils-ericw's light util and discard the lit.
|
||||||
|
added support for tyrutil-ericw's qbsp's -notex argument that omits textures, reducing file size and avoiding gpl violations. still doesn't do replacements though.
|
||||||
|
fixed bsps that were compiled with vanilla qbsp's -noclip argument. will retain the correct view height, but will otherwise use the point-hull for everything.
|
||||||
|
binds menu -
|
||||||
|
if provided, will parse a bindlist.lst file from the gamedir. this should take the form of lines like:
|
||||||
|
+thecommand "some desc" "optional much longer description of it"
|
||||||
|
lines with a command that is just a hyphen are treated as comments/separators.
|
||||||
|
quakespasm ignores that third part, fte displays it on mouse-over.
|
||||||
|
if any binds are provided this way, they will completely replace the built-in list.
|
||||||
|
there is no limit to the binds that can be added, the menu will scroll, but there's no indicator that there are more/less.
|
||||||
|
particles -
|
||||||
|
now includes fte's scriptable particle system.
|
||||||
|
the config parser is a little different from fte (fte uses actual console commands, qs parses directly without the console).
|
||||||
|
this means that configs are limited to just r_part+r_effect+r_trail. setting cvars from particle configs are not supported here.
|
||||||
|
also currently missing support for models, embedded shaders (obviously), stains, viewspace particles.
|
||||||
|
tga images are supported, png+jpg are not.
|
||||||
|
no effects will be loaded by default, causing the engine to fall back on the existing particle system until a config is loaded.
|
||||||
|
users can set r_particledesc if they really specific particle effects. mods should include the config name as a namespace/prefix.
|
||||||
|
example usage (using FTE_SV_POINTPARTICLES with FTE_PART_NAMESPACES):
|
||||||
|
float myexplosion = particleeffectnum("mypartcfg.myexplosion");
|
||||||
|
pointparticles(myexplosion, self.origin, trace_plane_normal, 1);
|
||||||
|
note that DP_SV_POINTPARTICLES and FTE_SV_POINTPARTICLES qc extensions are supposed to be identical, except that *certain* mods see DP_ and assume the entire particle system too, which is NOT the case, hence the need to check both extensions.
|
||||||
|
note that if FTE_PART_NAMESPACES is supported, then particleeffectnum("mypartcfg.myexplosion") will automatically load the 'mypartcfg' particle set, however the engine deals with that.
|
||||||
|
note that for dp compat, if FTE_PART_NAMESPACE_EFFECTINFO is supported, then "effectinfo.*" or "effectinfo_*.*" are supported namespaces that will should be compatible with DP's effects (if you ignore the prefix).
|
||||||
|
Precaching a single particle effect like this will include this config for all particles with no namespace.
|
||||||
|
So for dp compat, you can use the following:
|
||||||
|
if (checkextension("FTE_SV_POINTPARTICLES") || checkextension("DP_SV_POINTPARTICLES"))
|
||||||
|
{
|
||||||
|
if (checkextension("FTE_PART_NAMESPACE_EFFECTINFO"))
|
||||||
|
{
|
||||||
|
particleeffectnum("effectinfo.dummy"); //so clients will attempt to load the effectinfo namespace, if not already available.
|
||||||
|
particleeffectnum(strcat("effectinfo_", mapname, ".dummy")); //map-specific effects
|
||||||
|
}
|
||||||
|
//else we have no idea where we're loading the config from... lets hope its either dp or the user helps us out
|
||||||
|
//do precaches
|
||||||
|
myexplosioneffect = particleeffectnum("myexplosioneffect");
|
||||||
|
}
|
||||||
|
//later
|
||||||
|
if (myexplosioneffect)
|
||||||
|
pointparticles(myexplosioneffect, self.origin, trace_plane_normal, 1);
|
||||||
|
else
|
||||||
|
te_explosion(self.origin); //'generic' fallback
|
||||||
|
(or you can just set 'r_particledesc effectinfo' in your mod's default.cfg and hope the user doesn't change it to something else)
|
||||||
|
note that particleeffectnum acts as a precache. you don't need to cache the result in a spawn function, but you do need to have called it early enough to avoid warning message.
|
||||||
|
note that any use of particleeffectnum will cause other clients to disconnect with 'illegible server message'.
|
||||||
|
it is *ENTIRELY* the modder's/user's responsibility to keep things consistent and not garish. pay close attention to particle sizes, texture resolution, etc.
|
||||||
|
mappers can add something like the following to their worldspawn entity:
|
||||||
|
"_texpart_sky1" "weather.tex_rainsky"
|
||||||
|
surfaces with the "sky1" texture will then act as emitters. this includes _texpart_*teleport or whatever. this doesn't require new gamecode.
|
||||||
|
r_partredirect can be used to redirect emitters (or effects) dynamically. redirections are normally meant to be a user feature, so mods should probably try to avoid tex_* effects in case the user switches gamedirs.
|
||||||
|
this command can work recursively, up to 5 itterations.
|
||||||
|
replacement network protocol -
|
||||||
|
namely FTE's nack-based PEXT2_REPLACEMENTDELTAS protocol extension. if you're a networking nerd, the archetecture is documented here: https://sourceforge.net/p/fteqw/code/HEAD/tree/trunk/specs/replacementdeltas.txt?format=raw
|
||||||
|
The extension applies to a base protocol, in this case 15, 666, or 999. There are some differences for QW vs NQ base protocols due to the netchan, these are not applicable to quakespasm.
|
||||||
|
the protocol is specced for lots of extended entity state, but most of that will be ignored/unused by the rest of the engine, and consequently won't be transmitted either.
|
||||||
|
automatically disabled per-client if unsupported by that client
|
||||||
|
all of the below will result in 'illegible server message' in older clients. usage of other extensions will be silently stripped, which may cause weirdness (eg: viewmodelforclient).
|
||||||
|
use of custom particles (particleeffectnum, trailparticles, pointparticles)
|
||||||
|
use of late precaches (at least if they were not already precached in a spawn function) [you shouldn't rely on this anyway].
|
||||||
|
this server implementation has not been applied to everything:
|
||||||
|
makestatic - static entities will not benefit from extensions like EF_NOSHADOW.
|
||||||
|
entities are sent as deltas from the previous packet
|
||||||
|
entity data is split up to not exceed the mtu (without needing netchan changes)
|
||||||
|
with PEXT2_PREDINFO, stats are also sent semi-unreliably using the same mechanism (avoids reliables-stall issues).
|
||||||
|
clc_clientdata is redundant.
|
||||||
|
all stats have full precision.
|
||||||
|
protocol does not change simply because a mission pack is loaded.
|
||||||
|
gamedir added to serverinfo, the client responds by displaying a warning if the gamedir does not match
|
||||||
|
baselines are generated per-client and split over multiple packets, so the signon buffer size is no longer a limiting factor for maps with insane entity counts (for all supported protocols).
|
||||||
|
MAX_VISEDICTS is gone.
|
||||||
|
however, try not to have them all visible at once. drawing 5k or 10k entities is a massive performance drain, as can them all getting angry at the player.
|
||||||
|
this implementation will reduce overall data sizes by avoiding retransmissions, but there is no rate limiting which can result in significant burst.
|
||||||
|
this may result in extra packetloss bursts if you have saturated tcp/etc connections running at the time.
|
||||||
|
packetloss is detected serverside and triggers resends
|
||||||
|
it will recover fully, but new entities appearing may have significant delays to them (especially if static) proportionally to other entities.
|
||||||
|
interpolation code unchanged, there is no time drifting, which means the engine will not be able to hide packetloss, resulting in slightly jerky player movement.
|
||||||
|
because of this FTE will still be smoother for internet play.
|
||||||
|
still playable while simulating 50% packetloss, but not smooth. this tested with no extra ping, so would be worse online.
|
||||||
|
the protocol does not carry nextthink hints, and quakespasm is too stupid to infer intervals, so assumes interpolation intervals of 0.1.
|
||||||
|
the protocol supports prediction, but this implementation does not.
|
||||||
|
To prevent the server from detecting replacement deltas (so they don't appear in demos), use "sv_protocol 666-" (omitting the - will neither enable nor disable fte extensions).
|
||||||
|
To re-enable extensions, use "sv_protocol FTE+666"
|
||||||
|
Other than a couple of extended svcs that a mod might use, 666 is effectively obsolete (but still useful as a base protocol for earlier quakespasm, fitzquake, etc).
|
||||||
|
Using 999 as the base protocol still provides map size increases.
|
||||||
|
This will also cause custom particle effects to become invisible to all clients.
|
||||||
|
To prevent the client from advertising support for replacement deltas, use 'cl_nopext 1'.
|
||||||
|
The server will fall back to only the base protocol, if *either* the client or server has it disabled (or both, obviously).
|
||||||
|
Ideally, leave it enabled on the server and disable it as desired on the client, but I guess people are not familiar with that yet.
|
||||||
|
This will allow you to record compatible demos even if you don't have rcon access to the server.
|
||||||
|
lightstyles -
|
||||||
|
bumped to 255 (the last index is not valid in bsps, so not relevant).
|
||||||
|
presense of additional lightmaps won't bug anything out, but actually using them might break other clients if they don't support this raised limit yet.
|
||||||
|
rcon -
|
||||||
|
proquake-compatible rcon is implemented server-side.
|
||||||
|
WARNING: the password is sent as plain text! it is NOT secure! (protocol limitation from )
|
||||||
|
set rcon_password to enable it, the default blank value will unconditionally treat all attempts as invalid.
|
||||||
|
no client support. there's no real reason for this, I just didn't bother writing the code (presumably it would be like the 'test' command, but *vomit*).
|
||||||
|
|
||||||
|
test mods:
|
||||||
|
dpmod -
|
||||||
|
a quick test of this seems to run fine, with the exception of a few non-generic particle effect builtins which are still stubs, mostly modified quad-damage effects.
|
||||||
|
smc -
|
||||||
|
this does actually run, but is not exactly enjoyable due to:
|
||||||
|
the use of pk3s means that everything needs to be extracted first.
|
||||||
|
use of md3 format (these models will be invisible)
|
||||||
|
high mdl poly counts making mdls unloadable (resulting in them being .. you guessed it, invisible)
|
||||||
|
unsupported stereo sounds (won't play, and might spam)
|
||||||
|
no shader support (hey, at least qs won't obey the 'depthfunc equal' lines)
|
||||||
|
smc loves late precaches (spammy).
|
||||||
|
additionally an smc bug causes monsters to be spawned underground (monsters can't move).
|
||||||
|
there's likely other issues. I've not tested it that extensively.
|
||||||
|
arcane dimensions -
|
||||||
|
urm. still works?..
|
||||||
|
gains DP_QC_GETSURFACE, so broken vanilla skies stop being broken (ad's only use for this extension).
|
||||||
|
gains EF_NOSHADOW.
|
||||||
|
ad's engine particle system usage assumes dp internals, and needs a tweak in order to get it to behave more generically.
|
||||||
|
rogue -
|
||||||
|
still need to test the ending with its writebyte hacks
|
||||||
|
|
||||||
|
|
||||||
|
issues:
|
||||||
|
(note that listed critisisms are not always bad things for the average qs user, but are probably bad for _someone_ and do limit potential mods)
|
||||||
|
(some things can only be good, except for how invasive such a thing would be resulting in too many bugs, or I'm just too lazy/selfish to do them myself)
|
||||||
|
protocol changes -
|
||||||
|
late precaches are in, but will still display warnings if depended upon. late precaches can still be an issue if the reliable is delayed while the unreliable is not.
|
||||||
|
sounds are still sent fully unreliably. this means they are subject to packetloss, and is especially significant on func_plat entities (where the sounds are typically looping, and thus might never be replaced/stopped).
|
||||||
|
staticsounds still use the sv.signon buffer, and are thus still limited to the underlying protocol and single-signon-buffer size.
|
||||||
|
pointparticles and trailparticles are new, but there is no support for most extended TE_* values (rain+snow are the only added TEs). Use pointparticles if you need such other effects.
|
||||||
|
while the protocol supports a range of extra entity state, much of that data is still unused (parsed and not sent). including ef_additive, tags, etc
|
||||||
|
not added -
|
||||||
|
voip would be a nice idea for all those first-playthrough map demos
|
||||||
|
no download mechanism added. I would want to use paks, which would make this far too complex. there's no automatic gamedir switching either.
|
||||||
|
(there is a gamedir hint, but currently it results in only a warning print because I really cba to rewrite quakespasm's filesystem code)
|
||||||
|
serious dp protocol issues -
|
||||||
|
sending 666 or 999 to a dp client results in dp spamming loads of useless gibberish that obscures the actual error, such that few people actually report the actual problem...
|
||||||
|
the only way I can think of getting DP to be remotely sane is to send it an svc_version for it to crap out on, reducing the spam in the hopes that people will read up a little.
|
||||||
|
the alternative is to hack in some 'cmd dpcheck $somedponlycvar' and see what the client says that cvar is set to (if $foo is supported).
|
||||||
|
unfortunately there's no version cvar, or any other kind of useful feature that I'm aware of, so this would fuck up for other clients with seta etc getting saved into $gamedir/config.cfg and then poluting other engines.
|
||||||
|
(this is not a new issue)
|
||||||
|
proquake+vanilla sucks:
|
||||||
|
sv_protocol=666 has higher limits. if this is inadvertantly set, then the server is permitted to send larger serverinfo packets (that exceed the 8192 limit).
|
||||||
|
proquake then displays 'read error' (due to recvfrom returning EMSGSIZE), which is awkward but not our bug, just a vanilla limitation.
|
||||||
|
(this is not a new issue)
|
||||||
|
note that reliables larger than 8192 but with an mtu compatible with vanilla can be used to crash both vanilla and proquake. this is true even if it is a client that sent the packets, crashing the server.
|
||||||
|
(this is not present in qss)
|
||||||
|
limited renderer changes -
|
||||||
|
no md3 support
|
||||||
|
no iqm support
|
||||||
|
harsh mdl limits
|
||||||
|
sprites still alpha-tested
|
||||||
|
still using render-to-texture instead of glsl for drawing water (which would allow mipmaps and anisotropic filtering, instead of using a random noise texture...)
|
||||||
|
randomization -
|
||||||
|
quakespasm likes seeding the random number generator as a handy trick... which can result in timers+particles getting a little too predictable
|
||||||
|
no filesystem updates -
|
||||||
|
no pk3s (could potentially decompress to a temp file, and fix up over time, but meh)
|
||||||
|
still only numbered paks, no pak.lst file or fs enumeration
|
||||||
|
'game' console command is still stupid (backwards, hardcoded special cases, limited paths)
|
||||||
|
I did add a 'gamedir' command as an alternative name for 'game', because quakeworld. I'd do show_fps too, but cvars make that messy.
|
||||||
|
console -
|
||||||
|
is still annoying
|
||||||
|
still prints non-ascii/non-unicode chars to stdout, which may include escape codes or other xterm/etc exploits.
|
||||||
|
con_printf is still horribly slow (at least with vsync), and likely to crash on someone... and not just me. fixing this would make a few poorly designed blocking things not refresh properly.
|
||||||
|
no markup -
|
||||||
|
all that ^1funny ^2and ^3annoying ^7text isn't handled, and remains as gibberish.
|
||||||
|
menu -
|
||||||
|
still no mouse support
|
||||||
|
still no way to add mod-specific cvars onto the menu
|
||||||
|
|
||||||
|
compiling:
|
||||||
|
export CFLAGS="-Wall -Werror -Wextra -Wno-missing-field-initializers -Wno-unused-parameter -DBUILD_SPECIAL=-spiked-rFOO"
|
||||||
|
is the CFLAGS environment setting that I'm compiling with. I only really mention that for branding. Also I'm building in windows with cygwin.
|
||||||
|
There's no 3rd-party dependancies from the vanilla quakespasm code included. this isn't an issue if you're going to compile for linux, where the dependancies are generally preinstalled as part of your distro, or you can just apt-get them or whatever.
|
||||||
|
So if you're going to compile for windows or osx, you'll need to do an svn checkout of vanilla quakespasm first, and then overwrite with the extra files (or just apply the patch to your checkout).
|
||||||
|
|
||||||
|
running:
|
||||||
|
win32+win64 binaries are included. linux users will need to build their own. osx users are screwed.
|
||||||
|
no 3rd-party libraries are included. It is assumed that you'll have previously installed vanilla QuakeSpasm and thus won't need them. In which case grab the exe that matches the archetecture of your existing QS install and just run that as if it were vanilla QuakeSpasm. Delete the other or whatever, it doesn't matter..
|
441
qsextensions.qc
Executable file
441
qsextensions.qc
Executable file
|
@ -0,0 +1,441 @@
|
||||||
|
/*
|
||||||
|
Extensions file for QuakeSpasm 0.92.2-spiked-r5
|
||||||
|
This file is auto-generated by pr_dumpplatform with no args.
|
||||||
|
You will probably need to use FTEQCC to compile this.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//QuakeSpasm only supports ssqc, so including this file in some other situation is a user error
|
||||||
|
#if defined(QUAKEWORLD) || defined(CSQC) || defined(MENU)
|
||||||
|
#error Mixed up module defs
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
//List of advertised extensions
|
||||||
|
//DP_ENT_ALPHA
|
||||||
|
//DP_CON_SET
|
||||||
|
//DP_CON_SETA
|
||||||
|
//DP_EF_NOSHADOW
|
||||||
|
//DP_QC_AUTOCVARS
|
||||||
|
//DP_QC_ASINACOSATANATAN2TAN
|
||||||
|
//DP_QC_COPYENTITY
|
||||||
|
//DP_QC_CRC16
|
||||||
|
//DP_QC_CVAR_DEFSTRING
|
||||||
|
//DP_QC_CVAR_STRING
|
||||||
|
//DP_QC_CVAR_TYPE
|
||||||
|
//DP_QC_EDICT_NUM
|
||||||
|
//DP_QC_ENTITYDATA
|
||||||
|
//DP_QC_ETOS
|
||||||
|
//DP_QC_FINDCHAIN
|
||||||
|
//DP_QC_FINDCHAINFLAGS
|
||||||
|
//DP_QC_FINDCHAINFLOAT
|
||||||
|
//DP_QC_FINDFLAGS
|
||||||
|
//DP_QC_FINDFLOAT
|
||||||
|
//DP_QC_GETSURFACE
|
||||||
|
//DP_QC_GETSURFACETRIANGLE
|
||||||
|
//DP_QC_GETSURFACEPOINTATTRIBUTE
|
||||||
|
//DP_QC_MINMAXBOUND
|
||||||
|
//DP_QC_MULTIPLETEMPSTRINGS
|
||||||
|
//DP_QC_RANDOMVEC
|
||||||
|
//DP_QC_SINCOSSQRTPOW
|
||||||
|
//DP_QC_STRFTIME
|
||||||
|
//DP_QC_STRING_CASE_FUNCTIONS
|
||||||
|
//DP_QC_STRINGBUFFERS
|
||||||
|
//DP_QC_STRREPLACE
|
||||||
|
//DP_QC_TOKENIZEBYSEPARATOR
|
||||||
|
//DP_QC_TRACEBOX
|
||||||
|
//DP_QC_TRACETOSS
|
||||||
|
//DP_QC_TRACE_MOVETYPES
|
||||||
|
//DP_QC_URI_ESCAPE
|
||||||
|
//DP_QC_VECTOANGLES_WITH_ROLL
|
||||||
|
//DP_QC_VECTORVECTORS
|
||||||
|
//DP_QC_WHICHPACK
|
||||||
|
//DP_REGISTERCVAR
|
||||||
|
//DP_SV_BOTCLIENT
|
||||||
|
//DP_SV_DROPCLIENT
|
||||||
|
//DP_SV_POINTSOUND
|
||||||
|
//DP_SV_SETCOLOR
|
||||||
|
//DP_SV_SPAWNFUNC_PREFIX
|
||||||
|
//DP_SV_WRITEUNTERMINATEDSTRING
|
||||||
|
//DP_TE_BLOOD
|
||||||
|
//DP_TE_STANDARDEFFECTBUILTINS
|
||||||
|
//EXT_BITSHIFT
|
||||||
|
//FRIK_FILE
|
||||||
|
//FTE_PART_SCRIPT
|
||||||
|
//FTE_PART_NAMESPACES
|
||||||
|
//FTE_PART_NAMESPACE_EFFECTINFO
|
||||||
|
//FTE_QC_CHECKCOMMAND
|
||||||
|
//FTE_QC_INTCONV
|
||||||
|
//FTE_SV_POINTPARTICLES
|
||||||
|
//KRIMZON_SV_PARSECLIENTCOMMAND
|
||||||
|
//ZQ_QC_STRINGS
|
||||||
|
|
||||||
|
|
||||||
|
//Explicitly flag this stuff as probably-not-referenced, meaning fteqcc will shut up about it and silently strip what it can.
|
||||||
|
#pragma noref 1
|
||||||
|
|
||||||
|
|
||||||
|
//Some custom types (that might be redefined as accessors by fteextensions.qc, although we don't define any methods here)
|
||||||
|
#ifdef _ACCESSORS
|
||||||
|
accessor strbuf:float;
|
||||||
|
accessor searchhandle:float;
|
||||||
|
accessor hashtable:float;
|
||||||
|
accessor infostring:string;
|
||||||
|
accessor filestream:float;
|
||||||
|
#else
|
||||||
|
#define strbuf float
|
||||||
|
#define searchhandle float
|
||||||
|
#define hashtable float
|
||||||
|
#define infostring string
|
||||||
|
#define filestream float
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
//Supported Extension fields
|
||||||
|
.float gravity;
|
||||||
|
//.float items2; /*if defined, overrides serverflags for displaying runes on the hud*/
|
||||||
|
.float alpha; /*entity opacity*/
|
||||||
|
.float traileffectnum; /*can also be set with 'traileffect' from a map editor*/
|
||||||
|
.float emiteffectnum; /*can also be set with 'traileffect' from a map editor*/
|
||||||
|
.vector movement; /*describes which forward/right/up keys the player is holidng*/
|
||||||
|
.entity viewmodelforclient; /*attaches this entity to the specified player's view. invisible to other players*/
|
||||||
|
|
||||||
|
|
||||||
|
//Supported Extension Constants
|
||||||
|
const float MOVETYPE_FOLLOW = 12;
|
||||||
|
const float SOLID_CORPSE = 5;
|
||||||
|
const float FILE_READ = 0;
|
||||||
|
const float FILE_APPEND = 1;
|
||||||
|
const float FILE_WRITE = 2;
|
||||||
|
const float CLIENTTYPE_DISCONNECT = 0;
|
||||||
|
const float CLIENTTYPE_REAL = 1;
|
||||||
|
const float CLIENTTYPE_BOT = 2;
|
||||||
|
const float CLIENTTYPE_NOTCLIENT = 3;
|
||||||
|
const float EF_NOSHADOW = 0x1000;
|
||||||
|
const float MSG_MULTICAST = 4;
|
||||||
|
const float MULTICAST_ALL = MULTICAST_ALL_U;
|
||||||
|
const float MULTICAST_PVS = MULTICAST_PVS_U;
|
||||||
|
const float MULTICAST_ONE = MULTICAST_ONE_U;
|
||||||
|
const float MULTICAST_ALL_R = MULTICAST_ALL_R;
|
||||||
|
const float MULTICAST_PVS_R = MULTICAST_PVS_R;
|
||||||
|
const float MULTICAST_ONE_R = MULTICAST_ONE_R;
|
||||||
|
const float MULTICAST_INIT = MULTICAST_INIT;
|
||||||
|
|
||||||
|
|
||||||
|
//Builtin list
|
||||||
|
vector(vector fwd, optional vector up) vectoangles2 = #51; /*
|
||||||
|
Returns the angles (+x=UP) required to orient an entity to look in the given direction. The 'up' argument is required if you wish to set a roll angle, otherwise it will be limited to just monster-style turning. */
|
||||||
|
|
||||||
|
float(float angle) sin = #60;
|
||||||
|
float(float angle) cos = #61;
|
||||||
|
float(float value) sqrt = #62;
|
||||||
|
void(entity ent, entity ignore) tracetoss = #64;
|
||||||
|
string(entity ent) etos = #65;
|
||||||
|
string(entity e, string key) infokey = #80; /*
|
||||||
|
If e is world, returns the field 'key' from either the serverinfo or the localinfo. If e is a player, returns the value of 'key' from the player's userinfo string. There are a few special exceptions, like 'ip' which is not technically part of the userinfo. */
|
||||||
|
|
||||||
|
float(string) stof = #81;
|
||||||
|
#define unicast(pl,reli) do{msg_entity = pl; multicast('0 0 0', reli?MULITCAST_ONE_R:MULTICAST_ONE);}while(0)
|
||||||
|
void(vector where, float set) multicast = #82; /*
|
||||||
|
Once the MSG_MULTICAST network message buffer has been filled with data, this builtin is used to dispatch it to the given target, filtering by pvs for reduced network bandwidth. */
|
||||||
|
|
||||||
|
void(vector start, vector mins, vector maxs, vector end, float nomonsters, entity ent) tracebox = #90; /*
|
||||||
|
Exactly like traceline, but a box instead of a uselessly thin point. Acceptable sizes are limited by bsp format, q1bsp has strict acceptable size values. */
|
||||||
|
|
||||||
|
vector() randomvec = #91; /*
|
||||||
|
Returns a vector with random values. Each axis is independantly a value between -1 and 1 inclusive. */
|
||||||
|
|
||||||
|
vector(vector org) getlight = #92;
|
||||||
|
float(string cvarname, string defaultvalue) registercvar = #93; /*
|
||||||
|
Creates a new cvar on the fly. If it does not already exist, it will be given the specified value. If it does exist, this is a no-op.
|
||||||
|
This builtin has the limitation that it does not apply to configs or commandlines. Such configs will need to use the set or seta command causing this builtin to be a noop.
|
||||||
|
In engines that support it, you will generally find the autocvar feature easier and more efficient to use. */
|
||||||
|
|
||||||
|
float(float a, float b, ...) min = #94; /*
|
||||||
|
Returns the lowest value of its arguments. */
|
||||||
|
|
||||||
|
float(float a, float b, ...) max = #95; /*
|
||||||
|
Returns the highest value of its arguments. */
|
||||||
|
|
||||||
|
float(float minimum, float val, float maximum) bound = #96; /*
|
||||||
|
Returns val, unless minimum is higher, or maximum is less. */
|
||||||
|
|
||||||
|
float(float value, float exp) pow = #97;
|
||||||
|
#define findentity findfloat
|
||||||
|
entity(entity start, .__variant fld, __variant match) findfloat = #98; /*
|
||||||
|
Equivelent to the find builtin, but instead of comparing strings contents, this builtin compares the raw values. This builtin requires multiple calls in order to scan all entities - set start to the previous call's return value.
|
||||||
|
world is returned when there are no more entities. */
|
||||||
|
|
||||||
|
float(string extname) checkextension = #99; /*
|
||||||
|
Checks for an extension by its name (eg: checkextension("FRIK_FILE") says that its okay to go ahead and use strcat).
|
||||||
|
Use cvar("pr_checkextension") to see if this builtin exists. */
|
||||||
|
|
||||||
|
float(__variant funcref) checkbuiltin = #0; /*
|
||||||
|
Checks to see if the specified builtin is supported/mapped. This is intended as a way to check for #0 functions, allowing for simple single-builtin functions. */
|
||||||
|
|
||||||
|
float(string builtinname) builtin_find = #100; /*
|
||||||
|
Looks to see if the named builtin is valid, and returns the builtin number it exists at. */
|
||||||
|
|
||||||
|
float(float value) anglemod = #102;
|
||||||
|
filestream(string filename, float mode, optional float mmapminsize) fopen = #110; /*
|
||||||
|
Opens a file, typically prefixed with "data/", for either read or write access. */
|
||||||
|
|
||||||
|
void(filestream fhandle) fclose = #111;
|
||||||
|
string(filestream fhandle) fgets = #112; /*
|
||||||
|
Reads a single line out of the file. The new line character is not returned as part of the string. Returns the null string on EOF (use if not(string) to easily test for this, which distinguishes it from the empty string which is returned if the line being read is blank */
|
||||||
|
|
||||||
|
void(filestream fhandle, string s, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6, optional string s7) fputs = #113; /*
|
||||||
|
Writes the given string(s) into the file. For compatibility with fgets, you should ensure that the string is terminated with a \n - this will not otherwise be done for you. It is up to the engine whether dos or unix line endings are actually written. */
|
||||||
|
|
||||||
|
#define ftell fseek //c-compat
|
||||||
|
int(filestream fhandle, optional int newoffset) fseek = #0; /*
|
||||||
|
Changes the current position of the file, if specified. Returns prior position, in bytes. */
|
||||||
|
|
||||||
|
float(string s) strlen = #114;
|
||||||
|
string(string s1, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6, optional string s7, optional string s8) strcat = #115;
|
||||||
|
string(string s, float start, float length) substring = #116;
|
||||||
|
vector(string s) stov = #117;
|
||||||
|
string(string s, ...) strzone = #118; /*
|
||||||
|
Create a semi-permanent copy of a string that only becomes invalid once strunzone is called on the string (instead of when the engine assumes your string has left scope). */
|
||||||
|
|
||||||
|
void(string s) strunzone = #119; /*
|
||||||
|
Destroys a string that was allocated by strunzone. Further references to the string MAY crash the game. */
|
||||||
|
|
||||||
|
float(float number, float quantity) bitshift = #218;
|
||||||
|
void(vector org) te_lightningblood = #219;
|
||||||
|
float(string s1, string sub, optional float startidx) strstrofs = #221; /*
|
||||||
|
Returns the 0-based offset of sub within the s1 string, or -1 if sub is not in s1.
|
||||||
|
If startidx is set, this builtin will ignore matches before that 0-based offset. */
|
||||||
|
|
||||||
|
float(string str, float index) str2chr = #222; /*
|
||||||
|
Retrieves the character value at offset 'index'. */
|
||||||
|
|
||||||
|
string(float chr, ...) chr2str = #223; /*
|
||||||
|
The input floats are considered character values, and are concatenated. */
|
||||||
|
|
||||||
|
string(float pad, string str1, ...) strpad = #225; /*
|
||||||
|
Pads the string with spaces, to ensure its a specific length (so long as a fixed-width font is used, anyway). If pad is negative, the spaces are added on the left. If positive the padding is on the right. */
|
||||||
|
|
||||||
|
#define strcmp strncmp
|
||||||
|
float(string s1, string s2, optional float len, optional float s1ofs, optional float s2ofs) strncmp = #228; /*
|
||||||
|
Compares up to 'len' chars in the two strings. s1ofs allows you to treat s2 as a substring to compare against, or should be 0.
|
||||||
|
Returns 0 if the two strings are equal, a negative value if s1 appears numerically lower, and positive if s1 appears numerically higher. */
|
||||||
|
|
||||||
|
float(string s1, string s2) strcasecmp = #229; /*
|
||||||
|
Compares the two strings without case sensitivity.
|
||||||
|
Returns 0 if they are equal. The sign of the return value may be significant, but should not be depended upon. */
|
||||||
|
|
||||||
|
float(string s1, string s2, float len, optional float s1ofs, optional float s2ofs) strncasecmp = #230; /*
|
||||||
|
Compares up to 'len' chars in the two strings without case sensitivity. s1ofs allows you to treat s2 as a substring to compare against, or should be 0.
|
||||||
|
Returns 0 if they are equal. The sign of the return value may be significant, but should not be depended upon. */
|
||||||
|
|
||||||
|
string(string s) strtrim = #0; /*
|
||||||
|
Trims the whitespace from the start+end of the string. */
|
||||||
|
|
||||||
|
void(vector org, float count) te_bloodqw = #239;
|
||||||
|
float(float a, float n) mod = #245;
|
||||||
|
int(string) stoi = #259; /*
|
||||||
|
Converts the given string into a true integer. Base 8, 10, or 16 is determined based upon the format of the string. */
|
||||||
|
|
||||||
|
string(int) itos = #260; /*
|
||||||
|
Converts the passed true integer into a base10 string. */
|
||||||
|
|
||||||
|
int(string) stoh = #261; /*
|
||||||
|
Reads a base-16 string (with or without 0x prefix) as an integer. Bugs out if given a base 8 or base 10 string. :P */
|
||||||
|
|
||||||
|
string(int) htos = #262; /*
|
||||||
|
Formats an integer as a base16 string, with leading 0s and no prefix. Always returns 8 characters. */
|
||||||
|
|
||||||
|
int(float) ftoi = #0; /*
|
||||||
|
Converts the given float into a true integer without depending on extended qcvm instructions. */
|
||||||
|
|
||||||
|
float(int) itof = #0; /*
|
||||||
|
Converts the given true integer into a float without depending on extended qcvm instructions. */
|
||||||
|
|
||||||
|
#define dotproduct(v1,v2) ((vector)(v1)*(vector)(v2))
|
||||||
|
vector(vector v1, vector v2) crossproduct = #0; /*
|
||||||
|
Small helper function to calculate the crossproduct of two vectors. */
|
||||||
|
|
||||||
|
float(float modidx, string framename) frameforname = #276; /*
|
||||||
|
Looks up a framegroup from a model by name, avoiding the need for hardcoding. Returns -1 on error. */
|
||||||
|
|
||||||
|
float(float modidx, float framenum) frameduration = #277; /*
|
||||||
|
Retrieves the duration (in seconds) of the specified framegroup. */
|
||||||
|
|
||||||
|
void(float buf, float fl) WriteFloat = #280;
|
||||||
|
string(float modidx, float framenum) frametoname = #284;
|
||||||
|
float(string name) checkcommand = #294; /*
|
||||||
|
Checks to see if the supplied name is a valid command, cvar, or alias. Returns 0 if it does not exist. */
|
||||||
|
|
||||||
|
float(string effectname) particleeffectnum = #335; /*
|
||||||
|
Precaches the named particle effect. If your effect name is of the form 'foo.bar' then particles/foo.cfg will be loaded by the client if foo.bar was not already defined.
|
||||||
|
Different engines will have different particle systems, this specifies the QC API only. */
|
||||||
|
|
||||||
|
void(float effectnum, entity ent, vector start, vector end) trailparticles = #336; /*
|
||||||
|
Draws the given effect between the two named points. If ent is not world, distances will be cached in the entity in order to avoid framerate dependancies. The entity is not otherwise used. */
|
||||||
|
|
||||||
|
void(float effectnum, vector origin, optional vector dir, optional float count) pointparticles = #337; /*
|
||||||
|
Spawn a load of particles from the given effect at the given point traveling or aiming along the direction specified. The number of particles are scaled by the count argument. */
|
||||||
|
|
||||||
|
void(string s, ...) print = #339; /*
|
||||||
|
Unconditionally print on the local system's console, even in ssqc (doesn't care about the value of the developer cvar). */
|
||||||
|
|
||||||
|
float(entity ent) wasfreed = #353; /*
|
||||||
|
Quickly check to see if the entity is currently free. This function is only valid during the two-second non-reuse window, after that it may give bad results. Try one second to make it more robust. */
|
||||||
|
|
||||||
|
entity(entity from, optional entity to) copyentity = #400; /*
|
||||||
|
Copies all fields from one entity to another. */
|
||||||
|
|
||||||
|
void(entity ent, float colours) setcolors = #401; /*
|
||||||
|
Changes a player's colours. The bits 0-3 are the lower/trouser colour, bits 4-7 are the upper/shirt colours. */
|
||||||
|
|
||||||
|
entity(.string field, string match) findchain = #402;
|
||||||
|
entity(.float fld, float match) findchainfloat = #403;
|
||||||
|
void(vector org, vector dir, float count) te_blood = #405;
|
||||||
|
void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain = #409;
|
||||||
|
void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow = #410;
|
||||||
|
void(vector org, optional float count) te_gunshot = #418;
|
||||||
|
void(vector org) te_spike = #419;
|
||||||
|
void(vector org) te_superspike = #420;
|
||||||
|
void(vector org) te_explosion = #421;
|
||||||
|
void(vector org) te_tarexplosion = #422;
|
||||||
|
void(vector org) te_wizspike = #423;
|
||||||
|
void(vector org) te_knightspike = #424;
|
||||||
|
void(vector org) te_lavasplash = #425;
|
||||||
|
void(vector org) te_teleport = #426;
|
||||||
|
void(vector org, float color, float colorlength) te_explosion2 = #427;
|
||||||
|
void(entity own, vector start, vector end) te_lightning1 = #428;
|
||||||
|
void(entity own, vector start, vector end) te_lightning2 = #429;
|
||||||
|
void(entity own, vector start, vector end) te_lightning3 = #430;
|
||||||
|
void(entity own, vector start, vector end) te_beam = #431;
|
||||||
|
void(vector dir) vectorvectors = #432;
|
||||||
|
float(entity e, float s) getsurfacenumpoints = #434;
|
||||||
|
vector(entity e, float s, float n) getsurfacepoint = #435;
|
||||||
|
vector(entity e, float s) getsurfacenormal = #436;
|
||||||
|
string(entity e, float s) getsurfacetexture = #437;
|
||||||
|
float(entity e, vector p) getsurfacenearpoint = #438;
|
||||||
|
vector(entity e, float s, vector p) getsurfaceclippedpoint = #439;
|
||||||
|
void(entity e, string s) clientcommand = #440;
|
||||||
|
float(string s) tokenize = #441;
|
||||||
|
string(float n) argv = #442;
|
||||||
|
float() argc = #0;
|
||||||
|
string(string cvarname) cvar_string = #448;
|
||||||
|
entity(entity start, .float fld, float match) findflags = #449;
|
||||||
|
entity(.float fld, float match) findchainflags = #450;
|
||||||
|
void(entity player) dropclient = #453;
|
||||||
|
entity() spawnclient = #454; /*
|
||||||
|
Spawns a dummy player entity.
|
||||||
|
Note that such dummy players will be carried from one map to the next.
|
||||||
|
Warning: DP_SV_CLIENTCOLORS DP_SV_CLIENTNAME are not implemented in quakespasm, so use KRIMZON_SV_PARSECLIENTCOMMAND's clientcommand builtin to change the bot's name/colours/skin/team/etc, in the same way that clients would ask. */
|
||||||
|
|
||||||
|
float(entity client) clienttype = #455;
|
||||||
|
void(float target, string str) WriteUnterminatedString = #456;
|
||||||
|
entity(float entnum) edict_num = #459;
|
||||||
|
strbuf() buf_create = #460;
|
||||||
|
void(strbuf bufhandle) buf_del = #461;
|
||||||
|
float(strbuf bufhandle) buf_getsize = #462;
|
||||||
|
void(strbuf bufhandle_from, strbuf bufhandle_to) buf_copy = #463;
|
||||||
|
void(strbuf bufhandle, float sortprefixlen, float backward) buf_sort = #464;
|
||||||
|
string(strbuf bufhandle, string glue) buf_implode = #465;
|
||||||
|
string(strbuf bufhandle, float string_index) bufstr_get = #466;
|
||||||
|
void(strbuf bufhandle, float string_index, string str) bufstr_set = #467;
|
||||||
|
float(strbuf bufhandle, string str, float order) bufstr_add = #468;
|
||||||
|
void(strbuf bufhandle, float string_index) bufstr_free = #469;
|
||||||
|
float(float s) asin = #471;
|
||||||
|
float(float c) acos = #472;
|
||||||
|
float(float t) atan = #473;
|
||||||
|
float(float c, float s) atan2 = #474;
|
||||||
|
float(float a) tan = #475;
|
||||||
|
string(float uselocaltime, string format, ...) strftime = #478;
|
||||||
|
float(string s, string separator1, ...) tokenizebyseparator = #479;
|
||||||
|
string(string s) strtolower = #480;
|
||||||
|
string(string s) strtoupper = #481;
|
||||||
|
string(string s) cvar_defstring = #482;
|
||||||
|
void(vector origin, string sample, float volume, float attenuation) pointsound = #483;
|
||||||
|
string(string search, string replace, string subject) strreplace = #484;
|
||||||
|
string(string search, string replace, string subject) strireplace = #485;
|
||||||
|
vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
|
||||||
|
float(float caseinsensitive, string s, ...) crc16 = #494;
|
||||||
|
float(string name) cvar_type = #495;
|
||||||
|
float() numentityfields = #496; /*
|
||||||
|
Gives the number of named entity fields. Note that this is not the size of an entity, but rather just the number of unique names (ie: vectors use 4 names rather than 3). */
|
||||||
|
|
||||||
|
float(string fieldname) findentityfield = #0; /*
|
||||||
|
Find a field index by name. */
|
||||||
|
|
||||||
|
typedef .__variant field_t;
|
||||||
|
field_t(float fieldnum) entityfieldref = #0; /*
|
||||||
|
Returns a field value that can be directly used to read entity fields. Be sure to validate the type with entityfieldtype before using. */
|
||||||
|
|
||||||
|
string(float fieldnum) entityfieldname = #497; /*
|
||||||
|
Retrieves the name of the given entity field. */
|
||||||
|
|
||||||
|
float(float fieldnum) entityfieldtype = #498; /*
|
||||||
|
Provides information about the type of the field specified by the field num. Returns one of the EV_ values. */
|
||||||
|
|
||||||
|
string(float fieldnum, entity ent) getentityfieldstring = #499;
|
||||||
|
float(float fieldnum, entity ent, string s) putentityfieldstring = #500;
|
||||||
|
string(string filename, optional float makereferenced) whichpack = #503; /*
|
||||||
|
Returns the pak file name that contains the file specified. progs/player.mdl will generally return something like 'pak0.pak'. If makereferenced is true, clients will automatically be told that the returned package should be pre-downloaded and used, even if allow_download_refpackages is not set. */
|
||||||
|
|
||||||
|
string(string in) uri_escape = #510;
|
||||||
|
string(string in) uri_unescape = #511;
|
||||||
|
float(entity ent) num_for_edict = #512;
|
||||||
|
float(string str) tokenize_console = #514; /*
|
||||||
|
Tokenize a string exactly as the console's tokenizer would do so. The regular tokenize builtin became bastardized for convienient string parsing, which resulted in a large disparity that can be exploited to bypass checks implemented in a naive SV_ParseClientCommand function, therefore you can use this builtin to make sure it exactly matches. */
|
||||||
|
|
||||||
|
float(float idx) argv_start_index = #515; /*
|
||||||
|
Returns the character index that the tokenized arg started at. */
|
||||||
|
|
||||||
|
float(float idx) argv_end_index = #516; /*
|
||||||
|
Returns the character index that the tokenized arg stopped at. */
|
||||||
|
|
||||||
|
string(string cvarname) cvar_description = #518; /*
|
||||||
|
Retrieves the description of a cvar, which might be useful for tooltips or help files. This may still not be useful. */
|
||||||
|
|
||||||
|
float(optional float timetype) gettime = #519;
|
||||||
|
float(float v, optional float base) log = #532; /*
|
||||||
|
Determines the logarithm of the input value according to the specified base. This can be used to calculate how much something was shifted by. */
|
||||||
|
|
||||||
|
float(string filename, strbuf bufhandle) buf_loadfile = #535; /*
|
||||||
|
Appends the named file into a string buffer (which must have been created in advance). The return value merely says whether the file was readable. */
|
||||||
|
|
||||||
|
float(filestream filehandle, strbuf bufhandle, optional float startpos, optional float numstrings) buf_writefile = #536; /*
|
||||||
|
Writes the contents of a string buffer onto the end of the supplied filehandle (you must have already used fopen). Additional optional arguments permit you to constrain the writes to a subsection of the stringbuffer. */
|
||||||
|
|
||||||
|
void(.../*, string funcname*/) callfunction = #605; /*
|
||||||
|
Invokes the named function. The function name is always passed as the last parameter and must always be present. The others are passed to the named function as-is */
|
||||||
|
|
||||||
|
float(string s) isfunction = #607; /*
|
||||||
|
Returns true if the named function exists and can be called with the callfunction builtin. */
|
||||||
|
|
||||||
|
float(entity e, string s, optional float offset) parseentitydata = #613; /*
|
||||||
|
Reads a single entity's fields into an already-spawned entity. s should contain field pairs like in a saved game: {"foo1" "bar" "foo2" "5"}. Returns <=0 on failure, otherwise returns the offset in the string that was read to. */
|
||||||
|
|
||||||
|
string(string fmt, ...) sprintf = #627;
|
||||||
|
float(entity e, float s) getsurfacenumtriangles = #628;
|
||||||
|
vector(entity e, float s, float n) getsurfacetriangle = #629;
|
||||||
|
|
||||||
|
|
||||||
|
//Builtin Stubs List (these are present for simpler compatibility, but not properly supported in QuakeSpasm at this time).
|
||||||
|
/*
|
||||||
|
void(vector org, string modelname, float startframe, float endframe, float framerate) effect = #404;
|
||||||
|
void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower = #406;
|
||||||
|
void(vector org, vector color) te_explosionrgb = #407;
|
||||||
|
void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube = #408;
|
||||||
|
void(vector org, vector vel, float howmany) te_spark = #411;
|
||||||
|
void(vector org) te_gunshotquad = #412;
|
||||||
|
void(vector org) te_spikequad = #413;
|
||||||
|
void(vector org) te_superspikequad = #414;
|
||||||
|
void(vector org) te_explosionquad = #415;
|
||||||
|
void(vector org) te_smallflash = #416;
|
||||||
|
void(vector org, float radius, float lifetime, vector color) te_customflash = #417;
|
||||||
|
void(vector org) te_plasmaburn = #433;
|
||||||
|
void(entity e, entity tagentity, string tagname) setattachment = #443;
|
||||||
|
float(string s) strlennocol = #476;
|
||||||
|
string(string s) strdecolorize = #477;
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//Reset this back to normal.
|
||||||
|
#pragma noref 0
|
|
@ -67,6 +67,25 @@ entity_t **cl_visedicts;
|
||||||
|
|
||||||
extern cvar_t r_lerpmodels, r_lerpmove; //johnfitz
|
extern cvar_t r_lerpmodels, r_lerpmove; //johnfitz
|
||||||
|
|
||||||
|
void CL_ClearTrailStates(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < cl.num_statics; i++)
|
||||||
|
{
|
||||||
|
PScript_DelinkTrailstate(&(cl_static_entities[i].trailstate));
|
||||||
|
PScript_DelinkTrailstate(&(cl_static_entities[i].emitstate));
|
||||||
|
}
|
||||||
|
for (i = 0; i < cl_max_edicts; i++)
|
||||||
|
{
|
||||||
|
PScript_DelinkTrailstate(&(cl_entities[i].trailstate));
|
||||||
|
PScript_DelinkTrailstate(&(cl_entities[i].emitstate));
|
||||||
|
}
|
||||||
|
for (i = 0; i < MAX_BEAMS; i++)
|
||||||
|
{
|
||||||
|
PScript_DelinkTrailstate(&(cl_beams[i].trailstate));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=====================
|
=====================
|
||||||
CL_ClearState
|
CL_ClearState
|
||||||
|
@ -80,6 +99,8 @@ void CL_ClearState (void)
|
||||||
if (!sv.active)
|
if (!sv.active)
|
||||||
Host_ClearMemory ();
|
Host_ClearMemory ();
|
||||||
|
|
||||||
|
CL_ClearTrailStates();
|
||||||
|
|
||||||
// wipe the entire cl structure
|
// wipe the entire cl structure
|
||||||
memset (&cl, 0, sizeof(cl));
|
memset (&cl, 0, sizeof(cl));
|
||||||
|
|
||||||
|
@ -438,15 +459,17 @@ void CL_RelinkEntities (void)
|
||||||
float bobjrotate;
|
float bobjrotate;
|
||||||
vec3_t oldorg;
|
vec3_t oldorg;
|
||||||
dlight_t *dl;
|
dlight_t *dl;
|
||||||
float frametime = cl.time - cl.oldtime;
|
float frametime;
|
||||||
|
|
||||||
|
// determine partial update time
|
||||||
|
frac = CL_LerpPoint ();
|
||||||
|
|
||||||
|
frametime = cl.time - cl.oldtime;
|
||||||
if (frametime < 0)
|
if (frametime < 0)
|
||||||
frametime = 0;
|
frametime = 0;
|
||||||
if (frametime > 0.1)
|
if (frametime > 0.1)
|
||||||
frametime = 0.1;
|
frametime = 0.1;
|
||||||
|
|
||||||
// determine partial update time
|
|
||||||
frac = CL_LerpPoint ();
|
|
||||||
|
|
||||||
if (cl_numvisedicts + 64 > cl_maxvisedicts)
|
if (cl_numvisedicts + 64 > cl_maxvisedicts)
|
||||||
{
|
{
|
||||||
cl_maxvisedicts = cl_maxvisedicts+64;
|
cl_maxvisedicts = cl_maxvisedicts+64;
|
||||||
|
@ -481,7 +504,7 @@ void CL_RelinkEntities (void)
|
||||||
for (i=1,ent=cl_entities+1 ; i<cl.num_entities ; i++,ent++)
|
for (i=1,ent=cl_entities+1 ; i<cl.num_entities ; i++,ent++)
|
||||||
{
|
{
|
||||||
if (!ent->model)
|
if (!ent->model)
|
||||||
{ // empty slot
|
{ // empty slot, ish.
|
||||||
if (ent->forcelink)
|
if (ent->forcelink)
|
||||||
R_RemoveEfrags (ent); // just became empty
|
R_RemoveEfrags (ent); // just became empty
|
||||||
continue;
|
continue;
|
||||||
|
@ -559,10 +582,10 @@ void CL_RelinkEntities (void)
|
||||||
//johnfitz -- assume muzzle flash accompanied by muzzle flare, which looks bad when lerped
|
//johnfitz -- assume muzzle flash accompanied by muzzle flare, which looks bad when lerped
|
||||||
if (r_lerpmodels.value != 2)
|
if (r_lerpmodels.value != 2)
|
||||||
{
|
{
|
||||||
if (ent == &cl_entities[cl.viewentity])
|
if (ent == &cl_entities[cl.viewentity])
|
||||||
cl.viewent.lerpflags |= LERP_RESETANIM|LERP_RESETANIM2; //no lerping for two frames
|
cl.viewent.lerpflags |= LERP_RESETANIM|LERP_RESETANIM2; //no lerping for two frames
|
||||||
else
|
else
|
||||||
ent->lerpflags |= LERP_RESETANIM|LERP_RESETANIM2; //no lerping for two frames
|
ent->lerpflags |= LERP_RESETANIM|LERP_RESETANIM2; //no lerping for two frames
|
||||||
}
|
}
|
||||||
//johnfitz
|
//johnfitz
|
||||||
}
|
}
|
||||||
|
@ -583,18 +606,18 @@ void CL_RelinkEntities (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PSET_SCRIPT
|
#ifdef PSET_SCRIPT
|
||||||
if (ent->model->traileffect >= 0)
|
if (ent->netstate.traileffectnum > 0 && ent->netstate.traileffectnum < MAX_PARTICLETYPES)
|
||||||
{
|
|
||||||
vec3_t axis[3];
|
|
||||||
AngleVectors(ent->angles, axis[0], axis[1], axis[2]);
|
|
||||||
PScript_ParticleTrail(oldorg, ent->origin, ent->model->traileffect, i, axis, &ent->trailstate);
|
|
||||||
}
|
|
||||||
else if (ent->netstate.traileffectnum > 0 && ent->netstate.traileffectnum < MAX_PARTICLETYPES)
|
|
||||||
{
|
{
|
||||||
vec3_t axis[3];
|
vec3_t axis[3];
|
||||||
AngleVectors(ent->angles, axis[0], axis[1], axis[2]);
|
AngleVectors(ent->angles, axis[0], axis[1], axis[2]);
|
||||||
PScript_ParticleTrail(oldorg, ent->origin, cl.particle_precache[ent->netstate.traileffectnum].index, i, axis, &ent->trailstate);
|
PScript_ParticleTrail(oldorg, ent->origin, cl.particle_precache[ent->netstate.traileffectnum].index, i, axis, &ent->trailstate);
|
||||||
}
|
}
|
||||||
|
else if (ent->model->traileffect >= 0)
|
||||||
|
{
|
||||||
|
vec3_t axis[3];
|
||||||
|
AngleVectors(ent->angles, axis[0], axis[1], axis[2]);
|
||||||
|
PScript_ParticleTrail(oldorg, ent->origin, ent->model->traileffect, i, axis, &ent->trailstate);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
if (ent->model->flags & EF_GIB)
|
if (ent->model->flags & EF_GIB)
|
||||||
|
@ -640,9 +663,26 @@ void CL_RelinkEntities (void)
|
||||||
ent->forcelink = false;
|
ent->forcelink = false;
|
||||||
|
|
||||||
#ifdef PSET_SCRIPT
|
#ifdef PSET_SCRIPT
|
||||||
if (ent->model->emiteffect >= 0)
|
if (ent->netstate.emiteffectnum > 0)
|
||||||
{
|
{
|
||||||
PScript_RunParticleEffectState(ent->origin, NULL, frametime, ent->model->emiteffect, &ent->emitstate);
|
vec3_t axis[3];
|
||||||
|
AngleVectors(ent->angles, axis[0], axis[1], axis[2]);
|
||||||
|
if (ent->model->type == mod_alias)
|
||||||
|
axis[0][2] *= -1; //stupid vanilla bug
|
||||||
|
PScript_RunParticleEffectState(ent->origin, axis[0], frametime, cl.particle_precache[ent->netstate.emiteffectnum].index, &ent->emitstate);
|
||||||
|
}
|
||||||
|
else if (ent->model->emiteffect >= 0)
|
||||||
|
{
|
||||||
|
vec3_t axis[3];
|
||||||
|
AngleVectors(ent->angles, axis[0], axis[1], axis[2]);
|
||||||
|
if (ent->model->flags & MOD_EMITFORWARDS)
|
||||||
|
{
|
||||||
|
if (ent->model->type == mod_alias)
|
||||||
|
axis[0][2] *= -1; //stupid vanilla bug
|
||||||
|
}
|
||||||
|
else
|
||||||
|
VectorScale(axis[2], -1, axis[0]);
|
||||||
|
PScript_RunParticleEffectState(ent->origin, axis[0], frametime, ent->model->emiteffect, &ent->emitstate);
|
||||||
if (ent->model->flags & MOD_EMITREPLACE)
|
if (ent->model->flags & MOD_EMITREPLACE)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -374,6 +374,7 @@ static unsigned int CLFTE_ReadDelta(unsigned int entnum, entity_state_t *news, c
|
||||||
|
|
||||||
if (bits & UF_SOLID)
|
if (bits & UF_SOLID)
|
||||||
{ //knowing the size of an entity is important for prediction
|
{ //knowing the size of an entity is important for prediction
|
||||||
|
//without prediction, its a bit pointless.
|
||||||
/*if (cl.protocol_pext2 & PEXT2_NEWSIZEENCODING)
|
/*if (cl.protocol_pext2 & PEXT2_NEWSIZEENCODING)
|
||||||
{
|
{
|
||||||
qbyte enc = MSG_ReadByte();
|
qbyte enc = MSG_ReadByte();
|
||||||
|
@ -464,7 +465,17 @@ static unsigned int CLFTE_ReadDelta(unsigned int entnum, entity_state_t *news, c
|
||||||
/*news->lightpflags =*/ MSG_ReadByte();
|
/*news->lightpflags =*/ MSG_ReadByte();
|
||||||
}
|
}
|
||||||
if (bits & UF_TRAILEFFECT)
|
if (bits & UF_TRAILEFFECT)
|
||||||
news->traileffectnum = MSG_ReadShort();
|
{
|
||||||
|
unsigned short v = MSG_ReadShort();
|
||||||
|
news->emiteffectnum = 0;
|
||||||
|
news->traileffectnum = v & 0x3fff;
|
||||||
|
if (v & 0x8000)
|
||||||
|
news->emiteffectnum = MSG_ReadShort() & 0x3fff;
|
||||||
|
if (news->traileffectnum >= MAX_PARTICLETYPES)
|
||||||
|
news->traileffectnum = 0;
|
||||||
|
if (news->emiteffectnum >= MAX_PARTICLETYPES)
|
||||||
|
news->emiteffectnum = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (bits & UF_COLORMOD)
|
if (bits & UF_COLORMOD)
|
||||||
{
|
{
|
||||||
|
@ -680,13 +691,23 @@ static void CLFTE_ParseEntitiesUpdate(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cl.protocol_pext2 & PEXT2_PREDINFO)
|
if (cl.protocol_pext2 & PEXT2_PREDINFO)
|
||||||
{
|
{ //stats should normally be sent before the entity data.
|
||||||
VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
|
VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
|
||||||
ent = CL_EntityNum(cl.viewentity);
|
ent = CL_EntityNum(cl.viewentity);
|
||||||
cl.mvelocity[0][0] = ent->netstate.velocity[0]*(1/8.0);
|
cl.mvelocity[0][0] = ent->netstate.velocity[0]*(1/8.0);
|
||||||
cl.mvelocity[0][1] = ent->netstate.velocity[1]*(1/8.0);
|
cl.mvelocity[0][1] = ent->netstate.velocity[1]*(1/8.0);
|
||||||
cl.mvelocity[0][2] = ent->netstate.velocity[2]*(1/8.0);
|
cl.mvelocity[0][2] = ent->netstate.velocity[2]*(1/8.0);
|
||||||
cl.onground = (ent->netstate.eflags & EFLAGS_ONGROUND)?true:false;
|
cl.onground = (ent->netstate.eflags & EFLAGS_ONGROUND)?true:false;
|
||||||
|
|
||||||
|
|
||||||
|
cl.punchangle[0] = cl.statsf[STAT_PUNCHANGLE_X];
|
||||||
|
cl.punchangle[1] = cl.statsf[STAT_PUNCHANGLE_Y];
|
||||||
|
cl.punchangle[2] = cl.statsf[STAT_PUNCHANGLE_Z];
|
||||||
|
if (v_punchangles[0][0] != cl.punchangle[0] || v_punchangles[0][1] != cl.punchangle[1] || v_punchangles[0][2] != cl.punchangle[2])
|
||||||
|
{
|
||||||
|
VectorCopy (v_punchangles[0], v_punchangles[1]);
|
||||||
|
VectorCopy (cl.punchangle, v_punchangles[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cl.requestresend)
|
if (!cl.requestresend)
|
||||||
|
@ -1535,6 +1556,10 @@ static void CL_ParseStatic (int version) //johnfitz -- added a parameter
|
||||||
|
|
||||||
// copy it to the current state
|
// copy it to the current state
|
||||||
|
|
||||||
|
ent->netstate = ent->baseline;
|
||||||
|
|
||||||
|
ent->trailstate = NULL;
|
||||||
|
ent->emitstate = NULL;
|
||||||
ent->model = cl.model_precache[ent->baseline.modelindex];
|
ent->model = cl.model_precache[ent->baseline.modelindex];
|
||||||
ent->lerpflags |= LERP_RESETANIM; //johnfitz -- lerping
|
ent->lerpflags |= LERP_RESETANIM; //johnfitz -- lerping
|
||||||
ent->frame = ent->baseline.frame;
|
ent->frame = ent->baseline.frame;
|
||||||
|
@ -1742,7 +1767,8 @@ void CL_ParseServerMessage (void)
|
||||||
else if (cl_shownet.value == 2)
|
else if (cl_shownet.value == 2)
|
||||||
Con_Printf ("------------------\n");
|
Con_Printf ("------------------\n");
|
||||||
|
|
||||||
cl.onground = false; // unless the server says otherwise
|
if (!(cl.protocol_pext2 & PEXT2_PREDINFO))
|
||||||
|
cl.onground = false; // unless the server says otherwise
|
||||||
//
|
//
|
||||||
// parse the message
|
// parse the message
|
||||||
//
|
//
|
||||||
|
|
|
@ -341,6 +341,7 @@ void CL_ParseTEnt (void);
|
||||||
void CL_UpdateTEnts (void);
|
void CL_UpdateTEnts (void);
|
||||||
|
|
||||||
void CL_ClearState (void);
|
void CL_ClearState (void);
|
||||||
|
void CL_ClearTrailStates(void);
|
||||||
|
|
||||||
//
|
//
|
||||||
// cl_demo.c
|
// cl_demo.c
|
||||||
|
|
|
@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
#include "quakedef.h"
|
#include "quakedef.h"
|
||||||
|
|
||||||
|
cvar_t cl_nopext = {"cl_nopext","0",CVAR_NONE}; //Spike -- prevent autodetection of protocol extensions, so that servers fall back to only their base protocol (without needing to reconfigure the server. Requires reconnect.
|
||||||
void Cmd_ForwardToServer (void);
|
void Cmd_ForwardToServer (void);
|
||||||
|
|
||||||
#define MAX_ALIAS_NAME 32
|
#define MAX_ALIAS_NAME 32
|
||||||
|
@ -517,6 +518,8 @@ void Cmd_Init (void)
|
||||||
Cmd_AddCommand ("alias",Cmd_Alias_f);
|
Cmd_AddCommand ("alias",Cmd_Alias_f);
|
||||||
Cmd_AddCommand ("cmd", Cmd_ForwardToServer);
|
Cmd_AddCommand ("cmd", Cmd_ForwardToServer);
|
||||||
Cmd_AddCommand ("wait", Cmd_Wait_f);
|
Cmd_AddCommand ("wait", Cmd_Wait_f);
|
||||||
|
|
||||||
|
Cvar_RegisterVariable (&cl_nopext);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -793,7 +796,7 @@ void Cmd_ForwardToServer (void)
|
||||||
SZ_Print (&cls.message, "protocols 15 666 999");
|
SZ_Print (&cls.message, "protocols 15 666 999");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!strcmp(Cmd_Args(), "pext"))
|
if (!strcmp(Cmd_Args(), "pext") && !cl_nopext.value)
|
||||||
{ //server asked us for a key+value list of the extensions+attributes we support
|
{ //server asked us for a key+value list of the extensions+attributes we support
|
||||||
SZ_Print (&cls.message, va("pext %#x %#x", PROTOCOL_FTE_PEXT2, PEXT2_SUPPORTED_CLIENT));
|
SZ_Print (&cls.message, va("pext %#x %#x", PROTOCOL_FTE_PEXT2, PEXT2_SUPPORTED_CLIENT));
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -192,6 +192,7 @@ void Mod_ClearAll (void)
|
||||||
{
|
{
|
||||||
mod->needload = true;
|
mod->needload = true;
|
||||||
TexMgr_FreeTexturesForOwner (mod); //johnfitz
|
TexMgr_FreeTexturesForOwner (mod); //johnfitz
|
||||||
|
PScript_ClearSurfaceParticles(mod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,7 +207,10 @@ void Mod_ResetAll (void)
|
||||||
for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
|
for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
|
||||||
{
|
{
|
||||||
if (!mod->needload) //otherwise Mod_ClearAll() did it already
|
if (!mod->needload) //otherwise Mod_ClearAll() did it already
|
||||||
|
{
|
||||||
TexMgr_FreeTexturesForOwner (mod);
|
TexMgr_FreeTexturesForOwner (mod);
|
||||||
|
PScript_ClearSurfaceParticles(mod);
|
||||||
|
}
|
||||||
memset(mod, 0, sizeof(qmodel_t));
|
memset(mod, 0, sizeof(qmodel_t));
|
||||||
}
|
}
|
||||||
mod_numknown = 0;
|
mod_numknown = 0;
|
||||||
|
@ -288,26 +292,28 @@ qmodel_t *Mod_LoadModel (qmodel_t *mod, qboolean crash)
|
||||||
return mod; // not cached at all
|
return mod; // not cached at all
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// because the world is so huge, load it one piece at a time
|
|
||||||
//
|
|
||||||
if (!crash)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// load the file
|
// load the file
|
||||||
//
|
//
|
||||||
buf = COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf), & mod->path_id);
|
if (*mod->name == '*')
|
||||||
|
buf = NULL;
|
||||||
|
else
|
||||||
|
buf = COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf), & mod->path_id);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
{
|
{
|
||||||
if (crash)
|
if (crash)
|
||||||
Sys_Error ("Mod_LoadModel: %s not found", mod->name); //johnfitz -- was "Mod_NumForName"
|
Sys_Error ("Mod_LoadModel: %s not found", mod->name); //johnfitz -- was "Mod_NumForName"
|
||||||
|
else if (mod->name[0] == '*' && (mod->name[1] < '0' || mod->name[1] > '9'))
|
||||||
|
; //*foo doesn't warn, unless its *NUM. inline models. gah.
|
||||||
|
else
|
||||||
|
Con_Warning("Mod_LoadModel: %s not found\n", mod->name);
|
||||||
|
|
||||||
//avoid crashes
|
//avoid crashes
|
||||||
mod->needload = false;
|
mod->needload = false;
|
||||||
mod->type = mod_ext_invalid;
|
mod->type = mod_ext_invalid;
|
||||||
|
mod->flags = 0;
|
||||||
|
|
||||||
|
Mod_SetExtraFlags (mod); //johnfitz. spike -- moved this to be generic, because most of the flags are anyway.
|
||||||
return mod;
|
return mod;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -401,6 +401,7 @@ typedef enum {mod_brush, mod_sprite, mod_alias, mod_ext_invalid} modtype_t;
|
||||||
//johnfitz
|
//johnfitz
|
||||||
//spike -- added this for particle stuff
|
//spike -- added this for particle stuff
|
||||||
#define MOD_EMITREPLACE 2048 //particle effect completely replaces the model (for flames or whatever).
|
#define MOD_EMITREPLACE 2048 //particle effect completely replaces the model (for flames or whatever).
|
||||||
|
#define MOD_EMITFORWARDS 4096 //particle effect is emitted forwards, rather than downwards. why down? good question.
|
||||||
|
|
||||||
typedef struct qmodel_s
|
typedef struct qmodel_s
|
||||||
{
|
{
|
||||||
|
@ -418,6 +419,9 @@ typedef struct qmodel_s
|
||||||
#ifdef PSET_SCRIPT
|
#ifdef PSET_SCRIPT
|
||||||
int emiteffect; //spike -- this effect is emitted per-frame by entities with this model
|
int emiteffect; //spike -- this effect is emitted per-frame by entities with this model
|
||||||
int traileffect; //spike -- this effect is used when entities move
|
int traileffect; //spike -- this effect is used when entities move
|
||||||
|
struct skytris_s *skytris; //spike -- surface-based particle emission for this model
|
||||||
|
struct skytriblock_s *skytrimem; //spike -- surface-based particle emission for this model (for better cache performance+less allocs)
|
||||||
|
double skytime; //doesn't really cope with multiples. oh well...
|
||||||
#endif
|
#endif
|
||||||
//
|
//
|
||||||
// volume occupied by the model graphics
|
// volume occupied by the model graphics
|
||||||
|
|
|
@ -238,9 +238,30 @@ void R_StoreEfrags (efrag_t **ppefrag)
|
||||||
pent->visframe = r_framecount;
|
pent->visframe = r_framecount;
|
||||||
|
|
||||||
#ifdef PSET_SCRIPT
|
#ifdef PSET_SCRIPT
|
||||||
if (pent->model->emiteffect >= 0)
|
if (pent->netstate.emiteffectnum > 0)
|
||||||
{
|
{
|
||||||
PScript_RunParticleEffectState(pent->origin, NULL, ((host_frametime>0.1)?0.1:host_frametime), pent->model->emiteffect, &pent->emitstate);
|
float t = cl.time-cl.oldtime;
|
||||||
|
vec3_t axis[3];
|
||||||
|
if (t < 0) t = 0; else if (t > 0.1) t= 0.1;
|
||||||
|
AngleVectors(pent->angles, axis[0], axis[1], axis[2]);
|
||||||
|
if (pent->model->type == mod_alias)
|
||||||
|
axis[0][2] *= -1; //stupid vanilla bug
|
||||||
|
PScript_RunParticleEffectState(pent->origin, axis[0], t, cl.particle_precache[pent->netstate.emiteffectnum].index, &pent->emitstate);
|
||||||
|
}
|
||||||
|
else if (pent->model->emiteffect >= 0)
|
||||||
|
{
|
||||||
|
float t = cl.time-cl.oldtime;
|
||||||
|
vec3_t axis[3];
|
||||||
|
if (t < 0) t = 0; else if (t > 0.1) t= 0.1;
|
||||||
|
AngleVectors(pent->angles, axis[0], axis[1], axis[2]);
|
||||||
|
if (pent->model->flags & MOD_EMITFORWARDS)
|
||||||
|
{
|
||||||
|
if (pent->model->type == mod_alias)
|
||||||
|
axis[0][2] *= -1; //stupid vanilla bug
|
||||||
|
}
|
||||||
|
else
|
||||||
|
VectorScale(axis[2], -1, axis[0]);
|
||||||
|
PScript_RunParticleEffectState(pent->origin, axis[0], t, pent->model->emiteffect, &pent->emitstate);
|
||||||
if (pent->model->flags & MOD_EMITREPLACE)
|
if (pent->model->flags & MOD_EMITREPLACE)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,8 +112,10 @@ int PScript_FindParticleType(const char *fullname);
|
||||||
int PScript_RunParticleEffectTypeString (vec3_t org, vec3_t dir, float count, const char *name);
|
int PScript_RunParticleEffectTypeString (vec3_t org, vec3_t dir, float count, const char *name);
|
||||||
int PScript_EntParticleTrail(vec3_t oldorg, entity_t *ent, const char *name);
|
int PScript_EntParticleTrail(vec3_t oldorg, entity_t *ent, const char *name);
|
||||||
int PScript_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count);
|
int PScript_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count);
|
||||||
|
void PScript_DelinkTrailstate(struct trailstate_s **tsk);
|
||||||
void PScript_ClearParticles (void);
|
void PScript_ClearParticles (void);
|
||||||
void PScript_UpdateModelEffects(qmodel_t *mod);
|
void PScript_UpdateModelEffects(qmodel_t *mod);
|
||||||
|
void PScript_ClearSurfaceParticles(qmodel_t *mod); //model is being unloaded.
|
||||||
#else
|
#else
|
||||||
#define PScript_RunParticleEffectState(o,d,c,t,s) true
|
#define PScript_RunParticleEffectState(o,d,c,t,s) true
|
||||||
#define PScript_RunParticleEffectTypeString(o,d,c,n) true //just unconditionally returns an error
|
#define PScript_RunParticleEffectTypeString(o,d,c,n) true //just unconditionally returns an error
|
||||||
|
@ -121,6 +123,8 @@ void PScript_UpdateModelEffects(qmodel_t *mod);
|
||||||
#define PScript_ParticleTrail(o,e,t,d,a,s) true
|
#define PScript_ParticleTrail(o,e,t,d,a,s) true
|
||||||
#define PScript_EntParticleTrail(o,e,n) true
|
#define PScript_EntParticleTrail(o,e,n) true
|
||||||
#define PScript_RunParticleEffect(o,d,p,c) true
|
#define PScript_RunParticleEffect(o,d,p,c) true
|
||||||
|
#define PScript_ClearSurfaceParticles(m)
|
||||||
|
#define PScript_DelinkTrailstate(tsp)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//====================================================
|
//====================================================
|
||||||
|
|
|
@ -556,6 +556,8 @@ void Host_ClearMemory (void)
|
||||||
Hunk_FreeToLowMark (host_hunklevel);
|
Hunk_FreeToLowMark (host_hunklevel);
|
||||||
cls.signon = 0;
|
cls.signon = 0;
|
||||||
free(sv.edicts); // ericw -- sv.edicts switched to use malloc()
|
free(sv.edicts); // ericw -- sv.edicts switched to use malloc()
|
||||||
|
cl_max_edicts = 0; // Spike -- paranoia
|
||||||
|
cl_entities = NULL;
|
||||||
memset (&sv, 0, sizeof(sv));
|
memset (&sv, 0, sizeof(sv));
|
||||||
memset (&cl, 0, sizeof(cl));
|
memset (&cl, 0, sizeof(cl));
|
||||||
}
|
}
|
||||||
|
|
|
@ -487,7 +487,7 @@ void Host_Status_f (void)
|
||||||
j++;
|
j++;
|
||||||
if (j)
|
if (j)
|
||||||
print_fn ( "effects: %i/%i\n", j, MAX_PARTICLETYPES-1);
|
print_fn ( "effects: %i/%i\n", j, MAX_PARTICLETYPES-1);
|
||||||
for (i = 1,j=0; i < sv.max_edicts; i++)
|
for (i = 1,j=1; i < sv.num_edicts; i++)
|
||||||
if (!sv.edicts[i].free)
|
if (!sv.edicts[i].free)
|
||||||
j++;
|
j++;
|
||||||
print_fn ( "entities:%i/%i\n", j, sv.max_edicts);
|
print_fn ( "entities:%i/%i\n", j, sv.max_edicts);
|
||||||
|
|
|
@ -48,7 +48,7 @@ static int droppedDatagrams;
|
||||||
//we additionally look for 'DarkPlaces-Quake' servers too, because we can, but most of those servers will be using dpp7 and will (safely) not respond to our ccreq_server_info requests.
|
//we additionally look for 'DarkPlaces-Quake' servers too, because we can, but most of those servers will be using dpp7 and will (safely) not respond to our ccreq_server_info requests.
|
||||||
//we are not visible to DarkPlaces users - dp does not support fitz666 so that's not a viable option, at least by default, feel free to switch the order if you also change sv_protocol back to 15.
|
//we are not visible to DarkPlaces users - dp does not support fitz666 so that's not a viable option, at least by default, feel free to switch the order if you also change sv_protocol back to 15.
|
||||||
cvar_t sv_reportheartbeats = {"sv_reportheartbeats", "0"};
|
cvar_t sv_reportheartbeats = {"sv_reportheartbeats", "0"};
|
||||||
cvar_t sv_public = {"sv_public", "0"};
|
cvar_t sv_public = {"sv_public", NULL};
|
||||||
cvar_t com_protocolname = {"com_protocolname", "FTE-Quake DarkPlaces-Quake"};
|
cvar_t com_protocolname = {"com_protocolname", "FTE-Quake DarkPlaces-Quake"};
|
||||||
cvar_t net_masters[] =
|
cvar_t net_masters[] =
|
||||||
{
|
{
|
||||||
|
@ -1441,7 +1441,7 @@ static void _Datagram_ServerControlPacket (sys_socket_t acceptsock, struct qsock
|
||||||
if (s->disconnected)
|
if (s->disconnected)
|
||||||
continue;
|
continue;
|
||||||
ret = dfunc.AddrCompare(clientaddr, &s->addr);
|
ret = dfunc.AddrCompare(clientaddr, &s->addr);
|
||||||
if (ret >= 0)
|
if (ret == 0)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
|
@ -186,7 +186,10 @@ const char *NET_QSocketGetMaskedAddressString (const qsocket_t *s)
|
||||||
}
|
}
|
||||||
qboolean NET_QSocketGetProQuakeAngleHack(const qsocket_t *s)
|
qboolean NET_QSocketGetProQuakeAngleHack(const qsocket_t *s)
|
||||||
{
|
{
|
||||||
return s->proquake_angle_hack;
|
if (s && !s->disconnected)
|
||||||
|
return s->proquake_angle_hack;
|
||||||
|
else
|
||||||
|
return false; //happens with demos
|
||||||
}
|
}
|
||||||
void NET_QSocketSetMSS(qsocket_t *s, int mss)
|
void NET_QSocketSetMSS(qsocket_t *s, int mss)
|
||||||
{
|
{
|
||||||
|
|
|
@ -536,6 +536,12 @@ int UDP_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
|
||||||
((struct sockaddr_in6 *)addr2)->sin6_port)
|
((struct sockaddr_in6 *)addr2)->sin6_port)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
if (((struct sockaddr_in6 *)addr1)->sin6_scope_id &&
|
||||||
|
((struct sockaddr_in6 *)addr2)->sin6_scope_id &&
|
||||||
|
((struct sockaddr_in6 *)addr1)->sin6_scope_id !=
|
||||||
|
((struct sockaddr_in6 *)addr2)->sin6_scope_id) //the ipv6 scope id is for use with link-local addresses, to identify the specific interface.
|
||||||
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -1095,6 +1095,31 @@ static void PF_precache_sound (void)
|
||||||
PR_RunError ("PF_precache_sound: overflow");
|
PR_RunError ("PF_precache_sound: overflow");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SV_Precache_Model(const char *s)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < MAX_MODELS; i++)
|
||||||
|
{
|
||||||
|
if (!sv.model_precache[i])
|
||||||
|
{
|
||||||
|
if (sv.state != ss_loading)
|
||||||
|
{
|
||||||
|
//let existing clients know about it
|
||||||
|
MSG_WriteByte(&sv.reliable_datagram, svcdp_precache);
|
||||||
|
MSG_WriteShort(&sv.reliable_datagram, i|0x8000);
|
||||||
|
MSG_WriteString(&sv.reliable_datagram, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
sv.model_precache[i] = s;
|
||||||
|
sv.models[i] = Mod_ForName (s, i==1);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
if (!strcmp(sv.model_precache[i], s))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void PF_precache_model (void)
|
static void PF_precache_model (void)
|
||||||
{
|
{
|
||||||
const char *s;
|
const char *s;
|
||||||
|
@ -1553,9 +1578,9 @@ static void PF_WriteEntity (void)
|
||||||
|
|
||||||
static void PF_makestatic (void)
|
static void PF_makestatic (void)
|
||||||
{
|
{
|
||||||
|
eval_t *val;
|
||||||
|
entity_state_t *st;
|
||||||
edict_t *ent;
|
edict_t *ent;
|
||||||
int i;
|
|
||||||
int bits = 0; //johnfitz -- PROTOCOL_FITZQUAKE
|
|
||||||
|
|
||||||
ent = G_EDICT(OFS_PARM0);
|
ent = G_EDICT(OFS_PARM0);
|
||||||
|
|
||||||
|
@ -1566,56 +1591,29 @@ static void PF_makestatic (void)
|
||||||
}
|
}
|
||||||
//johnfitz
|
//johnfitz
|
||||||
|
|
||||||
//johnfitz -- PROTOCOL_FITZQUAKE
|
if (sv.num_statics == sv.max_statics)
|
||||||
if (sv.protocol == PROTOCOL_NETQUAKE)
|
PR_RunError ("PF_makestatic: Too many static entities");
|
||||||
{
|
st = &sv.static_entities[sv.num_statics];
|
||||||
if (SV_ModelIndex(PR_GetString(ent->v.model)) & 0xFF00 || (int)(ent->v.frame) & 0xFF00)
|
memset(st, 0, sizeof(*st));
|
||||||
{
|
VectorCopy(ent->v.origin, st->origin);
|
||||||
ED_Free (ent);
|
VectorCopy(ent->v.angles, st->angles);
|
||||||
return; //can't display the correct model & frame, so don't show it at all
|
st->modelindex = SV_ModelIndex(PR_GetString(ent->v.model)); //o.O Why does QuakeSpasm use model instead of modelindex?
|
||||||
}
|
st->frame = ent->v.frame;
|
||||||
}
|
st->effects = ent->v.effects;
|
||||||
|
st->colormap = ent->v.colormap;
|
||||||
|
st->skin = ent->v.skin;
|
||||||
|
if ((val = GetEdictFieldValue(ent, pr_extfields.alpha)))
|
||||||
|
st->alpha = ENTALPHA_ENCODE(val->_float);
|
||||||
else
|
else
|
||||||
{
|
st->alpha = ent->alpha;
|
||||||
if (SV_ModelIndex(PR_GetString(ent->v.model)) & 0xFF00)
|
// st->pmovetype = ent->v.pmovetype;
|
||||||
bits |= B_LARGEMODEL;
|
if ((val = GetEdictFieldValue(ent, pr_extfields.traileffectnum)))
|
||||||
if ((int)(ent->v.frame) & 0xFF00)
|
st->traileffectnum = val->_float;
|
||||||
bits |= B_LARGEFRAME;
|
if ((val = GetEdictFieldValue(ent, pr_extfields.emiteffectnum)))
|
||||||
if (ent->alpha != ENTALPHA_DEFAULT)
|
st->emiteffectnum = val->_float;
|
||||||
bits |= B_ALPHA;
|
// VectorScale(ent->v.velocity, 8, st->velocity);
|
||||||
}
|
// st->eflags = ent->v.eflags;
|
||||||
|
sv.num_statics++;
|
||||||
if (bits)
|
|
||||||
{
|
|
||||||
MSG_WriteByte (&sv.signon, svc_spawnstatic2);
|
|
||||||
MSG_WriteByte (&sv.signon, bits);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
MSG_WriteByte (&sv.signon, svc_spawnstatic);
|
|
||||||
|
|
||||||
if (bits & B_LARGEMODEL)
|
|
||||||
MSG_WriteShort (&sv.signon, SV_ModelIndex(PR_GetString(ent->v.model)));
|
|
||||||
else
|
|
||||||
MSG_WriteByte (&sv.signon, SV_ModelIndex(PR_GetString(ent->v.model)));
|
|
||||||
|
|
||||||
if (bits & B_LARGEFRAME)
|
|
||||||
MSG_WriteShort (&sv.signon, ent->v.frame);
|
|
||||||
else
|
|
||||||
MSG_WriteByte (&sv.signon, ent->v.frame);
|
|
||||||
//johnfitz
|
|
||||||
|
|
||||||
MSG_WriteByte (&sv.signon, ent->v.colormap);
|
|
||||||
MSG_WriteByte (&sv.signon, ent->v.skin);
|
|
||||||
for (i = 0; i < 3; i++)
|
|
||||||
{
|
|
||||||
MSG_WriteCoord(&sv.signon, ent->v.origin[i], sv.protocolflags);
|
|
||||||
MSG_WriteAngle(&sv.signon, ent->v.angles[i], sv.protocolflags);
|
|
||||||
}
|
|
||||||
|
|
||||||
//johnfitz -- PROTOCOL_FITZQUAKE
|
|
||||||
if (bits & B_ALPHA)
|
|
||||||
MSG_WriteByte (&sv.signon, ent->alpha);
|
|
||||||
//johnfitz
|
|
||||||
|
|
||||||
// throw the entity away now
|
// throw the entity away now
|
||||||
ED_Free (ent);
|
ED_Free (ent);
|
||||||
|
@ -1669,6 +1667,25 @@ void PF_Fixme (void);
|
||||||
// PR_RunError ("unimplemented builtin");
|
// PR_RunError ("unimplemented builtin");
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
void PR_spawnfunc_misc_model(edict_t *self)
|
||||||
|
{
|
||||||
|
eval_t *val;
|
||||||
|
if (!self->v.model && (val = GetEdictFieldValue(self, ED_FindFieldOffset("mdl"))))
|
||||||
|
self->v.model = val->string;
|
||||||
|
if (!*PR_GetString(self->v.model)) //must have a model, because otherwise various things will assume its not valid at all.
|
||||||
|
self->v.model = PR_SetEngineString("*null");
|
||||||
|
|
||||||
|
if (self->v.angles[1] < 0) //mimic AD. shame there's no avelocity clientside.
|
||||||
|
self->v.angles[1] = (rand()*(360.0f/RAND_MAX));
|
||||||
|
|
||||||
|
//make sure the model is precached, to avoid errors.
|
||||||
|
G_INT(OFS_PARM0) = self->v.model;
|
||||||
|
PF_precache_model();
|
||||||
|
|
||||||
|
//and lets just call makestatic instead of worrying if it'll interfere with the rest of the qc.
|
||||||
|
G_INT(OFS_PARM0) = EDICT_TO_PROG(self);
|
||||||
|
PF_makestatic();
|
||||||
|
}
|
||||||
|
|
||||||
static builtin_t pr_builtin[] =
|
static builtin_t pr_builtin[] =
|
||||||
{
|
{
|
||||||
|
|
|
@ -835,6 +835,7 @@ const char *ED_ParseEdict (const char *data, edict_t *ent)
|
||||||
char keyname[256];
|
char keyname[256];
|
||||||
qboolean anglehack, init;
|
qboolean anglehack, init;
|
||||||
int n;
|
int n;
|
||||||
|
eval_t *val;
|
||||||
|
|
||||||
init = false;
|
init = false;
|
||||||
|
|
||||||
|
@ -896,11 +897,26 @@ const char *ED_ParseEdict (const char *data, edict_t *ent)
|
||||||
ent->alpha = ENTALPHA_ENCODE(atof(com_token));
|
ent->alpha = ENTALPHA_ENCODE(atof(com_token));
|
||||||
//johnfitz
|
//johnfitz
|
||||||
|
|
||||||
|
//spike -- hacks to support func_illusionary with all sorts of mdls, and various particle effects
|
||||||
|
if (!strcmp(keyname, "model") && sv.state == ss_loading)
|
||||||
|
/*ent->v.modelindex = */SV_Precache_Model(com_token);
|
||||||
|
//spike
|
||||||
|
|
||||||
key = ED_FindField (keyname);
|
key = ED_FindField (keyname);
|
||||||
if (!key)
|
if (!key)
|
||||||
{
|
{
|
||||||
|
if (!strcmp(keyname, "traileffect") && sv.state == ss_loading)
|
||||||
|
{
|
||||||
|
if ((val = GetEdictFieldValue(ent, pr_extfields.traileffectnum)))
|
||||||
|
val->_float = PF_SV_ForceParticlePrecache(com_token);
|
||||||
|
}
|
||||||
|
else if (!strcmp(keyname, "emiteffect") && sv.state == ss_loading)
|
||||||
|
{
|
||||||
|
if ((val = GetEdictFieldValue(ent, pr_extfields.emiteffectnum)))
|
||||||
|
val->_float = PF_SV_ForceParticlePrecache(com_token);
|
||||||
|
}
|
||||||
//johnfitz -- HACK -- suppress error becuase fog/sky/alpha fields might not be mentioned in defs.qc
|
//johnfitz -- HACK -- suppress error becuase fog/sky/alpha fields might not be mentioned in defs.qc
|
||||||
if (strncmp(keyname, "sky", 3) && strcmp(keyname, "fog") && strcmp(keyname, "alpha"))
|
else if (strncmp(keyname, "sky", 3) && strcmp(keyname, "fog") && strcmp(keyname, "alpha"))
|
||||||
Con_DPrintf ("\"%s\" is not a field\n", keyname); //johnfitz -- was Con_Printf
|
Con_DPrintf ("\"%s\" is not a field\n", keyname); //johnfitz -- was Con_Printf
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1006,9 +1022,15 @@ void ED_LoadFromFile (const char *data)
|
||||||
|
|
||||||
if (!func)
|
if (!func)
|
||||||
{
|
{
|
||||||
Con_SafePrintf ("No spawn function for:\n"); //johnfitz -- was Con_Printf
|
const char *classname = PR_GetString(ent->v.classname);
|
||||||
ED_Print (ent);
|
if (!strcmp(classname, "misc_model"))
|
||||||
ED_Free (ent);
|
PR_spawnfunc_misc_model(ent);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Con_SafePrintf ("No spawn function for:\n"); //johnfitz -- was Con_Printf
|
||||||
|
ED_Print (ent);
|
||||||
|
ED_Free (ent);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1111,18 +1133,25 @@ void PR_LoadProgs (void)
|
||||||
pr_fielddefs[i].s_name = LittleLong (pr_fielddefs[i].s_name);
|
pr_fielddefs[i].s_name = LittleLong (pr_fielddefs[i].s_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < progs->numglobals; i++)
|
||||||
|
((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
|
||||||
|
|
||||||
//spike: detect extended fields from progs
|
//spike: detect extended fields from progs
|
||||||
pr_extfields.items2 = ED_FindFieldOffset("items2");
|
pr_extfields.items2 = ED_FindFieldOffset("items2");
|
||||||
pr_extfields.gravity = ED_FindFieldOffset("gravity");
|
pr_extfields.gravity = ED_FindFieldOffset("gravity");
|
||||||
pr_extfields.alpha = ED_FindFieldOffset("alpha");
|
pr_extfields.alpha = ED_FindFieldOffset("alpha");
|
||||||
pr_extfields.movement = ED_FindFieldOffset("movement");
|
pr_extfields.movement = ED_FindFieldOffset("movement");
|
||||||
pr_extfields.traileffectnum = ED_FindFieldOffset("traileffectnum");
|
pr_extfields.traileffectnum = ED_FindFieldOffset("traileffectnum");
|
||||||
|
pr_extfields.emiteffectnum = ED_FindFieldOffset("emiteffectnum");
|
||||||
pr_extfields.viewmodelforclient = ED_FindFieldOffset("viewmodelforclient");
|
pr_extfields.viewmodelforclient = ED_FindFieldOffset("viewmodelforclient");
|
||||||
|
|
||||||
for (i = 0; i < progs->numglobals; i++)
|
i = progs->entityfields;
|
||||||
((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
|
if (pr_extfields.emiteffectnum < 0)
|
||||||
|
pr_extfields.emiteffectnum = i++;
|
||||||
|
if (pr_extfields.traileffectnum < 0)
|
||||||
|
pr_extfields.traileffectnum = i++;
|
||||||
|
|
||||||
pr_edict_size = progs->entityfields * 4 + sizeof(edict_t) - sizeof(entvars_t);
|
pr_edict_size = i * 4 + sizeof(edict_t) - sizeof(entvars_t);
|
||||||
// round off to next highest whole word address (esp for Alpha)
|
// round off to next highest whole word address (esp for Alpha)
|
||||||
// this ensures that pointers in the engine data area are always
|
// this ensures that pointers in the engine data area are always
|
||||||
// properly aligned
|
// properly aligned
|
||||||
|
|
|
@ -2125,9 +2125,20 @@ static qboolean QC_FixFileName(const char *name, const char **result, const char
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct
|
//small note on access modes:
|
||||||
|
//when reading, we fopen files inside paks, for compat with (crappy non-zip-compatible) filesystem code
|
||||||
|
//when writing, we directly fopen the file such that it can never be inside a pak.
|
||||||
|
//this means that we need to take care when reading in order to detect EOF properly.
|
||||||
|
//writing doesn't need anything like that, so it can just dump stuff out, but we do need to ensure that the modes don't get mixed up, because trying to read from a writable file will not do what you would expect.
|
||||||
|
//even libc mandates a seek between reading+writing, so no great loss there.
|
||||||
|
static struct qcfile_s
|
||||||
{
|
{
|
||||||
|
char cache[1024];
|
||||||
|
int cacheoffset, cachesize;
|
||||||
FILE *file;
|
FILE *file;
|
||||||
|
int fileoffset;
|
||||||
|
int filesize;
|
||||||
|
int filebase; //the offset of the file inside a pak
|
||||||
int mode;
|
int mode;
|
||||||
} *qcfiles;
|
} *qcfiles;
|
||||||
static size_t qcfiles_max;
|
static size_t qcfiles_max;
|
||||||
|
@ -2140,6 +2151,7 @@ static void PF_fopen(void)
|
||||||
FILE *file;
|
FILE *file;
|
||||||
size_t i;
|
size_t i;
|
||||||
char name[MAX_OSPATH];
|
char name[MAX_OSPATH];
|
||||||
|
int filesize = 0;
|
||||||
|
|
||||||
G_FLOAT(OFS_RETURN) = -1; //assume failure
|
G_FLOAT(OFS_RETURN) = -1; //assume failure
|
||||||
|
|
||||||
|
@ -2155,9 +2167,9 @@ static void PF_fopen(void)
|
||||||
switch(fmode)
|
switch(fmode)
|
||||||
{
|
{
|
||||||
case 0: //read
|
case 0: //read
|
||||||
COM_FOpenFile (fname, &file, NULL);
|
filesize = COM_FOpenFile (fname, &file, NULL);
|
||||||
if (!file && fallback)
|
if (!file && fallback)
|
||||||
COM_FOpenFile (fallback, &file, NULL);
|
filesize = COM_FOpenFile (fallback, &file, NULL);
|
||||||
break;
|
break;
|
||||||
case 1: //append
|
case 1: //append
|
||||||
q_snprintf (name, sizeof(name), "%s/%s", com_gamedir, fname);
|
q_snprintf (name, sizeof(name), "%s/%s", com_gamedir, fname);
|
||||||
|
@ -2185,8 +2197,13 @@ static void PF_fopen(void)
|
||||||
if (!qcfiles[i].file)
|
if (!qcfiles[i].file)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
qcfiles[i].filebase = ftell(file);
|
||||||
qcfiles[i].file = file;
|
qcfiles[i].file = file;
|
||||||
qcfiles[i].mode = fmode;
|
qcfiles[i].mode = fmode;
|
||||||
|
//reading needs size info
|
||||||
|
qcfiles[i].filesize = filesize;
|
||||||
|
//clear the read cache.
|
||||||
|
qcfiles[i].fileoffset = qcfiles[i].cacheoffset = qcfiles[i].cachesize = 0;
|
||||||
|
|
||||||
G_FLOAT(OFS_RETURN) = i+QC_FILE_BASE;
|
G_FLOAT(OFS_RETURN) = i+QC_FILE_BASE;
|
||||||
}
|
}
|
||||||
|
@ -2198,20 +2215,45 @@ static void PF_fgets(void)
|
||||||
Con_Warning("PF_fgets: invalid file handle\n");
|
Con_Warning("PF_fgets: invalid file handle\n");
|
||||||
else if (!qcfiles[fileid].file)
|
else if (!qcfiles[fileid].file)
|
||||||
Con_Warning("PF_fgets: file not open\n");
|
Con_Warning("PF_fgets: file not open\n");
|
||||||
|
else if (qcfiles[fileid].mode != 0)
|
||||||
|
Con_Warning("PF_fgets: file not open for reading\n");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
struct qcfile_s *f = &qcfiles[fileid];
|
||||||
char *ret = PR_GetTempString();
|
char *ret = PR_GetTempString();
|
||||||
char *end;
|
char *s = ret;
|
||||||
if (fgets(ret, STRINGTEMP_LENGTH, qcfiles[fileid].file))
|
char *end = ret+STRINGTEMP_LENGTH;
|
||||||
|
for (;;)
|
||||||
{
|
{
|
||||||
//strip any \r\n chars on the end.
|
if (!f->cachesize)
|
||||||
end = ret+strlen(ret);
|
{
|
||||||
if (end>ret && end[-1] == '\n')
|
//figure out how much we can try to cache.
|
||||||
*--end = 0;
|
int sz = f->filesize - f->fileoffset;
|
||||||
if (end>ret && end[-1] == '\r')
|
if (sz < 0 || f->fileoffset < 0) //... maybe we shouldn't have implemented seek support.
|
||||||
*--end = 0;
|
sz = 0;
|
||||||
G_INT(OFS_RETURN) = PR_SetEngineString(ret);
|
else if ((size_t)sz > sizeof(f->cache))
|
||||||
|
sz = sizeof(f->cache);
|
||||||
|
//read a chunk
|
||||||
|
f->cacheoffset = 0;
|
||||||
|
f->cachesize = fread(f->cache, 1, sz, f->file);
|
||||||
|
f->fileoffset += f->cachesize;
|
||||||
|
if (!f->cachesize)
|
||||||
|
{
|
||||||
|
//classic eof...
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*s = f->cache[f->cacheoffset++];
|
||||||
|
if (*s == '\n') //new line, yay!
|
||||||
|
break;
|
||||||
|
s++;
|
||||||
|
if (s == end)
|
||||||
|
s--; //rewind if we're overflowing, such that we truncate the string.
|
||||||
}
|
}
|
||||||
|
if (s > ret && s[-1] == '\r')
|
||||||
|
s--; //terminate it on the \r of a \r\n pair.
|
||||||
|
*s = 0; //terminate it
|
||||||
|
G_INT(OFS_RETURN) = PR_SetEngineString(ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void PF_fputs(void)
|
static void PF_fputs(void)
|
||||||
|
@ -2222,6 +2264,8 @@ static void PF_fputs(void)
|
||||||
Con_Warning("PF_fputs: invalid file handle\n");
|
Con_Warning("PF_fputs: invalid file handle\n");
|
||||||
else if (!qcfiles[fileid].file)
|
else if (!qcfiles[fileid].file)
|
||||||
Con_Warning("PF_fputs: file not open\n");
|
Con_Warning("PF_fputs: file not open\n");
|
||||||
|
else if (qcfiles[fileid].mode == 0)
|
||||||
|
Con_Warning("PF_fgets: file not open for writing\n");
|
||||||
else
|
else
|
||||||
fputs(str, qcfiles[fileid].file);
|
fputs(str, qcfiles[fileid].file);
|
||||||
}
|
}
|
||||||
|
@ -2248,9 +2292,16 @@ static void PF_fseek(void)
|
||||||
Con_Warning("PF_fread: file not open\n");
|
Con_Warning("PF_fread: file not open\n");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
G_INT(OFS_RETURN) = ftell(qcfiles[fileid].file);
|
if (qcfiles[fileid].mode == 0)
|
||||||
|
G_INT(OFS_RETURN) = qcfiles[fileid].fileoffset; //when we're reading, use the cached read offset
|
||||||
|
else
|
||||||
|
G_INT(OFS_RETURN) = ftell(qcfiles[fileid].file)-qcfiles[fileid].filebase;
|
||||||
if (pr_argc>1)
|
if (pr_argc>1)
|
||||||
fseek(qcfiles[fileid].file, G_INT(OFS_PARM1), SEEK_SET);
|
{
|
||||||
|
qcfiles[fileid].fileoffset = G_INT(OFS_PARM1);
|
||||||
|
fseek(qcfiles[fileid].file, qcfiles[fileid].filebase+qcfiles[fileid].fileoffset, SEEK_SET);
|
||||||
|
qcfiles[fileid].cachesize = qcfiles[fileid].cacheoffset = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -2301,6 +2352,11 @@ static void PF_fsize(void)
|
||||||
Con_Warning("PF_fread: invalid file handle\n");
|
Con_Warning("PF_fread: invalid file handle\n");
|
||||||
else if (!qcfiles[fileid].file)
|
else if (!qcfiles[fileid].file)
|
||||||
Con_Warning("PF_fread: file not open\n");
|
Con_Warning("PF_fread: file not open\n");
|
||||||
|
else if (qcfiles[fileid].mode == 0)
|
||||||
|
{
|
||||||
|
G_INT(OFS_RETURN) = qcfiles[fileid].filesize;
|
||||||
|
//can't truncate if we're reading.
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
long curpos = ftell(qcfiles[fileid].file);
|
long curpos = ftell(qcfiles[fileid].file);
|
||||||
|
@ -3410,7 +3466,7 @@ static void PF_void_stub(void)
|
||||||
|
|
||||||
#ifdef PSET_SCRIPT
|
#ifdef PSET_SCRIPT
|
||||||
//for compat with dpp7 protocols, and mods that cba to precache things.
|
//for compat with dpp7 protocols, and mods that cba to precache things.
|
||||||
static void COM_Effectinfo_Enumerate(void (*cb)(const char *pname))
|
static void COM_Effectinfo_Enumerate(int (*cb)(const char *pname))
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
char *f, *e, *buf;
|
char *f, *e, *buf;
|
||||||
|
@ -3472,7 +3528,7 @@ static void COM_Effectinfo_Enumerate(void (*cb)(const char *pname))
|
||||||
}
|
}
|
||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
static void PF_SV_ForceParticlePrecache(const char *s)
|
int PF_SV_ForceParticlePrecache(const char *s)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
for (i = 1; i < MAX_PARTICLETYPES; i++)
|
for (i = 1; i < MAX_PARTICLETYPES; i++)
|
||||||
|
@ -3488,11 +3544,12 @@ static void PF_SV_ForceParticlePrecache(const char *s)
|
||||||
}
|
}
|
||||||
|
|
||||||
sv.particle_precache[i] = strcpy(Hunk_Alloc(strlen(s)+1), s); //weirdness to avoid issues with tempstrings
|
sv.particle_precache[i] = strcpy(Hunk_Alloc(strlen(s)+1), s); //weirdness to avoid issues with tempstrings
|
||||||
return;
|
return i;
|
||||||
}
|
}
|
||||||
if (!strcmp(sv.particle_precache[i], s))
|
if (!strcmp(sv.particle_precache[i], s))
|
||||||
return;
|
return i;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
static void PF_sv_particleeffectnum(void)
|
static void PF_sv_particleeffectnum(void)
|
||||||
{
|
{
|
||||||
|
@ -3862,7 +3919,7 @@ static const char *extnames[] =
|
||||||
"DP_QC_STRFTIME",
|
"DP_QC_STRFTIME",
|
||||||
"DP_QC_STRING_CASE_FUNCTIONS",
|
"DP_QC_STRING_CASE_FUNCTIONS",
|
||||||
"DP_QC_STRINGBUFFERS",
|
"DP_QC_STRINGBUFFERS",
|
||||||
// "DP_QC_STRINGCOLORFUNCTIONS", //the functions are implemented... the colour codes are nor
|
// "DP_QC_STRINGCOLORFUNCTIONS", //the functions are provided only as stubs. the client has absolutely no support.
|
||||||
"DP_QC_STRREPLACE",
|
"DP_QC_STRREPLACE",
|
||||||
"DP_QC_TOKENIZEBYSEPARATOR",
|
"DP_QC_TOKENIZEBYSEPARATOR",
|
||||||
"DP_QC_TRACEBOX",
|
"DP_QC_TRACEBOX",
|
||||||
|
@ -3883,7 +3940,7 @@ static const char *extnames[] =
|
||||||
"DP_TE_BLOOD",
|
"DP_TE_BLOOD",
|
||||||
"DP_TE_STANDARDEFFECTBUILTINS",
|
"DP_TE_STANDARDEFFECTBUILTINS",
|
||||||
"EXT_BITSHIFT",
|
"EXT_BITSHIFT",
|
||||||
//"FRIK_FILE", //lacks the file part, but does have the strings part.
|
"FRIK_FILE", //lacks the file part, but does have the strings part.
|
||||||
#ifdef PSET_SCRIPT
|
#ifdef PSET_SCRIPT
|
||||||
"FTE_PART_SCRIPT",
|
"FTE_PART_SCRIPT",
|
||||||
"FTE_PART_NAMESPACES",
|
"FTE_PART_NAMESPACES",
|
||||||
|
@ -4219,14 +4276,39 @@ void PR_DumpPlatform_f(void)
|
||||||
//extra fields
|
//extra fields
|
||||||
fprintf(f, "\n\n//Supported Extension fields\n");
|
fprintf(f, "\n\n//Supported Extension fields\n");
|
||||||
fprintf(f, ".float gravity;\n"); //used by hipnotic
|
fprintf(f, ".float gravity;\n"); //used by hipnotic
|
||||||
fprintf(f, "//.float items2;\n"); //used by both mission packs. *REPLACES* serverflags if defined, so lets try not to define it.
|
fprintf(f, "//.float items2; /*if defined, overrides serverflags for displaying runes on the hud*/\n"); //used by both mission packs. *REPLACES* serverflags if defined, so lets try not to define it.
|
||||||
fprintf(f, ".float alpha;\n"); //entity alpha. woot.
|
fprintf(f, ".float alpha; /*entity opacity*/\n"); //entity alpha. woot.
|
||||||
|
fprintf(f, ".float traileffectnum; /*can also be set with 'traileffect' from a map editor*/\n");
|
||||||
|
fprintf(f, ".float emiteffectnum; /*can also be set with 'traileffect' from a map editor*/\n");
|
||||||
|
fprintf(f, ".vector movement; /*describes which forward/right/up keys the player is holidng*/\n");
|
||||||
|
fprintf(f, ".entity viewmodelforclient; /*attaches this entity to the specified player's view. invisible to other players*/\n");
|
||||||
|
|
||||||
//extra constants
|
//extra constants
|
||||||
fprintf(f, "\n\n//Supported Extension Constants\n");
|
fprintf(f, "\n\n//Supported Extension Constants\n");
|
||||||
fprintf(f, "const float MOVETYPE_FOLLOW\t= "STRINGIFY(MOVETYPE_EXT_FOLLOW)";\n");
|
fprintf(f, "const float MOVETYPE_FOLLOW = "STRINGIFY(MOVETYPE_EXT_FOLLOW)";\n");
|
||||||
fprintf(f, "const float SOLID_CORPSE\t= "STRINGIFY(SOLID_EXT_CORPSE)";\n");
|
fprintf(f, "const float SOLID_CORPSE = "STRINGIFY(SOLID_EXT_CORPSE)";\n");
|
||||||
|
|
||||||
|
fprintf(f, "const float FILE_READ = "STRINGIFY(0)";\n");
|
||||||
|
fprintf(f, "const float FILE_APPEND = "STRINGIFY(1)";\n");
|
||||||
|
fprintf(f, "const float FILE_WRITE = "STRINGIFY(2)";\n");
|
||||||
|
|
||||||
|
fprintf(f, "const float CLIENTTYPE_DISCONNECT = "STRINGIFY(0)";\n");
|
||||||
|
fprintf(f, "const float CLIENTTYPE_REAL = "STRINGIFY(1)";\n");
|
||||||
|
fprintf(f, "const float CLIENTTYPE_BOT = "STRINGIFY(2)";\n");
|
||||||
|
fprintf(f, "const float CLIENTTYPE_NOTCLIENT = "STRINGIFY(3)";\n");
|
||||||
|
|
||||||
|
fprintf(f, "const float EF_NOSHADOW = "STRINGIFY(0x1000)";\n");
|
||||||
|
|
||||||
|
fprintf(f, "const float MSG_MULTICAST = "STRINGIFY(4)";\n");
|
||||||
|
fprintf(f, "const float MULTICAST_ALL = "STRINGIFY(MULTICAST_ALL_U)";\n");
|
||||||
|
// fprintf(f, "const float MULTICAST_PHS = "STRINGIFY(MULTICAST_PHS_U)";\n");
|
||||||
|
fprintf(f, "const float MULTICAST_PVS = "STRINGIFY(MULTICAST_PVS_U)";\n");
|
||||||
|
fprintf(f, "const float MULTICAST_ONE = "STRINGIFY(MULTICAST_ONE_U)";\n");
|
||||||
|
fprintf(f, "const float MULTICAST_ALL_R = "STRINGIFY(MULTICAST_ALL_R)";\n");
|
||||||
|
// fprintf(f, "const float MULTICAST_PHS_R = "STRINGIFY(MULTICAST_PHS_R)";\n");
|
||||||
|
fprintf(f, "const float MULTICAST_PVS_R = "STRINGIFY(MULTICAST_PVS_R)";\n");
|
||||||
|
fprintf(f, "const float MULTICAST_ONE_R = "STRINGIFY(MULTICAST_ONE_R)";\n");
|
||||||
|
fprintf(f, "const float MULTICAST_INIT = "STRINGIFY(MULTICAST_INIT)";\n");
|
||||||
|
|
||||||
for (j = 0; j < 2; j++)
|
for (j = 0; j < 2; j++)
|
||||||
{
|
{
|
||||||
|
|
0
quakespasm/Quake/progdefs.q1
Normal file → Executable file
0
quakespasm/Quake/progdefs.q1
Normal file → Executable file
|
@ -79,6 +79,10 @@ void PR_EnableExtensions(ddef_t *pr_globaldefs); //adds in the extra builtins et
|
||||||
void PR_AutoCvarChanged(cvar_t *var); //updates the autocvar_ globals when their cvar is changed
|
void PR_AutoCvarChanged(cvar_t *var); //updates the autocvar_ globals when their cvar is changed
|
||||||
void PR_ShutdownExtensions(void); //nooooes!
|
void PR_ShutdownExtensions(void); //nooooes!
|
||||||
void PR_DumpPlatform_f(void); //console command: writes out a qsextensions.qc file
|
void PR_DumpPlatform_f(void); //console command: writes out a qsextensions.qc file
|
||||||
|
//special hacks...
|
||||||
|
int PF_SV_ForceParticlePrecache(const char *s);
|
||||||
|
int SV_Precache_Model(const char *s);
|
||||||
|
void PR_spawnfunc_misc_model(edict_t *self);
|
||||||
|
|
||||||
//from pr_edict, for pr_ext. reflection is messy.
|
//from pr_edict, for pr_ext. reflection is messy.
|
||||||
qboolean ED_ParseEpair (void *base, ddef_t *key, const char *s);
|
qboolean ED_ParseEpair (void *base, ddef_t *key, const char *s);
|
||||||
|
@ -178,6 +182,7 @@ extern struct pr_extfields_s
|
||||||
int movement;
|
int movement;
|
||||||
int viewmodelforclient;
|
int viewmodelforclient;
|
||||||
int traileffectnum;
|
int traileffectnum;
|
||||||
|
int emiteffectnum;
|
||||||
} pr_extfields;
|
} pr_extfields;
|
||||||
|
|
||||||
#endif /* _QUAKE_PROGS_H */
|
#endif /* _QUAKE_PROGS_H */
|
||||||
|
|
|
@ -362,15 +362,16 @@ typedef struct
|
||||||
vec3_t angles;
|
vec3_t angles;
|
||||||
unsigned short modelindex; //johnfitz -- was int
|
unsigned short modelindex; //johnfitz -- was int
|
||||||
unsigned short frame; //johnfitz -- was int
|
unsigned short frame; //johnfitz -- was int
|
||||||
|
unsigned int effects;
|
||||||
unsigned char colormap; //johnfitz -- was int
|
unsigned char colormap; //johnfitz -- was int
|
||||||
unsigned char skin; //johnfitz -- was int
|
unsigned char skin; //johnfitz -- was int
|
||||||
unsigned char alpha; //johnfitz -- added
|
unsigned char alpha; //johnfitz -- added
|
||||||
unsigned char pmovetype; //spike
|
unsigned char pmovetype; //spike
|
||||||
unsigned short traileffectnum; //spike -- for qc-defined particle trails. typically evilly used for things that are not trails.
|
unsigned short traileffectnum; //spike -- for qc-defined particle trails. typically evilly used for things that are not trails.
|
||||||
|
unsigned short emiteffectnum; //spike -- for qc-defined particle trails. typically evilly used for things that are not trails.
|
||||||
short velocity[3]; //spike -- the player's velocity.
|
short velocity[3]; //spike -- the player's velocity.
|
||||||
unsigned short effects;
|
|
||||||
unsigned char eflags;
|
unsigned char eflags;
|
||||||
unsigned char pad;
|
// unsigned char pad;
|
||||||
} entity_state_t;
|
} entity_state_t;
|
||||||
#define EFLAGS_STEP 1
|
#define EFLAGS_STEP 1
|
||||||
//#define EFLAGS_GLOWTRAIL 2
|
//#define EFLAGS_GLOWTRAIL 2
|
||||||
|
@ -379,7 +380,7 @@ typedef struct
|
||||||
//#define EFLAGS_ 16
|
//#define EFLAGS_ 16
|
||||||
//#define EFLAGS_COLOURMAPPED 32 //.colormap=1024|(top<<4)|bottom), instead of a player number
|
//#define EFLAGS_COLOURMAPPED 32 //.colormap=1024|(top<<4)|bottom), instead of a player number
|
||||||
//#define EFLAGS_ 64
|
//#define EFLAGS_ 64
|
||||||
#define EFLAGS_ONGROUND 128
|
#define EFLAGS_ONGROUND 128 //for bobbing more than anything else. *sigh*.
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
|
|
@ -128,7 +128,7 @@ static float psintable[256];
|
||||||
|
|
||||||
int PScript_RunParticleEffectState (vec3_t org, vec3_t dir, float count, int typenum, trailstate_t **tsk);
|
int PScript_RunParticleEffectState (vec3_t org, vec3_t dir, float count, int typenum, trailstate_t **tsk);
|
||||||
int PScript_ParticleTrail (vec3_t startpos, vec3_t end, int type, int dlkey, vec3_t axis[3], trailstate_t **tsk);
|
int PScript_ParticleTrail (vec3_t startpos, vec3_t end, int type, int dlkey, vec3_t axis[3], trailstate_t **tsk);
|
||||||
static qboolean P_LoadParticleSet(char *name, qboolean implicit);
|
static qboolean P_LoadParticleSet(char *name, qboolean implicit, qboolean showwarning);
|
||||||
static void R_Particles_KillAllEffects(void);
|
static void R_Particles_KillAllEffects(void);
|
||||||
|
|
||||||
static void buildsintable(void)
|
static void buildsintable(void)
|
||||||
|
@ -200,7 +200,7 @@ typedef struct skytris_s {
|
||||||
vec3_t x;
|
vec3_t x;
|
||||||
vec3_t y;
|
vec3_t y;
|
||||||
float area;
|
float area;
|
||||||
float nexttime;
|
double nexttime;
|
||||||
int ptype;
|
int ptype;
|
||||||
struct msurface_s *face;
|
struct msurface_s *face;
|
||||||
} skytris_t;
|
} skytris_t;
|
||||||
|
@ -430,9 +430,6 @@ static beamseg_t *free_beams;
|
||||||
static beamseg_t *beams;
|
static beamseg_t *beams;
|
||||||
static int r_numbeams;
|
static int r_numbeams;
|
||||||
|
|
||||||
static skytriblock_t *skytrimem;
|
|
||||||
static skytris_t *skytris;
|
|
||||||
|
|
||||||
static clippeddecal_t *free_decals;
|
static clippeddecal_t *free_decals;
|
||||||
static clippeddecal_t *decals;
|
static clippeddecal_t *decals;
|
||||||
static int r_numdecals;
|
static int r_numdecals;
|
||||||
|
@ -764,11 +761,11 @@ typedef struct associatedeffect_s
|
||||||
struct associatedeffect_s *next;
|
struct associatedeffect_s *next;
|
||||||
char mname[MAX_QPATH];
|
char mname[MAX_QPATH];
|
||||||
char pname[MAX_QPATH];
|
char pname[MAX_QPATH];
|
||||||
|
unsigned int flags;
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
AE_TRAIL,
|
AE_TRAIL,
|
||||||
AE_EMIT,
|
AE_EMIT,
|
||||||
AE_REPLACE
|
|
||||||
} type;
|
} type;
|
||||||
} associatedeffect_t;
|
} associatedeffect_t;
|
||||||
static associatedeffect_t *associatedeffect;
|
static associatedeffect_t *associatedeffect;
|
||||||
|
@ -776,16 +773,28 @@ static void PScript_AssociateEffect_f(void)
|
||||||
{
|
{
|
||||||
const char *modelname = Cmd_Argv(1);
|
const char *modelname = Cmd_Argv(1);
|
||||||
const char *effectname = Cmd_Argv(2);
|
const char *effectname = Cmd_Argv(2);
|
||||||
int type = atoi(Cmd_Argv(3));
|
unsigned int flags = 0;
|
||||||
|
int type;
|
||||||
associatedeffect_t *ae;
|
associatedeffect_t *ae;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (!strcmp(Cmd_Argv(0), "r_trail"))
|
if (!strcmp(Cmd_Argv(0), "r_trail"))
|
||||||
type = AE_TRAIL;
|
type = AE_TRAIL;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (type)
|
type = AE_EMIT;
|
||||||
type = AE_REPLACE;
|
for (i = 3; i < Cmd_Argc(); i++)
|
||||||
else
|
{
|
||||||
type = AE_EMIT;
|
const char *fn = Cmd_Argv(i);
|
||||||
|
if (!strcmp(fn, "replace") || !strcmp(fn, "1"))
|
||||||
|
flags |= MOD_EMITREPLACE;
|
||||||
|
else if (!strcmp(fn, "forwards") || !strcmp(fn, "forward"))
|
||||||
|
flags |= MOD_EMITFORWARDS;
|
||||||
|
else if (!strcmp(fn, "0"))
|
||||||
|
; //1 or 0 are legacy, meaning replace or not
|
||||||
|
else
|
||||||
|
Con_DPrintf("%s %s: unknown flag %s\n", Cmd_Argv(0), modelname, fn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -796,6 +805,7 @@ static void PScript_AssociateEffect_f(void)
|
||||||
strstr(modelname, ".bsp") ||
|
strstr(modelname, ".bsp") ||
|
||||||
strstr(modelname, "turr"))
|
strstr(modelname, "turr"))
|
||||||
{
|
{
|
||||||
|
//there is a very real possibility of attaching 'large' effects to models so that they become more visible (eg: a stream of particles passing through walls showing you the entity that they're eminating from)
|
||||||
Con_Printf("Sorry: Not allowed to attach effects to model \"%s\"\n", modelname);
|
Con_Printf("Sorry: Not allowed to attach effects to model \"%s\"\n", modelname);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -808,20 +818,18 @@ static void PScript_AssociateEffect_f(void)
|
||||||
{
|
{
|
||||||
if (!strcmp(ae->mname, modelname))
|
if (!strcmp(ae->mname, modelname))
|
||||||
if ((ae->type==AE_TRAIL) == (type==AE_TRAIL))
|
if ((ae->type==AE_TRAIL) == (type==AE_TRAIL))
|
||||||
{
|
|
||||||
strcpy(ae->pname, effectname);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!ae)
|
if (!ae)
|
||||||
{
|
{
|
||||||
ae = Z_Malloc(sizeof(*ae));
|
ae = Z_Malloc(sizeof(*ae));
|
||||||
ae->type = type;
|
|
||||||
strcpy(ae->mname, modelname);
|
strcpy(ae->mname, modelname);
|
||||||
strcpy(ae->pname, effectname);
|
|
||||||
ae->next = associatedeffect;
|
ae->next = associatedeffect;
|
||||||
associatedeffect = ae;
|
associatedeffect = ae;
|
||||||
}
|
}
|
||||||
|
strcpy(ae->pname, effectname);
|
||||||
|
ae->type = type;
|
||||||
|
ae->flags = flags;
|
||||||
|
|
||||||
r_plooksdirty = true;
|
r_plooksdirty = true;
|
||||||
}
|
}
|
||||||
|
@ -888,11 +896,8 @@ void PScript_UpdateModelEffects(qmodel_t *mod)
|
||||||
break;
|
break;
|
||||||
case AE_EMIT:
|
case AE_EMIT:
|
||||||
mod->emiteffect = PScript_FindParticleType(ae->pname);
|
mod->emiteffect = PScript_FindParticleType(ae->pname);
|
||||||
mod->flags &= ~MOD_EMITREPLACE;
|
mod->flags &= ~(MOD_EMITREPLACE|MOD_EMITFORWARDS);
|
||||||
break;
|
mod->flags |= ae->flags;
|
||||||
case AE_REPLACE:
|
|
||||||
mod->emiteffect = PScript_FindParticleType(ae->pname);
|
|
||||||
mod->flags |= MOD_EMITREPLACE;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1098,7 +1103,7 @@ int PScript_FindParticleType(const char *fullname)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (*cfg)
|
if (*cfg)
|
||||||
if (P_LoadParticleSet(cfg, true))
|
if (P_LoadParticleSet(cfg, true, true))
|
||||||
return PScript_FindParticleType(fullname);
|
return PScript_FindParticleType(fullname);
|
||||||
|
|
||||||
/* if (fallback)
|
/* if (fallback)
|
||||||
|
@ -1244,6 +1249,13 @@ static void P_LoadTexture(part_type_t *ptype, qboolean warn)
|
||||||
}
|
}
|
||||||
ptype->looks.texture = thetex;
|
ptype->looks.texture = thetex;
|
||||||
}
|
}
|
||||||
|
else if (strstr(ptype->texname, "classicparticle"))
|
||||||
|
{
|
||||||
|
extern gltexture_t *particletexture1;
|
||||||
|
ptype->looks.texture = particletexture1;
|
||||||
|
ptype->s2 = 0.5;
|
||||||
|
ptype->t2 = 0.5;
|
||||||
|
}
|
||||||
else if (strstr(ptype->texname, "glow") || strstr(ptype->texname, "ball") || ptype->looks.type == PT_TEXTUREDSPARK) //sparks and special names get a nice circular texture.
|
else if (strstr(ptype->texname, "glow") || strstr(ptype->texname, "ball") || ptype->looks.type == PT_TEXTUREDSPARK) //sparks and special names get a nice circular texture.
|
||||||
{
|
{
|
||||||
static gltexture_t *thetex;
|
static gltexture_t *thetex;
|
||||||
|
@ -1400,9 +1412,32 @@ static void P_ResetToDefaults(part_type_t *ptype)
|
||||||
ptype->t2 = 1;
|
ptype->t2 = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *PScript_ReadLine(char *buffer, size_t buffersize, const char *filedata, size_t filesize, size_t *offset)
|
||||||
|
{
|
||||||
|
const char *start = filedata + *offset;
|
||||||
|
const char *f = start;
|
||||||
|
const char *e = filedata+filesize;
|
||||||
|
if (f >= e)
|
||||||
|
return NULL; //eof
|
||||||
|
while (f < e)
|
||||||
|
{
|
||||||
|
if (*f++ == '\n')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*offset = f-filedata;
|
||||||
|
|
||||||
|
buffersize--;
|
||||||
|
if (buffersize >= (size_t)(f-start))
|
||||||
|
buffersize = f-start;
|
||||||
|
memcpy(buffer, start, buffersize);
|
||||||
|
buffer[buffersize] = 0; //null terminate it
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
//This is the function that loads the effect descriptions.
|
//This is the function that loads the effect descriptions.
|
||||||
void PScript_ParseParticleEffectFile(const char *config, qboolean part_parseweak, FILE *context)
|
void PScript_ParseParticleEffectFile(const char *config, qboolean part_parseweak, char *context, size_t filesize)
|
||||||
{
|
{
|
||||||
const char *var, *value;
|
const char *var, *value;
|
||||||
char *buf;
|
char *buf;
|
||||||
|
@ -1415,14 +1450,15 @@ void PScript_ParseParticleEffectFile(const char *config, qboolean part_parseweak
|
||||||
char line[512];
|
char line[512];
|
||||||
char part_parsenamespace[MAX_QPATH];
|
char part_parsenamespace[MAX_QPATH];
|
||||||
|
|
||||||
byte *palrgba = (byte *)d_8to24table;
|
byte *palrgba = (byte *)d_8to24table;
|
||||||
|
size_t offset = 0;
|
||||||
|
|
||||||
q_strlcpy(part_parsenamespace, config, sizeof(part_parsenamespace));
|
q_strlcpy(part_parsenamespace, config, sizeof(part_parsenamespace));
|
||||||
config = part_parsenamespace;
|
config = part_parsenamespace;
|
||||||
|
|
||||||
nexteffect:
|
nexteffect:
|
||||||
|
|
||||||
if (!fgets(line, sizeof(line), context))
|
if (!PScript_ReadLine(line, sizeof(line), context, filesize, &offset))
|
||||||
return; //eof
|
return; //eof
|
||||||
reparse:
|
reparse:
|
||||||
|
|
||||||
|
@ -1465,7 +1501,7 @@ reparse:
|
||||||
goto nexteffect;
|
goto nexteffect;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = fgets(line, sizeof(line), context);
|
buf = PScript_ReadLine(line, sizeof(line), context, filesize, &offset);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return; //eof
|
return; //eof
|
||||||
while (*buf && *buf <= ' ')
|
while (*buf && *buf <= ' ')
|
||||||
|
@ -1489,7 +1525,7 @@ reparse:
|
||||||
int depth = 1;
|
int depth = 1;
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
buf = fgets(line, sizeof(line), context);
|
buf = PScript_ReadLine(line, sizeof(line), context, filesize, &offset);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1561,13 +1597,13 @@ reparse:
|
||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
buf = fgets(line, sizeof(line), context);
|
buf = PScript_ReadLine(line, sizeof(line), context, filesize, &offset);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
{
|
{
|
||||||
Con_Printf("Unexpected end of buffer with effect %s\n", ptype->name);
|
Con_Printf("Unexpected end of buffer with effect %s\n", ptype->name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
skipread:
|
||||||
while (*buf && *buf <= ' ')
|
while (*buf && *buf <= ' ')
|
||||||
buf++; //no whitespace please.
|
buf++; //no whitespace please.
|
||||||
if (*buf == '}')
|
if (*buf == '}')
|
||||||
|
@ -1586,11 +1622,16 @@ reparse:
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
#if UNSUPPORTED
|
|
||||||
if (!strcmp(var, "shader"))
|
if (!strcmp(var, "shader"))
|
||||||
{
|
{
|
||||||
q_strlcpy(ptype->texname, ptype->name, sizeof(ptype->texname));
|
q_strlcpy(ptype->texname, ptype->name, sizeof(ptype->texname));
|
||||||
buf = Cbuf_GetNext(Cmd_ExecLevel, true);
|
|
||||||
|
#if UNSUPPORTED
|
||||||
|
Con_DPrintf("%s.%s: shaders are not supported in this build\n", ptype->config, ptype->name);
|
||||||
|
#endif
|
||||||
|
buf = PScript_ReadLine(line, sizeof(line), context, filesize, &offset);
|
||||||
|
if (!buf)
|
||||||
|
continue;
|
||||||
while (*buf && *buf <= ' ')
|
while (*buf && *buf <= ' ')
|
||||||
buf++; //no leading whitespace please.
|
buf++; //no leading whitespace please.
|
||||||
if (*buf == '{')
|
if (*buf == '{')
|
||||||
|
@ -1603,8 +1644,8 @@ reparse:
|
||||||
str[2] = 0;
|
str[2] = 0;
|
||||||
while(nest)
|
while(nest)
|
||||||
{
|
{
|
||||||
buf = Cbuf_GetNext(Cmd_ExecLevel, true);
|
buf = PScript_ReadLine(line, sizeof(line), context, filesize, &offset);
|
||||||
if (!*buf)
|
if (!buf)
|
||||||
{
|
{
|
||||||
Con_Printf("Unexpected end of buffer with effect %s\n", ptype->name);
|
Con_Printf("Unexpected end of buffer with effect %s\n", ptype->name);
|
||||||
break;
|
break;
|
||||||
|
@ -1621,15 +1662,15 @@ reparse:
|
||||||
str[slen++] = '\n';
|
str[slen++] = '\n';
|
||||||
}
|
}
|
||||||
str[slen] = 0;
|
str[slen] = 0;
|
||||||
|
#if UNSUPPORTED
|
||||||
R_RegisterShader(ptype->texname, SUF_NONE, str);
|
R_RegisterShader(ptype->texname, SUF_NONE, str);
|
||||||
|
#endif
|
||||||
Z_Free(str);
|
Z_Free(str);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Cbuf_InsertText(buf, Cmd_ExecLevel, true);
|
goto skipread;
|
||||||
}
|
}
|
||||||
else
|
else if (!strcmp(var, "texture") || !strcmp(var, "linear_texture") || !strcmp(var, "nearest_texture") || !strcmp(var, "nearesttexture"))
|
||||||
#endif
|
|
||||||
if (!strcmp(var, "texture") || !strcmp(var, "linear_texture") || !strcmp(var, "nearest_texture") || !strcmp(var, "nearesttexture"))
|
|
||||||
{
|
{
|
||||||
q_strlcpy(ptype->texname, value, sizeof(ptype->texname));
|
q_strlcpy(ptype->texname, value, sizeof(ptype->texname));
|
||||||
ptype->looks.nearest = !strncmp(var, "nearest", 7);
|
ptype->looks.nearest = !strncmp(var, "nearest", 7);
|
||||||
|
@ -1802,7 +1843,7 @@ reparse:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
else if (!strcmp(var, "randomvel"))
|
else if (!strcmp(var, "randomvel"))
|
||||||
{
|
{ //shortcut for velwrand (and velbias for z bias)
|
||||||
ptype->velbias[0] = ptype->velbias[1] = 0;
|
ptype->velbias[0] = ptype->velbias[1] = 0;
|
||||||
ptype->velwrand[0] = ptype->velwrand[1] = atof(value);
|
ptype->velwrand[0] = ptype->velwrand[1] = atof(value);
|
||||||
if (Cmd_Argc()>3)
|
if (Cmd_Argc()>3)
|
||||||
|
@ -1845,18 +1886,19 @@ reparse:
|
||||||
ptype->orgbias[1] = atof(Cmd_Argv(2));
|
ptype->orgbias[1] = atof(Cmd_Argv(2));
|
||||||
ptype->orgbias[2] = atof(Cmd_Argv(3));
|
ptype->orgbias[2] = atof(Cmd_Argv(3));
|
||||||
}
|
}
|
||||||
else if (!strcmp(var, "velbias"))
|
|
||||||
{
|
|
||||||
ptype->velbias[0] = atof(value);
|
|
||||||
ptype->velbias[1] = atof(Cmd_Argv(2));
|
|
||||||
ptype->velbias[2] = atof(Cmd_Argv(3));
|
|
||||||
}
|
|
||||||
else if (!strcmp(var, "orgwrand"))
|
else if (!strcmp(var, "orgwrand"))
|
||||||
{
|
{
|
||||||
ptype->orgwrand[0] = atof(value);
|
ptype->orgwrand[0] = atof(value);
|
||||||
ptype->orgwrand[1] = atof(Cmd_Argv(2));
|
ptype->orgwrand[1] = atof(Cmd_Argv(2));
|
||||||
ptype->orgwrand[2] = atof(Cmd_Argv(3));
|
ptype->orgwrand[2] = atof(Cmd_Argv(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (!strcmp(var, "velbias"))
|
||||||
|
{
|
||||||
|
ptype->velbias[0] = atof(value);
|
||||||
|
ptype->velbias[1] = atof(Cmd_Argv(2));
|
||||||
|
ptype->velbias[2] = atof(Cmd_Argv(3));
|
||||||
|
}
|
||||||
else if (!strcmp(var, "velwrand"))
|
else if (!strcmp(var, "velwrand"))
|
||||||
{
|
{
|
||||||
ptype->velwrand[0] = atof(value);
|
ptype->velwrand[0] = atof(value);
|
||||||
|
@ -1942,9 +1984,9 @@ parsefluid:
|
||||||
ptype->flags |= PT_TROVERWATER;
|
ptype->flags |= PT_TROVERWATER;
|
||||||
goto parsefluid;
|
goto parsefluid;
|
||||||
}
|
}
|
||||||
#if UNSUPPORTED
|
|
||||||
else if (!strcmp(var, "model"))
|
else if (!strcmp(var, "model"))
|
||||||
{
|
{
|
||||||
|
#if UNSUPPORTED
|
||||||
partmodels_t *mod;
|
partmodels_t *mod;
|
||||||
char *e;
|
char *e;
|
||||||
|
|
||||||
|
@ -2029,8 +2071,10 @@ parsefluid:
|
||||||
else
|
else
|
||||||
mod->traileffect = P_INVALID;
|
mod->traileffect = P_INVALID;
|
||||||
}
|
}
|
||||||
}
|
#else
|
||||||
|
Con_DPrintf("%s.%s: model particles are not supported in this build\n", ptype->config, ptype->name);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
else if (!strcmp(var, "sound"))
|
else if (!strcmp(var, "sound"))
|
||||||
{
|
{
|
||||||
const char *e;
|
const char *e;
|
||||||
|
@ -2221,6 +2265,7 @@ parsefluid:
|
||||||
ptype->stainonimpact = atof(value);
|
ptype->stainonimpact = atof(value);
|
||||||
else if (!strcmp(var, "blend"))
|
else if (!strcmp(var, "blend"))
|
||||||
{
|
{
|
||||||
|
//small note: use premultiplied alpha where possible. this reduces the required state switches.
|
||||||
ptype->looks.premul = false;
|
ptype->looks.premul = false;
|
||||||
if (!strcmp(value, "adda") || !strcmp(value, "add"))
|
if (!strcmp(value, "adda") || !strcmp(value, "add"))
|
||||||
ptype->looks.blendmode = BM_ADDA;
|
ptype->looks.blendmode = BM_ADDA;
|
||||||
|
@ -2234,7 +2279,7 @@ parsefluid:
|
||||||
ptype->looks.blendmode = BM_INVMODC;
|
ptype->looks.blendmode = BM_INVMODC;
|
||||||
else if (!strcmp(value, "blendcolour") || !strcmp(value, "blendcolor"))
|
else if (!strcmp(value, "blendcolour") || !strcmp(value, "blendcolor"))
|
||||||
ptype->looks.blendmode = BM_BLENDCOLOUR;
|
ptype->looks.blendmode = BM_BLENDCOLOUR;
|
||||||
else if (!strcmp(value, "blendalpha"))
|
else if (!strcmp(value, "blendalpha") || !strcmp(value, "blend"))
|
||||||
ptype->looks.blendmode = BM_BLEND;
|
ptype->looks.blendmode = BM_BLEND;
|
||||||
else if (!strcmp(value, "premul_subtract"))
|
else if (!strcmp(value, "premul_subtract"))
|
||||||
{
|
{
|
||||||
|
@ -2252,7 +2297,10 @@ parsefluid:
|
||||||
ptype->looks.blendmode = BM_PREMUL;
|
ptype->looks.blendmode = BM_PREMUL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
Con_DPrintf("%s.%s: uses unknown blend type '%s', assuming legacy 'blendalpha'\n", ptype->config, ptype->name, value);
|
||||||
ptype->looks.blendmode = BM_BLEND; //fallback
|
ptype->looks.blendmode = BM_BLEND; //fallback
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (!strcmp(var, "spawnmode"))
|
else if (!strcmp(var, "spawnmode"))
|
||||||
{
|
{
|
||||||
|
@ -2280,8 +2328,13 @@ parsefluid:
|
||||||
}
|
}
|
||||||
else if (!strcmp(value, "distball"))
|
else if (!strcmp(value, "distball"))
|
||||||
ptype->spawnmode = SM_DISTBALL;
|
ptype->spawnmode = SM_DISTBALL;
|
||||||
else
|
else if (!strcmp(value, "box"))
|
||||||
ptype->spawnmode = SM_BOX;
|
ptype->spawnmode = SM_BOX;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Con_DPrintf("%s.%s: uses unknown spawn type '%s', assuming 'box'\n", ptype->config, ptype->name, value);
|
||||||
|
ptype->spawnmode = SM_BOX;
|
||||||
|
}
|
||||||
|
|
||||||
if (Cmd_Argc()>2)
|
if (Cmd_Argc()>2)
|
||||||
{
|
{
|
||||||
|
@ -2304,8 +2357,13 @@ parsefluid:
|
||||||
ptype->looks.type = PT_CDECAL;
|
ptype->looks.type = PT_CDECAL;
|
||||||
else if (!strcmp(value, "udecal"))
|
else if (!strcmp(value, "udecal"))
|
||||||
ptype->looks.type = PT_UDECAL;
|
ptype->looks.type = PT_UDECAL;
|
||||||
else
|
else if (!strcmp(value, "normal"))
|
||||||
ptype->looks.type = PT_NORMAL;
|
ptype->looks.type = PT_NORMAL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Con_DPrintf("%s.%s: uses unknown render type '%s', assuming 'normal'\n", ptype->config, ptype->name, value);
|
||||||
|
ptype->looks.type = PT_NORMAL; //fallback
|
||||||
|
}
|
||||||
settype = true;
|
settype = true;
|
||||||
}
|
}
|
||||||
else if (!strcmp(var, "clippeddecal")) //mask, match
|
else if (!strcmp(var, "clippeddecal")) //mask, match
|
||||||
|
@ -2419,7 +2477,10 @@ parsefluid:
|
||||||
/* else if (!strcmp(var, "spawnparam3"))
|
/* else if (!strcmp(var, "spawnparam3"))
|
||||||
ptype->spawnparam3 = atof(value); */
|
ptype->spawnparam3 = atof(value); */
|
||||||
else if (!strcmp(var, "up"))
|
else if (!strcmp(var, "up"))
|
||||||
|
{
|
||||||
ptype->orgbias[2] = atof(value);
|
ptype->orgbias[2] = atof(value);
|
||||||
|
Con_DPrintf("%s.%s: up is deprecated, use orgbias 0 0 Z\n", ptype->config, ptype->name);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
else if (!strcmp(var, "rampmode"))
|
else if (!strcmp(var, "rampmode"))
|
||||||
|
@ -2437,8 +2498,13 @@ parsefluid:
|
||||||
ptype->rampmode = RAMP_NEAREST;
|
ptype->rampmode = RAMP_NEAREST;
|
||||||
else if (!strcmp(value, "lerp")) //don't use the name 'linear'. ramps are there to avoid linear...
|
else if (!strcmp(value, "lerp")) //don't use the name 'linear'. ramps are there to avoid linear...
|
||||||
ptype->rampmode = RAMP_LERP;
|
ptype->rampmode = RAMP_LERP;
|
||||||
else //if (!strcmp(value, "delta"))
|
else if (!strcmp(value, "delta"))
|
||||||
ptype->rampmode = RAMP_DELTA;
|
ptype->rampmode = RAMP_DELTA;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Con_DPrintf("%s.%s: uses unknown ramp mode '%s', assuming 'delta'\n", ptype->config, ptype->name, value);
|
||||||
|
ptype->rampmode = RAMP_DELTA;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (!strcmp(var, "rampindexlist"))
|
else if (!strcmp(var, "rampindexlist"))
|
||||||
{ // better not use this with delta ramps...
|
{ // better not use this with delta ramps...
|
||||||
|
@ -2523,7 +2589,13 @@ parsefluid:
|
||||||
ptype->rampindexes++;
|
ptype->rampindexes++;
|
||||||
}
|
}
|
||||||
else if (!strcmp(var, "viewspace"))
|
else if (!strcmp(var, "viewspace"))
|
||||||
|
{
|
||||||
|
#if UNSUPPORTED
|
||||||
ptype->viewspacefrac = (Cmd_Argc()>1)?atof(value):1;
|
ptype->viewspacefrac = (Cmd_Argc()>1)?atof(value):1;
|
||||||
|
#else
|
||||||
|
Con_DPrintf("%s.%s: viewspace particles are not supported in this build\n", ptype->config, ptype->name);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
else if (!strcmp(var, "perframe"))
|
else if (!strcmp(var, "perframe"))
|
||||||
ptype->flags |= PT_INVFRAMETIME;
|
ptype->flags |= PT_INVFRAMETIME;
|
||||||
else if (!strcmp(var, "averageout"))
|
else if (!strcmp(var, "averageout"))
|
||||||
|
@ -2573,16 +2645,18 @@ parsefluid:
|
||||||
ptype->dl_scales[1] = atof(Cmd_Argv(2));
|
ptype->dl_scales[1] = atof(Cmd_Argv(2));
|
||||||
ptype->dl_scales[2] = atof(Cmd_Argv(3));
|
ptype->dl_scales[2] = atof(Cmd_Argv(3));
|
||||||
}
|
}
|
||||||
#if UNSUPPORTED
|
|
||||||
else if (!strcmp(var, "spawnstain"))
|
else if (!strcmp(var, "spawnstain"))
|
||||||
{
|
{
|
||||||
|
#if UNSUPPORTED
|
||||||
ptype->stain_radius = atof(value);
|
ptype->stain_radius = atof(value);
|
||||||
ptype->stain_rgb[0] = atof(Cmd_Argv(2));
|
ptype->stain_rgb[0] = atof(Cmd_Argv(2));
|
||||||
ptype->stain_rgb[1] = atof(Cmd_Argv(3));
|
ptype->stain_rgb[1] = atof(Cmd_Argv(3));
|
||||||
ptype->stain_rgb[2] = atof(Cmd_Argv(4));
|
ptype->stain_rgb[2] = atof(Cmd_Argv(4));
|
||||||
}
|
#else
|
||||||
|
Con_DPrintf("%s.%s: spawnstain is not supported in this build\n", ptype->config, ptype->name);
|
||||||
#endif
|
#endif
|
||||||
else
|
}
|
||||||
|
else if (Cmd_Argc())
|
||||||
Con_DPrintf("%s.%s: %s is not a recognised particle type field\n", ptype->config, ptype->name, var);
|
Con_DPrintf("%s.%s: %s is not a recognised particle type field\n", ptype->config, ptype->name, var);
|
||||||
}
|
}
|
||||||
ptype->loaded = part_parseweak?1:2;
|
ptype->loaded = part_parseweak?1:2;
|
||||||
|
@ -2847,7 +2921,7 @@ static void P_ImportEffectInfo(const char *config, char *line, qboolean part_par
|
||||||
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
FILE *file;
|
char *file;
|
||||||
const char *line;
|
const char *line;
|
||||||
char linebuf[1024];
|
char linebuf[1024];
|
||||||
//default assumes 8*8 grid, but we allow more
|
//default assumes 8*8 grid, but we allow more
|
||||||
|
@ -2859,10 +2933,11 @@ static void P_ImportEffectInfo(const char *config, char *line, qboolean part_par
|
||||||
teximages[i][3] = 1/8.0 * (i>>3);
|
teximages[i][3] = 1/8.0 * (i>>3);
|
||||||
}
|
}
|
||||||
|
|
||||||
COM_FOpenFile("particles/particlefont.txt", &file, NULL);
|
file = (char*)COM_LoadMallocFile("particles/particlefont.txt", NULL);
|
||||||
if (file)
|
if (file)
|
||||||
{
|
{
|
||||||
while (fgets(linebuf, sizeof(linebuf), file))
|
size_t offset = 0;
|
||||||
|
while (PScript_ReadLine(linebuf, sizeof(linebuf), file, com_filesize, &offset))
|
||||||
{
|
{
|
||||||
float s1,s2,t1,t2;
|
float s1,s2,t1,t2;
|
||||||
line = COM_Parse(linebuf);
|
line = COM_Parse(linebuf);
|
||||||
|
@ -2883,7 +2958,7 @@ static void P_ImportEffectInfo(const char *config, char *line, qboolean part_par
|
||||||
teximages[i][3] = t1;
|
teximages[i][3] = t1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose(file);
|
free(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3318,10 +3393,32 @@ void PScript_InitParticles (void)
|
||||||
//#endif
|
//#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PScript_ClearSurfaceParticles(qmodel_t *mod)
|
||||||
|
{
|
||||||
|
mod->skytime = 0;
|
||||||
|
mod->skytris = NULL;
|
||||||
|
while(mod->skytrimem)
|
||||||
|
{
|
||||||
|
void *f = mod->skytrimem;
|
||||||
|
mod->skytrimem = mod->skytrimem->next;
|
||||||
|
Z_Free(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void PScript_ClearAllSurfaceParticles(void)
|
||||||
|
{ //make sure we hit all models, even ones from the previous map. maybe this is overkill
|
||||||
|
extern qmodel_t mod_known[];
|
||||||
|
extern int mod_numknown;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < mod_numknown; i++)
|
||||||
|
PScript_ClearSurfaceParticles(&mod_known[i]);
|
||||||
|
}
|
||||||
|
|
||||||
void PScript_Shutdown (void)
|
void PScript_Shutdown (void)
|
||||||
{
|
{
|
||||||
Cvar_SetCallback(&r_particledesc, NULL);
|
Cvar_SetCallback(&r_particledesc, NULL);
|
||||||
|
|
||||||
|
CL_ClearTrailStates();
|
||||||
|
|
||||||
// if (fallback)
|
// if (fallback)
|
||||||
// fallback->ShutdownParticles();
|
// fallback->ShutdownParticles();
|
||||||
|
|
||||||
|
@ -3364,13 +3461,7 @@ void PScript_Shutdown (void)
|
||||||
free_decals = NULL;
|
free_decals = NULL;
|
||||||
free_beams = NULL;
|
free_beams = NULL;
|
||||||
|
|
||||||
skytris = NULL;
|
PScript_ClearAllSurfaceParticles();
|
||||||
while(skytrimem)
|
|
||||||
{
|
|
||||||
void *f = skytrimem;
|
|
||||||
skytrimem = skytrimem->next;
|
|
||||||
Z_Free(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
r_numparticles = 0;
|
r_numparticles = 0;
|
||||||
r_numdecals = 0;
|
r_numdecals = 0;
|
||||||
|
@ -3425,78 +3516,80 @@ qboolean PScript_Startup (void)
|
||||||
|
|
||||||
void PScript_RecalculateSkyTris (void)
|
void PScript_RecalculateSkyTris (void)
|
||||||
{
|
{
|
||||||
skytris = NULL;
|
qmodel_t *m = cl.worldmodel;
|
||||||
while(skytrimem)
|
size_t modidx;
|
||||||
{
|
|
||||||
void *f = skytrimem;
|
|
||||||
skytrimem = skytrimem->next;
|
|
||||||
Z_Free(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cl.worldmodel && !cl.worldmodel->needload && cl.worldmodel->type == mod_brush)
|
PScript_ClearAllSurfaceParticles();
|
||||||
{
|
|
||||||
qmodel_t *m = cl.worldmodel;
|
|
||||||
int t;
|
|
||||||
int i;
|
|
||||||
int ptype;
|
|
||||||
msurface_t *surf;
|
|
||||||
char key[128];
|
|
||||||
const char *data = COM_Parse(cl.worldmodel->entities);
|
|
||||||
int *remaps;
|
|
||||||
remaps = malloc(sizeof(*remaps)*m->numtextures);
|
|
||||||
for (t = 0; t < m->numtextures; t++)
|
|
||||||
remaps[t] = P_INVALID;
|
|
||||||
|
|
||||||
//parse the worldspawn entity fields for "_texpart_FOO" keys to give texture "FOO" particles from the effect specified by the value
|
for (modidx = 0; modidx < MAX_MODELS; modidx++)
|
||||||
if (data && com_token[0] == '{')
|
{
|
||||||
|
m = cl.model_precache[modidx];
|
||||||
|
|
||||||
|
if (m && !m->needload && m->type == mod_brush)
|
||||||
{
|
{
|
||||||
while (1)
|
int t;
|
||||||
|
int i;
|
||||||
|
int ptype;
|
||||||
|
msurface_t *surf;
|
||||||
|
char key[128];
|
||||||
|
const char *data = COM_Parse(m->entities);
|
||||||
|
int *remaps;
|
||||||
|
remaps = malloc(sizeof(*remaps)*m->numtextures);
|
||||||
|
for (t = 0; t < m->numtextures; t++)
|
||||||
|
remaps[t] = P_INVALID;
|
||||||
|
|
||||||
|
//parse the worldspawn entity fields for "_texpart_FOO" keys to give texture "FOO" particles from the effect specified by the value
|
||||||
|
if (data && com_token[0] == '{')
|
||||||
{
|
{
|
||||||
data = COM_Parse(data);
|
while (1)
|
||||||
if (!data)
|
|
||||||
break; // error
|
|
||||||
if (com_token[0] == '}')
|
|
||||||
break; // end of worldspawn
|
|
||||||
if (com_token[0] == '_')
|
|
||||||
strcpy(key, com_token + 1);
|
|
||||||
else
|
|
||||||
strcpy(key, com_token);
|
|
||||||
while (key[strlen(key)-1] == ' ') // remove trailing spaces
|
|
||||||
key[strlen(key)-1] = 0;
|
|
||||||
data = COM_Parse(data);
|
|
||||||
if (!data)
|
|
||||||
break; // error
|
|
||||||
if (!q_strncasecmp("texpart_", key, 8))
|
|
||||||
{
|
{
|
||||||
for (t = 0; t < m->numtextures; t++)
|
data = COM_Parse(data);
|
||||||
|
if (!data)
|
||||||
|
break; // error
|
||||||
|
if (com_token[0] == '}')
|
||||||
|
break; // end of worldspawn
|
||||||
|
if (com_token[0] == '_')
|
||||||
|
strcpy(key, com_token + 1);
|
||||||
|
else
|
||||||
|
strcpy(key, com_token);
|
||||||
|
while (key[strlen(key)-1] == ' ') // remove trailing spaces
|
||||||
|
key[strlen(key)-1] = 0;
|
||||||
|
data = COM_Parse(data);
|
||||||
|
if (!data)
|
||||||
|
break; // error
|
||||||
|
if (!q_strncasecmp("texpart_", key, 8))
|
||||||
{
|
{
|
||||||
if (!q_strcasecmp(key+8, m->textures[t]->name))
|
/*in quakespasm there are always two textures added on the end (rather than pointing to textures outside the model)*/
|
||||||
remaps[t] = PScript_FindParticleType(com_token);
|
for (t = 0; t < m->numtextures-2; t++)
|
||||||
|
{
|
||||||
|
if (!q_strcasecmp(key+8, m->textures[t]->name))
|
||||||
|
remaps[t] = PScript_FindParticleType(com_token);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (t = 0; t < m->numtextures; t++)
|
for (t = 0; t < m->numtextures; t++)
|
||||||
{
|
|
||||||
ptype = remaps[t];
|
|
||||||
if (ptype == P_INVALID)
|
|
||||||
ptype = PScript_FindParticleType(va("tex_%s", m->textures[t]->name));
|
|
||||||
|
|
||||||
if (ptype >= 0)
|
|
||||||
{
|
{
|
||||||
for (i=0; i<m->nummodelsurfaces; i++)
|
ptype = remaps[t];
|
||||||
|
if (ptype == P_INVALID)
|
||||||
|
ptype = PScript_FindParticleType(va("tex_%s", m->textures[t]->name));
|
||||||
|
|
||||||
|
if (ptype >= 0)
|
||||||
{
|
{
|
||||||
surf = m->surfaces + i + m->firstmodelsurface;
|
for (i=0; i<m->nummodelsurfaces; i++)
|
||||||
if (surf->texinfo->texture == m->textures[t])
|
|
||||||
{
|
{
|
||||||
/*FIXME: it would be a good idea to determine the surface's (midpoint) pvs cluster so that we're not spamming for the entire map*/
|
surf = m->surfaces + i + m->firstmodelsurface;
|
||||||
PScript_EmitSkyEffectTris(m, surf, ptype);
|
if (surf->texinfo->texture == m->textures[t])
|
||||||
|
{
|
||||||
|
/*FIXME: it would be a good idea to determine the surface's (midpoint) pvs cluster so that we're not spamming for the entire map*/
|
||||||
|
PScript_EmitSkyEffectTris(m, surf, ptype);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
free(remaps);
|
||||||
}
|
}
|
||||||
free(remaps);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -3546,19 +3639,15 @@ void PScript_ClearParticles (void)
|
||||||
part_type[i].beams = NULL;
|
part_type[i].beams = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
skytris = NULL;
|
PScript_ClearAllSurfaceParticles();
|
||||||
while(skytrimem)
|
|
||||||
{
|
|
||||||
void *f = skytrimem;
|
|
||||||
skytrimem = skytrimem->next;
|
|
||||||
Z_Free(f);
|
|
||||||
}
|
|
||||||
r_plooksdirty = true;
|
r_plooksdirty = true;
|
||||||
|
|
||||||
|
CL_ClearTrailStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
static qboolean P_LoadParticleSet(char *name, qboolean implicit)
|
static qboolean P_LoadParticleSet(char *name, qboolean implicit, qboolean showwarning)
|
||||||
{
|
{
|
||||||
FILE *file;
|
char *file;
|
||||||
pcfg_t *cfg;
|
pcfg_t *cfg;
|
||||||
|
|
||||||
if (!*name)
|
if (!*name)
|
||||||
|
@ -3591,13 +3680,13 @@ static qboolean P_LoadParticleSet(char *name, qboolean implicit)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
COM_FOpenFile(va("particles/%s.cfg", name), &file, NULL);
|
file = (char*)COM_LoadMallocFile(va("particles/%s.cfg", name), NULL);
|
||||||
if (!file)
|
if (!file)
|
||||||
COM_FOpenFile(va("%s.cfg", name), &file, NULL);
|
file = (char*)COM_LoadMallocFile(va("%s.cfg", name), NULL);
|
||||||
if (file)
|
if (file)
|
||||||
{
|
{
|
||||||
PScript_ParseParticleEffectFile(name, implicit, file);
|
PScript_ParseParticleEffectFile(name, implicit, file, com_filesize);
|
||||||
fclose(file);
|
free(file);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -3609,15 +3698,10 @@ static qboolean P_LoadParticleSet(char *name, qboolean implicit)
|
||||||
P_ImportEffectInfo_Name(name);
|
P_ImportEffectInfo_Name(name);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (P_LoadParticleSet("high", true))
|
|
||||||
Con_Printf(CON_WARNING "Couldn't find particle description %s, loading 'high' instead\n", name);
|
|
||||||
else
|
|
||||||
#endif
|
#endif
|
||||||
{
|
if (showwarning)
|
||||||
Con_Printf(CON_WARNING "Couldn't find particle description %s\n", name);
|
Con_Printf(CON_WARNING "Couldn't find particle description %s\n", name);
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -3664,50 +3748,40 @@ static void R_ParticleDesc_Callback(struct cvar_s *var)
|
||||||
for (c = var->string; (c=COM_Parse(c)); )
|
for (c = var->string; (c=COM_Parse(c)); )
|
||||||
{
|
{
|
||||||
if (*com_token)
|
if (*com_token)
|
||||||
P_LoadParticleSet(com_token, false);
|
P_LoadParticleSet(com_token, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cls.state == ca_connected && cl.model_precache[1])
|
||||||
|
{
|
||||||
|
//per-map configs. because we can.
|
||||||
|
memcpy(com_token, "map_", 4);
|
||||||
|
COM_FileBase(cl.model_precache[1]->name, com_token+4, sizeof(com_token)-4);
|
||||||
|
P_LoadParticleSet(com_token, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//make sure nothing is stale.
|
//make sure nothing is stale.
|
||||||
CL_RegisterParticles();
|
CL_RegisterParticles();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void P_AddRainParticles(void)
|
static void P_AddRainParticles(qmodel_t *mod, vec3_t axis[3], vec3_t eorg, int visframe, float contribution)
|
||||||
{
|
{
|
||||||
float x;
|
float x;
|
||||||
float y;
|
float y;
|
||||||
static float skipped;
|
|
||||||
static float lastrendered;
|
|
||||||
part_type_t *type;
|
part_type_t *type;
|
||||||
|
|
||||||
vec3_t org, vdist;
|
vec3_t org, vdist, worg, wnorm;
|
||||||
|
|
||||||
skytris_t *st;
|
skytris_t *st;
|
||||||
|
if (!r_part_rain_quantity.value)
|
||||||
if (!r_part_rain.value || !r_part_rain_quantity.value)
|
|
||||||
{
|
|
||||||
skipped = true;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (lastrendered < particletime - 0.5)
|
mod->skytime += contribution;
|
||||||
skipped = true; //we've gone for half a sec without any new rain. This would cause some strange effects, so reset times.
|
|
||||||
|
|
||||||
if (skipped)
|
for (st = mod->skytris; st; st = st->next)
|
||||||
{
|
{
|
||||||
for (st = skytris; st; st = st->next)
|
if (st->face->visframe != visframe)
|
||||||
{
|
{
|
||||||
st->nexttime = particletime;
|
st->nexttime = mod->skytime;
|
||||||
}
|
|
||||||
}
|
|
||||||
skipped = false;
|
|
||||||
|
|
||||||
lastrendered = particletime;
|
|
||||||
|
|
||||||
for (st = skytris; st; st = st->next)
|
|
||||||
{
|
|
||||||
if (st->face->visframe != r_visframecount)
|
|
||||||
{
|
|
||||||
st->nexttime = particletime;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3717,46 +3791,46 @@ static void P_AddRainParticles(void)
|
||||||
if (!type->loaded) //woo, batch skipping.
|
if (!type->loaded) //woo, batch skipping.
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
while (st->nexttime < particletime)
|
while (st->nexttime < mod->skytime)
|
||||||
{
|
{
|
||||||
if (!free_particles)
|
if (!free_particles)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
st->nexttime += 10000/(st->area*r_part_rain_quantity.value*type->rainfrequency);
|
st->nexttime += 10000.0/(st->area*r_part_rain_quantity.value*type->rainfrequency);
|
||||||
|
|
||||||
x = frandom()*frandom();
|
x = frandom()*frandom();
|
||||||
y = frandom() * (1-x);
|
y = frandom() * (1-x);
|
||||||
VectorMA(st->org, x, st->x, org);
|
VectorMA(st->org, x, st->x, org);
|
||||||
VectorMA(org, y, st->y, org);
|
VectorMA(org, y, st->y, org);
|
||||||
|
|
||||||
|
worg[0] = DotProduct(org, axis[0]) + eorg[0];
|
||||||
|
worg[1] = -DotProduct(org, axis[1]) + eorg[1];
|
||||||
|
worg[2] = DotProduct(org, axis[2]) + eorg[2];
|
||||||
|
|
||||||
VectorSubtract(org, r_refdef.vieworg, vdist);
|
//ignore it if its too far away
|
||||||
|
VectorSubtract(worg, r_refdef.vieworg, vdist);
|
||||||
if (VectorLength(vdist) > (1024+512)*frandom())
|
if (VectorLength(vdist) > (1024+512)*frandom())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (st->face->flags & SURF_PLANEBACK)
|
if (st->face->flags & SURF_PLANEBACK)
|
||||||
VectorMA(org, -0.5, st->face->plane->normal, org);
|
VectorScale(st->face->plane->normal, -1, vdist);
|
||||||
else
|
else
|
||||||
VectorMA(org, 0.5, st->face->plane->normal, org);
|
VectorCopy(st->face->plane->normal, vdist);
|
||||||
|
|
||||||
if (!(CL_PointContentsMask(org) & FTECONTENTS_SOLID)) //should be paranoia
|
wnorm[0] = DotProduct(vdist, axis[0]);
|
||||||
|
wnorm[1] = -DotProduct(vdist, axis[1]);
|
||||||
|
wnorm[2] = DotProduct(vdist, axis[2]);
|
||||||
|
|
||||||
|
VectorMA(worg, 0.5, wnorm, worg);
|
||||||
|
if (!(CL_PointContentsMask(worg) & FTECONTENTS_SOLID)) //should be paranoia, at least for the world.
|
||||||
{
|
{
|
||||||
if (st->face->flags & SURF_PLANEBACK)
|
PScript_RunParticleEffectState(worg, wnorm, 1, st->ptype, NULL);
|
||||||
{
|
|
||||||
vdist[0] = -st->face->plane->normal[0];
|
|
||||||
vdist[1] = -st->face->plane->normal[1];
|
|
||||||
vdist[2] = -st->face->plane->normal[2];
|
|
||||||
PScript_RunParticleEffectState(org, vdist, 1, st->ptype, NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
PScript_RunParticleEffectState(org, st->face->plane->normal, 1, st->ptype, NULL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void R_Part_SkyTri(float *v1, float *v2, float *v3, msurface_t *surf, int ptype)
|
static void R_Part_SkyTri(qmodel_t *mod, float *v1, float *v2, float *v3, msurface_t *surf, int ptype)
|
||||||
{
|
{
|
||||||
float dot;
|
float dot;
|
||||||
float xm;
|
float xm;
|
||||||
|
@ -3767,13 +3841,13 @@ static void R_Part_SkyTri(float *v1, float *v2, float *v3, msurface_t *surf, int
|
||||||
|
|
||||||
skytris_t *st;
|
skytris_t *st;
|
||||||
|
|
||||||
skytriblock_t *mem = skytrimem;
|
skytriblock_t *mem = mod->skytrimem;
|
||||||
if (!mem || mem->count == sizeof(mem->tris)/sizeof(mem->tris[0]))
|
if (!mem || mem->count == sizeof(mem->tris)/sizeof(mem->tris[0]))
|
||||||
{
|
{
|
||||||
skytrimem = Z_Malloc(sizeof(*skytrimem));
|
mod->skytrimem = Z_Malloc(sizeof(*mod->skytrimem));
|
||||||
skytrimem->next = mem;
|
mod->skytrimem->next = mem;
|
||||||
skytrimem->count = 0;
|
mod->skytrimem->count = 0;
|
||||||
mem = skytrimem;
|
mem = mod->skytrimem;
|
||||||
}
|
}
|
||||||
|
|
||||||
st = &mem->tris[mem->count];
|
st = &mem->tris[mem->count];
|
||||||
|
@ -3793,7 +3867,7 @@ static void R_Part_SkyTri(float *v1, float *v2, float *v3, msurface_t *surf, int
|
||||||
dot = DotProduct(xd, yd);
|
dot = DotProduct(xd, yd);
|
||||||
theta = acos(dot/(xm*ym));
|
theta = acos(dot/(xm*ym));
|
||||||
st->area = sin(theta)*xm*ym;
|
st->area = sin(theta)*xm*ym;
|
||||||
st->nexttime = particletime;
|
st->nexttime = mod->skytime;
|
||||||
st->face = surf;
|
st->face = surf;
|
||||||
st->ptype = ptype;
|
st->ptype = ptype;
|
||||||
|
|
||||||
|
@ -3801,8 +3875,8 @@ static void R_Part_SkyTri(float *v1, float *v2, float *v3, msurface_t *surf, int
|
||||||
return;//bummer.
|
return;//bummer.
|
||||||
mem->count++;
|
mem->count++;
|
||||||
|
|
||||||
st->next = skytris;
|
st->next = mod->skytris;
|
||||||
skytris = st;
|
mod->skytris = st;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3846,7 +3920,7 @@ void PScript_EmitSkyEffectTris(qmodel_t *mod, msurface_t *fa, int ptype)
|
||||||
v2 = 1;
|
v2 = 1;
|
||||||
for (v3 = 2; v3 < numverts; v3++)
|
for (v3 = 2; v3 < numverts; v3++)
|
||||||
{
|
{
|
||||||
R_Part_SkyTri(verts[v1], verts[v2], verts[v3], fa, ptype);
|
R_Part_SkyTri(mod, verts[v1], verts[v2], verts[v3], fa, ptype);
|
||||||
|
|
||||||
v2 = v3;
|
v2 = v3;
|
||||||
}
|
}
|
||||||
|
@ -3866,7 +3940,7 @@ static void P_CleanTrailstate(trailstate_t *ts)
|
||||||
memset(ts, 0, sizeof(trailstate_t));
|
memset(ts, 0, sizeof(trailstate_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PScript_DelinkTrailstate(trailstate_t **tsk)
|
void PScript_DelinkTrailstate(trailstate_t **tsk)
|
||||||
{
|
{
|
||||||
trailstate_t *ts;
|
trailstate_t *ts;
|
||||||
trailstate_t *assoc;
|
trailstate_t *assoc;
|
||||||
|
@ -5335,8 +5409,17 @@ int PScript_RunParticleEffectState (vec3_t org, vec3_t dir, float count, int typ
|
||||||
// maintain run list
|
// maintain run list
|
||||||
if (!(ptype->state & PS_INRUNLIST) && (ptype->particles || ptype->clippeddecals))
|
if (!(ptype->state & PS_INRUNLIST) && (ptype->particles || ptype->clippeddecals))
|
||||||
{
|
{
|
||||||
ptype->nexttorun = part_run_list;
|
if (part_run_list)
|
||||||
part_run_list = ptype;
|
{
|
||||||
|
//insert after, to try to avoid edge-case weirdness
|
||||||
|
ptype->nexttorun = part_run_list->nexttorun;
|
||||||
|
part_run_list->nexttorun = ptype;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ptype->nexttorun = part_run_list;
|
||||||
|
part_run_list = ptype;
|
||||||
|
}
|
||||||
ptype->state |= PS_INRUNLIST;
|
ptype->state |= PS_INRUNLIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6220,7 +6303,6 @@ int PScript_ParticleTrail (vec3_t startpos, vec3_t end, int type, int dlkey, vec
|
||||||
}
|
}
|
||||||
|
|
||||||
static vec3_t pright, pup;
|
static vec3_t pright, pup;
|
||||||
static float pframetime;
|
|
||||||
|
|
||||||
static void R_AddFanSparkParticle(scenetris_t *t, particle_t *p, plooks_t *type)
|
static void R_AddFanSparkParticle(scenetris_t *t, particle_t *p, plooks_t *type)
|
||||||
{
|
{
|
||||||
|
@ -6761,7 +6843,7 @@ static void R_AddTexturedParticle(scenetris_t *t, particle_t *p, plooks_t *type)
|
||||||
t->numidx += 6;
|
t->numidx += 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PScript_DrawParticleTypes (void)
|
static void PScript_DrawParticleTypes (float pframetime)
|
||||||
{
|
{
|
||||||
#if UNSUPPORTED
|
#if UNSUPPORTED
|
||||||
float viewtranslation[16];
|
float viewtranslation[16];
|
||||||
|
@ -6788,7 +6870,6 @@ static void PScript_DrawParticleTypes (void)
|
||||||
|
|
||||||
int traces=r_particle_tracelimit.value;
|
int traces=r_particle_tracelimit.value;
|
||||||
int rampind;
|
int rampind;
|
||||||
static float oldtime;
|
|
||||||
static float flurrytime;
|
static float flurrytime;
|
||||||
qboolean doflurry;
|
qboolean doflurry;
|
||||||
int batchflags;
|
int batchflags;
|
||||||
|
@ -6821,11 +6902,6 @@ static void PScript_DrawParticleTypes (void)
|
||||||
PScript_RecalculateSkyTris();
|
PScript_RecalculateSkyTris();
|
||||||
}
|
}
|
||||||
|
|
||||||
pframetime = cl.time - oldtime;
|
|
||||||
if (pframetime < 0)
|
|
||||||
pframetime = 0;
|
|
||||||
oldtime = cl.time;
|
|
||||||
|
|
||||||
VectorScale (vup, 1.5, pup);
|
VectorScale (vup, 1.5, pup);
|
||||||
VectorScale (vright, 1.5, pright);
|
VectorScale (vright, 1.5, pright);
|
||||||
|
|
||||||
|
@ -7516,7 +7592,7 @@ static void PScript_DrawParticleTypes (void)
|
||||||
{
|
{
|
||||||
VectorAdd(stop, oldorg, stop);
|
VectorAdd(stop, oldorg, stop);
|
||||||
VectorScale(stop, 0.5, stop);
|
VectorScale(stop, 0.5, stop);
|
||||||
#ifdef UNSUPPORTED
|
#if UNSUPPORTED
|
||||||
RQ_AddDistReorder(bdraw, b, type->slooks, stop);
|
RQ_AddDistReorder(bdraw, b, type->slooks, stop);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -7548,8 +7624,10 @@ endtype:
|
||||||
{
|
{
|
||||||
if (!lastvalidtype)
|
if (!lastvalidtype)
|
||||||
part_run_list = type->nexttorun;
|
part_run_list = type->nexttorun;
|
||||||
else
|
else if (lastvalidtype->nexttorun == type)
|
||||||
lastvalidtype->nexttorun = type->nexttorun;
|
lastvalidtype->nexttorun = type->nexttorun;
|
||||||
|
else
|
||||||
|
lastvalidtype->nexttorun->nexttorun = type->nexttorun;
|
||||||
type->state &= ~PS_INRUNLIST;
|
type->state &= ~PS_INRUNLIST;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -7641,6 +7719,7 @@ endtype:
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
glShadeModel(GL_FLAT);
|
glShadeModel(GL_FLAT);
|
||||||
glDepthMask(GL_TRUE);
|
glDepthMask(GL_TRUE);
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
GL_PolygonOffset (OFFSET_NONE);
|
GL_PolygonOffset (OFFSET_NONE);
|
||||||
cl_numstris = 0;
|
cl_numstris = 0;
|
||||||
|
@ -7655,9 +7734,38 @@ R_DrawParticles
|
||||||
*/
|
*/
|
||||||
void PScript_DrawParticles (void)
|
void PScript_DrawParticles (void)
|
||||||
{
|
{
|
||||||
P_AddRainParticles();
|
int i;
|
||||||
|
entity_t *ent;
|
||||||
|
vec3_t axis[3];
|
||||||
|
float pframetime;
|
||||||
|
static float oldtime;
|
||||||
|
|
||||||
|
pframetime = cl.time - oldtime;
|
||||||
|
if (pframetime < 0)
|
||||||
|
pframetime = 0;
|
||||||
|
if (pframetime > 1)
|
||||||
|
pframetime = 1;
|
||||||
|
oldtime = cl.time;
|
||||||
|
|
||||||
PScript_DrawParticleTypes();
|
if (r_part_rain.value)
|
||||||
|
{
|
||||||
|
for (i = 0; i < cl.num_entities; i++)
|
||||||
|
{
|
||||||
|
ent = &cl_entities[i];
|
||||||
|
if (!ent->model || ent->model->needload)
|
||||||
|
continue;
|
||||||
|
if (!ent->model->skytris)
|
||||||
|
continue;
|
||||||
|
AngleVectors(ent->angles, axis[0], axis[1], axis[2]);
|
||||||
|
//this timer, as well as the per-tri timer, are unable to deal with certain rates+sizes. it would be good to fix that...
|
||||||
|
//it would also be nice to do mdls too...
|
||||||
|
P_AddRainParticles(ent->model, axis, ent->origin, ((i==0)?r_visframecount:0), pframetime);
|
||||||
|
}
|
||||||
|
|
||||||
|
//FIXME: static entities too!
|
||||||
|
}
|
||||||
|
|
||||||
|
PScript_DrawParticleTypes(pframetime);
|
||||||
|
|
||||||
// if (fallback)
|
// if (fallback)
|
||||||
// fallback->DrawParticles();
|
// fallback->DrawParticles();
|
||||||
|
|
|
@ -80,6 +80,10 @@ typedef struct
|
||||||
byte multicast_buf[MAX_DATAGRAM];
|
byte multicast_buf[MAX_DATAGRAM];
|
||||||
|
|
||||||
const char *particle_precache[MAX_PARTICLETYPES]; // NULL terminated
|
const char *particle_precache[MAX_PARTICLETYPES]; // NULL terminated
|
||||||
|
|
||||||
|
entity_state_t *static_entities;
|
||||||
|
int num_statics;
|
||||||
|
int max_statics;
|
||||||
} server_t;
|
} server_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -148,7 +148,7 @@ static unsigned int SVFTE_DeltaCalcBits(entity_state_t *from, entity_state_t *to
|
||||||
bits |= UF_PREDINFO|UF_MOVETYPE;
|
bits |= UF_PREDINFO|UF_MOVETYPE;
|
||||||
/* if (from->weaponframe != to->weaponframe)
|
/* if (from->weaponframe != to->weaponframe)
|
||||||
bits |= UF_PREDINFO|UF_WEAPONFRAME_OLD;
|
bits |= UF_PREDINFO|UF_WEAPONFRAME_OLD;
|
||||||
*/ if (to->pmovetype)
|
*/// if (to->pmovetype) //we don't support prediction, but we still need to network the player's velocity for bob etc.
|
||||||
{
|
{
|
||||||
if (SVFTE_DeltaPredCalcBits(from, to))
|
if (SVFTE_DeltaPredCalcBits(from, to))
|
||||||
bits |= UF_PREDINFO;
|
bits |= UF_PREDINFO;
|
||||||
|
@ -224,7 +224,7 @@ static unsigned int SVFTE_DeltaCalcBits(entity_state_t *from, entity_state_t *to
|
||||||
// if (to->light[0] != from->light[0] || to->light[1] != from->light[1] || to->light[2] != from->light[2] || to->light[3] != from->light[3] || to->lightstyle != from->lightstyle || to->lightpflags != from->lightpflags)
|
// if (to->light[0] != from->light[0] || to->light[1] != from->light[1] || to->light[2] != from->light[2] || to->light[3] != from->light[3] || to->lightstyle != from->lightstyle || to->lightpflags != from->lightpflags)
|
||||||
// bits |= UF_LIGHT;
|
// bits |= UF_LIGHT;
|
||||||
|
|
||||||
if (to->traileffectnum != from->traileffectnum)
|
if (to->traileffectnum != from->traileffectnum || to->emiteffectnum != from->emiteffectnum)
|
||||||
bits |= UF_TRAILEFFECT;
|
bits |= UF_TRAILEFFECT;
|
||||||
|
|
||||||
// if (to->modelindex2 != from->modelindex2)
|
// if (to->modelindex2 != from->modelindex2)
|
||||||
|
@ -493,7 +493,15 @@ static void SVFTE_WriteEntityUpdate(unsigned int bits, entity_state_t *state, si
|
||||||
MSG_WriteByte (msg, state->lightpflags);
|
MSG_WriteByte (msg, state->lightpflags);
|
||||||
}
|
}
|
||||||
*/ if (bits & UF_TRAILEFFECT)
|
*/ if (bits & UF_TRAILEFFECT)
|
||||||
MSG_WriteShort(msg, state->traileffectnum);
|
{
|
||||||
|
if (state->emiteffectnum)
|
||||||
|
{ //3 spare bits. so that's nice (this is guarenteed to be 14 bits max due to precaches using the upper two bits).
|
||||||
|
MSG_WriteShort(msg, (state->traileffectnum&0x3fff)|0x8000);
|
||||||
|
MSG_WriteShort(msg, state->emiteffectnum&0x3fff);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
MSG_WriteShort(msg, state->traileffectnum&0x3fff);
|
||||||
|
}
|
||||||
|
|
||||||
/* if (bits & UF_COLORMOD)
|
/* if (bits & UF_COLORMOD)
|
||||||
{
|
{
|
||||||
|
@ -879,6 +887,7 @@ void SVFTE_BuildSnapshotForClient (client_t *client)
|
||||||
struct entity_num_state_s *ents = snapshot_entstate;
|
struct entity_num_state_s *ents = snapshot_entstate;
|
||||||
size_t numents = 0;
|
size_t numents = 0;
|
||||||
size_t maxents = snapshot_maxents;
|
size_t maxents = snapshot_maxents;
|
||||||
|
int emiteffect;
|
||||||
|
|
||||||
// find the client's PVS
|
// find the client's PVS
|
||||||
VectorAdd (clent->v.origin, clent->v.view_ofs, org);
|
VectorAdd (clent->v.origin, clent->v.view_ofs, org);
|
||||||
|
@ -892,10 +901,11 @@ void SVFTE_BuildSnapshotForClient (client_t *client)
|
||||||
for (e=1 ; e<maxentities ; e++, ent = NEXT_EDICT(ent))
|
for (e=1 ; e<maxentities ; e++, ent = NEXT_EDICT(ent))
|
||||||
{
|
{
|
||||||
eflags = 0;
|
eflags = 0;
|
||||||
|
emiteffect = GetEdictFieldValue(ent, pr_extfields.emiteffectnum)->_float;
|
||||||
if (ent != clent) // clent is ALLWAYS sent
|
if (ent != clent) // clent is ALLWAYS sent
|
||||||
{
|
{
|
||||||
// ignore ents without visible models
|
// ignore ents without visible models
|
||||||
if (!ent->v.modelindex || !PR_GetString(ent->v.model)[0])
|
if ((!ent->v.modelindex || !PR_GetString(ent->v.model)[0]) && !emiteffect)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
//johnfitz -- don't send model>255 entities if protocol is 15
|
//johnfitz -- don't send model>255 entities if protocol is 15
|
||||||
|
@ -907,7 +917,7 @@ void SVFTE_BuildSnapshotForClient (client_t *client)
|
||||||
eflags |= EFLAGS_VIEWMODEL;
|
eflags |= EFLAGS_VIEWMODEL;
|
||||||
else if (val && val->edict)
|
else if (val && val->edict)
|
||||||
continue;
|
continue;
|
||||||
else
|
else if (ent->num_leafs)
|
||||||
{
|
{
|
||||||
// ignore if not touching a PV leaf
|
// ignore if not touching a PV leaf
|
||||||
for (i=0 ; i < ent->num_leafs ; i++)
|
for (i=0 ; i < ent->num_leafs ; i++)
|
||||||
|
@ -958,6 +968,7 @@ void SVFTE_BuildSnapshotForClient (client_t *client)
|
||||||
ents[numents].state.traileffectnum = val->_float;
|
ents[numents].state.traileffectnum = val->_float;
|
||||||
else
|
else
|
||||||
ents[numents].state.traileffectnum = 0;
|
ents[numents].state.traileffectnum = 0;
|
||||||
|
ents[numents].state.emiteffectnum = emiteffect;
|
||||||
ents[numents].state.effects = ent->v.effects;
|
ents[numents].state.effects = ent->v.effects;
|
||||||
if (!ent->v.movetype || ent->v.movetype == MOVETYPE_STEP)
|
if (!ent->v.movetype || ent->v.movetype == MOVETYPE_STEP)
|
||||||
eflags |= EFLAGS_STEP;
|
eflags |= EFLAGS_STEP;
|
||||||
|
@ -1090,6 +1101,10 @@ void SV_Init (void)
|
||||||
Cvar_RegisterVariable (&pr_checkextension);
|
Cvar_RegisterVariable (&pr_checkextension);
|
||||||
Cvar_RegisterVariable (&sv_altnoclip); //johnfitz
|
Cvar_RegisterVariable (&sv_altnoclip); //johnfitz
|
||||||
|
|
||||||
|
if (isDedicated)
|
||||||
|
sv_public.string = "1";
|
||||||
|
else
|
||||||
|
sv_public.string = "0";
|
||||||
Cvar_RegisterVariable (&sv_public);
|
Cvar_RegisterVariable (&sv_public);
|
||||||
Cvar_RegisterVariable (&sv_reportheartbeats);
|
Cvar_RegisterVariable (&sv_reportheartbeats);
|
||||||
Cvar_RegisterVariable (&com_protocolname);
|
Cvar_RegisterVariable (&com_protocolname);
|
||||||
|
@ -2242,7 +2257,7 @@ qboolean SV_SendClientDatagram (client_t *client)
|
||||||
// send the datagram
|
// send the datagram
|
||||||
if (NET_SendUnreliableMessage (client->netconnection, &msg) == -1)
|
if (NET_SendUnreliableMessage (client->netconnection, &msg) == -1)
|
||||||
{
|
{
|
||||||
SV_DropClient (true);// if the message couldn't send, kick off
|
SV_DropClient (false);// if the message couldn't send, kick off
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2308,7 +2323,7 @@ void SV_SendNop (client_t *client)
|
||||||
MSG_WriteChar (&msg, svc_nop);
|
MSG_WriteChar (&msg, svc_nop);
|
||||||
|
|
||||||
if (NET_SendUnreliableMessage (client->netconnection, &msg) == -1)
|
if (NET_SendUnreliableMessage (client->netconnection, &msg) == -1)
|
||||||
SV_DropClient (true); // if the message couldn't send, kick off
|
SV_DropClient (false); // if the message couldn't send, kick off
|
||||||
client->last_message = realtime;
|
client->last_message = realtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2332,6 +2347,85 @@ int SV_SendPrespawnParticlePrecaches(int idx)
|
||||||
return -1;
|
return -1;
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
int SV_SendPrespawnStatics(int idx)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
entity_state_t *svent;
|
||||||
|
int maxsize = host_client->message.maxsize - 128; //we can go quite large
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (idx >= sv.num_statics)
|
||||||
|
return -1;
|
||||||
|
svent = &sv.static_entities[idx];
|
||||||
|
|
||||||
|
if (host_client->message.cursize > maxsize)
|
||||||
|
break;
|
||||||
|
idx++;
|
||||||
|
|
||||||
|
if (svent->modelindex >= host_client->limit_models)
|
||||||
|
continue;
|
||||||
|
if (memcmp(&nullentitystate, svent, sizeof(nullentitystate)))
|
||||||
|
{
|
||||||
|
if (host_client->protocol_pext2 & PEXT2_REPLACEMENTDELTAS)
|
||||||
|
{
|
||||||
|
MSG_WriteByte(&host_client->message, svcfte_spawnstatic2);
|
||||||
|
SVFTE_WriteEntityUpdate(SVFTE_DeltaCalcBits(&nullentitystate, svent), svent, &host_client->message, host_client->protocol_pext2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//johnfitz -- PROTOCOL_FITZQUAKE
|
||||||
|
int bits = 0;
|
||||||
|
if (sv.protocol == PROTOCOL_FITZQUAKE) //still want to send baseline in PROTOCOL_NETQUAKE, so reset these values
|
||||||
|
{
|
||||||
|
if (svent->modelindex & 0xFF00)
|
||||||
|
bits |= B_LARGEMODEL;
|
||||||
|
if (svent->frame & 0xFF00)
|
||||||
|
bits |= B_LARGEFRAME;
|
||||||
|
if (svent->alpha != ENTALPHA_DEFAULT)
|
||||||
|
bits |= B_ALPHA;
|
||||||
|
}
|
||||||
|
else if (svent->frame > 0xff)
|
||||||
|
continue; //can't send these with the vanilla protcol (yay pext).
|
||||||
|
|
||||||
|
if (bits)
|
||||||
|
MSG_WriteByte (&host_client->message, svc_spawnstatic2);
|
||||||
|
else
|
||||||
|
MSG_WriteByte (&host_client->message, svc_spawnstatic);
|
||||||
|
//johnfitz
|
||||||
|
|
||||||
|
//johnfitz -- PROTOCOL_FITZQUAKE
|
||||||
|
if (bits)
|
||||||
|
MSG_WriteByte (&host_client->message, bits);
|
||||||
|
|
||||||
|
if (bits & B_LARGEMODEL)
|
||||||
|
MSG_WriteShort (&host_client->message, svent->modelindex);
|
||||||
|
else
|
||||||
|
MSG_WriteByte (&host_client->message, svent->modelindex);
|
||||||
|
|
||||||
|
if (bits & B_LARGEFRAME)
|
||||||
|
MSG_WriteShort (&host_client->message, svent->frame);
|
||||||
|
else
|
||||||
|
MSG_WriteByte (&host_client->message, svent->frame);
|
||||||
|
//johnfitz
|
||||||
|
|
||||||
|
MSG_WriteByte (&host_client->message, svent->colormap);
|
||||||
|
MSG_WriteByte (&host_client->message, svent->skin);
|
||||||
|
for (i=0 ; i<3 ; i++)
|
||||||
|
{
|
||||||
|
MSG_WriteCoord(&host_client->message, svent->origin[i], sv.protocolflags);
|
||||||
|
MSG_WriteAngle(&host_client->message, svent->angles[i], sv.protocolflags);
|
||||||
|
}
|
||||||
|
|
||||||
|
//johnfitz -- PROTOCOL_FITZQUAKE
|
||||||
|
if (bits & B_ALPHA)
|
||||||
|
MSG_WriteByte (&host_client->message, svent->alpha);
|
||||||
|
//johnfitz
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
int SV_SendPrespawnBaselines(int idx)
|
int SV_SendPrespawnBaselines(int idx)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -2466,6 +2560,15 @@ void SV_SendClientMessages (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (host_client->sendsignon == 4)
|
if (host_client->sendsignon == 4)
|
||||||
|
{
|
||||||
|
host_client->signonidx = SV_SendPrespawnStatics(host_client->signonidx);
|
||||||
|
if (host_client->signonidx < 0)
|
||||||
|
{
|
||||||
|
host_client->signonidx = 0;
|
||||||
|
host_client->sendsignon++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (host_client->sendsignon == 5)
|
||||||
{
|
{
|
||||||
if (host_client->message.cursize+sv.signon.cursize+2 < host_client->message.maxsize)
|
if (host_client->message.cursize+sv.signon.cursize+2 < host_client->message.maxsize)
|
||||||
{
|
{
|
||||||
|
@ -2482,8 +2585,8 @@ void SV_SendClientMessages (void)
|
||||||
// changes level
|
// changes level
|
||||||
if (host_client->message.overflowed)
|
if (host_client->message.overflowed)
|
||||||
{
|
{
|
||||||
SV_DropClient (true);
|
SZ_Clear(&host_client->message);
|
||||||
host_client->message.overflowed = false;
|
SV_DropClient (false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2501,7 +2604,7 @@ void SV_SendClientMessages (void)
|
||||||
{
|
{
|
||||||
if (NET_SendMessage (host_client->netconnection
|
if (NET_SendMessage (host_client->netconnection
|
||||||
, &host_client->message) == -1)
|
, &host_client->message) == -1)
|
||||||
SV_DropClient (true); // if the message couldn't send, kick off
|
SV_DropClient (false); // if the message couldn't send, kick off
|
||||||
SZ_Clear (&host_client->message);
|
SZ_Clear (&host_client->message);
|
||||||
host_client->last_message = realtime;
|
host_client->last_message = realtime;
|
||||||
if (host_client->sendsignon == true)
|
if (host_client->sendsignon == true)
|
||||||
|
@ -2720,6 +2823,9 @@ void SV_SpawnServer (const char *server)
|
||||||
sv.max_edicts = CLAMP (MIN_EDICTS,(int)max_edicts.value,MAX_EDICTS); //johnfitz -- max_edicts cvar
|
sv.max_edicts = CLAMP (MIN_EDICTS,(int)max_edicts.value,MAX_EDICTS); //johnfitz -- max_edicts cvar
|
||||||
sv.edicts = (edict_t *) malloc (sv.max_edicts*pr_edict_size); // ericw -- sv.edicts switched to use malloc()
|
sv.edicts = (edict_t *) malloc (sv.max_edicts*pr_edict_size); // ericw -- sv.edicts switched to use malloc()
|
||||||
|
|
||||||
|
sv.max_statics = MAX_STATIC_ENTITIES;
|
||||||
|
sv.static_entities = Hunk_Alloc(sv.max_statics * sizeof(*sv.static_entities));
|
||||||
|
|
||||||
sv.datagram.maxsize = sizeof(sv.datagram_buf);
|
sv.datagram.maxsize = sizeof(sv.datagram_buf);
|
||||||
sv.datagram.cursize = 0;
|
sv.datagram.cursize = 0;
|
||||||
sv.datagram.data = sv.datagram_buf;
|
sv.datagram.data = sv.datagram_buf;
|
||||||
|
|
116
weather.cfg
Executable file
116
weather.cfg
Executable file
|
@ -0,0 +1,116 @@
|
||||||
|
//lame example weather particles by Spike
|
||||||
|
//move to id1/particles/weather.cfg
|
||||||
|
//
|
||||||
|
//to use from qc, r_particledesc "weather classic" or call particleeffecnum("weather.te_rain") so the engine knows which config to use, then use the particle[rain|snow] builtins as normal.
|
||||||
|
//without qc changes option 1) use a texture called skyrain or skysnow, in addition to the r_particledesc thing so that this config is actually used (this is more for people to add stuff to existing maps).
|
||||||
|
//without qc changes option 2) add a worldspawn field called "_texpart_TEXTURENAME" with value "weather.tex_skysnow" or "weather.tex_skyrain"
|
||||||
|
//without qc changes option 3) an equivelent console command: r_partredirect tex_TEXTURENAME "weather.tex_skysnow"
|
||||||
|
//note that without qc, you need to restart the map for it to take effect.
|
||||||
|
//on the other hand, if you wanted to emit particles from models, use r_effect (which can optionally hide those models too).
|
||||||
|
//to override trails defined by model flags, you can use the r_trail command.
|
||||||
|
//weather effects that leave decals are probably overkill
|
||||||
|
//one option is to spawn a particle from qc that emits other particles that leave trails. emitting such trail emitting emitters from surfaces is definitely overkill.
|
||||||
|
|
||||||
|
//generic rain for the qc builtin
|
||||||
|
//create another called te_rain_12 or whatever for alternative versions of rain (going by the specified palette)
|
||||||
|
r_part te_rain
|
||||||
|
{
|
||||||
|
texture ball
|
||||||
|
scalefactor 1
|
||||||
|
count 1
|
||||||
|
alpha 0.4
|
||||||
|
rgb 255 255 255
|
||||||
|
die 2
|
||||||
|
veladd 2
|
||||||
|
scale 2
|
||||||
|
stretchfactor -40
|
||||||
|
type texturedspark
|
||||||
|
cliptype weather.rainsplash
|
||||||
|
clipbounce 100
|
||||||
|
clipcount 5
|
||||||
|
}
|
||||||
|
|
||||||
|
//internal splash effect for rain
|
||||||
|
r_part weather.rainsplash
|
||||||
|
{
|
||||||
|
randomvel 50 50
|
||||||
|
count 1
|
||||||
|
texture ball
|
||||||
|
scalefactor 1
|
||||||
|
alpha 0.1
|
||||||
|
rgb 255 255 255
|
||||||
|
die 0.4
|
||||||
|
scale 50
|
||||||
|
stretchfactor -2.5
|
||||||
|
veladd 1
|
||||||
|
scale 1
|
||||||
|
type texturedspark
|
||||||
|
gravity 800
|
||||||
|
}
|
||||||
|
|
||||||
|
//generic snow for the qc builtin
|
||||||
|
//naming itself causes it to bounce
|
||||||
|
r_part te_snow
|
||||||
|
{
|
||||||
|
texture ball
|
||||||
|
scalefactor 1
|
||||||
|
count 1
|
||||||
|
alpha 1
|
||||||
|
rgb 255 255 255
|
||||||
|
die 2
|
||||||
|
veladd 1
|
||||||
|
scale 5
|
||||||
|
flurry 40
|
||||||
|
gravity 400
|
||||||
|
friction 5
|
||||||
|
|
||||||
|
//settle
|
||||||
|
clipbounce 0
|
||||||
|
}
|
||||||
|
|
||||||
|
//rain effect to be emitted from textures
|
||||||
|
//the base direction points away from the surface, so veladd is the speed to move away from said surface.
|
||||||
|
//this isn't very useful for rain, because that vector is quite often horizontal (where the sky surrounds the player)
|
||||||
|
//that said, sitting in a box of such rain surfaces gives an interesting laser-field effect...
|
||||||
|
//anyway, that's why we can't reuse the qc effects, because qc gives a velocity that is actually meant to be usable.
|
||||||
|
r_part tex_skyrain
|
||||||
|
{
|
||||||
|
texture ball
|
||||||
|
scalefactor 1
|
||||||
|
rainfrequency 10
|
||||||
|
count 1
|
||||||
|
alpha 0.1
|
||||||
|
rgb 255 255 255
|
||||||
|
die 2
|
||||||
|
veladd 0
|
||||||
|
velbias -200 -200 -2000 //move sideways slightly in the same direction as the sky
|
||||||
|
scale 1
|
||||||
|
stretchfactor -40
|
||||||
|
type texturedspark
|
||||||
|
cliptype weather.rainsplash
|
||||||
|
clipbounce 100
|
||||||
|
clipcount 5
|
||||||
|
}
|
||||||
|
|
||||||
|
//snow from sky surfaces is often within a box
|
||||||
|
//this means we don't want the snow to ever settle.
|
||||||
|
//we also have no volume, so make the snow fall a little further.
|
||||||
|
r_part tex_skysnow
|
||||||
|
{
|
||||||
|
texture ball
|
||||||
|
scalefactor 1
|
||||||
|
rainfrequency 2
|
||||||
|
count 1
|
||||||
|
alpha 1
|
||||||
|
rgb 255 255 255
|
||||||
|
die 8
|
||||||
|
veladd 0
|
||||||
|
velbias 0 0 -100
|
||||||
|
scale 5
|
||||||
|
flurry 40
|
||||||
|
gravity 400
|
||||||
|
friction 5
|
||||||
|
|
||||||
|
cliptype tex_skysnow
|
||||||
|
clipbounce 0
|
||||||
|
}
|
Loading…
Reference in a new issue