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