Xonotic
bgmscript.qc
Go to the documentation of this file.
1 #include "bgmscript.qh"
2 
3 #include <client/main.qh>
4 #include <common/util.qh>
5 
6 #define CONSTANT_SPEED_DECAY
7 
11 
12 classfield(BGMScript) .float bgmscriptline;
13 classfield(BGMScript) .float bgmscriptline0;
14 classfield(BGMScript) .float bgmscriptvolume;
15 classfield(BGMScript) .float bgmscripttime;
16 classfield(BGMScript) .float bgmscriptstate;
17 classfield(BGMScript) .float bgmscriptstatetime;
18 
19 float GetAttackDecaySustainAmplitude(float a, float d, float s, float t)
20 {
21  // phase:
22  // attack: from 0 to 1, in time a for a full length
23  // decay: from 1 to s, in time d
24  // sustain: s
25 
26  if(t < 0)
27  return 0;
28 
29  if(a)
30  if(t <= a)
31  return t / a;
32 
33  if(d)
34  if(t <= a + d)
35  return ((t - a) / d) * (s - 1) + 1;
36 
37  return s;
38 }
39 
40 float GetReleaseAmplitude(float d, float s, float r, float t)
41 {
42  float decayval, releaseval;
43 
44  if(!r)
45  return 0;
46 
47  if(t > r)
48  return 0;
49 
50  releaseval = s * (1 - t / r);
51 
52  if(t < -d)
53  return 1;
54 
55  if(t < 0 && t >= -d)
56  {
57  // pre-time decay
58  // value is s at time 0
59  // 1 at time -d
60  decayval = ((t + d) / d) * (s - 1) + 1;
61  return max(decayval, releaseval);
62  }
63 
64  return releaseval;
65 }
66 
67 float GetAttackTime(float a, float amp)
68 {
69  return amp * a;
70 }
71 
72 float GetReleaseTime(float d, float s, float r, float amp)
73 {
74  float decaytime, releasetime;
75 
76  if(!s)
77  return 0;
78 
79  // if amp > s, we may be in the attack or in the prolonged decay curve
80  releasetime = (1 - amp / s) * r;
81 
82  if(amp > s)
83  {
84  if(s == 1) // gracefully handle division by zero here
85  return 0;
86 
87  // pre-time decay
88  // value is s at time 0
89  // 1 at time -d
90  decaytime = (amp - 1) / (s - 1) * d - d;
91  return max(decaytime, releasetime);
92  }
93 
94  return releasetime;
95 }
96 
98 {
99  string s;
100  float fh;
102  bgmscriptbufloaded = 1;
103  s = strcat("maps/", mi_shortname, ".bgs");
104  fh = fopen(s, FILE_READ);
105  if(fh < 0)
106  return;
108  while((s = fgets(fh)))
109  {
110  bufstr_set(bgmscriptbuf, bgmscriptbufsize, s);
112  }
113  fclose(fh);
114 }
115 
117 {
118  float l;
119  string m;
120  if(e.bgmscript != "")
121  {
122  if(!bgmscriptbufloaded)
123  BGMScript_Init();
124 
125  float i;
126 
127  m = strcat(e.bgmscript, " ");
128  l = strlen(m);
129 
130  e.bgmscriptline0 = -1;
131  for(i = 0; i < bgmscriptbufsize; ++i)
132  {
133  if(substring(bufstr_get(bgmscriptbuf, i), 0, l) == m)
134  break;
135  }
136  e.bgmscriptline = e.bgmscriptline0 = i;
137  if(i >= bgmscriptbufsize)
138  {
139  LOG_INFOF("ERROR: bgmscript does not define %s", e.bgmscript);
140  strfree(e.bgmscript);
141  }
142  }
143 }
144 
145 float GetCurrentAmplitude(entity e, float trel)
146 {
147  if(e.bgmscriptstate)
148  return GetAttackDecaySustainAmplitude(e.bgmscriptattack, e.bgmscriptdecay, e.bgmscriptsustain, trel) * e.bgmscriptvolume;
149  else
150  {
151 #ifdef CONSTANT_SPEED_DECAY
152  return GetReleaseAmplitude(e.bgmscriptdecay, e.bgmscriptsustain * e.bgmscriptvolume, e.bgmscriptrelease, trel);
153 #else
154  return GetReleaseAmplitude(e.bgmscriptdecay, e.bgmscriptsustain, e.bgmscriptrelease, trel) * e.bgmscriptvolume;
155 #endif
156  }
157 }
158 
159 float GetTimeForAmplitude(entity e, float amp)
160 {
161  if(e.bgmscriptstate)
162  return GetAttackTime(e.bgmscriptattack, amp / e.bgmscriptvolume);
163  else
164  {
165 #ifdef CONSTANT_SPEED_DECAY
166  return GetReleaseTime(e.bgmscriptdecay, e.bgmscriptsustain * e.bgmscriptvolume, e.bgmscriptrelease, amp);
167 #else
168  return GetReleaseTime(e.bgmscriptdecay, e.bgmscriptsustain, e.bgmscriptrelease, amp / e.bgmscriptvolume);
169 #endif
170  }
171 }
172 
174 {
175  float amp, vel;
176 
177  if(e.bgmscript == "")
178  return 1;
179 
180  if(autocvar_bgmvolume <= 0)
181  return -1;
182 
183  e.just_toggled = false;
184 
185  if(bgmtime < 0)
186  return -1;
187 
188  if(bgmtime < e.bgmscripttime)
189  {
190  amp = GetCurrentAmplitude(e, e.bgmscripttime - e.bgmscriptstatetime + drawframetime);
191 
192  e.bgmscriptline = e.bgmscriptline0;
193  e.bgmscripttime = bgmtime;
194 
195  // treat this as a stop event for all notes, to prevent sticking keys
196  e.bgmscriptstate = false;
197  e.bgmscriptvolume = 1;
198  e.bgmscriptstatetime = bgmtime - GetTimeForAmplitude(e, amp);
199  }
200 
201  // find the CURRENT line
202  for (;;)
203  {
204  tokenize_console(bufstr_get(bgmscriptbuf, e.bgmscriptline));
205  if(stof(argv(1)) >= bgmtime || argv(0) != e.bgmscript)
206  {
207  e.bgmscripttime = bgmtime;
208  return GetCurrentAmplitude(e, bgmtime - e.bgmscriptstatetime);
209  }
210  else if(bgmtime >= stof(argv(1)))
211  {
212  e.bgmscriptline += 1;
213  e.bgmscripttime = stof(argv(1));
214 
215  amp = GetCurrentAmplitude(e, e.bgmscripttime - e.bgmscriptstatetime);
216 
217  // time code reached!
218  vel = stof(argv(2));
219  if(vel > 0)
220  {
221  e.just_toggled = e.bgmscriptstate = true;
222  e.bgmscriptvolume = vel;
223  }
224  else
225  e.just_toggled = e.bgmscriptstate = false;
226 
227  e.bgmscriptstatetime = e.bgmscripttime - GetTimeForAmplitude(e, amp);
228  }
229  }
230 }
231 
float bgmscriptbuf
Definition: bgmscript.qc:8
entity() spawn
const float FILE_READ
Definition: csprogsdefs.qc:231
float bgmscriptbufloaded
Definition: bgmscript.qc:10
float GetTimeForAmplitude(entity e, float amp)
Definition: bgmscript.qc:159
classfield(BGMScript) .float bgmscriptline
#define buf_create
Definition: dpextensions.qh:63
float GetAttackTime(float a, float amp)
Definition: bgmscript.qc:67
void BGMScript_InitEntity(entity e)
Definition: bgmscript.qc:116
#define LOG_INFOF(...)
Definition: log.qh:71
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
float autocvar_bgmvolume
Definition: bgmscript.qh:5
#define tokenize_console
Definition: dpextensions.qh:24
float bgmscriptbufsize
Definition: bgmscript.qc:9
float drawframetime
Definition: main.qh:92
float GetReleaseAmplitude(float d, float s, float r, float t)
Definition: bgmscript.qc:40
float GetAttackDecaySustainAmplitude(float a, float d, float s, float t)
Definition: bgmscript.qc:19
#define strfree(this)
Definition: string.qh:56
float GetCurrentAmplitude(entity e, float trel)
Definition: bgmscript.qc:145
void BGMScript_Init()
Definition: bgmscript.qc:97
float doBGMScript(entity e)
Definition: bgmscript.qc:173
float bgmtime
Definition: bgmscript.qh:9
float GetReleaseTime(float d, float s, float r, float amp)
Definition: bgmscript.qc:72