]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/triggers/trigger/magicear.qc
Cleanup
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / triggers / trigger / magicear.qc
1 #ifdef SVQC
2 float magicear_matched;
3 float W_Tuba_HasPlayed(entity pl, string melody, float instrument, float ignorepitch, float mintempo, float maxtempo);
4 string trigger_magicear_processmessage(entity ear, entity source, float teamsay, entity privatesay, string msgin)
5 {SELFPARAM();
6         float domatch, dotrigger, matchstart, l;
7         string s, msg;
8         string savemessage;
9
10         magicear_matched = false;
11
12         dotrigger = ((IS_PLAYER(source)) && (source.deadflag == DEAD_NO) && ((ear.radius == 0) || (vlen(source.origin - ear.origin) <= ear.radius)));
13         domatch = ((ear.spawnflags & 32) || dotrigger);
14
15         if (!domatch)
16                 return msgin;
17
18         if (!msgin)
19         {
20                 // we are in TUBA mode!
21                 if (!(ear.spawnflags & 256))
22                         return msgin;
23
24                 if(!W_Tuba_HasPlayed(source, ear.message, ear.movedir_x, !(ear.spawnflags & 512), ear.movedir_y, ear.movedir_z))
25                         return msgin;
26
27                 magicear_matched = true;
28
29                 if(dotrigger)
30                 {
31                         activator = source;
32                         setself(ear);
33                         savemessage = self.message;
34                         self.message = string_null;
35                         SUB_UseTargets();
36                         self.message = savemessage;
37                         setself(this);
38                 }
39
40                 if(ear.netname != "")
41                         return ear.netname;
42
43                 return msgin;
44         }
45
46         if(ear.spawnflags & 256) // ENOTUBA
47                 return msgin;
48
49         if(privatesay)
50         {
51                 if(ear.spawnflags & 4)
52                         return msgin;
53         }
54         else
55         {
56                 if(!teamsay)
57                         if(ear.spawnflags & 1)
58                                 return msgin;
59                 if(teamsay > 0)
60                         if(ear.spawnflags & 2)
61                                 return msgin;
62                 if(teamsay < 0)
63                         if(ear.spawnflags & 8)
64                                 return msgin;
65         }
66
67         matchstart = -1;
68         l = strlen(ear.message);
69
70         if(ear.spawnflags & 128)
71                 msg = msgin;
72         else
73                 msg = strdecolorize(msgin);
74
75         if(substring(ear.message, 0, 1) == "*")
76         {
77                 if(substring(ear.message, -1, 1) == "*")
78                 {
79                         // two wildcards
80                         // as we need multi-replacement here...
81                         s = substring(ear.message, 1, -2);
82                         l -= 2;
83                         if(strstrofs(msg, s, 0) >= 0)
84                                 matchstart = -2; // we use strreplace on s
85                 }
86                 else
87                 {
88                         // match at start
89                         s = substring(ear.message, 1, -1);
90                         l -= 1;
91                         if(substring(msg, -l, l) == s)
92                                 matchstart = strlen(msg) - l;
93                 }
94         }
95         else
96         {
97                 if(substring(ear.message, -1, 1) == "*")
98                 {
99                         // match at end
100                         s = substring(ear.message, 0, -2);
101                         l -= 1;
102                         if(substring(msg, 0, l) == s)
103                                 matchstart = 0;
104                 }
105                 else
106                 {
107                         // full match
108                         s = ear.message;
109                         if(msg == ear.message)
110                                 matchstart = 0;
111                 }
112         }
113
114         if(matchstart == -1) // no match
115                 return msgin;
116
117         magicear_matched = true;
118
119         if(dotrigger)
120         {
121                 activator = source;
122                 setself(ear);
123                 savemessage = self.message;
124                 self.message = string_null;
125                 SUB_UseTargets();
126                 self.message = savemessage;
127                 setself(this);
128         }
129
130         if(ear.spawnflags & 16)
131         {
132                 return ear.netname;
133         }
134         else if(ear.netname != "")
135         {
136                 if(matchstart < 0)
137                         return strreplace(s, ear.netname, msg);
138                 else
139                         return strcat(
140                                 substring(msg, 0, matchstart),
141                                 ear.netname,
142                                 substring(msg, matchstart + l, -1)
143                         );
144         }
145         else
146                 return msgin;
147 }
148
149 entity magicears;
150 string trigger_magicear_processmessage_forallears(entity source, float teamsay, entity privatesay, string msgin)
151 {
152         entity ear;
153         string msgout;
154         for(ear = magicears; ear; ear = ear.enemy)
155         {
156                 msgout = trigger_magicear_processmessage(ear, source, teamsay, privatesay, msgin);
157                 if(!(ear.spawnflags & 64))
158                 if(magicear_matched)
159                         return msgout;
160                 msgin = msgout;
161         }
162         return msgin;
163 }
164
165 spawnfunc(trigger_magicear)
166 {
167         self.enemy = magicears;
168         magicears = self;
169
170         // actually handled in "say" processing
171         // spawnflags:
172         //    1 = ignore say
173         //    2 = ignore teamsay
174         //    4 = ignore tell
175         //    8 = ignore tell to unknown player
176         //   16 = let netname replace the whole message (otherwise, netname is a word replacement if set)
177         //   32 = perform the replacement even if outside the radius or dead
178         //   64 = continue replacing/triggering even if this one matched
179         //  128 = don't decolorize message before matching
180         //  256 = message is a tuba note sequence (pitch.duration pitch.duration ...)
181         //  512 = tuba notes must be exact right pitch, no transposing
182         // message: either
183         //   *pattern*
184         // or
185         //   *pattern
186         // or
187         //   pattern*
188         // or
189         //   pattern
190         // netname:
191         //   if set, replacement for the matched text
192         // radius:
193         //   "hearing distance"
194         // target:
195         //   what to trigger
196         // movedir:
197         //   for spawnflags 256, defines 'instrument+1 mintempo maxtempo' (zero component doesn't matter)
198
199         self.movedir_x -= 1; // map to tuba instrument numbers
200 }
201 #endif