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