2 float bgmscriptbufsize;
3 float bgmscriptbufloaded;
7 .float bgmscriptvelocity;
10 .float bgmscriptstatetime;
11 .float bgmscriptdelta;
13 float GetAttackDecaySustainAmplitude(float a, float d, float s, float t)
16 // attack: from 0 to 1, in time a for a full length
17 // decay: from 1 to s, in time d
29 return ((t - a) / d) * (s - 1) + 1;
34 float GetReleaseAmplitude(float d, float s, float r, float t)
36 float decayval, releaseval;
44 releaseval = s * (1 - t / r);
52 // value is s at time 0
54 decayval = ((t + d) / d) * (s - 1) + 1;
55 return max(decayval, releaseval);
61 float GetAttackTime(float a, float amp)
66 float GetReleaseTime(float d, float s, float r, float amp)
68 float decaytime, releasetime;
73 // if amp > s, we may be in the attack or in the prolonged decay curve
74 releasetime = (1 - amp / s) * r;
78 if(s == 1) // gracefully handle division by zero here
82 // value is s at time 0
84 decaytime = (amp - 1) / (s - 1) * d - d;
85 return max(decaytime, releasetime);
95 bgmscriptbuf = bgmscriptbufsize = 0;
96 bgmscriptbufloaded = 1;
97 s = strcat("maps/", mi_shortname, ".bgs");
98 fh = fopen(s, FILE_READ);
101 bgmscriptbuf = buf_create();
102 while((s = fgets(fh)))
104 bufstr_set(bgmscriptbuf, bgmscriptbufsize, s);
110 void BGMScript_InitEntity(entity e)
114 if(e.bgmscript != "")
116 if(!bgmscriptbufloaded)
121 m = strcat(e.bgmscript, " ");
124 e.bgmscriptline0 = -1;
125 for(i = 0; i < bgmscriptbufsize; ++i)
127 if(substring(bufstr_get(bgmscriptbuf, i), 0, l) == m)
130 e.bgmscriptline = e.bgmscriptline0 = i;
131 if(i >= bgmscriptbufsize)
133 print("func_pointparticles: bgmscript does not define ", e.bgmscript, "\n");
139 float BGMScript(entity e)
144 if(e.bgmscript == "")
147 if(cvar("bgmvolume") <= 0)
150 e.just_toggled = FALSE;
152 t = gettime(GETTIME_CDTRACK);
153 if(t < e.bgmscripttime)
155 e.bgmscriptline = e.bgmscriptline0;
157 e.bgmscriptstatetime = t - drawframetime - e.bgmscriptdelta; // FIXME this causes a tiny hitch
160 // find the CURRENT line
163 tokenize_sane(bufstr_get(bgmscriptbuf, e.bgmscriptline));
164 if(stof(argv(1)) >= t)
166 if(argv(0) != e.bgmscript)
168 // end of bgmscript, will revert to beginning later
171 else if(t >= stof(argv(1)))
173 e.bgmscriptline += 1;
174 e.bgmscripttime = stof(argv(1));
177 amp = GetAttackDecaySustainAmplitude(e.bgmscriptattack, e.bgmscriptdecay, e.bgmscriptsustain, e.bgmscripttime - e.bgmscriptstatetime) * e.bgmscriptvelocity;
179 amp = GetReleaseAmplitude(e.bgmscriptdecay, e.bgmscriptsustain, e.bgmscriptrelease, e.bgmscripttime - e.bgmscriptstatetime);
181 // time code reached!
182 e.bgmscriptvelocity = stof(argv(2));
183 if(e.bgmscriptvelocity > 0)
184 e.just_toggled = e.bgmscriptstate = TRUE;
186 e.just_toggled = e.bgmscriptstate = FALSE;
189 e.bgmscriptstatetime = e.bgmscripttime - GetAttackTime(e.bgmscriptattack, amp / e.bgmscriptvelocity);
191 e.bgmscriptstatetime = e.bgmscripttime - GetReleaseTime(e.bgmscriptdecay, e.bgmscriptsustain, e.bgmscriptrelease, amp);
197 // attack, decay or sustain
198 e.bgmscriptdelta = t - e.bgmscriptstatetime;
199 return GetAttackDecaySustainAmplitude(e.bgmscriptattack, e.bgmscriptdecay, e.bgmscriptsustain, e.bgmscriptdelta) * e.bgmscriptvelocity;
204 e.bgmscriptdelta = t - e.bgmscriptstatetime;
205 return GetReleaseAmplitude(e.bgmscriptdecay, e.bgmscriptsustain, e.bgmscriptrelease, self.bgmscriptdelta);