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