Xonotic
magicear.qc
Go to the documentation of this file.
1 #include "magicear.qh"
2 #ifdef SVQC
4 bool magicear_matched;
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
const int MAGICEAR_TUBA_EXACTPITCH
Definition: magicear.qh:13
const int MAGICEAR_IGNORE_INVALIDTELL
Definition: magicear.qh:7
string string_null
Definition: nil.qh:9
const int MAGICEAR_TUBA
Definition: magicear.qh:12
entity() spawn
void SUB_UseTargets(entity this, entity actor, entity trigger)
Definition: triggers.qc:366
spawnfunc(info_player_attacker)
Definition: sv_assault.qc:283
entity enemy
Definition: sv_ctf.qh:143
const int MAGICEAR_IGNORE_SAY
Definition: magicear.qh:4
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"))
const int MAX_WEAPONSLOTS
Definition: weapon.qh:13
#define NULL
Definition: post.qh:17
#define strstrofs
Definition: dpextensions.qh:42
#define IS_DEAD(s)
Definition: utils.qh:26
const int MAGICEAR_REPLACE_WHOLE_MESSAGE
Definition: magicear.qh:8
const int MAGICEAR_CONTINUE
Definition: magicear.qh:10
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
Definition: vector.qh:8
entity weaponentities[MAX_WEAPONSLOTS]
Definition: weapon.qh:14
const int MAGICEAR_IGNORE_TELL
Definition: magicear.qh:6
const int MAGICEAR_REPLACE_OUTSIDE
Definition: magicear.qh:9
#define IS_PLAYER(v)
Definition: utils.qh:9
const int MAGICEAR_NODECOLORIZE
Definition: magicear.qh:11
const int MAGICEAR_IGNORE_TEAMSAY
Definition: magicear.qh:5