Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
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
12classfield(BGMScript) .float bgmscriptline;
13classfield(BGMScript) .float bgmscriptline0;
14classfield(BGMScript) .float bgmscriptvolume;
15classfield(BGMScript) .float bgmscripttime;
16classfield(BGMScript) .float bgmscriptstate;
17classfield(BGMScript) .float bgmscriptstatetime;
18
19float 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
40float 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
67float GetAttackTime(float a, float amp)
68{
69 return amp * a;
70}
71
72float 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;
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 {
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
145float 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
159float 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
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
float bgmscriptbufsize
Definition bgmscript.qc:9
float GetAttackDecaySustainAmplitude(float a, float d, float s, float t)
Definition bgmscript.qc:19
float bgmscriptbuf
Definition bgmscript.qc:8
float GetReleaseTime(float d, float s, float r, float amp)
Definition bgmscript.qc:72
float bgmscriptbufloaded
Definition bgmscript.qc:10
void BGMScript_InitEntity(entity e)
Definition bgmscript.qc:116
float GetReleaseAmplitude(float d, float s, float r, float t)
Definition bgmscript.qc:40
float doBGMScript(entity e)
Definition bgmscript.qc:173
float GetCurrentAmplitude(entity e, float trel)
Definition bgmscript.qc:145
float GetAttackTime(float a, float amp)
Definition bgmscript.qc:67
float GetTimeForAmplitude(entity e, float amp)
Definition bgmscript.qc:159
void BGMScript_Init()
Definition bgmscript.qc:97
float bgmtime
Definition bgmscript.qh:9
float autocvar_bgmvolume
Definition bgmscript.qh:5
float drawframetime
Definition main.qh:108
string mi_shortname
Definition util.qh:126
const float FILE_READ
#define strlen
#define tokenize_console
#define buf_create
#define LOG_INFOF(...)
Definition log.qh:66
string fgets(float fhandle)
void fclose(float fhandle)
float stof(string val,...)
string substring(string s, float start, float length)
float fopen(string filename, float mode)
string argv(float n)
float max(float f,...)
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
#define classfield(name)
Definition oo.qh:57
#define strfree(this)
Definition string.qh:59