1 #define CONSTANT_SPEED_DECAY
\r
4 float bgmscriptbufsize;
\r
5 float bgmscriptbufloaded;
\r
7 .float bgmscriptline;
\r
8 .float bgmscriptline0;
\r
9 .float bgmscriptvolume;
\r
10 .float bgmscripttime;
\r
11 .float bgmscriptstate;
\r
12 .float bgmscriptstatetime;
\r
14 float GetAttackDecaySustainAmplitude(float a, float d, float s, float t)
\r
17 // attack: from 0 to 1, in time a for a full length
\r
18 // decay: from 1 to s, in time d
\r
30 return ((t - a) / d) * (s - 1) + 1;
\r
35 float GetReleaseAmplitude(float d, float s, float r, float t)
\r
37 float decayval, releaseval;
\r
45 releaseval = s * (1 - t / r);
\r
50 if(t < 0 && t >= -d)
\r
53 // value is s at time 0
\r
55 decayval = ((t + d) / d) * (s - 1) + 1;
\r
56 return max(decayval, releaseval);
\r
62 float GetAttackTime(float a, float amp)
\r
67 float GetReleaseTime(float d, float s, float r, float amp)
\r
69 float decaytime, releasetime;
\r
74 // if amp > s, we may be in the attack or in the prolonged decay curve
\r
75 releasetime = (1 - amp / s) * r;
\r
79 if(s == 1) // gracefully handle division by zero here
\r
83 // value is s at time 0
\r
85 decaytime = (amp - 1) / (s - 1) * d - d;
\r
86 return max(decaytime, releasetime);
\r
92 void BGMScript_Init()
\r
96 bgmscriptbuf = bgmscriptbufsize = 0;
\r
97 bgmscriptbufloaded = 1;
\r
98 s = strcat("maps/", mi_shortname, ".bgs");
\r
99 fh = fopen(s, FILE_READ);
\r
102 bgmscriptbuf = buf_create();
\r
103 while((s = fgets(fh)))
\r
105 bufstr_set(bgmscriptbuf, bgmscriptbufsize, s);
\r
106 ++bgmscriptbufsize;
\r
111 void BGMScript_InitEntity(entity e)
\r
115 if(e.bgmscript != "")
\r
117 if(!bgmscriptbufloaded)
\r
122 m = strcat(e.bgmscript, " ");
\r
125 e.bgmscriptline0 = -1;
\r
126 for(i = 0; i < bgmscriptbufsize; ++i)
\r
128 if(substring(bufstr_get(bgmscriptbuf, i), 0, l) == m)
\r
131 e.bgmscriptline = e.bgmscriptline0 = i;
\r
132 if(i >= bgmscriptbufsize)
\r
134 print("ERROR: bgmscript does not define ", e.bgmscript, "\n");
\r
135 e.bgmscript = string_null;
\r
140 float GetCurrentAmplitude(entity e, float trel)
\r
142 if(e.bgmscriptstate)
\r
143 return GetAttackDecaySustainAmplitude(e.bgmscriptattack, e.bgmscriptdecay, e.bgmscriptsustain, trel) * e.bgmscriptvolume;
\r
146 #ifdef CONSTANT_SPEED_DECAY
\r
147 return GetReleaseAmplitude(e.bgmscriptdecay, e.bgmscriptsustain * e.bgmscriptvolume, e.bgmscriptrelease, trel);
\r
149 return GetReleaseAmplitude(e.bgmscriptdecay, e.bgmscriptsustain, e.bgmscriptrelease, trel) * e.bgmscriptvolume;
\r
154 float GetTimeForAmplitude(entity e, float amp)
\r
156 if(e.bgmscriptstate)
\r
157 return GetAttackTime(e.bgmscriptattack, amp / e.bgmscriptvolume);
\r
160 #ifdef CONSTANT_SPEED_DECAY
\r
161 return GetReleaseTime(e.bgmscriptdecay, e.bgmscriptsustain * e.bgmscriptvolume, e.bgmscriptrelease, amp);
\r
163 return GetReleaseTime(e.bgmscriptdecay, e.bgmscriptsustain, e.bgmscriptrelease, amp / e.bgmscriptvolume);
\r
168 float BGMScript(entity e)
\r
173 if(e.bgmscript == "")
\r
176 if(cvar("bgmvolume") <= 0)
\r
179 e.just_toggled = FALSE;
\r
181 t = gettime(GETTIME_CDTRACK);
\r
185 if(t < e.bgmscripttime)
\r
187 //print("reset ", e.bgmscript, "\n");
\r
188 amp = GetCurrentAmplitude(e, e.bgmscripttime - e.bgmscriptstatetime + drawframetime);
\r
190 e.bgmscriptline = e.bgmscriptline0;
\r
191 e.bgmscripttime = t;
\r
193 // treat this as a stop event for all notes, to prevent sticking keys
\r
194 e.bgmscriptstate = FALSE;
\r
195 e.bgmscriptvolume = 1;
\r
196 e.bgmscriptstatetime = t - GetTimeForAmplitude(e, amp);
\r
199 // find the CURRENT line
\r
202 tokenize_console(bufstr_get(bgmscriptbuf, e.bgmscriptline));
\r
203 if(stof(argv(1)) >= t || argv(0) != e.bgmscript)
\r
205 e.bgmscripttime = t;
\r
206 return GetCurrentAmplitude(e, t - e.bgmscriptstatetime);
\r
208 else if(t >= stof(argv(1)))
\r
210 e.bgmscriptline += 1;
\r
211 e.bgmscripttime = stof(argv(1));
\r
213 amp = GetCurrentAmplitude(e, e.bgmscripttime - e.bgmscriptstatetime);
\r
215 // time code reached!
\r
216 vel = stof(argv(2));
\r
219 e.just_toggled = e.bgmscriptstate = TRUE;
\r
220 e.bgmscriptvolume = vel;
\r
223 e.just_toggled = e.bgmscriptstate = FALSE;
\r
225 e.bgmscriptstatetime = e.bgmscripttime - GetTimeForAmplitude(e, amp);
\r