]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/mutators/mutator_new_toys.qc
s/WEP_(ID)/WEP_$1.m_id/
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / mutator_new_toys.qc
1 #include "../_all.qh"
2
3 #include "mutator.qh"
4
5 /*
6
7 CORE    laser   vortex     lg      rl      cry     gl      elec    hagar   fireb   hook
8                                                                         vaporizer  porto
9                                                                         tuba
10
11 NEW             rifle   hlac    minel                           seeker
12 IDEAS                                   OPEN    flak    OPEN            FUN FUN FUN FUN
13
14
15
16 How this mutator works:
17  =======================
18
19 When a gun tries to spawn, this mutator is called. It will provide alternate
20 weaponreplace lists.
21
22 Entity:
23
24 {
25 "classname" "weapon_vortex"
26 "new_toys" "rifle"
27 }
28 -> This will spawn as Rifle in this mutator ONLY, and as Vortex otherwise.
29
30 {
31 "classname" "weapon_vortext"
32 "new_toys" "vortex rifle"
33 }
34 -> This will spawn as either Vortex or Rifle in this mutator ONLY, and as Vortex otherwise.
35
36 {
37 "classname" "weapon_vortex"
38 "new_toys" "vortex"
39 }
40 -> This is always a Vortex.
41
42 If the map specifies no "new_toys" argument
43
44 There will be two default replacements selectable: "replace all" and "replace random".
45 In "replace all" mode, e.g. Vortex will have the default replacement "rifle".
46 In "replace random" mode, Vortex will have the default replacement "vortex rifle".
47
48 This mutator's replacements run BEFORE regular weaponreplace!
49
50 The New Toys guns do NOT get a spawn function, so they can only ever be spawned
51 when this mutator is active.
52
53 Likewise, warmup, give all, give ALL and impulse 99 will not give them unless
54 this mutator is active.
55
56 Outside this mutator, they still can be spawned by:
57 - setting their start weapon cvar to 1
58 - give weaponname
59 - weaponreplace
60 - weaponarena (but all and most weapons arena again won't include them)
61
62 This mutator performs the default replacements on the DEFAULTS of the
63 start weapon selection.
64
65 These weapons appear in the menu's priority list, BUT get a suffix
66 "(Mutator weapon)".
67
68 Picking up a "new toys" weapon will not play standard weapon pickup sound, but
69 roflsound "New toys, new toys!" sound.
70
71 */
72
73 .string new_toys;
74
75 float autocvar_g_new_toys_autoreplace;
76 const float NT_AUTOREPLACE_NEVER = 0;
77 const float NT_AUTOREPLACE_ALWAYS = 1;
78 const float NT_AUTOREPLACE_RANDOM = 2;
79
80 MUTATOR_HOOKFUNCTION(nt_SetModname)
81 {
82         modname = "NewToys";
83         return 0;
84 }
85
86 float nt_IsNewToy(float w)
87 {
88         switch(w)
89         {
90                 case WEP_SEEKER.m_id:
91                 case WEP_MINE_LAYER.m_id:
92                 case WEP_HLAC.m_id:
93                 case WEP_RIFLE.m_id:
94                 case WEP_SHOCKWAVE.m_id:
95                         return true;
96                 default:
97                         return false;
98         }
99 }
100
101 string nt_GetFullReplacement(string w)
102 {
103         switch(w)
104         {
105                 case "hagar": return "seeker";
106                 case "devastator": return "minelayer";
107                 case "machinegun": return "hlac";
108                 case "vortex": return "rifle";
109                 case "shotgun": return "shockwave";
110                 default: return string_null;
111         }
112 }
113
114 string nt_GetReplacement(string w, float m)
115 {
116         if(m == NT_AUTOREPLACE_NEVER)
117                 return w;
118         string s = nt_GetFullReplacement(w);
119         if (!s)
120                 return w;
121         if(m == NT_AUTOREPLACE_RANDOM)
122                 s = strcat(w, " ", s);
123         return s;
124 }
125
126 MUTATOR_HOOKFUNCTION(nt_SetStartItems)
127 {
128         // rearrange start_weapon_default
129         // apply those bits that are set by start_weapon_defaultmask
130         // same for warmup
131
132         float i, j, k, n;
133
134         WepSet newdefault;
135         WepSet warmup_newdefault;
136
137         newdefault = '0 0 0';
138         warmup_newdefault = '0 0 0';
139
140         for(i = WEP_FIRST; i <= WEP_LAST; ++i)
141         {
142                 entity e = get_weaponinfo(i);
143                 if(!e.weapon)
144                         continue;
145
146                 n = tokenize_console(nt_GetReplacement(e.netname, autocvar_g_new_toys_autoreplace));
147
148                 for(j = 0; j < n; ++j)
149                         for(k = WEP_FIRST; k <= WEP_LAST; ++k)
150                                 if(get_weaponinfo(k).netname == argv(j))
151                                 {
152                                         if(start_weapons & WepSet_FromWeapon(i))
153                                                 newdefault |= WepSet_FromWeapon(k);
154                                         if(warmup_start_weapons & WepSet_FromWeapon(i))
155                                                 warmup_newdefault |= WepSet_FromWeapon(k);
156                                 }
157         }
158
159         newdefault &= start_weapons_defaultmask;
160         start_weapons &= ~start_weapons_defaultmask;
161         start_weapons |= newdefault;
162
163         warmup_newdefault &= warmup_start_weapons_defaultmask;
164         warmup_start_weapons &= ~warmup_start_weapons_defaultmask;
165         warmup_start_weapons |= warmup_newdefault;
166
167         return 0;
168 }
169
170 MUTATOR_HOOKFUNCTION(nt_SetWeaponreplace)
171 {
172         // otherwise, we do replace
173         if(self.new_toys)
174         {
175                 // map defined replacement:
176                 ret_string = self.new_toys;
177         }
178         else
179         {
180                 // auto replacement:
181                 ret_string = nt_GetReplacement(other.netname, autocvar_g_new_toys_autoreplace);
182         }
183
184         // apply regular weaponreplace
185         ret_string = W_Apply_Weaponreplace(ret_string);
186
187         return 0;
188 }
189
190 MUTATOR_HOOKFUNCTION(nt_FilterItem)
191 {
192         if(nt_IsNewToy(self.weapon))
193                 self.item_pickupsound = "weapons/weaponpickup_new_toys.wav";
194         return 0;
195 }
196
197 MUTATOR_DEFINITION(mutator_new_toys)
198 {
199         MUTATOR_HOOK(SetModname, nt_SetModname, CBC_ORDER_ANY);
200         MUTATOR_HOOK(SetStartItems, nt_SetStartItems, CBC_ORDER_ANY);
201         MUTATOR_HOOK(SetWeaponreplace, nt_SetWeaponreplace, CBC_ORDER_LAST);
202         MUTATOR_HOOK(FilterItem, nt_FilterItem, CBC_ORDER_ANY);
203
204         MUTATOR_ONADD
205         {
206                 if(time > 1) // game loads at time 1
207                         error("This cannot be added at runtime\n");
208
209                 precache_sound("weapons/weaponpickup_new_toys.wav");
210
211                 // mark the guns as ok to use by e.g. impulse 99
212                 float i;
213                 for(i = WEP_FIRST; i <= WEP_LAST; ++i)
214                         if(nt_IsNewToy(i))
215                                 get_weaponinfo(i).spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
216         }
217
218         MUTATOR_ONROLLBACK_OR_REMOVE
219         {
220                 float i;
221                 for(i = WEP_FIRST; i <= WEP_LAST; ++i)
222                         if(nt_IsNewToy(i))
223                                 get_weaponinfo(i).spawnflags |= WEP_FLAG_MUTATORBLOCKED;
224         }
225
226         MUTATOR_ONREMOVE
227         {
228                 print("This cannot be removed at runtime\n");
229                 return -1;
230         }
231
232         return 0;
233 }